diff --git a/.clang-format b/.clang-format index 5e66ff611..edb50069b 100644 --- a/.clang-format +++ b/.clang-format @@ -104,7 +104,7 @@ SpacesInContainerLiterals: true SpacesInCStyleCastParentheses: false SpacesInParentheses: false SpacesInSquareBrackets: false -Standard: Cpp03 +Standard: Cpp11 TabWidth: 8 UseTab: Never ... diff --git a/.travis.yml b/.travis.yml index a06929f60..4eef5d994 100644 --- a/.travis.yml +++ b/.travis.yml @@ -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 diff --git a/Changes b/Changes index 91b9a8eb0..5bdbe0afa 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,32 @@ Revision history for Verilator The contributors that suggested a given feature are shown in []. Thanks! + +* Verilator 4.100 2020-09-07 + +** C++11 or newer compilers are now required. + +** SystemC 2.3.0 or newer (SYSTEMC_VERSION >= 20111121) is now required. + +** Support hierarchical Verilation (#2206). [Yutetsu TAKATSUKASA] + +**** Support (with limitations) class extern, class extends, virtual class. + +**** Support $urandom, $urandom_range without stability. + +**** Fix false DECLFILENAME on black-boxed modules (#2430). [Philipp Wagner] + +**** Fix naming of "id : begin" blocks. + +**** Fix class constructor error on assignments to const. + +**** Fix splitting eval functions with --output-split-cfuncs (#2368). [Geza Lore] + +**** Fix queues as class members (#2525). [nanduraj1] + +**** Add support for assume property. [Peter Monsson] + + * Verilator 4.040 2020-08-15 ** Version 4.040 is planned to be the final version that will @@ -31,6 +57,10 @@ The contributors that suggested a given feature are shown in []. Thanks! **** Fix SystemC net names (#2500). [Edgar E. Iglesias] +**** Fix build with Bison 3.7 and newer (#2505). [Rupert Swarbrick] + +**** Fix slice of unpacked array (#2506) (#2507). [Yutetsu TAKATSUKASA] + * Verilator 4.038 2020-07-11 diff --git a/Makefile.in b/Makefile.in index f1b09115a..8870f6cc0 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 diff --git a/bin/verilator b/bin/verilator index 83712deca..e685664d7 100755 --- a/bin/verilator +++ b/bin/verilator @@ -327,6 +327,7 @@ arguments. --generate-key Create random key for --protect-key --getenv Get environment variable with defaults --help Display this help + --hierarchical Enable hierarchical Verilation -I Directory to search for includes -j Parallelism for --build --gate-stmts 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. + =item -II 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 for more detail. + b) add hier_block line in the configuration file. + See C in L 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 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 "" + +Specifies that the module is a unit of hierarchical Verilation. +Note that the setting is ignored unless --hierachical option is specified. +See L for more information. + =item inline -module "" 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 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 diff --git a/ci/travis-script.bash b/ci/travis-script.bash index c80443053..b1405c9f0 100755 --- a/ci/travis-script.bash +++ b/ci/travis-script.bash @@ -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 diff --git a/configure.ac b/configure.ac index e672a3198..1cb0dd8d5 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ #AC_INIT([Verilator],[#.### YYYY-MM-DD]) #AC_INIT([Verilator],[#.### devel]) -AC_INIT([Verilator],[4.040 2020-08-15], +AC_INIT([Verilator],[4.100 2020-09-07], [https://verilator.org], [verilator],[https://verilator.org]) # When releasing, also update header of Changes file @@ -113,22 +113,6 @@ AC_ARG_ENABLE([longtests], AC_SUBST(CFG_WITH_LONGTESTS) AC_MSG_RESULT($CFG_WITH_LONGTESTS) -# CFG_WITH_PREC11 -AC_MSG_CHECKING(whether allow pre-C++11) -AC_ARG_ENABLE([prec11-final], - [AS_HELP_STRING([--enable-prec11-final], - [enable pre-C++11 compilers for Verilator binary - and Verilated makefiles])], - [case "${enableval}" in - yes) CFG_WITH_PREC11=yes ;; - no) CFG_WITH_PREC11=no ;; - *) AC_MSG_ERROR([bad value ${enableval} for --enable-prec11-final]) ;; - esac], - [CFG_WITH_PREC11=no;] - ) -AC_SUBST(CFG_WITH_PREC11) -AC_MSG_RESULT($CFG_WITH_PREC11) - # Compiler flags (ensure they are not empty to avoid configure defaults) CFLAGS+=" " CPPFLAGS+=" " @@ -410,12 +394,17 @@ _MY_LDLIBS_CHECK_IFELSE( fi]) AC_SUBST(CFG_LIBS) -# Set CFG_WITH_THREADED if can support threading -AC_MSG_CHECKING(whether $CXX supports Verilated threads) -ACO_SAVE_CXXFLAGS="$CXXFLAGS" -CXXFLAGS="$CXXFLAGS $CFG_CXXFLAGS_STD_NEWEST $CFG_CXXFLAGS_NO_UNUSED" -AC_LINK_IFELSE( - [AC_LANG_PROGRAM([#include ], [[ ]])], +# 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 +#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. diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index 5eeec896c..fca9bec6d 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -53,6 +53,7 @@ Pieter Kapsenberg Piotr Binkowski Qingyao Sun Richard Myers +Rupert Swarbrick Sean Cross Sebastien Van Cauwenberghe Sergi Granell diff --git a/docs/install.adoc b/docs/install.adoc index d3b13b244..dfe5c0e75 100644 --- a/docs/install.adoc +++ b/docs/install.adoc @@ -69,12 +69,12 @@ Linux distribution, see instead <>. === 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 diff --git a/docs/internals.adoc b/docs/internals.adoc index 22dbd1ad4..8b7cbd765 100644 --- a/docs/internals.adoc +++ b/docs/internals.adoc @@ -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 diff --git a/examples/make_hello_sc/sc_main.cpp b/examples/make_hello_sc/sc_main.cpp index 91f9b49ff..208ba582b 100644 --- a/examples/make_hello_sc/sc_main.cpp +++ b/examples/make_hello_sc/sc_main.cpp @@ -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 diff --git a/examples/make_protect_lib/sim_main.cpp b/examples/make_protect_lib/sim_main.cpp index 9850a54ad..d89aa3482 100644 --- a/examples/make_protect_lib/sim_main.cpp +++ b/examples/make_protect_lib/sim_main.cpp @@ -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); diff --git a/examples/make_tracing_c/sim_main.cpp b/examples/make_tracing_c/sim_main.cpp index a934952fd..571df64a8 100644 --- a/examples/make_tracing_c/sim_main.cpp +++ b/examples/make_tracing_c/sim_main.cpp @@ -99,7 +99,7 @@ int main(int argc, char** argv, char** env) { // Destroy model delete top; - top = NULL; + top = nullptr; // Fin exit(0); diff --git a/examples/make_tracing_sc/sc_main.cpp b/examples/make_tracing_sc/sc_main.cpp index 8ab3120d4..9df44e1e1 100644 --- a/examples/make_tracing_sc/sc_main.cpp +++ b/examples/make_tracing_sc/sc_main.cpp @@ -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 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; diff --git a/include/verilated.cpp b/include/verilated.cpp index f21bed470..fe450ab25 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -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(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(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(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(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 // in verilated.h (for compilation speed) -typedef std::list > VoidPCbList; +typedef std::list> 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(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); } } diff --git a/include/verilated.h b/include/verilated.h index 099066ab7..4f25248bd 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -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(sc_time_stamp()); } -# endif #else // Non-SystemC # ifdef VL_TIME_STAMP64 extern vluint64_t vl_time_stamp64(); diff --git a/include/verilated.mk.in b/include/verilated.mk.in index 3a8487c2d..f08066a49 100644 --- a/include/verilated.mk.in +++ b/include/verilated.mk.in @@ -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 diff --git a/include/verilated_cov.cpp b/include/verilated_cov.cpp index 65459998d..df46d5d37 100644 --- a/include/verilated_cov.cpp +++ b/include/verilated_cov.cpp @@ -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 > EventMap; + typedef std::map> 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); } diff --git a/include/verilated_cov.h b/include/verilated_cov.h index f9d036758..aef8eda67 100644 --- a/include/verilated_cov.h +++ b/include/verilated_cov.h @@ -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)); diff --git a/include/verilated_dpi.cpp b/include/verilated_dpi.cpp index 909a9cc2a..c1cc63f10 100644 --- a/include/verilated_dpi.cpp +++ b/include/verilated_dpi.cpp @@ -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(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()); diff --git a/include/verilated_fst_c.cpp b/include/verilated_fst_c.cpp index a006bd6fa..80c149abc 100644 --- a/include/verilated_fst_c.cpp +++ b/include/verilated_fst_c.cpp @@ -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::traceInit(); // Clear the scope stack - std::list::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::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::iterator cur_it = m_curScope.begin(); - std::list::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); diff --git a/include/verilated_fst_c.h b/include/verilated_fst_c.h index 9b935f763..f4aaf08ec 100644 --- a/include/verilated_fst_c.h +++ b/include/verilated_fst_c.h @@ -50,8 +50,8 @@ private: Code2SymbolType m_code2symbol; Local2FstDtype m_local2fstdtype; std::list 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(); } diff --git a/include/verilated_heavy.h b/include/verilated_heavy.h index 2241bf8d1..eb43fe595 100644 --- a/include/verilated_heavy.h +++ b/include/verilated_heavy.h @@ -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, but: -// 1. Doesn't require C++11 -// 2. Lighter weight, only methods needed by Verilator, to help compile time. +// Similar to std::array, 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 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& obj, QData start, QData end) VL_MT_SAFE { VlWriteMem wmem(hex, bits, filename, start, end); if (VL_UNLIKELY(!wmem.isOpen())) return; - for (typename VlAssocArray::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 std::string VL_TO_STRING(const VlQueue& 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 // T typically of type VlClassRef inline T VL_NULL_CHECK(T t, const char* filename, int linenum) { diff --git a/include/verilated_imp.h b/include/verilated_imp.h index 78007b096..a84aa13ba 100644 --- a/include/verilated_imp.h +++ b/include/verilated_imp.h @@ -62,8 +62,8 @@ private: public: // CONSTRUCTORS VerilatedMsg(const std::function& 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 ArgVec; @@ -201,17 +201,13 @@ protected: typedef std::map 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 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(31UL + 1UL + 3UL, s_s.m_fdps.size()); + const std::size_t start = std::max(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( fseek(*fdlist.begin(), static_cast(offset), static_cast(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(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; diff --git a/include/verilated_save.h b/include/verilated_save.h index cf6c3a5a5..adc65fa8d 100644 --- a/include/verilated_save.h +++ b/include/verilated_save.h @@ -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::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; diff --git a/include/verilated_sym_props.h b/include/verilated_sym_props.h index 51d154e18..ca2689108 100644 --- a/include/verilated_sym_props.h +++ b/include/verilated_sym_props.h @@ -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(datap)) {} + : m_propsp{propsp} + , m_datap{const_cast(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() {} diff --git a/include/verilated_threads.cpp b/include/verilated_threads.cpp index 8bc7347d2..4edd9db71 100644 --- a/include/verilated_threads.cpp +++ b/include/verilated_threads.cpp @@ -21,14 +21,14 @@ std::atomic 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 } diff --git a/include/verilated_threads.h b/include/verilated_threads.h index aee15f021..56ed7499b 100644 --- a/include/verilated_threads.h +++ b/include/verilated_threads.h @@ -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 diff --git a/include/verilated_trace.h b/include/verilated_trace.h index ab854d9fd..adffb68c3 100644 --- a/include/verilated_trace.h +++ b/include/verilated_trace.h @@ -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 diff --git a/include/verilated_trace_imp.cpp b/include/verilated_trace_imp.cpp index 3980a984c..5de211590 100644 --- a/include/verilated_trace_imp.cpp +++ b/include/verilated_trace_imp.cpp @@ -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::onExit(void* selfp) { template <> VerilatedTrace::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::VerilatedTrace() } template <> VerilatedTrace::~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::onFlush, this); Verilated::removeExitCb(VerilatedTrace::onExit, this); #ifdef VL_TRACE_THREADED diff --git a/include/verilated_unordered_set_map.h b/include/verilated_unordered_set_map.h deleted file mode 100644 index f66a2bec6..000000000 --- a/include/verilated_unordered_set_map.h +++ /dev/null @@ -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 -#include -#include - -// Abstract 'vl_hash' and 'vl_equal_to' templates. -template struct vl_hash { size_t operator()(const T& k) const; }; - -template 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(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::operator()(const int& k) const { return k; } - -template <> inline bool vl_equal_to::operator()(const int& a, const int& b) const { - return a == b; -} - -template <> inline size_t vl_hash::operator()(const unsigned int& k) const { - return k; -} - -template <> -inline bool vl_equal_to::operator()(const unsigned int& a, - const unsigned int& b) const { - return a == b; -} - -template <> inline size_t vl_hash::operator()(const std::string& k) const { - return vl_hash_bytes(k.data(), k.size()); -} - -template <> -inline bool vl_equal_to::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 struct vl_hash { - size_t operator()(T* kp) const { - return ((sizeof(size_t) == sizeof(kp)) ? reinterpret_cast(kp) - : vl_hash_bytes(&kp, sizeof(kp))); - } -}; - -template struct vl_equal_to { - bool operator()(T* ap, T* bp) const { return ap == bp; } -}; - -//=================================================================== -// -/// Functional clone of the std::unordered_set hash table. -template , class T_Equal = vl_equal_to > -class vl_unordered_set { -public: - // TYPES - typedef std::list Bucket; - enum RehashType { GROW, SHRINK }; - - template 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(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(this)->find_internal(key, bucketIdx); - } - - iterator find(const T_Key& key) { - size_t bucketIdx; - return find_internal(key, bucketIdx); - } - - std::pair 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(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(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_Equal = vl_equal_to > -class vl_unordered_map { -private: - // TYPES - typedef std::pair 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 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(this)->find(k); - } - std::pair 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 diff --git a/include/verilated_vcd_c.cpp b/include/verilated_vcd_c.cpp index e38f507cf..ce26b6c62 100644 --- a/include/verilated_vcd_c.cpp +++ b/include/verilated_vcd_c.cpp @@ -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(); diff --git a/include/verilated_vcd_c.h b/include/verilated_vcd_c.h index 24f10ab7d..63b34ec55 100644 --- a/include/verilated_vcd_c.h +++ b/include/verilated_vcd_c.h @@ -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 m_suffixes; ///< VCD line end string codes + metadata const char* m_suffixesp; ///< Pointer to first element of above typedef std::map 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(); } diff --git a/include/verilated_vcd_sc.cpp b/include/verilated_vcd_sc.cpp index db863366a..a09935527 100644 --- a/include/verilated_vcd_sc.cpp +++ b/include/verilated_vcd_sc.cpp @@ -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 diff --git a/include/verilated_vcd_sc.h b/include/verilated_vcd_sc.h index dcadc8bc2..15d0aae61 100644 --- a/include/verilated_vcd_sc.h +++ b/include/verilated_vcd_sc.h @@ -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 }; diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index e19c332e4..db0f73bf5 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -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 ""; } 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(reinterpret_cast(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(reinterpret_cast(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(reinterpret_cast(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(reinterpret_cast(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(reinterpret_cast(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(reinterpret_cast(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(varp->datap())) + entSize() * offset; } - virtual ~VerilatedVpioMemoryWord() {} + virtual ~VerilatedVpioMemoryWord() override {} static inline VerilatedVpioMemoryWord* castp(vpiHandle h) { return dynamic_cast(reinterpret_cast(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(reinterpret_cast(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(reinterpret_cast(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(reinterpret_cast(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& 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(reinterpret_cast(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 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(Verilated::productName()); } @@ -572,11 +566,11 @@ public: va_end(args); m_errorInfo.state = vpiPLI; filehold = file; - setError((PLI_BYTE8*)m_buff, NULL, const_cast(filehold.c_str()), line); + setError((PLI_BYTE8*)m_buff, nullptr, const_cast(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(mod)); + const VerilatedScope* mod = vop ? vop->scopep() : nullptr; + const auto it = vlstd::as_const(map)->find(const_cast(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(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(*(reinterpret_cast(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(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; diff --git a/include/verilatedos.h b/include/verilatedos.h index 027276558..7ba4ff55c 100644 --- a/include/verilatedos.h +++ b/include/verilatedos.h @@ -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(reinterpret_cast(&var)) = NULL; \ + *const_cast(reinterpret_cast(&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 -# define VL_INCLUDE_UNORDERED_SET -# endif +# define vl_unordered_map std::unordered_map +# define vl_unordered_set std::unordered_set +# define VL_INCLUDE_UNORDERED_MAP +# define VL_INCLUDE_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 T const& as_const(T& v) { return v; } +}; // namespace vlstd + //========================================================================= #endif // Guard diff --git a/src/Makefile_obj.in b/src/Makefile_obj.in index 0c2ed579c..8b058c7b0 100644 --- a/src/Makefile_obj.in +++ b/src/Makefile_obj.in @@ -203,6 +203,7 @@ RAW_OBJS = \ V3GraphPathChecker.o \ V3GraphTest.o \ V3Hashed.o \ + V3HierBlock.o \ V3Inline.o \ V3Inst.o \ V3InstrCount.o \ diff --git a/src/V3Active.cpp b/src/V3Active.cpp index 26cf3f3aa..7b0124922 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -36,7 +36,7 @@ #include "V3Const.h" #include "V3SenTree.h" // for SenTreeSet -#include VL_INCLUDE_UNORDERED_MAP +#include //***** 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 ActiveMap; + typedef std::unordered_map 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 {} }; //###################################################################### diff --git a/src/V3ActiveTop.cpp b/src/V3ActiveTop.cpp index 07f7741d2..b944618cf 100644 --- a/src/V3ActiveTop.cpp +++ b/src/V3ActiveTop.cpp @@ -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 {} }; //###################################################################### diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index 501c9039f..b4205e0a1 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -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(new AstCMath(fl, "Verilated::assertOn()", 1)) : static_cast(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); diff --git a/src/V3AssertPre.cpp b/src/V3AssertPre.cpp index ec1775503..2bc745a1c 100644 --- a/src/V3AssertPre.cpp +++ b/src/V3AssertPre.cpp @@ -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 {} }; //###################################################################### diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp index 31d0b892d..b20a3b184 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -60,17 +60,17 @@ std::ostream& operator<<(std::ostream& os, AstType rhs); void AstNode::init() { editCountInc(); - m_fileline = NULL; - m_nextp = NULL; - m_backp = NULL; + m_fileline = nullptr; + m_nextp = nullptr; + m_backp = nullptr; m_headtailp = this; // When made, we're a list of only a single element - m_op1p = NULL; - m_op2p = NULL; - m_op3p = NULL; - m_op4p = NULL; - m_iterpp = NULL; - m_dtypep = NULL; - m_clonep = NULL; + m_op1p = nullptr; + m_op2p = nullptr; + m_op3p = nullptr; + m_op4p = nullptr; + m_iterpp = nullptr; + m_dtypep = nullptr; + m_clonep = nullptr; m_cloneCnt = 0; // Attributes m_didWidth = false; @@ -275,8 +275,8 @@ AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp) { // New tail needs the head AstNode* newtailp = newp->m_headtailp; AstNode* headp = oldtailp->m_headtailp; - oldtailp->m_headtailp = NULL; // May be written again as new head - newp->m_headtailp = NULL; // May be written again as new tail + oldtailp->m_headtailp = nullptr; // May be written again as new head + newp->m_headtailp = nullptr; // May be written again as new tail newtailp->m_headtailp = headp; headp->m_headtailp = newtailp; newp->editCountInc(); @@ -321,17 +321,17 @@ void AstNode::addNextHere(AstNode* newp) { // tail (oldheadtailp && !oldnextp) // this was tail of list, might also // be head of one-node list // - newp->m_headtailp = NULL; // Not at head any longer - addlastp->m_headtailp = NULL; // Presume middle of list + newp->m_headtailp = nullptr; // Not at head any longer + addlastp->m_headtailp = nullptr; // Presume middle of list // newp might happen to be head/tail after all, if so will be set again below if (oldheadtailp) { // else in middle of list, no change if (oldheadtailp == this) { // this was one node this->m_headtailp = addlastp; // Was head/tail, now a tail - addlastp->m_headtailp = oldheadtailp; // Tail needs to remember head (or NULL) + addlastp->m_headtailp = oldheadtailp; // Tail needs to remember head (or nullptr) } else if (!oldnextp) { // this was tail - this->m_headtailp = NULL; // No longer a tail + this->m_headtailp = nullptr; // No longer a tail oldheadtailp->m_headtailp = addlastp; // Head gets new tail - addlastp->m_headtailp = oldheadtailp; // Tail needs to remember head (or NULL) + addlastp->m_headtailp = oldheadtailp; // Tail needs to remember head (or nullptr) } // else is head, and we're inserting into the middle, so no other change } @@ -470,7 +470,7 @@ AstNode* AstNode::unlinkFrBackWithNext(AstNRelinker* linkerp) { } } if (backp->m_nextp == oldp) { - backp->m_nextp = NULL; + backp->m_nextp = nullptr; // Old list gets truncated // New list becomes a list upon itself // Most common case is unlinking a entire operand tree @@ -486,21 +486,21 @@ AstNode* AstNode::unlinkFrBackWithNext(AstNRelinker* linkerp) { oldp->m_headtailp = oldtailp; oldp->m_headtailp->m_headtailp = oldp; } else if (backp->m_op1p == oldp) { - backp->m_op1p = NULL; + backp->m_op1p = nullptr; } else if (backp->m_op2p == oldp) { - backp->m_op2p = NULL; + backp->m_op2p = nullptr; } else if (backp->m_op3p == oldp) { - backp->m_op3p = NULL; + backp->m_op3p = nullptr; } else if (backp->m_op4p == oldp) { - backp->m_op4p = NULL; + backp->m_op4p = nullptr; } else { this->v3fatalSrc("Unlink of node with back not pointing to it."); } // Relink - oldp->m_backp = NULL; + oldp->m_backp = nullptr; // Iterator fixup - if (oldp->m_iterpp) *(oldp->m_iterpp) = NULL; - oldp->m_iterpp = NULL; + if (oldp->m_iterpp) *(oldp->m_iterpp) = nullptr; + oldp->m_iterpp = nullptr; oldp->debugTreeChange("-unlinkWNextOut: ", __LINE__, true); return oldp; } @@ -561,10 +561,10 @@ AstNode* AstNode::unlinkFrBack(AstNRelinker* linkerp) { // Iterator fixup if (oldp->m_iterpp) *(oldp->m_iterpp) = oldp->m_nextp; // Relink - oldp->m_nextp = NULL; - oldp->m_backp = NULL; + oldp->m_nextp = nullptr; + oldp->m_backp = nullptr; oldp->m_headtailp = this; - oldp->m_iterpp = NULL; + oldp->m_iterpp = nullptr; oldp->debugTreeChange("-unlinkFrBkOut: ", __LINE__, true); return oldp; } @@ -598,7 +598,7 @@ void AstNode::relink(AstNRelinker* linkerp) { } // Relink newp->m_backp = backp; - linkerp->m_backp = NULL; + linkerp->m_backp = nullptr; // Iterator fixup if (linkerp->m_iterpp) { // If we're iterating over a next() link, we need to follow links off the @@ -610,7 +610,7 @@ void AstNode::relink(AstNRelinker* linkerp) { newp->m_iterpp = linkerp->m_iterpp; } // Empty the linker so not used twice accidentally - linkerp->m_backp = NULL; + linkerp->m_backp = nullptr; this->debugTreeChange("-relinkOut: ", __LINE__, true); } @@ -633,8 +633,8 @@ void AstNode::relinkOneLink(AstNode*& pointpr, // Ref to pointer that gets set newlistlastp->m_nextp = pointpr; pointpr->m_backp = newlistlastp; // Head/tail - pointpr->m_headtailp = NULL; // Old head - newlistlastp->m_headtailp = NULL; // Old tail + pointpr->m_headtailp = nullptr; // Old head + newlistlastp->m_headtailp = nullptr; // Old tail newp->m_headtailp = oldlistlastp; // Head points to tail oldlistlastp->m_headtailp = newp; // Tail points to head } @@ -668,7 +668,7 @@ AstNode* AstNode::cloneTreeIter() { if (this->m_op2p) newp->op2p(this->m_op2p->cloneTreeIterList()); if (this->m_op3p) newp->op3p(this->m_op3p->cloneTreeIterList()); if (this->m_op4p) newp->op4p(this->m_op4p->cloneTreeIterList()); - newp->m_iterpp = NULL; + newp->m_iterpp = nullptr; newp->clonep(this); // Save pointers to/from both to simplify relinking. this->clonep(newp); // Save pointers to/from both to simplify relinking. return newp; @@ -676,12 +676,12 @@ AstNode* AstNode::cloneTreeIter() { AstNode* AstNode::cloneTreeIterList() { // private: Clone list of nodes, set m_headtailp - AstNode* newheadp = NULL; - AstNode* newtailp = NULL; - // Audited to make sure this is never NULL + AstNode* newheadp = nullptr; + AstNode* newtailp = nullptr; + // Audited to make sure this is never nullptr for (AstNode* oldp = this; oldp; oldp = oldp->m_nextp) { AstNode* newp = oldp->cloneTreeIter(); - newp->m_headtailp = NULL; + newp->m_headtailp = nullptr; newp->m_backp = newtailp; if (newtailp) newtailp->m_nextp = newp; if (!newheadp) newheadp = newp; @@ -700,10 +700,10 @@ AstNode* AstNode::cloneTree(bool cloneNextLink) { newp = cloneTreeIterList(); } else { newp = cloneTreeIter(); - newp->m_nextp = NULL; + newp->m_nextp = nullptr; newp->m_headtailp = newp; } - newp->m_backp = NULL; + newp->m_backp = nullptr; newp->cloneRelinkTree(); newp->debugTreeChange("-cloneOut: ", __LINE__, true); return newp; @@ -739,7 +739,7 @@ void AstNode::deleteNode() { void AstNode::deleteTreeIter() { // private: Delete list of nodes. Publicly call deleteTree() instead. - // Audited to make sure this is never NULL + // Audited to make sure this is never nullptr for (AstNode *nodep = this, *nnextp; nodep; nodep = nnextp) { nnextp = nodep->m_nextp; // MUST be depth first! @@ -747,8 +747,8 @@ void AstNode::deleteTreeIter() { if (nodep->m_op2p) nodep->m_op2p->deleteTreeIter(); if (nodep->m_op3p) nodep->m_op3p->deleteTreeIter(); if (nodep->m_op4p) nodep->m_op4p->deleteTreeIter(); - nodep->m_nextp = NULL; - nodep->m_backp = NULL; + nodep->m_nextp = nullptr; + nodep->m_backp = nullptr; nodep->deleteNode(); } } @@ -831,11 +831,11 @@ void AstNode::iterateAndNext(AstNVisitor& v) { niterp->m_iterpp = &niterp; niterp->accept(v); // accept may do a replaceNode and change niterp on us... - // niterp maybe NULL, so need cast if printing + // niterp maybe nullptr, so need cast if printing // if (niterp != nodep) UINFO(1,"iterateAndNext edited "<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 logsp(V3File::new_ofstream(filename, append)); + const std::unique_ptr logsp(V3File::new_ofstream(filename, append)); if (logsp->fail()) v3fatal("Can't write " << filename); *logsp << "Verilator Tree Dump (format 0x3900) from to " << endl; @@ -1267,8 +1265,6 @@ AstNodeDType* AstNode::findVoidDType() const { // AstNVisitor void AstNVisitor::doDeletes() { - for (std::vector::iterator it = m_deleteps.begin(); it != m_deleteps.end(); ++it) { - (*it)->deleteTree(); - } + for (AstNode* nodep : m_deleteps) nodep->deleteTree(); m_deleteps.clear(); } diff --git a/src/V3Ast.h b/src/V3Ast.h index f990b491c..636f45df1 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -26,7 +26,7 @@ #include "V3Global.h" #include -#include VL_INCLUDE_UNORDERED_SET +#include #include "V3Ast__gen_classes.h" // From ./astgen // Things like: @@ -82,9 +82,9 @@ public: inline AstType() {} // cppcheck-suppress noExplicitConstructor inline AstType(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline AstType(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } }; inline bool operator==(const AstType& lhs, const AstType& rhs) { return lhs.m_e == rhs.m_e; } @@ -96,19 +96,19 @@ inline std::ostream& operator<<(std::ostream& os, const AstType& rhs) { return o class VLifetime { public: - enum en { NONE, AUTOMATIC, STATIC }; + enum en : uint8_t { NONE, AUTOMATIC, STATIC }; enum en m_e; const char* ascii() const { static const char* const names[] = {"NONE", "VAUTOM", "VSTATIC"}; return names[m_e]; } inline VLifetime() - : m_e(NONE) {} + : m_e{NONE} {} // cppcheck-suppress noExplicitConstructor inline VLifetime(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline VLifetime(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } bool isNone() const { return m_e == NONE; } bool isAutomatic() const { return m_e == AUTOMATIC; } @@ -125,7 +125,7 @@ inline std::ostream& operator<<(std::ostream& os, const VLifetime& rhs) { class VSigning { public: - enum en { + enum en : uint8_t { UNSIGNED, SIGNED, NOSIGN, @@ -137,15 +137,15 @@ public: return names[m_e]; } inline VSigning() - : m_e(UNSIGNED) {} + : m_e{UNSIGNED} {} // cppcheck-suppress noExplicitConstructor inline VSigning(en _e) - : m_e(_e) {} + : m_e{_e} {} static inline VSigning fromBool(bool isSigned) { // Factory method return isSigned ? VSigning(SIGNED) : VSigning(UNSIGNED); } explicit inline VSigning(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } inline bool isSigned() const { return m_e == SIGNED; } inline bool isNosign() const { return m_e == NOSIGN; } @@ -162,9 +162,10 @@ inline std::ostream& operator<<(std::ostream& os, const VSigning& rhs) { class AstPragmaType { public: - enum en { + enum en : uint8_t { ILLEGAL, COVERAGE_BLOCK_OFF, + HIER_BLOCK, INLINE_MODULE, NO_INLINE_MODULE, NO_INLINE_TASK, @@ -176,12 +177,12 @@ public: }; enum en m_e; inline AstPragmaType() - : m_e(ILLEGAL) {} + : m_e{ILLEGAL} {} // cppcheck-suppress noExplicitConstructor inline AstPragmaType(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline AstPragmaType(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } }; inline bool operator==(const AstPragmaType& lhs, const AstPragmaType& rhs) { @@ -194,7 +195,7 @@ inline bool operator==(AstPragmaType::en lhs, const AstPragmaType& rhs) { return class AstCFuncType { public: - enum en { + enum en : uint8_t { FT_NORMAL, TRACE_REGISTER, TRACE_INIT, @@ -207,12 +208,12 @@ public: }; enum en m_e; inline AstCFuncType() - : m_e(FT_NORMAL) {} + : m_e{FT_NORMAL} {} // cppcheck-suppress noExplicitConstructor inline AstCFuncType(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline AstCFuncType(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } // METHODS bool isTrace() const { return m_e != FT_NORMAL; } @@ -228,7 +229,7 @@ inline bool operator==(AstCFuncType::en lhs, const AstCFuncType& rhs) { return l class VEdgeType { public: // REMEMBER to edit the strings below too - enum en { + enum en : uint8_t { // These must be in general -> most specific order, as we sort by it // in V3Const::visit AstSenTree ET_ILLEGAL, @@ -297,12 +298,12 @@ public: return false; } inline VEdgeType() - : m_e(ET_ILLEGAL) {} + : m_e{ET_ILLEGAL} {} // cppcheck-suppress noExplicitConstructor inline VEdgeType(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline VEdgeType(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } }; inline bool operator==(const VEdgeType& lhs, const VEdgeType& rhs) { return lhs.m_e == rhs.m_e; } @@ -314,7 +315,7 @@ inline bool operator==(VEdgeType::en lhs, const VEdgeType& rhs) { return lhs == class AstAttrType { public: // clang-format off - enum en { + enum en: uint8_t { ILLEGAL, // DIM_BITS, // V3Const converts to constant @@ -342,7 +343,6 @@ public: TYPENAME, // V3Width processes // VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes - VAR_CLOCK, // V3LinkParse moves to AstVar::attrScClocked VAR_CLOCK_ENABLE, // V3LinkParse moves to AstVar::attrClockEn VAR_PUBLIC, // V3LinkParse moves to AstVar::sigPublic VAR_PUBLIC_FLAT, // V3LinkParse moves to AstVar::sigPublic @@ -368,7 +368,7 @@ public: "ENUM_NEXT", "ENUM_PREV", "ENUM_NAME", "MEMBER_BASE", "TYPENAME", - "VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC", + "VAR_BASE", "VAR_CLOCK_ENABLE", "VAR_PUBLIC", "VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD", "VAR_PUBLIC_FLAT_RW", "VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT", "VAR_CLOCKER", "VAR_NO_CLOCKER", "VAR_SPLIT_VAR" @@ -377,12 +377,12 @@ public: return names[m_e]; } inline AstAttrType() - : m_e(ILLEGAL) {} + : m_e{ILLEGAL} {} // cppcheck-suppress noExplicitConstructor inline AstAttrType(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline AstAttrType(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } }; inline bool operator==(const AstAttrType& lhs, const AstAttrType& rhs) { @@ -395,7 +395,7 @@ inline bool operator==(AstAttrType::en lhs, const AstAttrType& rhs) { return lhs class AstBasicDTypeKwd { public: - enum en { + enum en : uint8_t { UNKNOWN, BIT, BYTE, @@ -447,12 +447,12 @@ public: "SelfTest: Enum mismatch"); } inline AstBasicDTypeKwd() - : m_e(UNKNOWN) {} + : m_e{UNKNOWN} {} // cppcheck-suppress noExplicitConstructor inline AstBasicDTypeKwd(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline AstBasicDTypeKwd(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } int width() const { switch (m_e) { @@ -531,15 +531,15 @@ inline bool operator==(AstBasicDTypeKwd::en lhs, const AstBasicDTypeKwd& rhs) { class VDirection { public: - enum en { NONE, INPUT, OUTPUT, INOUT, REF, CONSTREF }; + enum en : uint8_t { NONE, INPUT, OUTPUT, INOUT, REF, CONSTREF }; enum en m_e; inline VDirection() - : m_e(NONE) {} + : m_e{NONE} {} // cppcheck-suppress noExplicitConstructor inline VDirection(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline VDirection(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } const char* ascii() const { static const char* const names[] = {"NONE", "INPUT", "OUTPUT", "INOUT", "REF", "CONSTREF"}; @@ -576,16 +576,16 @@ inline std::ostream& operator<<(std::ostream& os, const VDirection& rhs) { /// Boolean or unknown class VBoolOrUnknown { public: - enum en { BU_FALSE = 0, BU_TRUE = 1, BU_UNKNOWN = 2, _ENUM_END }; + enum en : uint8_t { BU_FALSE = 0, BU_TRUE = 1, BU_UNKNOWN = 2, _ENUM_END }; enum en m_e; // CONSTRUCTOR - note defaults to *UNKNOWN* inline VBoolOrUnknown() - : m_e(BU_UNKNOWN) {} + : m_e{BU_UNKNOWN} {} // cppcheck-suppress noExplicitConstructor inline VBoolOrUnknown(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline VBoolOrUnknown(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning const char* ascii() const { static const char* const names[] = {"FALSE", "TRUE", "UNK"}; return names[m_e]; @@ -615,16 +615,16 @@ inline std::ostream& operator<<(std::ostream& os, const VBoolOrUnknown& rhs) { /// Join type class VJoinType { public: - enum en { JOIN = 0, JOIN_ANY = 1, JOIN_NONE = 2 }; + enum en : uint8_t { JOIN = 0, JOIN_ANY = 1, JOIN_NONE = 2 }; enum en m_e; // CONSTRUCTOR - note defaults to *UNKNOWN* inline VJoinType() - : m_e(JOIN) {} + : m_e{JOIN} {} // cppcheck-suppress noExplicitConstructor inline VJoinType(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline VJoinType(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning const char* ascii() const { static const char* const names[] = {"JOIN", "JOIN_ANY", "JOIN_NONE"}; return names[m_e]; @@ -648,7 +648,7 @@ inline std::ostream& operator<<(std::ostream& os, const VJoinType& rhs) { class AstVarType { public: - enum en { + enum en : uint8_t { UNKNOWN, GPARAM, LPARAM, @@ -672,12 +672,12 @@ public: }; enum en m_e; inline AstVarType() - : m_e(UNKNOWN) {} + : m_e{UNKNOWN} {} // cppcheck-suppress noExplicitConstructor inline AstVarType(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline AstVarType(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } const char* ascii() const { static const char* const names[] = { @@ -716,16 +716,16 @@ inline std::ostream& operator<<(std::ostream& os, const AstVarType& rhs) { class VBranchPred { public: - enum en { BP_UNKNOWN = 0, BP_LIKELY, BP_UNLIKELY, _ENUM_END }; + enum en : uint8_t { BP_UNKNOWN = 0, BP_LIKELY, BP_UNLIKELY, _ENUM_END }; enum en m_e; // CONSTRUCTOR - note defaults to *UNKNOWN* inline VBranchPred() - : m_e(BP_UNKNOWN) {} + : m_e{BP_UNKNOWN} {} // cppcheck-suppress noExplicitConstructor inline VBranchPred(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline VBranchPred(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } bool unknown() const { return m_e == BP_UNKNOWN; } bool likely() const { return m_e == BP_LIKELY; } @@ -757,16 +757,16 @@ inline std::ostream& operator<<(std::ostream& os, const VBranchPred& rhs) { class VVarAttrClocker { public: - enum en { CLOCKER_UNKNOWN = 0, CLOCKER_YES, CLOCKER_NO, _ENUM_END }; + enum en : uint8_t { CLOCKER_UNKNOWN = 0, CLOCKER_YES, CLOCKER_NO, _ENUM_END }; enum en m_e; // CONSTRUCTOR - note defaults to *UNKNOWN* inline VVarAttrClocker() - : m_e(CLOCKER_UNKNOWN) {} + : m_e{CLOCKER_UNKNOWN} {} // cppcheck-suppress noExplicitConstructor inline VVarAttrClocker(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline VVarAttrClocker(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } bool unknown() const { return m_e == CLOCKER_UNKNOWN; } VVarAttrClocker invert() const { @@ -800,15 +800,15 @@ inline std::ostream& operator<<(std::ostream& os, const VVarAttrClocker& rhs) { class VAlwaysKwd { public: - enum en { ALWAYS, ALWAYS_FF, ALWAYS_LATCH, ALWAYS_COMB }; + enum en : uint8_t { ALWAYS, ALWAYS_FF, ALWAYS_LATCH, ALWAYS_COMB }; enum en m_e; inline VAlwaysKwd() - : m_e(ALWAYS) {} + : m_e{ALWAYS} {} // cppcheck-suppress noExplicitConstructor inline VAlwaysKwd(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline VAlwaysKwd(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } const char* ascii() const { static const char* const names[] = {"always", "always_ff", "always_latch", "always_comb"}; @@ -823,15 +823,15 @@ inline bool operator==(VAlwaysKwd::en lhs, const VAlwaysKwd& rhs) { return lhs = class VCaseType { public: - enum en { CT_CASE, CT_CASEX, CT_CASEZ, CT_CASEINSIDE }; + enum en : uint8_t { CT_CASE, CT_CASEX, CT_CASEZ, CT_CASEINSIDE }; enum en m_e; inline VCaseType() - : m_e(CT_CASE) {} + : m_e{CT_CASE} {} // cppcheck-suppress noExplicitConstructor inline VCaseType(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline VCaseType(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } }; inline bool operator==(const VCaseType& lhs, const VCaseType& rhs) { return lhs.m_e == rhs.m_e; } @@ -842,15 +842,15 @@ inline bool operator==(VCaseType::en lhs, const VCaseType& rhs) { return lhs == class AstDisplayType { public: - enum en { DT_DISPLAY, DT_WRITE, DT_INFO, DT_ERROR, DT_WARNING, DT_FATAL }; + enum en : uint8_t { DT_DISPLAY, DT_WRITE, DT_INFO, DT_ERROR, DT_WARNING, DT_FATAL }; enum en m_e; inline AstDisplayType() - : m_e(DT_DISPLAY) {} + : m_e{DT_DISPLAY} {} // cppcheck-suppress noExplicitConstructor inline AstDisplayType(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline AstDisplayType(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } bool addNewline() const { return m_e != DT_WRITE; } bool needScopeTracking() const { return m_e != DT_DISPLAY && m_e != DT_WRITE; } @@ -874,15 +874,15 @@ inline bool operator==(AstDisplayType::en lhs, const AstDisplayType& rhs) { class VDumpCtlType { public: - enum en { FILE, VARS, ALL, FLUSH, LIMIT, OFF, ON }; + enum en : uint8_t { FILE, VARS, ALL, FLUSH, LIMIT, OFF, ON }; enum en m_e; inline VDumpCtlType() - : m_e(ON) {} + : m_e{ON} {} // cppcheck-suppress noExplicitConstructor inline VDumpCtlType(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline VDumpCtlType(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } const char* ascii() const { static const char* const names[] = {"$dumpfile", "$dumpvars", "$dumpall", "$dumpflush", @@ -900,19 +900,19 @@ inline bool operator==(VDumpCtlType::en lhs, const VDumpCtlType& rhs) { return l class VParseRefExp { public: - enum en { + enum en : uint8_t { PX_NONE, // Used in V3LinkParse only PX_ROOT, PX_TEXT // Unknown ID component }; enum en m_e; inline VParseRefExp() - : m_e(PX_NONE) {} + : m_e{PX_NONE} {} // cppcheck-suppress noExplicitConstructor inline VParseRefExp(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline VParseRefExp(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } const char* ascii() const { static const char* const names[] = {"", "$root", "TEXT", "PREDOT"}; @@ -958,19 +958,19 @@ public: // class LeftRight {}; VNumRange() - : m_hi(0) - , m_lo(0) - , mu_flags(0) {} + : m_hi{0} + , m_lo{0} + , mu_flags{0} {} VNumRange(int hi, int lo, bool littleEndian) - : m_hi(0) - , m_lo(0) - , mu_flags(0) { + : m_hi{0} + , m_lo{0} + , mu_flags{0} { init(hi, lo, littleEndian); } VNumRange(LeftRight, int left, int right) - : m_hi(0) - , m_lo(0) - , mu_flags(0) { + : m_hi{0} + , m_lo{0} + , mu_flags{0} { init((right > left) ? right : left, (right > left) ? left : right, (right > left)); } ~VNumRange() {} @@ -1013,7 +1013,7 @@ inline std::ostream& operator<<(std::ostream& os, const VNumRange& rhs) { class VUseType { public: - enum en { + enum en : uint8_t { IMP_INCLUDE, // Implementation (.cpp) needs an include INT_INCLUDE, // Interface (.h) needs an include IMP_FWD_CLASS, // Implementation (.cpp) needs a forward class declaration @@ -1021,12 +1021,12 @@ public: }; enum en m_e; inline VUseType() - : m_e(IMP_FWD_CLASS) {} + : m_e{IMP_FWD_CLASS} {} // cppcheck-suppress noExplicitConstructor inline VUseType(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline VUseType(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning bool isInclude() const { return m_e == IMP_INCLUDE || m_e == INT_INCLUDE; } bool isFwdClass() const { return m_e == IMP_FWD_CLASS || m_e == INT_FWD_CLASS; } operator en() const { return m_e; } @@ -1070,11 +1070,11 @@ public: } VBasicTypeKey(int width, int widthMin, VSigning numeric, AstBasicDTypeKwd kwd, const VNumRange& nrange) - : m_width(width) - , m_widthMin(widthMin) - , m_numeric(numeric) - , m_keyword(kwd) - , m_nrange(nrange) {} + : m_width{width} + , m_widthMin{widthMin} + , m_numeric{numeric} + , m_keyword{kwd} + , m_nrange{nrange} {} ~VBasicTypeKey() {} }; @@ -1241,9 +1241,9 @@ public: void iterateChildrenBackwards(AstNode* nodep); /// Call visit()s on const nodep's children void iterateChildrenConst(AstNode* nodep); - /// Call visit()s on nodep (maybe NULL) and nodep's nextp() list + /// Call visit()s on nodep (maybe nullptr) and nodep's nextp() list void iterateAndNextNull(AstNode* nodep); - /// Call visit()s on const nodep (maybe NULL) and nodep's nextp() list + /// Call visit()s on const nodep (maybe nullptr) and nodep's nextp() list void iterateAndNextConstNull(AstNode* nodep); /// Return edited nodep; see comments in V3Ast.cpp AstNode* iterateSubtreeReturnEdits(AstNode* nodep); @@ -1261,19 +1261,21 @@ public: class AstNRelinker { protected: friend class AstNode; - enum RelinkWhatEn { RELINK_BAD, RELINK_NEXT, RELINK_OP1, RELINK_OP2, RELINK_OP3, RELINK_OP4 }; - AstNode* m_oldp; // The old node that was linked to this point in the tree - AstNode* m_backp; - RelinkWhatEn m_chg; - AstNode** m_iterpp; + enum RelinkWhatEn : uint8_t { + RELINK_BAD, + RELINK_NEXT, + RELINK_OP1, + RELINK_OP2, + RELINK_OP3, + RELINK_OP4 + }; + AstNode* m_oldp = nullptr; // The old node that was linked to this point in the tree + AstNode* m_backp = nullptr; + RelinkWhatEn m_chg = RELINK_BAD; + AstNode** m_iterpp = nullptr; public: - AstNRelinker() { - m_oldp = NULL; - m_backp = NULL; - m_chg = RELINK_BAD; - m_iterpp = NULL; - } + AstNRelinker() {} void relink(AstNode* newp); AstNode* oldp() const { return m_oldp; } void dump(std::ostream& str = std::cout) const; @@ -1441,11 +1443,11 @@ public: protected: // CONSTRUCTORS AstNode(AstType t) - : m_type(t) { + : m_type{t} { init(); } AstNode(AstType t, FileLine* fl) - : m_type(t) { + : m_type{t} { init(); m_fileline = fl; } @@ -1497,9 +1499,9 @@ public: AstNode* op3p() const { return m_op3p; } AstNode* op4p() const { return m_op4p; } AstNodeDType* dtypep() const { return m_dtypep; } - AstNode* clonep() const { return ((m_cloneCnt == s_cloneCntGbl) ? m_clonep : NULL); } - AstNode* firstAbovep() const { // Returns NULL when second or later in list - return ((backp() && backp()->nextp() != this) ? backp() : NULL); + AstNode* clonep() const { return ((m_cloneCnt == s_cloneCntGbl) ? m_clonep : nullptr); } + AstNode* firstAbovep() const { // Returns nullptr when second or later in list + return ((backp() && backp()->nextp() != this) ? backp() : nullptr); } bool brokeExists() const; bool brokeExistsAbove() const; @@ -1663,7 +1665,7 @@ public: static void editCountSetLast() { s_editCntLast = editCountGbl(); } // ACCESSORS for specific types - // Alas these can't be virtual or they break when passed a NULL + // Alas these can't be virtual or they break when passed a nullptr bool isZero() const; bool isOne() const; bool isNeqZero() const; @@ -1734,7 +1736,7 @@ public: // METHODS - Tree modifications // Returns nodep, adds newp to end of nodep's list static AstNode* addNext(AstNode* nodep, AstNode* newp); - // Returns nodep, adds newp (maybe NULL) to end of nodep's list + // Returns nodep, adds newp (maybe nullptr) to end of nodep's list static AstNode* addNextNull(AstNode* nodep, AstNode* newp); inline AstNode* addNext(AstNode* newp) { return addNext(this, newp); } inline AstNode* addNextNull(AstNode* newp) { return addNextNull(this, newp); } @@ -1745,9 +1747,10 @@ public: } void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next void replaceWith(AstNode* newp); // Replace current node in tree with new node - AstNode* unlinkFrBack(AstNRelinker* linkerp = NULL); // Unlink this from whoever points to it. + AstNode* unlinkFrBack(AstNRelinker* linkerp + = nullptr); // Unlink this from whoever points to it. // Unlink this from whoever points to it, keep entire next list with unlinked node - AstNode* unlinkFrBackWithNext(AstNRelinker* linkerp = NULL); + AstNode* unlinkFrBackWithNext(AstNRelinker* linkerp = nullptr); void swapWith(AstNode* bp); void relink(AstNRelinker* linkerp); // Generally use linker->relink() instead void cloneRelinkNode() { cloneRelink(); } @@ -1758,9 +1761,9 @@ public: AstNode* belowp); // When calling, "this" is second argument // METHODS - Iterate on a tree - // Clone or return NULL if NULL + // Clone or return nullptr if nullptr static AstNode* cloneTreeNull(AstNode* nodep, bool cloneNextLink) { - return nodep ? nodep->cloneTree(cloneNextLink) : NULL; + return nodep ? nodep->cloneTree(cloneNextLink) : nullptr; } AstNode* cloneTree(bool cloneNextLink); // Not const, as sets clonep() on original nodep bool gateTree() { return gateTreeIter(); } // Is tree isGateOptimizable? @@ -1770,7 +1773,7 @@ public: void deleteTree(); // Always deletes the next link void checkTree(); // User Interface version void checkIter() const; - void clearIter() { m_iterpp = NULL; } + void clearIter() { m_iterpp = nullptr; } void dumpPtrs(std::ostream& os = std::cout) const; void dumpTree(std::ostream& os = std::cout, const string& indent = " ", int maxDepth = 0) const; @@ -1781,7 +1784,7 @@ public: void dumpTreeAndNext(std::ostream& os = std::cout, const string& indent = " ", int maxDepth = 0) const; void dumpTreeFile(const string& filename, bool append = false, bool doDump = true); - static void dumpTreeFileGdb(const char* filenamep = NULL); + static void dumpTreeFileGdb(const char* filenamep = nullptr); // METHODS - queries // Changes control flow, disable some optimizations @@ -1811,12 +1814,12 @@ public: // Iff has a data type; dtype() must be non null virtual bool hasDType() const { return false; } // Iff has a non-null childDTypep(), as generic node function - virtual AstNodeDType* getChildDTypep() const { return NULL; } + virtual AstNodeDType* getChildDTypep() const { return nullptr; } // Iff has a non-null child2DTypep(), as generic node function - virtual AstNodeDType* getChild2DTypep() const { return NULL; } + virtual AstNodeDType* getChild2DTypep() const { return nullptr; } // Another AstNode* may have a pointer into this node, other then normal front/back/etc. virtual bool maybePointedTo() const { return false; } - virtual const char* broken() const { return NULL; } + virtual const char* broken() const { return nullptr; } // INVOKERS virtual void accept(AstNVisitor& v) = 0; @@ -1857,7 +1860,7 @@ public: inline std::ostream& operator<<(std::ostream& os, const AstNode* rhs) { if (!rhs) { - os << "NULL"; + os << "nullptr"; } else { rhs->dump(os); } @@ -1872,7 +1875,7 @@ inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); } #define ASTNODE_BASE_FUNCS(name) \ virtual ~Ast##name() {} \ static Ast##name* cloneTreeNull(Ast##name* nodep, bool cloneNextLink) { \ - return nodep ? nodep->cloneTree(cloneNextLink) : NULL; \ + return nodep ? nodep->cloneTree(cloneNextLink) : nullptr; \ } \ Ast##name* cloneTree(bool cloneNext) { \ return static_cast(AstNode::cloneTree(cloneNext)); \ @@ -1883,10 +1886,10 @@ class AstNodeMath : public AstNode { // Math -- anything that's part of an expression tree public: AstNodeMath(AstType t, FileLine* fl) - : AstNode(t, fl) {} + : AstNode{t, fl} {} ASTNODE_BASE_FUNCS(NodeMath) // METHODS - virtual bool hasDType() const { return true; } + virtual bool hasDType() const override { return true; } virtual string emitVerilog() = 0; /// Format string for verilog writing; see V3EmitV // For documentation on emitC format see EmitCStmts::emitOpName virtual string emitC() = 0; @@ -1902,7 +1905,7 @@ class AstNodeTermop : public AstNodeMath { // Terminal operator -- a operator with no "inputs" public: AstNodeTermop(AstType t, FileLine* fl) - : AstNodeMath(t, fl) {} + : AstNodeMath{t, fl} {} ASTNODE_BASE_FUNCS(NodeTermop) // Know no children, and hot function, so skip iterator for speed // See checkTreeIter also that asserts no children @@ -1914,7 +1917,7 @@ class AstNodeUniop : public AstNodeMath { // Unary math public: AstNodeUniop(AstType t, FileLine* fl, AstNode* lhsp) - : AstNodeMath(t, fl) { + : AstNodeMath{t, fl} { dtypeFrom(lhsp); setOp1p(lhsp); } @@ -1930,16 +1933,16 @@ public: // Signed flavor of nodes with both flavors? virtual bool signedFlavor() const { return false; } virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors? - virtual int instrCount() const { return widthInstrs(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode*) const { return true; } + virtual int instrCount() const override { return widthInstrs(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode*) const override { return true; } }; class AstNodeBiop : public AstNodeMath { // Binary math public: AstNodeBiop(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs) - : AstNodeMath(t, fl) { + : AstNodeMath{t, fl} { setOp1p(lhs); setOp2p(rhs); } @@ -1962,16 +1965,16 @@ public: // Signed flavor of nodes with both flavors? virtual bool signedFlavor() const { return false; } virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors? - virtual int instrCount() const { return widthInstrs(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode*) const { return true; } + virtual int instrCount() const override { return widthInstrs(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode*) const override { return true; } }; class AstNodeTriop : public AstNodeMath { // Trinary math public: AstNodeTriop(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths) - : AstNodeMath(t, fl) { + : AstNodeMath{t, fl} { setOp1p(lhs); setOp2p(rhs); setOp3p(ths); @@ -1994,16 +1997,16 @@ public: virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size virtual bool sizeMattersThs() const = 0; // True if output result depends on ths size - virtual int instrCount() const { return widthInstrs(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode*) const { return true; } + virtual int instrCount() const override { return widthInstrs(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode*) const override { return true; } }; class AstNodeQuadop : public AstNodeMath { // Quaternary math public: AstNodeQuadop(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths, AstNode* fhs) - : AstNodeMath(t, fl) { + : AstNodeMath{t, fl} { setOp1p(lhs); setOp2p(rhs); setOp3p(ths); @@ -2031,16 +2034,16 @@ public: virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size virtual bool sizeMattersThs() const = 0; // True if output result depends on ths size virtual bool sizeMattersFhs() const = 0; // True if output result depends on ths size - virtual int instrCount() const { return widthInstrs(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode*) const { return true; } + virtual int instrCount() const override { return widthInstrs(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode*) const override { return true; } }; class AstNodeBiCom : public AstNodeBiop { // Binary math with commutative properties public: AstNodeBiCom(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs) - : AstNodeBiop(t, fl, lhs, rhs) {} + : AstNodeBiop{t, fl, lhs, rhs} {} ASTNODE_BASE_FUNCS(NodeBiCom) }; @@ -2048,13 +2051,13 @@ class AstNodeBiComAsv : public AstNodeBiCom { // Binary math with commutative & associative properties public: AstNodeBiComAsv(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs) - : AstNodeBiCom(t, fl, lhs, rhs) {} + : AstNodeBiCom{t, fl, lhs, rhs} {} ASTNODE_BASE_FUNCS(NodeBiComAsv) }; class AstNodeCond : public AstNodeTriop { public: AstNodeCond(AstType t, FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) - : AstNodeTriop(t, fl, condp, expr1p, expr2p) { + : AstNodeTriop{t, fl, condp, expr1p, expr2p} { if (expr1p) { dtypeFrom(expr1p); } else if (expr2p) { @@ -2063,20 +2066,22 @@ public: } ASTNODE_BASE_FUNCS(NodeCond) virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths); + const V3Number& ths) override; AstNode* condp() const { return op1p(); } // op1 = Condition AstNode* expr1p() const { return op2p(); } // op2 = If true... AstNode* expr2p() const { return op3p(); } // op3 = If false... - virtual string emitVerilog() { return "%k(%l %f? %r %k: %t)"; } - virtual string emitC() { return "VL_COND_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri, %ti)"; } - virtual bool cleanOut() const { return false; } // clean if e1 & e2 clean - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return false; } - virtual bool cleanThs() const { return false; } // Propagates up - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual bool sizeMattersThs() const { return false; } - virtual int instrCount() const { return instrCountBranch(); } + virtual string emitVerilog() override { return "%k(%l %f? %r %k: %t)"; } + virtual string emitC() override { + return "VL_COND_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri, %ti)"; + } + virtual bool cleanOut() const override { return false; } // clean if e1 & e2 clean + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return false; } + virtual bool cleanThs() const override { return false; } // Propagates up + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool sizeMattersThs() const override { return false; } + virtual int instrCount() const override { return instrCountBranch(); } virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) = 0; }; @@ -2089,15 +2094,15 @@ private: bool m_unnamed; // Originally unnamed (name change does not affect this) public: AstNodeBlock(AstType t, FileLine* fl, const string& name, AstNode* stmtsp) - : AstNode(t, fl) - , m_name(name) { + : AstNode{t, fl} + , m_name{name} { addNOp1p(stmtsp); m_unnamed = (name == ""); } ASTNODE_BASE_FUNCS(NodeBlock) - virtual void dump(std::ostream& str) const; - virtual string name() const { return m_name; } // * = Block name - virtual void name(const string& name) { m_name = name; } + virtual void dump(std::ostream& str) const override; + virtual string name() const override { return m_name; } // * = Block name + virtual void name(const string& name) override { m_name = name; } // op1 = Statements AstNode* stmtsp() const { return op1p(); } // op1 = List of statements void addStmtsp(AstNode* nodep) { addNOp1p(nodep); } @@ -2108,7 +2113,7 @@ class AstNodePreSel : public AstNode { // Something that becomes an AstSel public: AstNodePreSel(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths) - : AstNode(t, fl) { + : AstNode{t, fl} { setOp1p(lhs); setOp2p(rhs); setNOp3p(ths); @@ -2124,15 +2129,15 @@ public: void thsp(AstNode* nodep) { return setOp3p(nodep); } void attrp(AstAttrOf* nodep) { return setOp4p((AstNode*)nodep); } // METHODS - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode*) const { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode*) const override { return true; } }; class AstNodeProcedure : public AstNode { // IEEE procedure: initial, final, always public: AstNodeProcedure(AstType t, FileLine* fl, AstNode* bodysp) - : AstNode(t, fl) { + : AstNode{t, fl} { addNOp2p(bodysp); } ASTNODE_BASE_FUNCS(NodeProcedure) @@ -2147,8 +2152,8 @@ class AstNodeStmt : public AstNode { bool m_statement; // Really a statement (e.g. not a function with return) public: AstNodeStmt(AstType t, FileLine* fl, bool statement = true) - : AstNode(t, fl) - , m_statement(statement) {} + : AstNode{t, fl} + , m_statement{statement} {} ASTNODE_BASE_FUNCS(NodeStmt) // METHODS bool isStatement() const { return m_statement; } // Really a statement @@ -2160,7 +2165,7 @@ public: class AstNodeAssign : public AstNodeStmt { public: AstNodeAssign(AstType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : AstNodeStmt(t, fl) { + : AstNodeStmt{t, fl} { setOp1p(rhsp); setOp2p(lhsp); dtypeFrom(lhsp); @@ -2173,12 +2178,12 @@ public: AstNode* lhsp() const { return op2p(); } // op2 = Assign to void rhsp(AstNode* np) { setOp1p(np); } void lhsp(AstNode* np) { setOp2p(np); } - virtual bool hasDType() const { return true; } + virtual bool hasDType() const override { return true; } virtual bool cleanRhs() const { return true; } - virtual int instrCount() const { return widthInstrs(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode*) const { return true; } - virtual string verilogKwd() const { return "="; } + virtual int instrCount() const override { return widthInstrs(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode*) const override { return true; } + virtual string verilogKwd() const override { return "="; } virtual bool brokeLhsMustBeLvalue() const = 0; }; @@ -2186,7 +2191,7 @@ class AstNodeFor : public AstNodeStmt { public: AstNodeFor(AstType t, FileLine* fl, AstNode* initsp, AstNode* condp, AstNode* incsp, AstNode* bodysp) - : AstNodeStmt(t, fl) { + : AstNodeStmt{t, fl} { addNOp1p(initsp); setOp2p(condp); addNOp3p(incsp); @@ -2197,10 +2202,10 @@ public: AstNode* condp() const { return op2p(); } // op2 = condition to continue AstNode* incsp() const { return op3p(); } // op3 = increment statements AstNode* bodysp() const { return op4p(); } // op4 = body of loop - virtual bool isGateOptimizable() const { return false; } - virtual int instrCount() const { return instrCountBranch(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual int instrCount() const override { return instrCountBranch(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } }; class AstNodeIf : public AstNodeStmt { @@ -2208,7 +2213,7 @@ private: VBranchPred m_branchPred; // Branch prediction as taken/untaken? public: AstNodeIf(AstType t, FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp) - : AstNodeStmt(t, fl) { + : AstNodeStmt{t, fl} { setOp1p(condp); addNOp2p(ifsp); addNOp3p(elsesp); @@ -2220,11 +2225,11 @@ public: void condp(AstNode* newp) { setOp1p(newp); } void addIfsp(AstNode* newp) { addOp2p(newp); } void addElsesp(AstNode* newp) { addOp3p(newp); } - virtual bool isGateOptimizable() const { return false; } - virtual bool isGateDedupable() const { return true; } - virtual int instrCount() const { return instrCountBranch(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isGateDedupable() const override { return true; } + virtual int instrCount() const override { return instrCountBranch(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } void branchPred(VBranchPred flag) { m_branchPred = flag; } VBranchPred branchPred() const { return m_branchPred; } }; @@ -2232,12 +2237,12 @@ public: class AstNodeCase : public AstNodeStmt { public: AstNodeCase(AstType t, FileLine* fl, AstNode* exprp, AstNode* casesp) - : AstNodeStmt(t, fl) { + : AstNodeStmt{t, fl} { setOp1p(exprp); addNOp2p(casesp); } ASTNODE_BASE_FUNCS(NodeCase) - virtual int instrCount() const { return instrCountBranch(); } + virtual int instrCount() const override { return instrCountBranch(); } AstNode* exprp() const { return op1p(); } // op1 = case condition AstCaseItem* itemsp() const { return VN_CAST(op2p(), CaseItem); @@ -2252,39 +2257,33 @@ class AstNodeVarRef : public AstNodeMath { private: bool m_lvalue; // Left hand side assignment AstVar* m_varp; // [AfterLink] Pointer to variable itself - AstVarScope* m_varScopep; // Varscope for hierarchy - AstNodeModule* m_packagep; // Package hierarchy + AstVarScope* m_varScopep = nullptr; // Varscope for hierarchy + AstNodeModule* m_packagep = nullptr; // Package hierarchy string m_name; // Name of variable string m_hiername; // Scope converted into name-> for emitting - bool m_hierThis; // Hiername points to "this" function + bool m_hierThis = false; // Hiername points to "this" function public: AstNodeVarRef(AstType t, FileLine* fl, const string& name, bool lvalue) - : AstNodeMath(t, fl) - , m_lvalue(lvalue) - , m_varScopep(NULL) - , m_packagep(NULL) - , m_name(name) - , m_hierThis(false) { - this->varp(NULL); + : AstNodeMath{t, fl} + , m_lvalue{lvalue} + , m_name{name} { + this->varp(nullptr); } AstNodeVarRef(AstType t, FileLine* fl, const string& name, AstVar* varp, bool lvalue) - : AstNodeMath(t, fl) - , m_lvalue(lvalue) - , m_varScopep(NULL) - , m_packagep(NULL) - , m_name(name) - , m_hierThis(false) { - // May have varp==NULL + : AstNodeMath{t, fl} + , m_lvalue{lvalue} + , m_name{name} { + // May have varp==nullptr this->varp(varp); } ASTNODE_BASE_FUNCS(NodeVarRef) - virtual bool hasDType() const { return true; } - virtual const char* broken() const; - virtual int instrCount() const { return widthInstrs(); } - virtual void cloneRelink(); - virtual string name() const { return m_name; } // * = Var name - virtual void name(const string& name) { m_name = name; } + virtual bool hasDType() const override { return true; } + virtual const char* broken() const override; + virtual int instrCount() const override { return widthInstrs(); } + virtual void cloneRelink() override; + virtual string name() const override { return m_name; } // * = Var name + virtual void name(const string& name) override { m_name = name; } bool lvalue() const { return m_lvalue; } void lvalue(bool lval) { m_lvalue = lval; } // Avoid using this; Set in constructor AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable @@ -2311,13 +2310,13 @@ private: public: // Node that simply puts text into the output stream AstNodeText(AstType t, FileLine* fl, const string& textp) - : AstNode(t, fl) { + : AstNode{t, fl} { m_text = textp; // Copy it } ASTNODE_BASE_FUNCS(NodeText) - virtual void dump(std::ostream& str = std::cout) const; - virtual V3Hash sameHash() const { return V3Hash(text()); } - virtual bool same(const AstNode* samep) const { + virtual void dump(std::ostream& str = std::cout) const override; + virtual V3Hash sameHash() const override { return V3Hash(text()); } + virtual bool same(const AstNode* samep) const override { const AstNodeText* asamep = static_cast(samep); return text() == asamep->text(); } @@ -2340,16 +2339,16 @@ private: public: // CONSTRUCTORS AstNodeDType(AstType t, FileLine* fl) - : AstNode(t, fl) { + : AstNode{t, fl} { m_width = 0; m_widthMin = 0; m_generic = false; } ASTNODE_BASE_FUNCS(NodeDType) // ACCESSORS - virtual void dump(std::ostream& str) const; + virtual void dump(std::ostream& str) const override; virtual void dumpSmall(std::ostream& str) const; - virtual bool hasDType() const { return true; } + virtual bool hasDType() const override { return true; } virtual AstBasicDType* basicp() const = 0; // (Slow) recurse down to find basic data type // recurses over typedefs/const/enum to next non-typeref type virtual AstNodeDType* skipRefp() const = 0; @@ -2361,19 +2360,19 @@ public: virtual int widthAlignBytes() const = 0; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... virtual int widthTotalBytes() const = 0; - virtual bool maybePointedTo() const { return true; } + virtual bool maybePointedTo() const override { return true; } // Iff has a non-null refDTypep(), as generic node function - virtual AstNodeDType* virtRefDTypep() const { return NULL; } + virtual AstNodeDType* virtRefDTypep() const { return nullptr; } // Iff has refDTypep(), set as generic node function virtual void virtRefDTypep(AstNodeDType* nodep) {} // Iff has a non-null second dtypep, as generic node function - virtual AstNodeDType* virtRefDType2p() const { return NULL; } + virtual AstNodeDType* virtRefDType2p() const { return nullptr; } // Iff has second dtype, set as generic node function virtual void virtRefDType2p(AstNodeDType* nodep) {} // Assignable equivalence. Call skipRefp() on this and samep before calling virtual bool similarDType(AstNodeDType* samep) const = 0; // Iff has a non-null subDTypep(), as generic node function - virtual AstNodeDType* subDTypep() const { return NULL; } + virtual AstNodeDType* subDTypep() const { return nullptr; } virtual bool isFourstate() const; // Ideally an IEEE $typename virtual string prettyDTypeName() const { return prettyTypeName(); } @@ -2428,17 +2427,17 @@ private: public: AstNodeUOrStructDType(AstType t, FileLine* fl, VSigning numericUnpack) - : AstNodeDType(t, fl) { + : AstNodeDType{t, fl} { // VSigning::NOSIGN overloaded to indicate not packed m_packed = (numericUnpack != VSigning::NOSIGN); m_isFourstate = false; // V3Width computes numeric(VSigning::fromBool(numericUnpack.isSigned())); } ASTNODE_BASE_FUNCS(NodeUOrStructDType) - virtual const char* broken() const; - virtual void dump(std::ostream& str) const; + virtual const char* broken() const override; + virtual void dump(std::ostream& str) const override; // For basicp() we reuse the size to indicate a "fake" basic type of same size - virtual AstBasicDType* basicp() const { + virtual AstBasicDType* basicp() const override { return (isFourstate() ? VN_CAST( findLogicRangeDType(VNumRange(width() - 1, 0, false), width(), numeric()), BasicDType) @@ -2446,19 +2445,19 @@ public: width(), numeric()), BasicDType)); } - virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } - virtual int widthAlignBytes() - const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) - virtual int - widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) + virtual int widthAlignBytes() const override; + // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... + virtual int widthTotalBytes() const override; // op1 = members - virtual bool similarDType(AstNodeDType* samep) const { + virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; // We don't compare members, require exact equivalence } - virtual string name() const { return m_name; } - void name(const string& flag) { m_name = flag; } + virtual string name() const override { return m_name; } + virtual void name(const string& flag) override { m_name = flag; } AstMemberDType* membersp() const { return VN_CAST(op1p(), MemberDType); } // op1 = AstMember list @@ -2467,12 +2466,12 @@ public: // packed() but as don't support unpacked, presently all structs static bool packedUnsup() { return true; } void isFourstate(bool flag) { m_isFourstate = flag; } - virtual bool isFourstate() const { return m_isFourstate; } + virtual bool isFourstate() const override { return m_isFourstate; } void clearCache() { m_members.clear(); } void repairMemberCache(); AstMemberDType* findMember(const string& name) const { - MemberNameMap::const_iterator it = m_members.find(name); - return (it == m_members.end()) ? NULL : it->second; + const auto it = m_members.find(name); + return (it == m_members.end()) ? nullptr : it->second; } static int lsb() { return 0; } int msb() const { return dtypep()->width() - 1; } // Packed classes look like arrays @@ -2484,56 +2483,56 @@ class AstNodeArrayDType : public AstNodeDType { // Children: DTYPE (moved to refDTypep() in V3Width) // Children: RANGE (array bounds) private: - AstNodeDType* m_refDTypep; // Elements of this type (after widthing) + AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing) AstNode* rangenp() const { return op2p(); } // op2 = Array(s) of variable public: AstNodeArrayDType(AstType t, FileLine* fl) - : AstNodeDType(t, fl) { - m_refDTypep = NULL; - } + : AstNodeDType{t, fl} {} ASTNODE_BASE_FUNCS(NodeArrayDType) - virtual void dump(std::ostream& str) const; - virtual void dumpSmall(std::ostream& str) const; - virtual const char* broken() const { + virtual void dump(std::ostream& str) const override; + virtual void dumpSmall(std::ostream& str) const override; + virtual const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } } - virtual bool same(const AstNode* samep) const { + virtual bool same(const AstNode* samep) const override { const AstNodeArrayDType* asamep = static_cast(samep); return (msb() == asamep->msb() && subDTypep() == asamep->subDTypep() && rangenp()->sameTree(asamep->rangenp())); } // HashedDT doesn't recurse, so need to check children - virtual bool similarDType(AstNodeDType* samep) const { + virtual bool similarDType(AstNodeDType* samep) const override { const AstNodeArrayDType* asamep = static_cast(samep); return (asamep && type() == samep->type() && msb() == asamep->msb() && rangenp()->sameTree(asamep->rangenp()) && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); } - virtual V3Hash sameHash() const { + virtual V3Hash sameHash() const override { return V3Hash(V3Hash(m_refDTypep), V3Hash(msb()), V3Hash(lsb())); } - virtual AstNodeDType* getChildDTypep() const { return childDTypep(); } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } + virtual AstNodeDType* subDTypep() const override { + return m_refDTypep ? m_refDTypep : childDTypep(); + } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } + virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } AstRange* rangep() const { return VN_CAST(op2p(), Range); } // op2 = Array(s) of variable void rangep(AstRange* nodep); // METHODS - virtual AstBasicDType* basicp() const { + virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type - virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const { + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return elementsConst() * subDTypep()->widthTotalBytes(); } int msb() const; @@ -2546,21 +2545,23 @@ class AstNodeSel : public AstNodeBiop { // Single bit range extraction, perhaps with non-constant selection or array selection public: AstNodeSel(AstType t, FileLine* fl, AstNode* fromp, AstNode* bitp) - : AstNodeBiop(t, fl, fromp, bitp) {} + : AstNodeBiop{t, fl, fromp, bitp} {} ASTNODE_BASE_FUNCS(NodeSel) - AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing) + AstNode* fromp() const { + return op1p(); + } // op1 = Extracting what (nullptr=TBD during parsing) void fromp(AstNode* nodep) { setOp1p(nodep); } AstNode* bitp() const { return op2p(); } // op2 = Msb selection expression void bitp(AstNode* nodep) { setOp2p(nodep); } int bitConst() const; - virtual bool hasDType() const { return true; } + virtual bool hasDType() const override { return true; } }; class AstNodeStream : public AstNodeBiop { // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp() public: AstNodeStream(AstType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp) - : AstNodeBiop(t, fl, lhsp, rhsp) { + : AstNodeBiop{t, fl, lhsp, rhsp} { if (lhsp->dtypep()) { dtypeSetLogicSized(lhsp->dtypep()->width(), VSigning::UNSIGNED); } } ASTNODE_BASE_FUNCS(NodeStream) @@ -2577,36 +2578,35 @@ class AstNodeCCall : public AstNodeStmt { string m_argTypes; public: - AstNodeCCall(AstType t, FileLine* fl, AstCFunc* funcp, AstNode* argsp = NULL) - : AstNodeStmt(t, fl, true) - , m_funcp(funcp) { + AstNodeCCall(AstType t, FileLine* fl, AstCFunc* funcp, AstNode* argsp = nullptr) + : AstNodeStmt{t, fl, true} + , m_funcp{funcp} { addNOp2p(argsp); } // Replacement form for V3Combine // Note this removes old attachments from the oldp AstNodeCCall(AstType t, AstNodeCCall* oldp, AstCFunc* funcp) - : AstNodeStmt(t, oldp->fileline(), true) - , m_funcp(funcp) { - m_funcp = funcp; + : AstNodeStmt{t, oldp->fileline(), true} + , m_funcp{funcp} { m_hiername = oldp->hiername(); m_argTypes = oldp->argTypes(); if (oldp->argsp()) addNOp2p(oldp->argsp()->unlinkFrBackWithNext()); } ASTNODE_BASE_FUNCS(NodeCCall) - virtual void dump(std::ostream& str = std::cout) const; - virtual void cloneRelink(); - virtual const char* broken() const; - virtual int instrCount() const { return instrCountCall(); } - virtual V3Hash sameHash() const { return V3Hash(funcp()); } - virtual bool same(const AstNode* samep) const { + virtual void dump(std::ostream& str = std::cout) const override; + virtual void cloneRelink() override; + virtual const char* broken() const override; + virtual int instrCount() const override { return instrCountCall(); } + virtual V3Hash sameHash() const override { return V3Hash(funcp()); } + virtual bool same(const AstNode* samep) const override { const AstNodeCCall* asamep = static_cast(samep); return (funcp() == asamep->funcp() && argTypes() == asamep->argTypes()); } AstNode* exprsp() const { return op2p(); } // op2 = expressions to print - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const; - virtual bool isOutputter() const { return !isPure(); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override; + virtual bool isOutputter() const override { return !isPure(); } AstCFunc* funcp() const { return m_funcp; } string hiername() const { return m_hiername; } void hiername(const string& hn) { m_hiername = hn; } @@ -2622,11 +2622,12 @@ class AstNodeFTask : public AstNode { private: string m_name; // Name of task string m_cname; // Name of task if DPI import - uint64_t m_dpiOpenParent; // DPI import open array, if !=0, how many callees + uint64_t m_dpiOpenParent = 0; // DPI import open array, if !=0, how many callees bool m_taskPublic : 1; // Public task bool m_attrIsolateAssign : 1; // User isolate_assignments attribute bool m_classMethod : 1; // Class method - bool m_extern : 1; // Extern prototype + bool m_externProto : 1; // Extern prototype + bool m_externDef : 1; // Extern definition bool m_prototype : 1; // Just a prototype bool m_dpiExport : 1; // DPI exported bool m_dpiImport : 1; // DPI imported @@ -2640,39 +2641,44 @@ private: VLifetime m_lifetime; // Lifetime public: AstNodeFTask(AstType t, FileLine* fl, const string& name, AstNode* stmtsp) - : AstNode(t, fl) - , m_name(name) - , m_dpiOpenParent(0) - , m_taskPublic(false) - , m_attrIsolateAssign(false) - , m_classMethod(false) - , m_extern(false) - , m_prototype(false) - , m_dpiExport(false) - , m_dpiImport(false) - , m_dpiContext(false) - , m_dpiOpenChild(false) - , m_dpiTask(false) - , m_isConstructor(false) - , m_pure(false) - , m_pureVirtual(false) - , m_virtual(false) { + : AstNode{t, fl} + , m_name{name} + , m_taskPublic{false} + , m_attrIsolateAssign{false} + , m_classMethod{false} + , m_externProto{false} + , m_externDef{false} + , m_prototype{false} + , m_dpiExport{false} + , m_dpiImport{false} + , m_dpiContext{false} + , m_dpiOpenChild{false} + , m_dpiTask{false} + , m_isConstructor{false} + , m_pure{false} + , m_pureVirtual{false} + , m_virtual{false} { addNOp3p(stmtsp); cname(name); // Might be overridden by dpi import/export } ASTNODE_BASE_FUNCS(NodeFTask) - virtual void dump(std::ostream& str = std::cout) const; - virtual string name() const { return m_name; } // * = Var name - virtual bool maybePointedTo() const { return true; } - virtual bool isGateOptimizable() const { return !((m_dpiExport || m_dpiImport) && !m_pure); } + virtual void dump(std::ostream& str = std::cout) const override; + virtual string name() const override { return m_name; } // * = Var name + virtual bool maybePointedTo() const override { return true; } + virtual bool isGateOptimizable() const override { + return !((m_dpiExport || m_dpiImport) && !m_pure); + } // {AstFunc only} op1 = Range output variable - virtual void name(const string& name) { m_name = name; } + virtual void name(const string& name) override { m_name = name; } string cname() const { return m_cname; } void cname(const string& cname) { m_cname = cname; } - // op1 = Output variable (functions only, NULL for tasks) + // op1 = Output variable (functions only, nullptr for tasks) AstNode* fvarp() const { return op1p(); } void addFvarp(AstNode* nodep) { addNOp1p(nodep); } - bool isFunction() const { return fvarp() != NULL; } + bool isFunction() const { return fvarp() != nullptr; } + // op2 = Class/package scope + AstNode* packagep() const { return op2p(); } + void packagep(AstNode* nodep) { setNOp2p(nodep); } // op3 = Statements/Ports/Vars AstNode* stmtsp() const { return op3p(); } // op3 = List of statements void addStmtsp(AstNode* nodep) { addNOp3p(nodep); } @@ -2689,8 +2695,10 @@ public: bool attrIsolateAssign() const { return m_attrIsolateAssign; } void classMethod(bool flag) { m_classMethod = flag; } bool classMethod() const { return m_classMethod; } - void isExtern(bool flag) { m_extern = flag; } - bool isExtern() const { return m_extern; } + void isExternProto(bool flag) { m_externProto = flag; } + bool isExternProto() const { return m_externProto; } + void isExternDef(bool flag) { m_externDef = flag; } + bool isExternDef() const { return m_externDef; } void prototype(bool flag) { m_prototype = flag; } bool prototype() const { return m_prototype; } void dpiExport(bool flag) { m_dpiExport = flag; } @@ -2719,47 +2727,40 @@ class AstNodeFTaskRef : public AstNodeStmt { // A reference to a task (or function) // Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal. private: - AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced + AstNodeFTask* m_taskp = nullptr; // [AfterLink] Pointer to task referenced + AstNodeModule* m_packagep = nullptr; // Package hierarchy string m_name; // Name of variable string m_dotted; // Dotted part of scope the name()ed task/func is under or "" string m_inlinedDots; // Dotted hierarchy flattened out - AstNodeModule* m_packagep; // Package hierarchy - bool m_pli; // Pli system call ($name) + bool m_pli = false; // Pli system call ($name) public: AstNodeFTaskRef(AstType t, FileLine* fl, bool statement, AstNode* namep, AstNode* pinsp) - : AstNodeStmt(t, fl, statement) - , m_taskp(NULL) - , m_packagep(NULL) - , m_pli(false) { + : AstNodeStmt{t, fl, statement} { setOp1p(namep); addNOp3p(pinsp); } AstNodeFTaskRef(AstType t, FileLine* fl, bool statement, const string& name, AstNode* pinsp) - : AstNodeStmt(t, fl, statement) - , m_taskp(NULL) - , m_name(name) - , m_packagep(NULL) - , m_pli(false) { + : AstNodeStmt{t, fl, statement} + , m_name{name} { addNOp3p(pinsp); } ASTNODE_BASE_FUNCS(NodeFTaskRef) - virtual const char* broken() const { - BROKEN_RTN(m_taskp && !m_taskp->brokeExists()); - return NULL; - } - virtual void cloneRelink() { + virtual const char* broken() const override; + virtual void cloneRelink() override { if (m_taskp && m_taskp->clonep()) { m_taskp = m_taskp->clonep(); } } - virtual void dump(std::ostream& str = std::cout) const; - virtual string name() const { return m_name; } // * = Var name - virtual bool isGateOptimizable() const { return m_taskp && m_taskp->isGateOptimizable(); } + virtual void dump(std::ostream& str = std::cout) const override; + virtual string name() const override { return m_name; } // * = Var name + virtual bool isGateOptimizable() const override { + return m_taskp && m_taskp->isGateOptimizable(); + } string dotted() const { return m_dotted; } // * = Scope name or "" string prettyDotted() const { return prettyName(dotted()); } string inlinedDots() const { return m_inlinedDots; } void inlinedDots(const string& flag) { m_inlinedDots = flag; } AstNodeFTask* taskp() const { return m_taskp; } // [After Link] Pointer to variable void taskp(AstNodeFTask* taskp) { m_taskp = taskp; } - virtual void name(const string& name) { m_name = name; } + virtual void name(const string& name) override { m_name = name; } void dotted(const string& name) { m_dotted = name; } AstNodeModule* packagep() const { return m_packagep; } void packagep(AstNodeModule* nodep) { m_packagep = nodep; } @@ -2788,34 +2789,33 @@ private: bool m_modTrace : 1; // Tracing this module bool m_inLibrary : 1; // From a library, no error if not used, never top level bool m_dead : 1; // LinkDot believes is dead; will remove in Dead visitors + bool m_hierBlock : 1; // Hiearchical Block marked by HIER_BLOCK pragma bool m_internal : 1; // Internally created bool m_recursive : 1; // Recursive module - bool m_recursiveClone : 1; // If recursive, what module it clones, otherwise NULL - int m_level; // 1=top module, 2=cell off top module, ... - int m_varNum; // Incrementing variable number - int m_typeNum; // Incrementing implicit type number + bool m_recursiveClone : 1; // If recursive, what module it clones, otherwise nullptr + int m_level = 0; // 1=top module, 2=cell off top module, ... + int m_varNum = 0; // Incrementing variable number + int m_typeNum = 0; // Incrementing implicit type number VLifetime m_lifetime; // Lifetime VTimescale m_timeunit; // Global time unit VOptionBool m_unconnectedDrive; // State of `unconnected_drive public: AstNodeModule(AstType t, FileLine* fl, const string& name) - : AstNode(t, fl) - , m_name(name) - , m_origName(name) - , m_modPublic(false) - , m_modTrace(false) - , m_inLibrary(false) - , m_dead(false) - , m_internal(false) - , m_recursive(false) - , m_recursiveClone(false) - , m_level(0) - , m_varNum(0) - , m_typeNum(0) {} + : AstNode{t, fl} + , m_name{name} + , m_origName{name} + , m_modPublic{false} + , m_modTrace{false} + , m_inLibrary{false} + , m_dead{false} + , m_hierBlock{false} + , m_internal{false} + , m_recursive{false} + , m_recursiveClone{false} {} ASTNODE_BASE_FUNCS(NodeModule) - virtual void dump(std::ostream& str) const; - virtual bool maybePointedTo() const { return true; } - virtual string name() const { return m_name; } + virtual void dump(std::ostream& str) const override; + virtual bool maybePointedTo() const override { return true; } + virtual string name() const override { return m_name; } AstNode* stmtsp() const { return op2p(); } // op2 = List of statements AstActive* activesp() const { return VN_CAST(op3p(), Active); } // op3 = List of i/sblocks // METHODS @@ -2823,8 +2823,8 @@ public: void addStmtp(AstNode* nodep) { addNOp2p(nodep); } void addActivep(AstNode* nodep) { addOp3p(nodep); } // ACCESSORS - virtual void name(const string& name) { m_name = name; } - virtual string origName() const { return m_origName; } + virtual void name(const string& name) override { m_name = name; } + virtual string origName() const override { return m_origName; } string hierName() const { return m_hierName; } void hierName(const string& hierName) { m_hierName = hierName; } bool inLibrary() const { return m_inLibrary; } @@ -2840,6 +2840,8 @@ public: bool modTrace() const { return m_modTrace; } void dead(bool flag) { m_dead = flag; } bool dead() const { return m_dead; } + void hierBlock(bool flag) { m_hierBlock = flag; } + bool hierBlock() const { return m_hierBlock; } void internal(bool flag) { m_internal = flag; } bool internal() const { return m_internal; } void recursive(bool flag) { m_recursive = flag; } @@ -2858,7 +2860,7 @@ class AstNodeRange : public AstNode { // A range, sized or unsized public: AstNodeRange(AstType t, FileLine* fl) - : AstNode(t, fl) {} + : AstNode{t, fl} {} ASTNODE_BASE_FUNCS(NodeRange) }; @@ -2943,6 +2945,12 @@ inline VNumRange AstNodeArrayDType::declRange() const { return VNumRange(msb(), lsb(), rangep()->littleEndian()); } +inline const char* AstNodeFTaskRef::broken() const { + BROKEN_RTN(m_taskp && !m_taskp->brokeExists()); + BROKEN_RTN(m_packagep && !m_packagep->brokeExists()); + return nullptr; +} + inline void AstIfaceRefDType::cloneRelink() { if (m_cellp && m_cellp->clonep()) m_cellp = m_cellp->clonep(); if (m_ifacep && m_ifacep->clonep()) m_ifacep = m_ifacep->clonep(); diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index d9ec68bb3..8f140aa9e 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -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 @@ -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 exists; + std::unordered_set 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 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::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(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"); diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index f24e6b37c..f4dd547ff 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -25,10 +25,10 @@ // Standard defines for all AstNode final classes #define ASTNODE_NODE_FUNCS_NO_DTOR(name) \ - virtual void accept(AstNVisitor& v) { v.visit(this); } \ - virtual AstNode* clone() { return new Ast##name(*this); } \ + virtual void accept(AstNVisitor& v) override { v.visit(this); } \ + virtual AstNode* clone() override { return new Ast##name(*this); } \ static Ast##name* cloneTreeNull(Ast##name* nodep, bool cloneNextLink) { \ - return nodep ? nodep->cloneTree(cloneNextLink) : NULL; \ + return nodep ? nodep->cloneTree(cloneNextLink) : nullptr; \ } \ Ast##name* cloneTree(bool cloneNext) { \ return static_cast(AstNode::cloneTree(cloneNext)); \ @@ -36,7 +36,7 @@ Ast##name* clonep() const { return static_cast(AstNode::clonep()); } #define ASTNODE_NODE_FUNCS(name) \ - virtual ~Ast##name() {} \ + virtual ~Ast##name() override {} \ ASTNODE_NODE_FUNCS_NO_DTOR(name) //###################################################################### @@ -153,25 +153,25 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(Const) - virtual string name() const { return num().ascii(); } // * = Value + virtual string name() const override { return num().ascii(); } // * = Value const V3Number& num() const { return m_num; } // * = Value V3Number& num() { return m_num; } // * = Value uint32_t toUInt() const { return num().toUInt(); } vlsint32_t toSInt() const { return num().toSInt(); } vluint64_t toUQuad() const { return num().toUQuad(); } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(num().toHash()); } - virtual bool same(const AstNode* samep) const { + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual V3Hash sameHash() const override { return V3Hash(num().toHash()); } + virtual bool same(const AstNode* samep) const override { const AstConst* sp = static_cast(samep); return num().isCaseEq(sp->num()); } - virtual int instrCount() const { return widthInstrs(); } + virtual int instrCount() const override { return widthInstrs(); } bool isEqAllOnes() const { return num().isEqAllOnes(width()); } bool isEqAllOnesV() const { return num().isEqAllOnes(widthMinV()); } // Parse string and create appropriate type of AstConst. - // May return NULL on parse failure. + // May return nullptr on parse failure. static AstConst* parseParamLiteral(FileLine* fl, const string& literal); }; @@ -228,10 +228,10 @@ public: int leftToRightInc() const { return littleEndian() ? 1 : -1; } bool littleEndian() const { return m_littleEndian; } void littleEndian(bool flag) { m_littleEndian = flag; } - virtual void dump(std::ostream& str) const; + virtual void dump(std::ostream& str) const override; virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } }; class AstBracketRange : public AstNodeRange { @@ -245,11 +245,11 @@ public: ASTNODE_NODE_FUNCS(BracketRange) virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } // Will be removed in V3Width, which relies on this // being a child not a dtype pointed node - virtual bool maybePointedTo() const { return false; } + virtual bool maybePointedTo() const override { return false; } AstNode* elementsp() const { return op1p(); } }; @@ -261,8 +261,8 @@ public: ASTNODE_NODE_FUNCS(UnsizedRange) virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitVerilog() { return "[]"; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } }; class AstGatePin : public AstNodeMath { @@ -274,9 +274,9 @@ public: setOp2p(rangep); } ASTNODE_NODE_FUNCS(GatePin) - virtual string emitVerilog() { return "%l"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return true; } + virtual string emitVerilog() override { return "%l"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } AstNode* exprp() const { return op1p(); } // op1 = Pin expression AstRange* rangep() const { return VN_CAST(op2p(), Range); } // op2 = Range of pin }; @@ -286,14 +286,14 @@ public: class AstClassPackage : public AstNodeModule { // The static information portion of a class (treated similarly to a package) - AstClass* m_classp; // Class package this is under (weak pointer, hard link is other way) + AstClass* m_classp + = nullptr; // Class package this is under (weak pointer, hard link is other way) public: AstClassPackage(FileLine* fl, const string& name) - : ASTGEN_SUPER(fl, name) - , m_classp(NULL) {} + : ASTGEN_SUPER(fl, name) {} ASTNODE_NODE_FUNCS(ClassPackage) - virtual string verilogKwd() const { return "/*class*/package"; } - virtual const char* broken() const; + virtual string verilogKwd() const override { return "/*class*/package"; } + virtual const char* broken() const override; AstClass* classp() const { return m_classp; } void classp(AstClass* classp) { m_classp = classp; } }; @@ -303,23 +303,23 @@ class AstClass : public AstNodeModule { typedef std::map MemberNameMap; // MEMBERS MemberNameMap m_members; // Members or method children - AstClassPackage* m_packagep; // Class package this is under - bool m_virtual; // Virtual class + AstClassPackage* m_packagep = nullptr; // Class package this is under + bool m_virtual = false; // Virtual class + bool m_extended = false; // Is extension or extended by other classes void insertCache(AstNode* nodep); public: AstClass(FileLine* fl, const string& name) - : ASTGEN_SUPER(fl, name) - , m_packagep(NULL) {} + : ASTGEN_SUPER(fl, name) {} ASTNODE_NODE_FUNCS(Class) - virtual string verilogKwd() const { return "class"; } - virtual bool isHeavy() const { return true; } - virtual bool maybePointedTo() const { return true; } - virtual void dump(std::ostream& str) const; - virtual const char* broken() const { + virtual string verilogKwd() const override { return "class"; } + virtual bool isHeavy() const override { return true; } + virtual bool maybePointedTo() const override { return true; } + virtual void dump(std::ostream& str) const override; + virtual const char* broken() const override { BROKEN_BASE_RTN(AstNodeModule::broken()); BROKEN_RTN(m_packagep && !m_packagep->brokeExists()); - return NULL; + return nullptr; } // op1/op2/op3 in AstNodeModule AstClassPackage* packagep() const { return m_packagep; } @@ -330,13 +330,15 @@ public: addStmtp(nodep); } AstClassExtends* extendsp() const { return VN_CAST(op4p(), ClassExtends); } - void extendsp(AstNode* nodep) { addNOp2p(nodep); } + void extendsp(AstNode* nodep) { addNOp4p(nodep); } void clearCache() { m_members.clear(); } void repairCache(); AstNode* findMember(const string& name) const { - MemberNameMap::const_iterator it = m_members.find(name); - return (it == m_members.end()) ? NULL : it->second; + const auto it = m_members.find(name); + return (it == m_members.end()) ? nullptr : it->second; } + bool isExtended() const { return m_extended; } + void isExtended(bool flag) { m_extended = flag; } bool isVirtual() const { return m_virtual; } void isVirtual(bool flag) { m_virtual = flag; } }; @@ -347,13 +349,15 @@ class AstClassExtends : public AstNode { public: AstClassExtends(FileLine* fl, AstNode* classOrPkgsp) : ASTGEN_SUPER(fl) { - setNOp1p(classOrPkgsp); // Only for parser + setNOp2p(classOrPkgsp); // Only for parser } ASTNODE_NODE_FUNCS(ClassExtends) - virtual string verilogKwd() const { return "extends"; } - virtual bool hasDType() const { return true; } - AstNodeDType* classOrPkgsp() const { return VN_CAST(op1p(), NodeDType); } - void classOrPkgsp(AstNodeDType* nodep) { setOp1p(nodep); } + virtual bool hasDType() const override { return true; } + virtual string verilogKwd() const override { return "extends"; } + AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } + void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } + AstNode* classOrPkgsp() const { return op2p(); } + void classOrPkgsp(AstNode* nodep) { setOp2p(nodep); } AstClass* classp() const; // Class being extended (after link) }; @@ -370,32 +374,36 @@ public: AstParamTypeDType(FileLine* fl, AstVarType type, const string& name, VFlagChildDType, AstNodeDType* dtp) : ASTGEN_SUPER(fl) - , m_varType(type) - , m_name(name) { + , m_varType{type} + , m_name{name} { childDTypep(dtp); // Only for parser - dtypep(NULL); // V3Width will resolve + dtypep(nullptr); // V3Width will resolve } ASTNODE_NODE_FUNCS(ParamTypeDType) - AstNodeDType* getChildDTypep() const { return childDTypep(); } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Type assigning to AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } - virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } - virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); } - virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); } - virtual AstNodeDType* skipRefToEnump() const { return subDTypep()->skipRefToEnump(); } - virtual bool similarDType(AstNodeDType* samep) const { + virtual AstNodeDType* subDTypep() const override { + return dtypep() ? dtypep() : childDTypep(); + } + virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } + virtual AstNodeDType* skipRefToConstp() const override { + return subDTypep()->skipRefToConstp(); + } + virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } + virtual bool similarDType(AstNodeDType* samep) const override { const AstParamTypeDType* sp = static_cast(samep); return (sp && this->subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp())); } - virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); } + virtual int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); } // METHODS - virtual string name() const { return m_name; } - virtual bool maybePointedTo() const { return true; } - virtual bool hasDType() const { return true; } - void name(const string& flag) { m_name = flag; } + virtual string name() const override { return m_name; } + virtual bool maybePointedTo() const override { return true; } + virtual bool hasDType() const override { return true; } + virtual void name(const string& flag) override { m_name = flag; } AstVarType varType() const { return m_varType; } // * = Type of variable bool isParam() const { return true; } bool isGParam() const { return (varType() == AstVarType::GPARAM); } @@ -410,15 +418,15 @@ public: AstTypedef(FileLine* fl, const string& name, AstNode* attrsp, VFlagChildDType, AstNodeDType* dtp) : ASTGEN_SUPER(fl) - , m_name(name) { + , m_name{name} { childDTypep(dtp); // Only for parser addAttrsp(attrsp); - dtypep(NULL); // V3Width will resolve + dtypep(nullptr); // V3Width will resolve m_attrPublic = false; } ASTNODE_NODE_FUNCS(Typedef) - virtual void dump(std::ostream& str) const; - AstNodeDType* getChildDTypep() const { return childDTypep(); } + virtual void dump(std::ostream& str) const override; + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Type assigning to AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } @@ -426,14 +434,14 @@ public: void addAttrsp(AstNode* nodep) { addNOp4p(nodep); } AstNode* attrsp() const { return op4p(); } // op4 = Attributes during early parse // METHODS - virtual string name() const { return m_name; } - virtual bool maybePointedTo() const { return true; } - virtual bool hasDType() const { return true; } - void name(const string& flag) { m_name = flag; } + virtual string name() const override { return m_name; } + virtual bool maybePointedTo() const override { return true; } + virtual bool hasDType() const override { return true; } + virtual void name(const string& flag) override { m_name = flag; } bool attrPublic() const { return m_attrPublic; } void attrPublic(bool flag) { m_attrPublic = flag; } - virtual void tag(const string& text) { m_tag = text; } - virtual string tag() const { return m_tag; } + virtual void tag(const string& text) override { m_tag = text; } + virtual string tag() const override { return m_tag; } }; class AstTypedefFwd : public AstNode { @@ -444,11 +452,11 @@ private: public: AstTypedefFwd(FileLine* fl, const string& name) : ASTGEN_SUPER(fl) - , m_name(name) {} + , m_name{name} {} ASTNODE_NODE_FUNCS(TypedefFwd) // METHODS - virtual string name() const { return m_name; } - virtual bool maybePointedTo() const { return true; } + virtual string name() const override { return m_name; } + virtual bool maybePointedTo() const override { return true; } }; class AstDefImplicitDType : public AstNodeDType { @@ -465,38 +473,40 @@ public: AstDefImplicitDType(FileLine* fl, const string& name, void* containerp, VFlagChildDType, AstNodeDType* dtp) : ASTGEN_SUPER(fl) - , m_name(name) - , m_containerp(containerp) { + , m_name{name} + , m_containerp{containerp} { childDTypep(dtp); // Only for parser - dtypep(NULL); // V3Width will resolve + dtypep(nullptr); // V3Width will resolve m_uniqueNum = uniqueNumInc(); } ASTNODE_NODE_FUNCS(DefImplicitDType) - virtual bool same(const AstNode* samep) const { + virtual bool same(const AstNode* samep) const override { const AstDefImplicitDType* sp = static_cast(samep); return m_uniqueNum == sp->m_uniqueNum; } - virtual bool similarDType(AstNodeDType* samep) const { + virtual bool similarDType(AstNodeDType* samep) const override { return type() == samep->type() && same(samep); } - virtual V3Hash sameHash() const { return V3Hash(m_uniqueNum); } - AstNodeDType* getChildDTypep() const { return childDTypep(); } + virtual V3Hash sameHash() const override { return V3Hash(m_uniqueNum); } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } + virtual AstNodeDType* subDTypep() const override { + return dtypep() ? dtypep() : childDTypep(); + } void* containerp() const { return m_containerp; } // METHODS // op1 = Range of variable AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); } - virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } - virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const { return dtypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const { return dtypep()->widthTotalBytes(); } - virtual string name() const { return m_name; } - void name(const string& flag) { m_name = flag; } + virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); } + virtual string name() const override { return m_name; } + virtual void name(const string& flag) override { m_name = flag; } }; class AstAssocArrayDType : public AstNodeDType { @@ -511,45 +521,47 @@ public: : ASTGEN_SUPER(fl) { childDTypep(dtp); // Only for parser keyChildDTypep(keyDtp); // Only for parser - refDTypep(NULL); - keyDTypep(NULL); - dtypep(NULL); // V3Width will resolve + refDTypep(nullptr); + keyDTypep(nullptr); + dtypep(nullptr); // V3Width will resolve } ASTNODE_NODE_FUNCS(AssocArrayDType) - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); BROKEN_RTN(!((m_keyDTypep && !childDTypep() && m_keyDTypep->brokeExists()) || (!m_keyDTypep && childDTypep()))); - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } if (m_keyDTypep && m_keyDTypep->clonep()) { m_keyDTypep = m_keyDTypep->clonep(); } } - virtual bool same(const AstNode* samep) const { + virtual bool same(const AstNode* samep) const override { const AstAssocArrayDType* asamep = static_cast(samep); return (subDTypep() == asamep->subDTypep() && keyDTypep() == asamep->keyDTypep()); } - virtual bool similarDType(AstNodeDType* samep) const { + virtual bool similarDType(AstNodeDType* samep) const override { const AstAssocArrayDType* asamep = static_cast(samep); return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); } - virtual string prettyDTypeName() const; - virtual void dumpSmall(std::ostream& str) const; - virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); } - virtual AstNodeDType* getChildDTypep() const { return childDTypep(); } - virtual AstNodeDType* getChild2DTypep() const { return keyChildDTypep(); } - virtual bool isHeavy() const { return true; } + virtual string prettyDTypeName() const override; + virtual void dumpSmall(std::ostream& str) const override; + virtual V3Hash sameHash() const override { return V3Hash(m_refDTypep); } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } + virtual AstNodeDType* getChild2DTypep() const override { return keyChildDTypep(); } + virtual bool isHeavy() const override { return true; } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } + virtual AstNodeDType* subDTypep() const override { + return m_refDTypep ? m_refDTypep : childDTypep(); + } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } - virtual AstNodeDType* virtRefDType2p() const { return m_keyDTypep; } - virtual void virtRefDType2p(AstNodeDType* nodep) { keyDTypep(nodep); } + virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + virtual AstNodeDType* virtRefDType2p() const override { return m_keyDTypep; } + virtual void virtRefDType2p(AstNodeDType* nodep) override { keyDTypep(nodep); } // AstNodeDType* keyDTypep() const { return m_keyDTypep ? m_keyDTypep : keyChildDTypep(); } void keyDTypep(AstNodeDType* nodep) { m_keyDTypep = nodep; } @@ -557,12 +569,12 @@ public: AstNodeDType* keyChildDTypep() const { return VN_CAST(op2p(), NodeDType); } void keyChildDTypep(AstNodeDType* nodep) { setOp2p(nodep); } // METHODS - virtual AstBasicDType* basicp() const { return NULL; } - virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } + virtual AstBasicDType* basicp() const override { return nullptr; } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } }; class AstBracketArrayDType : public AstNodeDType { @@ -577,22 +589,22 @@ public: setOp2p(elementsp); // Only for parser } ASTNODE_NODE_FUNCS(BracketArrayDType) - virtual bool similarDType(AstNodeDType* samep) const { V3ERROR_NA_RETURN(false); } + virtual bool similarDType(AstNodeDType* samep) const override { V3ERROR_NA_RETURN(false); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } - virtual AstNodeDType* subDTypep() const { return childDTypep(); } + virtual AstNodeDType* subDTypep() const override { return childDTypep(); } // op2 = Range of variable AstNode* elementsp() const { return op2p(); } // METHODS // Will be removed in V3Width, which relies on this // being a child not a dtype pointed node - virtual bool maybePointedTo() const { return false; } - virtual AstBasicDType* basicp() const { return NULL; } - virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const { V3ERROR_NA_RETURN(0); } - virtual int widthTotalBytes() const { V3ERROR_NA_RETURN(0); } + virtual bool maybePointedTo() const override { return false; } + virtual AstBasicDType* basicp() const override { return nullptr; } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { V3ERROR_NA_RETURN(0); } + virtual int widthTotalBytes() const override { V3ERROR_NA_RETURN(0); } }; class AstDynArrayDType : public AstNodeDType { @@ -604,50 +616,52 @@ public: AstDynArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp) : ASTGEN_SUPER(fl) { childDTypep(dtp); // Only for parser - refDTypep(NULL); - dtypep(NULL); // V3Width will resolve + refDTypep(nullptr); + dtypep(nullptr); // V3Width will resolve } AstDynArrayDType(FileLine* fl, AstNodeDType* dtp) : ASTGEN_SUPER(fl) { refDTypep(dtp); - dtypep(NULL); // V3Width will resolve + dtypep(nullptr); // V3Width will resolve } ASTNODE_NODE_FUNCS(DynArrayDType) - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } } - virtual bool same(const AstNode* samep) const { + virtual bool same(const AstNode* samep) const override { const AstAssocArrayDType* asamep = static_cast(samep); return subDTypep() == asamep->subDTypep(); } - virtual bool similarDType(AstNodeDType* samep) const { + virtual bool similarDType(AstNodeDType* samep) const override { const AstAssocArrayDType* asamep = static_cast(samep); return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); } - virtual string prettyDTypeName() const; - virtual void dumpSmall(std::ostream& str) const; - virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); } - virtual bool isHeavy() const { return true; } - AstNodeDType* getChildDTypep() const { return childDTypep(); } + virtual string prettyDTypeName() const override; + virtual void dumpSmall(std::ostream& str) const override; + virtual V3Hash sameHash() const override { return V3Hash(m_refDTypep); } + virtual bool isHeavy() const override { return true; } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } + virtual AstNodeDType* subDTypep() const override { + return m_refDTypep ? m_refDTypep : childDTypep(); + } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } + virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } // METHODS - virtual AstBasicDType* basicp() const { return NULL; } - virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } + virtual AstBasicDType* basicp() const override { return nullptr; } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } }; class AstPackArrayDType : public AstNodeArrayDType { @@ -658,9 +672,9 @@ public: AstPackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep) : ASTGEN_SUPER(fl) { childDTypep(dtp); // Only for parser - refDTypep(NULL); + refDTypep(nullptr); setOp2p(rangep); - dtypep(NULL); // V3Width will resolve + dtypep(nullptr); // V3Width will resolve int width = subDTypep()->width() * rangep->elementsConst(); widthForce(width, width); } @@ -673,7 +687,7 @@ public: widthForce(width, width); } ASTNODE_NODE_FUNCS(PackArrayDType) - virtual string prettyDTypeName() const; + virtual string prettyDTypeName() const override; }; class AstUnpackArrayDType : public AstNodeArrayDType { @@ -684,9 +698,9 @@ public: AstUnpackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstRange* rangep) : ASTGEN_SUPER(fl) { childDTypep(dtp); // Only for parser - refDTypep(NULL); + refDTypep(nullptr); setOp2p(rangep); - dtypep(NULL); // V3Width will resolve + dtypep(nullptr); // V3Width will resolve // For backward compatibility AstNodeArrayDType and others inherit // width and signing from the subDType/base type widthFromSub(subDTypep()); @@ -701,7 +715,7 @@ public: widthFromSub(subDTypep()); } ASTNODE_NODE_FUNCS(UnpackArrayDType) - virtual string prettyDTypeName() const; + virtual string prettyDTypeName() const override; }; class AstUnsizedArrayDType : public AstNodeDType { @@ -713,43 +727,45 @@ public: AstUnsizedArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp) : ASTGEN_SUPER(fl) { childDTypep(dtp); // Only for parser - refDTypep(NULL); - dtypep(NULL); // V3Width will resolve + refDTypep(nullptr); + dtypep(nullptr); // V3Width will resolve } ASTNODE_NODE_FUNCS(UnsizedArrayDType) - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } } - virtual bool same(const AstNode* samep) const { + virtual bool same(const AstNode* samep) const override { const AstNodeArrayDType* asamep = static_cast(samep); return (subDTypep() == asamep->subDTypep()); } - virtual bool similarDType(AstNodeDType* samep) const { + virtual bool similarDType(AstNodeDType* samep) const override { const AstNodeArrayDType* asamep = static_cast(samep); return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); } - virtual void dumpSmall(std::ostream& str) const; - virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); } - AstNodeDType* getChildDTypep() const { return childDTypep(); } + virtual void dumpSmall(std::ostream& str) const override; + virtual V3Hash sameHash() const override { return V3Hash(m_refDTypep); } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } + virtual AstNodeDType* subDTypep() const override { + return m_refDTypep ? m_refDTypep : childDTypep(); + } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } + virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } // METHODS - virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } - virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } + virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } }; class AstBasicDType : public AstNodeDType { @@ -767,24 +783,24 @@ private: public: AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, const VSigning& signst = VSigning::NOSIGN) : ASTGEN_SUPER(fl) { - init(kwd, signst, 0, -1, NULL); + init(kwd, signst, 0, -1, nullptr); } AstBasicDType(FileLine* fl, VFlagLogicPacked, int wantwidth) : ASTGEN_SUPER(fl) { - init(AstBasicDTypeKwd::LOGIC, VSigning::NOSIGN, wantwidth, -1, NULL); + init(AstBasicDTypeKwd::LOGIC, VSigning::NOSIGN, wantwidth, -1, nullptr); } AstBasicDType(FileLine* fl, VFlagBitPacked, int wantwidth) : ASTGEN_SUPER(fl) { - init(AstBasicDTypeKwd::BIT, VSigning::NOSIGN, wantwidth, -1, NULL); + init(AstBasicDTypeKwd::BIT, VSigning::NOSIGN, wantwidth, -1, nullptr); } AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, VSigning numer, int wantwidth, int widthmin) : ASTGEN_SUPER(fl) { - init(kwd, numer, wantwidth, widthmin, NULL); + init(kwd, numer, wantwidth, widthmin, nullptr); } AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, VSigning numer, VNumRange range, int widthmin) : ASTGEN_SUPER(fl) { - init(kwd, numer, range.elements(), widthmin, NULL); + init(kwd, numer, range.elements(), widthmin, nullptr); m.m_nrange = range; // as init() presumes lsb==0, but range.lsb() might not be } // See also addRange in verilog.y @@ -828,24 +844,25 @@ private: public: ASTNODE_NODE_FUNCS(BasicDType) - virtual void dump(std::ostream& str) const; - virtual V3Hash sameHash() const { + virtual void dump(std::ostream& str) const override; + virtual V3Hash sameHash() const override { return V3Hash(V3Hash(m.m_keyword), V3Hash(m.m_nrange.hi())); } - virtual bool same(const AstNode* samep) const { // width/widthMin/numeric compared elsewhere + // width/widthMin/numeric compared elsewhere + virtual bool same(const AstNode* samep) const override { const AstBasicDType* sp = static_cast(samep); return m == sp->m; } - virtual bool similarDType(AstNodeDType* samep) const { + virtual bool similarDType(AstNodeDType* samep) const override { return type() == samep->type() && same(samep); } - virtual string name() const { return m.m_keyword.ascii(); } - virtual string prettyDTypeName() const; - virtual const char* broken() const { + virtual string name() const override { return m.m_keyword.ascii(); } + virtual string prettyDTypeName() const override; + virtual const char* broken() const override { BROKEN_RTN(dtypep() != this); - return NULL; + return nullptr; } - virtual bool isHeavy() const { return keyword() == AstBasicDTypeKwd::STRING; } + virtual bool isHeavy() const override { return keyword() == AstBasicDTypeKwd::STRING; } AstRange* rangep() const { return VN_CAST(op1p(), Range); } // op1 = Range of variable void rangep(AstRange* nodep) { setNOp1p(nodep); } void setSignedState(const VSigning& signst) { @@ -857,15 +874,15 @@ public: } } // METHODS - virtual AstBasicDType* basicp() const { return (AstBasicDType*)this; } - virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } + virtual AstBasicDType* basicp() const override { return (AstBasicDType*)this; } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) - virtual int widthAlignBytes() const; + virtual int widthAlignBytes() const override; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... - virtual int widthTotalBytes() const; - virtual bool isFourstate() const { return keyword().isFourstate(); } + virtual int widthTotalBytes() const override; + virtual bool isFourstate() const override { return keyword().isFourstate(); } AstBasicDTypeKwd keyword() const { // Avoid using - use isSomething accessors instead return m.m_keyword; } @@ -903,7 +920,7 @@ public: if (rangep() && VN_IS(rangep()->msbp(), Const) && VN_IS(rangep()->lsbp(), Const)) { m.m_nrange.init(rangep()->msbConst(), rangep()->lsbConst(), rangep()->littleEndian()); rangep()->unlinkFrBackWithNext()->deleteTree(); - rangep(NULL); + rangep(nullptr); } } }; @@ -918,85 +935,90 @@ public: AstConstDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp) : ASTGEN_SUPER(fl) { childDTypep(dtp); // Only for parser - refDTypep(NULL); // V3Width will resolve - dtypep(NULL); // V3Width will resolve + refDTypep(nullptr); // V3Width will resolve + dtypep(nullptr); // V3Width will resolve widthFromSub(subDTypep()); } ASTNODE_NODE_FUNCS(ConstDType) - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } } - virtual bool same(const AstNode* samep) const { + virtual bool same(const AstNode* samep) const override { const AstConstDType* sp = static_cast(samep); return (m_refDTypep == sp->m_refDTypep); } - virtual bool similarDType(AstNodeDType* samep) const { + virtual bool similarDType(AstNodeDType* samep) const override { return skipRefp()->similarDType(samep->skipRefp()); } - virtual V3Hash sameHash() const { + virtual V3Hash sameHash() const override { return V3Hash(m_refDTypep); } // node's type() included elsewhere - AstNodeDType* getChildDTypep() const { return childDTypep(); } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } + virtual AstNodeDType* subDTypep() const override { + return m_refDTypep ? m_refDTypep : childDTypep(); + } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } + virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } // METHODS - virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } - virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); } - virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const { return subDTypep()->skipRefToEnump(); } - virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } + virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } + virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } }; class AstClassRefDType : public AstNodeDType { // Reference to a class private: AstClass* m_classp; // data type pointed to, BELOW the AstTypedef - AstNodeModule* m_packagep; // Package hierarchy + AstNodeModule* m_packagep = nullptr; // Package hierarchy public: AstClassRefDType(FileLine* fl, AstClass* classp) : ASTGEN_SUPER(fl) - , m_classp(classp) - , m_packagep(NULL) { + , m_classp{classp} { dtypep(this); } ASTNODE_NODE_FUNCS(ClassRefDType) // METHODS - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(m_classp && !m_classp->brokeExists()); - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_classp && m_classp->clonep()) m_classp = m_classp->clonep(); } - virtual bool same(const AstNode* samep) const { + virtual bool same(const AstNode* samep) const override { const AstClassRefDType* asamep = static_cast(samep); return (m_classp == asamep->m_classp && m_packagep == asamep->m_packagep); } - virtual bool similarDType(AstNodeDType* samep) const { return this == samep || same(samep); } - virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_classp), V3Hash(m_packagep)); } - virtual void dump(std::ostream& str = std::cout) const; - virtual void dumpSmall(std::ostream& str) const; - virtual string name() const { return classp() ? classp()->name() : ""; } - virtual AstBasicDType* basicp() const { return NULL; } - virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const { return 0; } - virtual int widthTotalBytes() const { return 0; } - virtual AstNodeDType* virtRefDTypep() const { return NULL; } - virtual void virtRefDTypep(AstNodeDType* nodep) {} - virtual AstNodeDType* subDTypep() const { return NULL; } + virtual bool similarDType(AstNodeDType* samep) const override { + return this == samep || same(samep); + } + virtual V3Hash sameHash() const override { + return V3Hash(V3Hash(m_classp), V3Hash(m_packagep)); + } + virtual void dump(std::ostream& str = std::cout) const override; + virtual void dumpSmall(std::ostream& str) const override; + virtual string name() const override { return classp() ? classp()->name() : ""; } + virtual AstBasicDType* basicp() const override { return nullptr; } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return 0; } + virtual int widthTotalBytes() const override { return 0; } + virtual AstNodeDType* virtRefDTypep() const override { return nullptr; } + virtual void virtRefDTypep(AstNodeDType* nodep) override {} + virtual AstNodeDType* subDTypep() const override { return nullptr; } AstNodeModule* packagep() const { return m_packagep; } void packagep(AstNodeModule* nodep) { m_packagep = nodep; } AstClass* classp() const { return m_classp; } @@ -1010,43 +1032,37 @@ private: string m_cellName; // "" = no cell, such as when connects to 'input' iface string m_ifaceName; // Interface name string m_modportName; // "" = no modport - AstIface* m_ifacep; // Pointer to interface; note cellp() should override - AstCell* m_cellp; // When exact parent cell known; not a guess - AstModport* m_modportp; // NULL = unlinked or no modport + AstIface* m_ifacep = nullptr; // Pointer to interface; note cellp() should override + AstCell* m_cellp = nullptr; // When exact parent cell known; not a guess + AstModport* m_modportp = nullptr; // nullptr = unlinked or no modport public: AstIfaceRefDType(FileLine* fl, const string& cellName, const string& ifaceName) : ASTGEN_SUPER(fl) - , m_modportFileline(NULL) - , m_cellName(cellName) - , m_ifaceName(ifaceName) - , m_modportName("") - , m_ifacep(NULL) - , m_cellp(NULL) - , m_modportp(NULL) {} + , m_modportFileline{nullptr} + , m_cellName{cellName} + , m_ifaceName{ifaceName} + , m_modportName{""} {} AstIfaceRefDType(FileLine* fl, FileLine* modportFl, const string& cellName, const string& ifaceName, const string& modport) : ASTGEN_SUPER(fl) - , m_modportFileline(modportFl) - , m_cellName(cellName) - , m_ifaceName(ifaceName) - , m_modportName(modport) - , m_ifacep(NULL) - , m_cellp(NULL) - , m_modportp(NULL) {} + , m_modportFileline{modportFl} + , m_cellName{cellName} + , m_ifaceName{ifaceName} + , m_modportName{modport} {} ASTNODE_NODE_FUNCS(IfaceRefDType) // METHODS - virtual const char* broken() const; - virtual void dump(std::ostream& str = std::cout) const; - virtual void dumpSmall(std::ostream& str) const; - virtual void cloneRelink(); - virtual AstBasicDType* basicp() const { return NULL; } - virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } - virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } - virtual bool similarDType(AstNodeDType* samep) const { return this == samep; } - virtual V3Hash sameHash() const { return V3Hash(m_cellp); } - virtual int widthAlignBytes() const { return 1; } - virtual int widthTotalBytes() const { return 1; } + virtual const char* broken() const override; + virtual void dump(std::ostream& str = std::cout) const override; + virtual void dumpSmall(std::ostream& str) const override; + virtual void cloneRelink() override; + virtual AstBasicDType* basicp() const override { return nullptr; } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } + virtual V3Hash sameHash() const override { return V3Hash(m_cellp); } + virtual int widthAlignBytes() const override { return 1; } + virtual int widthTotalBytes() const override { return 1; } FileLine* modportFileline() const { return m_modportFileline; } string cellName() const { return m_cellName; } void cellName(const string& name) { m_cellName = name; } @@ -1074,155 +1090,152 @@ public: : ASTGEN_SUPER(fl) { setNOp2p(boundp); childDTypep(dtp); // Only for parser - refDTypep(NULL); - dtypep(NULL); // V3Width will resolve + refDTypep(nullptr); + dtypep(nullptr); // V3Width will resolve } ASTNODE_NODE_FUNCS(QueueDType) - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } } - virtual bool same(const AstNode* samep) const { + virtual bool same(const AstNode* samep) const override { const AstQueueDType* asamep = static_cast(samep); return (subDTypep() == asamep->subDTypep()); } - virtual bool similarDType(AstNodeDType* samep) const { + virtual bool similarDType(AstNodeDType* samep) const override { const AstQueueDType* asamep = static_cast(samep); return (subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); } - virtual void dumpSmall(std::ostream& str) const; - virtual V3Hash sameHash() const { return V3Hash(m_refDTypep); } - virtual string prettyDTypeName() const; - virtual bool isHeavy() const { return true; } - AstNodeDType* getChildDTypep() const { return childDTypep(); } + virtual void dumpSmall(std::ostream& str) const override; + virtual V3Hash sameHash() const override { return V3Hash(m_refDTypep); } + virtual string prettyDTypeName() const override; + virtual bool isHeavy() const override { return true; } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } + virtual AstNodeDType* subDTypep() const override { + return m_refDTypep ? m_refDTypep : childDTypep(); + } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - AstNode* boundp() const { return op2p(); } // op2 = Bound, NULL = none + AstNode* boundp() const { return op2p(); } // op2 = Bound, nullptr = none void boundp(AstNode* nodep) { setNOp2p(nodep); } int boundConst() const { AstConst* constp = VN_CAST(boundp(), Const); return (constp ? constp->toSInt() : 0); } - virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } + virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } // METHODS - virtual AstBasicDType* basicp() const { return NULL; } + virtual AstBasicDType* basicp() const override { return nullptr; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } }; class AstRefDType : public AstNodeDType { private: // Pre-Width must reference the Typeref, not what it points to, as some child // types like AstBracketArrayType will disappear and can't lose the handle - AstTypedef* m_typedefp; // referenced type + AstTypedef* m_typedefp = nullptr; // referenced type // Post-width typedefs are removed and point to type directly - AstNodeDType* m_refDTypep; // data type pointed to, BELOW the AstTypedef + AstNodeDType* m_refDTypep = nullptr; // data type pointed to, BELOW the AstTypedef string m_name; // Name of an AstTypedef - AstNodeModule* m_packagep; // Package hierarchy + AstNodeModule* m_packagep = nullptr; // Package hierarchy public: AstRefDType(FileLine* fl, const string& name) : ASTGEN_SUPER(fl) - , m_typedefp(NULL) - , m_refDTypep(NULL) - , m_name(name) - , m_packagep(NULL) {} + , m_name{name} {} AstRefDType(FileLine* fl, const string& name, AstNode* classOrPackagep, AstNode* paramsp) : ASTGEN_SUPER(fl) - , m_typedefp(NULL) - , m_refDTypep(NULL) - , m_name(name) - , m_packagep(NULL) { + , m_name{name} { setNOp3p(classOrPackagep); addNOp4p(paramsp); } class FlagTypeOfExpr {}; // type(expr) for parser only AstRefDType(FileLine* fl, FlagTypeOfExpr, AstNode* typeofp) - : ASTGEN_SUPER(fl) - , m_typedefp(NULL) - , m_refDTypep(NULL) - , m_packagep(NULL) { + : ASTGEN_SUPER(fl) { setOp2p(typeofp); } ASTNODE_NODE_FUNCS(RefDType) // METHODS - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(m_typedefp && !m_typedefp->brokeExists()); BROKEN_RTN(m_refDTypep && !m_refDTypep->brokeExists()); - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_typedefp && m_typedefp->clonep()) { m_typedefp = m_typedefp->clonep(); } if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } } - virtual bool same(const AstNode* samep) const { + virtual bool same(const AstNode* samep) const override { const AstRefDType* asamep = static_cast(samep); return (m_typedefp == asamep->m_typedefp && m_refDTypep == asamep->m_refDTypep && m_name == asamep->m_name && m_packagep == asamep->m_packagep); } - virtual bool similarDType(AstNodeDType* samep) const { + virtual bool similarDType(AstNodeDType* samep) const override { return skipRefp()->similarDType(samep->skipRefp()); } - virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_typedefp), V3Hash(m_packagep)); } - virtual void dump(std::ostream& str = std::cout) const; - virtual string name() const { return m_name; } - virtual string prettyDTypeName() const { + virtual V3Hash sameHash() const override { + return V3Hash(V3Hash(m_typedefp), V3Hash(m_packagep)); + } + virtual void dump(std::ostream& str = std::cout) const override; + virtual string name() const override { return m_name; } + virtual string prettyDTypeName() const override { return subDTypep() ? subDTypep()->name() : prettyName(); } - virtual AstBasicDType* basicp() const { return subDTypep() ? subDTypep()->basicp() : NULL; } - AstNodeDType* subDTypep() const { - if (typedefp()) return typedefp()->subDTypep(); - return refDTypep(); // Maybe NULL + virtual AstBasicDType* basicp() const override { + return subDTypep() ? subDTypep()->basicp() : nullptr; } - virtual AstNodeDType* skipRefp() const { + virtual AstNodeDType* subDTypep() const override { + if (typedefp()) return typedefp()->subDTypep(); + return refDTypep(); // Maybe nullptr + } + virtual AstNodeDType* skipRefp() const override { // Skip past both the Ref and the Typedef if (subDTypep()) { return subDTypep()->skipRefp(); } else { v3fatalSrc("Typedef not linked"); - return NULL; + return nullptr; } } - virtual AstNodeDType* skipRefToConstp() const { + virtual AstNodeDType* skipRefToConstp() const override { if (subDTypep()) { return subDTypep()->skipRefToConstp(); } else { v3fatalSrc("Typedef not linked"); - return NULL; + return nullptr; } } - virtual AstNodeDType* skipRefToEnump() const { + virtual AstNodeDType* skipRefToEnump() const override { if (subDTypep()) { return subDTypep()->skipRefToEnump(); } else { v3fatalSrc("Typedef not linked"); - return NULL; + return nullptr; } } - virtual int widthAlignBytes() const { return dtypeSkipRefp()->widthAlignBytes(); } - virtual int widthTotalBytes() const { return dtypeSkipRefp()->widthTotalBytes(); } - void name(const string& flag) { m_name = flag; } + virtual int widthAlignBytes() const override { return dtypeSkipRefp()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return dtypeSkipRefp()->widthTotalBytes(); } + virtual void name(const string& flag) override { m_name = flag; } // op1 = Range of variable AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } AstTypedef* typedefp() const { return m_typedefp; } void typedefp(AstTypedef* nodep) { m_typedefp = nodep; } AstNodeDType* refDTypep() const { return m_refDTypep; } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const { return refDTypep(); } - virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } + virtual AstNodeDType* virtRefDTypep() const override { return refDTypep(); } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } AstNodeModule* packagep() const { return m_packagep; } void packagep(AstNodeModule* nodep) { m_packagep = nodep; } AstNode* typeofp() const { return op2p(); } @@ -1236,7 +1249,7 @@ public: AstStructDType(FileLine* fl, VSigning numericUnpack) : ASTGEN_SUPER(fl, numericUnpack) {} ASTNODE_NODE_FUNCS(StructDType) - virtual string verilogKwd() const { return "struct"; } + virtual string verilogKwd() const override { return "struct"; } }; class AstUnionDType : public AstNodeUOrStructDType { @@ -1246,7 +1259,7 @@ public: AstUnionDType(FileLine* fl, VSigning numericUnpack) : ASTGEN_SUPER(fl, numericUnpack) {} ASTNODE_NODE_FUNCS(UnionDType) - virtual string verilogKwd() const { return "union"; } + virtual string verilogKwd() const override { return "union"; } }; class AstMemberDType : public AstNodeDType { @@ -1256,56 +1269,58 @@ private: AstNodeDType* m_refDTypep; // Elements of this type (after widthing) string m_name; // Name of variable string m_tag; // Holds the string of the verilator tag -- used in XML output. - int m_lsb; // Within this level's packed struct, the LSB of the first bit of the member + int m_lsb = -1; // Within this level's packed struct, the LSB of the first bit of the member // UNSUP: int m_randType; // Randomization type (IEEE) public: AstMemberDType(FileLine* fl, const string& name, VFlagChildDType, AstNodeDType* dtp) : ASTGEN_SUPER(fl) - , m_name(name) - , m_lsb(-1) { + , m_name{name} { childDTypep(dtp); // Only for parser - dtypep(NULL); // V3Width will resolve - refDTypep(NULL); + dtypep(nullptr); // V3Width will resolve + refDTypep(nullptr); } AstMemberDType(FileLine* fl, const string& name, AstNodeDType* dtp) : ASTGEN_SUPER(fl) - , m_name(name) - , m_lsb(-1) { + , m_name{name} { UASSERT(dtp, "AstMember created with no dtype"); refDTypep(dtp); dtypep(this); widthFromSub(subDTypep()); } ASTNODE_NODE_FUNCS(MemberDType) - virtual string name() const { return m_name; } // * = Var name - virtual bool hasDType() const { return true; } - virtual bool maybePointedTo() const { return true; } - AstNodeDType* getChildDTypep() const { return childDTypep(); } + virtual string name() const override { return m_name; } // * = Var name + virtual bool hasDType() const override { return true; } + virtual bool maybePointedTo() const override { return true; } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } - virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } + virtual AstNodeDType* subDTypep() const override { + return m_refDTypep ? m_refDTypep : childDTypep(); + } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } - virtual bool similarDType(AstNodeDType* samep) const { return this == samep; } + virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } // // (Slow) recurse down to find basic data type (Note don't need virtual - // AstVar isn't a NodeDType) - virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } + virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType) AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } - virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); } - virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); } - virtual AstNodeDType* skipRefToEnump() const { return subDTypep()->skipRefToEnump(); } + virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } + virtual AstNodeDType* skipRefToConstp() const override { + return subDTypep()->skipRefToConstp(); + } + virtual AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) - virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } + virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... - virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } + virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } // METHODS - virtual void name(const string& name) { m_name = name; } - virtual void tag(const string& text) { m_tag = text; } - virtual string tag() const { return m_tag; } + virtual void name(const string& name) override { m_name = name; } + virtual void tag(const string& text) override { m_tag = text; } + virtual string tag() const override { return m_tag; } int lsb() const { return m_lsb; } void lsb(int lsb) { m_lsb = lsb; } }; @@ -1318,23 +1333,23 @@ public: dtypep(this); } ASTNODE_NODE_FUNCS(VoidDType) - virtual void dumpSmall(std::ostream& str) const; - virtual bool hasDType() const { return true; } - virtual bool maybePointedTo() const { return true; } - virtual AstNodeDType* subDTypep() const { return NULL; } - virtual AstNodeDType* virtRefDTypep() const { return NULL; } - virtual void virtRefDTypep(AstNodeDType* nodep) {} - virtual bool similarDType(AstNodeDType* samep) const { return this == samep; } - virtual AstBasicDType* basicp() const { return NULL; } + virtual void dumpSmall(std::ostream& str) const override; + virtual bool hasDType() const override { return true; } + virtual bool maybePointedTo() const override { return true; } + virtual AstNodeDType* subDTypep() const override { return nullptr; } + virtual AstNodeDType* virtRefDTypep() const override { return nullptr; } + virtual void virtRefDTypep(AstNodeDType* nodep) override {} + virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } + virtual AstBasicDType* basicp() const override { return nullptr; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const { return 1; } - virtual int widthTotalBytes() const { return 1; } - virtual V3Hash sameHash() const { return V3Hash(); } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return 1; } + virtual int widthTotalBytes() const override { return 1; } + virtual V3Hash sameHash() const override { return V3Hash(); } }; class AstEnumItem : public AstNode { @@ -1345,15 +1360,15 @@ public: // Parents: ENUM AstEnumItem(FileLine* fl, const string& name, AstNode* rangep, AstNode* initp) : ASTGEN_SUPER(fl) - , m_name(name) { + , m_name{name} { addNOp1p(rangep); addNOp2p(initp); } ASTNODE_NODE_FUNCS(EnumItem) - virtual string name() const { return m_name; } - virtual bool maybePointedTo() const { return true; } - virtual bool hasDType() const { return true; } - void name(const string& flag) { m_name = flag; } + virtual string name() const override { return m_name; } + virtual bool maybePointedTo() const override { return true; } + virtual bool hasDType() const override { return true; } + virtual void name(const string& flag) override { m_name = flag; } AstRange* rangep() const { return VN_CAST(op1p(), Range); } // op1 = Range for name appending void rangep(AstNode* nodep) { addOp1p(nodep); } AstNode* valuep() const { return op2p(); } // op2 = Value @@ -1367,29 +1382,29 @@ private: public: AstEnumItemRef(FileLine* fl, AstEnumItem* itemp, AstNodeModule* packagep) : ASTGEN_SUPER(fl) - , m_itemp(itemp) - , m_packagep(packagep) { + , m_itemp{itemp} + , m_packagep{packagep} { dtypeFrom(m_itemp); } ASTNODE_NODE_FUNCS(EnumItemRef) - virtual void dump(std::ostream& str) const; - virtual string name() const { return itemp()->name(); } - virtual const char* broken() const { + virtual void dump(std::ostream& str) const override; + virtual string name() const override { return itemp()->name(); } + virtual const char* broken() const override { BROKEN_RTN(!VN_IS(itemp(), EnumItem)); - return NULL; + return nullptr; } - virtual int instrCount() const { return 0; } - virtual void cloneRelink() { + virtual int instrCount() const override { return 0; } + virtual void cloneRelink() override { if (m_itemp->clonep()) m_itemp = VN_CAST(m_itemp->clonep(), EnumItem); } - virtual bool same(const AstNode* samep) const { + virtual bool same(const AstNode* samep) const override { const AstEnumItemRef* sp = static_cast(samep); return itemp() == sp->itemp(); } AstEnumItem* itemp() const { return m_itemp; } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return true; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } AstNodeModule* packagep() const { return m_packagep; } void packagep(AstNodeModule* nodep) { m_packagep = nodep; } }; @@ -1406,47 +1421,51 @@ public: AstEnumDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp, AstNode* itemsp) : ASTGEN_SUPER(fl) { childDTypep(dtp); // Only for parser - refDTypep(NULL); + refDTypep(nullptr); addNOp2p(itemsp); - dtypep(NULL); // V3Width will resolve + dtypep(nullptr); // V3Width will resolve widthFromSub(subDTypep()); m_uniqueNum = uniqueNumInc(); } ASTNODE_NODE_FUNCS(EnumDType) - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists()) || (!m_refDTypep && childDTypep()))); - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_refDTypep && m_refDTypep->clonep()) { m_refDTypep = m_refDTypep->clonep(); } } - virtual bool same(const AstNode* samep) const { + virtual bool same(const AstNode* samep) const override { const AstEnumDType* sp = static_cast(samep); return m_uniqueNum == sp->m_uniqueNum; } - virtual bool similarDType(AstNodeDType* samep) const { return this == samep; } - virtual V3Hash sameHash() const { return V3Hash(m_uniqueNum); } - AstNodeDType* getChildDTypep() const { return childDTypep(); } + virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } + virtual V3Hash sameHash() const override { return V3Hash(m_uniqueNum); } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } // op1 = Data type void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); } // op1 = Range of variable - virtual AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); } + virtual AstNodeDType* subDTypep() const override { + return m_refDTypep ? m_refDTypep : childDTypep(); + } void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; } - virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; } - virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); } - virtual string name() const { return m_name; } - void name(const string& flag) { m_name = flag; } + virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; } + virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } + virtual string name() const override { return m_name; } + virtual void name(const string& flag) override { m_name = flag; } AstEnumItem* itemsp() const { return VN_CAST(op2p(), EnumItem); } // op2 = AstEnumItem's void addValuesp(AstNode* nodep) { addOp2p(nodep); } // METHODS - virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } - virtual AstNodeDType* skipRefp() const { return subDTypep()->skipRefp(); } - virtual AstNodeDType* skipRefToConstp() const { return subDTypep()->skipRefToConstp(); } + virtual AstBasicDType* basicp() const override { return subDTypep()->basicp(); } + virtual AstNodeDType* skipRefp() const override { return subDTypep()->skipRefp(); } + virtual AstNodeDType* skipRefToConstp() const override { + return subDTypep()->skipRefToConstp(); + } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); } - virtual int widthTotalBytes() const { return subDTypep()->widthTotalBytes(); } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } + virtual int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } }; class AstParseTypeDType : public AstNodeDType { @@ -1457,17 +1476,17 @@ public: explicit AstParseTypeDType(FileLine* fl) : ASTGEN_SUPER(fl) {} ASTNODE_NODE_FUNCS(ParseTypeDType) - AstNodeDType* dtypep() const { return NULL; } + AstNodeDType* dtypep() const { return nullptr; } // METHODS - virtual bool similarDType(AstNodeDType* samep) const { return this == samep; } - virtual AstBasicDType* basicp() const { return NULL; } - virtual AstNodeDType* skipRefp() const { return NULL; } + virtual bool similarDType(AstNodeDType* samep) const override { return this == samep; } + virtual AstBasicDType* basicp() const override { return nullptr; } + virtual AstNodeDType* skipRefp() const override { return nullptr; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; } + virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } // cppcheck-suppress csyleCast - virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; } - virtual int widthAlignBytes() const { return 0; } - virtual int widthTotalBytes() const { return 0; } + virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } + virtual int widthAlignBytes() const override { return 0; } + virtual int widthTotalBytes() const override { return 0; } }; //###################################################################### @@ -1493,24 +1512,26 @@ public: init(fromp); } ASTNODE_NODE_FUNCS(ArraySel) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstArraySel(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { V3ERROR_NA; /* How can from be a const? */ } - virtual string emitVerilog() { return "%k(%l%f[%r])"; } - virtual string emitC() { return "%li%k[%ri]"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual bool isGateOptimizable() const { return true; } // esp for V3Const::ifSameAssign - virtual bool isPredictOptimizable() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } - virtual int instrCount() const { return widthInstrs(); } + virtual string emitVerilog() override { return "%k(%l%f[%r])"; } + virtual string emitC() override { return "%li%k[%ri]"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool isGateOptimizable() const override { + return true; + } // esp for V3Const::ifSameAssign + virtual bool isPredictOptimizable() const override { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } // Special operators static AstNode* baseFromp(AstNode* nodep); ///< What is the base variable (or const) this dereferences? @@ -1533,24 +1554,26 @@ public: init(fromp); } ASTNODE_NODE_FUNCS(AssocSel) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssocSel(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { V3ERROR_NA; } - virtual string emitVerilog() { return "%k(%l%f[%r])"; } - virtual string emitC() { return "%li%k[%ri]"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual bool isGateOptimizable() const { return true; } // esp for V3Const::ifSameAssign - virtual bool isPredictOptimizable() const { return false; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } - virtual int instrCount() const { return widthInstrs(); } + virtual string emitVerilog() override { return "%k(%l%f[%r])"; } + virtual string emitC() override { return "%li%k[%ri]"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool isGateOptimizable() const override { + return true; + } // esp for V3Const::ifSameAssign + virtual bool isPredictOptimizable() const override { return false; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } }; class AstWordSel : public AstNodeSel { @@ -1561,21 +1584,23 @@ public: dtypeSetUInt32(); // Always used on WData arrays so returns edata size } ASTNODE_NODE_FUNCS(WordSel) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstWordSel(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit) { + virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit) override { V3ERROR_NA; } - virtual string emitVerilog() { return "%k(%l%f[%r])"; } - virtual string emitC() { return "%li[%ri]"; } // Not %k, as usually it's a small constant rhsp - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual string emitVerilog() override { return "%k(%l%f[%r])"; } + virtual string emitC() override { + return "%li[%ri]"; + } // Not %k, as usually it's a small constant rhsp + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } }; class AstSelLoopVars : public AstNode { @@ -1588,11 +1613,9 @@ public: addNOp2p(elementsp); } ASTNODE_NODE_FUNCS(SelLoopVars) - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } - virtual bool maybePointedTo() const { return false; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } + virtual bool maybePointedTo() const override { return false; } AstNode* fromp() const { return op1p(); } AstNode* elementsp() const { return op2p(); } }; @@ -1612,7 +1635,7 @@ class AstSelBit : public AstNodePreSel { // Gets replaced during link with AstArraySel or AstSel public: AstSelBit(FileLine* fl, AstNode* fromp, AstNode* bitp) - : ASTGEN_SUPER(fl, fromp, bitp, NULL) { + : ASTGEN_SUPER(fl, fromp, bitp, nullptr) { UASSERT_OBJ(!v3Global.assertDTypesResolved(), this, "not coded to create after dtypes resolved"); } @@ -1653,39 +1676,43 @@ private: int m_declElWidth; // If a packed array, the number of bits per element public: AstSel(FileLine* fl, AstNode* fromp, AstNode* lsbp, AstNode* widthp) - : ASTGEN_SUPER(fl, fromp, lsbp, widthp) { - m_declElWidth = 1; + : ASTGEN_SUPER(fl, fromp, lsbp, widthp) + , m_declElWidth{1} { if (VN_IS(widthp, Const)) { dtypeSetLogicSized(VN_CAST(widthp, Const)->toUInt(), VSigning::UNSIGNED); } } AstSel(FileLine* fl, AstNode* fromp, int lsb, int bitwidth) - : ASTGEN_SUPER(fl, fromp, new AstConst(fl, lsb), new AstConst(fl, bitwidth)) { - m_declElWidth = 1; + : ASTGEN_SUPER(fl, fromp, new AstConst(fl, lsb), new AstConst(fl, bitwidth)) + , m_declElWidth{1} { dtypeSetLogicSized(bitwidth, VSigning::UNSIGNED); } ASTNODE_NODE_FUNCS(Sel) - virtual void dump(std::ostream& str) const; + virtual void dump(std::ostream& str) const override; virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& bit, - const V3Number& width) { + const V3Number& width) override { out.opSel(from, bit.toUInt() + width.toUInt() - 1, bit.toUInt()); } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual string emitC() { + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { return this->widthp()->isOne() ? "VL_BITSEL_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri)" : "VL_SEL_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri, %ti)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool cleanThs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual bool sizeMattersThs() const { return false; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode*) const { return true; } - virtual int instrCount() const { return widthInstrs() * (VN_CAST(lsbp(), Const) ? 3 : 10); } - AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing) + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool cleanThs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool sizeMattersThs() const override { return false; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode*) const override { return true; } + virtual int instrCount() const override { + return widthInstrs() * (VN_CAST(lsbp(), Const) ? 3 : 10); + } + AstNode* fromp() const { + return op1p(); + } // op1 = Extracting what (nullptr=TBD during parsing) AstNode* lsbp() const { return op2p(); } // op2 = Msb selection expression AstNode* widthp() const { return op3p(); } // op3 = Width int widthConst() const { return VN_CAST(widthp(), Const)->toSInt(); } @@ -1708,26 +1735,28 @@ public: AstSliceSel(FileLine* fl, AstNode* fromp, const VNumRange& declRange) : ASTGEN_SUPER(fl, fromp, new AstConst(fl, declRange.lo()), new AstConst(fl, declRange.elements())) - , m_declRange(declRange) {} + , m_declRange{declRange} {} ASTNODE_NODE_FUNCS(SliceSel) - virtual void dump(std::ostream& str) const; + virtual void dump(std::ostream& str) const override; virtual void numberOperate(V3Number& out, const V3Number& from, const V3Number& lo, - const V3Number& width) { + const V3Number& width) override { V3ERROR_NA; } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual string emitC() { V3ERROR_NA_RETURN(""); } // Removed before EmitC - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return true; } - virtual bool cleanThs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual bool sizeMattersThs() const { return false; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode*) const { return true; } - virtual int instrCount() const { return 10; } // Removed before matters - AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing) + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } // Removed before EmitC + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return true; } + virtual bool cleanThs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool sizeMattersThs() const override { return false; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode*) const override { return true; } + virtual int instrCount() const override { return 10; } // Removed before matters + AstNode* fromp() const { + return op1p(); + } // op1 = Extracting what (nullptr=TBD during parsing) // For widthConst()/loConst etc, see declRange().elements() and other VNumRange methods VNumRange& declRange() { return m_declRange; } const VNumRange& declRange() const { return m_declRange; } @@ -1744,25 +1773,27 @@ public: AstNode* pinsp) : ASTGEN_SUPER(fl, false, name, pinsp) { setOp2p(fromp); - dtypep(NULL); // V3Width will resolve + dtypep(nullptr); // V3Width will resolve } AstMethodCall(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp) : ASTGEN_SUPER(fl, false, name, pinsp) { setOp2p(fromp); } ASTNODE_NODE_FUNCS(MethodCall) - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_BASE_RTN(AstNodeFTaskRef::broken()); BROKEN_RTN(!fromp()); - return NULL; + return nullptr; } - virtual void dump(std::ostream& str) const; - virtual bool hasDType() const { return true; } + virtual void dump(std::ostream& str) const override; + virtual bool hasDType() const override { return true; } void makeStatement() { statement(true); dtypeSetVoid(); } - AstNode* fromp() const { return op2p(); } // op2 = Extracting what (NULL=TBD during parsing) + AstNode* fromp() const { + return op2p(); + } // op2 = Extracting what (nullptr=TBD during parsing) void fromp(AstNode* nodep) { setOp2p(nodep); } }; @@ -1772,40 +1803,40 @@ class AstCMethodHard : public AstNodeStmt { // Not all calls are statments vs math. AstNodeStmt needs isStatement() to deal. private: string m_name; // Name of method - bool m_pure; // Pure optimizable + bool m_pure = false; // Pure optimizable public: AstCMethodHard(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name, AstNode* pinsp) : ASTGEN_SUPER(fl, false) - , m_name(name) - , m_pure(false) { + , m_name{name} { setOp1p(fromp); - dtypep(NULL); // V3Width will resolve + dtypep(nullptr); // V3Width will resolve addNOp2p(pinsp); } AstCMethodHard(FileLine* fl, AstNode* fromp, const string& name, AstNode* pinsp) : ASTGEN_SUPER(fl, false) - , m_name(name) - , m_pure(false) { + , m_name{name} { setOp1p(fromp); addNOp2p(pinsp); } ASTNODE_NODE_FUNCS(CMethodHard) - virtual string name() const { return m_name; } // * = Var name - virtual bool hasDType() const { return true; } - virtual void name(const string& name) { m_name = name; } - virtual V3Hash sameHash() const { return V3Hash(m_name); } - virtual bool same(const AstNode* samep) const { + virtual string name() const override { return m_name; } // * = Var name + virtual bool hasDType() const override { return true; } + virtual void name(const string& name) override { m_name = name; } + virtual V3Hash sameHash() const override { return V3Hash(m_name); } + virtual bool same(const AstNode* samep) const override { const AstCMethodHard* asamep = static_cast(samep); return (m_name == asamep->m_name); } - virtual bool isPure() const { return m_pure; } + virtual bool isPure() const override { return m_pure; } void pure(bool flag) { m_pure = flag; } void makeStatement() { statement(true); dtypeSetVoid(); } - AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing) + AstNode* fromp() const { + return op1p(); + } // op1 = Extracting what (nullptr=TBD during parsing) void fromp(AstNode* nodep) { setOp1p(nodep); } AstNode* pinsp() const { return op2p(); } // op2 = Pin interconnection list void addPinsp(AstNode* nodep) { addOp2p(nodep); } @@ -1851,6 +1882,7 @@ private: bool m_isDpiOpenArray : 1; // DPI import open array bool m_noReset : 1; // Do not do automated reset/randomization bool m_noSubst : 1; // Do not substitute out references + bool m_overridenParam : 1; // Overridden parameter by #(...) or defparam bool m_trace : 1; // Trace this variable VLifetime m_lifetime; // Lifetime VVarAttrClocker m_attrClocker; @@ -1887,6 +1919,7 @@ private: m_isDpiOpenArray = false; m_noReset = false; m_noSubst = false; + m_overridenParam = false; m_trace = false; m_attrClocker = VVarAttrClocker::CLOCKER_UNKNOWN; } @@ -1894,12 +1927,12 @@ private: public: AstVar(FileLine* fl, AstVarType type, const string& name, VFlagChildDType, AstNodeDType* dtp) : ASTGEN_SUPER(fl) - , m_name(name) - , m_origName(name) { + , m_name{name} + , m_origName{name} { init(); combineType(type); childDTypep(dtp); // Only for parser - dtypep(NULL); // V3Width will resolve + dtypep(nullptr); // V3Width will resolve if (dtp->basicp()) { m_declKwd = dtp->basicp()->keyword(); } else { @@ -1908,8 +1941,8 @@ public: } AstVar(FileLine* fl, AstVarType type, const string& name, AstNodeDType* dtp) : ASTGEN_SUPER(fl) - , m_name(name) - , m_origName(name) { + , m_name{name} + , m_origName{name} { init(); combineType(type); UASSERT(dtp, "AstVar created with no dtype"); @@ -1922,8 +1955,8 @@ public: } AstVar(FileLine* fl, AstVarType type, const string& name, VFlagLogicPacked, int wantwidth) : ASTGEN_SUPER(fl) - , m_name(name) - , m_origName(name) { + , m_name{name} + , m_origName{name} { init(); combineType(type); dtypeSetLogicSized(wantwidth, VSigning::UNSIGNED); @@ -1931,8 +1964,8 @@ public: } AstVar(FileLine* fl, AstVarType type, const string& name, VFlagBitPacked, int wantwidth) : ASTGEN_SUPER(fl) - , m_name(name) - , m_origName(name) { + , m_name{name} + , m_origName{name} { init(); combineType(type); dtypeSetBitSized(wantwidth, VSigning::UNSIGNED); @@ -1940,8 +1973,8 @@ public: } AstVar(FileLine* fl, AstVarType type, const string& name, AstVar* examplep) : ASTGEN_SUPER(fl) - , m_name(name) - , m_origName(name) { + , m_name{name} + , m_origName{name} { init(); combineType(type); if (examplep->childDTypep()) { childDTypep(examplep->childDTypep()->cloneTree(true)); } @@ -1949,11 +1982,11 @@ public: m_declKwd = examplep->declKwd(); } ASTNODE_NODE_FUNCS(Var) - virtual void dump(std::ostream& str) const; - virtual string name() const { return m_name; } // * = Var name - virtual bool hasDType() const { return true; } - virtual bool maybePointedTo() const { return true; } - virtual string origName() const { return m_origName; } // * = Original name + virtual void dump(std::ostream& str) const override; + virtual string name() const override { return m_name; } // * = Var name + virtual bool hasDType() const override { return true; } + virtual bool maybePointedTo() const override { return true; } + virtual string origName() const override { return m_origName; } // * = Original name void origName(const string& name) { m_origName = name; } AstVarType varType() const { return m_varType; } // * = Type of variable void direction(const VDirection& flag) { @@ -1982,9 +2015,9 @@ public: string vlArgType(bool named, bool forReturn, bool forFunc, const string& namespc = "") const; string vlEnumType() const; // Return VerilatorVarType: VLVT_UINT32, etc string vlEnumDir() const; // Return VerilatorVarDir: VLVD_INOUT, etc - string vlPropDecl(string propName) const; // Return VerilatorVarProps declaration + string vlPropDecl(const string& propName) const; // Return VerilatorVarProps declaration void combineType(AstVarType type); - AstNodeDType* getChildDTypep() const { return childDTypep(); } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } // op1 = Range of variable AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } @@ -2036,11 +2069,13 @@ public: bool noReset() const { return m_noReset; } void noSubst(bool flag) { m_noSubst = flag; } bool noSubst() const { return m_noSubst; } + void overriddenParam(bool flag) { m_overridenParam = flag; } + bool overriddenParam() const { return m_overridenParam; } void trace(bool flag) { m_trace = flag; } // METHODS - virtual void name(const string& name) { m_name = name; } - virtual void tag(const string& text) { m_tag = text; } - virtual string tag() const { return m_tag; } + virtual void name(const string& name) override { m_name = name; } + virtual void tag(const string& text) override { m_tag = text; } + virtual string tag() const override { return m_tag; } bool isAnsi() const { return m_ansi; } bool isDeclTyped() const { return m_declTyped; } bool isInoutish() const { return m_direction.isInoutish(); } @@ -2101,7 +2136,7 @@ public: bool attrSplitVar() const { return m_attrSplitVar; } bool attrIsolateAssign() const { return m_attrIsolateAssign; } VVarAttrClocker attrClocker() const { return m_attrClocker; } - virtual string verilogKwd() const; + virtual string verilogKwd() const override; void lifetime(const VLifetime& flag) { m_lifetime = flag; } VLifetime lifetime() const { return m_lifetime; } void propagateAttrFrom(AstVar* fromp) { @@ -2159,11 +2194,10 @@ public: m_name = name; m_path = path; } - virtual string name() const { return m_name; } // * = Scope name + virtual string name() const override { return m_name; } // * = Scope name ASTNODE_NODE_FUNCS(DefParam) - virtual bool cleanRhs() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode*) const { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode*) const override { return true; } AstNode* rhsp() const { return op1p(); } // op1 = Assign from string path() const { return m_path; } }; @@ -2187,23 +2221,23 @@ class AstScope : public AstNode { private: // An AstScope->name() is special: . indicates an uninlined scope, __DOT__ an inlined scope string m_name; // Name - AstScope* m_aboveScopep; // Scope above this one in the hierarchy (NULL if top) - AstCell* m_aboveCellp; // Cell above this in the hierarchy (NULL if top) + AstScope* m_aboveScopep; // Scope above this one in the hierarchy (nullptr if top) + AstCell* m_aboveCellp; // Cell above this in the hierarchy (nullptr if top) AstNodeModule* m_modp; // Module scope corresponds to public: AstScope(FileLine* fl, AstNodeModule* modp, const string& name, AstScope* aboveScopep, AstCell* aboveCellp) : ASTGEN_SUPER(fl) - , m_name(name) - , m_aboveScopep(aboveScopep) - , m_aboveCellp(aboveCellp) - , m_modp(modp) {} + , m_name{name} + , m_aboveScopep{aboveScopep} + , m_aboveCellp{aboveCellp} + , m_modp{modp} {} ASTNODE_NODE_FUNCS(Scope) - virtual void cloneRelink(); - virtual const char* broken() const; - virtual bool maybePointedTo() const { return true; } - virtual string name() const { return m_name; } // * = Scope name - virtual void name(const string& name) { m_name = name; } + virtual void cloneRelink() override; + virtual const char* broken() const override; + virtual bool maybePointedTo() const override { return true; } + virtual string name() const override { return m_name; } // * = Scope name + virtual void name(const string& name) override { m_name = name; } string nameDotless() const; string nameVlSym() const { return ((string("vlSymsp->")) + nameDotless()); } AstNodeModule* modp() const { return m_modp; } @@ -2215,7 +2249,7 @@ public: AstNode* finalClksp() const { return op3p(); } // op3 = Final assigns for clock correction AstScope* aboveScopep() const { return m_aboveScopep; } AstCell* aboveCellp() const { return m_aboveCellp; } - bool isTop() const { return aboveScopep() == NULL; } // At top of hierarchy + bool isTop() const { return aboveScopep() == nullptr; } // At top of hierarchy }; class AstTopScope : public AstNode { @@ -2248,32 +2282,32 @@ private: public: AstVarScope(FileLine* fl, AstScope* scopep, AstVar* varp) : ASTGEN_SUPER(fl) - , m_scopep(scopep) - , m_varp(varp) { + , m_scopep{scopep} + , m_varp{varp} { m_circular = false; m_trace = true; dtypeFrom(varp); } ASTNODE_NODE_FUNCS(VarScope) - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_varp && m_varp->clonep()) { m_varp = m_varp->clonep(); UASSERT(m_scopep->clonep(), "No clone cross link: " << this); m_scopep = m_scopep->clonep(); } } - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(m_varp && !m_varp->brokeExists()); BROKEN_RTN(m_scopep && !m_scopep->brokeExists()); - return NULL; + return nullptr; } - virtual bool maybePointedTo() const { return true; } - virtual string name() const { return scopep()->name() + "->" + varp()->name(); } - virtual void dump(std::ostream& str) const; - virtual bool hasDType() const { return true; } + virtual bool maybePointedTo() const override { return true; } + virtual string name() const override { return scopep()->name() + "->" + varp()->name(); } + virtual void dump(std::ostream& str) const override; + virtual bool hasDType() const override { return true; } AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable AstScope* scopep() const { return m_scopep; } // Pointer to scope it's under - // op1 = Calculation of value of variable, NULL=complicated + // op1 = Calculation of value of variable, nullptr=complicated AstNode* valuep() const { return op1p(); } void valuep(AstNode* valuep) { addOp1p(valuep); } bool isCircular() const { return m_circular; } @@ -2286,7 +2320,7 @@ class AstVarRef : public AstNodeVarRef { // A reference to a variable (lvalue or rvalue) public: AstVarRef(FileLine* fl, const string& name, bool lvalue) - : ASTGEN_SUPER(fl, name, NULL, lvalue) {} + : ASTGEN_SUPER(fl, name, nullptr, lvalue) {} // This form only allowed post-link because output/wire compression may // lead to deletion of AstVar's AstVarRef(FileLine* fl, AstVar* varp, bool lvalue) @@ -2297,9 +2331,11 @@ public: varScopep(varscp); } ASTNODE_NODE_FUNCS(VarRef) - virtual void dump(std::ostream& str) const; - virtual V3Hash sameHash() const { return V3Hash(V3Hash(varp()->name()), V3Hash(hiername())); } - virtual bool same(const AstNode* samep) const { + virtual void dump(std::ostream& str) const override; + virtual V3Hash sameHash() const override { + return V3Hash(V3Hash(varp()->name()), V3Hash(hiername())); + } + virtual bool same(const AstNode* samep) const override { return same(static_cast(samep)); } inline bool same(const AstVarRef* samep) const { @@ -2317,10 +2353,12 @@ public: return (hiername() == samep->hiername() && varp()->name() == samep->varp()->name()); } } - virtual int instrCount() const { return widthInstrs() * (lvalue() ? 1 : instrCountLd()); } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return true; } + virtual int instrCount() const override { + return widthInstrs() * (lvalue() ? 1 : instrCountLd()); + } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } }; class AstVarXRef : public AstNodeVarRef { @@ -2331,26 +2369,26 @@ private: string m_inlinedDots; // Dotted hierarchy flattened out public: AstVarXRef(FileLine* fl, const string& name, const string& dotted, bool lvalue) - : ASTGEN_SUPER(fl, name, NULL, lvalue) - , m_dotted(dotted) {} + : ASTGEN_SUPER(fl, name, nullptr, lvalue) + , m_dotted{dotted} {} AstVarXRef(FileLine* fl, AstVar* varp, const string& dotted, bool lvalue) : ASTGEN_SUPER(fl, varp->name(), varp, lvalue) - , m_dotted(dotted) { + , m_dotted{dotted} { dtypeFrom(varp); } ASTNODE_NODE_FUNCS(VarXRef) - virtual void dump(std::ostream& str) const; + virtual void dump(std::ostream& str) const override; string dotted() const { return m_dotted; } void dotted(const string& dotted) { m_dotted = dotted; } string prettyDotted() const { return prettyName(dotted()); } string inlinedDots() const { return m_inlinedDots; } void inlinedDots(const string& flag) { m_inlinedDots = flag; } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return true; } - virtual int instrCount() const { return widthInstrs(); } - virtual V3Hash sameHash() const { return V3Hash(V3Hash(varp()), V3Hash(dotted())); } - virtual bool same(const AstNode* samep) const { + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } + virtual V3Hash sameHash() const override { return V3Hash(V3Hash(varp()), V3Hash(dotted())); } + virtual bool same(const AstNode* samep) const override { const AstVarXRef* asamep = static_cast(samep); return (hiername() == asamep->hiername() && varp() == asamep->varp() && name() == asamep->name() && dotted() == asamep->dotted()); @@ -2362,41 +2400,33 @@ class AstPin : public AstNode { private: int m_pinNum; // Pin number string m_name; // Pin name, or "" for number based interconnect - AstVar* m_modVarp; // Input/output this pin connects to on submodule. - AstParamTypeDType* m_modPTypep; // Param type this pin connects to on submodule. - bool m_param; // Pin connects to parameter - bool m_svImplicit; // Pin is SystemVerilog .name'ed + AstVar* m_modVarp = nullptr; // Input/output this pin connects to on submodule. + AstParamTypeDType* m_modPTypep = nullptr; // Param type this pin connects to on submodule. + bool m_param = false; // Pin connects to parameter + bool m_svImplicit = false; // Pin is SystemVerilog .name'ed public: AstPin(FileLine* fl, int pinNum, const string& name, AstNode* exprp) : ASTGEN_SUPER(fl) - , m_name(name) - , m_param(false) - , m_svImplicit(false) { - m_pinNum = pinNum; - m_modVarp = NULL; - m_modPTypep = NULL; + , m_pinNum{pinNum} + , m_name{name} { setNOp1p(exprp); } AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp) : ASTGEN_SUPER(fl) - , m_param(false) - , m_svImplicit(false) { - m_name = varname->name(); - m_pinNum = pinNum; - m_modVarp = NULL; - m_modPTypep = NULL; + , m_pinNum{pinNum} + , m_name{varname->name()} { setNOp1p(exprp); } ASTNODE_NODE_FUNCS(Pin) - virtual void dump(std::ostream& str) const; - virtual const char* broken() const { + virtual void dump(std::ostream& str) const override; + virtual const char* broken() const override { BROKEN_RTN(m_modVarp && !m_modVarp->brokeExists()); BROKEN_RTN(m_modPTypep && !m_modPTypep->brokeExists()); - return NULL; + return nullptr; } - virtual string name() const { return m_name; } // * = Pin name, ""=go by number - virtual void name(const string& name) { m_name = name; } - virtual string prettyOperatorName() const { + virtual string name() const override { return m_name; } // * = Pin name, ""=go by number + virtual void name(const string& name) override { m_name = name; } + virtual string prettyOperatorName() const override { return modVarp() ? ((modVarp()->direction().isAny() ? modVarp()->direction().prettyName() + " " : "") @@ -2406,7 +2436,7 @@ public: bool dotStar() const { return name() == ".*"; } // Fake name for .* connections until linked int pinNum() const { return m_pinNum; } void exprp(AstNode* nodep) { addOp1p(nodep); } - // op1 = Expression connected to pin, NULL if unconnected + // op1 = Expression connected to pin, nullptr if unconnected AstNode* exprp() const { return op1p(); } AstVar* modVarp() const { return m_modVarp; } // [After Link] Pointer to variable void modVarp(AstVar* nodep) { m_modVarp = nodep; } @@ -2426,15 +2456,15 @@ private: public: AstArg(FileLine* fl, const string& name, AstNode* exprp) : ASTGEN_SUPER(fl) - , m_name(name) { + , m_name{name} { setNOp1p(exprp); } ASTNODE_NODE_FUNCS(Arg) - virtual string name() const { return m_name; } // * = Pin name, ""=go by number - virtual void name(const string& name) { m_name = name; } - virtual V3Hash sameHash() const { return V3Hash(); } + virtual string name() const override { return m_name; } // * = Pin name, ""=go by number + virtual void name(const string& name) override { m_name = name; } + virtual V3Hash sameHash() const override { return V3Hash(); } void exprp(AstNode* nodep) { addOp1p(nodep); } - // op1 = Expression connected to pin, NULL if unconnected + // op1 = Expression connected to pin, nullptr if unconnected AstNode* exprp() const { return op1p(); } bool emptyConnectNoNext() const { return !exprp() && name() == "" && !nextp(); } }; @@ -2446,9 +2476,9 @@ private: public: AstModule(FileLine* fl, const string& name, bool program = false) : ASTGEN_SUPER(fl, name) - , m_isProgram(program) {} + , m_isProgram{program} {} ASTNODE_NODE_FUNCS(Module) - virtual string verilogKwd() const { return m_isProgram ? "program" : "module"; } + virtual string verilogKwd() const override { return m_isProgram ? "program" : "module"; } }; class AstNotFoundModule : public AstNodeModule { @@ -2457,7 +2487,7 @@ public: AstNotFoundModule(FileLine* fl, const string& name) : ASTGEN_SUPER(fl, name) {} ASTNODE_NODE_FUNCS(NotFoundModule) - virtual string verilogKwd() const { return "/*not-found-*/ module"; } + virtual string verilogKwd() const override { return "/*not-found-*/ module"; } }; class AstPackage : public AstNodeModule { @@ -2466,7 +2496,7 @@ public: AstPackage(FileLine* fl, const string& name) : ASTGEN_SUPER(fl, name) {} ASTNODE_NODE_FUNCS(Package) - virtual string verilogKwd() const { return "package"; } + virtual string verilogKwd() const override { return "package"; } static string dollarUnitName() { return AstNode::encodeName("$unit"); } bool isDollarUnit() const { return name() == dollarUnitName(); } }; @@ -2477,7 +2507,7 @@ public: AstPrimitive(FileLine* fl, const string& name) : ASTGEN_SUPER(fl, name) {} ASTNODE_NODE_FUNCS(Primitive) - virtual string verilogKwd() const { return "primitive"; } + virtual string verilogKwd() const override { return "primitive"; } }; class AstPackageExportStarStar : public AstNode { @@ -2497,18 +2527,18 @@ private: public: AstPackageExport(FileLine* fl, AstPackage* packagep, const string& name) : ASTGEN_SUPER(fl) - , m_name(name) - , m_packagep(packagep) {} + , m_name{name} + , m_packagep{packagep} {} ASTNODE_NODE_FUNCS(PackageExport) - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(!m_packagep || !m_packagep->brokeExists()); - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep(); } - virtual void dump(std::ostream& str) const; - virtual string name() const { return m_name; } + virtual void dump(std::ostream& str) const override; + virtual string name() const override { return m_name; } AstPackage* packagep() const { return m_packagep; } void packagep(AstPackage* nodep) { m_packagep = nodep; } }; @@ -2521,18 +2551,18 @@ private: public: AstPackageImport(FileLine* fl, AstPackage* packagep, const string& name) : ASTGEN_SUPER(fl) - , m_name(name) - , m_packagep(packagep) {} + , m_name{name} + , m_packagep{packagep} {} ASTNODE_NODE_FUNCS(PackageImport) - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(!m_packagep || !m_packagep->brokeExists()); - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep(); } - virtual void dump(std::ostream& str) const; - virtual string name() const { return m_name; } + virtual void dump(std::ostream& str) const override; + virtual string name() const override { return m_name; } AstPackage* packagep() const { return m_packagep; } void packagep(AstPackage* nodep) { m_packagep = nodep; } }; @@ -2551,42 +2581,41 @@ class AstMemberSel : public AstNodeMath { private: // Don't need the class we are extracting from, as the "fromp()"'s datatype can get us to it string m_name; - AstVar* m_varp; // Post link, variable within class that is target of selection + AstVar* m_varp = nullptr; // Post link, variable within class that is target of selection public: AstMemberSel(FileLine* fl, AstNode* fromp, VFlagChildDType, const string& name) : ASTGEN_SUPER(fl) - , m_name(name) - , m_varp(NULL) { + , m_name{name} { setOp1p(fromp); - dtypep(NULL); // V3Width will resolve + dtypep(nullptr); // V3Width will resolve } AstMemberSel(FileLine* fl, AstNode* fromp, AstNodeDType* dtp) : ASTGEN_SUPER(fl) - , m_name(dtp->name()) - , m_varp(NULL) { + , m_name{dtp->name()} { setOp1p(fromp); dtypep(dtp); } ASTNODE_NODE_FUNCS(MemberSel) - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_varp && m_varp->clonep()) { m_varp = m_varp->clonep(); } } - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(m_varp && !m_varp->brokeExists()); - return NULL; + return nullptr; } - virtual void dump(std::ostream& str) const; - virtual string name() const { return m_name; } - virtual V3Hash sameHash() const { return V3Hash(m_name); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { - V3ERROR_NA; /* How can from be a const? */ - } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return false; } - virtual bool same(const AstNode* samep) const { return true; } // dtype comparison does it - virtual int instrCount() const { return widthInstrs(); } - AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing) + virtual void dump(std::ostream& str) const override; + virtual string name() const override { return m_name; } + virtual V3Hash sameHash() const override { return V3Hash(m_name); } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool same(const AstNode* samep) const override { + return true; + } // dtype comparison does it + virtual int instrCount() const override { return widthInstrs(); } + AstNode* fromp() const { + return op1p(); + } // op1 = Extracting what (nullptr=TBD during parsing) void fromp(AstNode* nodep) { setOp1p(nodep); } AstVar* varp() const { return m_varp; } void varp(AstVar* nodep) { m_varp = nodep; } @@ -2600,21 +2629,20 @@ class AstModportFTaskRef : public AstNode { private: string m_name; // Name of the variable referenced bool m_export; // Type of the function (import/export) - AstNodeFTask* m_ftaskp; // Link to the function + AstNodeFTask* m_ftaskp = nullptr; // Link to the function public: AstModportFTaskRef(FileLine* fl, const string& name, bool isExport) : ASTGEN_SUPER(fl) - , m_name(name) - , m_export(isExport) - , m_ftaskp(NULL) {} + , m_name{name} + , m_export{isExport} {} ASTNODE_NODE_FUNCS(ModportFTaskRef) - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(m_ftaskp && !m_ftaskp->brokeExists()); - return NULL; + return nullptr; } - virtual void dump(std::ostream& str) const; - virtual string name() const { return m_name; } - virtual void cloneRelink() { + virtual void dump(std::ostream& str) const override; + virtual string name() const override { return m_name; } + virtual void cloneRelink() override { if (m_ftaskp && m_ftaskp->clonep()) m_ftaskp = m_ftaskp->clonep(); } bool isImport() const { return !m_export; } @@ -2630,23 +2658,22 @@ class AstModportVarRef : public AstNode { private: string m_name; // Name of the variable referenced VDirection m_direction; // Direction of the variable (in/out) - AstVar* m_varp; // Link to the actual Var + AstVar* m_varp = nullptr; // Link to the actual Var public: AstModportVarRef(FileLine* fl, const string& name, VDirection::en direction) : ASTGEN_SUPER(fl) - , m_name(name) - , m_direction(direction) - , m_varp(NULL) {} + , m_name{name} + , m_direction{direction} {} ASTNODE_NODE_FUNCS(ModportVarRef) - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(m_varp && !m_varp->brokeExists()); - return NULL; + return nullptr; } - virtual void dump(std::ostream& str) const; - virtual void cloneRelink() { + virtual void dump(std::ostream& str) const override; + virtual void cloneRelink() override { if (m_varp && m_varp->clonep()) m_varp = m_varp->clonep(); } - virtual string name() const { return m_name; } + virtual string name() const override { return m_name; } void direction(const VDirection& flag) { m_direction = flag; } VDirection direction() const { return m_direction; } AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable @@ -2660,11 +2687,11 @@ private: public: AstModport(FileLine* fl, const string& name, AstNode* varsp) : ASTGEN_SUPER(fl) - , m_name(name) { + , m_name{name} { addNOp1p(varsp); } - virtual string name() const { return m_name; } - virtual bool maybePointedTo() const { return true; } + virtual string name() const override { return m_name; } + virtual bool maybePointedTo() const override { return true; } ASTNODE_NODE_FUNCS(Modport) AstNode* varsp() const { return op1p(); } // op1 = List of Vars }; @@ -2676,8 +2703,8 @@ private: public: AstIntfRef(FileLine* fl, const string& name) : ASTGEN_SUPER(fl) - , m_name(name) {} - virtual string name() const { return m_name; } + , m_name{name} {} + virtual string name() const override { return m_name; } ASTNODE_NODE_FUNCS(IntfRef) }; @@ -2688,7 +2715,7 @@ private: string m_name; // Cell name string m_origName; // Original name before dot addition string m_modName; // Module the cell instances - AstNodeModule* m_modp; // [AfterLink] Pointer to module instanced + AstNodeModule* m_modp = nullptr; // [AfterLink] Pointer to module instanced bool m_hasIfaceVar : 1; // True if a Var has been created for this cell bool m_recursive : 1; // Self-recursive module bool m_trace : 1; // Trace this cell @@ -2696,30 +2723,29 @@ public: AstCell(FileLine* fl, FileLine* mfl, const string& instName, const string& modName, AstPin* pinsp, AstPin* paramsp, AstRange* rangep) : ASTGEN_SUPER(fl) - , m_modNameFileline(mfl) - , m_name(instName) - , m_origName(instName) - , m_modName(modName) - , m_modp(NULL) - , m_hasIfaceVar(false) - , m_recursive(false) - , m_trace(true) { + , m_modNameFileline{mfl} + , m_name{instName} + , m_origName{instName} + , m_modName{modName} + , m_hasIfaceVar{false} + , m_recursive{false} + , m_trace{true} { addNOp1p(pinsp); addNOp2p(paramsp); setNOp3p(rangep); } ASTNODE_NODE_FUNCS(Cell) // No cloneRelink, we presume cloneee's want the same module linkages - virtual void dump(std::ostream& str) const; - virtual const char* broken() const { + virtual void dump(std::ostream& str) const override; + virtual const char* broken() const override { BROKEN_RTN(m_modp && !m_modp->brokeExists()); - return NULL; + return nullptr; } - virtual bool maybePointedTo() const { return true; } + virtual bool maybePointedTo() const override { return true; } // ACCESSORS - virtual string name() const { return m_name; } // * = Cell name - virtual void name(const string& name) { m_name = name; } - virtual string origName() const { return m_origName; } // * = Original name + virtual string name() const override { return m_name; } // * = Cell name + virtual void name(const string& name) override { m_name = name; } + virtual string origName() const override { return m_origName; } // * = Original name void origName(const string& name) { m_origName = name; } string modName() const { return m_modName; } // * = Instance name void modName(const string& name) { m_modName = name; } @@ -2727,7 +2753,7 @@ public: AstPin* pinsp() const { return VN_CAST(op1p(), Pin); } // op1 = List of cell ports // op2 = List of parameter #(##) values AstPin* paramsp() const { return VN_CAST(op2p(), Pin); } - // op3 = Range of arrayed instants (NULL=not ranged) + // op3 = Range of arrayed instants (nullptr=not ranged) AstRange* rangep() const { return VN_CAST(op3p(), Range); } // op4 = List of interface references AstIntfRef* intfRefp() const { return VN_CAST(op4p(), IntfRef); } @@ -2753,26 +2779,25 @@ class AstCellInline : public AstNode { private: string m_name; // Cell name, possibly {a}__DOT__{b}... string m_origModName; // Original name of the module, ignoring name() changes, for dot lookup - AstScope* m_scopep; // The scope that the cell is inlined into + AstScope* m_scopep = nullptr; // The scope that the cell is inlined into VTimescale m_timeunit; // Parent module time unit public: AstCellInline(FileLine* fl, const string& name, const string& origModName, const VTimescale& timeunit) : ASTGEN_SUPER(fl) - , m_name(name) - , m_origModName(origModName) - , m_scopep(NULL) - , m_timeunit(timeunit) {} + , m_name{name} + , m_origModName{origModName} + , m_timeunit{timeunit} {} ASTNODE_NODE_FUNCS(CellInline) - virtual void dump(std::ostream& str) const; - virtual const char* broken() const { + virtual void dump(std::ostream& str) const override; + virtual const char* broken() const override { BROKEN_RTN(m_scopep && !m_scopep->brokeExists()); - return NULL; + return nullptr; } // ACCESSORS - virtual string name() const { return m_name; } // * = Cell name + virtual string name() const override { return m_name; } // * = Cell name string origModName() const { return m_origModName; } // * = modp()->origName() before inlining - virtual void name(const string& name) { m_name = name; } + virtual void name(const string& name) override { m_name = name; } void scopep(AstScope* scp) { m_scopep = scp; } AstScope* scopep() const { return m_scopep; } void timeunit(const VTimescale& flag) { m_timeunit = flag; } @@ -2786,13 +2811,13 @@ private: public: AstCellRef(FileLine* fl, const string& name, AstNode* cellp, AstNode* exprp) : ASTGEN_SUPER(fl) - , m_name(name) { + , m_name{name} { addNOp1p(cellp); addNOp2p(exprp); } ASTNODE_NODE_FUNCS(CellRef) // ACCESSORS - virtual string name() const { return m_name; } // * = Array name + virtual string name() const override { return m_name; } // * = Array name AstNode* cellp() const { return op1p(); } // op1 = Cell AstNode* exprp() const { return op2p(); } // op2 = Expression }; @@ -2804,12 +2829,12 @@ private: public: AstCellArrayRef(FileLine* fl, const string& name, AstNode* selectExprp) : ASTGEN_SUPER(fl) - , m_name(name) { + , m_name{name} { addNOp1p(selectExprp); } ASTNODE_NODE_FUNCS(CellArrayRef) // ACCESSORS - virtual string name() const { return m_name; } // * = Array name + virtual string name() const override { return m_name; } // * = Array name AstNode* selp() const { return op1p(); } // op1 = Select expression }; @@ -2820,13 +2845,13 @@ private: public: AstUnlinkedRef(FileLine* fl, AstNode* refp, const string& name, AstNode* crp) : ASTGEN_SUPER(fl) - , m_name(name) { + , m_name{name} { addNOp1p(refp); addNOp2p(crp); } ASTNODE_NODE_FUNCS(UnlinkedRef) // ACCESSORS - virtual string name() const { return m_name; } // * = Var name + virtual string name() const override { return m_name; } // * = Var name AstNode* refp() const { return op1p(); } // op1 = VarXRef or AstNodeFTaskRef AstNode* cellrefp() const { return op2p(); } // op2 = CellArrayRef or CellRef }; @@ -2839,14 +2864,14 @@ private: public: AstBind(FileLine* fl, const string& name, AstNode* cellsp) : ASTGEN_SUPER(fl) - , m_name(name) { + , m_name{name} { UASSERT_OBJ(VN_IS(cellsp, Cell), cellsp, "Only cells allowed to be bound"); addNOp1p(cellsp); } ASTNODE_NODE_FUNCS(Bind) // ACCESSORS - virtual string name() const { return m_name; } // * = Bind Target name - virtual void name(const string& name) { m_name = name; } + virtual string name() const override { return m_name; } // * = Bind Target name + virtual void name(const string& name) override { m_name = name; } AstNode* cellsp() const { return op1p(); } // op1 = cells }; @@ -2858,10 +2883,10 @@ private: public: AstPort(FileLine* fl, int pinnum, const string& name) : ASTGEN_SUPER(fl) - , m_pinNum(pinnum) - , m_name(name) {} + , m_pinNum{pinnum} + , m_name{name} {} ASTNODE_NODE_FUNCS(Port) - virtual string name() const { return m_name; } // * = Port name + virtual string name() const override { return m_name; } // * = Port name int pinNum() const { return m_pinNum; } // * = Pin number, for order based instantiation AstNode* exprp() const { return op1p(); } // op1 = Expression connected to port }; @@ -2879,25 +2904,23 @@ private: string m_name; public: - AstParseRef(FileLine* fl, VParseRefExp expect, const string& name, AstNode* lhsp = NULL, - AstNodeFTaskRef* ftaskrefp = NULL) + AstParseRef(FileLine* fl, VParseRefExp expect, const string& name, AstNode* lhsp = nullptr, + AstNodeFTaskRef* ftaskrefp = nullptr) : ASTGEN_SUPER(fl) - , m_expect(expect) - , m_name(name) { + , m_expect{expect} + , m_name{name} { setNOp1p(lhsp); setNOp2p(ftaskrefp); } ASTNODE_NODE_FUNCS(ParseRef) - virtual void dump(std::ostream& str) const; - virtual string name() const { return m_name; } // * = Var name - virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_expect), V3Hash(m_name)); } - virtual bool same(const AstNode* samep) const { + virtual void dump(std::ostream& str) const override; + virtual string name() const override { return m_name; } // * = Var name + virtual V3Hash sameHash() const override { return V3Hash(V3Hash(m_expect), V3Hash(m_name)); } + virtual bool same(const AstNode* samep) const override { const AstParseRef* asamep = static_cast(samep); return (expect() == asamep->expect() && m_name == asamep->m_name); } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual void name(const string& name) { m_name = name; } + virtual void name(const string& name) override { m_name = name; } VParseRefExp expect() const { return m_expect; } void expect(VParseRefExp exp) { m_expect = exp; } // op1 = Components @@ -2914,28 +2937,28 @@ public: AstClassOrPackageRef(FileLine* fl, const string& name, AstNode* classOrPackagep, AstNode* paramsp) : ASTGEN_SUPER(fl) - , m_name(name) - , m_classOrPackagep(classOrPackagep) { + , m_name{name} + , m_classOrPackagep{classOrPackagep} { addNOp4p(paramsp); } ASTNODE_NODE_FUNCS(ClassOrPackageRef) // METHODS - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists()); - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_classOrPackagep && m_classOrPackagep->clonep()) { m_classOrPackagep = m_classOrPackagep->clonep(); } } - virtual bool same(const AstNode* samep) const { + virtual bool same(const AstNode* samep) const override { return (m_classOrPackagep == static_cast(samep)->m_classOrPackagep); } - virtual V3Hash sameHash() const { return V3Hash(m_classOrPackagep); } - virtual void dump(std::ostream& str = std::cout) const; - virtual string name() const { return m_name; } // * = Var name + virtual V3Hash sameHash() const override { return V3Hash(m_classOrPackagep); } + virtual void dump(std::ostream& str = std::cout) const override; + virtual string name() const override { return m_name; } // * = Var name AstNode* classOrPackagep() const { return m_classOrPackagep; } AstPackage* packagep() const { return VN_CAST(classOrPackagep(), Package); } void classOrPackagep(AstNode* nodep) { m_classOrPackagep = nodep; } @@ -2949,7 +2972,7 @@ class AstDot : public AstNode { public: AstDot(FileLine* fl, bool colon, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl) - , m_colon(colon) { + , m_colon{colon} { setOp1p(lhsp); setOp2p(rhsp); } @@ -2959,9 +2982,7 @@ public: if (!packageOrClassp) return rhsp; return new AstDot(fl, true, packageOrClassp, rhsp); } - virtual void dump(std::ostream& str) const; - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual string emitC() { V3ERROR_NA_RETURN(""); } + virtual void dump(std::ostream& str) const override; AstNode* lhsp() const { return op1p(); } AstNode* rhsp() const { return op2p(); } bool colon() const { return m_colon; } @@ -2976,9 +2997,9 @@ public: dtypeSetSigned32(); } ASTNODE_NODE_FUNCS(Unbounded) - virtual string emitVerilog() { return "$"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return true; } + virtual string emitVerilog() override { return "$"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } }; //###################################################################### @@ -2999,7 +3020,7 @@ public: addNOp1p(fvarsp); } ASTNODE_NODE_FUNCS(Func) - virtual bool hasDType() const { return true; } + virtual bool hasDType() const override { return true; } }; class AstTaskRef : public AstNodeFTaskRef { @@ -3022,7 +3043,7 @@ public: AstFuncRef(FileLine* fl, const string& name, AstNode* pinsp) : ASTGEN_SUPER(fl, false, name, pinsp) {} ASTNODE_NODE_FUNCS(FuncRef) - virtual bool hasDType() const { return true; } + virtual bool hasDType() const override { return true; } }; class AstDpiExport : public AstNode { @@ -3035,11 +3056,11 @@ private: public: AstDpiExport(FileLine* fl, const string& vname, const string& cname) : ASTGEN_SUPER(fl) - , m_name(vname) - , m_cname(cname) {} + , m_name{vname} + , m_cname{cname} {} ASTNODE_NODE_FUNCS(DpiExport) - virtual string name() const { return m_name; } - virtual void name(const string& name) { m_name = name; } + virtual string name() const override { return m_name; } + virtual void name(const string& name) override { m_name = name; } string cname() const { return m_cname; } void cname(const string& cname) { m_cname = cname; } }; @@ -3053,8 +3074,8 @@ public: addNOp2p(argsp); } ASTNODE_NODE_FUNCS(With) - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } // AstNode* funcrefp() const { return op1p(); } }; @@ -3074,33 +3095,28 @@ public: class Never {}; // for creator type-overload selection AstSenItem(FileLine* fl, VEdgeType edgeType, AstNode* varrefp) : ASTGEN_SUPER(fl) - , m_edgeType(edgeType) { + , m_edgeType{edgeType} { setOp1p(varrefp); } AstSenItem(FileLine* fl, Combo) - : ASTGEN_SUPER(fl) { - m_edgeType = VEdgeType::ET_COMBO; - } + : ASTGEN_SUPER(fl) + , m_edgeType{VEdgeType::ET_COMBO} {} AstSenItem(FileLine* fl, Illegal) - : ASTGEN_SUPER(fl) { - m_edgeType = VEdgeType::ET_ILLEGAL; - } + : ASTGEN_SUPER(fl) + , m_edgeType{VEdgeType::ET_ILLEGAL} {} AstSenItem(FileLine* fl, Initial) - : ASTGEN_SUPER(fl) { - m_edgeType = VEdgeType::ET_INITIAL; - } + : ASTGEN_SUPER(fl) + , m_edgeType{VEdgeType::ET_INITIAL} {} AstSenItem(FileLine* fl, Settle) - : ASTGEN_SUPER(fl) { - m_edgeType = VEdgeType::ET_SETTLE; - } + : ASTGEN_SUPER(fl) + , m_edgeType{VEdgeType::ET_SETTLE} {} AstSenItem(FileLine* fl, Never) - : ASTGEN_SUPER(fl) { - m_edgeType = VEdgeType::ET_NEVER; - } + : ASTGEN_SUPER(fl) + , m_edgeType{VEdgeType::ET_NEVER} {} ASTNODE_NODE_FUNCS(SenItem) - virtual void dump(std::ostream& str) const; - virtual V3Hash sameHash() const { return V3Hash(edgeType()); } - virtual bool same(const AstNode* samep) const { + virtual void dump(std::ostream& str) const override; + virtual V3Hash sameHash() const override { return V3Hash(edgeType()); } + virtual bool same(const AstNode* samep) const override { return edgeType() == static_cast(samep)->edgeType(); } VEdgeType edgeType() const { return m_edgeType; } // * = Posedge/negedge @@ -3127,17 +3143,16 @@ class AstSenTree : public AstNode { // Parents: MODULE | SBLOCK // Children: SENITEM list private: - bool m_multi; // Created from combo logic by ORing multiple clock domains + bool m_multi = false; // Created from combo logic by ORing multiple clock domains public: AstSenTree(FileLine* fl, AstSenItem* sensesp) - : ASTGEN_SUPER(fl) - , m_multi(false) { + : ASTGEN_SUPER(fl) { addNOp1p(sensesp); } ASTNODE_NODE_FUNCS(SenTree) - virtual void dump(std::ostream& str) const; - virtual bool maybePointedTo() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(); } + virtual void dump(std::ostream& str) const override; + virtual bool maybePointedTo() const override { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } bool isMulti() const { return m_multi; } // op1 = Sensitivity list AstSenItem* sensesp() const { return VN_CAST(op1p(), SenItem); } @@ -3170,12 +3185,12 @@ class AstAlways : public AstNodeProcedure { public: AstAlways(FileLine* fl, VAlwaysKwd keyword, AstSenTree* sensesp, AstNode* bodysp) : ASTGEN_SUPER(fl, bodysp) - , m_keyword(keyword) { + , m_keyword{keyword} { addNOp1p(sensesp); } ASTNODE_NODE_FUNCS(Always) // - virtual void dump(std::ostream& str) const; + virtual void dump(std::ostream& str) const override; AstSenTree* sensesp() const { return VN_CAST(op1p(), SenTree); } // op1 = Sensitivity list void sensesp(AstSenTree* nodep) { setOp1p(nodep); } VAlwaysKwd keyword() const { return m_keyword; } @@ -3191,8 +3206,8 @@ public: addNOp2p(bodysp); } ASTNODE_NODE_FUNCS(AlwaysPublic) - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } // AstSenTree* sensesp() const { return VN_CAST(op1p(), SenTree); } // op1 = Sensitivity list AstNode* bodysp() const { return op2p(); } // op2 = Statements to evaluate @@ -3222,10 +3237,10 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(Assign) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssign(this->fileline(), lhsp, rhsp); } - virtual bool brokeLhsMustBeLvalue() const { return true; } + virtual bool brokeLhsMustBeLvalue() const override { return true; } }; class AstAssignAlias : public AstNodeAssign { @@ -3235,8 +3250,10 @@ public: AstAssignAlias(FileLine* fl, AstVarRef* lhsp, AstVarRef* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(AssignAlias) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { V3ERROR_NA_RETURN(NULL); } - virtual bool brokeLhsMustBeLvalue() const { return false; } + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + V3ERROR_NA_RETURN(nullptr); + } + virtual bool brokeLhsMustBeLvalue() const override { return false; } }; class AstAssignDly : public AstNodeAssign { @@ -3244,12 +3261,12 @@ public: AstAssignDly(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(AssignDly) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignDly(this->fileline(), lhsp, rhsp); } - virtual bool isGateOptimizable() const { return false; } - virtual string verilogKwd() const { return "<="; } - virtual bool brokeLhsMustBeLvalue() const { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual string verilogKwd() const override { return "<="; } + virtual bool brokeLhsMustBeLvalue() const override { return true; } }; class AstAssignW : public AstNodeAssign { @@ -3258,14 +3275,14 @@ public: AstAssignW(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(AssignW) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignW(this->fileline(), lhsp, rhsp); } - virtual bool brokeLhsMustBeLvalue() const { return true; } + virtual bool brokeLhsMustBeLvalue() const override { return true; } AstAlways* convertToAlways() { AstNode* lhs1p = lhsp()->unlinkFrBack(); AstNode* rhs1p = rhsp()->unlinkFrBack(); - AstAlways* newp = new AstAlways(fileline(), VAlwaysKwd::ALWAYS, NULL, + AstAlways* newp = new AstAlways(fileline(), VAlwaysKwd::ALWAYS, nullptr, new AstAssign(fileline(), lhs1p, rhs1p)); replaceWith(newp); // User expected to then deleteTree(); return newp; @@ -3280,10 +3297,10 @@ public: dtypeFrom(rhsp); } ASTNODE_NODE_FUNCS(AssignVarScope) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignVarScope(this->fileline(), lhsp, rhsp); } - virtual bool brokeLhsMustBeLvalue() const { return false; } + virtual bool brokeLhsMustBeLvalue() const override { return false; } }; class AstPull : public AstNode { @@ -3297,7 +3314,7 @@ public: m_direction = direction; } ASTNODE_NODE_FUNCS(Pull) - virtual bool same(const AstNode* samep) const { + virtual bool same(const AstNode* samep) const override { return direction() == static_cast(samep)->direction(); } void lhsp(AstNode* np) { setOp1p(np); } @@ -3311,10 +3328,10 @@ public: AstAssignPre(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(AssignPre) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignPre(this->fileline(), lhsp, rhsp); } - virtual bool brokeLhsMustBeLvalue() const { return true; } + virtual bool brokeLhsMustBeLvalue() const override { return true; } }; class AstAssignPost : public AstNodeAssign { @@ -3323,10 +3340,10 @@ public: AstAssignPost(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(AssignPost) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAssignPost(this->fileline(), lhsp, rhsp); } - virtual bool brokeLhsMustBeLvalue() const { return true; } + virtual bool brokeLhsMustBeLvalue() const override { return true; } }; class AstComment : public AstNodeStmt { @@ -3339,12 +3356,14 @@ private: public: AstComment(FileLine* fl, const string& name, bool showAt = false) : ASTGEN_SUPER(fl) - , m_showAt(showAt) - , m_name(name) {} + , m_showAt{showAt} + , m_name{name} {} ASTNODE_NODE_FUNCS(Comment) - virtual string name() const { return m_name; } // * = Text - virtual V3Hash sameHash() const { return V3Hash(); } // Ignore name in comments - virtual bool same(const AstNode* samep) const { return true; } // Ignore name in comments + virtual string name() const override { return m_name; } // * = Text + virtual V3Hash sameHash() const override { return V3Hash(); } // Ignore name in comments + virtual bool same(const AstNode* samep) const override { + return true; + } // Ignore name in comments virtual bool showAt() const { return m_showAt; } }; @@ -3356,7 +3375,7 @@ public: AstCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) : ASTGEN_SUPER(fl, condp, expr1p, expr2p) {} ASTNODE_NODE_FUNCS(Cond) - virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) { + virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) override { return new AstCond(this->fileline(), condp, expr1p, expr2p); } }; @@ -3369,7 +3388,7 @@ public: AstCondBound(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p) : ASTGEN_SUPER(fl, condp, expr1p, expr2p) {} ASTNODE_NODE_FUNCS(CondBound) - virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) { + virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) override { return new AstCondBound(this->fileline(), condp, expr1p, expr2p); } }; @@ -3396,22 +3415,22 @@ public: m_linescov = linescov; m_offset = offset; m_binNum = 0; - m_dataDeclp = NULL; + m_dataDeclp = nullptr; } ASTNODE_NODE_FUNCS(CoverDecl) - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(m_dataDeclp && !m_dataDeclp->brokeExists()); if (m_dataDeclp && m_dataDeclp->m_dataDeclp) { // Avoid O(n^2) accessing v3fatalSrc("dataDeclp should point to real data, not be a list"); } - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_dataDeclp && m_dataDeclp->clonep()) m_dataDeclp = m_dataDeclp->clonep(); } - virtual void dump(std::ostream& str) const; - virtual int instrCount() const { return 1 + 2 * instrCountLd(); } - virtual bool maybePointedTo() const { return true; } + virtual void dump(std::ostream& str) const override; + virtual int instrCount() const override { return 1 + 2 * instrCountLd(); } + virtual bool maybePointedTo() const override { return true; } void binNum(int flag) { m_binNum = flag; } int binNum() const { return m_binNum; } int offset() const { return m_offset; } @@ -3421,15 +3440,15 @@ public: const string& hier() const { return m_hier; } void hier(const string& flag) { m_hier = flag; } void comment(const string& flag) { m_text = flag; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { const AstCoverDecl* asamep = static_cast(samep); return (fileline() == asamep->fileline() && linescov() == asamep->linescov() && hier() == asamep->hier() && comment() == asamep->comment()); } - virtual bool isPredictOptimizable() const { return false; } + virtual bool isPredictOptimizable() const override { return false; } void dataDeclp(AstCoverDecl* nodep) { m_dataDeclp = nodep; } - // dataDecl NULL means "use this one", but often you want "this" to + // dataDecl nullptr means "use this one", but often you want "this" to // indicate to get data from here AstCoverDecl* dataDeclNullp() const { return m_dataDeclp; } AstCoverDecl* dataDeclThisp() { return dataDeclNullp() ? dataDeclNullp() : this; } @@ -3443,26 +3462,25 @@ private: AstCoverDecl* m_declp; // [After V3Coverage] Pointer to declaration public: AstCoverInc(FileLine* fl, AstCoverDecl* declp) - : ASTGEN_SUPER(fl) { - m_declp = declp; - } + : ASTGEN_SUPER(fl) + , m_declp{declp} {} ASTNODE_NODE_FUNCS(CoverInc) - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(!declp()->brokeExists()); - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_declp->clonep()) m_declp = m_declp->clonep(); } - virtual void dump(std::ostream& str) const; - virtual int instrCount() const { return 1 + 2 * instrCountLd(); } - virtual V3Hash sameHash() const { return V3Hash(declp()); } - virtual bool same(const AstNode* samep) const { + virtual void dump(std::ostream& str) const override; + virtual int instrCount() const override { return 1 + 2 * instrCountLd(); } + virtual V3Hash sameHash() const override { return V3Hash(declp()); } + virtual bool same(const AstNode* samep) const override { return declp() == static_cast(samep)->declp(); } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isOutputter() const { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isOutputter() const override { return true; } // but isPure() true AstCoverDecl* declp() const { return m_declp; } // Where defined }; @@ -3479,12 +3497,12 @@ public: setOp3p(changep); } ASTNODE_NODE_FUNCS(CoverToggle) - virtual int instrCount() const { return 3 + instrCountBranch() + instrCountLd(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return true; } - virtual bool isOutputter() const { + virtual int instrCount() const override { return 3 + instrCountBranch() + instrCountLd(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return true; } + virtual bool isOutputter() const override { return false; // Though the AstCoverInc under this is an outputter } // but isPure() true @@ -3502,8 +3520,8 @@ public: setOp1p(lhsp); } ASTNODE_NODE_FUNCS(Delay) - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } // AstNode* lhsp() const { return op1p(); } // op2 = Statements to evaluate void lhsp(AstNode* nodep) { setOp1p(nodep); } @@ -3527,24 +3545,20 @@ class AstCase : public AstNodeCase { // casesp Children: CASEITEMs private: VCaseType m_casex; // 0=case, 1=casex, 2=casez - bool m_fullPragma; // Synthesis full_case - bool m_parallelPragma; // Synthesis parallel_case - bool m_uniquePragma; // unique case - bool m_unique0Pragma; // unique0 case - bool m_priorityPragma; // priority case + bool m_fullPragma = false; // Synthesis full_case + bool m_parallelPragma = false; // Synthesis parallel_case + bool m_uniquePragma = false; // unique case + bool m_unique0Pragma = false; // unique0 case + bool m_priorityPragma = false; // priority case public: AstCase(FileLine* fl, VCaseType casex, AstNode* exprp, AstNode* casesp) - : ASTGEN_SUPER(fl, exprp, casesp) { - m_casex = casex; - m_fullPragma = false; - m_parallelPragma = false; - m_uniquePragma = false; - m_unique0Pragma = false; - m_priorityPragma = false; - } + : ASTGEN_SUPER(fl, exprp, casesp) + , m_casex{casex} {} ASTNODE_NODE_FUNCS(Case) - virtual string verilogKwd() const { return casez() ? "casez" : casex() ? "casex" : "case"; } - virtual bool same(const AstNode* samep) const { + virtual string verilogKwd() const override { + return casez() ? "casez" : casex() ? "casex" : "case"; + } + virtual bool same(const AstNode* samep) const override { return m_casex == static_cast(samep)->m_casex; } bool casex() const { return m_casex == VCaseType::CT_CASEX; } @@ -3570,21 +3584,20 @@ class AstCaseItem : public AstNode { // condsp Children: MATH (Null condition used for default block) // bodysp Children: Statements private: - bool m_ignoreOverlap; // Default created by assertions; ignore overlaps + bool m_ignoreOverlap = false; // Default created by assertions; ignore overlaps public: AstCaseItem(FileLine* fl, AstNode* condsp, AstNode* bodysp) : ASTGEN_SUPER(fl) { addNOp1p(condsp); addNOp2p(bodysp); - m_ignoreOverlap = false; } ASTNODE_NODE_FUNCS(CaseItem) - virtual int instrCount() const { return widthInstrs() + instrCountBranch(); } + virtual int instrCount() const override { return widthInstrs() + instrCountBranch(); } AstNode* condsp() const { return op1p(); } // op1 = list of possible matching expressions AstNode* bodysp() const { return op2p(); } // op2 = what to do void condsp(AstNode* nodep) { setOp1p(nodep); } void addBodysp(AstNode* newp) { addOp2p(newp); } - bool isDefault() const { return condsp() == NULL; } + bool isDefault() const { return condsp() == nullptr; } bool ignoreOverlap() const { return m_ignoreOverlap; } void ignoreOverlap(bool flag) { m_ignoreOverlap = flag; } }; @@ -3602,34 +3615,34 @@ public: AstSFormatF(FileLine* fl, const string& text, bool hidden, AstNode* exprsp, char missingArgChar = 'd') : ASTGEN_SUPER(fl) - , m_text(text) - , m_hidden(hidden) - , m_hasFormat(true) - , m_missingArgChar(missingArgChar) { + , m_text{text} + , m_hidden{hidden} + , m_hasFormat{true} + , m_missingArgChar{missingArgChar} { dtypeSetString(); addNOp1p(exprsp); - addNOp2p(NULL); + addNOp2p(nullptr); } AstSFormatF(FileLine* fl, NoFormat, AstNode* exprsp, char missingArgChar = 'd', bool hidden = true) : ASTGEN_SUPER(fl) - , m_text("") - , m_hidden(hidden) - , m_hasFormat(false) - , m_missingArgChar(missingArgChar) { + , m_text{""} + , m_hidden{hidden} + , m_hasFormat{false} + , m_missingArgChar{missingArgChar} { dtypeSetString(); addNOp1p(exprsp); - addNOp2p(NULL); + addNOp2p(nullptr); } ASTNODE_NODE_FUNCS(SFormatF) - virtual string name() const { return m_text; } - virtual int instrCount() const { return instrCountPli(); } - virtual V3Hash sameHash() const { return V3Hash(text()); } - virtual bool hasDType() const { return true; } - virtual bool same(const AstNode* samep) const { + virtual string name() const override { return m_text; } + virtual int instrCount() const override { return instrCountPli(); } + virtual V3Hash sameHash() const override { return V3Hash(text()); } + virtual bool hasDType() const override { return true; } + virtual bool same(const AstNode* samep) const override { return text() == static_cast(samep)->text(); } - virtual string verilogKwd() const { return "$sformatf"; } + virtual string verilogKwd() const override { return "$sformatf"; } void addExprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output string text() const { return m_text; } // * = Text to display @@ -3670,25 +3683,27 @@ public: m_displayType = dispType; } ASTNODE_NODE_FUNCS(Display) - virtual void dump(std::ostream& str) const; - virtual const char* broken() const { + virtual void dump(std::ostream& str) const override; + virtual const char* broken() const override { BROKEN_RTN(!fmtp()); - return NULL; + return nullptr; } - virtual string verilogKwd() const { + virtual string verilogKwd() const override { return (filep() ? string("$f") + string(displayType().ascii()) : string("$") + string(displayType().ascii())); } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } // SPECIAL: $display has 'visual' ordering - virtual bool isOutputter() const { return true; } // SPECIAL: $display makes output - virtual bool isUnlikely() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(displayType()); } - virtual bool same(const AstNode* samep) const { + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { + return false; + } // SPECIAL: $display has 'visual' ordering + virtual bool isOutputter() const override { return true; } // SPECIAL: $display makes output + virtual bool isUnlikely() const override { return true; } + virtual V3Hash sameHash() const override { return V3Hash(displayType()); } + virtual bool same(const AstNode* samep) const override { return displayType() == static_cast(samep)->displayType(); } - virtual int instrCount() const { return instrCountPli(); } + virtual int instrCount() const override { return instrCountPli(); } AstDisplayType displayType() const { return m_displayType; } void displayType(AstDisplayType type) { m_displayType = type; } // * = Add a newline for $display @@ -3705,22 +3720,20 @@ class AstDumpCtl : public AstNodeStmt { // Child: expr based on type of control statement VDumpCtlType m_ctlType; // Type of operation public: - AstDumpCtl(FileLine* fl, VDumpCtlType ctlType, AstNode* exprp = NULL) + AstDumpCtl(FileLine* fl, VDumpCtlType ctlType, AstNode* exprp = nullptr) : ASTGEN_SUPER(fl) - , m_ctlType(ctlType) { + , m_ctlType{ctlType} { setNOp1p(exprp); } ASTNODE_NODE_FUNCS(DumpCtl) - virtual string verilogKwd() const { return ctlType().ascii(); } - virtual string emitVerilog() { return "%f" + verilogKwd() + "(%l)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const { return false; } - virtual bool isHeavy() const { return true; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isOutputter() const { return true; } + virtual string verilogKwd() const override { return ctlType().ascii(); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isHeavy() const override { return true; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isOutputter() const override { return true; } virtual bool cleanOut() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } VDumpCtlType ctlType() const { return m_ctlType; } AstNode* exprp() const { return op1p(); } // op2 = Expressions to output void exprp(AstNode* nodep) { setOp1p(nodep); } @@ -3739,21 +3752,25 @@ public: m_displayType = dispType; } ASTNODE_NODE_FUNCS(ElabDisplay) - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(!fmtp()); - return NULL; + return nullptr; } - virtual string verilogKwd() const { return (string("$") + string(displayType().ascii())); } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } // SPECIAL: $display has 'visual' ordering - virtual bool isOutputter() const { return true; } // SPECIAL: $display makes output - virtual bool isUnlikely() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(displayType()); } - virtual bool same(const AstNode* samep) const { + virtual string verilogKwd() const override { + return (string("$") + string(displayType().ascii())); + } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { + return false; + } // SPECIAL: $display has 'visual' ordering + virtual bool isOutputter() const override { return true; } // SPECIAL: $display makes output + virtual bool isUnlikely() const override { return true; } + virtual V3Hash sameHash() const override { return V3Hash(displayType()); } + virtual bool same(const AstNode* samep) const override { return displayType() == static_cast(samep)->displayType(); } - virtual int instrCount() const { return instrCountPli(); } + virtual int instrCount() const override { return instrCountPli(); } AstDisplayType displayType() const { return m_displayType; } void displayType(AstDisplayType type) { m_displayType = type; } void fmtp(AstSFormatF* nodep) { addOp1p(nodep); } // op1 = To-String formatter @@ -3777,21 +3794,19 @@ public: setOp3p(lhsp); } ASTNODE_NODE_FUNCS(SFormat) - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(!fmtp()); - return NULL; + return nullptr; } - virtual string verilogKwd() const { return "$sformat"; } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return true; } - virtual bool isPure() const { return true; } - virtual bool isOutputter() const { return false; } + virtual string verilogKwd() const override { return "$sformat"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return true; } + virtual bool isPure() const override { return true; } + virtual bool isOutputter() const override { return false; } virtual bool cleanOut() const { return false; } - virtual int instrCount() const { return instrCountPli(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual int instrCount() const override { return instrCountPli(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } void fmtp(AstSFormatF* nodep) { addOp1p(nodep); } // op1 = To-String formatter AstSFormatF* fmtp() const { return VN_CAST(op1p(), SFormatF); } AstNode* lhsp() const { return op3p(); } @@ -3808,14 +3823,14 @@ public: addNOp1p(exprsp); } ASTNODE_NODE_FUNCS(SysFuncAsTask) - virtual string verilogKwd() const { return ""; } - virtual bool isGateOptimizable() const { return true; } - virtual bool isPredictOptimizable() const { return true; } - virtual bool isPure() const { return true; } - virtual bool isOutputter() const { return false; } - virtual int instrCount() const { return 0; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual string verilogKwd() const override { return ""; } + virtual bool isGateOptimizable() const override { return true; } + virtual bool isPredictOptimizable() const override { return true; } + virtual bool isPure() const override { return true; } + virtual bool isOutputter() const override { return false; } + virtual int instrCount() const override { return 0; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } AstNode* lhsp() const { return op1p(); } // op1 = Expressions to eval void lhsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to eval }; @@ -3829,12 +3844,14 @@ public: addNOp1p(exprsp); } ASTNODE_NODE_FUNCS(SysIgnore) - virtual string verilogKwd() const { return "$ignored"; } - virtual bool isGateOptimizable() const { return false; } // Though deleted before opt - virtual bool isPredictOptimizable() const { return false; } // Though deleted before opt - virtual bool isPure() const { return false; } // Though deleted before opt - virtual bool isOutputter() const { return true; } // Though deleted before opt - virtual int instrCount() const { return instrCountPli(); } + virtual string verilogKwd() const override { return "$ignored"; } + virtual bool isGateOptimizable() const override { return false; } // Though deleted before opt + virtual bool isPredictOptimizable() const override { + return false; + } // Though deleted before opt + virtual bool isPure() const override { return false; } // Though deleted before opt + virtual bool isOutputter() const override { return true; } // Though deleted before opt + virtual int instrCount() const override { return instrCountPli(); } AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output void exprsp(AstNode* nodep) { addOp1p(nodep); } // op1 = Expressions to output }; @@ -3848,14 +3865,14 @@ public: setNOp2p(filep); } ASTNODE_NODE_FUNCS(FClose) - virtual string verilogKwd() const { return "$fclose"; } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } - virtual bool isOutputter() const { return true; } - virtual bool isUnlikely() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual string verilogKwd() const override { return "$fclose"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool isUnlikely() const override { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } AstNode* filep() const { return op2p(); } void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); } }; @@ -3870,15 +3887,15 @@ public: setOp3p(modep); } ASTNODE_NODE_FUNCS(FOpen) - virtual string verilogKwd() const { return "$fopen"; } - virtual bool isGateOptimizable() const { return false; } - virtual bool isHeavy() const { return true; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } - virtual bool isOutputter() const { return true; } - virtual bool isUnlikely() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual string verilogKwd() const override { return "$fopen"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isHeavy() const override { return true; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool isUnlikely() const override { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } AstNode* filep() const { return op1p(); } AstNode* filenamep() const { return op2p(); } AstNode* modep() const { return op3p(); } @@ -3893,15 +3910,15 @@ public: setOp2p(filenamep); } ASTNODE_NODE_FUNCS(FOpenMcd) - virtual string verilogKwd() const { return "$fopen"; } - virtual bool isGateOptimizable() const { return false; } - virtual bool isHeavy() const { return true; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } - virtual bool isOutputter() const { return true; } - virtual bool isUnlikely() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual string verilogKwd() const override { return "$fopen"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isHeavy() const override { return true; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool isUnlikely() const override { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } AstNode* filep() const { return op1p(); } AstNode* filenamep() const { return op2p(); } }; @@ -3915,14 +3932,14 @@ public: setNOp2p(filep); } ASTNODE_NODE_FUNCS(FFlush) - virtual string verilogKwd() const { return "$fflush"; } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } - virtual bool isOutputter() const { return true; } - virtual bool isUnlikely() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual string verilogKwd() const override { return "$fflush"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool isUnlikely() const override { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } AstNode* filep() const { return op2p(); } void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); } }; @@ -3942,16 +3959,16 @@ public: setNOp4p(countp); } ASTNODE_NODE_FUNCS(FRead) - virtual string verilogKwd() const { return "$fread"; } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } // SPECIAL: has 'visual' ordering - virtual bool isOutputter() const { return true; } // SPECIAL: makes output - virtual bool cleanOut() const { return false; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual string verilogKwd() const override { return "$fread"; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering + virtual bool isOutputter() const override { return true; } // SPECIAL: makes output + virtual bool cleanOut() const override { return false; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } AstNode* memp() const { return op1p(); } void memp(AstNode* nodep) { setOp1p(nodep); } AstNode* filep() const { return op2p(); } @@ -3971,17 +3988,17 @@ public: setNOp2p(filep); } ASTNODE_NODE_FUNCS(FRewind) - virtual string verilogKwd() const { return "$frewind"; } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } - virtual bool isOutputter() const { return true; } - virtual bool isUnlikely() const { return true; } - virtual bool cleanOut() const { return false; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual string verilogKwd() const override { return "$frewind"; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool isUnlikely() const override { return true; } + virtual bool cleanOut() const override { return false; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } AstNode* filep() const { return op2p(); } void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); } }; @@ -3995,17 +4012,17 @@ public: setNOp2p(filep); } ASTNODE_NODE_FUNCS(FTell) - virtual string verilogKwd() const { return "$ftell"; } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } - virtual bool isOutputter() const { return true; } - virtual bool isUnlikely() const { return true; } - virtual bool cleanOut() const { return false; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual string verilogKwd() const override { return "$ftell"; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool isUnlikely() const override { return true; } + virtual bool cleanOut() const override { return false; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } AstNode* filep() const { return op2p(); } void filep(AstNodeVarRef* nodep) { setNOp2p(nodep); } }; @@ -4023,16 +4040,16 @@ public: setNOp4p(operation); } ASTNODE_NODE_FUNCS(FSeek) - virtual string verilogKwd() const { return "$fseek"; } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } // SPECIAL: has 'visual' ordering - virtual bool isOutputter() const { return true; } // SPECIAL: makes output - virtual bool cleanOut() const { return false; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual string verilogKwd() const override { return "$fseek"; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering + virtual bool isOutputter() const override { return true; } // SPECIAL: makes output + virtual bool cleanOut() const override { return false; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } AstNode* filep() const { return op2p(); } void filep(AstNode* nodep) { setOp2p(nodep); } AstNode* offset() const { return op3p(); } @@ -4051,22 +4068,22 @@ private: public: AstFScanF(FileLine* fl, const string& text, AstNode* filep, AstNode* exprsp) : ASTGEN_SUPER(fl) - , m_text(text) { + , m_text{text} { addNOp1p(exprsp); setNOp2p(filep); } ASTNODE_NODE_FUNCS(FScanF) - virtual string name() const { return m_text; } - virtual string verilogKwd() const { return "$fscanf"; } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } // SPECIAL: has 'visual' ordering - virtual bool isOutputter() const { return true; } // SPECIAL: makes output - virtual bool cleanOut() const { return false; } - virtual V3Hash sameHash() const { return V3Hash(text()); } - virtual bool same(const AstNode* samep) const { + virtual string name() const override { return m_text; } + virtual string verilogKwd() const override { return "$fscanf"; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering + virtual bool isOutputter() const override { return true; } // SPECIAL: makes output + virtual bool cleanOut() const override { return false; } + virtual V3Hash sameHash() const override { return V3Hash(text()); } + virtual bool same(const AstNode* samep) const override { return text() == static_cast(samep)->text(); } AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output @@ -4087,22 +4104,22 @@ private: public: AstSScanF(FileLine* fl, const string& text, AstNode* fromp, AstNode* exprsp) : ASTGEN_SUPER(fl) - , m_text(text) { + , m_text{text} { addNOp1p(exprsp); setOp2p(fromp); } ASTNODE_NODE_FUNCS(SScanF) - virtual string name() const { return m_text; } - virtual string verilogKwd() const { return "$sscanf"; } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } // SPECIAL: has 'visual' ordering - virtual bool isOutputter() const { return true; } // SPECIAL: makes output - virtual bool cleanOut() const { return false; } - virtual V3Hash sameHash() const { return V3Hash(text()); } - virtual bool same(const AstNode* samep) const { + virtual string name() const override { return m_text; } + virtual string verilogKwd() const override { return "$sscanf"; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } // SPECIAL: has 'visual' ordering + virtual bool isOutputter() const override { return true; } // SPECIAL: makes output + virtual bool cleanOut() const override { return false; } + virtual V3Hash sameHash() const override { return V3Hash(text()); } + virtual bool same(const AstNode* samep) const override { return text() == static_cast(samep)->text(); } AstNode* exprsp() const { return op1p(); } // op1 = Expressions to output @@ -4126,14 +4143,14 @@ public: setNOp3p(lsbp); setNOp4p(msbp); } - virtual bool isGateOptimizable() const { return false; } - virtual bool isHeavy() const { return true; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } - virtual bool isOutputter() const { return true; } - virtual bool isUnlikely() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { + virtual bool isGateOptimizable() const override { return false; } + virtual bool isHeavy() const override { return true; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool isUnlikely() const override { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return isHex() == static_cast(samep)->isHex(); } bool isHex() const { return m_isHex; } @@ -4150,8 +4167,8 @@ public: AstNode* msbp) : ASTGEN_SUPER(fl, hex, filenamep, memp, lsbp, msbp) {} ASTNODE_NODE_FUNCS(ReadMem); - virtual string verilogKwd() const { return (isHex() ? "$readmemh" : "$readmemb"); } - virtual const char* cFuncPrefixp() const { return "VL_READMEM_"; } + virtual string verilogKwd() const override { return (isHex() ? "$readmemh" : "$readmemb"); } + virtual const char* cFuncPrefixp() const override { return "VL_READMEM_"; } }; class AstWriteMem : public AstNodeReadWriteMem { @@ -4160,8 +4177,8 @@ public: AstNode* msbp) : ASTGEN_SUPER(fl, hex, filenamep, memp, lsbp, msbp) {} ASTNODE_NODE_FUNCS(WriteMem) - virtual string verilogKwd() const { return (isHex() ? "$writememh" : "$writememb"); } - virtual const char* cFuncPrefixp() const { return "VL_WRITEMEM_"; } + virtual string verilogKwd() const override { return (isHex() ? "$writememh" : "$writememb"); } + virtual const char* cFuncPrefixp() const override { return "VL_WRITEMEM_"; } }; class AstSystemT : public AstNodeStmt { @@ -4172,14 +4189,14 @@ public: setOp1p(lhsp); } ASTNODE_NODE_FUNCS(SystemT) - virtual string verilogKwd() const { return "$system"; } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } - virtual bool isOutputter() const { return true; } - virtual bool isUnlikely() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual string verilogKwd() const override { return "$system"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool isUnlikely() const override { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } AstNode* lhsp() const { return op1p(); } }; @@ -4191,23 +4208,23 @@ public: setOp1p(lhsp); } ASTNODE_NODE_FUNCS(SystemF) - virtual string verilogKwd() const { return "$system"; } - virtual string emitVerilog() { return verilogKwd(); } - virtual string emitC() { return "VL_SYSTEM_%nq(%lw, %P)"; } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } - virtual bool isOutputter() const { return true; } - virtual bool isUnlikely() const { return true; } - virtual bool cleanOut() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual string verilogKwd() const override { return "$system"; } + virtual string emitVerilog() override { return verilogKwd(); } + virtual string emitC() override { return "VL_SYSTEM_%nq(%lw, %P)"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual bool isUnlikely() const override { return true; } + virtual bool cleanOut() const override { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } AstNode* lhsp() const { return op1p(); } }; class AstValuePlusArgs : public AstNodeMath { // Parents: expr - // Child: variable to set. If NULL then this is a $test$plusargs instead of $value$plusargs + // Child: variable to set. If nullptr then this is a $test$plusargs instead of $value$plusargs public: AstValuePlusArgs(FileLine* fl, AstNode* searchp, AstNode* outp) : ASTGEN_SUPER(fl) { @@ -4215,15 +4232,15 @@ public: setOp2p(outp); } ASTNODE_NODE_FUNCS(ValuePlusArgs) - virtual string verilogKwd() const { return "$value$plusargs"; } - virtual string emitVerilog() { return "%f$value$plusargs(%l, %k%r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool isGateOptimizable() const { return false; } - virtual bool isHeavy() const { return true; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool cleanOut() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual string verilogKwd() const override { return "$value$plusargs"; } + virtual string emitVerilog() override { return "%f$value$plusargs(%l, %k%r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isHeavy() const override { return true; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool cleanOut() const override { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } AstNode* searchp() const { return op1p(); } // op1 = Search expression void searchp(AstNode* nodep) { setOp1p(nodep); } AstNode* outp() const { return op2p(); } // op2 = Expressions to output @@ -4232,24 +4249,24 @@ public: class AstTestPlusArgs : public AstNodeMath { // Parents: expr - // Child: variable to set. If NULL then this is a $test$plusargs instead of $value$plusargs + // Child: variable to set. If nullptr then this is a $test$plusargs instead of $value$plusargs private: string m_text; public: AstTestPlusArgs(FileLine* fl, const string& text) : ASTGEN_SUPER(fl) - , m_text(text) {} + , m_text{text} {} ASTNODE_NODE_FUNCS(TestPlusArgs) - virtual string name() const { return m_text; } - virtual string verilogKwd() const { return "$test$plusargs"; } - virtual string emitVerilog() { return verilogKwd(); } - virtual string emitC() { return "VL_VALUEPLUSARGS_%nq(%lw, %P, NULL)"; } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool cleanOut() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(text()); } - virtual bool same(const AstNode* samep) const { + virtual string name() const override { return m_text; } + virtual string verilogKwd() const override { return "$test$plusargs"; } + virtual string emitVerilog() override { return verilogKwd(); } + virtual string emitC() override { return "VL_VALUEPLUSARGS_%nq(%lw, %P, nullptr)"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool cleanOut() const override { return true; } + virtual V3Hash sameHash() const override { return V3Hash(text()); } + virtual bool same(const AstNode* samep) const override { return text() == static_cast(samep)->text(); } string text() const { return m_text; } // * = Text to display @@ -4273,10 +4290,10 @@ public: ASTNODE_NODE_FUNCS(Foreach) AstNode* arrayp() const { return op1p(); } // op1 = array and index vars AstNode* bodysp() const { return op4p(); } // op4 = body of loop - virtual bool isGateOptimizable() const { return false; } - virtual int instrCount() const { return instrCountBranch(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual int instrCount() const override { return instrCountBranch(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } }; class AstRepeat : public AstNodeStmt { @@ -4289,10 +4306,12 @@ public: ASTNODE_NODE_FUNCS(Repeat) AstNode* countp() const { return op2p(); } // op2 = condition to continue AstNode* bodysp() const { return op3p(); } // op3 = body of loop - virtual bool isGateOptimizable() const { return false; } // Not relevant - converted to FOR - virtual int instrCount() const { return instrCountBranch(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual bool isGateOptimizable() const override { + return false; + } // Not relevant - converted to FOR + virtual int instrCount() const override { return instrCountBranch(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } }; class AstWait : public AstNodeStmt { @@ -4308,7 +4327,7 @@ public: class AstWhile : public AstNodeStmt { public: - AstWhile(FileLine* fl, AstNode* condp, AstNode* bodysp, AstNode* incsp = NULL) + AstWhile(FileLine* fl, AstNode* condp, AstNode* bodysp, AstNode* incsp = nullptr) : ASTGEN_SUPER(fl) { setOp2p(condp); addNOp3p(bodysp); @@ -4323,12 +4342,14 @@ public: void addPrecondsp(AstNode* newp) { addOp1p(newp); } void addBodysp(AstNode* newp) { addOp3p(newp); } void addIncsp(AstNode* newp) { addOp4p(newp); } - virtual bool isGateOptimizable() const { return false; } - virtual int instrCount() const { return instrCountBranch(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } - virtual void addBeforeStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here - virtual void addNextStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here + virtual bool isGateOptimizable() const override { return false; } + virtual int instrCount() const override { return instrCountBranch(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } + // Stop statement searchback here + virtual void addBeforeStmt(AstNode* newp, AstNode* belowp) override; + // Stop statement searchback here + virtual void addNextStmt(AstNode* newp, AstNode* belowp) override; }; class AstBreak : public AstNodeStmt { @@ -4336,9 +4357,9 @@ public: explicit AstBreak(FileLine* fl) : ASTGEN_SUPER(fl) {} ASTNODE_NODE_FUNCS(Break) - virtual string verilogKwd() const { return "break"; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool isBrancher() const { + virtual string verilogKwd() const override { return "break"; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool isBrancher() const override { return true; // SPECIAL: We don't process code after breaks } }; @@ -4348,9 +4369,9 @@ public: explicit AstContinue(FileLine* fl) : ASTGEN_SUPER(fl) {} ASTNODE_NODE_FUNCS(Continue) - virtual string verilogKwd() const { return "continue"; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool isBrancher() const { + virtual string verilogKwd() const override { return "continue"; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool isBrancher() const override { return true; // SPECIAL: We don't process code after breaks } }; @@ -4361,11 +4382,11 @@ private: public: AstDisable(FileLine* fl, const string& name) : ASTGEN_SUPER(fl) - , m_name(name) {} + , m_name{name} {} ASTNODE_NODE_FUNCS(Disable) - virtual string name() const { return m_name; } // * = Block name - void name(const string& flag) { m_name = flag; } - virtual bool isBrancher() const { + virtual string name() const override { return m_name; } // * = Block name + virtual void name(const string& flag) override { m_name = flag; } + virtual bool isBrancher() const override { return true; // SPECIAL: We don't process code after breaks } }; @@ -4388,15 +4409,15 @@ public: class AstReturn : public AstNodeStmt { public: - explicit AstReturn(FileLine* fl, AstNode* lhsp = NULL) + explicit AstReturn(FileLine* fl, AstNode* lhsp = nullptr) : ASTGEN_SUPER(fl) { setNOp1p(lhsp); } ASTNODE_NODE_FUNCS(Return) - virtual string verilogKwd() const { return "return"; } - virtual V3Hash sameHash() const { return V3Hash(); } + virtual string verilogKwd() const override { return "return"; } + virtual V3Hash sameHash() const override { return V3Hash(); } AstNode* lhsp() const { return op1p(); } - virtual bool isBrancher() const { + virtual bool isBrancher() const override { return true; // SPECIAL: We don't process code after breaks } }; @@ -4414,7 +4435,7 @@ private: bool m_unique0Pragma; // unique0 case bool m_priorityPragma; // priority case public: - AstIf(FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp = NULL) + AstIf(FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp = nullptr) : ASTGEN_SUPER(fl, condp, ifsp, elsesp) { m_uniquePragma = false; m_unique0Pragma = false; @@ -4435,21 +4456,20 @@ class AstJumpBlock : public AstNodeStmt { // Children: {statement list, with JumpGo and JumpLabel below} private: AstJumpLabel* m_labelp; // [After V3Jump] Pointer to declaration - int m_labelNum; // Set by V3EmitCSyms to tell final V3Emit what to increment + int m_labelNum = 0; // Set by V3EmitCSyms to tell final V3Emit what to increment public: // After construction must call ->labelp to associate with appropriate label AstJumpBlock(FileLine* fl, AstNode* stmtsp) - : ASTGEN_SUPER(fl) - , m_labelNum(0) { + : ASTGEN_SUPER(fl) { addNOp1p(stmtsp); } - virtual const char* broken() const; - virtual void cloneRelink(); + virtual const char* broken() const override; + virtual void cloneRelink() override; ASTNODE_NODE_FUNCS(JumpBlock) - virtual int instrCount() const { return 0; } - virtual bool maybePointedTo() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual int instrCount() const override { return 0; } + virtual bool maybePointedTo() const override { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } // op1 = Statements AstNode* stmtsp() const { return op1p(); } // op1 = List of statements void addStmtsp(AstNode* nodep) { addNOp1p(nodep); } @@ -4470,21 +4490,21 @@ private: public: AstJumpLabel(FileLine* fl, AstJumpBlock* blockp) : ASTGEN_SUPER(fl) - , m_blockp(blockp) {} + , m_blockp{blockp} {} ASTNODE_NODE_FUNCS(JumpLabel) - virtual bool maybePointedTo() const { return true; } - virtual const char* broken() const { + virtual bool maybePointedTo() const override { return true; } + virtual const char* broken() const override { BROKEN_RTN(!blockp()->brokeExistsAbove()); BROKEN_RTN(blockp()->labelp() != this); - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_blockp->clonep()) m_blockp = m_blockp->clonep(); } - virtual void dump(std::ostream& str) const; - virtual int instrCount() const { return 0; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { + virtual void dump(std::ostream& str) const override; + virtual int instrCount() const override { return 0; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return blockp() == static_cast(samep)->blockp(); } AstJumpBlock* blockp() const { return m_blockp; } @@ -4500,23 +4520,23 @@ private: public: AstJumpGo(FileLine* fl, AstJumpLabel* labelp) : ASTGEN_SUPER(fl) - , m_labelp(labelp) {} + , m_labelp{labelp} {} ASTNODE_NODE_FUNCS(JumpGo); - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(!labelp()->brokeExistsBelow()); - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_labelp->clonep()) m_labelp = m_labelp->clonep(); } - virtual void dump(std::ostream& str) const; - virtual int instrCount() const { return instrCountBranch(); } - virtual V3Hash sameHash() const { return V3Hash(labelp()); } - virtual bool same(const AstNode* samep) const { + virtual void dump(std::ostream& str) const override; + virtual int instrCount() const override { return instrCountBranch(); } + virtual V3Hash sameHash() const override { return V3Hash(labelp()); } + virtual bool same(const AstNode* samep) const override { return labelp() == static_cast(samep)->labelp(); } - virtual bool isGateOptimizable() const { return false; } - virtual bool isBrancher() const { + virtual bool isGateOptimizable() const override { return false; } + virtual bool isBrancher() const override { return true; // SPECIAL: We don't process code after breaks } AstJumpLabel* labelp() const { return m_labelp; } @@ -4533,21 +4553,21 @@ public: dtypeSetUInt32(); // Always used on, and returns word entities } ASTNODE_NODE_FUNCS(ChangeXor) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstChangeXor(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opChangeXor(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f^ %r)"; } - virtual string emitC() { return "VL_CHANGEXOR_%li(%lw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "^"; } - virtual bool cleanOut() const { return false; } // Lclean && Rclean - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs(); } + virtual string emitVerilog() override { return "%k(%l %f^ %r)"; } + virtual string emitC() override { return "VL_CHANGEXOR_%li(%lw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "^"; } + virtual bool cleanOut() const override { return false; } // Lclean && Rclean + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs(); } }; class AstChangeDet : public AstNodeStmt { @@ -4566,11 +4586,11 @@ public: AstNode* lhsp() const { return op1p(); } AstNode* rhsp() const { return op2p(); } bool isClockReq() const { return m_clockReq; } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual int instrCount() const { return widthInstrs(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual int instrCount() const override { return widthInstrs(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } }; class AstBegin : public AstNodeBlock { @@ -4584,12 +4604,11 @@ public: // Node that simply puts name into the output stream AstBegin(FileLine* fl, const string& name, AstNode* stmtsp, bool generate = false, bool implied = false) - : ASTGEN_SUPER(fl, name, stmtsp) { - m_generate = generate; - m_implied = implied; - } + : ASTGEN_SUPER(fl, name, stmtsp) + , m_generate{generate} + , m_implied{implied} {} ASTNODE_NODE_FUNCS(Begin) - virtual void dump(std::ostream& str) const; + virtual void dump(std::ostream& str) const override; // op1p is statements in NodeBlock AstNode* genforp() const { return op2p(); } // op2 = GENFOR, if applicable, // might NOT be a GenFor, as loop unrolling replaces with Begin @@ -4610,7 +4629,7 @@ public: AstFork(FileLine* fl, const string& name, AstNode* stmtsp) : ASTGEN_SUPER(fl, name, stmtsp) {} ASTNODE_NODE_FUNCS(Fork) - virtual void dump(std::ostream& str) const; + virtual void dump(std::ostream& str) const override; VJoinType joinType() const { return m_joinType; } void joinType(const VJoinType& flag) { m_joinType = flag; } }; @@ -4627,9 +4646,9 @@ public: AstNode* exprp() const { return op1p(); } // op1 = LHS expression to compare with // op2 = RHS, possibly a list of expr or AstInsideRange AstNode* itemsp() const { return op2p(); } - virtual string emitVerilog() { return "%l inside { %r }"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return false; } // NA + virtual string emitVerilog() override { return "%l inside { %r }"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } // NA }; class AstInsideRange : public AstNodeMath { @@ -4642,9 +4661,9 @@ public: ASTNODE_NODE_FUNCS(InsideRange) AstNode* lhsp() const { return op1p(); } // op1 = LHS AstNode* rhsp() const { return op2p(); } // op2 = RHS - virtual string emitVerilog() { return "[%l:%r]"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return false; } // NA + virtual string emitVerilog() override { return "[%l:%r]"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } // NA // Create AstAnd(AstGte(...), AstLte(...)) AstNode* newAndFromInside(AstNode* exprp, AstNode* lhsp, AstNode* rhsp); }; @@ -4660,9 +4679,9 @@ public: addOp1p(valuep); } ASTNODE_NODE_FUNCS(InitItem) - virtual bool maybePointedTo() const { return true; } - virtual bool hasDType() const { return false; } // See valuep()'s dtype instead - virtual V3Hash sameHash() const { return V3Hash(); } + virtual bool maybePointedTo() const override { return true; } + virtual bool hasDType() const override { return false; } // See valuep()'s dtype instead + virtual V3Hash sameHash() const override { return V3Hash(); } AstNode* valuep() const { return op1p(); } // op1 = Value void valuep(AstNode* nodep) { addOp1p(nodep); } }; @@ -4686,22 +4705,22 @@ public: addNOp1p(defaultp); } ASTNODE_NODE_FUNCS(InitArray) - virtual void dump(std::ostream& str) const; - virtual const char* broken() const { + virtual void dump(std::ostream& str) const override; + virtual const char* broken() const override { for (KeyItemMap::const_iterator it = m_map.begin(); it != m_map.end(); ++it) { BROKEN_RTN(!VN_IS(it->second, InitItem)); BROKEN_RTN(!it->second->brokeExists()); } - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { for (KeyItemMap::iterator it = m_map.begin(); it != m_map.end(); ++it) { if (it->second->clonep()) it->second = it->second->clonep(); } } - virtual bool hasDType() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { + virtual bool hasDType() const override { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { // Only works if exact same children, instead should override comparison // of children list, and instead use map-vs-map key/value compare return m_map == static_cast(samep)->m_map; @@ -4713,8 +4732,8 @@ public: const KeyItemMap& map() const { return m_map; } AstNode* addIndexValuep(uint32_t index, AstNode* newp) { // Returns old value, caller must garbage collect - AstNode* oldp = NULL; - KeyItemMap::iterator it = m_map.find(index); + AstNode* oldp = nullptr; + const auto it = m_map.find(index); if (it != m_map.end()) { oldp = it->second->valuep(); it->second->valuep(newp); @@ -4726,9 +4745,9 @@ public: return oldp; } AstNode* getIndexValuep(uint32_t index) const { - KeyItemMap::const_iterator it = m_map.find(index); + const auto it = m_map.find(index); if (it == m_map.end()) { - return NULL; + return nullptr; } else { return it->second->valuep(); } @@ -4749,13 +4768,11 @@ public: AstNew(FileLine* fl, AstNode* pinsp) : ASTGEN_SUPER(fl, false, "new", pinsp) {} ASTNODE_NODE_FUNCS(New) - virtual V3Hash sameHash() const { return V3Hash(); } - virtual string emitVerilog() { return "new"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } + virtual V3Hash sameHash() const override { return V3Hash(); } virtual bool cleanOut() const { return true; } - virtual bool same(const AstNode* samep) const { return true; } - virtual bool hasDType() const { return true; } - virtual int instrCount() const { return widthInstrs(); } + virtual bool same(const AstNode* samep) const override { return true; } + virtual bool hasDType() const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } }; class AstNewCopy : public AstNodeMath { @@ -4769,12 +4786,12 @@ public: setNOp1p(rhsp); } ASTNODE_NODE_FUNCS(NewCopy) - virtual V3Hash sameHash() const { return V3Hash(); } - virtual string emitVerilog() { return "new"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return true; } - virtual bool same(const AstNode* samep) const { return true; } - virtual int instrCount() const { return widthInstrs(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual string emitVerilog() override { return "new"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual bool same(const AstNode* samep) const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } AstNode* rhsp() const { return op1p(); } }; @@ -4790,12 +4807,12 @@ public: setNOp2p(rhsp); } ASTNODE_NODE_FUNCS(NewDynamic) - virtual V3Hash sameHash() const { return V3Hash(); } - virtual string emitVerilog() { return "new"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return true; } - virtual bool same(const AstNode* samep) const { return true; } - virtual int instrCount() const { return widthInstrs(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual string emitVerilog() override { return "new"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual bool same(const AstNode* samep) const override { return true; } + virtual int instrCount() const override { return widthInstrs(); } AstNode* sizep() const { return op1p(); } AstNode* rhsp() const { return op2p(); } }; @@ -4807,14 +4824,13 @@ public: // Pragmas don't result in any output code, they're just flags that affect // other processing in verilator. AstPragma(FileLine* fl, AstPragmaType pragType) - : ASTGEN_SUPER(fl) { - m_pragType = pragType; - } + : ASTGEN_SUPER(fl) + , m_pragType{pragType} {} ASTNODE_NODE_FUNCS(Pragma) AstPragmaType pragType() const { return m_pragType; } // *=type of the pragma - virtual V3Hash sameHash() const { return V3Hash(pragType()); } - virtual bool isPredictOptimizable() const { return false; } - virtual bool same(const AstNode* samep) const { + virtual V3Hash sameHash() const override { return V3Hash(pragType()); } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool same(const AstNode* samep) const override { return pragType() == static_cast(samep)->pragType(); } }; @@ -4827,16 +4843,16 @@ public: AstPrintTimeScale(FileLine* fl) : ASTGEN_SUPER(fl) {} ASTNODE_NODE_FUNCS(PrintTimeScale) - virtual void name(const string& name) { m_name = name; } - virtual string name() const { return m_name; } // * = Var name - virtual void dump(std::ostream& str) const; - virtual string verilogKwd() const { return "$printtimescale"; } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } - virtual bool isOutputter() const { return true; } - virtual int instrCount() const { return instrCountPli(); } - virtual V3Hash sameHash() const { return V3Hash(); } + virtual void name(const string& name) override { m_name = name; } + virtual string name() const override { return m_name; } // * = Var name + virtual void dump(std::ostream& str) const override; + virtual string verilogKwd() const override { return "$printtimescale"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual int instrCount() const override { return instrCountPli(); } + virtual V3Hash sameHash() const override { return V3Hash(); } void timeunit(const VTimescale& flag) { m_timeunit = flag; } VTimescale timeunit() const { return m_timeunit; } }; @@ -4846,14 +4862,18 @@ public: AstStop(FileLine* fl, bool maybe) : ASTGEN_SUPER(fl) {} ASTNODE_NODE_FUNCS(Stop) - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } // SPECIAL: $display has 'visual' ordering - virtual bool isOutputter() const { return true; } // SPECIAL: $display makes output - virtual bool isUnlikely() const { return true; } - virtual int instrCount() const { return 0; } // Rarely executes - virtual V3Hash sameHash() const { return V3Hash(fileline()->lineno()); } - virtual bool same(const AstNode* samep) const { return fileline() == samep->fileline(); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { + return false; + } // SPECIAL: $display has 'visual' ordering + virtual bool isOutputter() const override { return true; } // SPECIAL: $display makes output + virtual bool isUnlikely() const override { return true; } + virtual int instrCount() const override { return 0; } // Rarely executes + virtual V3Hash sameHash() const override { return V3Hash(fileline()->lineno()); } + virtual bool same(const AstNode* samep) const override { + return fileline() == samep->fileline(); + } }; class AstFinish : public AstNodeStmt { @@ -4861,14 +4881,18 @@ public: explicit AstFinish(FileLine* fl) : ASTGEN_SUPER(fl) {} ASTNODE_NODE_FUNCS(Finish) - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } // SPECIAL: $display has 'visual' ordering - virtual bool isOutputter() const { return true; } // SPECIAL: $display makes output - virtual bool isUnlikely() const { return true; } - virtual int instrCount() const { return 0; } // Rarely executes - virtual V3Hash sameHash() const { return V3Hash(fileline()->lineno()); } - virtual bool same(const AstNode* samep) const { return fileline() == samep->fileline(); } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { + return false; + } // SPECIAL: $display has 'visual' ordering + virtual bool isOutputter() const override { return true; } // SPECIAL: $display makes output + virtual bool isUnlikely() const override { return true; } + virtual int instrCount() const override { return 0; } // Rarely executes + virtual V3Hash sameHash() const override { return V3Hash(fileline()->lineno()); } + virtual bool same(const AstNode* samep) const override { + return fileline() == samep->fileline(); + } }; class AstNullCheck : public AstNodeUniop { @@ -4880,16 +4904,18 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(NullCheck) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; } - virtual int instrCount() const { return 1; } // Rarely executes - virtual string emitVerilog() { return "%l"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual V3Hash sameHash() const { return V3Hash(fileline()->lineno()); } - virtual bool same(const AstNode* samep) const { return fileline() == samep->fileline(); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } + virtual int instrCount() const override { return 1; } // Rarely executes + virtual string emitVerilog() override { return "%l"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual V3Hash sameHash() const override { return V3Hash(fileline()->lineno()); } + virtual bool same(const AstNode* samep) const override { + return fileline() == samep->fileline(); + } }; class AstTimingControl : public AstNodeStmt { @@ -4901,13 +4927,13 @@ public: setNOp2p(stmtsp); } ASTNODE_NODE_FUNCS(TimingControl) - virtual string verilogKwd() const { return "@(%l) %r"; } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } - virtual bool isOutputter() const { return false; } - virtual int instrCount() const { return 0; } - virtual V3Hash sameHash() const { return V3Hash(); } + virtual string verilogKwd() const override { return "@(%l) %r"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return false; } + virtual int instrCount() const override { return 0; } + virtual V3Hash sameHash() const override { return V3Hash(); } AstSenTree* sensesp() const { return VN_CAST(op1p(), SenTree); } AstNode* stmtsp() const { return op2p(); } }; @@ -4924,13 +4950,13 @@ public: setOp4p(widthp); } ASTNODE_NODE_FUNCS(TimeFormat) - virtual string verilogKwd() const { return "$timeformat"; } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } - virtual bool isOutputter() const { return true; } - virtual int instrCount() const { return instrCountPli(); } - virtual V3Hash sameHash() const { return V3Hash(); } + virtual string verilogKwd() const override { return "$timeformat"; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual int instrCount() const override { return instrCountPli(); } + virtual V3Hash sameHash() const override { return V3Hash(); } AstNode* unitsp() const { return op1p(); } AstNode* precisionp() const { return op2p(); } AstNode* suffixp() const { return op3p(); } @@ -4943,7 +4969,7 @@ class AstTraceDecl : public AstNodeStmt { // Parents: {statement list} // Children: expression being traced private: - uint32_t m_code; // Trace identifier code; converted to ASCII by trace routines + uint32_t m_code = 0; // Trace identifier code; converted to ASCII by trace routines const string m_showname; // Name of variable const VNumRange m_bitRange; // Property of var the trace details const VNumRange m_arrayRange; // Property of var the trace details @@ -4958,26 +4984,25 @@ public: AstNode* valuep, const VNumRange& bitRange, const VNumRange& arrayRange, bool isScoped) : ASTGEN_SUPER(fl) - , m_code(0) - , m_showname(showname) - , m_bitRange(bitRange) - , m_arrayRange(arrayRange) + , m_showname{showname} + , m_bitRange{bitRange} + , m_arrayRange{arrayRange} , m_codeInc( ((arrayRange.ranged() ? arrayRange.elements() : 1) * valuep->dtypep()->widthWords() * (VL_EDATASIZE / 32))) // A code is always 32-bits - , m_varType(varp->varType()) - , m_declKwd(varp->declKwd()) - , m_declDirection(varp->declDirection()) - , m_isScoped(isScoped) { + , m_varType{varp->varType()} + , m_declKwd{varp->declKwd()} + , m_declDirection{varp->declDirection()} + , m_isScoped{isScoped} { dtypeFrom(valuep); addNOp1p(valuep); } - virtual int instrCount() const { return 100; } // Large... + virtual int instrCount() const override { return 100; } // Large... ASTNODE_NODE_FUNCS(TraceDecl) - virtual string name() const { return m_showname; } - virtual bool maybePointedTo() const { return true; } - virtual bool hasDType() const { return true; } - virtual bool same(const AstNode* samep) const { return false; } + virtual string name() const override { return m_showname; } + virtual bool maybePointedTo() const override { return true; } + virtual bool hasDType() const override { return true; } + virtual bool same(const AstNode* samep) const override { return false; } string showname() const { return m_showname; } // * = Var name // Details on what we're tracing uint32_t code() const { return m_code; } @@ -5004,29 +5029,29 @@ private: public: AstTraceInc(FileLine* fl, AstTraceDecl* declp, bool full) : ASTGEN_SUPER(fl) - , m_declp(declp) - , m_full(full) { + , m_declp{declp} + , m_full{full} { dtypeFrom(declp); addOp2p(declp->valuep()->cloneTree(true)); } ASTNODE_NODE_FUNCS(TraceInc) - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(!declp()->brokeExists()); - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_declp->clonep()) m_declp = m_declp->clonep(); } - virtual void dump(std::ostream& str) const; - virtual int instrCount() const { return 10 + 2 * instrCountLd(); } - virtual bool hasDType() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(declp()); } - virtual bool same(const AstNode* samep) const { + virtual void dump(std::ostream& str) const override; + virtual int instrCount() const override { return 10 + 2 * instrCountLd(); } + virtual bool hasDType() const override { return true; } + virtual V3Hash sameHash() const override { return V3Hash(declp()); } + virtual bool same(const AstNode* samep) const override { return declp() == static_cast(samep)->declp(); } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isOutputter() const { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isOutputter() const override { return true; } // but isPure() true // op1 = Statements before the value AstNode* precondsp() const { return op1p(); } @@ -5052,13 +5077,13 @@ public: m_sensesp = sensesp; } ASTNODE_NODE_FUNCS(Active) - virtual void dump(std::ostream& str = std::cout) const; - virtual string name() const { return m_name; } - virtual const char* broken() const { + virtual void dump(std::ostream& str = std::cout) const override; + virtual string name() const override { return m_name; } + virtual const char* broken() const override { BROKEN_RTN(m_sensesp && !m_sensesp->brokeExists()); - return NULL; + return nullptr; } - virtual void cloneRelink() { + virtual void cloneRelink() override { if (m_sensesp->clonep()) { m_sensesp = m_sensesp->clonep(); UASSERT(m_sensesp, "Bad clone cross link: " << this); @@ -5084,7 +5109,8 @@ private: // Return a value of a attribute, for example a LSB or array LSB of a signal AstAttrType m_attrType; // What sort of extraction public: - AstAttrOf(FileLine* fl, AstAttrType attrtype, AstNode* fromp = NULL, AstNode* dimp = NULL) + AstAttrOf(FileLine* fl, AstAttrType attrtype, AstNode* fromp = nullptr, + AstNode* dimp = nullptr) : ASTGEN_SUPER(fl) { setNOp1p(fromp); setNOp2p(dimp); @@ -5094,8 +5120,8 @@ public: AstNode* fromp() const { return op1p(); } AstNode* dimp() const { return op2p(); } AstAttrType attrType() const { return m_attrType; } - virtual V3Hash sameHash() const { return V3Hash(m_attrType); } - virtual void dump(std::ostream& str = std::cout) const; + virtual V3Hash sameHash() const override { return V3Hash(m_attrType); } + virtual void dump(std::ostream& str = std::cout) const override; }; class AstScopeName : public AstNodeMath { @@ -5103,24 +5129,23 @@ class AstScopeName : public AstNodeMath { // Parents: DISPLAY // Children: TEXT private: - bool m_dpiExport; // Is for dpiExport + bool m_dpiExport = false; // Is for dpiExport string scopeNameFormatter(AstText* scopeTextp) const; string scopePrettyNameFormatter(AstText* scopeTextp) const; public: explicit AstScopeName(FileLine* fl) - : ASTGEN_SUPER(fl) - , m_dpiExport(false) { + : ASTGEN_SUPER(fl) { dtypeSetUInt64(); } ASTNODE_NODE_FUNCS(ScopeName) - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return m_dpiExport == static_cast(samep)->m_dpiExport; } - virtual string emitVerilog() { return ""; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return true; } + virtual string emitVerilog() override { return ""; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } AstText* scopeAttrp() const { return VN_CAST(op1p(), Text); } void scopeAttrp(AstNode* nodep) { addOp1p(nodep); } AstText* scopeEntrp() const { return VN_CAST(op2p(), Text); } @@ -5158,9 +5183,9 @@ class AstUdpTableLine : public AstNode { public: AstUdpTableLine(FileLine* fl, const string& text) : ASTGEN_SUPER(fl) - , m_text(text) {} + , m_text{text} {} ASTNODE_NODE_FUNCS(UdpTableLine) - virtual string name() const { return m_text; } + virtual string name() const override { return m_text; } string text() const { return m_text; } }; @@ -5173,24 +5198,68 @@ private: bool m_reset; // Random reset, versus always random public: AstRand(FileLine* fl, AstNodeDType* dtp, bool reset) - : ASTGEN_SUPER(fl) { + : ASTGEN_SUPER(fl) + , m_reset{reset} { dtypep(dtp); - m_reset = reset; } explicit AstRand(FileLine* fl) : ASTGEN_SUPER(fl) - , m_reset(false) {} + , m_reset{false} {} ASTNODE_NODE_FUNCS(Rand) - virtual string emitVerilog() { return "%f$random"; } - virtual string emitC() { + virtual string emitVerilog() override { return "%f$random"; } + virtual string emitC() override { return (m_reset ? "VL_RAND_RESET_%nq(%nw, %P)" : "VL_RANDOM_%nq(%nw, %P)"); } - virtual bool cleanOut() const { return true; } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual int instrCount() const { return instrCountPli(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual bool cleanOut() const override { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual int instrCount() const override { return instrCountPli(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } +}; + +class AstURandom : public AstNodeTermop { + // $urandom +public: + explicit AstURandom(FileLine* fl) + : ASTGEN_SUPER(fl) { + dtypeSetUInt32(); // Says IEEE + } + ASTNODE_NODE_FUNCS(URandom) + virtual string emitVerilog() override { return "%f$urandom"; } + virtual string emitC() override { return "VL_RANDOM_%nq(%nw)"; } + virtual bool cleanOut() const override { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual int instrCount() const override { return instrCountPli(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } +}; + +class AstURandomRange : public AstNodeBiop { + // $urandom_range +public: + explicit AstURandomRange(FileLine* fl, AstNode* lhsp, AstNode* rhsp) + : ASTGEN_SUPER(fl, lhsp, rhsp) { + dtypeSetUInt32(); // Says IEEE + } + ASTNODE_NODE_FUNCS(URandomRange) + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { + return new AstURandomRange(fileline(), lhsp, rhsp); + } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { + V3ERROR_NA; + } + virtual string emitVerilog() override { return "%f$urandom_range(%l, %r)"; } + virtual string emitC() override { return "VL_URANDOM_RANGE_%nq(%li, %ri)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual int instrCount() const override { return instrCountPli(); } }; class AstTime : public AstNodeTermop { @@ -5198,19 +5267,19 @@ class AstTime : public AstNodeTermop { public: AstTime(FileLine* fl, const VTimescale& timeunit) : ASTGEN_SUPER(fl) - , m_timeunit(timeunit) { + , m_timeunit{timeunit} { dtypeSetUInt64(); } ASTNODE_NODE_FUNCS(Time) - virtual string emitVerilog() { return "%f$time"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return true; } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual int instrCount() const { return instrCountTime(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } - virtual void dump(std::ostream& str = std::cout) const; + virtual string emitVerilog() override { return "%f$time"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual int instrCount() const override { return instrCountTime(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } + virtual void dump(std::ostream& str = std::cout) const override; void timeunit(const VTimescale& flag) { m_timeunit = flag; } VTimescale timeunit() const { return m_timeunit; } }; @@ -5220,19 +5289,19 @@ class AstTimeD : public AstNodeTermop { public: AstTimeD(FileLine* fl, const VTimescale& timeunit) : ASTGEN_SUPER(fl) - , m_timeunit(timeunit) { + , m_timeunit{timeunit} { dtypeSetDouble(); } ASTNODE_NODE_FUNCS(TimeD) - virtual string emitVerilog() { return "%f$realtime"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return true; } - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual int instrCount() const { return instrCountTime(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } - virtual void dump(std::ostream& str = std::cout) const; + virtual string emitVerilog() override { return "%f$realtime"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual int instrCount() const override { return instrCountTime(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } + virtual void dump(std::ostream& str = std::cout) const override; void timeunit(const VTimescale& flag) { m_timeunit = flag; } VTimescale timeunit() const { return m_timeunit; } }; @@ -5246,18 +5315,18 @@ public: addNOp1p(exprsp); } ASTNODE_NODE_FUNCS(UCFunc) - virtual bool cleanOut() const { return false; } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual string emitC() { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } AstNode* bodysp() const { return op1p(); } // op1 = expressions to print - virtual bool isPure() const { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const { return true; } - virtual bool isGateOptimizable() const { return false; } - virtual bool isSubstOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual int instrCount() const { return instrCountPli(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + virtual bool isOutputter() const override { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isSubstOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual int instrCount() const override { return instrCountPli(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } }; //====================================================================== @@ -5270,13 +5339,13 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(Negate) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNegate(lhs); } - virtual string emitVerilog() { return "%f(- %l)"; } - virtual string emitC() { return "VL_NEGATE_%lq(%lW, %P, %li)"; } - virtual string emitSimpleOperator() { return "-"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } - virtual bool sizeMattersLhs() const { return true; } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegate(lhs); } + virtual string emitVerilog() override { return "%f(- %l)"; } + virtual string emitC() override { return "VL_NEGATE_%lq(%lW, %P, %li)"; } + virtual string emitSimpleOperator() override { return "-"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } }; class AstNegateD : public AstNodeUniop { public: @@ -5285,15 +5354,15 @@ public: dtypeSetDouble(); } ASTNODE_NODE_FUNCS(NegateD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNegateD(lhs); } - virtual string emitVerilog() { return "%f(- %l)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { return "-"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return instrCountDouble(); } - virtual bool doubleFlavor() const { return true; } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNegateD(lhs); } + virtual string emitVerilog() override { return "%f(- %l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "-"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return instrCountDouble(); } + virtual bool doubleFlavor() const override { return true; } }; class AstRedAnd : public AstNodeUniop { public: @@ -5302,12 +5371,12 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(RedAnd) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedAnd(lhs); } - virtual string emitVerilog() { return "%f(& %l)"; } - virtual string emitC() { return "VL_REDAND_%nq%lq(%nw,%lw, %P, %li)"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedAnd(lhs); } + virtual string emitVerilog() override { return "%f(& %l)"; } + virtual string emitC() override { return "VL_REDAND_%nq%lq(%nw,%lw, %P, %li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } }; class AstRedOr : public AstNodeUniop { public: @@ -5316,12 +5385,12 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(RedOr) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedOr(lhs); } - virtual string emitVerilog() { return "%f(| %l)"; } - virtual string emitC() { return "VL_REDOR_%lq(%lW, %P, %li)"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedOr(lhs); } + virtual string emitVerilog() override { return "%f(| %l)"; } + virtual string emitC() override { return "VL_REDOR_%lq(%lW, %P, %li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } }; class AstRedXor : public AstNodeUniop { public: @@ -5330,16 +5399,16 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(RedXor) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXor(lhs); } - virtual string emitVerilog() { return "%f(^ %l)"; } - virtual string emitC() { return "VL_REDXOR_%lq(%lW, %P, %li)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedXor(lhs); } + virtual string emitVerilog() override { return "%f(^ %l)"; } + virtual string emitC() override { return "VL_REDXOR_%lq(%lW, %P, %li)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { int w = lhsp()->width(); return (w != 1 && w != 2 && w != 4 && w != 8 && w != 16); } - virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return 1 + V3Number::log2b(width()); } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return 1 + V3Number::log2b(width()); } }; class AstRedXnor : public AstNodeUniop { // AstRedXnors are replaced with AstRedXors in V3Const. @@ -5349,16 +5418,16 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(RedXnor) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRedXnor(lhs); } - virtual string emitVerilog() { return "%f(~^ %l)"; } - virtual string emitC() { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRedXnor(lhs); } + virtual string emitVerilog() override { return "%f(~^ %l)"; } + virtual string emitC() override { v3fatalSrc("REDXNOR should have became REDXOR"); return ""; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return 1 + V3Number::log2b(width()); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return 1 + V3Number::log2b(width()); } }; class AstLenN : public AstNodeUniop { @@ -5369,12 +5438,12 @@ public: dtypeSetSigned32(); } ASTNODE_NODE_FUNCS(LenN) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opLenN(lhs); } - virtual string emitVerilog() { return "%f(%l)"; } - virtual string emitC() { return "VL_LEN_IN(%li)"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLenN(lhs); } + virtual string emitVerilog() override { return "%f(%l)"; } + virtual string emitC() override { return "VL_LEN_IN(%li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } }; class AstLogNot : public AstNodeUniop { public: @@ -5383,13 +5452,13 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(LogNot) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opLogNot(lhs); } - virtual string emitVerilog() { return "%f(! %l)"; } - virtual string emitC() { return "VL_LOGNOT_%nq%lq(%nw,%lw, %P, %li)"; } - virtual string emitSimpleOperator() { return "!"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opLogNot(lhs); } + virtual string emitVerilog() override { return "%f(! %l)"; } + virtual string emitC() override { return "VL_LOGNOT_%nq%lq(%nw,%lw, %P, %li)"; } + virtual string emitSimpleOperator() override { return "!"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } }; class AstNot : public AstNodeUniop { public: @@ -5398,13 +5467,13 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(Not) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opNot(lhs); } - virtual string emitVerilog() { return "%f(~ %l)"; } - virtual string emitC() { return "VL_NOT_%lq(%lW, %P, %li)"; } - virtual string emitSimpleOperator() { return "~"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } - virtual bool sizeMattersLhs() const { return true; } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opNot(lhs); } + virtual string emitVerilog() override { return "%f(~ %l)"; } + virtual string emitC() override { return "VL_NOT_%lq(%lW, %P, %li)"; } + virtual string emitSimpleOperator() override { return "~"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } }; class AstExtend : public AstNodeUniop { // Expand a value into a wider entity by 0 extension. Width is implied from nodep->width() @@ -5416,15 +5485,15 @@ public: dtypeSetLogicSized(width, VSigning::UNSIGNED); } ASTNODE_NODE_FUNCS(Extend) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); } - virtual string emitVerilog() { return "%l"; } - virtual string emitC() { return "VL_EXTEND_%nq%lq(%nw,%lw, %P, %li)"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); } + virtual string emitVerilog() override { return "%l"; } + virtual string emitC() override { return "VL_EXTEND_%nq%lq(%nw,%lw, %P, %li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; // Because the EXTEND operator self-casts } - virtual int instrCount() const { return 0; } + virtual int instrCount() const override { return 0; } }; class AstExtendS : public AstNodeUniop { // Expand a value into a wider entity by sign extension. Width is implied from nodep->width() @@ -5437,18 +5506,18 @@ public: dtypeSetLogicSized(width, VSigning::UNSIGNED); } ASTNODE_NODE_FUNCS(ExtendS) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opExtendS(lhs, lhsp()->widthMinV()); } - virtual string emitVerilog() { return "%l"; } - virtual string emitC() { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { + virtual string emitVerilog() override { return "%l"; } + virtual string emitC() override { return "VL_EXTENDS_%nq%lq(%nw,%lw, %P, %li)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; // Because the EXTEND operator self-casts } - virtual int instrCount() const { return 0; } - virtual bool signedFlavor() const { return true; } + virtual int instrCount() const override { return 0; } + virtual bool signedFlavor() const override { return true; } }; class AstSigned : public AstNodeUniop { // $signed(lhs) @@ -5459,16 +5528,16 @@ public: "not coded to create after dtypes resolved"); } ASTNODE_NODE_FUNCS(Signed) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); out.isSigned(false); } - virtual string emitVerilog() { return "%f$signed(%l)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } // Eliminated before matters - virtual bool sizeMattersLhs() const { return true; } // Eliminated before matters - virtual int instrCount() const { return 0; } + virtual string emitVerilog() override { return "%f$signed(%l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } // Eliminated before matters + virtual bool sizeMattersLhs() const override { return true; } // Eliminated before matters + virtual int instrCount() const override { return 0; } }; class AstUnsigned : public AstNodeUniop { // $unsigned(lhs) @@ -5479,16 +5548,16 @@ public: "not coded to create after dtypes resolved"); } ASTNODE_NODE_FUNCS(Unsigned) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); out.isSigned(false); } - virtual string emitVerilog() { return "%f$unsigned(%l)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } // Eliminated before matters - virtual bool sizeMattersLhs() const { return true; } // Eliminated before matters - virtual int instrCount() const { return 0; } + virtual string emitVerilog() override { return "%f$unsigned(%l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } // Eliminated before matters + virtual bool sizeMattersLhs() const override { return true; } // Eliminated before matters + virtual int instrCount() const override { return 0; } }; class AstRToIS : public AstNodeUniop { // $rtoi(lhs) @@ -5498,13 +5567,13 @@ public: dtypeSetSigned32(); } ASTNODE_NODE_FUNCS(RToIS) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRToIS(lhs); } - virtual string emitVerilog() { return "%f$rtoi(%l)"; } - virtual string emitC() { return "VL_RTOI_I_D(%li)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } // Eliminated before matters - virtual bool sizeMattersLhs() const { return false; } // Eliminated before matters - virtual int instrCount() const { return instrCountDouble(); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opRToIS(lhs); } + virtual string emitVerilog() override { return "%f$rtoi(%l)"; } + virtual string emitC() override { return "VL_RTOI_I_D(%li)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } // Eliminated before matters + virtual bool sizeMattersLhs() const override { return false; } // Eliminated before matters + virtual int instrCount() const override { return instrCountDouble(); } }; class AstRToIRoundS : public AstNodeUniop { // Convert real to integer, with arbitrary sized output (not just "integer" format) @@ -5514,13 +5583,15 @@ public: dtypeSetSigned32(); } ASTNODE_NODE_FUNCS(RToIRoundS) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRToIRoundS(lhs); } - virtual string emitVerilog() { return "%f$rtoi_rounded(%l)"; } - virtual string emitC() { return "VL_RTOIROUND_%nq_D(%nw, %P, %li)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return instrCountDouble(); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opRToIRoundS(lhs); + } + virtual string emitVerilog() override { return "%f$rtoi_rounded(%l)"; } + virtual string emitC() override { return "VL_RTOIROUND_%nq_D(%nw, %P, %li)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return instrCountDouble(); } }; class AstIToRD : public AstNodeUniop { // $itor where lhs is unsigned @@ -5530,13 +5601,13 @@ public: dtypeSetDouble(); } ASTNODE_NODE_FUNCS(IToRD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opIToRD(lhs); } - virtual string emitVerilog() { return "%f$itor(%l)"; } - virtual string emitC() { return "VL_ITOR_D_%lq(%lw, %li)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return instrCountDouble(); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opIToRD(lhs); } + virtual string emitVerilog() override { return "%f$itor(%l)"; } + virtual string emitC() override { return "VL_ITOR_D_%lq(%lw, %li)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return instrCountDouble(); } }; class AstISToRD : public AstNodeUniop { // $itor where lhs is signed @@ -5546,14 +5617,14 @@ public: dtypeSetDouble(); } ASTNODE_NODE_FUNCS(ISToRD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opISToRD(lhs); } - virtual string emitVerilog() { return "%f$itor($signed(%l))"; } - virtual string emitC() { return "VL_ISTOR_D_%lq(%lw, %li)"; } - virtual bool emitCheckMaxWords() { return true; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return instrCountDouble(); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opISToRD(lhs); } + virtual string emitVerilog() override { return "%f$itor($signed(%l))"; } + virtual string emitC() override { return "VL_ISTOR_D_%lq(%lw, %li)"; } + virtual bool emitCheckMaxWords() override { return true; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return instrCountDouble(); } }; class AstRealToBits : public AstNodeUniop { public: @@ -5562,13 +5633,15 @@ public: dtypeSetUInt64(); } ASTNODE_NODE_FUNCS(RealToBits) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opRealToBits(lhs); } - virtual string emitVerilog() { return "%f$realtobits(%l)"; } - virtual string emitC() { return "VL_CVT_Q_D(%li)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } // Eliminated before matters - virtual bool sizeMattersLhs() const { return false; } // Eliminated before matters - virtual int instrCount() const { return instrCountDouble(); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opRealToBits(lhs); + } + virtual string emitVerilog() override { return "%f$realtobits(%l)"; } + virtual string emitC() override { return "VL_CVT_Q_D(%li)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } // Eliminated before matters + virtual bool sizeMattersLhs() const override { return false; } // Eliminated before matters + virtual int instrCount() const override { return instrCountDouble(); } }; class AstBitsToRealD : public AstNodeUniop { public: @@ -5577,13 +5650,15 @@ public: dtypeSetDouble(); } ASTNODE_NODE_FUNCS(BitsToRealD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opBitsToRealD(lhs); } - virtual string emitVerilog() { return "%f$bitstoreal(%l)"; } - virtual string emitC() { return "VL_CVT_D_Q(%li)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } // Eliminated before matters - virtual bool sizeMattersLhs() const { return false; } // Eliminated before matters - virtual int instrCount() const { return instrCountDouble(); } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opBitsToRealD(lhs); + } + virtual string emitVerilog() override { return "%f$bitstoreal(%l)"; } + virtual string emitC() override { return "VL_CVT_D_Q(%li)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } // Eliminated before matters + virtual bool sizeMattersLhs() const override { return false; } // Eliminated before matters + virtual int instrCount() const override { return instrCountDouble(); } }; class AstCLog2 : public AstNodeUniop { @@ -5591,13 +5666,13 @@ public: AstCLog2(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(CLog2) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opCLog2(lhs); } - virtual string emitVerilog() { return "%f$clog2(%l)"; } - virtual string emitC() { return "VL_CLOG2_%lq(%lW, %P, %li)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * 16; } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opCLog2(lhs); } + virtual string emitVerilog() override { return "%f$clog2(%l)"; } + virtual string emitC() override { return "VL_CLOG2_%lq(%lW, %P, %li)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 16; } }; class AstCountBits : public AstNodeQuadop { // Number of bits set in vector @@ -5610,21 +5685,21 @@ public: : ASTGEN_SUPER(fl, exprp, ctrl1p, ctrl2p, ctrl3p) {} ASTNODE_NODE_FUNCS(CountBits) virtual void numberOperate(V3Number& out, const V3Number& expr, const V3Number& ctrl1, - const V3Number& ctrl2, const V3Number& ctrl3) { + const V3Number& ctrl2, const V3Number& ctrl3) override { out.opCountBits(expr, ctrl1, ctrl2, ctrl3); } - virtual string emitVerilog() { return "%f$countbits(%l, %r, %f, %o)"; } - virtual string emitC() { return ""; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool cleanThs() const { return true; } - virtual bool cleanFhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual bool sizeMattersThs() const { return false; } - virtual bool sizeMattersFhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * 16; } + virtual string emitVerilog() override { return "%f$countbits(%l, %r, %f, %o)"; } + virtual string emitC() override { return ""; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool cleanThs() const override { return true; } + virtual bool cleanFhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool sizeMattersThs() const override { return false; } + virtual bool sizeMattersFhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 16; } }; class AstCountOnes : public AstNodeUniop { // Number of bits set in vector @@ -5632,13 +5707,15 @@ public: AstCountOnes(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(CountOnes) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opCountOnes(lhs); } - virtual string emitVerilog() { return "%f$countones(%l)"; } - virtual string emitC() { return "VL_COUNTONES_%lq(%lW, %P, %li)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * 16; } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opCountOnes(lhs); + } + virtual string emitVerilog() override { return "%f$countones(%l)"; } + virtual string emitC() override { return "VL_COUNTONES_%lq(%lW, %P, %li)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 16; } }; class AstIsUnknown : public AstNodeUniop { // True if any unknown bits @@ -5648,12 +5725,14 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(IsUnknown) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opIsUnknown(lhs); } - virtual string emitVerilog() { return "%f$isunknown(%l)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opIsUnknown(lhs); + } + virtual string emitVerilog() override { return "%f$isunknown(%l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } }; class AstIsUnbounded : public AstNodeUniop { // True if is unmbounded ($) @@ -5663,15 +5742,15 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(IsUnbounded) - virtual void numberOperate(V3Number& out, const V3Number&) { + virtual void numberOperate(V3Number& out, const V3Number&) override { // Any constant isn't unbounded out.setZero(); } - virtual string emitVerilog() { return "%f$isunbounded(%l)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } + virtual string emitVerilog() override { return "%f$isunbounded(%l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } }; class AstOneHot : public AstNodeUniop { // True if only single bit set in vector @@ -5681,13 +5760,13 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(OneHot) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opOneHot(lhs); } - virtual string emitVerilog() { return "%f$onehot(%l)"; } - virtual string emitC() { return "VL_ONEHOT_%lq(%lW, %P, %li)"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * 4; } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot(lhs); } + virtual string emitVerilog() override { return "%f$onehot(%l)"; } + virtual string emitC() override { return "VL_ONEHOT_%lq(%lW, %P, %li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 4; } }; class AstOneHot0 : public AstNodeUniop { // True if only single bit, or no bits set in vector @@ -5697,13 +5776,13 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(OneHot0) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opOneHot0(lhs); } - virtual string emitVerilog() { return "%f$onehot0(%l)"; } - virtual string emitC() { return "VL_ONEHOT0_%lq(%lW, %P, %li)"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * 3; } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opOneHot0(lhs); } + virtual string emitVerilog() override { return "%f$onehot0(%l)"; } + virtual string emitC() override { return "VL_ONEHOT0_%lq(%lW, %P, %li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 3; } }; class AstCast : public AstNode { @@ -5716,14 +5795,13 @@ public: dtypeFrom(dtp); } ASTNODE_NODE_FUNCS(Cast) - virtual bool hasDType() const { return true; } + virtual bool hasDType() const override { return true; } virtual string emitVerilog() { return "((%d)'(%l))"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); } virtual bool cleanLhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } AstNode* lhsp() const { return op1p(); } - AstNodeDType* getChildDTypep() const { return childDTypep(); } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } AstNodeDType* childDTypep() const { return VN_CAST(op2p(), NodeDType); } virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } }; @@ -5733,22 +5811,22 @@ public: AstCastDynamic(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(CastDynamic) - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { V3ERROR_NA; } - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstCastDynamic(this->fileline(), lhsp, rhsp); } - virtual string emitVerilog() { return "%f$cast(%r, %l)"; } + virtual string emitVerilog() override { return "%f$cast(%r, %l)"; } // Non-existent filehandle returns EOF - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * 20; } - virtual bool isPure() const { return true; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 20; } + virtual bool isPure() const override { return true; } }; class AstCastParse : public AstNode { @@ -5780,7 +5858,6 @@ public: ASTNODE_NODE_FUNCS(CastSize) // No hasDType because widthing removes this node before the hasDType check virtual string emitVerilog() { return "((%r)'(%l))"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual bool cleanOut() const { V3ERROR_NA_RETURN(true); } virtual bool cleanLhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } @@ -5808,17 +5885,17 @@ public: m_size = width(); } ASTNODE_NODE_FUNCS(CCast) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAssign(lhs); } - virtual string emitVerilog() { return "%f$_CAST(%l)"; } - virtual string emitC() { return "VL_CAST_%nq%lq(%nw,%lw, %P, %li)"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } // Special cased in V3Cast - virtual V3Hash sameHash() const { return V3Hash(size()); } - virtual bool same(const AstNode* samep) const { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.opAssign(lhs); } + virtual string emitVerilog() override { return "%f$_CAST(%l)"; } + virtual string emitC() override { return "VL_CAST_%nq%lq(%nw,%lw, %P, %li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } // Special cased in V3Cast + virtual V3Hash sameHash() const override { return V3Hash(size()); } + virtual bool same(const AstNode* samep) const override { return size() == static_cast(samep)->size(); } - virtual void dump(std::ostream& str = std::cout) const; + virtual void dump(std::ostream& str = std::cout) const override; // int size() const { return m_size; } }; @@ -5831,14 +5908,14 @@ public: dtypeSetString(); } ASTNODE_NODE_FUNCS(CvtPackString) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; } - virtual string emitVerilog() { return "%f$_CAST(%l)"; } - virtual string emitC() { return "VL_CVT_PACK_STR_N%lq(%lW, %li)"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } + virtual string emitVerilog() override { return "%f$_CAST(%l)"; } + virtual string emitC() override { return "VL_CVT_PACK_STR_N%lq(%lW, %li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } }; class AstFEof : public AstNodeUniop { @@ -5846,14 +5923,16 @@ public: AstFEof(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(FEof) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; } - virtual string emitVerilog() { return "%f$feof(%l)"; } - virtual string emitC() { return "(%li ? feof(VL_CVT_I_FP(%li)) : true)"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * 16; } - virtual bool isPure() const { return false; } // SPECIAL: $display has 'visual' ordering + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } + virtual string emitVerilog() override { return "%f$feof(%l)"; } + virtual string emitC() override { return "(%li ? feof(VL_CVT_I_FP(%li)) : true)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 16; } + virtual bool isPure() const override { + return false; + } // SPECIAL: $display has 'visual' ordering AstNode* filep() const { return lhsp(); } }; @@ -5865,20 +5944,21 @@ public: setOp2p(strp); } ASTNODE_NODE_FUNCS(FError) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; } - virtual string emitVerilog() { return "%f$ferror(%l, %r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return true; } + virtual string emitVerilog() override { return "%f$ferror(%l, %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return true; } virtual bool cleanLhs() const { return true; } virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * 64; } - virtual bool isPure() const { return false; } // SPECIAL: $display has 'visual' ordering + virtual int instrCount() const override { return widthInstrs() * 64; } + virtual bool isPure() const override { + return false; + } // SPECIAL: $display has 'visual' ordering void filep(AstNode* nodep) { setOp1p(nodep); } AstNode* filep() const { return op1p(); } void strp(AstNode* nodep) { setOp2p(nodep); } AstNode* strp() const { return op2p(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } }; class AstFGetC : public AstNodeUniop { @@ -5886,15 +5966,17 @@ public: AstFGetC(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(FGetC) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; } - virtual string emitVerilog() { return "%f$fgetc(%l)"; } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } + virtual string emitVerilog() override { return "%f$fgetc(%l)"; } // Non-existent filehandle returns EOF - virtual string emitC() { return "(%li ? fgetc(VL_CVT_I_FP(%li)) : -1)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * 64; } - virtual bool isPure() const { return false; } // SPECIAL: $display has 'visual' ordering + virtual string emitC() override { return "(%li ? fgetc(VL_CVT_I_FP(%li)) : -1)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 64; } + virtual bool isPure() const override { + return false; + } // SPECIAL: $display has 'visual' ordering AstNode* filep() const { return lhsp(); } }; @@ -5903,22 +5985,26 @@ public: AstFUngetC(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(FUngetC) - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { V3ERROR_NA; } - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstFUngetC(this->fileline(), lhsp, rhsp); } - virtual string emitVerilog() { return "%f$ungetc(%r, %l)"; } + virtual string emitVerilog() override { return "%f$ungetc(%r, %l)"; } // Non-existent filehandle returns EOF - virtual string emitC() { return "(%li ? (ungetc(%ri, VL_CVT_I_FP(%li)) >= 0 ? 0 : -1) : -1)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * 64; } - virtual bool isPure() const { return false; } // SPECIAL: $display has 'visual' ordering + virtual string emitC() override { + return "(%li ? (ungetc(%ri, VL_CVT_I_FP(%li)) >= 0 ? 0 : -1) : -1)"; + } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 64; } + virtual bool isPure() const override { + return false; + } // SPECIAL: $display has 'visual' ordering AstNode* filep() const { return lhsp(); } AstNode* charp() const { return rhsp(); } }; @@ -5930,11 +6016,11 @@ public: dtypeSetDouble(); } ASTNODE_BASE_FUNCS(NodeSystemUniop) - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual int instrCount() const { return instrCountDoubleTrig(); } - virtual bool doubleFlavor() const { return true; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual int instrCount() const override { return instrCountDoubleTrig(); } + virtual bool doubleFlavor() const override { return true; } }; class AstLogD : public AstNodeSystemUniop { @@ -5942,22 +6028,22 @@ public: AstLogD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(LogD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(log(lhs.toDouble())); } - virtual string emitVerilog() { return "%f$ln(%l)"; } - virtual string emitC() { return "log(%li)"; } + virtual string emitVerilog() override { return "%f$ln(%l)"; } + virtual string emitC() override { return "log(%li)"; } }; class AstLog10D : public AstNodeSystemUniop { public: AstLog10D(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(Log10D) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(log10(lhs.toDouble())); } - virtual string emitVerilog() { return "%f$log10(%l)"; } - virtual string emitC() { return "log10(%li)"; } + virtual string emitVerilog() override { return "%f$log10(%l)"; } + virtual string emitC() override { return "log10(%li)"; } }; class AstExpD : public AstNodeSystemUniop { @@ -5965,11 +6051,11 @@ public: AstExpD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(ExpD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(exp(lhs.toDouble())); } - virtual string emitVerilog() { return "%f$exp(%l)"; } - virtual string emitC() { return "exp(%li)"; } + virtual string emitVerilog() override { return "%f$exp(%l)"; } + virtual string emitC() override { return "exp(%li)"; } }; class AstSqrtD : public AstNodeSystemUniop { @@ -5977,11 +6063,11 @@ public: AstSqrtD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(SqrtD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(sqrt(lhs.toDouble())); } - virtual string emitVerilog() { return "%f$sqrt(%l)"; } - virtual string emitC() { return "sqrt(%li)"; } + virtual string emitVerilog() override { return "%f$sqrt(%l)"; } + virtual string emitC() override { return "sqrt(%li)"; } }; class AstFloorD : public AstNodeSystemUniop { @@ -5989,11 +6075,11 @@ public: AstFloorD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(FloorD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(floor(lhs.toDouble())); } - virtual string emitVerilog() { return "%f$floor(%l)"; } - virtual string emitC() { return "floor(%li)"; } + virtual string emitVerilog() override { return "%f$floor(%l)"; } + virtual string emitC() override { return "floor(%li)"; } }; class AstCeilD : public AstNodeSystemUniop { @@ -6001,11 +6087,11 @@ public: AstCeilD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(CeilD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(ceil(lhs.toDouble())); } - virtual string emitVerilog() { return "%f$ceil(%l)"; } - virtual string emitC() { return "ceil(%li)"; } + virtual string emitVerilog() override { return "%f$ceil(%l)"; } + virtual string emitC() override { return "ceil(%li)"; } }; class AstSinD : public AstNodeSystemUniop { @@ -6013,11 +6099,11 @@ public: AstSinD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(SinD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(sin(lhs.toDouble())); } - virtual string emitVerilog() { return "%f$sin(%l)"; } - virtual string emitC() { return "sin(%li)"; } + virtual string emitVerilog() override { return "%f$sin(%l)"; } + virtual string emitC() override { return "sin(%li)"; } }; class AstCosD : public AstNodeSystemUniop { @@ -6025,11 +6111,11 @@ public: AstCosD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(CosD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(cos(lhs.toDouble())); } - virtual string emitVerilog() { return "%f$cos(%l)"; } - virtual string emitC() { return "cos(%li)"; } + virtual string emitVerilog() override { return "%f$cos(%l)"; } + virtual string emitC() override { return "cos(%li)"; } }; class AstTanD : public AstNodeSystemUniop { @@ -6037,11 +6123,11 @@ public: AstTanD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(TanD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(tan(lhs.toDouble())); } - virtual string emitVerilog() { return "%f$tan(%l)"; } - virtual string emitC() { return "tan(%li)"; } + virtual string emitVerilog() override { return "%f$tan(%l)"; } + virtual string emitC() override { return "tan(%li)"; } }; class AstAsinD : public AstNodeSystemUniop { @@ -6049,11 +6135,11 @@ public: AstAsinD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(AsinD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(asin(lhs.toDouble())); } - virtual string emitVerilog() { return "%f$asin(%l)"; } - virtual string emitC() { return "asin(%li)"; } + virtual string emitVerilog() override { return "%f$asin(%l)"; } + virtual string emitC() override { return "asin(%li)"; } }; class AstAcosD : public AstNodeSystemUniop { @@ -6061,11 +6147,11 @@ public: AstAcosD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(AcosD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(acos(lhs.toDouble())); } - virtual string emitVerilog() { return "%f$acos(%l)"; } - virtual string emitC() { return "acos(%li)"; } + virtual string emitVerilog() override { return "%f$acos(%l)"; } + virtual string emitC() override { return "acos(%li)"; } }; class AstAtanD : public AstNodeSystemUniop { @@ -6073,11 +6159,11 @@ public: AstAtanD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(AtanD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(atan(lhs.toDouble())); } - virtual string emitVerilog() { return "%f$atan(%l)"; } - virtual string emitC() { return "atan(%li)"; } + virtual string emitVerilog() override { return "%f$atan(%l)"; } + virtual string emitC() override { return "atan(%li)"; } }; class AstSinhD : public AstNodeSystemUniop { @@ -6085,11 +6171,11 @@ public: AstSinhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(SinhD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(sinh(lhs.toDouble())); } - virtual string emitVerilog() { return "%f$sinh(%l)"; } - virtual string emitC() { return "sinh(%li)"; } + virtual string emitVerilog() override { return "%f$sinh(%l)"; } + virtual string emitC() override { return "sinh(%li)"; } }; class AstCoshD : public AstNodeSystemUniop { @@ -6097,11 +6183,11 @@ public: AstCoshD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(CoshD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(cosh(lhs.toDouble())); } - virtual string emitVerilog() { return "%f$cosh(%l)"; } - virtual string emitC() { return "cosh(%li)"; } + virtual string emitVerilog() override { return "%f$cosh(%l)"; } + virtual string emitC() override { return "cosh(%li)"; } }; class AstTanhD : public AstNodeSystemUniop { @@ -6109,11 +6195,11 @@ public: AstTanhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(TanhD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(tanh(lhs.toDouble())); } - virtual string emitVerilog() { return "%f$tanh(%l)"; } - virtual string emitC() { return "tanh(%li)"; } + virtual string emitVerilog() override { return "%f$tanh(%l)"; } + virtual string emitC() override { return "tanh(%li)"; } }; class AstAsinhD : public AstNodeSystemUniop { @@ -6121,11 +6207,11 @@ public: AstAsinhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(AsinhD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(asinh(lhs.toDouble())); } - virtual string emitVerilog() { return "%f$asinh(%l)"; } - virtual string emitC() { return "asinh(%li)"; } + virtual string emitVerilog() override { return "%f$asinh(%l)"; } + virtual string emitC() override { return "asinh(%li)"; } }; class AstAcoshD : public AstNodeSystemUniop { @@ -6133,11 +6219,11 @@ public: AstAcoshD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(AcoshD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(acosh(lhs.toDouble())); } - virtual string emitVerilog() { return "%f$acosh(%l)"; } - virtual string emitC() { return "acosh(%li)"; } + virtual string emitVerilog() override { return "%f$acosh(%l)"; } + virtual string emitC() override { return "acosh(%li)"; } }; class AstAtanhD : public AstNodeSystemUniop { @@ -6145,11 +6231,11 @@ public: AstAtanhD(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(AtanhD) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { out.setDouble(atanh(lhs.toDouble())); } - virtual string emitVerilog() { return "%f$atanh(%l)"; } - virtual string emitC() { return "atanh(%li)"; } + virtual string emitVerilog() override { return "%f$atanh(%l)"; } + virtual string emitC() override { return "atanh(%li)"; } }; class AstToLowerN : public AstNodeUniop { // string.tolower() @@ -6159,12 +6245,14 @@ public: dtypeSetString(); } ASTNODE_NODE_FUNCS(ToLowerN) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opToLowerN(lhs); } - virtual string emitVerilog() { return "%l.tolower()"; } - virtual string emitC() { return "VL_TOLOWER_NN(%li)"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opToLowerN(lhs); + } + virtual string emitVerilog() override { return "%l.tolower()"; } + virtual string emitC() override { return "VL_TOLOWER_NN(%li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } }; class AstToUpperN : public AstNodeUniop { // string.toupper() @@ -6174,12 +6262,14 @@ public: dtypeSetString(); } ASTNODE_NODE_FUNCS(ToUpperN) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opToUpperN(lhs); } - virtual string emitVerilog() { return "%l.toupper()"; } - virtual string emitC() { return "VL_TOUPPER_NN(%li)"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opToUpperN(lhs); + } + virtual string emitVerilog() override { return "%l.toupper()"; } + virtual string emitC() override { return "VL_TOUPPER_NN(%li)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } }; class AstTimeImport : public AstNodeUniop { // Take a constant that represents a time and needs conversion based on time units @@ -6188,13 +6278,13 @@ public: AstTimeImport(FileLine* fl, AstNode* lhsp) : ASTGEN_SUPER(fl, lhsp) {} ASTNODE_NODE_FUNCS(TimeImport) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { V3ERROR_NA; } - virtual string emitVerilog() { return "%l"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual void dump(std::ostream& str = std::cout) const; + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { V3ERROR_NA; } + virtual string emitVerilog() override { return "%l"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual void dump(std::ostream& str = std::cout) const override; void timeunit(const VTimescale& flag) { m_timeunit = flag; } VTimescale timeunit() const { return m_timeunit; } }; @@ -6209,12 +6299,14 @@ private: public: AstAtoN(FileLine* fl, AstNode* lhsp, FmtType fmt) : ASTGEN_SUPER(fl, lhsp) - , m_fmt(fmt) { + , m_fmt{fmt} { fmt == ATOREAL ? dtypeSetDouble() : dtypeSetSigned32(); } ASTNODE_NODE_FUNCS(AtoN) - virtual void numberOperate(V3Number& out, const V3Number& lhs) { out.opAtoN(lhs, m_fmt); } - virtual string name() const { + virtual void numberOperate(V3Number& out, const V3Number& lhs) override { + out.opAtoN(lhs, m_fmt); + } + virtual string name() const override { switch (m_fmt) { case ATOI: return "atoi"; case ATOHEX: return "atohex"; @@ -6224,8 +6316,8 @@ public: default: V3ERROR_NA; } } - virtual string emitVerilog() { return "%l." + name() + "()"; } - virtual string emitC() { + virtual string emitVerilog() override { return "%l." + name() + "()"; } + virtual string emitC() override { switch (m_fmt) { case ATOI: return "VL_ATOI_N(%li, 10)"; case ATOHEX: return "VL_ATOI_N(%li, 16)"; @@ -6235,10 +6327,10 @@ public: default: V3ERROR_NA; } } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool isHeavy() const { return true; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool isHeavy() const override { return true; } FmtType format() const { return m_fmt; } }; @@ -6252,21 +6344,21 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(LogOr) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLogOr(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLogOr(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f|| %r)"; } - virtual string emitC() { return "VL_LOGOR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "||"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs() + instrCountBranch(); } + virtual string emitVerilog() override { return "%k(%l %f|| %r)"; } + virtual string emitC() override { return "VL_LOGOR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "||"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() + instrCountBranch(); } }; class AstLogAnd : public AstNodeBiop { public: @@ -6275,21 +6367,21 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(LogAnd) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLogAnd(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLogAnd(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f&& %r)"; } - virtual string emitC() { return "VL_LOGAND_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "&&"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs() + instrCountBranch(); } + virtual string emitVerilog() override { return "%k(%l %f&& %r)"; } + virtual string emitC() override { return "VL_LOGAND_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "&&"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() + instrCountBranch(); } }; class AstLogEq : public AstNodeBiCom { public: @@ -6298,21 +6390,21 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(LogEq) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLogEq(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLogEq(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f<-> %r)"; } - virtual string emitC() { return "VL_LOGEQ_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "<->"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs() + instrCountBranch(); } + virtual string emitVerilog() override { return "%k(%l %f<-> %r)"; } + virtual string emitC() override { return "VL_LOGEQ_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "<->"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() + instrCountBranch(); } }; class AstLogIf : public AstNodeBiop { public: @@ -6321,21 +6413,21 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(LogIf) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLogIf(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLogIf(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f-> %r)"; } - virtual string emitC() { return "VL_LOGIF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "->"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs() + instrCountBranch(); } + virtual string emitVerilog() override { return "%k(%l %f-> %r)"; } + virtual string emitC() override { return "VL_LOGIF_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "->"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() + instrCountBranch(); } }; class AstOr : public AstNodeBiComAsv { public: @@ -6344,20 +6436,20 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(Or) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstOr(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opOr(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f| %r)"; } - virtual string emitC() { return "VL_OR_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "|"; } - virtual bool cleanOut() const { V3ERROR_NA_RETURN(false); } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } + virtual string emitVerilog() override { return "%k(%l %f| %r)"; } + virtual string emitC() override { return "VL_OR_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "|"; } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(false); } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } }; class AstAnd : public AstNodeBiComAsv { public: @@ -6366,20 +6458,20 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(And) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAnd(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opAnd(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f& %r)"; } - virtual string emitC() { return "VL_AND_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "&"; } - virtual bool cleanOut() const { V3ERROR_NA_RETURN(false); } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } + virtual string emitVerilog() override { return "%k(%l %f& %r)"; } + virtual string emitC() override { return "VL_AND_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "&"; } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(false); } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } }; class AstXor : public AstNodeBiComAsv { public: @@ -6388,20 +6480,20 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(Xor) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstXor(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opXor(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f^ %r)"; } - virtual string emitC() { return "VL_XOR_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "^"; } - virtual bool cleanOut() const { return false; } // Lclean && Rclean - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } + virtual string emitVerilog() override { return "%k(%l %f^ %r)"; } + virtual string emitC() override { return "VL_XOR_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "^"; } + virtual bool cleanOut() const override { return false; } // Lclean && Rclean + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } }; class AstXnor : public AstNodeBiComAsv { public: @@ -6410,20 +6502,20 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(Xnor) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstXnor(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opXnor(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f^ ~ %r)"; } - virtual string emitC() { return "VL_XNOR_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "^ ~"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f^ ~ %r)"; } + virtual string emitC() override { return "VL_XNOR_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "^ ~"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } }; class AstEq : public AstNodeBiCom { public: @@ -6432,22 +6524,22 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(Eq) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstEq(this->fileline(), lhsp, rhsp); } static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstEq/AstEqD - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opEq(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f== %r)"; } - virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "=="; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } + virtual string emitVerilog() override { return "%k(%l %f== %r)"; } + virtual string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "=="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } }; class AstEqD : public AstNodeBiCom { public: @@ -6456,22 +6548,22 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(EqD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstEqD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opEqD(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f== %r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { return "=="; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountDouble(); } - virtual bool doubleFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f== %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "=="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return instrCountDouble(); } + virtual bool doubleFlavor() const override { return true; } }; class AstEqN : public AstNodeBiCom { public: @@ -6480,22 +6572,22 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(EqN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstEqN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opEqN(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f== %r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { return "=="; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountString(); } - virtual bool stringFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f== %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "=="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return instrCountString(); } + virtual bool stringFlavor() const override { return true; } }; class AstNeq : public AstNodeBiCom { public: @@ -6504,20 +6596,20 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(Neq) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstNeq(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opNeq(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f!= %r)"; } - virtual string emitC() { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "!="; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } + virtual string emitVerilog() override { return "%k(%l %f!= %r)"; } + virtual string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "!="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } }; class AstNeqD : public AstNodeBiCom { public: @@ -6526,22 +6618,22 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(NeqD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstNeqD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opNeqD(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f!= %r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { return "!="; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountDouble(); } - virtual bool doubleFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f!= %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "!="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return instrCountDouble(); } + virtual bool doubleFlavor() const override { return true; } }; class AstNeqN : public AstNodeBiCom { public: @@ -6550,22 +6642,22 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(NeqN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstNeqN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opNeqN(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f!= %r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { return "!="; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountString(); } - virtual bool stringFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f!= %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "!="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return instrCountString(); } + virtual bool stringFlavor() const override { return true; } }; class AstLt : public AstNodeBiop { public: @@ -6574,20 +6666,20 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(Lt) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLt(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLt(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f< %r)"; } - virtual string emitC() { return "VL_LT_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "<"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } + virtual string emitVerilog() override { return "%k(%l %f< %r)"; } + virtual string emitC() override { return "VL_LT_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "<"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } }; class AstLtD : public AstNodeBiop { public: @@ -6596,22 +6688,22 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(LtD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLtD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLtD(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f< %r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { return "<"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountDouble(); } - virtual bool doubleFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f< %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "<"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return instrCountDouble(); } + virtual bool doubleFlavor() const override { return true; } }; class AstLtS : public AstNodeBiop { public: @@ -6620,21 +6712,21 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(LtS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLtS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLtS(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f< %r)"; } - virtual string emitC() { return "VL_LTS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return ""; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual bool signedFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f< %r)"; } + virtual string emitC() override { return "VL_LTS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool signedFlavor() const override { return true; } }; class AstLtN : public AstNodeBiop { public: @@ -6643,22 +6735,22 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(LtN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLtN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLtN(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f< %r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { return "<"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountString(); } - virtual bool stringFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f< %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "<"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return instrCountString(); } + virtual bool stringFlavor() const override { return true; } }; class AstGt : public AstNodeBiop { public: @@ -6667,20 +6759,20 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(Gt) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGt(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGt(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f> %r)"; } - virtual string emitC() { return "VL_GT_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return ">"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } + virtual string emitVerilog() override { return "%k(%l %f> %r)"; } + virtual string emitC() override { return "VL_GT_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return ">"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } }; class AstGtD : public AstNodeBiop { public: @@ -6689,22 +6781,22 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(GtD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGtD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGtD(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f> %r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { return ">"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountDouble(); } - virtual bool doubleFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f> %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return ">"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return instrCountDouble(); } + virtual bool doubleFlavor() const override { return true; } }; class AstGtS : public AstNodeBiop { public: @@ -6713,21 +6805,21 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(GtS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGtS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGtS(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f> %r)"; } - virtual string emitC() { return "VL_GTS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return ""; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual bool signedFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f> %r)"; } + virtual string emitC() override { return "VL_GTS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool signedFlavor() const override { return true; } }; class AstGtN : public AstNodeBiop { public: @@ -6736,22 +6828,22 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(GtN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGtN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGtN(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f> %r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { return ">"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountString(); } - virtual bool stringFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f> %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return ">"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return instrCountString(); } + virtual bool stringFlavor() const override { return true; } }; class AstGte : public AstNodeBiop { public: @@ -6760,22 +6852,22 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(Gte) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGte(this->fileline(), lhsp, rhsp); } static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstGte/AstGteS/AstGteD - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGte(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f>= %r)"; } - virtual string emitC() { return "VL_GTE_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return ">="; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } + virtual string emitVerilog() override { return "%k(%l %f>= %r)"; } + virtual string emitC() override { return "VL_GTE_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return ">="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } }; class AstGteD : public AstNodeBiop { public: @@ -6784,22 +6876,22 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(GteD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGteD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGteD(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f>= %r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { return ">="; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountDouble(); } - virtual bool doubleFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f>= %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return ">="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return instrCountDouble(); } + virtual bool doubleFlavor() const override { return true; } }; class AstGteS : public AstNodeBiop { public: @@ -6808,21 +6900,21 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(GteS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGteS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGteS(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f>= %r)"; } - virtual string emitC() { return "VL_GTES_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return ""; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual bool signedFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f>= %r)"; } + virtual string emitC() override { return "VL_GTES_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool signedFlavor() const override { return true; } }; class AstGteN : public AstNodeBiop { public: @@ -6831,22 +6923,22 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(GteN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGteN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGteN(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f>= %r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { return ">="; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountString(); } - virtual bool stringFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f>= %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return ">="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return instrCountString(); } + virtual bool stringFlavor() const override { return true; } }; class AstLte : public AstNodeBiop { public: @@ -6855,22 +6947,22 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(Lte) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLte(this->fileline(), lhsp, rhsp); } static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstLte/AstLteS/AstLteD - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLte(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f<= %r)"; } - virtual string emitC() { return "VL_LTE_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "<="; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } + virtual string emitVerilog() override { return "%k(%l %f<= %r)"; } + virtual string emitC() override { return "VL_LTE_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "<="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } }; class AstLteD : public AstNodeBiop { public: @@ -6879,22 +6971,22 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(LteD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLteD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLteD(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f<= %r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { return "<="; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountDouble(); } - virtual bool doubleFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f<= %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "<="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return instrCountDouble(); } + virtual bool doubleFlavor() const override { return true; } }; class AstLteS : public AstNodeBiop { public: @@ -6903,21 +6995,21 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(LteS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLteS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLteS(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f<= %r)"; } - virtual string emitC() { return "VL_LTES_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return ""; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual bool signedFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f<= %r)"; } + virtual string emitC() override { return "VL_LTES_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool signedFlavor() const override { return true; } }; class AstLteN : public AstNodeBiop { public: @@ -6926,22 +7018,22 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(LteN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstLteN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opLteN(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f<= %r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { return "<="; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountString(); } - virtual bool stringFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f<= %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "<="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return instrCountString(); } + virtual bool stringFlavor() const override { return true; } }; class AstShiftL : public AstNodeBiop { public: @@ -6950,20 +7042,20 @@ public: if (setwidth) { dtypeSetLogicSized(setwidth, VSigning::UNSIGNED); } } ASTNODE_NODE_FUNCS(ShiftL) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstShiftL(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opShiftL(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f<< %r)"; } - virtual string emitC() { return "VL_SHIFTL_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "<<"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return false; } + virtual string emitVerilog() override { return "%k(%l %f<< %r)"; } + virtual string emitC() override { return "VL_SHIFTL_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "<<"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return false; } }; class AstShiftR : public AstNodeBiop { public: @@ -6972,21 +7064,21 @@ public: if (setwidth) { dtypeSetLogicSized(setwidth, VSigning::UNSIGNED); } } ASTNODE_NODE_FUNCS(ShiftR) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstShiftR(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opShiftR(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f>> %r)"; } - virtual string emitC() { return "VL_SHIFTR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return ">>"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f>> %r)"; } + virtual string emitC() override { return "VL_SHIFTR_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return ">>"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } // LHS size might be > output size, so don't want to force size - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } }; class AstShiftRS : public AstNodeBiop { // Shift right with sign extension, >>> operator @@ -6998,21 +7090,21 @@ public: if (setwidth) { dtypeSetLogicSized(setwidth, VSigning::SIGNED); } } ASTNODE_NODE_FUNCS(ShiftRS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstShiftRS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opShiftRS(lhs, rhs, lhsp()->widthMinV()); } - virtual string emitVerilog() { return "%k(%l %f>>> %r)"; } - virtual string emitC() { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return ""; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual bool signedFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f>>> %r)"; } + virtual string emitC() override { return "VL_SHIFTRS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool signedFlavor() const override { return true; } }; class AstAdd : public AstNodeBiComAsv { public: @@ -7021,20 +7113,20 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(Add) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAdd(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opAdd(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f+ %r)"; } - virtual string emitC() { return "VL_ADD_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "+"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f+ %r)"; } + virtual string emitC() override { return "VL_ADD_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "+"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } }; class AstAddD : public AstNodeBiComAsv { public: @@ -7043,22 +7135,22 @@ public: dtypeSetDouble(); } ASTNODE_NODE_FUNCS(AddD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAddD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opAddD(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f+ %r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { return "+"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountDouble(); } - virtual bool doubleFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f+ %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "+"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return instrCountDouble(); } + virtual bool doubleFlavor() const override { return true; } }; class AstSub : public AstNodeBiop { public: @@ -7067,20 +7159,20 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(Sub) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstSub(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opSub(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f- %r)"; } - virtual string emitC() { return "VL_SUB_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "-"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f- %r)"; } + virtual string emitC() override { return "VL_SUB_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "-"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } }; class AstSubD : public AstNodeBiop { public: @@ -7089,22 +7181,22 @@ public: dtypeSetDouble(); } ASTNODE_NODE_FUNCS(SubD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstSubD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opSubD(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f- %r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { return "-"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountDouble(); } - virtual bool doubleFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f- %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "-"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return instrCountDouble(); } + virtual bool doubleFlavor() const override { return true; } }; class AstMul : public AstNodeBiComAsv { public: @@ -7113,21 +7205,21 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(Mul) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstMul(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opMul(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f* %r)"; } - virtual string emitC() { return "VL_MUL_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "*"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return true; } - virtual int instrCount() const { return widthInstrs() * instrCountMul(); } + virtual string emitVerilog() override { return "%k(%l %f* %r)"; } + virtual string emitC() override { return "VL_MUL_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "*"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual int instrCount() const override { return widthInstrs() * instrCountMul(); } }; class AstMulD : public AstNodeBiComAsv { public: @@ -7136,22 +7228,22 @@ public: dtypeSetDouble(); } ASTNODE_NODE_FUNCS(MulD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstMulD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opMulD(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f* %r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { return "*"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return true; } - virtual int instrCount() const { return instrCountDouble(); } - virtual bool doubleFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f* %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "*"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual int instrCount() const override { return instrCountDouble(); } + virtual bool doubleFlavor() const override { return true; } }; class AstMulS : public AstNodeBiComAsv { public: @@ -7160,23 +7252,23 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(MulS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstMulS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opMulS(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f* %r)"; } - virtual string emitC() { return "VL_MULS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return ""; } - virtual bool emitCheckMaxWords() { return true; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return true; } - virtual int instrCount() const { return widthInstrs() * instrCountMul(); } - virtual bool signedFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f* %r)"; } + virtual string emitC() override { return "VL_MULS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool emitCheckMaxWords() override { return true; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual int instrCount() const override { return widthInstrs() * instrCountMul(); } + virtual bool signedFlavor() const override { return true; } }; class AstDiv : public AstNodeBiop { public: @@ -7185,20 +7277,20 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(Div) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstDiv(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opDiv(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f/ %r)"; } - virtual string emitC() { return "VL_DIV_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return true; } - virtual int instrCount() const { return widthInstrs() * instrCountDiv(); } + virtual string emitVerilog() override { return "%k(%l %f/ %r)"; } + virtual string emitC() override { return "VL_DIV_%nq%lq%rq(%lw, %P, %li, %ri)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual int instrCount() const override { return widthInstrs() * instrCountDiv(); } }; class AstDivD : public AstNodeBiop { public: @@ -7207,22 +7299,22 @@ public: dtypeSetDouble(); } ASTNODE_NODE_FUNCS(DivD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstDivD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opDivD(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f/ %r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { return "/"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountDoubleDiv(); } - virtual bool doubleFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f/ %r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return "/"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return instrCountDoubleDiv(); } + virtual bool doubleFlavor() const override { return true; } }; class AstDivS : public AstNodeBiop { public: @@ -7231,21 +7323,21 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(DivS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstDivS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opDivS(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f/ %r)"; } - virtual string emitC() { return "VL_DIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return true; } - virtual int instrCount() const { return widthInstrs() * instrCountDiv(); } - virtual bool signedFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f/ %r)"; } + virtual string emitC() override { return "VL_DIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual int instrCount() const override { return widthInstrs() * instrCountDiv(); } + virtual bool signedFlavor() const override { return true; } }; class AstModDiv : public AstNodeBiop { public: @@ -7254,20 +7346,20 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(ModDiv) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstModDiv(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opModDiv(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f%% %r)"; } - virtual string emitC() { return "VL_MODDIV_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return true; } - virtual int instrCount() const { return widthInstrs() * instrCountDiv(); } + virtual string emitVerilog() override { return "%k(%l %f%% %r)"; } + virtual string emitC() override { return "VL_MODDIV_%nq%lq%rq(%lw, %P, %li, %ri)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual int instrCount() const override { return widthInstrs() * instrCountDiv(); } }; class AstModDivS : public AstNodeBiop { public: @@ -7276,21 +7368,21 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(ModDivS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstModDivS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opModDivS(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f%% %r)"; } - virtual string emitC() { return "VL_MODDIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return true; } - virtual int instrCount() const { return widthInstrs() * instrCountDiv(); } - virtual bool signedFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f%% %r)"; } + virtual string emitC() override { return "VL_MODDIVS_%nq%lq%rq(%lw, %P, %li, %ri)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual int instrCount() const override { return widthInstrs() * instrCountDiv(); } + virtual bool signedFlavor() const override { return true; } }; class AstPow : public AstNodeBiop { public: @@ -7299,21 +7391,21 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(Pow) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstPow(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opPow(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f** %r)"; } - virtual string emitC() { return "VL_POW_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual bool emitCheckMaxWords() { return true; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * instrCountMul() * 10; } + virtual string emitVerilog() override { return "%k(%l %f** %r)"; } + virtual string emitC() override { return "VL_POW_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual bool emitCheckMaxWords() override { return true; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * instrCountMul() * 10; } }; class AstPowD : public AstNodeBiop { public: @@ -7322,21 +7414,21 @@ public: dtypeSetDouble(); } ASTNODE_NODE_FUNCS(PowD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstPowD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opPowD(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f** %r)"; } - virtual string emitC() { return "pow(%li,%ri)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountDoubleDiv() * 5; } - virtual bool doubleFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f** %r)"; } + virtual string emitC() override { return "pow(%li,%ri)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return instrCountDoubleDiv() * 5; } + virtual bool doubleFlavor() const override { return true; } }; class AstPowSU : public AstNodeBiop { public: @@ -7345,22 +7437,24 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(PowSU) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstPowSU(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opPowSU(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f** %r)"; } - virtual string emitC() { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,0)"; } - virtual bool emitCheckMaxWords() { return true; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * instrCountMul() * 10; } - virtual bool signedFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f** %r)"; } + virtual string emitC() override { + return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,0)"; + } + virtual bool emitCheckMaxWords() override { return true; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * instrCountMul() * 10; } + virtual bool signedFlavor() const override { return true; } }; class AstPowSS : public AstNodeBiop { public: @@ -7369,22 +7463,24 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(PowSS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstPowSS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opPowSS(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f** %r)"; } - virtual string emitC() { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,1)"; } - virtual bool emitCheckMaxWords() { return true; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * instrCountMul() * 10; } - virtual bool signedFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f** %r)"; } + virtual string emitC() override { + return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 1,1)"; + } + virtual bool emitCheckMaxWords() override { return true; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * instrCountMul() * 10; } + virtual bool signedFlavor() const override { return true; } }; class AstPowUS : public AstNodeBiop { public: @@ -7393,22 +7489,24 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(PowUS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstPowUS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opPowUS(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f** %r)"; } - virtual string emitC() { return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 0,1)"; } - virtual bool emitCheckMaxWords() { return true; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * instrCountMul() * 10; } - virtual bool signedFlavor() const { return true; } + virtual string emitVerilog() override { return "%k(%l %f** %r)"; } + virtual string emitC() override { + return "VL_POWSS_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri, 0,1)"; + } + virtual bool emitCheckMaxWords() override { return true; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * instrCountMul() * 10; } + virtual bool signedFlavor() const override { return true; } }; class AstPreAdd : public AstNodeTriop { // Pre-increment/add @@ -7421,19 +7519,19 @@ public: : ASTGEN_SUPER(fl, lhsp, rhsp, thsp) {} ASTNODE_NODE_FUNCS(PreAdd) virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) { + const V3Number& ths) override { V3ERROR_NA; // Need to modify lhs } - virtual string emitVerilog() { return "%k(++%r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool cleanThs() const { return false; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return true; } - virtual bool sizeMattersThs() const { return true; } + virtual string emitVerilog() override { return "%k(++%r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool cleanThs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual bool sizeMattersThs() const override { return true; } }; class AstPreSub : public AstNodeTriop { // Pre-decrement/subtract @@ -7446,19 +7544,19 @@ public: : ASTGEN_SUPER(fl, lhsp, rhsp, thsp) {} ASTNODE_NODE_FUNCS(PreSub) virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) { + const V3Number& ths) override { V3ERROR_NA; // Need to modify lhs } - virtual string emitVerilog() { return "%k(--%r)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool cleanThs() const { return false; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return true; } - virtual bool sizeMattersThs() const { return true; } + virtual string emitVerilog() override { return "%k(--%r)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool cleanThs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual bool sizeMattersThs() const override { return true; } }; class AstPostAdd : public AstNodeTriop { // Post-increment/add @@ -7471,19 +7569,19 @@ public: : ASTGEN_SUPER(fl, lhsp, rhsp, thsp) {} ASTNODE_NODE_FUNCS(PostAdd) virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) { + const V3Number& ths) override { V3ERROR_NA; // Need to modify lhs } - virtual string emitVerilog() { return "%k(%r++)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool cleanThs() const { return false; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return true; } - virtual bool sizeMattersThs() const { return true; } + virtual string emitVerilog() override { return "%k(%r++)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool cleanThs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual bool sizeMattersThs() const override { return true; } }; class AstPostSub : public AstNodeTriop { // Post-decrement/subtract @@ -7496,19 +7594,19 @@ public: : ASTGEN_SUPER(fl, lhsp, rhsp, thsp) {} ASTNODE_NODE_FUNCS(PostSub) virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) { + const V3Number& ths) override { V3ERROR_NA; // Need to modify lhs } - virtual string emitVerilog() { return "%k(%r--)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool cleanThs() const { return false; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return true; } - virtual bool sizeMattersThs() const { return true; } + virtual string emitVerilog() override { return "%k(%r--)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool cleanThs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return true; } + virtual bool sizeMattersThs() const override { return true; } }; class AstEqCase : public AstNodeBiCom { public: @@ -7517,20 +7615,20 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(EqCase) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstEqCase(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opCaseEq(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f=== %r)"; } - virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "=="; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } + virtual string emitVerilog() override { return "%k(%l %f=== %r)"; } + virtual string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "=="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } }; class AstNeqCase : public AstNodeBiCom { public: @@ -7539,20 +7637,20 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(NeqCase) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstNeqCase(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opCaseNeq(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f!== %r)"; } - virtual string emitC() { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "!="; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } + virtual string emitVerilog() override { return "%k(%l %f!== %r)"; } + virtual string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "!="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } }; class AstEqWild : public AstNodeBiop { // Note wildcard operator rhs differs from lhs @@ -7562,22 +7660,22 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(EqWild) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstEqWild(this->fileline(), lhsp, rhsp); } static AstNodeBiop* newTyped(FileLine* fl, AstNode* lhsp, AstNode* rhsp); // Return AstEqWild/AstEqD - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opWildEq(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f==? %r)"; } - virtual string emitC() { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "=="; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } + virtual string emitVerilog() override { return "%k(%l %f==? %r)"; } + virtual string emitC() override { return "VL_EQ_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "=="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } }; class AstNeqWild : public AstNodeBiop { public: @@ -7586,20 +7684,20 @@ public: dtypeSetLogicBool(); } ASTNODE_NODE_FUNCS(NeqWild) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstNeqWild(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opWildNeq(lhs, rhs); } - virtual string emitVerilog() { return "%k(%l %f!=? %r)"; } - virtual string emitC() { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } - virtual string emitSimpleOperator() { return "!="; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } + virtual string emitVerilog() override { return "%k(%l %f!=? %r)"; } + virtual string emitC() override { return "VL_NEQ_%lq(%lW, %P, %li, %ri)"; } + virtual string emitSimpleOperator() override { return "!="; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } }; class AstConcat : public AstNodeBiop { // If you're looking for {#{}}, see AstReplicate @@ -7612,20 +7710,20 @@ public: } } ASTNODE_NODE_FUNCS(Concat) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstConcat(this->fileline(), lhsp, rhsp); } - virtual string emitVerilog() { return "%f{%l, %k%r}"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual string emitVerilog() override { return "%f{%l, %k%r}"; } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opConcat(lhs, rhs); } - virtual string emitC() { return "VL_CONCAT_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * 2; } + virtual string emitC() override { return "VL_CONCAT_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 2; } }; class AstConcatN : public AstNodeBiop { // String concatenate @@ -7635,89 +7733,77 @@ public: dtypeSetString(); } ASTNODE_NODE_FUNCS(ConcatN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstConcatN(this->fileline(), lhsp, rhsp); } - virtual string emitVerilog() { return "%f{%l, %k%r}"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual string emitVerilog() override { return "%f{%l, %k%r}"; } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opConcatN(lhs, rhs); } - virtual string emitC() { return "VL_CONCATN_NNN(%li, %ri)"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountString(); } - virtual bool stringFlavor() const { return true; } + virtual string emitC() override { return "VL_CONCATN_NNN(%li, %ri)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return instrCountString(); } + virtual bool stringFlavor() const override { return true; } }; class AstReplicate : public AstNodeBiop { // Also used as a "Uniop" flavor of Concat, e.g. "{a}" // Verilog {rhs{lhs}} - Note rhsp() is the replicate value, not the lhsp() -private: - void init() { - if (lhsp()) { - if (const AstConst* constp = VN_CAST(rhsp(), Const)) { - dtypeSetLogicSized(lhsp()->width() * constp->toUInt(), VSigning::UNSIGNED); - } - } - } - public: AstReplicate(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - init(); + if (lhsp) { + if (const AstConst* constp = VN_CAST(rhsp, Const)) { + dtypeSetLogicSized(lhsp->width() * constp->toUInt(), VSigning::UNSIGNED); + } + } } AstReplicate(FileLine* fl, AstNode* lhsp, uint32_t repCount) - : ASTGEN_SUPER(fl, lhsp, new AstConst(fl, repCount)) { - init(); - } + : AstReplicate(fl, lhsp, new AstConst(fl, repCount)) {} ASTNODE_NODE_FUNCS(Replicate) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstReplicate(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opRepl(lhs, rhs); } - virtual string emitVerilog() { return "%f{%r{%k%l}}"; } - virtual string emitC() { return "VL_REPLICATE_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * 2; } + virtual string emitVerilog() override { return "%f{%r{%k%l}}"; } + virtual string emitC() override { return "VL_REPLICATE_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 2; } }; class AstReplicateN : public AstNodeBiop { // String replicate -private: - void init() { dtypeSetString(); } - public: AstReplicateN(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) { - init(); + dtypeSetString(); } AstReplicateN(FileLine* fl, AstNode* lhsp, uint32_t repCount) - : ASTGEN_SUPER(fl, lhsp, new AstConst(fl, repCount)) { - init(); - } + : AstReplicateN(fl, lhsp, new AstConst(fl, repCount)) {} ASTNODE_NODE_FUNCS(ReplicateN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstReplicateN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opReplN(lhs, rhs); } - virtual string emitVerilog() { return "%f{%r{%k%l}}"; } - virtual string emitC() { return "VL_REPLICATEN_NN%rq(0,0,%rw, %li, %ri)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * 2; } - virtual bool stringFlavor() const { return true; } + virtual string emitVerilog() override { return "%f{%r{%k%l}}"; } + virtual string emitC() override { return "VL_REPLICATEN_NN%rq(0,0,%rw, %li, %ri)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 2; } + virtual bool stringFlavor() const override { return true; } }; class AstStreamL : public AstNodeStream { // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp() @@ -7725,20 +7811,20 @@ public: AstStreamL(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(StreamL) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstStreamL(this->fileline(), lhsp, rhsp); } - virtual string emitVerilog() { return "%f{ << %r %k{%l} }"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual string emitVerilog() override { return "%f{ << %r %k{%l} }"; } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opStreamL(lhs, rhs); } - virtual string emitC() { return "VL_STREAML_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * 2; } + virtual string emitC() override { return "VL_STREAML_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)"; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 2; } }; class AstStreamR : public AstNodeStream { // Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp() @@ -7746,20 +7832,20 @@ public: AstStreamR(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(StreamR) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstStreamR(this->fileline(), lhsp, rhsp); } - virtual string emitVerilog() { return "%f{ >> %r %k{%l} }"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual string emitVerilog() override { return "%f{ >> %r %k{%l} }"; } + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opAssign(lhs); } - virtual string emitC() { return isWide() ? "VL_ASSIGN_W(%nw, %P, %li)" : "%li"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return true; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * 2; } + virtual string emitC() override { return isWide() ? "VL_ASSIGN_W(%nw, %P, %li)" : "%li"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return true; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 2; } }; class AstBufIf1 : public AstNodeBiop { // lhs is enable, rhs is data to drive @@ -7771,40 +7857,40 @@ public: dtypeFrom(lhsp); } ASTNODE_NODE_FUNCS(BufIf1) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstBufIf1(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opBufIf1(lhs, rhs); } - virtual string emitVerilog() { return "bufif(%r,%l)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } // Lclean || Rclean - virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); } // Lclean || Rclean - virtual bool cleanOut() const { V3ERROR_NA_RETURN(""); } // Lclean || Rclean - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } + virtual string emitVerilog() override { return "bufif(%r,%l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } // Lclean || Rclean + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } }; class AstFGetS : public AstNodeBiop { public: AstFGetS(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(FGetS) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstFGetS(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { V3ERROR_NA; } - virtual string emitVerilog() { return "%f$fgets(%l,%r)"; } - virtual string emitC() { return "VL_FGETS_%nqX%rq(%lw, %P, &(%li), %ri)"; } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return widthInstrs() * 64; } + virtual string emitVerilog() override { return "%f$fgets(%l,%r)"; } + virtual string emitC() override { return "VL_FGETS_%nqX%rq(%lw, %P, &(%li), %ri)"; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return widthInstrs() * 64; } AstNode* strgp() const { return lhsp(); } AstNode* filep() const { return rhsp(); } }; @@ -7815,13 +7901,13 @@ public: : AstNodeBiop(t, fl, lhsp, rhsp) { dtypeSetDouble(); } - virtual bool cleanOut() const { return false; } - virtual bool cleanLhs() const { return false; } - virtual bool cleanRhs() const { return false; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual int instrCount() const { return instrCountDoubleTrig(); } - virtual bool doubleFlavor() const { return true; } + virtual bool cleanOut() const override { return false; } + virtual bool cleanLhs() const override { return false; } + virtual bool cleanRhs() const override { return false; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual int instrCount() const override { return instrCountDoubleTrig(); } + virtual bool doubleFlavor() const override { return true; } }; class AstAtan2D : public AstNodeSystemBiop { @@ -7829,14 +7915,14 @@ public: AstAtan2D(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(Atan2D) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstAtan2D(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.setDouble(atan2(lhs.toDouble(), rhs.toDouble())); } - virtual string emitVerilog() { return "%f$atan2(%l,%r)"; } - virtual string emitC() { return "atan2(%li,%ri)"; } + virtual string emitVerilog() override { return "%f$atan2(%l,%r)"; } + virtual string emitC() override { return "atan2(%li,%ri)"; } }; class AstHypotD : public AstNodeSystemBiop { @@ -7844,14 +7930,14 @@ public: AstHypotD(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : ASTGEN_SUPER(fl, lhsp, rhsp) {} ASTNODE_NODE_FUNCS(HypotD) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstHypotD(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.setDouble(hypot(lhs.toDouble(), rhs.toDouble())); } - virtual string emitVerilog() { return "%f$hypot(%l,%r)"; } - virtual string emitC() { return "hypot(%li,%ri)"; } + virtual string emitVerilog() override { return "%f$hypot(%l,%r)"; } + virtual string emitC() override { return "hypot(%li,%ri)"; } }; class AstPutcN : public AstNodeTriop { @@ -7863,21 +7949,21 @@ public: } ASTNODE_NODE_FUNCS(PutcN) virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) { + const V3Number& ths) override { out.opPutcN(lhs, rhs, ths); } - virtual string name() const { return "putc"; } - virtual string emitVerilog() { return "%k(%l.putc(%r,%t))"; } - virtual string emitC() { return "VL_PUTC_N(%li,%ri,%ti)"; } - virtual string emitSimpleOperator() { return ""; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool cleanThs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual bool sizeMattersThs() const { return false; } - virtual bool isHeavy() const { return true; } + virtual string name() const override { return "putc"; } + virtual string emitVerilog() override { return "%k(%l.putc(%r,%t))"; } + virtual string emitC() override { return "VL_PUTC_N(%li,%ri,%ti)"; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool cleanThs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool sizeMattersThs() const override { return false; } + virtual bool isHeavy() const override { return true; } }; class AstGetcN : public AstNodeBiop { @@ -7888,22 +7974,22 @@ public: dtypeSetBitSized(8, VSigning::UNSIGNED); } ASTNODE_NODE_FUNCS(GetcN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGetcN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opGetcN(lhs, rhs); } - virtual string name() const { return "getc"; } - virtual string emitVerilog() { return "%k(%l.getc(%r))"; } - virtual string emitC() { return "VL_GETC_N(%li,%ri)"; } - virtual string emitSimpleOperator() { return ""; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual bool isHeavy() const { return true; } + virtual string name() const override { return "getc"; } + virtual string emitVerilog() override { return "%k(%l.getc(%r))"; } + virtual string emitC() override { return "VL_GETC_N(%li,%ri)"; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool isHeavy() const override { return true; } }; class AstGetcRefN : public AstNodeBiop { @@ -7915,21 +8001,21 @@ public: dtypeSetBitSized(8, VSigning::UNSIGNED); } ASTNODE_NODE_FUNCS(GetcRefN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstGetcRefN(this->fileline(), lhsp, rhsp); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { V3ERROR_NA; } - virtual string emitVerilog() { return "%k%l[%r]"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { return ""; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual bool isHeavy() const { return true; } + virtual string emitVerilog() override { return "%k%l[%r]"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool isHeavy() const override { return true; } }; class AstSubstrN : public AstNodeTriop { @@ -7941,21 +8027,21 @@ public: } ASTNODE_NODE_FUNCS(SubstrN) virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, - const V3Number& ths) { + const V3Number& ths) override { out.opSubstrN(lhs, rhs, ths); } - virtual string name() const { return "substr"; } - virtual string emitVerilog() { return "%k(%l.substr(%r,%t))"; } - virtual string emitC() { return "VL_SUBSTR_N(%li,%ri,%ti)"; } - virtual string emitSimpleOperator() { return ""; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool cleanThs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual bool sizeMattersThs() const { return false; } - virtual bool isHeavy() const { return true; } + virtual string name() const override { return "substr"; } + virtual string emitVerilog() override { return "%k(%l.substr(%r,%t))"; } + virtual string emitC() override { return "VL_SUBSTR_N(%li,%ri,%ti)"; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool cleanThs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool sizeMattersThs() const override { return false; } + virtual bool isHeavy() const override { return true; } }; class AstCompareNN : public AstNodeBiop { @@ -7965,30 +8051,30 @@ private: public: AstCompareNN(FileLine* fl, AstNode* lhsp, AstNode* rhsp, bool ignoreCase) : ASTGEN_SUPER(fl, lhsp, rhsp) - , m_ignoreCase(ignoreCase) { + , m_ignoreCase{ignoreCase} { dtypeSetUInt32(); } ASTNODE_NODE_FUNCS(CompareNN) - virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) { + virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) override { return new AstCompareNN(this->fileline(), lhsp, rhsp, m_ignoreCase); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { + virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) override { out.opCompareNN(lhs, rhs, m_ignoreCase); } - virtual string name() const { return m_ignoreCase ? "icompare" : "compare"; } - virtual string emitVerilog() { + virtual string name() const override { return m_ignoreCase ? "icompare" : "compare"; } + virtual string emitVerilog() override { return m_ignoreCase ? "%k(%l.icompare(%r))" : "%k(%l.compare(%r))"; } - virtual string emitC() { + virtual string emitC() override { return m_ignoreCase ? "VL_CMP_NN(%li,%ri,true)" : "VL_CMP_NN(%li,%ri,false)"; } - virtual string emitSimpleOperator() { return ""; } - virtual bool cleanOut() const { return true; } - virtual bool cleanLhs() const { return true; } - virtual bool cleanRhs() const { return true; } - virtual bool sizeMattersLhs() const { return false; } - virtual bool sizeMattersRhs() const { return false; } - virtual bool isHeavy() const { return true; } + virtual string emitSimpleOperator() override { return ""; } + virtual bool cleanOut() const override { return true; } + virtual bool cleanLhs() const override { return true; } + virtual bool cleanRhs() const override { return true; } + virtual bool sizeMattersLhs() const override { return false; } + virtual bool sizeMattersRhs() const override { return false; } + virtual bool isHeavy() const override { return true; } }; class AstFell : public AstNodeMath { @@ -8001,19 +8087,16 @@ public: addOp1p(exprp); } ASTNODE_NODE_FUNCS(Fell) - virtual string emitVerilog() { return "$fell(%l)"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { - V3ERROR_NA; - } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const { return widthInstrs(); } + virtual string emitVerilog() override { return "$fell(%l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + virtual int instrCount() const override { return widthInstrs(); } AstNode* exprp() const { return op1p(); } // op1 = expression AstSenTree* sentreep() const { return VN_CAST(op2p(), SenTree); } // op2 = clock domain void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } }; class AstPast : public AstNodeMath { @@ -8027,20 +8110,17 @@ public: addNOp2p(ticksp); } ASTNODE_NODE_FUNCS(Past) - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { - V3ERROR_NA; - } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const { return widthInstrs(); } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + virtual int instrCount() const override { return widthInstrs(); } AstNode* exprp() const { return op1p(); } // op1 = expression - AstNode* ticksp() const { return op2p(); } // op2 = ticks or NULL means 1 + AstNode* ticksp() const { return op2p(); } // op2 = ticks or nullptr means 1 AstSenTree* sentreep() const { return VN_CAST(op4p(), SenTree); } // op4 = clock domain void sentreep(AstSenTree* sentreep) { addOp4p(sentreep); } // op4 = clock domain - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } }; class AstRose : public AstNodeMath { @@ -8053,19 +8133,16 @@ public: addOp1p(exprp); } ASTNODE_NODE_FUNCS(Rose) - virtual string emitVerilog() { return "$rose(%l)"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { - V3ERROR_NA; - } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const { return widthInstrs(); } + virtual string emitVerilog() override { return "$rose(%l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + virtual int instrCount() const override { return widthInstrs(); } AstNode* exprp() const { return op1p(); } // op1 = expression AstSenTree* sentreep() const { return VN_CAST(op2p(), SenTree); } // op2 = clock domain void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } }; class AstSampled : public AstNodeMath { @@ -8078,14 +8155,14 @@ public: addOp1p(exprp); } ASTNODE_NODE_FUNCS(Sampled) - virtual string emitVerilog() { return "$sampled(%l)"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const { return 0; } + virtual string emitVerilog() override { return "$sampled(%l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + virtual int instrCount() const override { return 0; } AstNode* exprp() const { return op1p(); } // op1 = expression - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } }; class AstStable : public AstNodeMath { @@ -8098,19 +8175,16 @@ public: addOp1p(exprp); } ASTNODE_NODE_FUNCS(Stable) - virtual string emitVerilog() { return "$stable(%l)"; } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { - V3ERROR_NA; - } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const { return widthInstrs(); } + virtual string emitVerilog() override { return "$stable(%l)"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + virtual int instrCount() const override { return widthInstrs(); } AstNode* exprp() const { return op1p(); } // op1 = expression AstSenTree* sentreep() const { return VN_CAST(op2p(), SenTree); } // op2 = clock domain void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } }; class AstPattern : public AstNodeMath { @@ -8123,15 +8197,12 @@ public: addNOp2p(itemsp); } ASTNODE_NODE_FUNCS(Pattern) - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { - V3ERROR_NA; - } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const { return widthInstrs(); } - AstNodeDType* getChildDTypep() const { return childDTypep(); } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + virtual int instrCount() const override { return widthInstrs(); } + virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); } virtual AstNodeDType* subDTypep() const { return dtypep() ? dtypep() : childDTypep(); } // op1 = Type assigning to AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); } @@ -8143,27 +8214,23 @@ class AstPatMember : public AstNodeMath { // Parents: AstPattern // Children: expression, AstPattern, replication count private: - bool m_default; + bool m_default = false; public: AstPatMember(FileLine* fl, AstNode* lhsp, AstNode* keyp, AstNode* repp) : ASTGEN_SUPER(fl) { addOp1p(lhsp), setNOp2p(keyp), setNOp3p(repp); - m_default = false; } ASTNODE_NODE_FUNCS(PatMember) - virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) { - V3ERROR_NA; - } - virtual string emitVerilog() { return lhssp() ? "%f{%r{%k%l}}" : "%l"; } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual string emitSimpleOperator() { V3ERROR_NA_RETURN(""); } - virtual bool cleanOut() const { V3ERROR_NA_RETURN(""); } - virtual int instrCount() const { return widthInstrs() * 2; } + virtual string emitVerilog() override { return lhssp() ? "%f{%r{%k%l}}" : "%l"; } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } + virtual bool cleanOut() const override { V3ERROR_NA_RETURN(""); } + virtual int instrCount() const override { return widthInstrs() * 2; } // op1 = expression to assign or another AstPattern (list if replicated) AstNode* lhssp() const { return op1p(); } AstNode* keyp() const { return op2p(); } // op2 = assignment key (Const, id Text) - AstNode* repp() const { return op3p(); } // op3 = replication count, or NULL for count 1 + AstNode* repp() const { return op3p(); } // op3 = replication count, or nullptr for count 1 bool isDefault() const { return m_default; } void isDefault(bool flag) { m_default = flag; } }; @@ -8202,7 +8269,9 @@ public: addOp3p(propp); } ASTNODE_NODE_FUNCS(PropClocked) - virtual bool hasDType() const { return true; } // Used under Cover, which expects a bool child + virtual bool hasDType() const override { + return true; + } // Used under Cover, which expects a bool child AstSenItem* sensesp() const { return VN_CAST(op1p(), SenItem); } // op1 = Sensitivity list AstNode* disablep() const { return op2p(); } // op2 = disable AstNode* propp() const { return op3p(); } // op3 = property @@ -8225,11 +8294,11 @@ public: addNOp4p(passsp); } ASTNODE_BASE_FUNCS(NodeCoverOrAssert) - virtual string name() const { return m_name; } // * = Var name - virtual V3Hash sameHash() const { return V3Hash(name()); } - virtual bool same(const AstNode* samep) const { return samep->name() == name(); } - virtual void name(const string& name) { m_name = name; } - virtual void dump(std::ostream& str = std::cout) const; + virtual string name() const override { return m_name; } // * = Var name + virtual V3Hash sameHash() const override { return V3Hash(name()); } + virtual bool same(const AstNode* samep) const override { return samep->name() == name(); } + virtual void name(const string& name) override { m_name = name; } + virtual void dump(std::ostream& str = std::cout) const override; AstNode* propp() const { return op1p(); } // op1 = property AstSenTree* sentreep() const { return VN_CAST(op2p(), SenTree); } // op2 = clock domain void sentreep(AstSenTree* sentreep) { addOp2p(sentreep); } // op2 = clock domain @@ -8263,7 +8332,7 @@ class AstRestrict : public AstNodeCoverOrAssert { public: ASTNODE_NODE_FUNCS(Restrict) AstRestrict(FileLine* fl, AstNode* propp) - : ASTGEN_SUPER(fl, propp, NULL, false, "") {} + : ASTGEN_SUPER(fl, propp, nullptr, false, "") {} }; //====================================================================== @@ -8311,8 +8380,8 @@ public: AstScCtor(FileLine* fl, const string& textp) : ASTGEN_SUPER(fl, textp) {} ASTNODE_NODE_FUNCS(ScCtor) - virtual bool isPure() const { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const { return true; } + virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + virtual bool isOutputter() const override { return true; } }; class AstScDtor : public AstNodeText { @@ -8320,8 +8389,8 @@ public: AstScDtor(FileLine* fl, const string& textp) : ASTGEN_SUPER(fl, textp) {} ASTNODE_NODE_FUNCS(ScDtor) - virtual bool isPure() const { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const { return true; } + virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + virtual bool isOutputter() const override { return true; } }; class AstScHdr : public AstNodeText { @@ -8329,8 +8398,8 @@ public: AstScHdr(FileLine* fl, const string& textp) : ASTGEN_SUPER(fl, textp) {} ASTNODE_NODE_FUNCS(ScHdr) - virtual bool isPure() const { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const { return true; } + virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + virtual bool isOutputter() const override { return true; } }; class AstScImp : public AstNodeText { @@ -8338,8 +8407,8 @@ public: AstScImp(FileLine* fl, const string& textp) : ASTGEN_SUPER(fl, textp) {} ASTNODE_NODE_FUNCS(ScImp) - virtual bool isPure() const { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const { return true; } + virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + virtual bool isOutputter() const override { return true; } }; class AstScImpHdr : public AstNodeText { @@ -8347,8 +8416,8 @@ public: AstScImpHdr(FileLine* fl, const string& textp) : ASTGEN_SUPER(fl, textp) {} ASTNODE_NODE_FUNCS(ScImpHdr) - virtual bool isPure() const { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const { return true; } + virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + virtual bool isOutputter() const override { return true; } }; class AstScInt : public AstNodeText { @@ -8356,8 +8425,8 @@ public: AstScInt(FileLine* fl, const string& textp) : ASTGEN_SUPER(fl, textp) {} ASTNODE_NODE_FUNCS(ScInt) - virtual bool isPure() const { return false; } // SPECIAL: User may order w/other sigs - virtual bool isOutputter() const { return true; } + virtual bool isPure() const override { return false; } // SPECIAL: User may order w/other sigs + virtual bool isOutputter() const override { return true; } }; class AstUCStmt : public AstNodeStmt { @@ -8369,12 +8438,12 @@ public: } ASTNODE_NODE_FUNCS(UCStmt) AstNode* bodysp() const { return op1p(); } // op1 = expressions to print - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual bool isPure() const { return false; } - virtual bool isOutputter() const { return true; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual bool isPure() const override { return false; } + virtual bool isOutputter() const override { return true; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } }; //====================================================================== @@ -8392,9 +8461,9 @@ public: m_name = name; } ASTNODE_BASE_FUNCS(NodeFile) - virtual string name() const { return m_name; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual string name() const override { return m_name; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } void tblockp(AstTextBlock* tblockp) { setOp1p(tblockp); } AstTextBlock* tblockp() { return VN_CAST(op1p(), TextBlock); } }; @@ -8409,7 +8478,7 @@ public: AstVFile(FileLine* fl, const string& name) : ASTGEN_SUPER(fl, name) {} ASTNODE_NODE_FUNCS(VFile) - virtual void dump(std::ostream& str = std::cout) const; + virtual void dump(std::ostream& str = std::cout) const override; }; //====================================================================== @@ -8424,13 +8493,12 @@ private: bool m_support : 1; ///< Support file (non systemc) public: AstCFile(FileLine* fl, const string& name) - : ASTGEN_SUPER(fl, name) { - m_slow = false; - m_source = false; - m_support = false; - } + : ASTGEN_SUPER(fl, name) + , m_slow{false} + , m_source{false} + , m_support{false} {} ASTNODE_NODE_FUNCS(CFile) - virtual void dump(std::ostream& str = std::cout) const; + virtual void dump(std::ostream& str = std::cout) const override; bool slow() const { return m_slow; } void slow(bool flag) { m_slow = flag; } bool source() const { return m_source; } @@ -8449,7 +8517,8 @@ private: string m_name; string m_cname; // C name, for dpiExports string m_rtnType; // void, bool, or other return type - string m_argTypes; + string m_argTypes; // Argument types + string m_ctorInits; // Constructor sub-class inits string m_ifdef; // #ifdef symbol around this function VBoolOrUnknown m_isConst; // Function is declared const (*this not changed) VBoolOrUnknown m_isStatic; // Function is declared static (no this) @@ -8500,23 +8569,23 @@ public: m_dpiImportWrapper = false; } ASTNODE_NODE_FUNCS(CFunc) - virtual string name() const { return m_name; } - virtual const char* broken() const { + virtual string name() const override { return m_name; } + virtual const char* broken() const override { BROKEN_RTN((m_scopep && !m_scopep->brokeExists())); - return NULL; + return nullptr; } - virtual bool maybePointedTo() const { return true; } - virtual void dump(std::ostream& str = std::cout) const; - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { + virtual bool maybePointedTo() const override { return true; } + virtual void dump(std::ostream& str = std::cout) const override; + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { const AstCFunc* asamep = static_cast(samep); return ((funcType() == asamep->funcType()) && (rtnTypeVoid() == asamep->rtnTypeVoid()) - && (argTypes() == asamep->argTypes()) + && (argTypes() == asamep->argTypes()) && (ctorInits() == asamep->ctorInits()) && (!(dpiImport() || dpiExport()) || name() == asamep->name())); } // - virtual void name(const string& name) { m_name = name; } - virtual int instrCount() const { return dpiImport() ? instrCountDpi() : 0; } + virtual void name(const string& name) override { m_name = name; } + virtual int instrCount() const override { return dpiImport() ? instrCountDpi() : 0; } VBoolOrUnknown isConst() const { return m_isConst; } void isConst(bool flag) { m_isConst.setTrueOrFalse(flag); } void isConst(VBoolOrUnknown flag) { m_isConst = flag; } @@ -8543,6 +8612,8 @@ public: void funcPublic(bool flag) { m_funcPublic = flag; } void argTypes(const string& str) { m_argTypes = str; } string argTypes() const { return m_argTypes; } + void ctorInits(const string& str) { m_ctorInits = str; } + string ctorInits() const { return m_ctorInits; } void ifdef(const string& str) { m_ifdef = str; } string ifdef() const { return m_ifdef; } void funcType(AstCFuncType flag) { m_funcType = flag; } @@ -8583,7 +8654,8 @@ public: void addFinalsp(AstNode* nodep) { addOp4p(nodep); } // Special methods bool emptyBody() const { - return argsp() == NULL && initsp() == NULL && stmtsp() == NULL && finalsp() == NULL; + return argsp() == nullptr && initsp() == nullptr && stmtsp() == nullptr + && finalsp() == nullptr; } }; @@ -8592,7 +8664,7 @@ class AstCCall : public AstNodeCCall { // Parents: Anything above a statement // Children: Args to the function public: - AstCCall(FileLine* fl, AstCFunc* funcp, AstNode* argsp = NULL) + AstCCall(FileLine* fl, AstCFunc* funcp, AstNode* argsp = nullptr) : ASTGEN_SUPER(fl, funcp, argsp) {} // Replacement form for V3Combine // Note this removes old attachments from the oldp @@ -8606,17 +8678,19 @@ class AstCMethodCall : public AstNodeCCall { // Parents: Anything above a statement // Children: Args to the function public: - AstCMethodCall(FileLine* fl, AstNode* fromp, AstCFunc* funcp, AstNode* argsp = NULL) + AstCMethodCall(FileLine* fl, AstNode* fromp, AstCFunc* funcp, AstNode* argsp = nullptr) : ASTGEN_SUPER(fl, funcp, argsp) { setOp1p(fromp); } ASTNODE_NODE_FUNCS(CMethodCall) - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_BASE_RTN(AstNodeCCall::broken()); BROKEN_RTN(!fromp()); - return NULL; + return nullptr; } - AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing) + AstNode* fromp() const { + return op1p(); + } // op1 = Extracting what (nullptr=TBD during parsing) void fromp(AstNode* nodep) { setOp1p(nodep); } }; @@ -8625,7 +8699,7 @@ class AstCNew : public AstNodeCCall { // Parents: Anything above an expression // Children: Args to the function public: - AstCNew(FileLine* fl, AstCFunc* funcp, AstNode* argsp = NULL) + AstCNew(FileLine* fl, AstCFunc* funcp, AstNode* argsp = nullptr) : ASTGEN_SUPER(fl, funcp, argsp) { statement(false); } @@ -8633,7 +8707,7 @@ public: // Note this removes old attachments from the oldp AstCNew(AstCCall* oldp, AstCFunc* funcp) : ASTGEN_SUPER(oldp, funcp) {} - virtual bool hasDType() const { return true; } + virtual bool hasDType() const override { return true; } ASTNODE_NODE_FUNCS(CNew) }; @@ -8647,9 +8721,9 @@ public: setOp1p(lhsp); } ASTNODE_NODE_FUNCS(CReturn) - virtual int instrCount() const { return widthInstrs(); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual int instrCount() const override { return widthInstrs(); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } // AstNode* lhsp() const { return op1p(); } }; @@ -8662,26 +8736,26 @@ public: // Emit C textual math function (like AstUCFunc) AstCMath(FileLine* fl, AstNode* exprsp) : ASTGEN_SUPER(fl) - , m_cleanOut(true) - , m_pure(false) { + , m_cleanOut{true} + , m_pure{false} { addOp1p(exprsp); dtypeFrom(exprsp); } AstCMath(FileLine* fl, const string& textStmt, int setwidth, bool cleanOut = true) : ASTGEN_SUPER(fl) - , m_cleanOut(cleanOut) - , m_pure(true) { + , m_cleanOut{cleanOut} + , m_pure{true} { addNOp1p(new AstText(fl, textStmt, true)); if (setwidth) { dtypeSetLogicSized(setwidth, VSigning::UNSIGNED); } } ASTNODE_NODE_FUNCS(CMath) - virtual bool isGateOptimizable() const { return m_pure; } - virtual bool isPredictOptimizable() const { return m_pure; } - virtual bool cleanOut() const { return m_cleanOut; } - virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - virtual string emitC() { V3ERROR_NA_RETURN(""); } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual bool isGateOptimizable() const override { return m_pure; } + virtual bool isPredictOptimizable() const override { return m_pure; } + virtual bool cleanOut() const override { return m_cleanOut; } + virtual string emitVerilog() override { V3ERROR_NA_RETURN(""); } + virtual string emitC() override { V3ERROR_NA_RETURN(""); } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } void addBodysp(AstNode* nodep) { addNOp1p(nodep); } AstNode* bodysp() const { return op1p(); } // op1 = expressions to print bool pure() const { return m_pure; } @@ -8696,10 +8770,10 @@ public: addNOp1p(exprsp); } ASTNODE_NODE_FUNCS(CReset) - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } AstVarRef* varrefp() const { return VN_CAST(op1p(), VarRef); } // op1 = varref to reset }; @@ -8715,10 +8789,10 @@ public: addNOp1p(new AstText(fl, textStmt, true)); } ASTNODE_NODE_FUNCS(CStmt) - virtual bool isGateOptimizable() const { return false; } - virtual bool isPredictOptimizable() const { return false; } - virtual V3Hash sameHash() const { return V3Hash(); } - virtual bool same(const AstNode* samep) const { return true; } + virtual bool isGateOptimizable() const override { return false; } + virtual bool isPredictOptimizable() const override { return false; } + virtual V3Hash sameHash() const override { return V3Hash(); } + virtual bool same(const AstNode* samep) const override { return true; } void addBodysp(AstNode* nodep) { addNOp1p(nodep); } AstNode* bodysp() const { return op1p(); } // op1 = expressions to print }; @@ -8733,11 +8807,11 @@ private: public: AstCUse(FileLine* fl, VUseType useType, const string& name) : ASTGEN_SUPER(fl) - , m_useType(useType) - , m_name(name) {} + , m_useType{useType} + , m_name{name} {} ASTNODE_NODE_FUNCS(CUse) - virtual string name() const { return m_name; } - virtual void dump(std::ostream& str = std::cout) const; + virtual string name() const override { return m_name; } + virtual void dump(std::ostream& str = std::cout) const override; VUseType useType() const { return m_useType; } void useType(VUseType useType) { m_useType = useType; } }; @@ -8745,22 +8819,21 @@ public: class AstMTaskBody : public AstNode { // Hold statements for each MTask private: - ExecMTask* m_execMTaskp; + ExecMTask* m_execMTaskp = nullptr; public: explicit AstMTaskBody(FileLine* fl) - : ASTGEN_SUPER(fl) - , m_execMTaskp(NULL) {} + : ASTGEN_SUPER(fl) {} ASTNODE_NODE_FUNCS(MTaskBody); - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(!m_execMTaskp); - return NULL; + return nullptr; } AstNode* stmtsp() const { return op1p(); } void addStmtsp(AstNode* nodep) { addOp1p(nodep); } ExecMTask* execMTaskp() const { return m_execMTaskp; } void execMTaskp(ExecMTask* execMTaskp) { m_execMTaskp = execMTaskp; } - virtual void dump(std::ostream& str = std::cout) const; + virtual void dump(std::ostream& str = std::cout) const override; }; class AstExecGraph : public AstNode { @@ -8777,10 +8850,10 @@ private: public: explicit AstExecGraph(FileLine* fl); ASTNODE_NODE_FUNCS_NO_DTOR(ExecGraph) - virtual ~AstExecGraph(); - virtual const char* broken() const { + virtual ~AstExecGraph() override; + virtual const char* broken() const override { BROKEN_RTN(!m_depGraphp); - return NULL; + return nullptr; } const V3Graph* depGraphp() const { return m_depGraphp; } V3Graph* mutableDepGraphp() { return m_depGraphp; } @@ -8801,7 +8874,7 @@ public: class AstTypeTable : public AstNode { // Container for hash of standard data types // Children: NODEDTYPEs - AstVoidDType* m_voidp; + AstVoidDType* m_voidp = nullptr; AstBasicDType* m_basicps[AstBasicDTypeKwd::_ENUM_MAX]; // typedef std::map DetailedMap; @@ -8809,9 +8882,8 @@ class AstTypeTable : public AstNode { public: explicit AstTypeTable(FileLine* fl) - : ASTGEN_SUPER(fl) - , m_voidp(NULL) { - for (int i = 0; i < AstBasicDTypeKwd::_ENUM_MAX; ++i) m_basicps[i] = NULL; + : ASTGEN_SUPER(fl) { + for (int i = 0; i < AstBasicDTypeKwd::_ENUM_MAX; ++i) m_basicps[i] = nullptr; } ASTNODE_NODE_FUNCS(TypeTable) AstNodeDType* typesp() const { return VN_CAST(op1p(), NodeDType); } // op1 = List of dtypes @@ -8820,12 +8892,12 @@ public: AstBasicDType* findBasicDType(FileLine* fl, AstBasicDTypeKwd kwd); AstBasicDType* findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd, int width, int widthMin, VSigning numeric); - AstBasicDType* findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd, VNumRange range, + AstBasicDType* findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd, const VNumRange& range, int widthMin, VSigning numeric); AstBasicDType* findInsertSameDType(AstBasicDType* nodep); void clearCache(); void repairCache(); - virtual void dump(std::ostream& str = std::cout) const; + virtual void dump(std::ostream& str = std::cout) const override; }; //###################################################################### @@ -8836,27 +8908,23 @@ class AstNetlist : public AstNode { // Parents: none // Children: MODULEs & CFILEs private: - AstTypeTable* m_typeTablep; // Reference to top type table, for faster lookup - AstPackage* m_dollarUnitPkgp; // $unit - AstCFunc* m_evalp; // The '_eval' function - AstExecGraph* m_execGraphp; // Execution MTask graph for threads>1 mode + AstTypeTable* m_typeTablep = nullptr; // Reference to top type table, for faster lookup + AstPackage* m_dollarUnitPkgp = nullptr; // $unit + AstCFunc* m_evalp = nullptr; // The '_eval' function + AstExecGraph* m_execGraphp = nullptr; // Execution MTask graph for threads>1 mode VTimescale m_timeunit; // Global time unit VTimescale m_timeprecision; // Global time precision public: AstNetlist() - : ASTGEN_SUPER(new FileLine(FileLine::builtInFilename())) - , m_typeTablep(NULL) - , m_dollarUnitPkgp(NULL) - , m_evalp(NULL) - , m_execGraphp(NULL) {} + : ASTGEN_SUPER(new FileLine(FileLine::builtInFilename())) {} ASTNODE_NODE_FUNCS(Netlist) - virtual const char* broken() const { + virtual const char* broken() const override { BROKEN_RTN(m_dollarUnitPkgp && !m_dollarUnitPkgp->brokeExists()); BROKEN_RTN(m_evalp && !m_evalp->brokeExists()); - return NULL; + return nullptr; } - virtual string name() const { return "$root"; } - virtual void dump(std::ostream& str) const; + virtual string name() const override { return "$root"; } + virtual void dump(std::ostream& str) const override; AstNodeModule* modulesp() const { // op1 = List of modules return VN_CAST(op1p(), NodeModule); } diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index 30ae3cbc5..f5a7668ec 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -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 {} }; //###################################################################### diff --git a/src/V3Branch.cpp b/src/V3Branch.cpp index 94123dd6a..2aa42a9b3 100644 --- a/src/V3Branch.cpp +++ b/src/V3Branch.cpp @@ -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 {} }; //###################################################################### diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index e9371d2be..4af93f4ec 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -32,7 +32,7 @@ #include "V3AstConstOnly.h" #include -#include VL_INCLUDE_UNORDERED_MAP +#include //###################################################################### @@ -41,7 +41,7 @@ class BrokenTable : public AstNVisitor { private: // MEMBERS // For each node, we keep if it exists or not. - typedef vl_unordered_map NodeMap; // Performance matters (when --debug) + typedef std::unordered_map 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(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 {} }; //###################################################################### diff --git a/src/V3CCtors.cpp b/src/V3CCtors.cpp index a08f0dd5b..55c60685e 100644 --- a/src/V3CCtors.cpp +++ b/src/V3CCtors.cpp @@ -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); } diff --git a/src/V3CUse.cpp b/src/V3CUse.cpp index 82a20e7a5..087418028 100644 --- a/src/V3CUse.cpp +++ b/src/V3CUse.cpp @@ -32,7 +32,7 @@ #include "V3Ast.h" #include "V3EmitCBase.h" -#include VL_INCLUDE_UNORDERED_MAP +#include //###################################################################### @@ -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); }; diff --git a/src/V3Case.cpp b/src/V3Case.cpp index 01ba0b96d..ac15870f7 100644 --- a/src/V3Case.cpp +++ b/src/V3Case.cpp @@ -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); } diff --git a/src/V3Cast.cpp b/src/V3Cast.cpp index d8f24070f..66fb537c0 100644 --- a/src/V3Cast.cpp +++ b/src/V3Cast.cpp @@ -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 {} }; //###################################################################### diff --git a/src/V3Cdc.cpp b/src/V3Cdc.cpp index 7369d3b63..24f9703aa 100644 --- a/src/V3Cdc.cpp +++ b/src/V3Cdc.cpp @@ -37,7 +37,7 @@ #include #include -#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(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(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 ofp(V3File::new_ofstream(filename)); + const std::unique_ptr 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::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); } }; diff --git a/src/V3Changed.cpp b/src/V3Changed.cpp index 47be72d4c..471d0d03c 100644 --- a/src/V3Changed.cpp +++ b/src/V3Changed.cpp @@ -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 {} }; //###################################################################### diff --git a/src/V3Class.cpp b/src/V3Class.cpp index b942c30c5..df895f107 100644 --- a/src/V3Class.cpp +++ b/src/V3Class.cpp @@ -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 > MoveVector; + AstScope* m_classScopep = nullptr; // Package moving scopes into + typedef std::vector> 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()); } diff --git a/src/V3Clean.cpp b/src/V3Clean.cpp index 274c628c5..c67f18c1c 100644 --- a/src/V3Clean.cpp +++ b/src/V3Clean.cpp @@ -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 {} }; //###################################################################### diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp index a37b2f922..378bf4245 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -48,16 +48,16 @@ private: AstUser1InUse m_inuser1; // STATE - AstNodeModule* m_modp; // Current module - AstTopScope* m_topScopep; // Current top scope - AstScope* m_scopep; // Current scope - AstCFunc* m_evalFuncp; // Top eval function we are creating - AstCFunc* m_initFuncp; // Top initial function we are creating - AstCFunc* m_finalFuncp; // Top final function we are creating - AstCFunc* m_settleFuncp; // Top settlement function we are creating - AstSenTree* m_lastSenp; // Last sensitivity match, so we can detect duplicates. - AstIf* m_lastIfp; // Last sensitivity if active to add more under - AstMTaskBody* m_mtaskBodyp; // Current mtask body + AstNodeModule* m_modp = nullptr; // Current module + AstTopScope* m_topScopep = nullptr; // Current top scope + AstScope* m_scopep = nullptr; // Current scope + AstCFunc* m_evalFuncp = nullptr; // Top eval function we are creating + AstCFunc* m_initFuncp = nullptr; // Top initial function we are creating + AstCFunc* m_finalFuncp = nullptr; // Top final function we are creating + AstCFunc* m_settleFuncp = nullptr; // Top settlement function we are creating + AstSenTree* m_lastSenp = nullptr; // Last sensitivity match, so we can detect duplicates. + AstIf* m_lastIfp = nullptr; // Last sensitivity if active to add more under + AstMTaskBody* m_mtaskBodyp = nullptr; // Current mtask body // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -101,11 +101,11 @@ private: // BOTHEDGE: var ^ var_last // HIGHEDGE: var // LOWEDGE: ~var - AstNode* newp = NULL; + AstNode* newp = nullptr; if (nodep->edgeType() == VEdgeType::ET_ILLEGAL) { nodep->v3warn(E_UNSUPPORTED, "Unsupported: Complicated event expression in sensitive activity list"); - return NULL; + return nullptr; } AstVarScope* clkvscp = nodep->varrefp()->varScopep(); if (nodep->edgeType() == VEdgeType::ET_POSEDGE) { @@ -138,7 +138,7 @@ private: } AstNode* createSenseEquation(AstSenItem* nodesp) { // Nodep may be a list of elements; we need to walk it - AstNode* senEqnp = NULL; + AstNode* senEqnp = nullptr; for (AstSenItem* senp = nodesp; senp; senp = VN_CAST(senp->nextp(), SenItem)) { AstNode* const senOnep = createSenItemEquation(senp); if (senEqnp) { @@ -153,16 +153,53 @@ private: AstIf* makeActiveIf(AstSenTree* sensesp) { AstNode* senEqnp = createSenseEquation(sensesp->sensesp()); UASSERT_OBJ(senEqnp, sensesp, "No sense equation, shouldn't be in sequent activation."); - AstIf* newifp = new AstIf(sensesp->fileline(), senEqnp, NULL, NULL); + AstIf* newifp = new AstIf(sensesp->fileline(), senEqnp, nullptr, nullptr); return newifp; } void clearLastSen() { - m_lastSenp = NULL; - m_lastIfp = NULL; + m_lastSenp = nullptr; + m_lastIfp = nullptr; + } + void splitCheck(AstCFunc* ofuncp) { + if (!v3Global.opt.outputSplitCFuncs() || !ofuncp->stmtsp()) return; + if (EmitCBaseCounterVisitor(ofuncp->stmtsp()).count() < v3Global.opt.outputSplitCFuncs()) + return; + + int funcnum = 0; + int func_stmts = 0; + AstCFunc* funcp = nullptr; + + // Unlink all statements, then add item by item to new sub-functions + AstBegin* tempp = new AstBegin{ofuncp->fileline(), "[EditWrapper]", + ofuncp->stmtsp()->unlinkFrBackWithNext()}; + if (ofuncp->finalsp()) tempp->addStmtsp(ofuncp->finalsp()->unlinkFrBackWithNext()); + while (tempp->stmtsp()) { + AstNode* itemp = tempp->stmtsp()->unlinkFrBack(); + int stmts = EmitCBaseCounterVisitor(itemp).count(); + if (!funcp || (func_stmts + stmts) > v3Global.opt.outputSplitCFuncs()) { + // Make a new function + funcp = new AstCFunc{ofuncp->fileline(), ofuncp->name() + cvtToStr(++funcnum), + m_topScopep->scopep()}; + funcp->argTypes(EmitCBaseVisitor::symClassVar()); + funcp->dontCombine(true); + funcp->symProlog(true); + funcp->isStatic(true); + funcp->slow(ofuncp->slow()); + m_topScopep->scopep()->addActivep(funcp); + // + AstCCall* callp = new AstCCall{funcp->fileline(), funcp}; + callp->argTypes("vlSymsp"); + ofuncp->addStmtsp(callp); + func_stmts = 0; + } + funcp->addStmtsp(itemp); + func_stmts += stmts; + } + VL_DO_DANGLING(tempp->deleteTree(), tempp); } // VISITORS - virtual void visit(AstTopScope* nodep) VL_OVERRIDE { + virtual void visit(AstTopScope* nodep) override { UINFO(4, " TOPSCOPE " << nodep << endl); m_topScopep = nodep; m_scopep = nodep->scopep(); @@ -172,28 +209,29 @@ private: AstNode::user1ClearTree(); // Make top functions { - AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval", m_scopep); + AstCFunc* funcp = new AstCFunc{nodep->fileline(), "_eval", m_topScopep->scopep()}; funcp->argTypes(EmitCBaseVisitor::symClassVar()); funcp->dontCombine(true); funcp->symProlog(true); funcp->isStatic(true); funcp->entryPoint(true); - m_scopep->addActivep(funcp); + m_topScopep->scopep()->addActivep(funcp); m_evalFuncp = funcp; } { - AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval_initial", m_scopep); + AstCFunc* funcp + = new AstCFunc{nodep->fileline(), "_eval_initial", m_topScopep->scopep()}; funcp->argTypes(EmitCBaseVisitor::symClassVar()); funcp->dontCombine(true); funcp->slow(true); funcp->symProlog(true); funcp->isStatic(true); funcp->entryPoint(true); - m_scopep->addActivep(funcp); + m_topScopep->scopep()->addActivep(funcp); m_initFuncp = funcp; } { - AstCFunc* funcp = new AstCFunc(nodep->fileline(), "final", m_scopep); + AstCFunc* funcp = new AstCFunc{nodep->fileline(), "final", m_topScopep->scopep()}; funcp->skipDecl(true); funcp->dontCombine(true); funcp->slow(true); @@ -204,38 +242,44 @@ private: + " = this->__VlSymsp;\n")); funcp->addInitsp( new AstCStmt(nodep->fileline(), EmitCBaseVisitor::symTopAssign() + "\n")); - m_scopep->addActivep(funcp); + m_topScopep->scopep()->addActivep(funcp); m_finalFuncp = funcp; } { - AstCFunc* funcp = new AstCFunc(nodep->fileline(), "_eval_settle", m_scopep); + AstCFunc* funcp + = new AstCFunc{nodep->fileline(), "_eval_settle", m_topScopep->scopep()}; funcp->argTypes(EmitCBaseVisitor::symClassVar()); funcp->dontCombine(true); funcp->slow(true); funcp->isStatic(true); funcp->symProlog(true); funcp->entryPoint(true); - m_scopep->addActivep(funcp); + m_topScopep->scopep()->addActivep(funcp); m_settleFuncp = funcp; } // Process the activates iterateChildren(nodep); + UINFO(4, " TOPSCOPE iter done " << nodep << endl); + // Split large functions + splitCheck(m_evalFuncp); + splitCheck(m_initFuncp); + splitCheck(m_finalFuncp); + splitCheck(m_settleFuncp); // Done, clear so we can detect errors UINFO(4, " TOPSCOPEDONE " << nodep << endl); clearLastSen(); - m_topScopep = NULL; - m_scopep = NULL; + m_topScopep = nullptr; + m_scopep = nullptr; } - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { + virtual void visit(AstNodeModule* nodep) override { // UINFO(4, " MOD " << nodep << endl); - AstNodeModule* origModp = m_modp; + VL_RESTORER(m_modp); { m_modp = nodep; iterateChildren(nodep); } - m_modp = origModp; } - virtual void visit(AstScope* nodep) VL_OVERRIDE { + virtual void visit(AstScope* nodep) override { // UINFO(4, " SCOPE " << nodep << endl); m_scopep = nodep; iterateChildren(nodep); @@ -244,9 +288,9 @@ private: movep->unlinkFrBackWithNext(); m_evalFuncp->addFinalsp(movep); } - m_scopep = NULL; + m_scopep = nullptr; } - virtual void visit(AstAlways* nodep) VL_OVERRIDE { + virtual void visit(AstAlways* nodep) override { AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true); nodep->replaceWith(cmtp); if (AstNode* stmtsp = nodep->bodysp()) { @@ -255,7 +299,7 @@ private: } VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstAlwaysPost* nodep) VL_OVERRIDE { + virtual void visit(AstAlwaysPost* nodep) override { AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true); nodep->replaceWith(cmtp); if (AstNode* stmtsp = nodep->bodysp()) { @@ -264,7 +308,7 @@ private: } VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE { + virtual void visit(AstCoverToggle* nodep) override { // nodep->dumpTree(cout, "ct:"); // COVERTOGGLE(INC, ORIG, CHANGE) -> // IF(ORIG ^ CHANGE) { INC; CHANGE = ORIG; } @@ -272,7 +316,7 @@ private: AstNode* origp = nodep->origp()->unlinkFrBack(); AstNode* changep = nodep->changep()->unlinkFrBack(); AstIf* newp = new AstIf(nodep->fileline(), new AstXor(nodep->fileline(), origp, changep), - incp, NULL); + incp, nullptr); // We could add another IF to detect posedges, and only increment if so. // It's another whole branch though versus a potential memory miss. // We'll go with the miss. @@ -281,7 +325,7 @@ private: nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstInitial* nodep) VL_OVERRIDE { + virtual void visit(AstInitial* nodep) override { AstNode* cmtp = new AstComment(nodep->fileline(), nodep->typeName(), true); nodep->replaceWith(cmtp); if (AstNode* stmtsp = nodep->bodysp()) { @@ -290,7 +334,7 @@ private: } VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstCFunc* nodep) override { iterateChildren(nodep); // Link to global function if (nodep->formCallTree()) { @@ -300,7 +344,7 @@ private: m_finalFuncp->addStmtsp(callp); } } - virtual void visit(AstSenTree* nodep) VL_OVERRIDE { + virtual void visit(AstSenTree* nodep) override { // Delete it later; Actives still pointing to it nodep->unlinkFrBack(); pushDeletep(nodep); @@ -314,7 +358,7 @@ private: void addToInitial(AstNode* stmtsp) { m_initFuncp->addStmtsp(stmtsp); // add to top level function } - virtual void visit(AstActive* nodep) VL_OVERRIDE { + virtual void visit(AstActive* nodep) override { // Careful if adding variables here, ACTIVES can be under other ACTIVES // Need to save and restore any member state in AstUntilStable block if (!m_topScopep || !nodep->stmtsp()) { @@ -382,7 +426,7 @@ private: VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } } - virtual void visit(AstExecGraph* nodep) VL_OVERRIDE { + virtual void visit(AstExecGraph* nodep) override { for (m_mtaskBodyp = VN_CAST(nodep->op1p(), MTaskBody); m_mtaskBodyp; m_mtaskBodyp = VN_CAST(m_mtaskBodyp->nextp(), MTaskBody)) { clearLastSen(); @@ -397,28 +441,17 @@ private: } //-------------------- - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit ClockVisitor(AstNetlist* nodep) { - m_modp = NULL; - m_evalFuncp = NULL; - m_initFuncp = NULL; - m_finalFuncp = NULL; - m_settleFuncp = NULL; - m_topScopep = NULL; - m_lastSenp = NULL; - m_lastIfp = NULL; - m_scopep = NULL; - m_mtaskBodyp = NULL; - // iterate(nodep); // Allow downstream modules to find _eval() // easily without iterating through the tree. nodep->evalp(m_evalFuncp); } - virtual ~ClockVisitor() {} + virtual ~ClockVisitor() override {} }; //###################################################################### diff --git a/src/V3Combine.cpp b/src/V3Combine.cpp index c38cc96f7..c938da506 100644 --- a/src/V3Combine.cpp +++ b/src/V3Combine.cpp @@ -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 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 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); } }; diff --git a/src/V3Config.cpp b/src/V3Config.cpp index aab3e6d62..a1e12f5f0 100644 --- a/src/V3Config.cpp +++ b/src/V3Config.cpp @@ -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 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 V3ConfigFTaskResolver; // Modules have tasks, variables, named blocks and properties class V3ConfigModule { - typedef vl_unordered_set StringSet; + typedef std::unordered_set StringSet; typedef std::set 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; diff --git a/src/V3Const.cpp b/src/V3Const.cpp index 097562560..ef617c634 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -41,10 +41,10 @@ class ConstVarMarkVisitor : public AstNVisitor { // AstVar::user4p -> bool, Var marked, 0=not set yet private: // VISITORS - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { if (nodep->varp()) nodep->varp()->user4(1); } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -52,29 +52,26 @@ public: AstNode::user4ClearTree(); // Check marked InUse before we're called iterate(nodep); } - virtual ~ConstVarMarkVisitor() {} + virtual ~ConstVarMarkVisitor() override {} }; class ConstVarFindVisitor : public AstNVisitor { // NODE STATE // AstVar::user4p -> bool, input from ConstVarMarkVisitor // MEMBERS - bool m_found; + bool m_found = false; private: // VISITORS - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { if (nodep->varp() && nodep->varp()->user4()) m_found = true; } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - explicit ConstVarFindVisitor(AstNode* nodep) { - m_found = false; - iterateAndNextNull(nodep); - } - virtual ~ConstVarFindVisitor() {} + explicit ConstVarFindVisitor(AstNode* nodep) { iterateAndNextNull(nodep); } + virtual ~ConstVarFindVisitor() override {} // METHODS bool found() const { return m_found; } }; @@ -92,20 +89,20 @@ private: // AstEnum::user4 -> bool. Recursing. // STATE - bool m_params; // If true, propagate parameterized and true numbers only - bool m_required; // If true, must become a constant - bool m_wremove; // Inside scope, no assignw removal - bool m_warn; // Output warnings - bool m_doExpensive; // Enable computationally expensive optimizations - bool m_doNConst; // Enable non-constant-child simplifications - bool m_doShort; // Remove expressions that short circuit - bool m_doV; // Verilog, not C++ conversion - bool m_doGenerate; // Postpone width checking inside generate - bool m_hasJumpDelay; // JumpGo or Delay under this while - AstNodeModule* m_modp; // Current module - AstArraySel* m_selp; // Current select - AstNode* m_scopep; // Current scope - AstAttrOf* m_attrp; // Current attribute + bool m_params = false; // If true, propagate parameterized and true numbers only + bool m_required = false; // If true, must become a constant + bool m_wremove = true; // Inside scope, no assignw removal + bool m_warn = false; // Output warnings + bool m_doExpensive = false; // Enable computationally expensive optimizations + bool m_doNConst = false; // Enable non-constant-child simplifications + bool m_doShort = true; // Remove expressions that short circuit + bool m_doV = false; // Verilog, not C++ conversion + bool m_doGenerate = false; // Postpone width checking inside generate + bool m_hasJumpDelay = false; // JumpGo or Delay under this while + AstNodeModule* m_modp = nullptr; // Current module + AstArraySel* m_selp = nullptr; // Current select + AstNode* m_scopep = nullptr; // Current scope + AstAttrOf* m_attrp = nullptr; // Current attribute // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -1115,7 +1112,7 @@ private: AstSel* sel2p = new AstSel(conp->fileline(), rhs2p, lsb2, msb2 - lsb2 + 1); // Make new assigns of same flavor as old one //*** Not cloneTree; just one node. - AstNode* newp = NULL; + AstNode* newp = nullptr; if (!need_temp) { AstNodeAssign* asn1ap = VN_CAST(nodep->cloneType(lc1p, sel1p), NodeAssign); AstNodeAssign* asn2ap = VN_CAST(nodep->cloneType(lc2p, sel2p), NodeAssign); @@ -1282,32 +1279,31 @@ private: //---------------------------------------- // VISITORS - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { // Iterate modules backwards, in bottom-up order. That's faster iterateChildrenBackwards(nodep); } - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { - AstNodeModule* origModp = m_modp; + virtual void visit(AstNodeModule* nodep) override { + VL_RESTORER(m_modp); { m_modp = nodep; iterateChildren(nodep); } - m_modp = origModp; } - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstCFunc* nodep) override { // No ASSIGNW removals under funcs, we've long eliminated INITIALs // (We should perhaps rename the assignw's to just assigns) m_wremove = false; iterateChildren(nodep); m_wremove = true; } - virtual void visit(AstScope* nodep) VL_OVERRIDE { + virtual void visit(AstScope* nodep) override { // No ASSIGNW removals under scope, we've long eliminated INITIALs m_scopep = nodep; m_wremove = false; iterateChildren(nodep); m_wremove = true; - m_scopep = NULL; + m_scopep = nullptr; } void swapSides(AstNodeBiCom* nodep) { @@ -1373,16 +1369,16 @@ private: } // Special cases - virtual void visit(AstConst*) VL_OVERRIDE {} // Already constant + virtual void visit(AstConst*) override {} // Already constant - virtual void visit(AstCell* nodep) VL_OVERRIDE { + virtual void visit(AstCell* nodep) override { if (m_params) { iterateAndNextNull(nodep->paramsp()); } else { iterateChildren(nodep); } } - virtual void visit(AstPin* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstPin* nodep) override { iterateChildren(nodep); } void replaceLogEq(AstLogEq* nodep) { // LOGEQ(a,b) => AstLogAnd{AstLogOr{AstLogNot{a},b},AstLogOr{AstLogNot{b},a}} @@ -1563,14 +1559,15 @@ private: VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstAttrOf* nodep) VL_OVERRIDE { - AstAttrOf* oldAttr = m_attrp; - m_attrp = nodep; - iterateChildren(nodep); - m_attrp = oldAttr; + virtual void visit(AstAttrOf* nodep) override { + VL_RESTORER(m_attrp); + { + m_attrp = nodep; + iterateChildren(nodep); + } } - virtual void visit(AstArraySel* nodep) VL_OVERRIDE { + virtual void visit(AstArraySel* nodep) override { iterateAndNextNull(nodep->bitp()); if (VN_IS(nodep->bitp(), Const) && VN_IS(nodep->fromp(), VarRef) @@ -1594,9 +1591,9 @@ private: VL_DO_DANGLING(nodep->deleteTree(), nodep); } } - m_selp = NULL; + m_selp = nullptr; } - virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstNodeVarRef* nodep) override { iterateChildren(nodep); UASSERT_OBJ(nodep->varp(), nodep, "Not linked"); bool did = false; @@ -1650,7 +1647,7 @@ private: << nodep->varp()->prettyNameQ()); } } - virtual void visit(AstEnumItemRef* nodep) VL_OVERRIDE { + virtual void visit(AstEnumItemRef* nodep) override { iterateChildren(nodep); UASSERT_OBJ(nodep->itemp(), nodep, "Not linked"); bool did = false; @@ -1675,7 +1672,7 @@ private: } } - // virtual void visit(AstCvtPackString* nodep) VL_OVERRIDE { + // virtual void visit(AstCvtPackString* nodep) override { // Not constant propagated (for today) because AstNodeMath::isOpaque is set // Someday if lower is constant, convert to quoted "string". @@ -1683,7 +1680,7 @@ private: // Only one if it's not in a list return (!nodep->nextp() && nodep->backp()->nextp() != nodep); } - virtual void visit(AstSenItem* nodep) VL_OVERRIDE { + virtual void visit(AstSenItem* nodep) override { iterateChildren(nodep); if (m_doNConst && (VN_IS(nodep->sensp(), Const) || VN_IS(nodep->sensp(), EnumItemRef) @@ -1750,7 +1747,7 @@ private: } }; - virtual void visit(AstSenTree* nodep) VL_OVERRIDE { + virtual void visit(AstSenTree* nodep) override { iterateChildren(nodep); if (m_doExpensive) { // cout<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 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::iterator it = vec.begin(); it != vec.end(); - ++it) { - (*it)->unlinkFrBack(); - } - for (std::vector::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); diff --git a/src/V3Coverage.cpp b/src/V3Coverage.cpp index ccbd365cb..f371d4fa8 100644 --- a/src/V3Coverage.cpp +++ b/src/V3Coverage.cpp @@ -32,7 +32,7 @@ #include "V3Ast.h" #include -#include VL_INCLUDE_UNORDERED_MAP +#include //###################################################################### // Coverage state, as a visitor of each AstNode @@ -40,41 +40,37 @@ class CoverageVisitor : public AstNVisitor { private: // TYPES - typedef vl_unordered_map VarNameMap; + typedef std::unordered_map VarNameMap; typedef std::set LinenoSet; - typedef vl_unordered_map HandleLines; + typedef std::unordered_map 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 {} }; //###################################################################### diff --git a/src/V3CoverageJoin.cpp b/src/V3CoverageJoin.cpp index b0b1025ac..94da008d7 100644 --- a/src/V3CoverageJoin.cpp +++ b/src/V3CoverageJoin.cpp @@ -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); } }; diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp index 7a0add24c..9f709f5ab 100644 --- a/src/V3Dead.cpp +++ b/src/V3Dead.cpp @@ -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::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::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::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 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 {} }; //###################################################################### diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp index 87faab264..4ba1acb24 100644 --- a/src/V3Delayed.cpp +++ b/src/V3Delayed.cpp @@ -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, 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); } }; diff --git a/src/V3Depth.cpp b/src/V3Depth.cpp index 9ca85d2ef..d76a5cc11 100644 --- a/src/V3Depth.cpp +++ b/src/V3Depth.cpp @@ -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 {} }; //###################################################################### diff --git a/src/V3DepthBlock.cpp b/src/V3DepthBlock.cpp index 55000a20a..54db059ec 100644 --- a/src/V3DepthBlock.cpp +++ b/src/V3DepthBlock.cpp @@ -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 {} }; //###################################################################### diff --git a/src/V3Descope.cpp b/src/V3Descope.cpp index d969ec144..007c8236e 100644 --- a/src/V3Descope.cpp +++ b/src/V3Descope.cpp @@ -45,11 +45,11 @@ private: typedef std::multimap 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 {} }; //###################################################################### diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 441ca96be..467d8af97 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -28,11 +28,12 @@ #include #include #include -#include VL_INCLUDE_UNORDERED_SET +#include -#define VL_VALUE_STRING_MAX_WIDTH 8192 // We use a static char array in VL_VALUE_STRING +constexpr int VL_VALUE_STRING_MAX_WIDTH = 8192; // We use a static char array in VL_VALUE_STRING -#define EMITC_NUM_CONSTW 8 // Number of VL_CONST_W_*X's in verilated.h (IE VL_CONST_W_8X is last) +constexpr int EMITC_NUM_CONSTW + = 8; // Number of VL_CONST_W_*X's in verilated.h (IE VL_CONST_W_8X is last) //###################################################################### // Emit statements and math operators @@ -62,7 +63,7 @@ public: int splitSize() const { return m_splitSize; } void splitSizeInc(int count) { m_splitSize += count; } void splitSizeInc(AstNode* nodep) { splitSizeInc(EmitCBaseCounterVisitor(nodep).count()); } - bool splitNeeded() { + bool splitNeeded() const { return (splitSize() && v3Global.opt.outputSplit() && v3Global.opt.outputSplit() < splitSize()); } @@ -75,7 +76,7 @@ public: char fmtLetter); void emitVarDecl(const AstVar* nodep, const string& prefixIfImp); - typedef enum { + typedef enum : uint8_t { EVL_CLASS_IO, EVL_CLASS_SIG, EVL_CLASS_TEMP, @@ -226,8 +227,7 @@ public: stable_sort(funcsp.begin(), funcsp.end(), CmpName()); - for (FuncVec::iterator it = funcsp.begin(); it != funcsp.end(); ++it) { - const AstCFunc* funcp = *it; + for (const AstCFunc* funcp : funcsp) { ofp()->putsPrivate(funcp->declPrivate()); if (!funcp->ifdef().empty()) puts("#ifdef " + funcp->ifdef() + "\n"); if (funcp->isStatic().trueUnknown()) puts("static "); @@ -264,9 +264,18 @@ public: puts("static void __Vmtask__final(bool even_cycle, void* symtab);\n"); } } + void ccallIterateArgs(AstNodeCCall* nodep) { + puts(nodep->argTypes()); + bool comma = (nodep->argTypes() != ""); + for (AstNode* subnodep = nodep->argsp(); subnodep; subnodep = subnodep->nextp()) { + if (comma) puts(", "); + iterate(subnodep); + comma = true; + } + } // VISITORS - virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { + virtual void visit(AstNodeAssign* nodep) override { bool paren = true; bool decind = false; if (AstSel* selp = VN_CAST(nodep->lhsp(), Sel)) { @@ -347,8 +356,8 @@ public: if (decind) ofp()->blockDec(); if (!m_suppressSemi) puts(";\n"); } - virtual void visit(AstAlwaysPublic*) VL_OVERRIDE {} - virtual void visit(AstAssocSel* nodep) VL_OVERRIDE { + virtual void visit(AstAlwaysPublic*) override {} + virtual void visit(AstAssocSel* nodep) override { iterateAndNextNull(nodep->fromp()); putbs(".at("); AstAssocArrayDType* adtypep = VN_CAST(nodep->fromp()->dtypep(), AssocArrayDType); @@ -363,7 +372,7 @@ public: puts(".data()"); // Access returned std::array as C array } } - virtual void visit(AstNodeCCall* nodep) VL_OVERRIDE { + virtual void visit(AstNodeCCall* nodep) override { if (AstCMethodCall* ccallp = VN_CAST(nodep, CMethodCall)) { // make this a Ast type for future opt iterate(ccallp->fromp()); @@ -373,13 +382,7 @@ public: } puts(nodep->funcp()->nameProtect()); puts("("); - puts(nodep->argTypes()); - bool comma = (nodep->argTypes() != ""); - for (AstNode* subnodep = nodep->argsp(); subnodep; subnodep = subnodep->nextp()) { - if (comma) puts(", "); - iterate(subnodep); - comma = true; - } + ccallIterateArgs(nodep); if (VN_IS(nodep->backp(), NodeMath) || VN_IS(nodep->backp(), CReturn)) { // We should have a separate CCall for math and statement usage, but... puts(")"); @@ -387,7 +390,7 @@ public: puts(");\n"); } } - virtual void visit(AstCMethodHard* nodep) VL_OVERRIDE { + virtual void visit(AstCMethodHard* nodep) override { iterate(nodep->fromp()); puts("."); puts(nodep->nameProtect()); @@ -415,14 +418,14 @@ public: UASSERT_OBJ(!nodep->isStatement() || VN_IS(nodep->dtypep(), VoidDType), nodep, "Statement of non-void data type"); } - virtual void visit(AstIntfRef* nodep) VL_OVERRIDE { + virtual void visit(AstIntfRef* nodep) override { putsQuoted(VIdProtect::protectWordsIf(AstNode::vcdName(nodep->name()), nodep->protect())); } - virtual void visit(AstNodeCase* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE + virtual void visit(AstNodeCase* nodep) override { // LCOV_EXCL_LINE // In V3Case... nodep->v3fatalSrc("Case statements should have been reduced out"); } - virtual void visit(AstComment* nodep) VL_OVERRIDE { + virtual void visit(AstComment* nodep) override { string at; if (nodep->showAt()) { at = " at " + nodep->fileline()->ascii(); @@ -434,7 +437,7 @@ public: } iterateChildren(nodep); } - virtual void visit(AstCoverDecl* nodep) VL_OVERRIDE { + virtual void visit(AstCoverDecl* nodep) override { puts("__vlCoverInsert("); // As Declared in emitCoverageDecl puts("&(vlSymsp->__Vcoverage["); puts(cvtToStr(nodep->dataDeclThisp()->binNum())); @@ -462,7 +465,7 @@ public: putsQuoted(nodep->linescov()); puts(");\n"); } - virtual void visit(AstCoverInc* nodep) VL_OVERRIDE { + virtual void visit(AstCoverInc* nodep) override { if (v3Global.opt.threads()) { puts("vlSymsp->__Vcoverage["); puts(cvtToStr(nodep->declp()->dataDeclThisp()->binNum())); @@ -473,17 +476,17 @@ public: puts("]);\n"); } } - virtual void visit(AstCReturn* nodep) VL_OVERRIDE { + virtual void visit(AstCReturn* nodep) override { puts("return ("); iterateAndNextNull(nodep->lhsp()); puts(");\n"); } - virtual void visit(AstDisplay* nodep) VL_OVERRIDE { + virtual void visit(AstDisplay* nodep) override { string text = nodep->fmtp()->text(); if (nodep->addNewline()) text += "\n"; displayNode(nodep, nodep->fmtp()->scopeNamep(), text, nodep->fmtp()->exprsp(), false); } - virtual void visit(AstDumpCtl* nodep) VL_OVERRIDE { + virtual void visit(AstDumpCtl* nodep) override { switch (nodep->ctlType()) { case VDumpCtlType::FILE: puts("vl_dumpctl_filenamep(true, "); @@ -522,7 +525,7 @@ public: default: nodep->v3fatalSrc("Bad case, unexpected " << nodep->ctlType().ascii()); } } - virtual void visit(AstScopeName* nodep) VL_OVERRIDE { + virtual void visit(AstScopeName* nodep) override { // For use under AstCCalls for dpiImports. ScopeNames under // displays are handled in AstDisplay if (!nodep->dpiExport()) { @@ -531,20 +534,20 @@ public: putbs("(&(vlSymsp->" + protect("__Vscope_" + scope) + "))"); } } - virtual void visit(AstSFormat* nodep) VL_OVERRIDE { + virtual void visit(AstSFormat* nodep) override { displayNode(nodep, nodep->fmtp()->scopeNamep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp(), false); } - virtual void visit(AstSFormatF* nodep) VL_OVERRIDE { + virtual void visit(AstSFormatF* nodep) override { displayNode(nodep, nodep->scopeNamep(), nodep->text(), nodep->exprsp(), false); } - virtual void visit(AstFScanF* nodep) VL_OVERRIDE { - displayNode(nodep, NULL, nodep->text(), nodep->exprsp(), true); + virtual void visit(AstFScanF* nodep) override { + displayNode(nodep, nullptr, nodep->text(), nodep->exprsp(), true); } - virtual void visit(AstSScanF* nodep) VL_OVERRIDE { - displayNode(nodep, NULL, nodep->text(), nodep->exprsp(), true); + virtual void visit(AstSScanF* nodep) override { + displayNode(nodep, nullptr, nodep->text(), nodep->exprsp(), true); } - virtual void visit(AstValuePlusArgs* nodep) VL_OVERRIDE { + virtual void visit(AstValuePlusArgs* nodep) override { puts("VL_VALUEPLUSARGS_IN"); emitIQW(nodep->outp()); puts("("); @@ -556,21 +559,21 @@ public: iterateAndNextNull(nodep->outp()); puts(")"); } - virtual void visit(AstTestPlusArgs* nodep) VL_OVERRIDE { + virtual void visit(AstTestPlusArgs* nodep) override { puts("VL_TESTPLUSARGS_I("); putsQuoted(nodep->text()); puts(")"); } - virtual void visit(AstFError* nodep) VL_OVERRIDE { + virtual void visit(AstFError* nodep) override { puts("VL_FERROR_IN("); iterateAndNextNull(nodep->filep()); putbs(", "); iterateAndNextNull(nodep->strp()); puts(")"); } - virtual void visit(AstFGetS* nodep) VL_OVERRIDE { + virtual void visit(AstFGetS* nodep) override { checkMaxWords(nodep); - emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), NULL); + emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), nullptr); } void checkMaxWords(AstNode* nodep) { @@ -581,7 +584,7 @@ public: << " bits exceeds hardcoded limit VL_TO_STRING_MAX_WORDS in verilatedos.h"); } } - virtual void visit(AstFOpen* nodep) VL_OVERRIDE { + virtual void visit(AstFOpen* nodep) override { iterateAndNextNull(nodep->filep()); puts(" = VL_FOPEN_NN("); emitCvtPackStr(nodep->filenamep()); @@ -591,13 +594,13 @@ public: emitCvtPackStr(nodep->modep()); puts(");\n"); } - virtual void visit(AstFOpenMcd* nodep) VL_OVERRIDE { + virtual void visit(AstFOpenMcd* nodep) override { iterateAndNextNull(nodep->filep()); puts(" = VL_FOPEN_MCD_N("); emitCvtPackStr(nodep->filenamep()); puts(");\n"); } - virtual void visit(AstNodeReadWriteMem* nodep) VL_OVERRIDE { + virtual void visit(AstNodeReadWriteMem* nodep) override { puts(nodep->cFuncPrefixp()); puts("N("); puts(nodep->isHex() ? "true" : "false"); @@ -641,14 +644,14 @@ public: } puts(");\n"); } - virtual void visit(AstFClose* nodep) VL_OVERRIDE { + virtual void visit(AstFClose* nodep) override { puts("VL_FCLOSE_I("); iterateAndNextNull(nodep->filep()); puts("); "); iterateAndNextNull(nodep->filep()); // For safety, so user doesn't later WRITE with it. puts(" = 0;\n"); } - virtual void visit(AstFFlush* nodep) VL_OVERRIDE { + virtual void visit(AstFFlush* nodep) override { if (!nodep->filep()) { puts("Verilated::runFlushCallbacks();\n"); } else { @@ -659,7 +662,7 @@ public: puts("); }\n"); } } - virtual void visit(AstFSeek* nodep) VL_OVERRIDE { + virtual void visit(AstFSeek* nodep) override { puts("(VL_FSEEK_I("); iterateAndNextNull(nodep->filep()); puts(","); @@ -668,17 +671,17 @@ public: iterateAndNextNull(nodep->operation()); puts(")==-1?-1:0)"); } - virtual void visit(AstFTell* nodep) VL_OVERRIDE { + virtual void visit(AstFTell* nodep) override { puts("VL_FTELL_I("); iterateAndNextNull(nodep->filep()); puts(")"); } - virtual void visit(AstFRewind* nodep) VL_OVERRIDE { + virtual void visit(AstFRewind* nodep) override { puts("(VL_FSEEK_I("); iterateAndNextNull(nodep->filep()); puts(", 0, 0)==-1?-1:0)"); } - virtual void visit(AstFRead* nodep) VL_OVERRIDE { + virtual void visit(AstFRead* nodep) override { puts("VL_FREAD_I("); puts(cvtToStr(nodep->memp()->widthMin())); // Need real storage width putbs(","); @@ -723,12 +726,12 @@ public: } puts(");\n"); } - virtual void visit(AstSysFuncAsTask* nodep) VL_OVERRIDE { + virtual void visit(AstSysFuncAsTask* nodep) override { if (!nodep->lhsp()->isWide()) puts("(void)"); iterateAndNextNull(nodep->lhsp()); if (!nodep->lhsp()->isWide()) puts(";"); } - virtual void visit(AstSystemT* nodep) VL_OVERRIDE { + virtual void visit(AstSystemT* nodep) override { puts("(void)VL_SYSTEM_I"); emitIQW(nodep->lhsp()); puts("("); @@ -740,7 +743,7 @@ public: iterateAndNextNull(nodep->lhsp()); puts(");\n"); } - virtual void visit(AstSystemF* nodep) VL_OVERRIDE { + virtual void visit(AstSystemF* nodep) override { puts("VL_SYSTEM_I"); emitIQW(nodep->lhsp()); puts("("); @@ -752,20 +755,20 @@ public: iterateAndNextNull(nodep->lhsp()); puts(")"); } - virtual void visit(AstJumpBlock* nodep) VL_OVERRIDE { + virtual void visit(AstJumpBlock* nodep) override { nodep->labelNum(++m_labelNum); puts("{\n"); // Make it visually obvious label jumps outside these iterateAndNextNull(nodep->stmtsp()); iterateAndNextNull(nodep->endStmtsp()); puts("}\n"); } - virtual void visit(AstJumpGo* nodep) VL_OVERRIDE { + virtual void visit(AstJumpGo* nodep) override { puts("goto __Vlabel" + cvtToStr(nodep->labelp()->blockp()->labelNum()) + ";\n"); } - virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE { + virtual void visit(AstJumpLabel* nodep) override { puts("__Vlabel" + cvtToStr(nodep->blockp()->labelNum()) + ": ;\n"); } - virtual void visit(AstWhile* nodep) VL_OVERRIDE { + virtual void visit(AstWhile* nodep) override { iterateAndNextNull(nodep->precondsp()); puts("while ("); iterateAndNextNull(nodep->condp()); @@ -775,7 +778,7 @@ public: iterateAndNextNull(nodep->precondsp()); // Need to recompute before next loop puts("}\n"); } - virtual void visit(AstNodeIf* nodep) VL_OVERRIDE { + virtual void visit(AstNodeIf* nodep) override { puts("if ("); if (!nodep->branchPred().unknown()) { puts(nodep->branchPred().ascii()); @@ -791,7 +794,7 @@ public: } puts("}\n"); } - virtual void visit(AstStop* nodep) VL_OVERRIDE { + virtual void visit(AstStop* nodep) override { puts("VL_STOP_MT("); putsQuoted(protect(nodep->fileline()->filename())); puts(", "); @@ -799,35 +802,35 @@ public: puts(", \"\""); puts(");\n"); } - virtual void visit(AstFinish* nodep) VL_OVERRIDE { + virtual void visit(AstFinish* nodep) override { puts("VL_FINISH_MT("); putsQuoted(protect(nodep->fileline()->filename())); puts(", "); puts(cvtToStr(nodep->fileline()->lineno())); puts(", \"\");\n"); } - virtual void visit(AstPrintTimeScale* nodep) VL_OVERRIDE { + virtual void visit(AstPrintTimeScale* nodep) override { puts("VL_PRINTTIMESCALE("); putsQuoted(protect(nodep->name())); puts(", "); putsQuoted(nodep->timeunit().ascii()); puts(");\n"); } - virtual void visit(AstTime* nodep) VL_OVERRIDE { + virtual void visit(AstTime* nodep) override { puts("VL_TIME_UNITED_Q("); if (nodep->timeunit().isNone()) nodep->v3fatalSrc("$time has no units"); puts(cvtToStr(nodep->timeunit().multiplier() / v3Global.rootp()->timeprecision().multiplier())); puts(")"); } - virtual void visit(AstTimeD* nodep) VL_OVERRIDE { + virtual void visit(AstTimeD* nodep) override { puts("VL_TIME_UNITED_D("); if (nodep->timeunit().isNone()) nodep->v3fatalSrc("$realtime has no units"); puts(cvtToStr(nodep->timeunit().multiplier() / v3Global.rootp()->timeprecision().multiplier())); puts(")"); } - virtual void visit(AstTimeFormat* nodep) VL_OVERRIDE { + virtual void visit(AstTimeFormat* nodep) override { puts("VL_TIMEFORMAT_IINI("); iterateAndNextNull(nodep->unitsp()); puts(", "); @@ -838,34 +841,34 @@ public: iterateAndNextNull(nodep->widthp()); puts(");\n"); } - virtual void visit(AstNodeSimpleText* nodep) VL_OVERRIDE { + virtual void visit(AstNodeSimpleText* nodep) override { if (nodep->tracking() || m_trackText) { puts(nodep->text()); } else { ofp()->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(AstCStmt* nodep) VL_OVERRIDE { + virtual void visit(AstCStmt* nodep) override { putbs(""); iterateAndNextNull(nodep->bodysp()); } - virtual void visit(AstCMath* nodep) VL_OVERRIDE { + virtual void visit(AstCMath* nodep) override { putbs(""); iterateAndNextNull(nodep->bodysp()); } - virtual void visit(AstUCStmt* nodep) VL_OVERRIDE { + virtual void visit(AstUCStmt* nodep) override { putsDecoration(ifNoProtect("// $c statement at " + nodep->fileline()->ascii() + "\n")); iterateAndNextNull(nodep->bodysp()); puts("\n"); } - virtual void visit(AstUCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstUCFunc* nodep) override { puts("\n"); putsDecoration(ifNoProtect("// $c function at " + nodep->fileline()->ascii() + "\n")); iterateAndNextNull(nodep->bodysp()); @@ -873,10 +876,10 @@ public: } // Operators - virtual void visit(AstNodeTermop* nodep) VL_OVERRIDE { - emitOpName(nodep, nodep->emitC(), NULL, NULL, NULL); + virtual void visit(AstNodeTermop* nodep) override { + emitOpName(nodep, nodep->emitC(), nullptr, nullptr, nullptr); } - virtual void visit(AstNodeUniop* nodep) VL_OVERRIDE { + virtual void visit(AstNodeUniop* nodep) override { if (nodep->emitCheckMaxWords() && (nodep->widthWords() > VL_MULS_MAX_WORDS || nodep->lhsp()->widthWords() > VL_MULS_MAX_WORDS)) { @@ -893,10 +896,10 @@ public: iterateAndNextNull(nodep->lhsp()); puts(")"); } else { - emitOpName(nodep, nodep->emitC(), nodep->lhsp(), NULL, NULL); + emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nullptr, nullptr); } } - virtual void visit(AstNodeBiop* nodep) VL_OVERRIDE { + virtual void visit(AstNodeBiop* nodep) override { if (nodep->emitCheckMaxWords() && nodep->widthWords() > VL_MULS_MAX_WORDS) { nodep->v3warn( E_UNSUPPORTED, @@ -913,14 +916,14 @@ public: iterateAndNextNull(nodep->rhsp()); puts(")"); } else { - emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), NULL); + emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), nullptr); } } - virtual void visit(AstNodeTriop* nodep) VL_OVERRIDE { + virtual void visit(AstNodeTriop* nodep) override { UASSERT_OBJ(!emitSimpleOk(nodep), nodep, "Triop cannot be described in a simple way"); emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), nodep->thsp()); } - virtual void visit(AstRedXor* nodep) VL_OVERRIDE { + virtual void visit(AstRedXor* nodep) override { if (nodep->lhsp()->isWide()) { visit(VN_CAST(nodep, NodeUniop)); } else { @@ -931,7 +934,7 @@ public: puts(")"); } } - virtual void visit(AstCCast* nodep) VL_OVERRIDE { + virtual void visit(AstCCast* nodep) override { // Extending a value of the same word width is just a NOP. if (nodep->size() <= VL_IDATASIZE) { puts("(IData)("); @@ -941,7 +944,7 @@ public: iterateAndNextNull(nodep->lhsp()); puts(")"); } - virtual void visit(AstNodeCond* nodep) VL_OVERRIDE { + virtual void visit(AstNodeCond* nodep) override { // Widths match up already, so we'll just use C++'s operator w/o any temps. if (nodep->expr1p()->isWide()) { emitOpName(nodep, nodep->emitC(), nodep->condp(), nodep->expr1p(), nodep->expr2p()); @@ -955,12 +958,12 @@ public: puts(")"); } } - virtual void visit(AstMemberSel* nodep) VL_OVERRIDE { + virtual void visit(AstMemberSel* nodep) override { iterateAndNextNull(nodep->fromp()); putbs("->"); puts(nodep->varp()->nameProtect()); } - virtual void visit(AstNullCheck* nodep) VL_OVERRIDE { + virtual void visit(AstNullCheck* nodep) override { puts("VL_NULL_CHECK("); iterateAndNextNull(nodep->lhsp()); puts(", "); @@ -969,24 +972,24 @@ public: puts(cvtToStr(nodep->fileline()->lineno())); puts(")"); } - virtual void visit(AstCNew* nodep) VL_OVERRIDE { + virtual void visit(AstCNew* nodep) override { puts("std::make_shared<" + prefixNameProtect(nodep->dtypep()) + ">("); puts("vlSymsp"); // TODO make this part of argsp, and eliminate when unnecessary if (nodep->argsp()) puts(", "); iterateAndNextNull(nodep->argsp()); puts(")"); } - virtual void visit(AstNewCopy* nodep) VL_OVERRIDE { + virtual void visit(AstNewCopy* nodep) override { puts("std::make_shared<" + prefixNameProtect(nodep->dtypep()) + ">("); puts("*"); // i.e. make into a reference iterateAndNextNull(nodep->rhsp()); puts(")"); } - virtual void visit(AstSel* nodep) VL_OVERRIDE { + virtual void visit(AstSel* nodep) override { // Note ASSIGN checks for this on a LHS emitOpName(nodep, nodep->emitC(), nodep->fromp(), nodep->lsbp(), nodep->thsp()); } - virtual void visit(AstReplicate* nodep) VL_OVERRIDE { + virtual void visit(AstReplicate* nodep) override { if (nodep->lhsp()->widthMin() == 1 && !nodep->isWide()) { UASSERT_OBJ((static_cast(VN_CAST(nodep->rhsp(), Const)->toUInt()) * nodep->lhsp()->widthMin()) @@ -1004,10 +1007,10 @@ public: iterateAndNextNull(nodep->rhsp()); puts(")"); } else { - emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), NULL); + emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), nullptr); } } - virtual void visit(AstStreamL* nodep) VL_OVERRIDE { + virtual void visit(AstStreamL* nodep) override { // Attempt to use a "fast" stream function for slice size = power of 2 if (!nodep->isWide()) { uint32_t isPow2 = VN_CAST(nodep->rhsp(), Const)->num().countOnes() == 1; @@ -1029,9 +1032,9 @@ public: } } emitOpName(nodep, "VL_STREAML_%nq%lq%rq(%nw,%lw,%rw, %P, %li, %ri)", nodep->lhsp(), - nodep->rhsp(), NULL); + nodep->rhsp(), nullptr); } - virtual void visit(AstCountBits* nodep) VL_OVERRIDE { + virtual void visit(AstCountBits* nodep) override { putbs("VL_COUNTBITS_"); emitIQW(nodep->lhsp()); puts("("); @@ -1052,7 +1055,7 @@ public: puts(")"); } // Terminals - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { puts(nodep->hiernameProtect()); puts(nodep->varp()->nameProtect()); } @@ -1187,58 +1190,56 @@ public: puts(assignString); puts(" = "); } - emitConstant(constp, NULL, assignString); + emitConstant(constp, nullptr, assignString); puts(";\n"); } - virtual void visit(AstConst* nodep) VL_OVERRIDE { + virtual void visit(AstConst* nodep) override { if (nodep->isWide()) { UASSERT_OBJ(m_wideTempRefp, nodep, "Wide Constant w/ no temp"); emitConstant(nodep, m_wideTempRefp, ""); - m_wideTempRefp = NULL; // We used it, barf if set it a second time + m_wideTempRefp = nullptr; // We used it, barf if set it a second time } else { - emitConstant(nodep, NULL, ""); + emitConstant(nodep, nullptr, ""); } } // Just iterate - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { iterateChildren(nodep); } - virtual void visit(AstTopScope* nodep) VL_OVERRIDE { iterateChildren(nodep); } - virtual void visit(AstScope* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNetlist* nodep) override { iterateChildren(nodep); } + virtual void visit(AstTopScope* nodep) override { iterateChildren(nodep); } + virtual void visit(AstScope* nodep) override { iterateChildren(nodep); } // NOPs - virtual void visit(AstTypedef*) VL_OVERRIDE {} - virtual void visit(AstPragma*) VL_OVERRIDE {} - virtual void visit(AstCell*) VL_OVERRIDE {} // Handled outside the Visit class - virtual void visit(AstVar*) VL_OVERRIDE {} // Handled outside the Visit class - virtual void visit(AstNodeText*) VL_OVERRIDE {} // Handled outside the Visit class - virtual void visit(AstTraceDecl*) VL_OVERRIDE {} // Handled outside the Visit class - virtual void visit(AstTraceInc*) VL_OVERRIDE {} // Handled outside the Visit class - virtual void visit(AstCFile*) VL_OVERRIDE {} // Handled outside the Visit class - virtual void visit(AstCellInline*) VL_OVERRIDE {} // Handled outside visit (in EmitCSyms) - virtual void visit(AstCUse*) VL_OVERRIDE {} // Handled outside the Visit class + virtual void visit(AstTypedef*) override {} + virtual void visit(AstPragma*) override {} + virtual void visit(AstCell*) override {} // Handled outside the Visit class + virtual void visit(AstVar*) override {} // Handled outside the Visit class + virtual void visit(AstNodeText*) override {} // Handled outside the Visit class + virtual void visit(AstTraceDecl*) override {} // Handled outside the Visit class + virtual void visit(AstTraceInc*) override {} // Handled outside the Visit class + virtual void visit(AstCFile*) override {} // Handled outside the Visit class + virtual void visit(AstCellInline*) override {} // Handled outside visit (in EmitCSyms) + virtual void visit(AstCUse*) 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); nodep->v3fatalSrc("Unknown node type reached emitter: " << nodep->prettyTypeName()); } - void init() { +public: + EmitCStmts() { m_suppressSemi = false; - m_wideTempRefp = NULL; + m_wideTempRefp = nullptr; m_labelNum = 0; m_splitSize = 0; m_splitFilenum = 0; } - -public: - EmitCStmts() { init(); } - EmitCStmts(AstNode* nodep, V3OutCFile* ofp, bool trackText = false) { - init(); + EmitCStmts(AstNode* nodep, V3OutCFile* ofp, bool trackText = false) + : EmitCStmts{} { m_ofp = ofp; m_trackText = trackText; iterate(nodep); } - virtual ~EmitCStmts() {} + virtual ~EmitCStmts() override {} }; //###################################################################### @@ -1253,16 +1254,17 @@ private: public: // CONSTRUCTORS explicit EmitVarTspSorter(const MTaskIdSet& mtaskIds) - : m_mtaskIds(mtaskIds) - , m_serial(++m_serialNext) {} + : m_mtaskIds(mtaskIds) { // Cannot be {} or GCC 4.8 false warning + m_serial = ++m_serialNext; // Cannot be ()/{} or GCC 4.8 false warning + } virtual ~EmitVarTspSorter() {} // METHODS - bool operator<(const TspStateBase& other) const { + virtual bool operator<(const TspStateBase& other) const override { return operator<(dynamic_cast(other)); } bool operator<(const EmitVarTspSorter& other) const { return m_serial < other.m_serial; } const MTaskIdSet& mtaskIds() const { return m_mtaskIds; } - virtual int cost(const TspStateBase* otherp) const { + virtual int cost(const TspStateBase* otherp) const override { return cost(dynamic_cast(otherp)); } virtual int cost(const EmitVarTspSorter* otherp) const { @@ -1287,10 +1289,10 @@ unsigned EmitVarTspSorter::m_serialNext = 0; class EmitCImp : EmitCStmts { // MEMBERS - AstNodeModule* m_modp; + AstNodeModule* m_modp = nullptr; std::vector m_blkChangeDetVec; // All encountered changes in block - bool m_slow; // Creating __Slow file - bool m_fast; // Creating non __Slow file (or both) + bool m_slow = false; // Creating __Slow file + bool m_fast = false; // Creating non __Slow file (or both) //--------------------------------------- // METHODS @@ -1340,7 +1342,7 @@ class EmitCImp : EmitCStmts { string filenameNoExt = v3Global.opt.makeDir() + "/" + prefixNameProtect(modp); if (filenum) filenameNoExt += "__" + cvtToStr(filenum); filenameNoExt += (slow ? "__Slow" : ""); - V3OutCFile* ofp = NULL; + V3OutCFile* ofp = nullptr; if (v3Global.opt.lintOnly()) { // Unfortunately we have some lint checks here, so we can't just skip processing. // We should move them to a different stage. @@ -1401,7 +1403,7 @@ class EmitCImp : EmitCStmts { string recName; if (v3Global.opt.profThreads()) { recName = "__Vprfthr_" + cvtToStr(curExecMTaskp->id()); - puts("VlProfileRec* " + recName + " = NULL;\n"); + puts("VlProfileRec* " + recName + " = nullptr;\n"); // Leave this if() here, as don't want to call VL_RDTSC_Q unless profiling puts("if (VL_UNLIKELY(vlTOPp->__Vm_profile_cycle_start)) {\n"); puts(recName + " = vlTOPp->__Vm_threadPoolp->profileAppend();\n"); @@ -1445,7 +1447,7 @@ class EmitCImp : EmitCStmts { } } - virtual void visit(AstMTaskBody* nodep) VL_OVERRIDE { + virtual void visit(AstMTaskBody* nodep) override { ExecMTask* mtp = nodep->execMTaskp(); puts("\n"); puts("void "); @@ -1464,7 +1466,7 @@ class EmitCImp : EmitCStmts { //--------------------------------------- // VISITORS using EmitCStmts::visit; // Suppress hidden overloaded virtual function warning - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstCFunc* nodep) override { // TRACE_* and DPI handled elsewhere if (nodep->funcType().isTrace()) return; if (nodep->dpiImport()) return; @@ -1486,6 +1488,13 @@ class EmitCImp : EmitCStmts { puts(funcNameProtect(nodep, m_modp)); puts("(" + cFuncArgs(nodep) + ")"); if (nodep->isConst().trueKnown()) puts(" const"); + + // TODO perhaps better to have a new AstCCtorInit so we can pass arguments + // rather than requiring a string here + if (!nodep->ctorInits().empty()) { + puts(": "); + puts(nodep->ctorInits()); + } puts(" {\n"); // "+" in the debug indicates a print from the model @@ -1528,9 +1537,7 @@ class EmitCImp : EmitCStmts { puts("QData __req = false; // Logically a bool\n"); // But not because it results in // faster code bool gotOne = false; - for (std::vector::iterator it = m_blkChangeDetVec.begin(); - it != m_blkChangeDetVec.end(); ++it) { - AstChangeDet* changep = *it; + for (AstChangeDet* changep : m_blkChangeDetVec) { if (changep->lhsp()) { if (!gotOne) { // Not a clocked block puts("__req |= ("); @@ -1543,9 +1550,7 @@ class EmitCImp : EmitCStmts { if (gotOne) puts(");\n"); if (gotOne && !v3Global.opt.protectIds()) { // puts("VL_DEBUG_IF( if (__req) cout<<\"- CLOCKREQ );"); - for (std::vector::iterator it = m_blkChangeDetVec.begin(); - it != m_blkChangeDetVec.end(); ++it) { - AstChangeDet* nodep = *it; + for (AstChangeDet* nodep : m_blkChangeDetVec) { if (nodep->lhsp()) { puts("VL_DEBUG_IF( if(__req && ("); bool gotOneIgnore = false; @@ -1563,16 +1568,16 @@ class EmitCImp : EmitCStmts { } } - virtual void visit(AstChangeDet* nodep) VL_OVERRIDE { // + virtual void visit(AstChangeDet* nodep) override { // m_blkChangeDetVec.push_back(nodep); } - virtual void visit(AstCReset* nodep) VL_OVERRIDE { + virtual void visit(AstCReset* nodep) override { AstVar* varp = nodep->varrefp()->varp(); emitVarReset(varp); } - virtual void visit(AstExecGraph* nodep) VL_OVERRIDE { + virtual void visit(AstExecGraph* nodep) override { UASSERT_OBJ(nodep == v3Global.rootp()->execGraphp(), nodep, "ExecGraph should be a singleton!"); // The location of the AstExecGraph within the containing _eval() @@ -1771,12 +1776,8 @@ class EmitCImp : EmitCStmts { void maybeSplit(AstNodeModule* modp); public: - EmitCImp() { - m_modp = NULL; - m_slow = false; - m_fast = false; - } - virtual ~EmitCImp() {} + EmitCImp() {} + virtual ~EmitCImp() override {} void mainImp(AstNodeModule* modp, bool slow); void mainInt(AstNodeModule* modp); void mainDoFunc(AstCFunc* nodep) { iterate(nodep); } @@ -1857,9 +1858,7 @@ void EmitCStmts::emitVarCtors(bool* firstp) { if (!m_ctorVarsVec.empty()) { ofp()->indentInc(); puts("\n"); - puts("#if (SYSTEMC_VERSION>20011000)\n"); // SystemC 2.0.1 and newer - for (VarVec::iterator it = m_ctorVarsVec.begin(); it != m_ctorVarsVec.end(); ++it) { - const AstVar* varp = *it; + for (const AstVar* varp : m_ctorVarsVec) { bool isArray = !VN_CAST(varp->dtypeSkipRefp(), BasicDType); if (isArray) { puts("// Skipping array: "); @@ -1873,7 +1872,7 @@ void EmitCStmts::emitVarCtors(bool* firstp) { puts(")"); } } - puts("\n#endif\n"); + puts("\n"); ofp()->indentDec(); } } @@ -1934,7 +1933,7 @@ void EmitCStmts::emitOpName(AstNode* nodep, const string& format, AstNode* lhsp, } else if (pos[0] == '%') { ++pos; bool detail = false; - AstNode* detailp = NULL; + AstNode* detailp = nullptr; switch (pos[0]) { case '%': puts("%"); break; case 'k': putbs(""); break; @@ -1961,7 +1960,7 @@ void EmitCStmts::emitOpName(AstNode* nodep, const string& format, AstNode* lhsp, COMMA; puts(m_wideTempRefp->hiernameProtect()); puts(m_wideTempRefp->varp()->nameProtect()); - m_wideTempRefp = NULL; + m_wideTempRefp = nullptr; needComma = true; } break; @@ -2113,10 +2112,11 @@ void EmitCStmts::displayEmit(AstNode* nodep, bool isScan) { } // End puts(")"); - if (isStmt) + if (isStmt) { puts(";\n"); - else + } else { puts(" "); + } // Prep for next emitDispState.clear(); } @@ -2125,7 +2125,7 @@ void EmitCStmts::displayEmit(AstNode* nodep, bool isScan) { void EmitCStmts::displayArg(AstNode* dispp, AstNode** elistp, bool isScan, const string& vfmt, bool ignore, char fmtLetter) { // Print display argument, edits elistp - AstNode* argp = NULL; + AstNode* argp = nullptr; if (!ignore) { argp = *elistp; // Prep for next parameter @@ -2161,10 +2161,10 @@ void EmitCStmts::displayArg(AstNode* dispp, AstNode** elistp, bool isScan, const } emitDispState.pushFormat(pfmt); if (!ignore) { - emitDispState.pushArg(' ', NULL, cvtToStr(argp->widthMin())); + emitDispState.pushArg(' ', nullptr, cvtToStr(argp->widthMin())); emitDispState.pushArg(fmtLetter, argp, ""); } else { - emitDispState.pushArg(fmtLetter, NULL, ""); + emitDispState.pushArg(fmtLetter, nullptr, ""); } } @@ -2247,7 +2247,7 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep, const str } else { emitDispState.pushFormat("%N"); // Add a . when needed } - emitDispState.pushArg(' ', NULL, "vlSymsp->name()"); + emitDispState.pushArg(' ', nullptr, "vlSymsp->name()"); emitDispState.pushFormat(suffix); break; } @@ -2307,7 +2307,7 @@ void EmitCImp::emitMTaskVertexCtors(bool* firstp) { // This will flip to 'true' before the start of the 0th cycle. emitCtorSep(firstp); - puts("__Vm_threadPoolp(NULL)"); + puts("__Vm_threadPoolp(nullptr)"); if (v3Global.opt.profThreads()) { emitCtorSep(firstp); puts("__Vm_profile_cycle_start(0)"); @@ -2438,7 +2438,7 @@ void EmitCImp::emitDestructorImp(AstNodeModule* modp) { puts(prefixNameProtect(modp) + "::~" + prefixNameProtect(modp) + "() {\n"); if (modp->isTop()) { if (v3Global.opt.mtasks()) { - puts("VL_DO_CLEAR(delete __Vm_threadPoolp, __Vm_threadPoolp = NULL);\n"); + puts("VL_DO_CLEAR(delete __Vm_threadPoolp, __Vm_threadPoolp = nullptr);\n"); } // Call via function in __Trace.cpp as this .cpp file does not have trace header if (v3Global.needTraceDumper()) { @@ -2448,7 +2448,7 @@ void EmitCImp::emitDestructorImp(AstNodeModule* modp) { } } emitTextSection(AstType::atScDtor); - if (modp->isTop()) puts("VL_DO_CLEAR(delete __VlSymsp, __VlSymsp = NULL);\n"); + if (modp->isTop()) puts("VL_DO_CLEAR(delete __VlSymsp, __VlSymsp = nullptr);\n"); puts("}\n"); splitSizeInc(10); } @@ -2838,10 +2838,7 @@ void EmitCStmts::emitVarSort(const VarSortMap& vmap, VarVec* sortedp) { for (VarSortMap::const_iterator it = vmap.begin(); it != vmap.end(); ++it) { int size_class = it->first; const VarVec& vec = it->second; - for (VarVec::const_iterator jt = vec.begin(); jt != vec.end(); ++jt) { - const AstVar* varp = *jt; - m2v[varp->mtaskIds()][size_class].push_back(varp); - } + for (const AstVar* varp : vec) { m2v[varp->mtaskIds()][size_class].push_back(varp); } } // Create a TSP sort state for each MTaskIdSet footprint @@ -2891,14 +2888,14 @@ void EmitCStmts::emitSortedVarList(const VarVec& anons, const VarVec& nonanons, } if (anonL1s != 1) puts("// Anonymous structures to workaround compiler member-count bugs\n"); - VarVec::const_iterator it = anons.begin(); - for (int l3 = 0; l3 < anonL3s && it != anons.end(); ++l3) { + auto it = anons.cbegin(); + for (int l3 = 0; l3 < anonL3s && it != anons.cend(); ++l3) { if (anonL3s != 1) puts("struct {\n"); - for (int l2 = 0; l2 < anonL2s && it != anons.end(); ++l2) { + for (int l2 = 0; l2 < anonL2s && it != anons.cend(); ++l2) { if (anonL2s != 1) puts("struct {\n"); - for (int l1 = 0; l1 < anonL1s && it != anons.end(); ++l1) { + for (int l1 = 0; l1 < anonL1s && it != anons.cend(); ++l1) { if (anonL1s != 1) puts("struct {\n"); - for (int l0 = 0; l0 < lim && it != anons.end(); ++l0) { + for (int l0 = 0; l0 < lim && it != anons.cend(); ++l0) { const AstVar* varp = *it; emitVarCmtChg(varp, &curVarCmt); emitVarDecl(varp, prefixIfImp); @@ -2918,8 +2915,7 @@ void EmitCStmts::emitSortedVarList(const VarVec& anons, const VarVec& nonanons, } } // Output nonanons - for (VarVec::const_iterator it = nonanons.begin(); it != nonanons.end(); ++it) { - const AstVar* varp = *it; + for (const AstVar* varp : nonanons) { emitVarCmtChg(varp, &curVarCmt); emitVarDecl(varp, prefixIfImp); } @@ -2995,7 +2991,8 @@ void EmitCImp::emitInt(AstNodeModule* modp) { if (AstClass* classp = VN_CAST(modp, Class)) { puts("class " + prefixNameProtect(modp)); - if (classp->extendsp()) puts(" : public " + classp->extendsp()->classp()->nameProtect()); + if (classp->extendsp()) + puts(" : public " + prefixNameProtect(classp->extendsp()->classp())); puts(" {\n"); } else if (optSystemC() && modp->isTop()) { puts("SC_MODULE(" + prefixNameProtect(modp) + ") {\n"); @@ -3107,7 +3104,7 @@ void EmitCImp::emitInt(AstNodeModule* modp) { + "C* tfp, int levels, int options = 0);\n"); if (optSystemC()) { puts("/// SC tracing; avoid overloaded virtual function lint warning\n"); - puts("virtual void trace(sc_trace_file* tfp) const { " + puts("virtual void trace(sc_trace_file* tfp) const override { " "::sc_core::sc_module::trace(tfp); }\n"); } } @@ -3252,7 +3249,7 @@ void EmitCImp::maybeSplit(AstNodeModule* fileModp) { // Splitting file, so using parallel build. v3Global.useParallelBuild(true); // Close old file - VL_DO_CLEAR(delete m_ofp, m_ofp = NULL); + VL_DO_CLEAR(delete m_ofp, m_ofp = nullptr); // Open a new file m_ofp = newOutCFile(fileModp, !m_fast, true /*source*/, splitFilenumInc()); emitImpTop(fileModp); @@ -3278,7 +3275,7 @@ void EmitCImp::mainInt(AstNodeModule* modp) { m_modp = modp; } ofp()->putsEndGuard(); - VL_DO_CLEAR(delete m_ofp, m_ofp = NULL); + VL_DO_CLEAR(delete m_ofp, m_ofp = nullptr); } void EmitCImp::mainImp(AstNodeModule* modp, bool slow) { @@ -3321,7 +3318,7 @@ void EmitCImp::mainImp(AstNodeModule* modp, bool slow) { } } } - VL_DO_CLEAR(delete m_ofp, m_ofp = NULL); + VL_DO_CLEAR(delete m_ofp, m_ofp = nullptr); } //###################################################################### @@ -3334,10 +3331,10 @@ class EmitCTrace : EmitCStmts { AstUser1InUse m_inuser1; // MEMBERS - AstCFunc* m_funcp; // Function we're in now + AstCFunc* m_funcp = nullptr; // Function we're in now bool m_slow; // Making slow file - int m_enumNum; // Enumeration number (whole netlist) - int m_baseCode; // Code of first AstTraceInc in this function + int m_enumNum = 0; // Enumeration number (whole netlist) + int m_baseCode = -1; // Code of first AstTraceInc in this function // METHODS void newOutCFile(int filenum) { @@ -3375,7 +3372,7 @@ class EmitCTrace : EmitCStmts { if (v3Global.needTraceDumper() && !optSystemC()) { puts("void " + topClassName() + "::_traceDump() {\n"); - // Caller checked for __Vm_dumperp non-NULL + // Caller checked for __Vm_dumperp non-nullptr puts("const VerilatedLockGuard lock(__VlSymsp->__Vm_dumperMutex);\n"); puts("__VlSymsp->__Vm_dumperp->dump(VL_TIME_Q());\n"); puts("}\n"); @@ -3399,7 +3396,8 @@ class EmitCTrace : EmitCStmts { puts("void " + topClassName() + "::_traceDumpClose() {\n"); puts("const VerilatedLockGuard lock(__VlSymsp->__Vm_dumperMutex);\n"); puts("__VlSymsp->__Vm_dumping = false;\n"); - puts("VL_DO_CLEAR(delete __VlSymsp->__Vm_dumperp, __VlSymsp->__Vm_dumperp = NULL);\n"); + puts("VL_DO_CLEAR(delete __VlSymsp->__Vm_dumperp, __VlSymsp->__Vm_dumperp = " + "nullptr);\n"); puts("}\n"); splitSizeInc(10); } @@ -3658,12 +3656,12 @@ class EmitCTrace : EmitCStmts { // VISITORS using EmitCStmts::visit; // Suppress hidden overloaded virtual function warning - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { // Top module only iterate(nodep->topModulep()); } - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { iterateChildren(nodep); } - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstNodeModule* nodep) override { iterateChildren(nodep); } + virtual void visit(AstCFunc* nodep) override { if (nodep->slow() != m_slow) return; if (nodep->funcType().isTrace()) { // TRACE_* m_funcp = nodep; @@ -3672,7 +3670,7 @@ class EmitCTrace : EmitCStmts { // Splitting file, so using parallel build. v3Global.useParallelBuild(true); // Close old file - VL_DO_CLEAR(delete m_ofp, m_ofp = NULL); + VL_DO_CLEAR(delete m_ofp, m_ofp = nullptr); // Open a new file newOutCFile(splitFilenumInc()); } @@ -3736,9 +3734,9 @@ class EmitCTrace : EmitCStmts { } puts("}\n"); } - m_funcp = NULL; + m_funcp = nullptr; } - virtual void visit(AstTraceDecl* nodep) VL_OVERRIDE { + virtual void visit(AstTraceDecl* nodep) override { int enumNum = emitTraceDeclDType(nodep->dtypep()); if (nodep->arrayRange().ranged()) { puts("{int i; for (i=0; i<" + cvtToStr(nodep->arrayRange().elements()) + "; i++) {\n"); @@ -3749,7 +3747,7 @@ class EmitCTrace : EmitCStmts { puts("\n"); } } - virtual void visit(AstTraceInc* nodep) VL_OVERRIDE { + virtual void visit(AstTraceInc* nodep) override { if (nodep->declp()->arrayRange().ranged()) { // It traces faster if we unroll the loop for (int i = 0; i < nodep->declp()->arrayRange().elements(); i++) { @@ -3759,16 +3757,13 @@ class EmitCTrace : EmitCStmts { emitTraceChangeOne(nodep, -1); } } - virtual void visit(AstCoverDecl* nodep) VL_OVERRIDE {} - virtual void visit(AstCoverInc* nodep) VL_OVERRIDE {} + virtual void visit(AstCoverDecl* nodep) override {} + virtual void visit(AstCoverInc* nodep) override {} public: - explicit EmitCTrace(bool slow) { - m_funcp = NULL; - m_slow = slow; - m_enumNum = 0; - } - virtual ~EmitCTrace() {} + explicit EmitCTrace(bool slow) + : m_slow{slow} {} + virtual ~EmitCTrace() override {} void main() { // Put out the file newOutCFile(0); @@ -3777,7 +3772,7 @@ public: iterate(v3Global.rootp()); - VL_DO_CLEAR(delete m_ofp, m_ofp = NULL); + VL_DO_CLEAR(delete m_ofp, m_ofp = nullptr); } }; diff --git a/src/V3EmitCBase.h b/src/V3EmitCBase.h index 94a5e2d8e..75e4838ec 100644 --- a/src/V3EmitCBase.h +++ b/src/V3EmitCBase.h @@ -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; } }; diff --git a/src/V3EmitCInlines.cpp b/src/V3EmitCInlines.cpp index b2b526f29..eb91000d0 100644 --- a/src/V3EmitCInlines.cpp +++ b/src/V3EmitCInlines.cpp @@ -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); } diff --git a/src/V3EmitCMain.cpp b/src/V3EmitCMain.cpp index 6eba5ec84..3d066bc1b 100644 --- a/src/V3EmitCMain.cpp +++ b/src/V3EmitCMain.cpp @@ -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 diff --git a/src/V3EmitCMake.cpp b/src/V3EmitCMake.cpp index 5e741264f..8139cd418 100644 --- a/src/V3EmitCMake.cpp +++ b/src/V3EmitCMake.cpp @@ -21,6 +21,7 @@ #include "V3Os.h" #include "V3EmitCMake.h" #include "V3EmitCBase.h" +#include "V3HierBlock.h" #include @@ -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 of( + const std::unique_ptr 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 classes_fast, classes_slow, support_fast, support_slow, global; + std::vector classes_fast; + std::vector classes_slow; + std::vector support_fast; + std::vector support_slow; + std::vector 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: diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp index 978c56e2e..9193c8a9c 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -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 ScopeFuncs; typedef std::map 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 m_scopes; // Every scope by module std::vector m_dpis; // DPI functions std::vector 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 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 "<name()<<" sp "<scopePrettySymName() // <<" ss"<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(static_cast("); - puts(varName.c_str()); + puts(varName); puts(".c_str())), "); } else { puts(", const_cast(static_cast(&("); - 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::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::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"); diff --git a/src/V3EmitMk.cpp b/src/V3EmitMk.cpp index 6fe9cf8c0..e0cfd151a 100644 --- a/src/V3EmitMk.cpp +++ b/src/V3EmitMk.cpp @@ -18,6 +18,7 @@ #include "verilatedos.h" #include "V3Global.h" +#include "V3HierBlock.h" #include "V3Os.h" #include "V3EmitMk.h" #include "V3EmitCBase.h" @@ -46,11 +47,8 @@ public: of.puts("# See " + v3Global.opt.prefix() + ".mk" + " for the caller.\n"); of.puts("\n### Switches...\n"); - of.puts("# C11 constructs required? 0/1 (from --threads, " - "--trace-threads or use of classes)\n"); - of.puts("VM_C11 = "); - of.puts(v3Global.needC11() || v3Global.opt.threads() ? "1" : "0"); - of.puts("\n"); + of.puts("# C11 constructs required? 0/1 (always on now)\n"); + of.puts("VM_C11 = 1\n"); of.puts("# Coverage output mode? 0/1 (from --coverage)\n"); of.puts("VM_COVERAGE = "); of.puts(v3Global.opt.coverage() ? "1" : "0"); @@ -94,7 +92,10 @@ public: of.puts(support == 2 ? "VM_GLOBAL" : support == 1 ? "VM_SUPPORT" : "VM_CLASSES"); of.puts(slow ? "_SLOW" : "_FAST"); of.puts(" += \\\n"); - if (support == 2 && !slow) { + if (support == 2 && v3Global.opt.hierChild()) { + // Do nothing because VM_GLOBAL is necessary per executable. Top module will + // have them. + } else if (support == 2 && !slow) { putMakeClassEntry(of, "verilated.cpp"); if (v3Global.dpi()) { putMakeClassEntry(of, "verilated_dpi.cpp"); } if (v3Global.opt.vpi()) { putMakeClassEntry(of, "verilated_vpi.cpp"); } @@ -189,25 +190,20 @@ public: of.puts("VM_USER_CFLAGS = \\\n"); if (!v3Global.opt.protectLib().empty()) of.puts("\t-fPIC \\\n"); const V3StringList& cFlags = v3Global.opt.cFlags(); - for (V3StringList::const_iterator it = cFlags.begin(); it != cFlags.end(); ++it) { - of.puts("\t" + *it + " \\\n"); - } + for (const string& i : cFlags) of.puts("\t" + i + " \\\n"); of.puts("\n"); of.puts("# User LDLIBS (from -LDFLAGS on Verilator command line)\n"); of.puts("VM_USER_LDLIBS = \\\n"); const V3StringList& ldLibs = v3Global.opt.ldLibs(); - for (V3StringList::const_iterator it = ldLibs.begin(); it != ldLibs.end(); ++it) { - of.puts("\t" + *it + " \\\n"); - } + for (const string& i : ldLibs) of.puts("\t" + i + " \\\n"); of.puts("\n"); V3StringSet dirs; of.puts("# User .cpp files (from .cpp's on Verilator command line)\n"); of.puts("VM_USER_CLASSES = \\\n"); const V3StringSet& cppFiles = v3Global.opt.cppFiles(); - for (V3StringSet::const_iterator it = cppFiles.begin(); it != cppFiles.end(); ++it) { - string cppfile = *it; + for (const auto& cppfile : cppFiles) { of.puts("\t" + V3Os::filenameNonExt(cppfile) + " \\\n"); string dir = V3Os::filenameDir(cppfile); dirs.insert(dir); @@ -216,14 +212,16 @@ public: of.puts("# User .cpp directories (from .cpp's on Verilator command line)\n"); of.puts("VM_USER_DIR = \\\n"); - for (V3StringSet::iterator it = dirs.begin(); it != dirs.end(); ++it) { - of.puts("\t" + *it + " \\\n"); - } + for (const auto& i : dirs) of.puts("\t" + i + " \\\n"); of.puts("\n"); of.puts("\n### Default rules...\n"); of.puts("# Include list of all generated classes\n"); of.puts("include " + v3Global.opt.prefix() + "_classes.mk\n"); + if (v3Global.opt.hierTop()) { + of.puts("# Include rules for hierarchical blocks\n"); + of.puts("include " + v3Global.opt.prefix() + "_hier.mk\n"); + } of.puts("# Include global rules\n"); of.puts("include $(VERILATOR_ROOT)/include/verilated.mk\n"); @@ -231,8 +229,7 @@ public: of.puts("\n### Executable rules... (from --exe)\n"); of.puts("VPATH += $(VM_USER_DIR)\n"); of.puts("\n"); - for (V3StringSet::const_iterator it = cppFiles.begin(); it != cppFiles.end(); ++it) { - string cppfile = *it; + for (const string& cppfile : cppFiles) { string basename = V3Os::filenameNonExt(cppfile); // NOLINTNEXTLINE(performance-inefficient-string-concatenation) of.puts(basename + ".o: " + cppfile + "\n"); @@ -241,24 +238,39 @@ public: of.puts("\n### Link rules... (from --exe)\n"); of.puts(v3Global.opt.exeName() - + ": $(VK_USER_OBJS) $(VK_GLOBAL_OBJS) $(VM_PREFIX)__ALL.a\n"); + + ": $(VK_USER_OBJS) $(VK_GLOBAL_OBJS) $(VM_PREFIX)__ALL.a $(VM_HIER_LIBS)\n"); of.puts("\t$(LINK) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) $(LIBS) $(SC_LIBS) -o $@\n"); of.puts("\n"); } if (!v3Global.opt.protectLib().empty()) { - const string protectLibDeps - = "$(VK_OBJS) $(VK_GLOBAL_OBJS) " + v3Global.opt.protectLib() + ".o"; + const string protectLibDeps = "$(VK_OBJS) $(VK_GLOBAL_OBJS) " + + v3Global.opt.protectLib() + ".o $(VM_HIER_LIBS)"; of.puts("\n### Library rules from --protect-lib\n"); + // The rule to create .a is defined in verilated.mk, so just define dependency here. of.puts(v3Global.opt.protectLibName(false) + ": " + protectLibDeps + "\n"); - of.puts("\tar rc $@ $^\n"); of.puts("\n"); - of.puts(v3Global.opt.protectLibName(true) + ": " + protectLibDeps + "\n"); - of.puts("\t$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -shared -o $@ $^\n"); - of.puts("\n"); - - of.puts("lib" + v3Global.opt.protectLib() + ": " + v3Global.opt.protectLibName(false) - + " " + v3Global.opt.protectLibName(true) + "\n"); + if (v3Global.opt.hierChild()) { + // Hierarchical child does not need .so because hierTop() will create .so from .a + of.puts("lib" + v3Global.opt.protectLib() + ": " + + v3Global.opt.protectLibName(false) + "\n"); + } else { + of.puts(v3Global.opt.protectLibName(true) + ": " + protectLibDeps + "\n"); + // Linker on mac emits an error if all symbols are not found here, + // but some symbols that are referred as "DPI-C" can not be found at this moment. + // So add dynamic_lookup + of.puts("ifeq ($(shell uname -s),Darwin)\n"); + of.puts("\t$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -undefined " + "dynamic_lookup -shared -flat_namespace -o $@ $^\n"); + of.puts("else\n"); + of.puts( + "\t$(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_FAST) -shared -o $@ $^\n"); + of.puts("endif\n"); + of.puts("\n"); + of.puts("lib" + v3Global.opt.protectLib() + ": " + + v3Global.opt.protectLibName(false) + " " + + v3Global.opt.protectLibName(true) + "\n"); + } } of.puts("\n"); @@ -273,6 +285,131 @@ public: virtual ~EmitMk() {} }; +//###################################################################### +class EmitMkHierVerilation { + const V3HierBlockPlan* const m_planp; + const string m_makefile; // path of this makefile + void emitCommonOpts(V3OutMkFile& of) const { + const string cwd = V3Os::filenameRealPath("."); + of.puts("# Verilation of hierarchical blocks are executed in this directory\n"); + of.puts("VM_HIER_RUN_DIR := " + cwd + "\n"); + of.puts("# Common options for hierarchical blocks\n"); + const string fullpath_bin = V3Os::filenameRealPath(v3Global.opt.bin()); + const string perl_wrapper = V3Os::filenameDir(fullpath_bin) + "/verilator"; + of.puts("VM_HIER_VERILATOR := " + perl_wrapper + "\n"); + of.puts("VM_HIER_INPUT_FILES := \\\n"); + const V3StringList& vFiles = v3Global.opt.vFiles(); + for (const string& i : vFiles) of.puts("\t" + V3Os::filenameRealPath(i) + " \\\n"); + of.puts("\n"); + const V3StringSet& libraryFiles = v3Global.opt.libraryFiles(); + of.puts("VM_HIER_VERILOG_LIBS := \\\n"); + for (const string& i : libraryFiles) { + of.puts("\t" + V3Os::filenameRealPath(i) + " \\\n"); + } + of.puts("\n"); + } + void emitOpts(V3OutMkFile& of, const V3StringList& opts) const { + for (const string& i : opts) { of.puts("\t\t" + i + " \\\n"); } + } + void emitLaunchVerilator(V3OutMkFile& of, const string& argsFile) const { + of.puts("\t@$(MAKE) -C $(VM_HIER_RUN_DIR) -f " + m_makefile + + " hier_launch_verilator \\\n"); + of.puts("\t\tVM_HIER_LAUNCH_VERILATOR_ARGSFILE=\"" + argsFile + "\"\n"); + } + void emit(V3OutMkFile& of) const { + of.puts("# Hierarchical Verilation -*- Makefile -*-\n"); + of.puts("# DESCR" + "IPTION: Verilator output: Makefile for hierarchical verilatrion\n"); + of.puts("#\n"); + of.puts("# The main makefile " + v3Global.opt.prefix() + ".mk calls this makefile\n"); + of.puts("\n"); + of.puts("ifndef VM_HIER_VERILATION_INCLUDED\n"); + of.puts("VM_HIER_VERILATION_INCLUDED = 1\n\n"); + + of.puts(".SUFFIXES:\n"); + of.puts(".PHONY: hier_build hier_verilation hier_launch_verilator\n"); + + of.puts("# Libraries of hierarchical blocks\n"); + of.puts("VM_HIER_LIBS := \\\n"); + const V3HierBlockPlan::HierVector blocks + = m_planp->hierBlocksSorted(); // leaf comes first + // List in order of leaf-last order so that linker can resolve dependency + for (auto it = blocks.rbegin(); it != blocks.rend(); ++it) { + of.puts("\t" + (*it)->hierLib(true) + " \\\n"); + } + of.puts("\n"); + + // Build hierarchical libraries as soon as possible to get maximum parallelism + of.puts("hier_build: $(VM_HIER_LIBS) " + v3Global.opt.prefix() + ".mk\n"); + of.puts("\t$(MAKE) -f " + v3Global.opt.prefix() + ".mk\n"); + of.puts("hier_verilation: " + v3Global.opt.prefix() + ".mk\n"); + emitCommonOpts(of); + + // Instead of direct execute of "cd $(VM_HIER_RUN_DIR) && $(VM_HIER_VERILATOR)", + // call via make to get message of "Entering directory" and "Leaving directory". + // This will make some editors and IDEs happy when viewing a logfile. + of.puts("# VM_HIER_LAUNCH_VERILATOR_ARGSFILE must be passed as a command argument\n"); + of.puts("hier_launch_verilator:\n"); + of.puts("\t$(VM_HIER_VERILATOR) -f $(VM_HIER_LAUNCH_VERILATOR_ARGSFILE)\n"); + + // Top level module + { + const string argsFile = v3Global.hierPlanp()->topCommandArgsFileName(false); + of.puts("\n# Verilate the top module\n"); + of.puts(v3Global.opt.prefix() + + ".mk: $(VM_HIER_INPUT_FILES) $(VM_HIER_VERILOG_LIBS) "); + of.puts(V3Os::filenameNonDir(argsFile) + " "); + for (V3HierBlockPlan::const_iterator it = m_planp->begin(); it != m_planp->end(); + ++it) { + of.puts(it->second->hierWrapper(true) + " "); + } + of.puts("\n"); + emitLaunchVerilator(of, argsFile); + } + + // Rules to process hierarchical blocks + of.puts("\n# Verilate hierarchical blocks\n"); + for (V3HierBlockPlan::const_iterator it = m_planp->begin(); it != m_planp->end(); ++it) { + const string prefix = it->second->hierPrefix(); + const string argsFile = it->second->commandArgsFileName(false); + of.puts(it->second->hierGenerated(true)); + of.puts(": $(VM_HIER_INPUT_FILES) $(VM_HIER_VERILOG_LIBS) "); + of.puts(V3Os::filenameNonDir(argsFile) + " "); + const V3HierBlock::HierBlockSet& children = it->second->children(); + for (V3HierBlock::HierBlockSet::const_iterator child = children.begin(); + child != children.end(); ++child) { + of.puts((*child)->hierWrapper(true) + " "); + } + of.puts("\n"); + emitLaunchVerilator(of, argsFile); + + // Rule to build lib*.a + of.puts(it->second->hierLib(true)); + of.puts(": "); + of.puts(it->second->hierMk(true)); + of.puts(" "); + for (V3HierBlock::HierBlockSet::const_iterator child = children.begin(); + child != children.end(); ++child) { + of.puts((*child)->hierLib(true)); + of.puts(" "); + } + of.puts("\n\t$(MAKE) -f " + it->second->hierMk(false) + " -C " + prefix); + of.puts(" VM_PREFIX=" + prefix); + of.puts("\n\n"); + } + of.puts("endif # Guard\n"); + } + +public: + explicit EmitMkHierVerilation(const V3HierBlockPlan* planp) + : m_planp{planp} + , m_makefile{v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "_hier.mk"} { + V3OutMkFile of(m_makefile); + emit(of); + } + VL_DEBUG_FUNC; // Declare debug() +}; + //###################################################################### // Gate class functions @@ -280,3 +417,8 @@ void V3EmitMk::emitmk() { UINFO(2, __FUNCTION__ << ": " << endl); EmitMk emitter; } + +void V3EmitMk::emitHierVerilation(const V3HierBlockPlan* planp) { + UINFO(2, __FUNCTION__ << ": " << endl); + EmitMkHierVerilation emitter(planp); +} diff --git a/src/V3EmitMk.h b/src/V3EmitMk.h index 809e65173..4e30f598c 100644 --- a/src/V3EmitMk.h +++ b/src/V3EmitMk.h @@ -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 diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp index 07c9395d5..6ebfece29 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -30,8 +30,8 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { // MEMBERS - bool m_suppressSemi; - AstSenTree* m_sensesp; + bool m_suppressSemi = false; + AstSenTree* m_sensesp; // Domain for printing one a ALWAYS under a ACTIVE // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -51,13 +51,13 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } // VISITORS - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { iterateChildren(nodep); } - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { iterateChildren(nodep); } + virtual void visit(AstNodeModule* nodep) override { putfs(nodep, nodep->verilogKwd() + " " + prefixNameProtect(nodep) + ";\n"); iterateChildren(nodep); putqs(nodep, "end" + nodep->verilogKwd() + "\n"); } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTask* nodep) override { putfs(nodep, nodep->isFunction() ? "function" : "task"); puts(" "); puts(nodep->prettyName()); @@ -68,7 +68,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { putqs(nodep, "end\n"); } - virtual void visit(AstBegin* nodep) VL_OVERRIDE { + virtual void visit(AstBegin* nodep) override { if (nodep->name() == "") { putbs("begin\n"); } else { @@ -77,7 +77,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { iterateChildren(nodep); puts("end\n"); } - virtual void visit(AstFork* nodep) VL_OVERRIDE { + virtual void visit(AstFork* nodep) override { if (nodep->name() == "") { putbs("fork\n"); } else { @@ -87,17 +87,17 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { puts(nodep->joinType().verilogKwd()); puts("\n"); } - virtual void visit(AstFinal* nodep) VL_OVERRIDE { + virtual void visit(AstFinal* nodep) override { putfs(nodep, "final begin\n"); iterateChildren(nodep); putqs(nodep, "end\n"); } - virtual void visit(AstInitial* nodep) VL_OVERRIDE { + virtual void visit(AstInitial* nodep) override { putfs(nodep, "initial begin\n"); iterateChildren(nodep); putqs(nodep, "end\n"); } - virtual void visit(AstAlways* nodep) VL_OVERRIDE { + virtual void visit(AstAlways* nodep) override { putfs(nodep, "always "); if (m_sensesp) { iterateAndNextNull(m_sensesp); @@ -109,7 +109,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { iterateAndNextNull(nodep->bodysp()); putqs(nodep, "end\n"); } - virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE { + virtual void visit(AstAlwaysPublic* nodep) override { putfs(nodep, "/*verilator public_flat_rw "); if (m_sensesp) { iterateAndNextNull(m_sensesp); @@ -121,37 +121,37 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { iterateAndNextNull(nodep->bodysp()); putqs(nodep, "*/\n"); } - virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { + virtual void visit(AstNodeAssign* nodep) override { iterateAndNextNull(nodep->lhsp()); putfs(nodep, " " + nodep->verilogKwd() + " "); iterateAndNextNull(nodep->rhsp()); if (!m_suppressSemi) puts(";\n"); } - virtual void visit(AstAssignDly* nodep) VL_OVERRIDE { + virtual void visit(AstAssignDly* nodep) override { iterateAndNextNull(nodep->lhsp()); putfs(nodep, " <= "); iterateAndNextNull(nodep->rhsp()); puts(";\n"); } - virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { + virtual void visit(AstAssignAlias* nodep) override { putbs("alias "); iterateAndNextNull(nodep->lhsp()); putfs(nodep, " = "); iterateAndNextNull(nodep->rhsp()); if (!m_suppressSemi) puts(";\n"); } - virtual void visit(AstAssignW* nodep) VL_OVERRIDE { + virtual void visit(AstAssignW* nodep) override { putfs(nodep, "assign "); iterateAndNextNull(nodep->lhsp()); putbs(" = "); iterateAndNextNull(nodep->rhsp()); if (!m_suppressSemi) puts(";\n"); } - virtual void visit(AstBreak* nodep) VL_OVERRIDE { + virtual void visit(AstBreak*) override { putbs("break"); if (!m_suppressSemi) puts(";\n"); } - virtual void visit(AstSenTree* nodep) VL_OVERRIDE { + virtual void visit(AstSenTree* nodep) override { // AstSenItem is called for dumping in isolation by V3Order putfs(nodep, "@("); for (AstNode* expp = nodep->sensesp(); expp; expp = expp->nextp()) { @@ -160,13 +160,13 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } puts(")"); } - virtual void visit(AstSenItem* nodep) VL_OVERRIDE { + virtual void visit(AstSenItem* nodep) override { putfs(nodep, ""); puts(nodep->edgeType().verilogKwd()); if (nodep->sensp()) puts(" "); iterateChildren(nodep); } - virtual void visit(AstNodeCase* nodep) VL_OVERRIDE { + virtual void visit(AstNodeCase* nodep) override { putfs(nodep, ""); if (const AstCase* casep = VN_CAST(nodep, Case)) { if (casep->priorityPragma()) puts("priority "); @@ -187,7 +187,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { iterateAndNextNull(nodep->itemsp()); putqs(nodep, "endcase\n"); } - virtual void visit(AstCaseItem* nodep) VL_OVERRIDE { + virtual void visit(AstCaseItem* nodep) override { if (nodep->condsp()) { iterateAndNextNull(nodep->condsp()); } else { @@ -197,17 +197,17 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { iterateAndNextNull(nodep->bodysp()); putqs(nodep, "end\n"); } - virtual void visit(AstComment* nodep) VL_OVERRIDE { + virtual void visit(AstComment* nodep) override { puts(string("// ") + nodep->name() + "\n"); iterateChildren(nodep); } - virtual void visit(AstContinue* nodep) VL_OVERRIDE { + virtual void visit(AstContinue*) override { putbs("continue"); if (!m_suppressSemi) puts(";\n"); } - virtual void visit(AstCoverDecl*) VL_OVERRIDE {} // N/A - virtual void visit(AstCoverInc*) VL_OVERRIDE {} // N/A - virtual void visit(AstCoverToggle*) VL_OVERRIDE {} // N/A + virtual void visit(AstCoverDecl*) override {} // N/A + virtual void visit(AstCoverInc*) override {} // N/A + virtual void visit(AstCoverToggle*) override {} // N/A void visitNodeDisplay(AstNode* nodep, AstNode* fileOrStrgp, const string& text, AstNode* exprsp) { @@ -224,28 +224,26 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } puts(");\n"); } - virtual void visit(AstDisable* nodep) VL_OVERRIDE { - putbs("disable " + nodep->name() + ";\n"); - } - virtual void visit(AstDisplay* nodep) VL_OVERRIDE { + virtual void visit(AstDisable* nodep) override { putbs("disable " + nodep->name() + ";\n"); } + virtual void visit(AstDisplay* nodep) override { visitNodeDisplay(nodep, nodep->filep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp()); } - virtual void visit(AstElabDisplay* nodep) VL_OVERRIDE { - visitNodeDisplay(nodep, NULL, nodep->fmtp()->text(), nodep->fmtp()->exprsp()); + virtual void visit(AstElabDisplay* nodep) override { + visitNodeDisplay(nodep, nullptr, nodep->fmtp()->text(), nodep->fmtp()->exprsp()); } - virtual void visit(AstFScanF* nodep) VL_OVERRIDE { + virtual void visit(AstFScanF* nodep) override { visitNodeDisplay(nodep, nodep->filep(), nodep->text(), nodep->exprsp()); } - virtual void visit(AstSScanF* nodep) VL_OVERRIDE { + virtual void visit(AstSScanF* nodep) override { visitNodeDisplay(nodep, nodep->fromp(), nodep->text(), nodep->exprsp()); } - virtual void visit(AstSFormat* nodep) VL_OVERRIDE { + virtual void visit(AstSFormat* nodep) override { visitNodeDisplay(nodep, nodep->lhsp(), nodep->fmtp()->text(), nodep->fmtp()->exprsp()); } - virtual void visit(AstSFormatF* nodep) VL_OVERRIDE { - visitNodeDisplay(nodep, NULL, nodep->text(), nodep->exprsp()); + virtual void visit(AstSFormatF* nodep) override { + visitNodeDisplay(nodep, nullptr, nodep->text(), nodep->exprsp()); } - virtual void visit(AstFOpen* nodep) VL_OVERRIDE { + virtual void visit(AstFOpen* nodep) override { putfs(nodep, nodep->verilogKwd()); putbs("("); iterateAndNextNull(nodep->filenamep()); @@ -253,36 +251,36 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { iterateAndNextNull(nodep->modep()); puts(");\n"); } - virtual void visit(AstFOpenMcd* nodep) VL_OVERRIDE { + virtual void visit(AstFOpenMcd* nodep) override { putfs(nodep, nodep->verilogKwd()); putbs("("); iterateAndNextNull(nodep->filenamep()); puts(");\n"); } - virtual void visit(AstFClose* nodep) VL_OVERRIDE { + virtual void visit(AstFClose* nodep) override { putfs(nodep, nodep->verilogKwd()); putbs(" ("); if (nodep->filep()) iterateAndNextNull(nodep->filep()); puts(");\n"); } - virtual void visit(AstFFlush* nodep) VL_OVERRIDE { + virtual void visit(AstFFlush* nodep) override { putfs(nodep, nodep->verilogKwd()); putbs(" ("); if (nodep->filep()) iterateAndNextNull(nodep->filep()); puts(");\n"); } - virtual void visit(AstJumpBlock* nodep) VL_OVERRIDE { + virtual void visit(AstJumpBlock* nodep) override { putbs("begin : label" + cvtToStr(nodep->labelNum()) + "\n"); if (nodep->stmtsp()) iterateAndNextNull(nodep->stmtsp()); puts("end\n"); } - virtual void visit(AstJumpGo* nodep) VL_OVERRIDE { + virtual void visit(AstJumpGo* nodep) override { putbs("disable label" + cvtToStr(nodep->labelp()->blockp()->labelNum()) + ";\n"); } - virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE { + virtual void visit(AstJumpLabel* nodep) override { putbs("// " + cvtToStr(nodep->blockp()) + ":\n"); } - virtual void visit(AstNodeReadWriteMem* nodep) VL_OVERRIDE { + virtual void visit(AstNodeReadWriteMem* nodep) override { putfs(nodep, nodep->verilogKwd()); putbs(" ("); if (nodep->filenamep()) iterateAndNextNull(nodep->filenamep()); @@ -298,17 +296,17 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } puts(");\n"); } - virtual void visit(AstSysFuncAsTask* nodep) VL_OVERRIDE { + virtual void visit(AstSysFuncAsTask* nodep) override { iterateAndNextNull(nodep->lhsp()); puts(";\n"); } - virtual void visit(AstSysIgnore* nodep) VL_OVERRIDE { + virtual void visit(AstSysIgnore* nodep) override { putfs(nodep, nodep->verilogKwd()); putbs(" ("); iterateAndNextNull(nodep->exprsp()); puts(");\n"); } - virtual void visit(AstNodeFor* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFor* nodep) override { putfs(nodep, "for ("); m_suppressSemi = true; iterateAndNextNull(nodep->initsp()); @@ -321,14 +319,14 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { iterateAndNextNull(nodep->bodysp()); putqs(nodep, "end\n"); } - virtual void visit(AstRepeat* nodep) VL_OVERRIDE { + virtual void visit(AstRepeat* nodep) override { putfs(nodep, "repeat ("); iterateAndNextNull(nodep->countp()); puts(") begin\n"); iterateAndNextNull(nodep->bodysp()); putfs(nodep, "end\n"); } - virtual void visit(AstWhile* nodep) VL_OVERRIDE { + virtual void visit(AstWhile* nodep) override { iterateAndNextNull(nodep->precondsp()); putfs(nodep, "while ("); iterateAndNextNull(nodep->condp()); @@ -338,7 +336,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { iterateAndNextNull(nodep->precondsp()); // Need to recompute before next loop putfs(nodep, "end\n"); } - virtual void visit(AstNodeIf* nodep) VL_OVERRIDE { + virtual void visit(AstNodeIf* nodep) override { putfs(nodep, ""); if (const AstIf* ifp = VN_CAST(nodep, If)) { if (ifp->priorityPragma()) puts("priority "); @@ -356,7 +354,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } putqs(nodep, "end\n"); } - virtual void visit(AstPast* nodep) VL_OVERRIDE { + virtual void visit(AstPast* nodep) override { putfs(nodep, "$past("); iterateAndNextNull(nodep->exprp()); if (nodep->ticksp()) { @@ -365,53 +363,53 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } puts(")"); } - virtual void visit(AstReturn* nodep) VL_OVERRIDE { + virtual void visit(AstReturn* nodep) override { putfs(nodep, "return "); iterateAndNextNull(nodep->lhsp()); puts(";\n"); } - virtual void visit(AstStop* nodep) VL_OVERRIDE { putfs(nodep, "$stop;\n"); } - virtual void visit(AstFinish* nodep) VL_OVERRIDE { putfs(nodep, "$finish;\n"); } - virtual void visit(AstNodeSimpleText* nodep) VL_OVERRIDE { + virtual void visit(AstStop* nodep) override { putfs(nodep, "$stop;\n"); } + virtual void visit(AstFinish* nodep) override { putfs(nodep, "$finish;\n"); } + virtual void visit(AstNodeSimpleText* nodep) override { if (nodep->tracking() || m_trackText) { puts(nodep->text()); } else { putsNoTracking(nodep->text()); } } - virtual void visit(AstTextBlock* nodep) VL_OVERRIDE { + virtual void visit(AstTextBlock* nodep) override { visit(VN_CAST(nodep, NodeSimpleText)); for (AstNode* childp = nodep->nodesp(); childp; childp = childp->nextp()) { iterate(childp); if (nodep->commas() && childp->nextp()) puts(", "); } } - virtual void visit(AstScopeName* nodep) VL_OVERRIDE {} - virtual void visit(AstCStmt* nodep) VL_OVERRIDE { + virtual void visit(AstScopeName* nodep) override {} + virtual void visit(AstCStmt* nodep) override { putfs(nodep, "$_CSTMT("); iterateAndNextNull(nodep->bodysp()); puts(");\n"); } - virtual void visit(AstCMath* nodep) VL_OVERRIDE { + virtual void visit(AstCMath* nodep) override { putfs(nodep, "$_CMATH("); iterateAndNextNull(nodep->bodysp()); puts(");\n"); } - virtual void visit(AstUCStmt* nodep) VL_OVERRIDE { + virtual void visit(AstUCStmt* nodep) override { putfs(nodep, "$c("); iterateAndNextNull(nodep->bodysp()); puts(");\n"); } - virtual void visit(AstUCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstUCFunc* nodep) override { putfs(nodep, "$c("); iterateAndNextNull(nodep->bodysp()); puts(")"); } // Operators - virtual void emitVerilogFormat(AstNode* nodep, const string& format, AstNode* lhsp = NULL, - AstNode* rhsp = NULL, AstNode* thsp = NULL, - AstNode* fhsp = NULL) { + virtual void emitVerilogFormat(AstNode* nodep, const string& format, AstNode* lhsp = nullptr, + AstNode* rhsp = nullptr, AstNode* thsp = nullptr, + AstNode* fhsp = nullptr) { // Look at emitVerilog() format for term/uni/dual/triops, // and write out appropriate text. // %f Potential fileline-if-change and line break @@ -423,16 +421,16 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { // %k Potential line break bool inPct = false; putbs(""); - for (string::const_iterator pos = format.begin(); pos != format.end(); ++pos) { - if (pos[0] == '%') { + for (const char c : format) { + if (c == '%') { inPct = true; } else if (!inPct) { // Normal text string s; - s += pos[0]; + s += c; puts(s); } else { // Format character inPct = false; - switch (*pos) { + switch (c) { case '%': puts("%"); break; case 'f': putfs(nodep, ""); break; case 'k': putbs(""); break; @@ -461,26 +459,26 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { iterateAndNextNull(nodep->dtypep()); break; } - default: nodep->v3fatalSrc("Unknown emitVerilog format code: %" << pos[0]); break; + default: nodep->v3fatalSrc("Unknown emitVerilog format code: %" << c); break; } } } } - virtual void visit(AstNodeTermop* nodep) VL_OVERRIDE { + virtual void visit(AstNodeTermop* nodep) override { emitVerilogFormat(nodep, nodep->emitVerilog()); } - virtual void visit(AstNodeUniop* nodep) VL_OVERRIDE { + virtual void visit(AstNodeUniop* nodep) override { emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp()); } - virtual void visit(AstNodeBiop* nodep) VL_OVERRIDE { + virtual void visit(AstNodeBiop* nodep) override { emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp(), nodep->rhsp()); } - virtual void visit(AstNodeTriop* nodep) VL_OVERRIDE { + virtual void visit(AstNodeTriop* nodep) override { emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp(), nodep->rhsp(), nodep->thsp()); } - virtual void visit(AstAttrOf* nodep) VL_OVERRIDE { + virtual void visit(AstAttrOf* nodep) override { putfs(nodep, "$_ATTROF("); iterateAndNextNull(nodep->fromp()); if (nodep->dimp()) { @@ -489,7 +487,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } puts(")"); } - virtual void visit(AstInitArray* nodep) VL_OVERRIDE { + virtual void visit(AstInitArray* nodep) override { putfs(nodep, "`{"); int comma = 0; const AstInitArray::KeyItemMap& mapr = nodep->map(); @@ -502,7 +500,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } puts("}"); } - virtual void visit(AstNodeCond* nodep) VL_OVERRIDE { + virtual void visit(AstNodeCond* nodep) override { putbs("("); iterateAndNextNull(nodep->condp()); putfs(nodep, " ? "); @@ -511,7 +509,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { iterateAndNextNull(nodep->expr2p()); puts(")"); } - virtual void visit(AstRange* nodep) VL_OVERRIDE { + virtual void visit(AstRange* nodep) override { puts("["); if (VN_IS(nodep->msbp(), Const) && VN_IS(nodep->lsbp(), Const)) { // Looks nicer if we print [1:0] rather than [32'sh1:32sh0] @@ -526,7 +524,7 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { puts("]"); } } - virtual void visit(AstSel* nodep) VL_OVERRIDE { + virtual void visit(AstSel* nodep) override { iterateAndNextNull(nodep->fromp()); puts("["); if (VN_IS(nodep->lsbp(), Const)) { @@ -550,18 +548,18 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } puts("]"); } - virtual void visit(AstSliceSel* nodep) VL_OVERRIDE { + virtual void visit(AstSliceSel* nodep) override { iterateAndNextNull(nodep->fromp()); puts(cvtToStr(nodep->declRange())); } - virtual void visit(AstTypedef* nodep) VL_OVERRIDE { + virtual void visit(AstTypedef* nodep) override { putfs(nodep, "typedef "); iterateAndNextNull(nodep->dtypep()); puts(" "); puts(nodep->prettyName()); puts(";\n"); } - virtual void visit(AstBasicDType* nodep) VL_OVERRIDE { + virtual void visit(AstBasicDType* nodep) override { if (nodep->isSigned()) putfs(nodep, "signed "); putfs(nodep, nodep->prettyName()); if (nodep->rangep()) { @@ -574,28 +572,28 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { puts(":0] "); } } - virtual void visit(AstConstDType* nodep) VL_OVERRIDE { + virtual void visit(AstConstDType* nodep) override { putfs(nodep, "const "); iterate(nodep->subDTypep()); } - virtual void visit(AstNodeArrayDType* nodep) VL_OVERRIDE { + virtual void visit(AstNodeArrayDType* nodep) override { iterate(nodep->subDTypep()); iterateAndNextNull(nodep->rangep()); } - virtual void visit(AstNodeUOrStructDType* nodep) VL_OVERRIDE { + virtual void visit(AstNodeUOrStructDType* nodep) override { puts(nodep->verilogKwd() + " "); if (nodep->packed()) puts("packed "); puts("\n"); iterateAndNextNull(nodep->membersp()); puts("}"); } - virtual void visit(AstMemberDType* nodep) VL_OVERRIDE { + virtual void visit(AstMemberDType* nodep) override { iterate(nodep->subDTypep()); puts(" "); puts(nodep->name()); puts("}"); } - virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTaskRef* nodep) override { if (nodep->dotted() != "") { putfs(nodep, nodep->dotted()); puts("."); @@ -607,9 +605,9 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { iterateAndNextNull(nodep->pinsp()); puts(")"); } - virtual void visit(AstArg* nodep) VL_OVERRIDE { iterateAndNextNull(nodep->exprp()); } + virtual void visit(AstArg* nodep) override { iterateAndNextNull(nodep->exprp()); } // Terminals - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { if (nodep->varScopep()) { putfs(nodep, nodep->varScopep()->prettyName()); } else { @@ -617,19 +615,17 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { puts(nodep->varp()->prettyName()); } } - virtual void visit(AstVarXRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarXRef* nodep) override { putfs(nodep, nodep->dotted()); puts("."); puts(nodep->varp()->prettyName()); } - virtual void visit(AstConst* nodep) VL_OVERRIDE { - putfs(nodep, nodep->num().ascii(true, true)); - } + virtual void visit(AstConst* nodep) override { putfs(nodep, nodep->num().ascii(true, true)); } // Just iterate - virtual void visit(AstTopScope* nodep) VL_OVERRIDE { iterateChildren(nodep); } - virtual void visit(AstScope* nodep) VL_OVERRIDE { iterateChildren(nodep); } - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstTopScope* nodep) override { iterateChildren(nodep); } + virtual void visit(AstScope* nodep) override { iterateChildren(nodep); } + virtual void visit(AstVar* nodep) override { putfs(nodep, nodep->verilogKwd()); puts(" "); iterate(nodep->dtypep()); @@ -641,20 +637,20 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { puts("\n"); } } - virtual void visit(AstActive* nodep) VL_OVERRIDE { + virtual void visit(AstActive* nodep) override { m_sensesp = nodep->sensesp(); iterateAndNextNull(nodep->stmtsp()); - m_sensesp = NULL; + m_sensesp = nullptr; } - virtual void visit(AstVarScope*) VL_OVERRIDE {} - virtual void visit(AstNodeText*) VL_OVERRIDE {} - virtual void visit(AstTraceDecl*) VL_OVERRIDE {} - virtual void visit(AstTraceInc*) VL_OVERRIDE {} + virtual void visit(AstVarScope*) override {} + virtual void visit(AstNodeText*) override {} + virtual void visit(AstTraceDecl*) override {} + virtual void visit(AstTraceInc*) override {} // NOPs - virtual void visit(AstPragma*) VL_OVERRIDE {} - virtual void visit(AstCell*) VL_OVERRIDE {} // Handled outside the Visit class + virtual void visit(AstPragma*) override {} + virtual void visit(AstCell*) override {} // Handled outside the Visit class // Default - virtual void visit(AstNode* nodep) VL_OVERRIDE { + virtual void visit(AstNode* nodep) override { puts(string("\n???? // ") + nodep->prettyTypeName() + "\n"); iterateChildren(nodep); // Not v3fatalSrc so we keep processing @@ -662,14 +658,10 @@ class EmitVBaseVisitor : public EmitCBaseVisitor { } public: - bool m_suppressVarSemi; // Suppress emitting semicolon for AstVars - explicit EmitVBaseVisitor(AstSenTree* domainp = NULL) { - // Domain for printing one a ALWAYS under a ACTIVE - m_suppressSemi = false; - m_suppressVarSemi = false; - m_sensesp = domainp; - } - virtual ~EmitVBaseVisitor() {} + bool m_suppressVarSemi = false; // Suppress emitting semicolon for AstVars + explicit EmitVBaseVisitor(AstSenTree* domainp = nullptr) + : m_sensesp{domainp} {} + virtual ~EmitVBaseVisitor() override {} }; //###################################################################### @@ -680,11 +672,11 @@ class EmitVFileVisitor : public EmitVBaseVisitor { V3OutFile* m_ofp; // METHODS V3OutFile* ofp() const { return m_ofp; } - virtual void puts(const string& str) { ofp()->puts(str); } - virtual void putbs(const string& str) { ofp()->putbs(str); } - virtual void putfs(AstNode*, const string& str) { putbs(str); } - virtual void putqs(AstNode*, const string& str) { putbs(str); } - virtual void putsNoTracking(const string& str) { ofp()->putsNoTracking(str); } + virtual void puts(const string& str) override { ofp()->puts(str); } + virtual void putbs(const string& str) override { ofp()->putbs(str); } + virtual void putfs(AstNode*, const string& str) override { putbs(str); } + virtual void putqs(AstNode*, const string& str) override { putbs(str); } + virtual void putsNoTracking(const string& str) override { ofp()->putsNoTracking(str); } public: EmitVFileVisitor(AstNode* nodep, V3OutFile* ofp, bool trackText = false, @@ -694,7 +686,7 @@ public: m_suppressVarSemi = suppressVarSemi; iterate(nodep); } - virtual ~EmitVFileVisitor() {} + virtual ~EmitVFileVisitor() override {} }; //###################################################################### @@ -704,18 +696,18 @@ class EmitVStreamVisitor : public EmitVBaseVisitor { // MEMBERS std::ostream& m_os; // METHODS - virtual void putsNoTracking(const string& str) { m_os << str; } - virtual void puts(const string& str) { putsNoTracking(str); } - virtual void putbs(const string& str) { puts(str); } - virtual void putfs(AstNode*, const string& str) { putbs(str); } - virtual void putqs(AstNode*, const string& str) { putbs(str); } + virtual void putsNoTracking(const string& str) override { m_os << str; } + virtual void puts(const string& str) override { putsNoTracking(str); } + virtual void putbs(const string& str) override { puts(str); } + virtual void putfs(AstNode*, const string& str) override { putbs(str); } + virtual void putqs(AstNode*, const string& str) override { putbs(str); } public: EmitVStreamVisitor(AstNode* nodep, std::ostream& os) - : m_os(os) { + : m_os(os) { // Need () or GCC 4.8 false warning iterate(nodep); } - virtual ~EmitVStreamVisitor() {} + virtual ~EmitVStreamVisitor() override {} }; //###################################################################### @@ -728,7 +720,7 @@ class EmitVPrefixedFormatter : public V3OutFormatter { int m_column; // Rough location; need just zero or non-zero FileLine* m_prefixFl; // METHODS - virtual void putcOutput(char chr) { + virtual void putcOutput(char chr) override { if (chr == '\n') { m_column = 0; m_os << chr; @@ -750,15 +742,16 @@ public: FileLine* prefixFl() const { return m_prefixFl; } int column() const { return m_column; } EmitVPrefixedFormatter(std::ostream& os, const string& prefix, int flWidth) - : V3OutFormatter("__STREAM", V3OutFormatter::LA_VERILOG) - , m_os(os) - , m_prefix(prefix) - , m_flWidth(flWidth) { + : V3OutFormatter{"__STREAM", V3OutFormatter::LA_VERILOG} + , m_os(os) // Need () or GCC 4.8 false warning + , m_prefix{prefix} + , m_flWidth{flWidth} { m_column = 0; - m_prefixFl = v3Global.rootp() - ->fileline(); // NETLIST's fileline instead of NULL to avoid NULL checks + m_prefixFl + = v3Global.rootp() + ->fileline(); // NETLIST's fileline instead of nullptr to avoid nullptr checks } - virtual ~EmitVPrefixedFormatter() { + virtual ~EmitVPrefixedFormatter() override { if (m_column) puts("\n"); } }; @@ -768,13 +761,13 @@ class EmitVPrefixedVisitor : public EmitVBaseVisitor { EmitVPrefixedFormatter m_formatter; // Special verilog formatter (Way down the // inheritance is another unused V3OutFormatter) // METHODS - virtual void putsNoTracking(const string& str) { m_formatter.putsNoTracking(str); } - virtual void puts(const string& str) { m_formatter.puts(str); } + virtual void putsNoTracking(const string& str) override { m_formatter.putsNoTracking(str); } + virtual void puts(const string& str) override { m_formatter.puts(str); } // We don't use m_formatter's putbs because the tokens will change filelines // and insert returns at the proper locations - virtual void putbs(const string& str) { m_formatter.puts(str); } - virtual void putfs(AstNode* nodep, const string& str) { putfsqs(nodep, str, false); } - virtual void putqs(AstNode* nodep, const string& str) { putfsqs(nodep, str, true); } + virtual void putbs(const string& str) override { m_formatter.puts(str); } + virtual void putfs(AstNode* nodep, const string& str) override { putfsqs(nodep, str, false); } + virtual void putqs(AstNode* nodep, const string& str) override { putfsqs(nodep, str, true); } void putfsqs(AstNode* nodep, const string& str, bool quiet) { if (m_formatter.prefixFl() != nodep->fileline()) { m_formatter.prefixFl(nodep->fileline()); @@ -787,12 +780,12 @@ class EmitVPrefixedVisitor : public EmitVBaseVisitor { public: EmitVPrefixedVisitor(AstNode* nodep, std::ostream& os, const string& prefix, int flWidth, AstSenTree* domainp, bool user3mark) - : EmitVBaseVisitor(domainp) - , m_formatter(os, prefix, flWidth) { + : EmitVBaseVisitor{domainp} + , m_formatter{os, prefix, flWidth} { if (user3mark) { AstUser3InUse::check(); } iterate(nodep); } - virtual ~EmitVPrefixedVisitor() {} + virtual ~EmitVPrefixedVisitor() override {} }; //###################################################################### diff --git a/src/V3EmitXml.cpp b/src/V3EmitXml.cpp index 671410316..da2d26720 100644 --- a/src/V3EmitXml.cpp +++ b/src/V3EmitXml.cpp @@ -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("\n"); iterateChildren(nodep); puts("\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 << "\n"; - for (std::deque::iterator it = m_nodeModules.begin(); it != m_nodeModules.end(); - ++it) { - m_os << "filenameLetters() << "\" filename=\"" - << (*it)->filename() << "\" language=\"" << (*it)->language().ascii() << "\"/>\n"; + for (const FileLine* ifp : m_nodeModules) { + m_os << "filenameLetters() << "\" filename=\"" << ifp->filename() + << "\" language=\"" << ifp->language().ascii() << "\"/>\n"; } m_os << "\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 << "\n"; @@ -337,7 +334,7 @@ private: m_os << "\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 << "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 {} }; //###################################################################### diff --git a/src/V3Error.cpp b/src/V3Error.cpp index 8c617d294..e60ce5667 100644 --- a/src/V3Error.cpp +++ b/src/V3Error.cpp @@ -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 diff --git a/src/V3Error.h b/src/V3Error.h index 88f96d0e1..a1846e8e4 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -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(_e)) {} + : m_e(static_cast(_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"); diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp index 623f98c1f..a1b9d4ed0 100644 --- a/src/V3Expand.cpp +++ b/src/V3Expand.cpp @@ -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 {} }; //---------------------------------------------------------------------- diff --git a/src/V3File.cpp b/src/V3File.cpp index e2437ccb9..4f5607494 100644 --- a/src/V3File.cpp +++ b/src/V3File.cpp @@ -56,8 +56,8 @@ // If change this code, run a test with the below size set very small //#define INFILTER_IPC_BUFSIZ 16 -#define INFILTER_IPC_BUFSIZ (64 * 1024) // For debug, try this as a small number -#define INFILTER_CACHE_MAX (64 * 1024) // Maximum bytes to cache if same file read twice +constexpr int INFILTER_IPC_BUFSIZ = (64 * 1024); // For debug, try this as a small number +constexpr int INFILTER_CACHE_MAX = (64 * 1024); // Maximum bytes to cache if same file read twice //###################################################################### // V3File Internal state @@ -72,9 +72,9 @@ class V3FileDependImp { struct stat m_stat; // Stat information public: DependFile(const string& filename, bool target) - : m_target(target) - , m_exists(true) - , m_filename(filename) { + : m_target{target} + , m_exists{true} + , m_filename{filename} { m_stat.st_ctime = 0; m_stat.st_mtime = 0; } @@ -146,29 +146,26 @@ V3FileDependImp dependImp; // Depend implementation class // V3FileDependImp inline void V3FileDependImp::writeDepend(const string& filename) { - const vl_unique_ptr ofp(V3File::new_ofstream(filename)); + const std::unique_ptr ofp(V3File::new_ofstream(filename)); if (ofp->fail()) v3fatal("Can't write " << filename); - for (std::set::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::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::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 V3FileDependImp::getAllDeps() const { } inline void V3FileDependImp::writeTimes(const string& filename, const string& cmdlineIn) { - const vl_unique_ptr ofp(V3File::new_ofstream(filename)); + const std::unique_ptr 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 ifp(V3File::new_ifstream_nodepend(filename)); + const std::unique_ptr 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(NULL)); + execl("/bin/sh", "sh", "-c", command.c_str(), static_cast(nullptr)); // Don't use v3fatal, we don't share the common structures any more fprintf(stderr, "--pipe-filter: exec failed: %s\n", strerror(errno)); _exit(1); @@ -575,7 +573,7 @@ protected: friend class VInFilter; // Read file contents and return it bool readWholefile(const string& filename, StrList& outl) { - FileContentsMap::iterator it = m_contentsMap.find(filename); + const auto it = m_contentsMap.find(filename); if (it != m_contentsMap.end()) { outl.push_back(it->second); return true; @@ -591,24 +589,16 @@ protected: } size_t listSize(StrList& sl) { size_t out = 0; - for (StrList::iterator it = sl.begin(); it != sl.end(); ++it) out += it->length(); + for (const string& i : sl) out += i.length(); return out; } string listString(StrList& sl) { string out; - for (StrList::iterator it = sl.begin(); it != sl.end(); ++it) out += *it; + for (const string& i : sl) out += i; return out; } // CONSTRUCTORS - explicit VInFilterImp(const string& command) { - m_readEof = false; - m_pid = 0; - m_pidExited = false; - m_pidStatus = 0; - m_writeFd = 0; - m_readFd = 0; - start(command); - } + explicit VInFilterImp(const string& command) { start(command); } ~VInFilterImp() { stop(); } }; @@ -618,7 +608,7 @@ protected: VInFilter::VInFilter(const string& command) { m_impp = new VInFilterImp(command); } VInFilter::~VInFilter() { - if (m_impp) VL_DO_CLEAR(delete m_impp, m_impp = NULL); + if (m_impp) VL_DO_CLEAR(delete m_impp, m_impp = nullptr); } bool VInFilter::readWholefile(const string& filename, VInFilter::StrList& outl) { @@ -630,14 +620,8 @@ bool VInFilter::readWholefile(const string& filename, VInFilter::StrList& outl) // V3OutFormatter: A class for printing to a file, with automatic indentation of C++ code. V3OutFormatter::V3OutFormatter(const string& filename, V3OutFormatter::Language lang) - : m_filename(filename) - , m_lang(lang) - , m_lineno(1) - , m_column(0) - , m_nobreak(false) - , m_prependIndent(true) - , m_indentLevel(0) - , m_bracketLevel(0) { + : m_filename{filename} + , m_lang{lang} { m_blockIndent = v3Global.opt.decoration() ? 4 : 1; m_commaWidth = v3Global.opt.decoration() ? 50 : 150; } @@ -844,14 +828,12 @@ void V3OutFormatter::putsQuoted(const string& strg) { // Don't use to quote a filename for #include - #include doesn't \ escape. putcNoTracking('"'); string quoted = quoteNameControls(strg); - for (string::const_iterator cp = quoted.begin(); cp != quoted.end(); ++cp) { - putcNoTracking(*cp); - } + for (const char c : quoted) putcNoTracking(c); putcNoTracking('"'); } void V3OutFormatter::putsNoTracking(const string& strg) { // Don't track {}'s, probably because it's a $display format string - for (string::const_iterator cp = strg.begin(); cp != strg.end(); ++cp) putcNoTracking(*cp); + for (const char c : strg) putcNoTracking(c); } void V3OutFormatter::putcNoTracking(char chr) { @@ -880,43 +862,43 @@ string V3OutFormatter::quoteNameControls(const string& namein, V3OutFormatter::L string out; if (lang == LA_XML) { // Encode chars into XML string - for (string::const_iterator pos = namein.begin(); pos != namein.end(); ++pos) { - if (pos[0] == '"') { + for (const char c : namein) { + if (c == '"') { out += string("""); - } else if (pos[0] == '\'') { + } else if (c == '\'') { out += string("'"); - } else if (pos[0] == '<') { + } else if (c == '<') { out += string("<"); - } else if (pos[0] == '>') { + } else if (c == '>') { out += string(">"); - } else if (pos[0] == '&') { + } else if (c == '&') { out += string("&"); - } else if (isprint(pos[0])) { - out += pos[0]; + } else if (isprint(c)) { + out += c; } else { char decimal[10]; - sprintf(decimal, "&#%u;", (unsigned char)pos[0]); + sprintf(decimal, "&#%u;", (unsigned char)c); out += decimal; } } } else { // Encode control chars into C style escapes - for (string::const_iterator pos = namein.begin(); pos != namein.end(); ++pos) { - if (pos[0] == '\\' || pos[0] == '"') { - out += string("\\") + pos[0]; - } else if (pos[0] == '\n') { + for (const char c : namein) { + if (c == '\\' || c == '"') { + out += string("\\") + c; + } else if (c == '\n') { out += "\\n"; - } else if (pos[0] == '\r') { + } else if (c == '\r') { out += "\\r"; - } else if (pos[0] == '\t') { + } else if (c == '\t') { out += "\\t"; - } else if (isprint(pos[0])) { - out += pos[0]; + } else if (isprint(c)) { + out += c; } else { // This will also cover \a etc // Can't use %03o as messes up when signed char octal[10]; - sprintf(octal, "\\%o%o%o", (pos[0] >> 6) & 3, (pos[0] >> 3) & 7, pos[0] & 7); + sprintf(octal, "\\%o%o%o", (c >> 6) & 3, (c >> 3) & 7, c & 7); out += octal; } } @@ -940,20 +922,20 @@ void V3OutFormatter::printf(const char* fmt...) { // V3OutFormatter: A class for printing to a file, with automatic indentation of C++ code. V3OutFile::V3OutFile(const string& filename, V3OutFormatter::Language lang) - : V3OutFormatter(filename, lang) { - if ((m_fp = V3File::new_fopen_w(filename)) == NULL) { v3fatal("Cannot write " << filename); } + : V3OutFormatter{filename, lang} { + if ((m_fp = V3File::new_fopen_w(filename)) == nullptr) { + v3fatal("Cannot write " << filename); + } } V3OutFile::~V3OutFile() { if (m_fp) fclose(m_fp); - m_fp = NULL; + m_fp = nullptr; } void V3OutFile::putsForceIncs() { const V3StringList& forceIncs = v3Global.opt.forceIncs(); - for (V3StringList::const_iterator it = forceIncs.begin(); it != forceIncs.end(); ++it) { - puts("#include \"" + *it + "\"\n"); - } + for (const string& i : forceIncs) { puts("#include \"" + i + "\"\n"); } } void V3OutCFile::putsGuard() { @@ -974,7 +956,7 @@ class VIdProtectImp { // MEMBERS typedef std::map IdMap; IdMap m_nameMap; // Map of old name into new name - typedef vl_unordered_set IdSet; + typedef std::unordered_set 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 diff --git a/src/V3File.h b/src/V3File.h index e98496bc9..98145475e 100644 --- a/src/V3File.h +++ b/src/V3File.h @@ -101,10 +101,10 @@ public: class V3OutFormatter { // TYPES - enum MiscConsts { MAXSPACE = 80 }; // After this indent, stop indenting more + static constexpr int MAXSPACE = 80; // After this indent, stop indenting more public: - enum AlignClass { AL_AUTO = 0, AL_STATIC = 1 }; - enum Language { + enum AlignClass : uint8_t { AL_AUTO = 0, AL_STATIC = 1 }; + enum Language : uint8_t { LA_C = 0, LA_VERILOG = 1, LA_MK = 2, @@ -117,13 +117,13 @@ private: Language m_lang; // Indenting Verilog code int m_blockIndent; // Characters per block indent int m_commaWidth; // Width after which to break at ,'s - int m_lineno; - int m_column; - int m_nobreak; // Basic operator or begin paren, don't break next - bool m_prependIndent; - int m_indentLevel; // Current {} indentation + int m_lineno = 1; + int m_column = 0; + int m_nobreak = false; // Basic operator or begin paren, don't break next + bool m_prependIndent = true; + int m_indentLevel = 0; // Current {} indentation std::stack 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("\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); } diff --git a/src/V3FileLine.cpp b/src/V3FileLine.cpp index 23b07c4cd..118292375 100644 --- a/src/V3FileLine.cpp +++ b/src/V3FileLine.cpp @@ -31,7 +31,7 @@ #include #include -#include VL_INCLUDE_UNORDERED_SET +#include //###################################################################### // 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 FileLineCheckSet; +typedef std::unordered_set 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(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. diff --git a/src/V3FileLine.h b/src/V3FileLine.h index 4cc568886..85aa5500a 100644 --- a/src/V3FileLine.h +++ b/src/V3FileLine.h @@ -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(); diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index 8c3a785ad..085586bf5 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -35,11 +35,11 @@ #include #include #include -#include VL_INCLUDE_UNORDERED_SET +#include typedef std::list 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 VarScopeSet; + typedef std::unordered_set 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(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(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(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(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 {} }; //###################################################################### diff --git a/src/V3GenClk.cpp b/src/V3GenClk.cpp index 135d1394a..60ba799df 100644 --- a/src/V3GenClk.cpp +++ b/src/V3GenClk.cpp @@ -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 {} }; //###################################################################### diff --git a/src/V3Global.cpp b/src/V3Global.cpp index 1e1f0a784..2b8a627fe 100644 --- a/src/V3Global.cpp +++ b/src/V3Global.cpp @@ -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) { diff --git a/src/V3Global.h b/src/V3Global.h index 659b47737..3c607052e 100644 --- a/src/V3Global.h +++ b/src/V3Global.h @@ -31,26 +31,47 @@ #include "V3Options.h" #include -#include VL_INCLUDE_UNORDERED_MAP +#include 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 restorer_##var(var); + +// Object used by VL_RESTORER. This object must be an auto variable, not +// allocated on the heap or otherwise. +template 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(_e)) {} + : m_e(static_cast(_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 PtrToIdMap; // The map type + typedef std::unordered_map 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); diff --git a/src/V3Graph.cpp b/src/V3Graph.cpp index 0b91d6ac4..2ee8c5c9b 100644 --- a/src/V3Graph.cpp +++ b/src/V3Graph.cpp @@ -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 logp(V3File::new_ofstream(filename)); + const std::unique_ptr logp(V3File::new_ofstream(filename)); if (logp->fail()) v3fatal("Can't write " << filename); // Header diff --git a/src/V3Graph.h b/src/V3Graph.h index c30f12618..c8d0b2431 100644 --- a/src/V3Graph.h +++ b/src/V3Graph.h @@ -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(_e)) {} + : m_e(static_cast(_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; diff --git a/src/V3GraphAcyc.cpp b/src/V3GraphAcyc.cpp index da07309ca..393b74754 100644 --- a/src/V3GraphAcyc.cpp +++ b/src/V3GraphAcyc.cpp @@ -35,23 +35,20 @@ class GraphAcycVertex : public V3GraphVertex { protected: friend class GraphAcyc; V3ListEnt 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 m_work; // List of vertices with optimization work left std::vector 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::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::iterator it = edges.begin(); it != edges.end(); ++it) { - V3GraphEdge* edgep = (*it); - placeTryEdge(edgep); - } + for (V3GraphEdge* edgep : edges) placeTryEdge(edgep); } void GraphAcyc::placeTryEdge(V3GraphEdge* edgep) { diff --git a/src/V3GraphAlg.cpp b/src/V3GraphAlg.cpp index d82babee4..504c719cf 100644 --- a/src/V3GraphAlg.cpp +++ b/src/V3GraphAlg.cpp @@ -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::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::const_iterator it = edges.begin(); it != edges.end(); - ++it) { - (*it)->outPushBack(); - } + for (V3GraphEdge* edgep : edges) edgep->outPushBack(); // Prep for next edges.clear(); } diff --git a/src/V3GraphAlg.h b/src/V3GraphAlg.h index 073c48c98..3d7abaea5 100644 --- a/src/V3GraphAlg.h +++ b/src/V3GraphAlg.h @@ -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) { diff --git a/src/V3GraphDfa.cpp b/src/V3GraphDfa.cpp index 084f628e9..9d2eeb203 100644 --- a/src/V3GraphDfa.cpp +++ b/src/V3GraphDfa.cpp @@ -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(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 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(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() {} diff --git a/src/V3GraphDfa.h b/src/V3GraphDfa.h index 85fc47f60..a2ec64bd8 100644 --- a/src/V3GraphDfa.h +++ b/src/V3GraphDfa.h @@ -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; } diff --git a/src/V3GraphPathChecker.cpp b/src/V3GraphPathChecker.cpp index 611ed8fe2..d0242f9dc 100644 --- a/src/V3GraphPathChecker.cpp +++ b/src/V3GraphPathChecker.cpp @@ -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(graphp, edgeFuncp) - , m_generation(0) { + : GraphAlg{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(vxp->userp()); VL_DO_DANGLING(delete nodep, nodep); - vxp->userp(NULL); + vxp->userp(nullptr); } } diff --git a/src/V3GraphPathChecker.h b/src/V3GraphPathChecker.h index 2f6675460..e50daf064 100644 --- a/src/V3GraphPathChecker.h +++ b/src/V3GraphPathChecker.h @@ -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; } diff --git a/src/V3GraphStream.h b/src/V3GraphStream.h index 028d0a203..233184397 100644 --- a/src/V3GraphStream.h +++ b/src/V3GraphStream.h @@ -24,7 +24,7 @@ #include "V3Graph.h" #include -#include VL_INCLUDE_UNORDERED_MAP +#include //###################################################################### // 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 ReadyVertices; - typedef vl_unordered_map WaitingVertices; + typedef std::unordered_map 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 > GraphStreamUnordered; +typedef GraphStream> GraphStreamUnordered; #endif // Guard diff --git a/src/V3GraphTest.cpp b/src/V3GraphTest.cpp index 19f489f0c..ac2f66f48 100644 --- a/src/V3GraphTest.cpp +++ b/src/V3GraphTest.cpp @@ -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(); diff --git a/src/V3Hashed.cpp b/src/V3Hashed.cpp index 8a3589234..9196a808d 100644 --- a/src/V3Hashed.cpp +++ b/src/V3Hashed.cpp @@ -60,7 +60,7 @@ private: nodep, "Node " << nodep->prettyTypeName() << " in statement position but not marked stmt (node under function)"); - V3Hash oldHash = m_lowerHash; + VL_RESTORER(m_lowerHash); { m_lowerHash = nodep->sameHash(); UASSERT_OBJ(!m_lowerHash.isIllegal(), nodep, @@ -74,19 +74,18 @@ private: // Store the hash value nodep->user4(m_lowerHash.fullValue()); // UINFO(9, " hashnode "<(nodep)); } V3Hash finalHash() const { return m_lowerHash; } - virtual ~HashedVisitor() {} + virtual ~HashedVisitor() override {} }; //###################################################################### @@ -136,7 +135,7 @@ void V3Hashed::erase(iterator it) { UINFO(8, " erase " << nodep << endl); UASSERT_OBJ(nodep->user4p(), nodep, "Called removeNode on non-hashed node"); m_hashMmap.erase(it); - nodep->user4p(NULL); // So we don't allow removeNode again + nodep->user4p(nullptr); // So we don't allow removeNode again } void V3Hashed::check() { @@ -151,7 +150,7 @@ void V3Hashed::dumpFilePrefixed(const string& nameComment, bool tree) { } void V3Hashed::dumpFile(const string& filename, bool tree) { - const vl_unique_ptr logp(V3File::new_ofstream(filename)); + const std::unique_ptr logp(V3File::new_ofstream(filename)); if (logp->fail()) v3fatal("Can't write " << filename); std::map dist; diff --git a/src/V3Hashed.h b/src/V3Hashed.h index 0ea3ee10d..fd538cadd 100644 --- a/src/V3Hashed.h +++ b/src/V3Hashed.h @@ -79,7 +79,7 @@ public: bool sameNodes(AstNode* node1p, AstNode* node2p); // After hashing, and tell if identical void erase(iterator it); // Remove node from structures // Return duplicate in hash, if any, with optional user check for sameness - iterator findDuplicate(AstNode* nodep, V3HashedUserSame* checkp = NULL); + iterator findDuplicate(AstNode* nodep, V3HashedUserSame* checkp = nullptr); AstNode* iteratorNodep(iterator it) { return it->second; } void dumpFile(const string& filename, bool tree); void dumpFilePrefixed(const string& nameComment, bool tree = false); diff --git a/src/V3HierBlock.cpp b/src/V3HierBlock.cpp new file mode 100644 index 000000000..59adf8211 --- /dev/null +++ b/src/V3HierBlock.cpp @@ -0,0 +1,420 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: Hierarchical verilation for large designs +// +// 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 +// +//************************************************************************* +// Hierarchical Verilation is useful for large designs. +// It reduces +// - time and memory for Verilation +// - compilation time especially when a hierarchical block is used many times +// +// Hierarchical Verilation internally creates protect-lib for each hierarchical block. +// Upper modules read wrapper for the protect-lib instead of the actual design. +// +// Hierarchical Verilation runs as the following step +// 1) Find modules marked by /*verilator hier_block*/ metacomment +// 2) Generate ${prefix}_hier.mk to create protected-lib for hierarchical blocks and +// final Verilation to process the top module, that refers wrappers +// 3) Call child Verilator process via ${prefix}_hier.mk +// +// There are 3 kinds of Verilator run. +// a) To create ${prefix}_hier.mk (--hierarchical) +// b) To create protect-lib for each hierarchical block (--hierarchical-child) +// c) To load wrappers and Verilate the top module (... what primary flags?) +// +// Then user can build Verilated module as usual. +// +// Here is more detailed internal process. +// 1) Parser adds AstPragmaType::HIER_BLOCK of AstPragma to modules +// that are marked with /*verilator hier_block*/ metacomment in Verilator run a). +// 2) AstModule with HIER_BLOCK pragma is marked modp->hier_block(true) +// in V3LinkResolve.cpp during run a). +// 3) In V3LinkCells.cpp, the following things are done during run b) and c). +// 3-1) Delete the upper modules of the hierarchical block because the top module in run b) is +// hierarchical block, not the top module of run c). +// 3-2) If the top module of the run b) or c) instantiates other hierarchical blocks that is +// parameterized, +// module and task names are renamed to the original name to be compatible with the +// hier module to be called. +// +// Parameterized modules have unique name by V3Param.cpp. The unique name contains '__' and +// Verilator encodes '__' when loading such symbols. +// 4) V3LinkDot.cpp checks dotted access across hierarchical block boundary. +// 5) In V3Dead.cpp, some parameters of parameterized modules are protected not to be deleted even +// if the parameter is not referred. This protection is necessary to match step 6) below. +// 6) In V3Param.cpp, use protect-lib wrapper of parameterized module made in b) and c). +// If a hierarchical block is a parameterized module and instantiated in multiple locations, +// all parameters must exactly match. +// 7) In V3HierBlock.cpp, relationship among hierarchical blocks are checked in run a). +// (which block uses other blocks..) +// 8) In V3EmitMk.cpp, ${prefix}_hier.mk is created in run a). +// +// There are two hidden command options. +// --hierarchical-child is added to Verilator run b). +// --hierarchical-block module_name,mangled_name,name0,value0,name1,value1,... +// module_name :The original modulename +// mangled_name :Mangled name of parameterized modules (named in V3Param.cpp). +// Same as module_name for non-parameterized hierarchical block. +// name :The name of the parameter +// value :Overridden value of the parameter +// +// Used for b) and c). +// This options is repeated for all instantiating hierarchical blocks. + +#include +#include +#include +#include + +#include "V3Ast.h" +#include "V3Error.h" +#include "V3File.h" +#include "V3HierBlock.h" +#include "V3String.h" +#include "V3Stats.h" + +static string V3HierCommandArgsFileName(const string& prefix, bool forCMake) { + return v3Global.opt.makeDir() + "/" + prefix + + (forCMake ? "_hierCMakeArgs.f" : "_hierMkArgs.f"); +} + +static void V3HierWriteCommonInputs(std::ostream* of, bool forCMake) { + if (!forCMake) { + const V3StringList& vFiles = v3Global.opt.vFiles(); + for (const string& i : vFiles) *of << i << "\n"; + } + const V3StringSet& libraryFiles = v3Global.opt.libraryFiles(); + for (const string& i : libraryFiles) *of << "-v " << i << "\n"; +} + +//###################################################################### + +V3HierBlock::StrGParams V3HierBlock::stringifyParams(const GParams& gparams, bool forGOption) { + StrGParams strParams; + for (V3HierBlock::GParams::const_iterator gparamIt = gparams.begin(); + gparamIt != gparams.end(); ++gparamIt) { + if (const AstConst* constp = VN_CAST((*gparamIt)->valuep(), Const)) { + string s; + // Only constant parameter needs to be set to -G because already checked in + // V3Param.cpp. See also ParamVisitor::checkSupportedParam() in the file. + if (constp->isDouble()) { + // 64 bit width of hex can be expressed with 16 chars. + // 32 chars must be long enough for hexadecial floating point + // considering prefix of '0x', '.', and 'P'. + std::vector hexFpStr(32, '\0'); + const int len = VL_SNPRINTF(hexFpStr.data(), hexFpStr.size(), "%a", + constp->num().toDouble()); + UASSERT_OBJ(0 < len && static_cast(len) < hexFpStr.size(), constp, + " is not properly converted to string"); + s = hexFpStr.data(); + } else if (constp->isString()) { + s = constp->num().toString(); + if (!forGOption) s = VString::quoteBackslash(s); + s = VString::quoteStringLiteralForShell(s); + } else { // Either signed or unsigned integer. + s = constp->num().ascii(true, true); + s = VString::quoteAny(s, '\'', '\\'); + } + strParams.push_back(std::make_pair((*gparamIt)->name(), s)); + } + } + return strParams; +} + +V3HierBlock::~V3HierBlock() { + UASSERT(m_children.empty(), "at least one module must be a leaf"); + for (HierBlockSet::const_iterator child = m_children.begin(); child != m_children.end(); + ++child) { + const bool deleted = (*child)->m_children.erase(this); + UASSERT_OBJ(deleted, m_modp, " is not registered"); + } +} + +V3StringList V3HierBlock::commandArgs(bool forCMake) const { + V3StringList opts; + const string prefix = hierPrefix(); + if (!forCMake) { + opts.push_back(" --prefix " + prefix); + opts.push_back(" --mod-prefix " + prefix); + opts.push_back(" --top-module " + modp()->name()); + } + opts.push_back(" --protect-lib " + modp()->name()); // mangled name + opts.push_back(" --protect-key " + v3Global.opt.protectKeyDefaulted()); + opts.push_back(" --hierarchical-child"); + + const StrGParams gparamsStr = stringifyParams(gparams(), true); + for (StrGParams::const_iterator paramIt = gparamsStr.begin(); paramIt != gparamsStr.end(); + ++paramIt) { + opts.push_back("-G" + paramIt->first + "=" + paramIt->second + ""); + } + return opts; +} + +V3StringList V3HierBlock::hierBlockArgs() const { + V3StringList opts; + const StrGParams gparamsStr = stringifyParams(gparams(), false); + opts.push_back("--hierarchical-block "); + string s = modp()->origName(); // origName + s += "," + modp()->name(); // mangledName + for (StrGParams::const_iterator paramIt = gparamsStr.begin(); paramIt != gparamsStr.end(); + ++paramIt) { + s += "," + paramIt->first; + s += "," + paramIt->second; + } + opts.back() += s; + return opts; +} + +string V3HierBlock::hierPrefix() const { return "V" + modp()->name(); } + +string V3HierBlock::hierSomeFile(bool withDir, const char* prefix, const char* suffix) const { + string s; + if (withDir) s = hierPrefix() + '/'; + s += prefix + modp()->name() + suffix; + return s; +} + +string V3HierBlock::hierWrapper(bool withDir) const { return hierSomeFile(withDir, "", ".sv"); } + +string V3HierBlock::hierMk(bool withDir) const { return hierSomeFile(withDir, "V", ".mk"); } + +string V3HierBlock::hierLib(bool withDir) const { return hierSomeFile(withDir, "lib", ".a"); } + +string V3HierBlock::hierGenerated(bool withDir) const { + return hierWrapper(withDir) + ' ' + hierMk(withDir); +} + +void V3HierBlock::writeCommandArgsFile(bool forCMake) const { + std::unique_ptr of(V3File::new_ofstream(commandArgsFileName(forCMake))); + *of << "--cc\n"; + + if (!forCMake) { + for (V3HierBlock::HierBlockSet::const_iterator child = m_children.begin(); + child != m_children.end(); ++child) { + *of << v3Global.opt.makeDir() << "/" << (*child)->hierWrapper(true) << "\n"; + } + } + *of << "-Mdir " << v3Global.opt.makeDir() << "/" << hierPrefix() << " \n"; + V3HierWriteCommonInputs(of.get(), forCMake); + const V3StringList& commandOpts = commandArgs(false); + for (const string& opt : commandOpts) *of << opt << "\n"; + *of << hierBlockArgs().front() << "\n"; + for (HierBlockSet::const_iterator child = m_children.begin(); child != m_children.end(); + ++child) { + *of << (*child)->hierBlockArgs().front() << "\n"; + } + *of << v3Global.opt.allArgsStringForHierBlock(false) << "\n"; +} + +string V3HierBlock::commandArgsFileName(bool forCMake) const { + return V3HierCommandArgsFileName(hierPrefix(), forCMake); +} + +//###################################################################### +// Collect how hierarchical blocks are used +class HierBlockUsageCollectVisitor : public AstNVisitor { + // NODE STATE + // AstNode::user1() -> bool. Processed + AstUser1InUse m_inuser1; + + // STATE + typedef std::set ModuleSet; + V3HierBlockPlan* const m_planp; + AstModule* m_modp = nullptr; // The current module + AstModule* m_hierBlockp = nullptr; // The nearest parent module that is a hierarchical block + ModuleSet m_referred; // Modules that have hier_block pragma + V3HierBlock::GParams m_gparams; // list of variables that is AstVarType::GPARAM + + virtual void visit(AstModule* nodep) override { + // Don't visit twice + if (nodep->user1SetOnce()) return; + UINFO(5, "Checking " << nodep->prettyNameQ() << " from " + << (m_hierBlockp ? m_hierBlockp->prettyNameQ() : string("null")) + << std::endl); + VL_RESTORER(m_modp); + AstModule* const prevHierBlockp = m_hierBlockp; + ModuleSet prevReferred; + V3HierBlock::GParams prevGParams; + m_modp = nodep; + if (nodep->hierBlock()) { + m_hierBlockp = nodep; + prevReferred.swap(m_referred); + } + prevGParams.swap(m_gparams); + + iterateChildren(nodep); + + if (nodep->hierBlock()) { + m_planp->add(nodep, m_gparams); + for (const AstModule* modp : m_referred) m_planp->registerUsage(nodep, modp); + m_hierBlockp = prevHierBlockp; + m_referred = prevReferred; + } + m_gparams = prevGParams; + } + virtual void visit(AstCell* nodep) override { + // Visit used module here to know that the module is hier_block or not. + // This visitor behaves almost depth first search + if (AstModule* modp = VN_CAST(nodep->modp(), Module)) { + iterate(modp); + m_referred.insert(modp); + } + // Nothing to do for interface because hierarchical block does not exist + // beyond interface. + } + virtual void visit(AstVar* nodep) override { + if (m_modp && m_modp->hierBlock() && nodep->isIfaceRef() && !nodep->isIfaceParent()) { + nodep->v3error("Modport cannot be used at the hierarchical block boundary"); + } + if (nodep->isGParam() && nodep->overriddenParam()) m_gparams.push_back(nodep); + } + + virtual void visit(AstNodeMath*) override {} // Accelerate + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + +public: + HierBlockUsageCollectVisitor(V3HierBlockPlan* planp, AstNetlist* netlist) + : m_planp{planp} { + iterateChildren(netlist); + } + VL_DEBUG_FUNC; // Declare debug() +}; + +//###################################################################### + +V3HierBlockPlan::V3HierBlockPlan() {} + +bool V3HierBlockPlan::isHierBlock(const AstNodeModule* modp) const { + return m_blocks.find(modp) != m_blocks.end(); +} + +void V3HierBlockPlan::add(const AstNodeModule* modp, const std::vector& gparams) { + iterator it = m_blocks.find(modp); + if (it == m_blocks.end()) { + V3HierBlock* hblockp = new V3HierBlock(modp, gparams); + UINFO(3, "Add " << modp->prettyNameQ() << " with " << gparams.size() << " parameters" + << std::endl); + m_blocks.insert(std::make_pair(modp, hblockp)); + } +} + +void V3HierBlockPlan::registerUsage(const AstNodeModule* parentp, const AstNodeModule* childp) { + iterator parent = m_blocks.find(parentp); + UASSERT_OBJ(parent != m_blocks.end(), parentp, "must be added"); + iterator child = m_blocks.find(childp); + if (child != m_blocks.end()) { + UINFO(3, "Found usage relation " << parentp->prettyNameQ() << " uses " + << childp->prettyNameQ() << std::endl); + parent->second->addChild(child->second); + child->second->addParent(parent->second); + } +} + +void V3HierBlockPlan::createPlan(AstNetlist* nodep) { + // When processing a hierarchical block, no need to create a plan anymore. + if (v3Global.opt.hierChild()) return; + + AstNodeModule* modp = nodep->topModulep(); + if (modp->hierBlock()) { + modp->v3warn(HIERBLOCK, + "Top module illegally marked hierarchical block, ignoring marking\n" + + V3Error::warnMore() + + "... Suggest remove verilator hier_block on this module"); + modp->hierBlock(false); + } + + std::unique_ptr planp(new V3HierBlockPlan()); + { HierBlockUsageCollectVisitor visitor(planp.get(), nodep); } + + V3Stats::addStat("HierBlock, Hierarchical blocks", planp->m_blocks.size()); + + // No hierarchical block is found, nothing to do. + if (planp->empty()) return; + + v3Global.hierPlanp(planp.release()); +} + +V3HierBlockPlan::HierVector V3HierBlockPlan::hierBlocksSorted() const { + typedef std::map> ChildrenMap; + ChildrenMap childrenOfHierBlock; + + HierVector sorted; + for (const_iterator it = begin(); it != end(); ++it) { + if (!it->second->hasChild()) { // No children, already leaf + sorted.push_back(it->second); + } else { + ChildrenMap::value_type::second_type& childrenSet + = childrenOfHierBlock[it->second]; // insert + const V3HierBlock::HierBlockSet& c = it->second->children(); + childrenSet.insert(c.begin(), c.end()); + } + } + + // Use index instead of iterator because new elements will be added in this loop + for (size_t i = 0; i < sorted.size(); ++i) { + // This hblockp is already leaf. + const V3HierBlock* hblockp = sorted[i]; + const V3HierBlock::HierBlockSet& p = hblockp->parents(); + for (V3HierBlock::HierBlockSet::const_iterator it = p.begin(); it != p.end(); ++it) { + // Delete hblockp from parrents. If a parent does not have a child anymore, then it is + // a leaf too. + const auto parentIt = childrenOfHierBlock.find(*it); + UASSERT_OBJ(parentIt != childrenOfHierBlock.end(), (*it)->modp(), "must be included"); + const V3HierBlock::HierBlockSet::size_type erased = parentIt->second.erase(hblockp); + UASSERT_OBJ(erased == 1, hblockp->modp(), + " must be a child of " << parentIt->first->modp()); + if (parentIt->second.empty()) { // Now parentIt is leaf + sorted.push_back(parentIt->first); + childrenOfHierBlock.erase(parentIt); + } + } + } + return sorted; +} + +void V3HierBlockPlan::writeCommandArgsFiles(bool forCMake) const { + for (const_iterator it = begin(); it != end(); ++it) { + it->second->writeCommandArgsFile(forCMake); + } + // For the top module + std::unique_ptr of(V3File::new_ofstream(topCommandArgsFileName(forCMake))); + if (!forCMake) { + // Load wrappers first not to be overwritten by the original HDL + for (const_iterator it = begin(); it != end(); ++it) { + *of << it->second->hierWrapper(true) << "\n"; + } + } + V3HierWriteCommonInputs(of.get(), forCMake); + if (!forCMake) { + const V3StringSet& cppFiles = v3Global.opt.cppFiles(); + for (const string& i : cppFiles) *of << i << "\n"; + *of << "--top-module " << v3Global.rootp()->topModulep()->name() << "\n"; + *of << "--prefix " << v3Global.opt.prefix() << "\n"; + *of << "-Mdir " << v3Global.opt.makeDir() << "\n"; + *of << "--mod-prefix " << v3Global.opt.modPrefix() << "\n"; + } + for (const_iterator it = begin(); it != end(); ++it) { + *of << it->second->hierBlockArgs().front() << "\n"; + } + + if (!v3Global.opt.protectLib().empty()) { + *of << "--protect-lib " << v3Global.opt.protectLib() << "\n"; + *of << "--protect-key " << v3Global.opt.protectKeyDefaulted() << "\n"; + } + *of << (v3Global.opt.systemC() ? "--sc" : "--cc") << "\n"; + *of << v3Global.opt.allArgsStringForHierBlock(true) << "\n"; +} + +string V3HierBlockPlan::topCommandArgsFileName(bool forCMake) const { + return V3HierCommandArgsFileName(v3Global.opt.prefix(), forCMake); +} diff --git a/src/V3HierBlock.h b/src/V3HierBlock.h new file mode 100644 index 000000000..6bc0ce285 --- /dev/null +++ b/src/V3HierBlock.h @@ -0,0 +1,128 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: Plan for Hierarchical Verilation +// +// Code available from: https://verilator.org +// +//************************************************************************* +// +// Copyright 2003-2020 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// +// Verilator is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +//************************************************************************* + +#ifndef _V3HIERBLOCK_H_ +#define _V3HIERBLOCK_H_ 1 + +#include "verilatedos.h" + +#include "V3Global.h" + +#include +#include +#include +#include +#include + +class AstNodeModule; +class AstNetlist; +class AstVar; + +//###################################################################### + +class V3HierBlock { +public: + typedef std::vector GParams; + typedef std::set HierBlockSet; + typedef std::set NodeModuleSet; + +private: + // TYPES + // Parameter name, stringified value + typedef std::vector> StrGParams; + + // MEMBERS + const AstNodeModule* m_modp; // Hierarchical block module + // Hierarchical blocks that directly or indirectly instantiate this block + HierBlockSet m_parents; + // Hierarchical blocks that this block directly or indirectly instantiates + HierBlockSet m_children; + // Parameters that are overridden by #(.param(value)) syntax. + GParams m_gparams; + + // METHODS + VL_UNCOPYABLE(V3HierBlock); + static StrGParams stringifyParams(const GParams& gparams, bool forGOption); + +public: + V3HierBlock(const AstNodeModule* modp, const GParams& gparams) + : m_modp{modp} + , m_gparams{gparams} {} + ~V3HierBlock(); + VL_DEBUG_FUNC; // Declare debug() + + void addParent(V3HierBlock* parentp) { m_parents.insert(parentp); } + void addChild(V3HierBlock* childp) { m_children.insert(childp); } + bool hasChild() const { return !m_children.empty(); } + const HierBlockSet& parents() const { return m_parents; } + const HierBlockSet& children() const { return m_children; } + const GParams& gparams() const { return m_gparams; } + const AstNodeModule* modp() const { return m_modp; } + + // For emitting Makefile and CMakeLists.txt + V3StringList commandArgs(bool forCMake) const; + V3StringList hierBlockArgs() const; + string hierPrefix() const; + string hierSomeFile(bool withDir, const char* prefix, const char* suffix) const; + string hierWrapper(bool withDir) const; + string hierMk(bool withDir) const; + string hierLib(bool withDir) const; + string hierGenerated(bool withDir) const; + // Write command line argumuents to .f file for this hierarchical block + void writeCommandArgsFile(bool forCMake) const; + string commandArgsFileName(bool forCMake) const; +}; + +//###################################################################### + +// Holds relashonship between AstNodeModule and V3HierBlock +class V3HierBlockPlan { + typedef std::map HierMap; + HierMap m_blocks; + + V3HierBlockPlan(); + VL_UNCOPYABLE(V3HierBlockPlan); + +public: + typedef HierMap::iterator iterator; + typedef HierMap::const_iterator const_iterator; + typedef std::vector HierVector; + VL_DEBUG_FUNC; // Declare debug() + + bool isHierBlock(const AstNodeModule* modp) const; + void add(const AstNodeModule* modp, const std::vector& gparams); + void registerUsage(const AstNodeModule* parentp, const AstNodeModule* childp); + + const_iterator begin() const { return m_blocks.begin(); } + const_iterator end() const { return m_blocks.end(); } + bool empty() const { return m_blocks.empty(); } + + // Returns all hierarchical blocks that sorted in leaf-first order. + // Latter block refers only already appeared hierarchical blocks. + HierVector hierBlocksSorted() const; + + // Write command line arguments to .f files for child Verilation run + void writeCommandArgsFiles(bool forCMake) const; + string topCommandArgsFileName(bool forCMake) const; + + static void createPlan(AstNetlist* nodep); +}; + +#endif // guard diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index 301590f3b..9a0c9af82 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -36,7 +36,7 @@ #include #include -#include VL_INCLUDE_UNORDERED_SET +#include // CONFIG static const int INLINE_MODS_SMALLER = 100; // If a mod is < this # nodes, can always inline it @@ -58,7 +58,7 @@ private: AstUser4InUse m_inuser4; // For the user2 field: - enum { + enum : uint8_t { CIL_NOTHARD = 0, // Inline not supported CIL_NOTSOFT, // Don't inline unless user overrides CIL_MAYBE, // Might inline @@ -66,7 +66,7 @@ private: }; // Pragma suggests inlining // STATE - AstNodeModule* m_modp; // Current module + AstNodeModule* m_modp = nullptr; // Current module VDouble0 m_statUnsup; // Statistic tracking typedef std::vector ModVec; @@ -97,7 +97,7 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { + virtual void visit(AstNodeModule* nodep) override { UASSERT_OBJ(!m_modp, nodep, "Unsupported: Recursive modules"); m_modp = nodep; m_allMods.push_back(nodep); @@ -111,20 +111,20 @@ private: if (m_modp->modPublic()) cantInline("modPublic", false); iterateChildren(nodep); - m_modp = NULL; + m_modp = nullptr; } - virtual void visit(AstClass* nodep) VL_OVERRIDE { + virtual void visit(AstClass* nodep) override { // TODO allow inlining of modules that have classes // (Probably wait for new inliner scheme) cantInline("class", true); iterateChildren(nodep); } - virtual void visit(AstCell* nodep) VL_OVERRIDE { + virtual void visit(AstCell* nodep) override { nodep->modp()->user3Inc(); // Inc refs m_instances[m_modp][nodep->modp()]++; iterateChildren(nodep); } - virtual void visit(AstPragma* nodep) VL_OVERRIDE { + virtual void visit(AstPragma* nodep) override { if (nodep->pragType() == AstPragmaType::INLINE_MODULE) { // UINFO(0, "PRAG MARK " << m_modp << endl); if (!m_modp) { @@ -146,35 +146,35 @@ private: iterateChildren(nodep); } } - virtual void visit(AstVarXRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarXRef* nodep) override { // Cleanup link until V3LinkDot can correct it - nodep->varp(NULL); + nodep->varp(nullptr); } - virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTaskRef* nodep) override { // Cleanup link until V3LinkDot can correct it // MethodCalls not currently supported by inliner, so keep linked - if (!nodep->packagep() && !VN_IS(nodep, MethodCall)) nodep->taskp(NULL); + if (!nodep->packagep() && !VN_IS(nodep, MethodCall)) nodep->taskp(nullptr); iterateChildren(nodep); } - virtual void visit(AstAlways* nodep) VL_OVERRIDE { + virtual void visit(AstAlways* nodep) override { iterateChildren(nodep); m_modp->user4Inc(); // statement count } - virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { + virtual void visit(AstNodeAssign* nodep) override { // Don't count assignments, as they'll likely flatten out // Still need to iterate though to nullify VarXRefs int oldcnt = m_modp->user4(); iterateChildren(nodep); m_modp->user4(oldcnt); } - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { // Build user2, user3, and user4 for all modules. // Also build m_allMods and m_instances. iterateChildren(nodep); // Iterate through all modules in bottom-up order. // Make a final inlining decision for each. - for (ModVec::reverse_iterator it = m_allMods.rbegin(); it != m_allMods.rend(); ++it) { + for (auto it = m_allMods.rbegin(); it != m_allMods.rend(); ++it) { AstNodeModule* modp = *it; // If we're going to inline some modules into this one, @@ -210,7 +210,7 @@ private: } } //-------------------- - virtual void visit(AstNode* nodep) VL_OVERRIDE { + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); if (m_modp) { m_modp->user4Inc(); // Inc statement count @@ -219,11 +219,8 @@ private: public: // CONSTRUCTORS - explicit InlineMarkVisitor(AstNode* nodep) { - m_modp = NULL; - iterate(nodep); - } - virtual ~InlineMarkVisitor() { + explicit InlineMarkVisitor(AstNode* nodep) { iterate(nodep); } + virtual ~InlineMarkVisitor() override { V3Stats::addStat("Optimizations, Inline unsupported", m_statUnsup); // Done with these, are not outputs AstNode::user2ClearTree(); @@ -246,18 +243,18 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstCell* nodep) VL_OVERRIDE { nodep->user4p(nodep->clonep()); } + virtual void visit(AstCell* nodep) override { nodep->user4p(nodep->clonep()); } //-------------------- - virtual void visit(AstNodeStmt*) VL_OVERRIDE {} // Accelerate - virtual void visit(AstNodeMath*) VL_OVERRIDE {} // Accelerate - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNodeStmt*) override {} // Accelerate + virtual void visit(AstNodeMath*) override {} // Accelerate + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit InlineCollectVisitor(AstNodeModule* nodep) { // passed OLD module, not new one iterate(nodep); } - virtual ~InlineCollectVisitor() {} + virtual ~InlineCollectVisitor() override {} }; //###################################################################### @@ -265,7 +262,7 @@ public: class InlineRelinkVisitor : public AstNVisitor { private: - typedef vl_unordered_set StringSet; + typedef std::unordered_set StringSet; // NODE STATE // Input: @@ -280,7 +277,7 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstCellInline* nodep) VL_OVERRIDE { + virtual void visit(AstCellInline* nodep) override { // Inlined cell under the inline cell, need to move to avoid conflicts nodep->unlinkFrBack(); m_modp->addInlinesp(nodep); @@ -291,22 +288,22 @@ private: // Do CellInlines under this, but don't move them iterateChildren(nodep); } - virtual void visit(AstCell* nodep) VL_OVERRIDE { + virtual void visit(AstCell* nodep) override { // Cell under the inline cell, need to rename to avoid conflicts string name = m_cellp->name() + "__DOT__" + nodep->name(); nodep->name(name); iterateChildren(nodep); } - virtual void visit(AstClass* nodep) VL_OVERRIDE { + virtual void visit(AstClass* nodep) override { string name = m_cellp->name() + "__DOT__" + nodep->name(); nodep->name(name); iterateChildren(nodep); } - virtual void visit(AstModule* nodep) VL_OVERRIDE { + virtual void visit(AstModule* nodep) override { m_renamedInterfaces.clear(); iterateChildren(nodep); } - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { if (nodep->user2p()) { // Make an assignment, so we'll trace it properly // user2p is either a const or a var. @@ -384,17 +381,17 @@ private: if (debug() >= 9 && nodep->valuep()) { nodep->valuep()->dumpTree(cout, "varchangei:"); } iterateChildren(nodep); } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTask* nodep) override { // Function under the inline cell, need to rename to avoid conflicts nodep->name(m_cellp->name() + "__DOT__" + nodep->name()); iterateChildren(nodep); } - virtual void visit(AstTypedef* nodep) VL_OVERRIDE { + virtual void visit(AstTypedef* nodep) override { // Typedef under the inline cell, need to rename to avoid conflicts nodep->name(m_cellp->name() + "__DOT__" + nodep->name()); iterateChildren(nodep); } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { if (nodep->varp()->user2p() // It's being converted to an alias. && !nodep->varp()->user3() // Don't constant propagate aliases (we just made) @@ -414,7 +411,7 @@ private: nodep->name(nodep->varp()->name()); iterateChildren(nodep); } - virtual void visit(AstVarXRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarXRef* nodep) override { // Track what scope it was originally under so V3LinkDot can resolve it string newdots = VString::dot(m_cellp->name(), ".", nodep->inlinedDots()); nodep->inlinedDots(newdots); @@ -433,7 +430,7 @@ private: } iterateChildren(nodep); } - virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTaskRef* nodep) override { // Track what scope it was originally under so V3LinkDot can resolve it string newdots = VString::dot(m_cellp->name(), ".", nodep->inlinedDots()); nodep->inlinedDots(newdots); @@ -445,9 +442,9 @@ private: } // Not needed, as V3LinkDot doesn't care about typedefs - // virtual void visit(AstRefDType* nodep) VL_OVERRIDE {} + // virtual void visit(AstRefDType* nodep) override {} - 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 V3Begin // To keep correct visual order, must add before other Text's @@ -461,21 +458,21 @@ private: if (afterp) nodep->scopeEntrp(afterp); iterateChildren(nodep); } - virtual void visit(AstCoverDecl* nodep) VL_OVERRIDE { + virtual void visit(AstCoverDecl* nodep) override { // Fix path in coverage statements nodep->hier(VString::dot(m_cellp->prettyName(), ".", nodep->hier())); iterateChildren(nodep); } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - InlineRelinkVisitor(AstNodeModule* cloneModp, AstNodeModule* oldModp, AstCell* cellp) { - m_modp = oldModp; - m_cellp = cellp; + InlineRelinkVisitor(AstNodeModule* cloneModp, AstNodeModule* oldModp, AstCell* cellp) + : m_modp{oldModp} + , m_cellp{cellp} { iterate(cloneModp); } - virtual ~InlineRelinkVisitor() {} + virtual ~InlineRelinkVisitor() override {} }; //###################################################################### @@ -501,34 +498,33 @@ private: AstUser5InUse m_inuser5; // STATE - AstNodeModule* m_modp; // Current module + AstNodeModule* m_modp = nullptr; // Current module VDouble0 m_statCells; // Statistic tracking // METHODS VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { // Iterate modules backwards, in bottom-up order. Required! iterateChildrenBackwards(nodep); } - virtual void visit(AstIfaceRefDType* nodep) VL_OVERRIDE { + virtual void visit(AstIfaceRefDType* nodep) override { if (nodep->user5()) { // The cell has been removed so let's make sure we don't leave a reference to it // This dtype may still be in use by the AstAssignVarScope created earlier // but that'll get cleared up later - nodep->cellp(NULL); + nodep->cellp(nullptr); } } - 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(AstCell* nodep) VL_OVERRIDE { + virtual void visit(AstCell* nodep) override { if (nodep->modp()->user1()) { // Marked with inline request UINFO(5, " Inline CELL " << nodep << endl); UINFO(5, " To MOD " << m_modp << endl); @@ -608,17 +604,14 @@ private: } //-------------------- - virtual void visit(AstNodeMath*) VL_OVERRIDE {} // Accelerate - virtual void visit(AstNodeStmt*) VL_OVERRIDE {} // Accelerate - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNodeMath*) override {} // Accelerate + virtual void visit(AstNodeStmt*) override {} // Accelerate + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - explicit InlineVisitor(AstNode* nodep) { - m_modp = NULL; - iterate(nodep); - } - virtual ~InlineVisitor() { // + explicit InlineVisitor(AstNode* nodep) { iterate(nodep); } + virtual ~InlineVisitor() override { // V3Stats::addStat("Optimizations, Inlined cells", m_statCells); } }; @@ -639,12 +632,12 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { iterateChildren(nodep); } - virtual void visit(AstModule* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { iterateChildren(nodep); } + virtual void visit(AstModule* nodep) override { if (nodep->isTop()) { iterateChildren(nodep); } } - virtual void visit(AstCell* nodep) VL_OVERRIDE { - string oldScope = m_scope; + virtual void visit(AstCell* nodep) override { + VL_RESTORER(m_scope); if (m_scope.empty()) { m_scope = nodep->name(); } else { @@ -674,10 +667,8 @@ private: nodep->addIntfRefp(new AstIntfRef(nodep->fileline(), m_scope)); // No need to iterate on interface cells } - - m_scope = oldScope; } - virtual void visit(AstAssignVarScope* nodep) VL_OVERRIDE { + virtual void visit(AstAssignVarScope* nodep) override { // Reference AstVarRef* reflp = VN_CAST(nodep->lhsp(), VarRef); // What the reference refers to @@ -702,14 +693,14 @@ private: cellp->addIntfRefp(new AstIntfRef(varlp->fileline(), alias)); } //-------------------- - virtual void visit(AstNodeMath*) VL_OVERRIDE {} // Accelerate - virtual void visit(AstNodeStmt*) VL_OVERRIDE {} // Accelerate - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNodeMath*) override {} // Accelerate + virtual void visit(AstNodeStmt*) override {} // Accelerate + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit InlineIntfRefVisitor(AstNode* nodep) { iterate(nodep); } - virtual ~InlineIntfRefVisitor() {} + virtual ~InlineIntfRefVisitor() override {} }; //###################################################################### diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp index 1fb8467cb..7919c547f 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -42,21 +42,21 @@ private: AstUser1InUse m_inuser1; // STATE - AstCell* m_cellp; // Current cell + AstCell* m_cellp = nullptr; // Current cell // METHODS VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstCell* nodep) VL_OVERRIDE { + virtual void visit(AstCell* nodep) override { UINFO(4, " CELL " << nodep << endl); m_cellp = nodep; // VV***** We reset user1p() on each cell!!! AstNode::user1ClearTree(); iterateChildren(nodep); - m_cellp = NULL; + m_cellp = nullptr; } - virtual void visit(AstPin* nodep) VL_OVERRIDE { + virtual void visit(AstPin* nodep) override { // PIN(p,expr) -> ASSIGNW(VARXREF(p),expr) (if sub's input) // or ASSIGNW(expr,VARXREF(p)) (if sub's output) UINFO(4, " PIN " << nodep << endl); @@ -113,7 +113,7 @@ private: VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstUdpTable* nodep) VL_OVERRIDE { + virtual void visit(AstUdpTable* nodep) override { if (!v3Global.opt.bboxUnsup()) { // If we support primitives, update V3Undriven to remove special case nodep->v3warn(E_UNSUPPORTED, "Unsupported: Verilog 1995 UDP Tables. " @@ -122,21 +122,17 @@ private: } // Save some time - virtual void visit(AstNodeMath*) VL_OVERRIDE {} - virtual void visit(AstNodeAssign*) VL_OVERRIDE {} - virtual void visit(AstAlways*) VL_OVERRIDE {} + virtual void visit(AstNodeMath*) override {} + virtual void visit(AstNodeAssign*) override {} + virtual void visit(AstAlways*) override {} //-------------------- - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - explicit InstVisitor(AstNetlist* nodep) { - m_cellp = NULL; - // - iterate(nodep); - } - virtual ~InstVisitor() {} + explicit InstVisitor(AstNetlist* nodep) { iterate(nodep); } + virtual ~InstVisitor() override {} }; //###################################################################### @@ -151,15 +147,15 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { if (VN_IS(nodep->dtypep(), IfaceRefDType)) { UINFO(8, " dm-1-VAR " << nodep << endl); insert(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: // METHODS @@ -168,11 +164,11 @@ public: m_modVarNameMap.insert(make_pair(nodep->name(), nodep)); } AstVar* find(const string& name) { - VarNameMap::iterator it = m_modVarNameMap.find(name); + const auto it = m_modVarNameMap.find(name); if (it != m_modVarNameMap.end()) { return it->second; } else { - return NULL; + return nullptr; } } void dump() { @@ -190,7 +186,7 @@ public: m_modVarNameMap.clear(); iterate(nodep); } - virtual ~InstDeModVarVisitor() {} + virtual ~InstDeModVarVisitor() override {} }; //###################################################################### @@ -199,19 +195,20 @@ class InstDeVisitor : public AstNVisitor { // Find all cells with arrays, and convert to non-arrayed private: // STATE - AstRange* m_cellRangep; // Range for arrayed instantiations, NULL for normal instantiations - int m_instSelNum; // Current instantiation count 0..N-1 + AstRange* m_cellRangep + = nullptr; // Range for arrayed instantiations, nullptr for normal instantiations + int m_instSelNum = 0; // Current instantiation count 0..N-1 InstDeModVarVisitor m_deModVars; // State of variables for current cell module VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { if (VN_IS(nodep->dtypep(), UnpackArrayDType) && VN_IS(VN_CAST(nodep->dtypep(), UnpackArrayDType)->subDTypep(), IfaceRefDType)) { UINFO(8, " dv-vec-VAR " << nodep << endl); AstUnpackArrayDType* arrdtype = VN_CAST(nodep->dtypep(), UnpackArrayDType); - AstNode* prevp = NULL; + AstNode* prevp = nullptr; for (int i = arrdtype->lsb(); i <= arrdtype->msb(); ++i) { string varNewName = nodep->name() + "__BRA__" + cvtToStr(i) + "__KET__"; UINFO(8, "VAR name insert " << varNewName << " " << nodep << endl); @@ -219,7 +216,7 @@ private: AstIfaceRefDType* ifaceRefp = VN_CAST(arrdtype->subDTypep(), IfaceRefDType)->cloneTree(false); arrdtype->addNextHere(ifaceRefp); - ifaceRefp->cellp(NULL); + ifaceRefp->cellp(nullptr); AstVar* varNewp = nodep->cloneTree(false); varNewp->name(varNewName); @@ -242,7 +239,7 @@ private: iterateChildren(nodep); } - virtual void visit(AstCell* nodep) VL_OVERRIDE { + virtual void visit(AstCell* nodep) override { UINFO(4, " CELL " << nodep << endl); // Find submodule vars UASSERT_OBJ(nodep->modp(), nodep, "Unlinked"); @@ -279,7 +276,7 @@ private: AstUnpackArrayDType* arrdtype = VN_CAST(ifaceVarp->dtypep(), UnpackArrayDType); AstIfaceRefDType* origIfaceRefp = VN_CAST(arrdtype->subDTypep(), IfaceRefDType); - origIfaceRefp->cellp(NULL); + origIfaceRefp->cellp(nullptr); AstVar* varNewp = ifaceVarp->cloneTree(false); AstIfaceRefDType* ifaceRefp = VN_CAST(arrdtype->subDTypep(), IfaceRefDType)->cloneTree(false); @@ -305,7 +302,7 @@ private: } // Done. Delete original - m_cellRangep = NULL; + m_cellRangep = nullptr; if (isIface) { ifaceVarp->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(ifaceVarp), ifaceVarp); @@ -313,12 +310,12 @@ private: nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); } else { - m_cellRangep = NULL; + m_cellRangep = nullptr; iterateChildren(nodep); } } - virtual void visit(AstPin* nodep) VL_OVERRIDE { + virtual void visit(AstPin* nodep) override { // Any non-direct pins need reconnection with a part-select if (!nodep->exprp()) return; // No-connect if (m_cellRangep) { @@ -394,20 +391,20 @@ private: AstUnpackArrayDType* pinArrp = VN_CAST(pinVarp->dtypep(), UnpackArrayDType); if (!pinArrp || !VN_IS(pinArrp->subDTypep(), IfaceRefDType)) return; // Arrayed pin/var attaches to arrayed submodule lower port/var, expand it - AstNode* prevp = NULL; - AstNode* prevPinp = NULL; + AstNode* prevp = nullptr; + AstNode* prevPinp = nullptr; // Clone the var referenced by the pin, and clone each var referenced by the varref // Clone pin varp: for (int i = pinArrp->lsb(); i <= pinArrp->msb(); ++i) { string varNewName = pinVarp->name() + "__BRA__" + cvtToStr(i) + "__KET__"; - AstVar* varNewp = NULL; + AstVar* varNewp = nullptr; // Only clone the var once for all usages of a given child module if (!pinVarp->backp()) { varNewp = m_deModVars.find(varNewName); } else { AstIfaceRefDType* ifaceRefp = VN_CAST(pinArrp->subDTypep(), IfaceRefDType); - ifaceRefp->cellp(NULL); + ifaceRefp->cellp(nullptr); varNewp = pinVarp->cloneTree(false); varNewp->name(varNewName); varNewp->origName(varNewp->origName() + "__BRA__" + cvtToStr(i) + "__KET__"); @@ -461,18 +458,13 @@ private: } //-------------------- - 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 InstDeVisitor(AstNetlist* nodep) { - m_cellRangep = NULL; - m_instSelNum = 0; - // - iterate(nodep); - } - virtual ~InstDeVisitor() {} + explicit InstDeVisitor(AstNetlist* nodep) { iterate(nodep); } + virtual ~InstDeVisitor() override {} }; //###################################################################### @@ -516,14 +508,14 @@ public: && cellp->modp()->unconnectedDrive().isSetFalse()) { pinp->exprp(new AstConst(pinp->fileline(), AstConst::StringToParse(), "'0")); } else { - return NULL; + return nullptr; } } AstVarRef* connectRefp = VN_CAST(pinp->exprp(), VarRef); AstVarXRef* connectXRefp = VN_CAST(pinp->exprp(), VarXRef); - AstBasicDType* pinBasicp = VN_CAST(pinVarp->dtypep(), BasicDType); // Maybe NULL - AstBasicDType* connBasicp = NULL; - AstAssignW* assignp = NULL; + AstBasicDType* pinBasicp = VN_CAST(pinVarp->dtypep(), BasicDType); // Maybe nullptr + AstBasicDType* connBasicp = nullptr; + AstAssignW* assignp = nullptr; if (connectRefp) connBasicp = VN_CAST(connectRefp->varp()->dtypep(), BasicDType); // if (!alwaysCvt && connectRefp && connectRefp->varp()->dtypep()->sameTree(pinVarp->dtypep()) diff --git a/src/V3InstrCount.cpp b/src/V3InstrCount.cpp index 972c791fd..f01b10608 100644 --- a/src/V3InstrCount.cpp +++ b/src/V3InstrCount.cpp @@ -37,10 +37,10 @@ private: AstUser4InUse m_inuser4; // MEMBERS - uint32_t m_instrCount; // Running count of instructions + uint32_t m_instrCount = 0; // Running count of instructions const AstNode* m_startNodep; // Start node of count - bool m_tracingCall; // Iterating into a CCall to a CFunc - bool m_inCFunc; // Inside AstCFunc + bool m_tracingCall = false; // Iterating into a CCall to a CFunc + bool m_inCFunc = false; // Inside AstCFunc bool m_assertNoDups; // Check for duplicates std::ostream* m_osp; // Dump file @@ -56,8 +56,8 @@ private: public: // CONSTRUCTORS VisitBase(InstrCountVisitor* visitor, AstNode* nodep) - : m_nodep(nodep) - , m_visitor(visitor) { + : m_nodep{nodep} + , m_visitor{visitor} { m_savedCount = m_visitor->startVisitBase(nodep); } ~VisitBase() { m_visitor->endVisitBase(m_savedCount, m_nodep); } @@ -69,15 +69,12 @@ private: public: // CONSTRUCTORS InstrCountVisitor(AstNode* nodep, bool assertNoDups, std::ostream* osp) - : m_instrCount(0) - , m_startNodep(nodep) - , m_tracingCall(false) - , m_inCFunc(false) - , m_assertNoDups(assertNoDups) - , m_osp(osp) { + : m_startNodep{nodep} + , m_assertNoDups{assertNoDups} + , m_osp{osp} { if (nodep) iterate(nodep); } - virtual ~InstrCountVisitor() {} + virtual ~InstrCountVisitor() override {} // METHODS uint32_t instrCount() const { return m_instrCount; } @@ -119,7 +116,7 @@ private: } // VISITORS - virtual void visit(AstNodeSel* nodep) VL_OVERRIDE { + virtual void visit(AstNodeSel* nodep) override { // This covers both AstArraySel and AstWordSel // // If some vector is a bazillion dwords long, and we're selecting 1 @@ -130,7 +127,7 @@ private: VisitBase vb(this, nodep); iterateAndNextNull(nodep->bitp()); } - virtual void visit(AstSel* nodep) VL_OVERRIDE { + virtual void visit(AstSel* nodep) override { // Similar to AstNodeSel above, a small select into a large vector // is not expensive. Count the cost of the AstSel itself (scales with // its width) and the cost of the lsbp() and widthp() nodes, but not @@ -139,13 +136,13 @@ private: iterateAndNextNull(nodep->lsbp()); iterateAndNextNull(nodep->widthp()); } - virtual void visit(AstSliceSel* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE + virtual void visit(AstSliceSel* nodep) override { // LCOV_EXCL_LINE nodep->v3fatalSrc("AstSliceSel unhandled"); } - virtual void visit(AstMemberSel* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE + virtual void visit(AstMemberSel* nodep) override { // LCOV_EXCL_LINE nodep->v3fatalSrc("AstMemberSel unhandled"); } - virtual void visit(AstConcat* nodep) VL_OVERRIDE { + virtual void visit(AstConcat* nodep) override { // Nop. // // Ignore concat. The problem with counting concat is that when we @@ -165,7 +162,7 @@ private: // the widths of the operands (ignored here). markCost(nodep); } - virtual void visit(AstNodeIf* nodep) VL_OVERRIDE { + virtual void visit(AstNodeIf* nodep) override { VisitBase vb(this, nodep); iterateAndNextNull(nodep->condp()); uint32_t savedCount = m_instrCount; @@ -190,7 +187,7 @@ private: if (nodep->ifsp()) nodep->ifsp()->user4(0); // Don't dump it } } - virtual void visit(AstNodeCond* nodep) VL_OVERRIDE { + virtual void visit(AstNodeCond* nodep) override { // Just like if/else above, the ternary operator only evaluates // one of the two expressions, so only count the max. VisitBase vb(this, nodep); @@ -215,7 +212,7 @@ private: if (nodep->expr2p()) nodep->expr2p()->user4(0); // Don't dump it } } - virtual void visit(AstActive* nodep) VL_OVERRIDE { + virtual void visit(AstActive* nodep) override { // You'd think that the OrderLogicVertex's would be disjoint trees // of stuff in the AST, but it isn't so: V3Order makes an // OrderLogicVertex for each ACTIVE, and then also makes an @@ -231,14 +228,14 @@ private: markCost(nodep); UASSERT_OBJ(nodep == m_startNodep, nodep, "Multiple actives, or not start node"); } - virtual void visit(AstNodeCCall* nodep) VL_OVERRIDE { + virtual void visit(AstNodeCCall* nodep) override { VisitBase vb(this, nodep); iterateChildren(nodep); m_tracingCall = true; iterate(nodep->funcp()); UASSERT_OBJ(!m_tracingCall, nodep, "visit(AstCFunc) should have cleared m_tracingCall."); } - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstCFunc* nodep) override { // Don't count a CFunc other than by tracing a call or counting it // from the root UASSERT_OBJ(m_tracingCall || nodep == m_startNodep, nodep, @@ -252,7 +249,7 @@ private: } m_inCFunc = saved_inCFunc; } - virtual void visit(AstNode* nodep) VL_OVERRIDE { + virtual void visit(AstNode* nodep) override { VisitBase vb(this, nodep); iterateChildren(nodep); } @@ -269,23 +266,22 @@ private: // MEMBERS std::ostream* m_osp; // Dump file - unsigned m_depth; // Current tree depth for printing indent + unsigned m_depth = 0; // Current tree depth for printing indent public: // CONSTRUCTORS InstrCountDumpVisitor(AstNode* nodep, std::ostream* osp) - : m_osp(osp) - , m_depth(0) { - // No check for NULL output, so... + : m_osp{osp} { + // No check for nullptr output, so... UASSERT_OBJ(osp, nodep, "Don't call if not dumping"); if (nodep) iterate(nodep); } - virtual ~InstrCountDumpVisitor() {} + virtual ~InstrCountDumpVisitor() override {} private: // METHODS - string indent() { return string(m_depth, ':') + " "; } - virtual void visit(AstNode* nodep) VL_OVERRIDE { + string indent() const { return string(m_depth, ':') + " "; } + virtual void visit(AstNode* nodep) override { ++m_depth; if (unsigned costPlus1 = nodep->user4()) { *m_osp << " " << indent() << "cost " << std::setw(6) << std::left << (costPlus1 - 1) diff --git a/src/V3InstrCount.h b/src/V3InstrCount.h index 8f3bcf1b8..697a69cb6 100644 --- a/src/V3InstrCount.h +++ b/src/V3InstrCount.h @@ -38,7 +38,7 @@ public: // if we see the same node twice (across more than one call to count, // potentially) raises an error. // Optional osp is stream to dump critical path to. - static uint32_t count(AstNode* nodep, bool assertNoDups, std::ostream* osp = NULL); + static uint32_t count(AstNode* nodep, bool assertNoDups, std::ostream* osp = nullptr); }; #endif // guard diff --git a/src/V3LangCode.h b/src/V3LangCode.h index 9e59cf787..e9eb7ae4e 100644 --- a/src/V3LangCode.h +++ b/src/V3LangCode.h @@ -30,7 +30,7 @@ //! file). class V3LangCode { public: - enum en { + enum en : uint8_t { L_ERROR, // Must be first. L1364_1995, L1364_2001, @@ -56,13 +56,13 @@ public: // enum en m_e; inline V3LangCode() - : m_e(L_ERROR) {} + : m_e{L_ERROR} {} // cppcheck-suppress noExplicitConstructor inline V3LangCode(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit V3LangCode(const char* textp); explicit inline V3LangCode(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } }; diff --git a/src/V3LanguageWords.h b/src/V3LanguageWords.h index ecccfe693..a11a6a222 100644 --- a/src/V3LanguageWords.h +++ b/src/V3LanguageWords.h @@ -41,7 +41,7 @@ public: static const_iterator begin() { return s().s_kwdMap.begin(); } static const_iterator end() { return s().s_kwdMap.end(); } static string isKeyword(const string& kwd) { - KeywordMap::const_iterator it = s().s_kwdMap.find(kwd); + const auto it = vlstd::as_const(s().s_kwdMap).find(kwd); if (it == s().s_kwdMap.end()) return ""; return it->second; } @@ -56,7 +56,7 @@ private: inline void V3LanguageWords::Singleton::init() { // C++ keywords // clang-format off - addKwd("NULL", "C++ common word"); + addKwd("nullptr", "C++ common word"); addKwd("abort", "C++ common word"); addKwd("alignas", "C++11 keyword"); addKwd("alignof", "C++11 keyword"); diff --git a/src/V3Life.cpp b/src/V3Life.cpp index 1462ee4c4..dff42a07e 100644 --- a/src/V3Life.cpp +++ b/src/V3Life.cpp @@ -55,10 +55,9 @@ public: ~LifeState() { V3Stats::addStatSum("Optimizations, Lifetime assign deletions", m_statAssnDel); V3Stats::addStatSum("Optimizations, Lifetime constant prop", m_statAssnCon); - for (std::vector::iterator it = m_unlinkps.begin(); it != m_unlinkps.end(); - ++it) { - (*it)->unlinkFrBack(); - (*it)->deleteTree(); + for (AstNode* ip : m_unlinkps) { + ip->unlinkFrBack(); + ip->deleteTree(); } } // METHODS @@ -69,7 +68,7 @@ public: // Structure for each variable encountered class LifeVarEntry { - AstNodeAssign* m_assignp; // Last assignment to this varscope, NULL if no longer relevant + AstNodeAssign* m_assignp; // Last assignment to this varscope, nullptr if no longer relevant AstConst* m_constp; // Known constant value // First access was a set (and thus block above may have a set that can be deleted bool m_setBeforeUse; @@ -77,8 +76,8 @@ class LifeVarEntry { bool m_everSet; inline void init(bool setBeforeUse) { - m_assignp = NULL; - m_constp = NULL; + m_assignp = nullptr; + m_constp = nullptr; m_setBeforeUse = setBeforeUse; m_everSet = false; } @@ -103,17 +102,17 @@ public: ~LifeVarEntry() {} inline void simpleAssign(AstNodeAssign* assp) { // New simple A=.... assignment m_assignp = assp; - m_constp = NULL; + m_constp = nullptr; m_everSet = true; if (VN_IS(assp->rhsp(), Const)) m_constp = VN_CAST(assp->rhsp(), Const); } inline void complexAssign() { // A[x]=... or some complicated assignment - m_assignp = NULL; - m_constp = NULL; + m_assignp = nullptr; + m_constp = nullptr; m_everSet = true; } inline void consumed() { // Rvalue read of A - m_assignp = NULL; + m_assignp = nullptr; } AstNodeAssign* assignp() const { return m_assignp; } AstConst* constNodep() const { return m_constp; } @@ -133,7 +132,7 @@ class LifeBlock { // For each basic block, we'll make a new map of what variables that if/else is changing typedef std::map LifeMap; LifeMap m_map; // Current active lifetime map for current scope - LifeBlock* m_aboveLifep; // Upper life, or NULL + LifeBlock* m_aboveLifep; // Upper life, or nullptr LifeState* m_statep; // Current global state VL_DEBUG_FUNC; // Declare debug() @@ -168,7 +167,7 @@ public: // Do we have a old assignment we can nuke? UINFO(4, " ASSIGNof: " << nodep << endl); UINFO(7, " new: " << assp << endl); - LifeMap::iterator it = m_map.find(nodep); + const auto it = m_map.find(nodep); if (it != m_map.end()) { checkRemoveAssign(it); it->second.simpleAssign(assp); @@ -179,7 +178,7 @@ public: } void complexAssign(AstVarScope* nodep) { UINFO(4, " clearof: " << nodep << endl); - LifeMap::iterator it = m_map.find(nodep); + const auto it = m_map.find(nodep); if (it != m_map.end()) { it->second.complexAssign(); } else { @@ -188,7 +187,7 @@ public: } void varUsageReplace(AstVarScope* nodep, AstVarRef* varrefp) { // Variable rvalue. If it references a constant, we can simply replace it - LifeMap::iterator it = m_map.find(nodep); + const auto it = m_map.find(nodep); if (it != m_map.end()) { if (AstConst* constp = it->second.constNodep()) { if (!varrefp->varp()->isSigPublic()) { @@ -208,7 +207,7 @@ public: } } void complexAssignFind(AstVarScope* nodep) { - LifeMap::iterator it = m_map.find(nodep); + const auto it = m_map.find(nodep); if (it != m_map.end()) { UINFO(4, " casfind: " << it->first << endl); it->second.complexAssign(); @@ -217,7 +216,7 @@ public: } } void consumedFind(AstVarScope* nodep) { - LifeMap::iterator it = m_map.find(nodep); + const auto it = m_map.find(nodep); if (it != m_map.end()) { it->second.consumed(); } else { @@ -254,7 +253,7 @@ public: if (it->second.setBeforeUse() && nodep->user1()) { // Both branches set the var, we can remove the assignment before the IF. UINFO(4, "DUALBRANCH " << nodep << endl); - LifeMap::iterator itab = m_map.find(nodep); + const auto itab = m_map.find(nodep); if (itab != m_map.end()) checkRemoveAssign(itab); } } @@ -280,9 +279,9 @@ class LifeVisitor : public AstNVisitor { private: // STATE LifeState* m_statep; // Current state - bool m_sideEffect; // Side effects discovered in assign RHS - bool m_noopt; // Disable optimization of variables in this block - bool m_tracingCall; // Iterating into a CCall to a CFunc + bool m_sideEffect = false; // Side effects discovered in assign RHS + bool m_noopt = false; // Disable optimization of variables in this block + bool m_tracingCall = false; // Iterating into a CCall to a CFunc // LIFE MAP // For each basic block, we'll make a new map of what variables that if/else is changing @@ -294,10 +293,10 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { // Consumption/generation of a variable, // it's used so can't elim assignment before this use. - UASSERT_OBJ(nodep->varScopep(), nodep, "NULL"); + UASSERT_OBJ(nodep->varScopep(), nodep, "nullptr"); // AstVarScope* vscp = nodep->varScopep(); UASSERT_OBJ(vscp, nodep, "Scope not assigned"); @@ -308,7 +307,7 @@ private: VL_DO_DANGLING(m_lifep->varUsageReplace(vscp, nodep), nodep); } } - virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { + virtual void visit(AstNodeAssign* nodep) override { // Collect any used variables first, as lhs may also be on rhs // Similar code in V3Dead vluint64_t lastEdit = AstNode::editCountGbl(); // When it was last edited @@ -328,13 +327,13 @@ private: iterateAndNextNull(nodep->lhsp()); } } - virtual void visit(AstAssignDly* nodep) VL_OVERRIDE { + virtual void visit(AstAssignDly* nodep) override { // Don't treat as normal assign; V3Life doesn't understand time sense iterateChildren(nodep); } //---- Track control flow changes - virtual void visit(AstNodeIf* nodep) VL_OVERRIDE { + virtual void visit(AstNodeIf* nodep) override { UINFO(4, " IF " << nodep << endl); // Condition is part of PREVIOUS block iterateAndNextNull(nodep->condp()); @@ -360,7 +359,7 @@ private: VL_DO_DANGLING(delete elseLifep, elseLifep); } - virtual void visit(AstWhile* nodep) VL_OVERRIDE { + virtual void visit(AstWhile* nodep) override { // While's are a problem, as we don't allow loops in the graph. We // may go around the cond/body multiple times. Thus a // lifelication just in the body is ok, but we can't delete an @@ -389,7 +388,7 @@ private: VL_DO_DANGLING(delete condLifep, condLifep); VL_DO_DANGLING(delete bodyLifep, bodyLifep); } - virtual void visit(AstJumpBlock* nodep) VL_OVERRIDE { + virtual void visit(AstJumpBlock* nodep) override { // As with While's we can't predict if a JumpGo will kill us or not // It's worse though as an IF(..., JUMPGO) may change the control flow. // Just don't optimize blocks with labels; they're rare - so far. @@ -408,7 +407,7 @@ private: bodyLifep->lifeToAbove(); VL_DO_DANGLING(delete bodyLifep, bodyLifep); } - virtual void visit(AstNodeCCall* nodep) VL_OVERRIDE { + virtual void visit(AstNodeCCall* nodep) override { // UINFO(4, " CCALL " << nodep << endl); iterateChildren(nodep); // Enter the function and trace it @@ -418,7 +417,7 @@ private: iterate(nodep->funcp()); } } - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstCFunc* nodep) override { // UINFO(4, " CFUNC " << nodep << endl); if (!m_tracingCall && !nodep->entryPoint()) return; m_tracingCall = false; @@ -427,34 +426,31 @@ private: } iterateChildren(nodep); } - virtual void visit(AstUCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstUCFunc* nodep) override { m_sideEffect = true; // If appears on assign RHS, don't ever delete the assignment iterateChildren(nodep); } - virtual void visit(AstCMath* nodep) VL_OVERRIDE { + virtual void visit(AstCMath* nodep) override { m_sideEffect = true; // If appears on assign RHS, don't ever delete the assignment 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 LifeVisitor(AstNode* nodep, LifeState* statep) { UINFO(4, " LifeVisitor on " << nodep << endl); m_statep = statep; - m_sideEffect = false; - m_noopt = false; - m_tracingCall = false; { - m_lifep = new LifeBlock(NULL, m_statep); + m_lifep = new LifeBlock(nullptr, m_statep); iterate(nodep); - if (m_lifep) VL_DO_CLEAR(delete m_lifep, m_lifep = NULL); + if (m_lifep) VL_DO_CLEAR(delete m_lifep, m_lifep = nullptr); } } - virtual ~LifeVisitor() { - if (m_lifep) VL_DO_CLEAR(delete m_lifep, m_lifep = NULL); + virtual ~LifeVisitor() override { + if (m_lifep) VL_DO_CLEAR(delete m_lifep, m_lifep = nullptr); } VL_UNCOPYABLE(LifeVisitor); }; @@ -469,28 +465,28 @@ private: LifeState* m_statep; // Current state // VISITORS - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstCFunc* nodep) override { if (nodep->entryPoint()) { // Usage model 1: Simulate all C code, doing lifetime analysis LifeVisitor visitor(nodep, m_statep); } } - virtual void visit(AstNodeProcedure* nodep) VL_OVERRIDE { + virtual void visit(AstNodeProcedure* nodep) override { // Usage model 2: Cleanup basic blocks LifeVisitor visitor(nodep, m_statep); } - virtual void visit(AstVar*) VL_OVERRIDE {} // Accelerate - virtual void visit(AstNodeStmt*) VL_OVERRIDE {} // Accelerate - virtual void visit(AstNodeMath*) VL_OVERRIDE {} // Accelerate - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstVar*) override {} // Accelerate + virtual void visit(AstNodeStmt*) override {} // Accelerate + virtual void visit(AstNodeMath*) override {} // Accelerate + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - LifeTopVisitor(AstNetlist* nodep, LifeState* statep) { - m_statep = statep; + LifeTopVisitor(AstNetlist* nodep, LifeState* statep) + : m_statep{statep} { iterate(nodep); } - virtual ~LifeTopVisitor() {} + virtual ~LifeTopVisitor() override {} }; //###################################################################### diff --git a/src/V3LifePost.cpp b/src/V3LifePost.cpp index 80c72f749..65ee17693 100644 --- a/src/V3LifePost.cpp +++ b/src/V3LifePost.cpp @@ -34,15 +34,15 @@ #include "V3Stats.h" #include "V3Ast.h" -#include // for vl_unique_ptr -> auto_ptr or unique_ptr -#include VL_INCLUDE_UNORDERED_MAP +#include // for std::unique_ptr -> auto_ptr or unique_ptr +#include //###################################################################### // LifePost class functions class LifePostElimVisitor : public AstNVisitor { private: - bool m_tracingCall; // Iterating into a CCall to a CFunc + bool m_tracingCall = false; // Iterating into a CCall to a CFunc // NODE STATE // INPUT: @@ -53,7 +53,7 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { AstVarScope* vscp = nodep->varScopep(); UASSERT_OBJ(vscp, nodep, "Scope not assigned"); if (AstVarScope* newvscp = reinterpret_cast(vscp->user4p())) { @@ -63,11 +63,11 @@ private: VL_DO_DANGLING(nodep->deleteTree(), nodep); } } - 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()) 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 @@ -75,26 +75,23 @@ private: iterate(nodep->funcp()); } } - virtual void visit(AstExecGraph* nodep) VL_OVERRIDE { + virtual void visit(AstExecGraph* nodep) override { // Can just iterate across the MTask bodies in any order. Order // isn't important for LifePostElimVisitor's simple substitution. iterateChildren(nodep); } - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstCFunc* nodep) override { if (!m_tracingCall && !nodep->entryPoint()) return; m_tracingCall = false; 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 LifePostElimVisitor(AstTopScope* nodep) - : m_tracingCall(false) { - iterate(nodep); - } - virtual ~LifePostElimVisitor() {} + explicit LifePostElimVisitor(AstTopScope* nodep) { iterate(nodep); } + virtual ~LifePostElimVisitor() override {} }; //###################################################################### @@ -107,11 +104,11 @@ struct LifeLocation { public: LifeLocation() - : mtaskp(NULL) - , sequence(0) {} + : mtaskp{nullptr} + , sequence{0} {} LifeLocation(const ExecMTask* mtaskp_, uint32_t sequence_) - : mtaskp(mtaskp_) - , sequence(sequence_) {} + : mtaskp{mtaskp_} + , sequence{sequence_} {} bool operator<(const LifeLocation& b) const { unsigned a_id = mtaskp ? mtaskp->id() : 0; unsigned b_id = b.mtaskp ? b.mtaskp->id() : 0; @@ -125,10 +122,10 @@ struct LifePostLocation { LifeLocation loc; AstAssignPost* nodep; LifePostLocation() - : nodep(NULL) {} + : nodep{nullptr} {} LifePostLocation(LifeLocation loc_, AstAssignPost* nodep_) - : loc(loc_) - , nodep(nodep_) {} + : loc{loc_} + , nodep{nodep_} {} }; //###################################################################### @@ -142,25 +139,25 @@ private: AstUser4InUse m_inuser4; // STATE - uint32_t m_sequence; // Sequence number of assigns/varrefs, + uint32_t m_sequence = 0; // Sequence number of assigns/varrefs, // // local to the current MTask. - const ExecMTask* m_execMTaskp; // Current ExecMTask being processed, - // // or NULL for serial code. + const ExecMTask* m_execMTaskp = nullptr; // Current ExecMTask being processed, + // // or nullptr for serial code. VDouble0 m_statAssnDel; // Statistic tracking - bool m_tracingCall; // Currently tracing a CCall to a CFunc + bool m_tracingCall = false; // Currently tracing a CCall to a CFunc // Map each varscope to one or more locations where it's accessed. // These maps will not include any ASSIGNPOST accesses: - typedef vl_unordered_map > LocMap; + typedef std::unordered_map> LocMap; LocMap m_reads; // VarScope read locations LocMap m_writes; // VarScope write locations // Map each dly var to its AstAssignPost* node and the location thereof - typedef vl_unordered_map PostLocMap; + typedef std::unordered_map PostLocMap; PostLocMap m_assignposts; // AssignPost dly var locations - const V3Graph* m_mtasksGraphp; // Mtask tracking graph - vl_unique_ptr m_checker; + const V3Graph* m_mtasksGraphp = nullptr; // Mtask tracking graph + std::unique_ptr m_checker; // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -257,7 +254,7 @@ private: } // VISITORS - virtual void visit(AstTopScope* nodep) VL_OVERRIDE { + virtual void visit(AstTopScope* nodep) override { AstNode::user4ClearTree(); // user4p() used on entire tree // First, build maps of every location (mtask and sequence @@ -281,7 +278,7 @@ private: // Replace any node4p varscopes with the new scope LifePostElimVisitor visitor(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"); @@ -293,14 +290,14 @@ private: m_reads[vscp].insert(loc); } } - virtual void visit(AstAssignPre* nodep) VL_OVERRIDE { + virtual void visit(AstAssignPre* nodep) override { // Do not record varrefs within assign pre. // // The pre-assignment into the dly var should not count as its // first write; we only want to consider reads and writes that // would still happen if the dly var were eliminated. } - virtual void visit(AstAssignPost* nodep) VL_OVERRIDE { + virtual void visit(AstAssignPost* nodep) override { // Don't record ASSIGNPOST in the read/write maps, record them in a // separate map if (AstVarRef* rhsp = VN_CAST(nodep->rhsp(), VarRef)) { @@ -312,11 +309,11 @@ private: m_assignposts[dlyVarp] = LifePostLocation(loc, nodep); } } - 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()) 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 @@ -324,7 +321,7 @@ private: iterate(nodep->funcp()); } } - virtual void visit(AstExecGraph* nodep) VL_OVERRIDE { + virtual void visit(AstExecGraph* nodep) override { // Treat the ExecGraph like a call to each mtask body m_mtasksGraphp = nodep->depGraphp(); for (V3GraphVertex* mtaskVxp = m_mtasksGraphp->verticesBeginp(); mtaskVxp; @@ -334,27 +331,21 @@ private: m_sequence = 0; iterate(mtaskp->bodyp()); } - m_execMTaskp = NULL; + m_execMTaskp = nullptr; } - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstCFunc* nodep) override { if (!m_tracingCall && !nodep->entryPoint()) return; m_tracingCall = false; 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 LifePostDlyVisitor(AstNetlist* nodep) - : m_sequence(0) - , m_execMTaskp(NULL) - , m_tracingCall(false) - , m_mtasksGraphp(NULL) { - iterate(nodep); - } - virtual ~LifePostDlyVisitor() { + explicit LifePostDlyVisitor(AstNetlist* nodep) { iterate(nodep); } + virtual ~LifePostDlyVisitor() override { V3Stats::addStat("Optimizations, Lifetime postassign deletions", m_statAssnDel); } }; diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp index bb6f1110c..b97e1261b 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -36,7 +36,7 @@ #include #include #include -#include VL_INCLUDE_UNORDERED_SET +#include //###################################################################### // Graph subclasses @@ -44,8 +44,8 @@ class LinkCellsGraph : public V3Graph { public: LinkCellsGraph() {} - virtual ~LinkCellsGraph() {} - virtual void loopsMessageCb(V3GraphVertex* vertexp); + virtual ~LinkCellsGraph() override {} + virtual void loopsMessageCb(V3GraphVertex* vertexp) override; }; class LinkCellsVertex : public V3GraphVertex { @@ -53,14 +53,14 @@ class LinkCellsVertex : public V3GraphVertex { public: LinkCellsVertex(V3Graph* graphp, AstNodeModule* modp) - : V3GraphVertex(graphp) - , m_modp(modp) {} - virtual ~LinkCellsVertex() {} + : V3GraphVertex{graphp} + , m_modp{modp} {} + virtual ~LinkCellsVertex() override {} AstNodeModule* modp() const { return m_modp; } - virtual string name() const { return modp()->name(); } - virtual FileLine* fileline() const { return modp()->fileline(); } + virtual string name() const override { return modp()->name(); } + virtual FileLine* fileline() const override { return modp()->fileline(); } // Recursive modules get space for maximum recursion - virtual uint32_t rankAdder() const { + virtual uint32_t rankAdder() const override { return m_modp->recursiveClone() ? (1 + v3Global.opt.moduleRecursionDepth()) : 1; } }; @@ -68,9 +68,9 @@ public: class LibraryVertex : public V3GraphVertex { public: explicit LibraryVertex(V3Graph* graphp) - : V3GraphVertex(graphp) {} - virtual ~LibraryVertex() {} - virtual string name() const { return "*LIBRARY*"; } + : V3GraphVertex{graphp} {} + virtual ~LibraryVertex() override {} + virtual string name() const override { return "*LIBRARY*"; } }; void LinkCellsGraph::loopsMessageCb(V3GraphVertex* vertexp) { @@ -109,12 +109,13 @@ private: V3ParseSym* m_parseSymp; // Parser symbol table // Below state needs to be preserved between each module call. - AstNodeModule* m_modp; // Current module + AstNodeModule* m_modp = nullptr; // Current module VSymGraph m_mods; // Symbol table of all module names LinkCellsGraph m_graph; // Linked graph of all cell interconnects - LibraryVertex* m_libVertexp; // Vertex at root of all libraries - V3GraphVertex* m_topVertexp; // Vertex of top module - vl_unordered_set m_declfnWarned; // Files we issued DECLFILENAME on + LibraryVertex* m_libVertexp = nullptr; // Vertex at root of all libraries + V3GraphVertex* m_topVertexp = nullptr; // Vertex of top module + std::unordered_set m_declfnWarned; // Files we issued DECLFILENAME on + string m_origTopModuleName; // original name of the top module VL_DEBUG_FUNC; // Declare debug() @@ -128,7 +129,7 @@ private: AstNodeModule* findModuleSym(const string& modName) { VSymEnt* foundp = m_mods.rootp()->findIdFallback(modName); if (!foundp) { - return NULL; + return nullptr; } else { return VN_CAST(foundp->nodep(), NodeModule); } @@ -159,7 +160,7 @@ private: } // VISITs - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { AstNode::user1ClearTree(); readModNames(); iterateChildren(nodep); @@ -173,7 +174,7 @@ private: AstNodeModule* modp = vvertexp->modp(); modp->level(vvertexp->rank() + 1); if (vvertexp == m_topVertexp && modp->level() != 2) { - AstNodeModule* abovep = NULL; + AstNodeModule* abovep = nullptr; if (V3GraphEdge* edgep = vvertexp->inBeginp()) { if (LinkCellsVertex* eFromVertexp = dynamic_cast(edgep->fromp())) { @@ -192,15 +193,16 @@ private: << "' was not found in design."); } } - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { + virtual void visit(AstNodeModule* nodep) override { // Module: Pick up modnames, so we can resolve cells later - AstNodeModule* oldModp = m_modp; + VL_RESTORER(m_modp); { m_modp = nodep; UINFO(2, "Link Module: " << nodep << endl); if (nodep->fileline()->filebasenameNoExt() != nodep->prettyName() && !v3Global.opt.isLibraryFile(nodep->fileline()->filename()) - && !nodep->recursiveClone() && !nodep->internal()) { + && !VN_IS(nodep, NotFoundModule) && !nodep->recursiveClone() + && !nodep->internal()) { // We only complain once per file, otherwise library-like files // have a huge mess of warnings if (m_declfnWarned.find(nodep->fileline()->filename()) == m_declfnWarned.end()) { @@ -231,10 +233,9 @@ private: iterateChildren(nodep); nodep->checkTree(); } - m_modp = oldModp; } - virtual void visit(AstIfaceRefDType* nodep) VL_OVERRIDE { + virtual void visit(AstIfaceRefDType* nodep) override { // Cell: Resolve its filename. If necessary, parse it. UINFO(4, "Link IfaceRef: " << nodep << endl); // Use findIdUpward instead of findIdFlat; it doesn't matter for now @@ -253,14 +254,14 @@ private: // Note cannot do modport resolution here; modports are allowed underneath generates } - virtual void visit(AstPackageImport* nodep) VL_OVERRIDE { + virtual void visit(AstPackageImport* nodep) override { // Package Import: We need to do the package before the use of a package iterateChildren(nodep); UASSERT_OBJ(nodep->packagep(), nodep, "Unlinked package"); // Parser should set packagep new V3GraphEdge(&m_graph, vertex(m_modp), vertex(nodep->packagep()), 1, false); } - virtual void visit(AstBind* nodep) VL_OVERRIDE { + virtual void visit(AstBind* nodep) override { // Bind: Has cells underneath that need to be put into the new // module, and cells which need resolution // TODO this doesn't allow bind to dotted hier names, that would require @@ -271,25 +272,34 @@ private: if (modp) { AstNode* cellsp = nodep->cellsp()->unlinkFrBackWithNext(); // Module may have already linked, so need to pick up these new cells - AstNodeModule* oldModp = m_modp; + VL_RESTORER(m_modp); { m_modp = modp; // Important that this adds to end, as next iterate assumes does all cells modp->addStmtp(cellsp); iterateAndNextNull(cellsp); } - m_modp = oldModp; } pushDeletep(nodep->unlinkFrBack()); } - virtual void visit(AstCell* nodep) VL_OVERRIDE { + virtual void visit(AstCell* nodep) override { // Cell: Resolve its filename. If necessary, parse it. // Execute only once. Complication is that cloning may result in // user1 being set (for pre-clone) so check if user1() matches the // m_mod, if 0 never did it, if !=, it is an unprocessed clone bool cloned = (nodep->user1p() && nodep->user1p() != m_modp); if (nodep->user1p() == m_modp) return; // AstBind and AstNodeModule may call a cell twice + if (v3Global.opt.hierChild() && nodep->modName() == m_origTopModuleName) { + if (nodep->modName() == m_modp->origName()) { + // Only the root of the recursive instantiation can be a hierarhcical block. + nodep->modName(m_modp->name()); + } else { + // In hierarchical mode, non-top module can be the top module of this run + VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); + return; + } + } nodep->user1p(m_modp); // if (!nodep->modp() || cloned) { @@ -314,7 +324,7 @@ private: if (!otherModp) { otherModp = cellmodp->cloneTree(false); otherModp->name(otherModp->name() + "__Vrcm"); - otherModp->user1p(NULL); // Need new vertex + otherModp->user1p(nullptr); // Need new vertex otherModp->user2p(cellmodp); otherModp->recursiveClone(true); // user1 etc will retain its pre-clone value @@ -338,7 +348,7 @@ private: } } } - // Remove AstCell(AstPin("",NULL)), it's a side effect of how we parse "()" + // Remove AstCell(AstPin("",nullptr)), it's a side effect of how we parse "()" // the empty middle is identical to the empty rule that must find pins in "(,)". if (nodep->pinsp() && !nodep->pinsp()->nextp() && nodep->pinsp()->name() == "" && !nodep->pinsp()->exprp()) { @@ -370,7 +380,7 @@ private: if (nodep->modp()) { nodep->modName(nodep->modp()->name()); // Note what pins exist - vl_unordered_set ports; // Symbol table of all connected port names + std::unordered_set ports; // Symbol table of all connected port names for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { if (pinp->name() == "") pinp->v3error("Connect by position is illegal in .* connected cells"); @@ -396,16 +406,17 @@ private: if (pinStar) { UINFO(9, " need .* PORT " << portp << endl); // Create any not already connected - AstPin* newp = new AstPin(nodep->fileline(), 0, portp->name(), - new AstParseRef(nodep->fileline(), - VParseRefExp::PX_TEXT, - portp->name(), NULL, NULL)); + AstPin* newp = new AstPin( + nodep->fileline(), 0, portp->name(), + new AstParseRef(nodep->fileline(), VParseRefExp::PX_TEXT, + portp->name(), nullptr, nullptr)); newp->svImplicit(true); nodep->addPinsp(newp); } else { // warn on the CELL that needs it, not the port nodep->v3warn(PINMISSING, "Cell has missing pin: " << portp->prettyNameQ()); - AstPin* newp = new AstPin(nodep->fileline(), 0, portp->name(), NULL); + AstPin* newp + = new AstPin(nodep->fileline(), 0, portp->name(), nullptr); nodep->addPinsp(newp); } } @@ -423,7 +434,7 @@ private: string varName = nodep->name() + "__Viftop"; // V3LinkDot looks for this naming AstIfaceRefDType* idtypep = new AstIfaceRefDType(nodep->fileline(), nodep->name(), nodep->modp()->name()); - idtypep->ifacep(NULL); // cellp overrides + idtypep->ifacep(nullptr); // cellp overrides // In the case of arrayed interfaces, we replace cellp when de-arraying in V3Inst idtypep->cellp(nodep); // Only set when real parent cell known. AstVar* varp; @@ -448,18 +459,28 @@ private: // Accelerate the recursion // Must do statements to support Generates, math though... - virtual void visit(AstNodeMath*) VL_OVERRIDE {} - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNodeMath*) override {} + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } // METHODS void readModNames() { + // mangled_name, BlockOptions + const V3HierBlockOptSet& hierBlocks = v3Global.opt.hierBlocks(); + const auto hierIt = vlstd::as_const(hierBlocks).find(v3Global.opt.topModule()); + UASSERT((hierIt != hierBlocks.end()) == v3Global.opt.hierChild(), + "information of the top module must exist if --hierarchical-child is set"); // Look at all modules, and store pointers to all module names for (AstNodeModule *nextp, *nodep = v3Global.rootp()->modulesp(); nodep; nodep = nextp) { nextp = VN_CAST(nodep->nextp(), NodeModule); + if (v3Global.opt.hierChild() && nodep->name() == hierIt->second.origName()) { + nodep->name(hierIt->first); // Change name of this module to be mangled name + // considering parameter + } AstNodeModule* foundp = findModuleSym(nodep->name()); if (foundp && foundp != nodep) { if (!(foundp->fileline()->warnIsOff(V3ErrorCode::MODDUP) - || nodep->fileline()->warnIsOff(V3ErrorCode::MODDUP))) { + || nodep->fileline()->warnIsOff(V3ErrorCode::MODDUP) + || hierBlocks.find(nodep->name()) != hierBlocks.end())) { nodep->v3warn(MODDUP, "Duplicate declaration of module: " << nodep->prettyNameQ() << endl << nodep->warnContextPrimary() << endl @@ -479,15 +500,24 @@ private: public: // CONSTRUCTORS LinkCellsVisitor(AstNetlist* nodep, VInFilter* filterp, V3ParseSym* parseSymp) - : m_mods(nodep) { + : m_mods{nodep} { m_filterp = filterp; m_parseSymp = parseSymp; - m_modp = NULL; - m_libVertexp = NULL; - m_topVertexp = NULL; + if (v3Global.opt.hierChild()) { + const V3HierBlockOptSet& hierBlocks = v3Global.opt.hierBlocks(); + UASSERT(!v3Global.opt.topModule().empty(), + "top module must be explicitly specified in hierarchical mode"); + const V3HierBlockOptSet::const_iterator hierIt + = hierBlocks.find(v3Global.opt.topModule()); + UASSERT(hierIt != hierBlocks.end(), + "top module must be listed in --hierarchical-block"); + m_origTopModuleName = hierIt->second.origName(); + } else { + m_origTopModuleName = v3Global.opt.topModule(); + } iterate(nodep); } - virtual ~LinkCellsVisitor() {} + virtual ~LinkCellsVisitor() override {} }; //###################################################################### diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 18af595a0..1ec6fc337 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -76,21 +76,25 @@ //###################################################################### // Matcher classes (for suggestion matching) +class LinkNodeMatcherClass : public VNodeMatcher { +public: + virtual bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, Class); } +}; class LinkNodeMatcherFTask : public VNodeMatcher { public: - virtual bool nodeMatch(const AstNode* nodep) const { return VN_IS(nodep, NodeFTask); } + virtual bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, NodeFTask); } }; class LinkNodeMatcherModport : public VNodeMatcher { public: - virtual bool nodeMatch(const AstNode* nodep) const { return VN_IS(nodep, Modport); } + virtual bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, Modport); } }; class LinkNodeMatcherVar : public VNodeMatcher { public: - virtual bool nodeMatch(const AstNode* nodep) const { return VN_IS(nodep, Var); } + virtual bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, Var); } }; class LinkNodeMatcherVarIO : public VNodeMatcher { public: - virtual bool nodeMatch(const AstNode* nodep) const { + virtual bool nodeMatch(const AstNode* nodep) const override { const AstVar* varp = VN_CAST_CONST(nodep, Var); if (!varp) return false; return varp->isIO(); @@ -98,7 +102,7 @@ public: }; class LinkNodeMatcherVarParam : public VNodeMatcher { public: - virtual bool nodeMatch(const AstNode* nodep) const { + virtual bool nodeMatch(const AstNode* nodep) const override { const AstVar* varp = VN_CAST_CONST(nodep, Var); if (!varp) return false; return varp->isParam(); @@ -106,7 +110,7 @@ public: }; class LinkNodeMatcherVarOrScope : public VNodeMatcher { public: - virtual bool nodeMatch(const AstNode* nodep) const { + virtual bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, Var) || VN_IS(nodep, Scope); } }; @@ -134,15 +138,15 @@ private: public: // ENUMS // In order of priority, compute first ... compute last - enum SAMNum { SAMN_MODPORT, SAMN_IFTOP, SAMN__MAX }; // Values for m_scopeAliasMap + enum SAMNum : uint8_t { SAMN_MODPORT, SAMN_IFTOP, SAMN__MAX }; // Values for m_scopeAliasMap private: // TYPES typedef std::multimap NameScopeSymMap; typedef std::map ScopeAliasMap; - typedef std::set > ImplicitNameSet; + typedef std::set> ImplicitNameSet; typedef std::vector IfaceVarSyms; - typedef std::vector > IfaceModSyms; + typedef std::vector> IfaceModSyms; static LinkDotState* s_errorThisp; // Last self, for error reporting only @@ -164,7 +168,7 @@ public: void dump(const string& nameComment = "linkdot", bool force = false) { if (debug() >= 6 || force) { string filename = v3Global.debugFilename(nameComment) + ".txt"; - const vl_unique_ptr logp(V3File::new_ofstream(filename)); + const std::unique_ptr logp(V3File::new_ofstream(filename)); if (logp->fail()) v3fatal("Can't write " << filename); std::ostream& os = *logp; m_syms.dump(os); @@ -198,18 +202,18 @@ public: // CONSTRUCTORS LinkDotState(AstNetlist* rootp, VLinkDotStep step) - : m_syms(rootp) { + : m_syms{rootp} { UINFO(4, __FUNCTION__ << ": " << endl); m_forPrimary = (step == LDS_PRIMARY); m_forPrearray = (step == LDS_PARAMED || step == LDS_PRIMARY); m_forScopeCreation = (step == LDS_SCOPED); - m_dunitEntp = NULL; + m_dunitEntp = nullptr; s_errorThisp = this; V3Error::errorExitCb(preErrorDumpHandler); // If get error, dump self } ~LinkDotState() { - V3Error::errorExitCb(NULL); - s_errorThisp = NULL; + V3Error::errorExitCb(nullptr); + s_errorThisp = nullptr; } // ACCESSORS @@ -249,7 +253,7 @@ public: // Note we only check for conflicts at the same level; it's ok if one block hides another // We also wouldn't want to not insert it even though it's lower down VSymEnt* foundp = lookupSymp->findIdFlat(name); - AstNode* fnodep = foundp ? foundp->nodep() : NULL; + AstNode* fnodep = foundp ? foundp->nodep() : nullptr; if (!fnodep) { // Not found, will add in a moment. } else if (nodep == fnodep) { // Already inserted. @@ -286,7 +290,7 @@ public: VSymEnt* symp = new VSymEnt(&m_syms, nodep); UINFO(9, " INSERTdunit se" << cvtToHex(symp) << endl); symp->parentp(rootEntp()); // Needed so backward search can find name of top module - symp->fallbackp(NULL); + symp->fallbackp(nullptr); rootEntp()->insert("$unit ", symp); // Space so can never name conflict with user code // UASSERT_OBJ(!m_dunitEntp, nodep, "Call insertDUnit only once"); @@ -387,7 +391,7 @@ public: abovep->reinsert(name, symp); return symp; } - static bool existsModScope(AstNodeModule* nodep) { return nodep->user1p() != NULL; } + static bool existsModScope(AstNodeModule* nodep) { return nodep->user1p() != nullptr; } static VSymEnt* getNodeSym(AstNode* nodep) { // Don't use this in ResolveVisitor, as we need to pick up the proper // reference under each SCOPE @@ -396,7 +400,7 @@ public: return symp; } VSymEnt* getScopeSym(AstScope* nodep) { - NameScopeSymMap::iterator it = m_nameScopeSymMap.find(nodep->name()); + const auto it = m_nameScopeSymMap.find(nodep->name()); UASSERT_OBJ(it != m_nameScopeSymMap.end(), nodep, "Scope never assigned a symbol entry '" << nodep->name() << "'"); return it->second; @@ -404,7 +408,7 @@ public: void implicitOkAdd(AstNodeModule* nodep, const string& varname) { // Mark the given variable name as being allowed to be implicitly declared if (nodep) { - ImplicitNameSet::iterator it = m_implicitNameSet.find(make_pair(nodep, varname)); + const auto it = m_implicitNameSet.find(make_pair(nodep, varname)); if (it == m_implicitNameSet.end()) { m_implicitNameSet.insert(make_pair(nodep, varname)); } @@ -438,10 +442,8 @@ public: return ifacerefp; } void computeIfaceVarSyms() { - for (IfaceVarSyms::iterator it = m_ifaceVarSyms.begin(); it != m_ifaceVarSyms.end(); - ++it) { - VSymEnt* varSymp = *it; - AstVar* varp = varSymp ? VN_CAST(varSymp->nodep(), Var) : NULL; + for (VSymEnt* varSymp : m_ifaceVarSyms) { + AstVar* varp = varSymp ? VN_CAST(varSymp->nodep(), Var) : nullptr; UINFO(9, " insAllIface se" << cvtToHex(varSymp) << " " << varp << endl); AstIfaceRefDType* ifacerefp = ifaceRefFromArray(varp->subDTypep()); UASSERT_OBJ(ifacerefp, varp, "Non-ifacerefs on list!"); @@ -507,7 +509,7 @@ public: VSymEnt* lhsp = it->first; VSymEnt* srcp = lhsp; while (true) { // Follow chain of aliases up to highest level non-alias - ScopeAliasMap::iterator it2 = m_scopeAliasMap[samn].find(srcp); + const auto it2 = m_scopeAliasMap[samn].find(srcp); if (it2 != m_scopeAliasMap[samn].end()) { srcp = it2->second; continue; @@ -541,7 +543,7 @@ private: } public: - VSymEnt* findDotted(FileLine* /*refLocationp*/, VSymEnt* lookupSymp, const string& dotname, + VSymEnt* findDotted(FileLine* refLocationp, VSymEnt* lookupSymp, const string& dotname, string& baddot, VSymEnt*& okSymp) { // Given a dotted hierarchy name, return where in scope it is // Note when dotname=="" we just fall through and return lookupSymp @@ -576,10 +578,10 @@ public: // then look up (inst name or modname) if (firstId) { // Check this module - subcellnames - AstCell* cellp - = lookupSymp ? VN_CAST(lookupSymp->nodep(), Cell) : NULL; // Replicated below + AstCell* cellp = lookupSymp ? VN_CAST(lookupSymp->nodep(), Cell) + : nullptr; // Replicated below AstCellInline* inlinep = lookupSymp ? VN_CAST(lookupSymp->nodep(), CellInline) - : NULL; // Replicated below + : nullptr; // Replicated below if (VSymEnt* findSymp = findWithAltFallback(lookupSymp, ident, altIdent)) { lookupSymp = findSymp; } @@ -605,9 +607,9 @@ public: while (lookupSymp) { lookupSymp = lookupSymp->parentp(); cellp = lookupSymp ? VN_CAST(lookupSymp->nodep(), Cell) - : NULL; // Replicated above + : nullptr; // Replicated above inlinep = lookupSymp ? VN_CAST(lookupSymp->nodep(), CellInline) - : NULL; // Replicated above + : nullptr; // Replicated above if (lookupSymp) { UINFO(9, " Up to " << lookupSymp << endl); if (cellp || inlinep) crossedCell = true; @@ -620,20 +622,29 @@ public: if (crossedCell && VN_IS(lookupSymp->nodep(), Var)) { UINFO(9, " Not found but matches var name in parent " << lookupSymp << endl); - return NULL; + return nullptr; } break; } } else break; } - if (!lookupSymp) return NULL; // Not found + if (!lookupSymp) return nullptr; // Not found } } else { // Searching for middle submodule, must be a cell name if (VSymEnt* findSymp = findWithAltFallback(lookupSymp, ident, altIdent)) { lookupSymp = findSymp; } else { - return NULL; // Not found + return nullptr; // Not found + } + } + if (lookupSymp) { + if (AstCell* cellp = VN_CAST(lookupSymp->nodep(), Cell)) { + if (AstNodeModule* modp = cellp->modp()) { + if (modp->hierBlock()) { + refLocationp->v3error("Cannot access inside hierarchical block"); + } + } } } firstId = false; @@ -654,17 +665,17 @@ public: VSymEnt* findSymPrefixed(VSymEnt* lookupSymp, const string& dotname, string& baddot) { // Find symbol in given point in hierarchy, allowing prefix (post-Inline) - // For simplicity lookupSymp may be passed NULL result from findDotted - if (!lookupSymp) return NULL; + // For simplicity lookupSymp may be passed nullptr result from findDotted + if (!lookupSymp) return nullptr; UINFO(8, " findSymPrefixed " << dotname << " under se" << cvtToHex(lookupSymp) << ((lookupSymp->symPrefix() == "") ? "" : " as ") << ((lookupSymp->symPrefix() == "") ? "" : lookupSymp->symPrefix() + dotname) << " at se" << lookupSymp << endl); string prefix = lookupSymp->symPrefix(); - VSymEnt* foundp = NULL; + VSymEnt* foundp = nullptr; while (!foundp) { - foundp = lookupSymp->findIdFallback(prefix + dotname); // Might be NULL + foundp = lookupSymp->findIdFallback(prefix + dotname); // Might be nullptr if (prefix.empty()) break; string nextPrefix = removeLastInlineScope(prefix); if (prefix == nextPrefix) break; @@ -676,7 +687,7 @@ public: const VNodeMatcher& matcher) { // Suggest alternative symbol in given point in hierarchy // Does not support inline, as we find user-level errors before inlining - // For simplicity lookupSymp may be passed NULL result from findDotted + // For simplicity lookupSymp may be passed nullptr result from findDotted if (!lookupSymp) return ""; VSpellCheck speller; lookupSymp->candidateIdFallback(&speller, &matcher); @@ -690,38 +701,43 @@ public: } }; -LinkDotState* LinkDotState::s_errorThisp = NULL; +LinkDotState* LinkDotState::s_errorThisp = nullptr; //====================================================================== class LinkDotFindVisitor : public AstNVisitor { // STATE LinkDotState* m_statep; // State to pass between visitors, including symbol table - AstNodeModule* m_packagep; // Current package - VSymEnt* m_modSymp; // Symbol Entry for current module - VSymEnt* m_curSymp; // Symbol Entry for current table, where to lookup/insert + AstNodeModule* m_packagep = nullptr; // Current package + VSymEnt* m_modSymp = nullptr; // Symbol Entry for current module + VSymEnt* m_curSymp = nullptr; // Symbol Entry for current table, where to lookup/insert string m_scope; // Scope text - AstNodeBlock* m_blockp; // Current Begin/end block - AstNodeFTask* m_ftaskp; // Current function/task - bool m_inRecursion; // Inside a recursive module - int m_paramNum; // Parameter number, for position based connection - int m_blockNum; // Begin block number, 0=none seen - bool m_explicitNew; // Hit a "new" function - int m_modBlockNum; // Begin block number in module, 0=none seen + AstNodeBlock* m_blockp = nullptr; // Current Begin/end block + AstNodeFTask* m_ftaskp = nullptr; // Current function/task + bool m_inRecursion = false; // Inside a recursive module + int m_paramNum = 0; // Parameter number, for position based connection + int m_blockNum = 0; // Begin block number, 0=none seen + bool m_explicitNew = false; // Hit a "new" function + int m_modBlockNum = 0; // Begin block number in module, 0=none seen // METHODS - int debug() { return LinkDotState::debug(); } + static int debug() { return LinkDotState::debug(); } void makeImplicitNew(AstClass* nodep) { - AstFunc* newp = new AstFunc(nodep->fileline(), "new", NULL, NULL); + AstFunc* newp = new AstFunc(nodep->fileline(), "new", nullptr, nullptr); newp->isConstructor(true); nodep->addMembersp(newp); UINFO(8, "Made implicit new for " << nodep->name() << ": " << nodep << endl); m_statep->insertBlock(m_curSymp, newp->name(), newp, m_packagep); } + bool isHierBlockWrapper(const string& name) const { + const V3HierBlockOptSet& hierBlocks = v3Global.opt.hierBlocks(); + return hierBlocks.find(name) != hierBlocks.end(); + } + // VISITs - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { // Process $unit or other packages // Not needed - dotted references not allowed from inside packages // for (AstNodeModule* nodep = v3Global.rootp()->modulesp(); @@ -746,25 +762,25 @@ class LinkDotFindVisitor : public AstNVisitor { m_curSymp = m_modSymp = m_statep->insertTopCell(modp, m_scope); { iterate(modp); } m_scope = ""; - m_curSymp = m_modSymp = NULL; + m_curSymp = m_modSymp = nullptr; } } - virtual void visit(AstTypeTable*) VL_OVERRIDE {} - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { + virtual void visit(AstTypeTable*) override {} + virtual void visit(AstNodeModule* nodep) override { // Called on top module from Netlist, other modules from the cell creating them, // and packages UINFO(8, " " << nodep << endl); - // m_curSymp/m_modSymp maybe NULL for packages and non-top modules + // m_curSymp/m_modSymp maybe nullptr for packages and non-top modules // Packages will be under top after the initial phases, but until then // need separate handling bool standalonePkg = !m_modSymp && (m_statep->forPrearray() && VN_IS(nodep, Package)); bool doit = (m_modSymp || standalonePkg); - string oldscope = m_scope; - VSymEnt* oldModSymp = m_modSymp; - VSymEnt* oldCurSymp = m_curSymp; - int oldParamNum = m_paramNum; - int oldBlockNum = m_blockNum; - int oldModBlockNum = m_modBlockNum; + VL_RESTORER(m_scope); + VL_RESTORER(m_modSymp); + VL_RESTORER(m_curSymp); + VL_RESTORER(m_paramNum); + VL_RESTORER(m_blockNum); + VL_RESTORER(m_modBlockNum); if (doit && nodep->user2()) { nodep->v3warn(E_UNSUPPORTED, "Unsupported: Identically recursive module (module instantiates " @@ -801,29 +817,31 @@ class LinkDotFindVisitor : public AstNVisitor { if (AstIface* ifacep = VN_CAST(nodep, Iface)) { m_statep->insertIfaceModSym(ifacep, m_curSymp); } + } else if (isHierBlockWrapper(nodep->name())) { + UINFO(5, "Module is hierarchical block, must not be dead: " << nodep << endl); + m_scope = nodep->name(); + VSymEnt* upperSymp = m_curSymp ? m_curSymp : m_statep->rootEntp(); + m_curSymp = m_modSymp + = m_statep->insertBlock(upperSymp, nodep->name() + "::", nodep, m_packagep); + iterateChildren(nodep); + nodep->user4(true); } else { // !doit // Will be optimized away later // Can't remove now, as our backwards iterator will throw up UINFO(5, "Module not under any CELL or top - dead module: " << nodep << endl); } - m_scope = oldscope; - m_modSymp = oldModSymp; - m_curSymp = oldCurSymp; - m_paramNum = oldParamNum; - m_blockNum = oldBlockNum; - m_modBlockNum = oldModBlockNum; // Prep for next - m_packagep = NULL; + m_packagep = nullptr; } - virtual void visit(AstClass* nodep) VL_OVERRIDE { + virtual void visit(AstClass* nodep) override { UASSERT_OBJ(m_curSymp, nodep, "Class not under module/package/$unit"); UINFO(8, " " << nodep << endl); - string oldscope = m_scope; - VSymEnt* oldModSymp = m_modSymp; - VSymEnt* oldCurSymp = m_curSymp; - int oldParamNum = m_paramNum; - int oldBlockNum = m_blockNum; - int oldModBlockNum = m_modBlockNum; + VL_RESTORER(m_scope); + VL_RESTORER(m_modSymp); + VL_RESTORER(m_curSymp); + VL_RESTORER(m_paramNum); + VL_RESTORER(m_blockNum); + VL_RESTORER(m_modBlockNum); { UINFO(4, " Link Class: " << nodep << endl); VSymEnt* upperSymp = m_curSymp; @@ -844,30 +862,24 @@ class LinkDotFindVisitor : public AstNVisitor { // Implicit new needed? if (!m_explicitNew && m_statep->forPrimary()) makeImplicitNew(nodep); } - m_scope = oldscope; - m_modSymp = oldModSymp; - m_curSymp = oldCurSymp; - m_paramNum = oldParamNum; - m_blockNum = oldBlockNum; - m_modBlockNum = oldModBlockNum; } - virtual void visit(AstScope* nodep) VL_OVERRIDE { + virtual void visit(AstScope* nodep) override { UASSERT_OBJ(m_statep->forScopeCreation(), nodep, "Scopes should only exist right after V3Scope"); // Ignored. Processed in next step } - virtual void visit(AstCell* nodep) VL_OVERRIDE { + virtual void visit(AstCell* nodep) override { UINFO(5, " CELL under " << m_scope << " is " << nodep << endl); // Process XREFs/etc inside pins if (nodep->recursive() && m_inRecursion) return; iterateChildren(nodep); // Recurse in, preserving state - string oldscope = m_scope; - AstNodeBlock* oldblockp = m_blockp; - VSymEnt* oldModSymp = m_modSymp; - VSymEnt* oldCurSymp = m_curSymp; - int oldParamNum = m_paramNum; - bool oldRecursion = m_inRecursion; + VL_RESTORER(m_scope); + VL_RESTORER(m_blockp); + VL_RESTORER(m_modSymp); + VL_RESTORER(m_curSymp); + VL_RESTORER(m_paramNum); + VL_RESTORER(m_inRecursion); // Where do we add it? VSymEnt* aboveSymp = m_curSymp; string origname = AstNode::dedotName(nodep->name()); @@ -885,19 +897,13 @@ class LinkDotFindVisitor : public AstNVisitor { { m_scope = m_scope + "." + nodep->name(); m_curSymp = m_modSymp = m_statep->insertCell(aboveSymp, m_modSymp, nodep, m_scope); - m_blockp = NULL; + m_blockp = nullptr; m_inRecursion = nodep->recursive(); // We don't report NotFoundModule, as may be a unused module in a generate if (nodep->modp()) iterate(nodep->modp()); } - m_scope = oldscope; - m_blockp = oldblockp; - m_modSymp = oldModSymp; - m_curSymp = oldCurSymp; - m_paramNum = oldParamNum; - m_inRecursion = oldRecursion; } - virtual void visit(AstCellInline* nodep) VL_OVERRIDE { + virtual void visit(AstCellInline* nodep) override { UINFO(5, " CELLINLINE under " << m_scope << " is " << nodep << endl); VSymEnt* aboveSymp = m_curSymp; // If baz__DOT__foo__DOT__bar, we need to find baz__DOT__foo and add bar to it. @@ -917,11 +923,11 @@ class LinkDotFindVisitor : public AstNVisitor { m_statep->insertInline(aboveSymp, m_modSymp, nodep, nodep->name()); } } - virtual void visit(AstDefParam* nodep) VL_OVERRIDE { + virtual void visit(AstDefParam* nodep) override { nodep->user1p(m_curSymp); iterateChildren(nodep); } - virtual void visit(AstNodeBlock* nodep) VL_OVERRIDE { + virtual void visit(AstNodeBlock* nodep) override { UINFO(5, " " << nodep << endl); // Rename "genblk"s to include a number if (m_statep->forPrimary() && !nodep->user4SetOnce()) { @@ -948,9 +954,10 @@ class LinkDotFindVisitor : public AstNVisitor { if (nodep->name() == "") { iterateChildren(nodep); } else { - int oldNum = m_blockNum; - AstNodeBlock* oldblockp = m_blockp; - VSymEnt* oldCurSymp = m_curSymp; + VL_RESTORER(m_blockNum); + VL_RESTORER(m_blockp); + VL_RESTORER(m_curSymp); + VSymEnt* const oldCurSymp = m_curSymp; { m_blockNum = 0; m_blockp = nodep; @@ -959,26 +966,47 @@ class LinkDotFindVisitor : public AstNVisitor { // Iterate iterateChildren(nodep); } - m_curSymp = oldCurSymp; - m_blockp = oldblockp; - m_blockNum = oldNum; } } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTask* nodep) override { // NodeTask: Remember its name for later resolution UINFO(5, " " << nodep << endl); UASSERT_OBJ(m_curSymp && m_modSymp, nodep, "Function/Task not under module?"); if (nodep->name() == "new") m_explicitNew = true; // Remember the existing symbol table scope - VSymEnt* oldCurSymp = m_curSymp; + VL_RESTORER(m_curSymp); + VSymEnt* const oldCurSymp = m_curSymp; { + // Change to appropriate package if extern declaration (vs definition) + if (nodep->packagep()) { + AstClassOrPackageRef* cpackagerefp = VN_CAST(nodep->packagep(), ClassOrPackageRef); + if (!cpackagerefp) { + nodep->v3warn(E_UNSUPPORTED, + "Unsupported: extern function definition with class-in-class"); + } else { + AstClass* classp = VN_CAST(cpackagerefp->classOrPackagep(), Class); + if (!classp) { + nodep->v3error("Extern declaration's scope is not a defined class"); + } else { + m_curSymp = m_statep->getNodeSym(classp); + if (!nodep->isExternDef()) { + // Move it to proper spot under the target class + nodep->unlinkFrBack(); + classp->addStmtp(nodep); + nodep->isExternDef(true); // So we check there's a matching extern + nodep->packagep()->unlinkFrBack()->deleteTree(); + } + } + } + } // Create symbol table for the task's vars - m_curSymp = m_statep->insertBlock(m_curSymp, nodep->name(), nodep, m_packagep); + string name = string{nodep->isExternProto() ? "extern " : ""} + nodep->name(); + m_curSymp = m_statep->insertBlock(m_curSymp, name, nodep, m_packagep); m_curSymp->fallbackp(oldCurSymp); // Convert the func's range to the output variable // This should probably be done in the Parser instead, as then we could // just attach normal signal attributes to it. - if (nodep->fvarp() && !VN_IS(nodep->fvarp(), Var)) { + if (!nodep->isExternProto() && nodep->fvarp() && !VN_IS(nodep->fvarp(), Var)) { AstNodeDType* dtypep = VN_CAST(nodep->fvarp(), NodeDType); // If unspecified, function returns one bit; however when we // support NEW() it could also return the class reference. @@ -996,15 +1024,14 @@ class LinkDotFindVisitor : public AstNVisitor { newvarp->attrIsolateAssign(nodep->attrIsolateAssign()); nodep->addFvarp(newvarp); // Explicit insert required, as the var name shadows the upper level's task name - m_statep->insertSym(m_curSymp, newvarp->name(), newvarp, NULL /*packagep*/); + m_statep->insertSym(m_curSymp, newvarp->name(), newvarp, nullptr /*packagep*/); } m_ftaskp = nodep; iterateChildren(nodep); - m_ftaskp = NULL; + m_ftaskp = nullptr; } - m_curSymp = oldCurSymp; } - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { // Var: Remember its name for later resolution UASSERT_OBJ(m_curSymp && m_modSymp, nodep, "Var not under module?"); iterateChildren(nodep); @@ -1019,7 +1046,7 @@ class LinkDotFindVisitor : public AstNVisitor { if (!foundp && m_modSymp && nodep->name() == m_modSymp->nodep()->name()) { foundp = m_modSymp; // Conflicts with modname? } - AstVar* findvarp = foundp ? VN_CAST(foundp->nodep(), Var) : NULL; + AstVar* findvarp = foundp ? VN_CAST(foundp->nodep(), Var) : nullptr; bool ins = false; if (!foundp) { ins = true; @@ -1129,27 +1156,27 @@ class LinkDotFindVisitor : public AstNVisitor { } } } - virtual void visit(AstTypedef* nodep) VL_OVERRIDE { + virtual void visit(AstTypedef* nodep) override { UASSERT_OBJ(m_curSymp, nodep, "Typedef not under module/package/$unit"); iterateChildren(nodep); m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep); } - virtual void visit(AstTypedefFwd* nodep) VL_OVERRIDE { + virtual void visit(AstTypedefFwd* nodep) override { UASSERT_OBJ(m_curSymp, nodep, "Typedef not under module/package/$unit"); iterateChildren(nodep); // No need to insert, only the real typedef matters, but need to track for errors nodep->user1p(m_curSymp); } - virtual void visit(AstParamTypeDType* nodep) VL_OVERRIDE { + virtual void visit(AstParamTypeDType* nodep) override { UASSERT_OBJ(m_curSymp, nodep, "Parameter type not under module/package/$unit"); iterateChildren(nodep); m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep); } - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstCFunc* nodep) override { // For dotted resolution, ignore all AstVars under functions, otherwise shouldn't exist UASSERT_OBJ(!m_statep->forScopeCreation(), nodep, "No CFuncs expected in tree yet"); } - virtual void visit(AstEnumItem* nodep) VL_OVERRIDE { + virtual void visit(AstEnumItem* nodep) override { // EnumItem: Remember its name for later resolution iterateChildren(nodep); // Find under either a task or the module's vars @@ -1157,7 +1184,7 @@ class LinkDotFindVisitor : public AstNVisitor { if (!foundp && m_modSymp && nodep->name() == m_modSymp->nodep()->name()) { foundp = m_modSymp; // Conflicts with modname? } - AstEnumItem* findvarp = foundp ? VN_CAST(foundp->nodep(), EnumItem) : NULL; + AstEnumItem* findvarp = foundp ? VN_CAST(foundp->nodep(), EnumItem) : nullptr; bool ins = false; if (!foundp) { ins = true; @@ -1188,7 +1215,7 @@ class LinkDotFindVisitor : public AstNVisitor { } if (ins) m_statep->insertSym(m_curSymp, nodep->name(), nodep, m_packagep); } - virtual void visit(AstPackageImport* nodep) VL_OVERRIDE { + virtual void visit(AstPackageImport* nodep) override { UINFO(4, " Link: " << nodep << endl); VSymEnt* srcp = m_statep->getNodeSym(nodep->packagep()); if (nodep->name() == "*") { @@ -1206,7 +1233,7 @@ class LinkDotFindVisitor : public AstNVisitor { UINFO(9, " Link Done: " << nodep << endl); // No longer needed, but can't delete until any multi-instantiated modules are expanded } - virtual void visit(AstPackageExport* nodep) VL_OVERRIDE { + virtual void visit(AstPackageExport* nodep) override { UINFO(9, " Link: " << nodep << endl); VSymEnt* srcp = m_statep->getNodeSym(nodep->packagep()); if (nodep->name() != "*") { @@ -1220,32 +1247,23 @@ class LinkDotFindVisitor : public AstNVisitor { UINFO(9, " Link Done: " << nodep << endl); // No longer needed, but can't delete until any multi-instantiated modules are expanded } - virtual void visit(AstPackageExportStarStar* nodep) VL_OVERRIDE { + virtual void visit(AstPackageExportStarStar* nodep) override { UINFO(4, " Link: " << nodep << endl); m_curSymp->exportStarStar(m_statep->symsp()); // No longer needed, but can't delete until any multi-instantiated modules are expanded } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - LinkDotFindVisitor(AstNetlist* rootp, LinkDotState* statep) { + LinkDotFindVisitor(AstNetlist* rootp, LinkDotState* statep) + : m_statep{statep} { UINFO(4, __FUNCTION__ << ": " << endl); - m_packagep = NULL; - m_curSymp = m_modSymp = NULL; - m_statep = statep; - m_blockp = NULL; - m_ftaskp = NULL; - m_inRecursion = false; - m_paramNum = 0; - m_blockNum = 0; - m_explicitNew = false; - m_modBlockNum = 0; - // + iterate(rootp); } - virtual ~LinkDotFindVisitor() {} + virtual ~LinkDotFindVisitor() override {} }; //====================================================================== @@ -1260,9 +1278,9 @@ private: // STATE LinkDotState* m_statep; // State to pass between visitors, including symbol table - AstNodeModule* m_modp; // Current module + AstNodeModule* m_modp = nullptr; // Current module - int debug() { return LinkDotState::debug(); } + static int debug() { return LinkDotState::debug(); } void pinImplicitExprRecurse(AstNode* nodep) { // Under a pin, Check interconnect expression for a pin reference or a concat. @@ -1287,8 +1305,8 @@ private: } // VISITs - virtual void visit(AstTypeTable*) VL_OVERRIDE {} - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { + virtual void visit(AstTypeTable*) override {} + virtual void visit(AstNodeModule* nodep) override { UINFO(5, " " << nodep << endl); if (nodep->dead() || !nodep->user4()) { UINFO(4, "Mark dead module " << nodep << endl); @@ -1302,10 +1320,10 @@ private: } else { m_modp = nodep; iterateChildren(nodep); - m_modp = NULL; + m_modp = nullptr; } } - virtual void visit(AstPin* nodep) VL_OVERRIDE { + virtual void visit(AstPin* nodep) override { // Pin: Link to submodule's port // Deal with implicit definitions - do before Resolve visitor as may // be referenced above declaration @@ -1314,12 +1332,12 @@ private: pinImplicitExprRecurse(nodep->exprp()); } } - virtual void visit(AstDefParam* nodep) VL_OVERRIDE { + virtual void visit(AstDefParam* nodep) override { iterateChildren(nodep); nodep->v3warn(DEFPARAM, "Suggest replace defparam assignment with Verilog 2001 #(." << nodep->prettyName() << "(...etc...))"); VSymEnt* foundp = m_statep->getNodeSym(nodep)->findIdFallback(nodep->path()); - AstCell* cellp = foundp ? VN_CAST(foundp->nodep(), Cell) : NULL; + AstCell* cellp = foundp ? VN_CAST(foundp->nodep(), Cell) : nullptr; if (!cellp) { nodep->v3error("In defparam, cell " << nodep->path() << " never declared"); } else { @@ -1334,12 +1352,12 @@ private: VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } } - virtual void visit(AstPort* nodep) VL_OVERRIDE { + virtual void visit(AstPort* nodep) override { // Port: Stash the pin number // Need to set pin numbers after varnames are created // But before we do the final resolution based on names VSymEnt* foundp = m_statep->getNodeSym(m_modp)->findIdFlat(nodep->name()); - AstVar* refp = foundp ? VN_CAST(foundp->nodep(), Var) : NULL; + AstVar* refp = foundp ? VN_CAST(foundp->nodep(), Var) : nullptr; if (!refp) { nodep->v3error( "Input/output/inout declaration not found for port: " << nodep->prettyNameQ()); @@ -1356,20 +1374,20 @@ private: refp->user4(true); VSymEnt* symp = m_statep->insertSym(m_statep->getNodeSym(m_modp), "__pinNumber" + cvtToStr(nodep->pinNum()), refp, - NULL /*packagep*/); + nullptr /*packagep*/); symp->exported(false); } // Ports not needed any more VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstAssignW* nodep) VL_OVERRIDE { + virtual void visit(AstAssignW* nodep) override { // Deal with implicit definitions // We used to nodep->allowImplicit() here, but it turns out // normal "assigns" can also make implicit wires. Yuk. pinImplicitExprRecurse(nodep->lhsp()); iterateChildren(nodep); } - virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { + virtual void visit(AstAssignAlias* nodep) override { // tran gates need implicit creation // As VarRefs don't exist in forPrimary, sanity check UASSERT_OBJ(!m_statep->forPrimary(), nodep, "Assign aliases unexpected pre-dot"); @@ -1381,13 +1399,13 @@ private: } iterateChildren(nodep); } - virtual void visit(AstImplicit* nodep) VL_OVERRIDE { + virtual void visit(AstImplicit* nodep) override { // Unsupported gates need implicit creation pinImplicitExprRecurse(nodep); // We're done with implicit gates VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstTypedefFwd* nodep) VL_OVERRIDE { + virtual void visit(AstTypedefFwd* nodep) override { VSymEnt* foundp = m_statep->getNodeSym(nodep)->findIdFallback(nodep->name()); if (!foundp && v3Global.opt.pedantic()) { // We only check it was ever really defined in pedantic mode, as it @@ -1401,18 +1419,16 @@ private: VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - LinkDotParamVisitor(AstNetlist* rootp, LinkDotState* statep) { + LinkDotParamVisitor(AstNetlist* rootp, LinkDotState* statep) + : m_statep{statep} { UINFO(4, __FUNCTION__ << ": " << endl); - m_statep = statep; - m_modp = NULL; - // iterate(rootp); } - virtual ~LinkDotParamVisitor() {} + virtual ~LinkDotParamVisitor() override {} }; //====================================================================== @@ -1421,17 +1437,17 @@ class LinkDotScopeVisitor : public AstNVisitor { // STATE LinkDotState* m_statep; // State to pass between visitors, including symbol table - AstScope* m_scopep; // The current scope - VSymEnt* m_modSymp; // Symbol entry for current module + AstScope* m_scopep = nullptr; // The current scope + VSymEnt* m_modSymp = nullptr; // Symbol entry for current module - int debug() { return LinkDotState::debug(); } + static int debug() { return LinkDotState::debug(); } // VISITs - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { // Recurse..., backward as must do packages before using packages iterateChildrenBackwards(nodep); } - virtual void visit(AstScope* nodep) VL_OVERRIDE { + virtual void visit(AstScope* nodep) override { UINFO(8, " SCOPE " << nodep << endl); UASSERT_OBJ(m_statep->forScopeCreation(), nodep, "Scopes should only exist right after V3Scope"); @@ -1440,12 +1456,13 @@ class LinkDotScopeVisitor : public AstNVisitor { m_modSymp = m_statep->getScopeSym(nodep); m_scopep = nodep; iterateChildren(nodep); - m_modSymp = NULL; - m_scopep = NULL; + m_modSymp = nullptr; + m_scopep = nullptr; } - virtual void visit(AstVarScope* nodep) VL_OVERRIDE { + virtual void visit(AstVarScope* nodep) override { if (!nodep->varp()->isFuncLocal() && !nodep->varp()->isClassMember()) { - VSymEnt* varSymp = m_statep->insertSym(m_modSymp, nodep->varp()->name(), nodep, NULL); + VSymEnt* varSymp + = m_statep->insertSym(m_modSymp, nodep->varp()->name(), nodep, nullptr); if (nodep->varp()->isIfaceRef() && nodep->varp()->isIfaceParent()) { UINFO(9, "Iface parent ref var " << nodep->varp()->name() << " " << nodep << endl); // Find the interface cell the var references @@ -1479,12 +1496,12 @@ class LinkDotScopeVisitor : public AstNVisitor { } } } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { - VSymEnt* symp = m_statep->insertBlock(m_modSymp, nodep->name(), nodep, NULL); + virtual void visit(AstNodeFTask* nodep) override { + VSymEnt* symp = m_statep->insertBlock(m_modSymp, nodep->name(), nodep, nullptr); symp->fallbackp(m_modSymp); // No recursion, we don't want to pick up variables } - virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { + virtual void visit(AstAssignAlias* nodep) override { // Track aliases created by V3Inline; if we get a VARXREF(aliased_from) // we'll need to replace it with a VARXREF(aliased_to) if (debug() >= 9) nodep->dumpTree(cout, "- alias: "); @@ -1494,7 +1511,7 @@ class LinkDotScopeVisitor : public AstNVisitor { fromVscp->user2p(toVscp); iterateChildren(nodep); } - virtual void visit(AstAssignVarScope* nodep) VL_OVERRIDE { + virtual void visit(AstAssignVarScope* nodep) override { UINFO(5, "ASSIGNVARSCOPE " << nodep << endl); if (debug() >= 9) nodep->dumpTree(cout, "- avs: "); VSymEnt* rhsSymp; @@ -1506,7 +1523,7 @@ class LinkDotScopeVisitor : public AstNVisitor { string inl = ((xrefp && xrefp->inlinedDots().size()) ? (xrefp->inlinedDots() + "__DOT__") : ""); - VSymEnt* symp = NULL; + VSymEnt* symp = nullptr; string scopename; while (!symp) { scopename @@ -1552,22 +1569,19 @@ class LinkDotScopeVisitor : public AstNVisitor { } // For speed, don't recurse things that can't have scope // Note we allow AstNodeStmt's as generates may be under them - virtual void visit(AstCell*) VL_OVERRIDE {} - virtual void visit(AstVar*) VL_OVERRIDE {} - virtual void visit(AstNodeMath*) VL_OVERRIDE {} - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstCell*) override {} + virtual void visit(AstVar*) override {} + virtual void visit(AstNodeMath*) override {} + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - LinkDotScopeVisitor(AstNetlist* rootp, LinkDotState* statep) { + LinkDotScopeVisitor(AstNetlist* rootp, LinkDotState* statep) + : m_statep{statep} { UINFO(4, __FUNCTION__ << ": " << endl); - m_modSymp = NULL; - m_scopep = NULL; - m_statep = statep; - // iterate(rootp); } - virtual ~LinkDotScopeVisitor() {} + virtual ~LinkDotScopeVisitor() override {} }; //====================================================================== @@ -1579,22 +1593,22 @@ class LinkDotIfaceVisitor : public AstNVisitor { VSymEnt* m_curSymp; // Symbol Entry for current table, where to lookup/insert // METHODS - int debug() { return LinkDotState::debug(); } + static int debug() { return LinkDotState::debug(); } // VISITs - virtual void visit(AstModport* nodep) VL_OVERRIDE { + virtual void visit(AstModport* nodep) override { // Modport: Remember its name for later resolution UINFO(5, " fiv: " << nodep << endl); - VSymEnt* oldCurSymp = m_curSymp; + VL_RESTORER(m_curSymp); + VSymEnt* const oldCurSymp = m_curSymp; { // Create symbol table for the vars - m_curSymp = m_statep->insertBlock(m_curSymp, nodep->name(), nodep, NULL); + m_curSymp = m_statep->insertBlock(m_curSymp, nodep->name(), nodep, nullptr); m_curSymp->fallbackp(oldCurSymp); iterateChildren(nodep); } - m_curSymp = oldCurSymp; } - virtual void visit(AstModportFTaskRef* nodep) VL_OVERRIDE { + virtual void visit(AstModportFTaskRef* nodep) override { UINFO(5, " fif: " << nodep << endl); iterateChildren(nodep); if (nodep->isExport()) nodep->v3warn(E_UNSUPPORTED, "Unsupported: modport export"); @@ -1605,7 +1619,7 @@ class LinkDotIfaceVisitor : public AstNVisitor { // Make symbol under modport that points at the _interface_'s var, not the modport. nodep->ftaskp(ftaskp); VSymEnt* subSymp - = m_statep->insertSym(m_curSymp, nodep->name(), ftaskp, NULL /*package*/); + = m_statep->insertSym(m_curSymp, nodep->name(), ftaskp, nullptr /*package*/); m_statep->insertScopeAlias(LinkDotState::SAMN_MODPORT, subSymp, symp); } else { nodep->v3error("Modport item is not a function/task: " << nodep->prettyNameQ()); @@ -1617,7 +1631,7 @@ class LinkDotIfaceVisitor : public AstNVisitor { VL_DO_DANGLING(pushDeletep(nodep), nodep); } } - virtual void visit(AstModportVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstModportVarRef* nodep) override { UINFO(5, " fiv: " << nodep << endl); iterateChildren(nodep); VSymEnt* symp = m_curSymp->findIdFallback(nodep->name()); @@ -1627,11 +1641,11 @@ class LinkDotIfaceVisitor : public AstNVisitor { // Make symbol under modport that points at the _interface_'s var via the modport. // (Need modport still to test input/output markings) nodep->varp(varp); - m_statep->insertSym(m_curSymp, nodep->name(), nodep, NULL /*package*/); + m_statep->insertSym(m_curSymp, nodep->name(), nodep, nullptr /*package*/); } else if (AstVarScope* vscp = VN_CAST(symp->nodep(), VarScope)) { // Make symbol under modport that points at the _interface_'s var, not the modport. nodep->varp(vscp->varp()); - m_statep->insertSym(m_curSymp, nodep->name(), vscp, NULL /*package*/); + m_statep->insertSym(m_curSymp, nodep->name(), vscp, nullptr /*package*/); } else { nodep->v3error("Modport item is not a variable: " << nodep->prettyNameQ()); } @@ -1642,7 +1656,7 @@ class LinkDotIfaceVisitor : public AstNVisitor { VL_DO_DANGLING(pushDeletep(nodep), nodep); } } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS @@ -1652,7 +1666,7 @@ public: m_statep = statep; iterate(nodep); } - virtual ~LinkDotIfaceVisitor() {} + virtual ~LinkDotIfaceVisitor() override {} }; void LinkDotState::computeIfaceModSyms() { @@ -1680,7 +1694,7 @@ private: AstUser5InUse m_inuser5; // TYPES - enum DotPosition { + enum DotPosition : uint8_t { DP_NONE = 0, // Not under a DOT DP_PACKAGE, // {package}:: DOT DP_SCOPE, // [DOT...] {scope-or-var} DOT @@ -1690,13 +1704,13 @@ private: // STATE LinkDotState* m_statep; // State, including dotted symbol table - VSymEnt* m_curSymp; // SymEnt for current lookup point - VSymEnt* m_modSymp; // SymEnt for current module - VSymEnt* m_pinSymp; // SymEnt for pin lookups - AstCell* m_cellp; // Current cell - AstNodeModule* m_modp; // Current module - AstNodeFTask* m_ftaskp; // Current function/task - int m_modportNum; // Uniqueify modport numbers + VSymEnt* m_curSymp = nullptr; // SymEnt for current lookup point + VSymEnt* m_modSymp = nullptr; // SymEnt for current module + VSymEnt* m_pinSymp = nullptr; // SymEnt for pin lookups + AstCell* m_cellp = nullptr; // Current cell + AstNodeModule* m_modp = nullptr; // Current module + AstNodeFTask* m_ftaskp = nullptr; // Current function/task + int m_modportNum = 0; // Uniqueify modport numbers struct DotStates { DotPosition m_dotPos; // Scope part of dotted resolution @@ -1706,16 +1720,16 @@ private: AstNode* m_unlinkedScope; // Unresolved scope, needs corresponding VarXRef bool m_dotErr; // Error found in dotted resolution, ignore upwards string m_dotText; // String of dotted names found in below parseref - DotStates() { init(NULL); } + DotStates() { init(nullptr); } ~DotStates() {} void init(VSymEnt* curSymp) { m_dotPos = DP_NONE; m_dotSymp = curSymp; - m_dotp = NULL; + m_dotp = nullptr; m_dotErr = false; m_dotText = ""; m_unresolved = false; - m_unlinkedScope = NULL; + m_unlinkedScope = nullptr; } string ascii() const { static const char* const names[] = {"NONE", "PACKAGE", "SCOPE", "FINAL", "MEMBER"}; @@ -1728,7 +1742,7 @@ private: } } m_ds; // State to preserve across recursions - int debug() { return LinkDotState::debug(); } + static int debug() { return LinkDotState::debug(); } // METHODS - Variables void createImplicitVar(VSymEnt* lookupSymp, AstVarRef* nodep, AstNodeModule* modp, @@ -1763,13 +1777,13 @@ private: modp->addStmtp(newp); // Link it to signal list, must add the variable under the module; // current scope might be lower now - m_statep->insertSym(moduleSymp, newp->name(), newp, NULL /*packagep*/); + m_statep->insertSym(moduleSymp, newp->name(), newp, nullptr /*packagep*/); } } AstVar* foundToVarp(const VSymEnt* symp, AstNode* nodep, bool lvalue) { // Return a variable if possible, auto converting a modport to variable if (!symp) { - return NULL; + return nullptr; } else if (VN_IS(symp->nodep(), Var)) { return VN_CAST(symp->nodep(), Var); } else if (VN_IS(symp->nodep(), ModportVarRef)) { @@ -1780,7 +1794,7 @@ private: } // else other simulators don't warn about reading, and IEEE doesn't say illegal return varp; } else { - return NULL; + return nullptr; } } void taskFuncSwapCheck(AstNodeFTaskRef* nodep) { @@ -1823,44 +1837,44 @@ private: } // VISITs - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { // Recurse..., backward as must do packages before using packages iterateChildrenBackwards(nodep); } - virtual void visit(AstTypeTable*) VL_OVERRIDE {} - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { + virtual void visit(AstTypeTable*) override {} + virtual void visit(AstNodeModule* nodep) override { if (nodep->dead()) return; checkNoDot(nodep); UINFO(8, " " << nodep << endl); m_ds.init(m_curSymp); m_ds.m_dotSymp = m_curSymp = m_modSymp = m_statep->getNodeSym(nodep); // Until overridden by a SCOPE - m_cellp = NULL; + m_cellp = nullptr; m_modp = nodep; m_modportNum = 0; iterateChildren(nodep); - m_modp = NULL; - m_ds.m_dotSymp = m_curSymp = m_modSymp = NULL; + m_modp = nullptr; + m_ds.m_dotSymp = m_curSymp = m_modSymp = nullptr; } - virtual void visit(AstScope* nodep) VL_OVERRIDE { + virtual void visit(AstScope* nodep) override { UINFO(8, " " << nodep << endl); - VSymEnt* oldModSymp = m_modSymp; - VSymEnt* oldCurSymp = m_curSymp; - checkNoDot(nodep); - m_ds.m_dotSymp = m_curSymp = m_modSymp = m_statep->getScopeSym(nodep); - iterateChildren(nodep); - m_ds.m_dotSymp = m_curSymp = m_modSymp = NULL; - m_modSymp = oldModSymp; - m_curSymp = oldCurSymp; + VL_RESTORER(m_modSymp); + VL_RESTORER(m_curSymp); + { + checkNoDot(nodep); + m_ds.m_dotSymp = m_curSymp = m_modSymp = m_statep->getScopeSym(nodep); + iterateChildren(nodep); + m_ds.m_dotSymp = m_curSymp = m_modSymp = nullptr; + } } - virtual void visit(AstCellInline* nodep) VL_OVERRIDE { + virtual void visit(AstCellInline* nodep) override { checkNoDot(nodep); if (m_statep->forScopeCreation() && !v3Global.opt.vpi()) { nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); } } - virtual void visit(AstCell* nodep) VL_OVERRIDE { + virtual void visit(AstCell* nodep) override { // Cell: Recurse inside or cleanup not founds checkNoDot(nodep); m_cellp = nodep; @@ -1882,14 +1896,14 @@ private: // if (debug()) nodep->dumpTree(cout, "linkcell:"); // if (debug()) nodep->modp()->dumpTree(cout, "linkcemd:"); iterateChildren(nodep); - m_pinSymp = NULL; + m_pinSymp = nullptr; } } - m_cellp = NULL; + m_cellp = nullptr; // Parent module inherits child's publicity // This is done bottom up in the LinkBotupVisitor stage } - virtual void visit(AstPin* nodep) VL_OVERRIDE { + virtual void visit(AstPin* nodep) override { // Pin: Link to submodule's port checkNoDot(nodep); iterateChildren(nodep); @@ -1928,7 +1942,7 @@ private: } // Early return() above when deleted } - virtual void visit(AstDot* nodep) VL_OVERRIDE { + virtual void visit(AstDot* nodep) override { // Legal under a DOT: AstDot, AstParseRef, AstPackageRef, AstNodeSel // also a DOT can be part of an expression, but only above plus // AstFTaskRef are legal children @@ -1995,12 +2009,12 @@ private: m_ds.m_dotp = lastStates.m_dotp; } } - virtual void visit(AstParseRef* nodep) VL_OVERRIDE { + virtual void visit(AstParseRef* nodep) override { if (nodep->user3SetOnce()) return; UINFO(9, " linkPARSEREF " << m_ds.ascii() << " n=" << nodep << endl); // m_curSymp is symbol table of outer expression // m_ds.m_dotSymp is symbol table relative to "."'s above now - UASSERT_OBJ(m_ds.m_dotSymp, nodep, "NULL lookup symbol table"); + UASSERT_OBJ(m_ds.m_dotSymp, nodep, "nullptr lookup symbol table"); // Generally resolved during Primay, but might be at param time under AstUnlinkedRef UASSERT_OBJ(m_statep->forPrimary() || m_statep->forPrearray(), nodep, "ParseRefs should no longer exist"); @@ -2013,7 +2027,7 @@ private: bool start = (m_ds.m_dotPos == DP_NONE); // Save, as m_dotp will be changed if (start) { m_ds.init(m_curSymp); - // Note m_ds.m_dot remains NULL; this is a reference not under a dot + // Note m_ds.m_dot remains nullptr; this is a reference not under a dot } if (nodep->name() == "this") { nodep->v3warn(E_UNSUPPORTED, "Unsupported: this"); @@ -2027,10 +2041,11 @@ private: AstNode* varEtcp = m_ds.m_dotp->lhsp()->unlinkFrBack(); AstNode* newp = new AstMemberSel(nodep->fileline(), varEtcp, VFlagChildDType(), nodep->name()); - if (m_ds.m_dotErr) + if (m_ds.m_dotErr) { nodep->unlinkFrBack(); // Avoid circular node loop on errors - else + } else { nodep->replaceWith(newp); + } VL_DO_DANGLING(pushDeletep(nodep), nodep); } else { // @@ -2039,7 +2054,7 @@ private: bool allowVar = false; if (m_ds.m_dotPos == DP_PACKAGE) { // {package}::{a} - AstNodeModule* packagep = NULL; + AstNodeModule* packagep = nullptr; expectWhat = "scope/variable"; allowScope = true; allowVar = true; @@ -2072,10 +2087,10 @@ private: // Lookup VSymEnt* foundp; string baddot; - VSymEnt* okSymp = NULL; + VSymEnt* okSymp = nullptr; if (allowScope) { foundp = m_statep->findDotted(nodep->fileline(), m_ds.m_dotSymp, nodep->name(), - baddot, okSymp); // Maybe NULL + baddot, okSymp); // Maybe nullptr } else { foundp = m_ds.m_dotSymp->findIdFallback(nodep->name()); } @@ -2106,7 +2121,8 @@ private: // generate begin string findName = nodep->name() + "__Viftop"; VSymEnt* ifaceSymp = parentEntp->findIdFallback(findName); - AstVar* ifaceRefVarp = ifaceSymp ? VN_CAST(ifaceSymp->nodep(), Var) : NULL; + AstVar* ifaceRefVarp + = ifaceSymp ? VN_CAST(ifaceSymp->nodep(), Var) : nullptr; UASSERT_OBJ(ifaceRefVarp, nodep, "Can't find interface var ref: " << findName); // @@ -2165,7 +2181,7 @@ private: newp = new AstUnlinkedRef(nodep->fileline(), VN_CAST(refp, VarXRef), refp->name(), m_ds.m_unlinkedScope->unlinkFrBack()); - m_ds.m_unlinkedScope = NULL; + m_ds.m_unlinkedScope = nullptr; m_ds.m_unresolved = false; } } else { @@ -2267,7 +2283,7 @@ private: } if (start) m_ds = lastStates; } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { // VarRef: Resolve its reference // ParseRefs are used the first pass (forPrimary) so we shouldn't get can't find // errors here now that we have a VarRef. @@ -2275,9 +2291,9 @@ private: iterateChildren(nodep); if (!nodep->varp()) { UINFO(9, " linkVarRef se" << cvtToHex(m_curSymp) << " n=" << nodep << endl); - UASSERT_OBJ(m_curSymp, nodep, "NULL lookup symbol table"); + UASSERT_OBJ(m_curSymp, nodep, "nullptr lookup symbol table"); VSymEnt* foundp = m_curSymp->findIdFallback(nodep->name()); - if (AstVar* varp = foundp ? foundToVarp(foundp, nodep, nodep->lvalue()) : NULL) { + if (AstVar* varp = foundp ? foundToVarp(foundp, nodep, nodep->lvalue()) : nullptr) { nodep->varp(varp); // Generally set by parse, but might be an import nodep->packagep(foundp->packagep()); @@ -2287,7 +2303,7 @@ private: } } } - virtual void visit(AstVarXRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarXRef* nodep) override { // VarRef: Resolve its reference // We always link even if varp() is set, because the module we choose may change // due to creating new modules, flattening, etc. @@ -2297,7 +2313,7 @@ private: if (!m_modSymp) { // Module that is not in hierarchy. We'll be dead code eliminating it later. UINFO(9, "Dead module for " << nodep << endl); - nodep->varp(NULL); + nodep->varp(nullptr); } else { string baddot; VSymEnt* okSymp; @@ -2314,10 +2330,10 @@ private: << " in: " << nodep->inlinedDots()); } dotSymp = m_statep->findDotted(nodep->fileline(), dotSymp, nodep->dotted(), baddot, - okSymp); // Maybe NULL + okSymp); // Maybe nullptr if (!m_statep->forScopeCreation()) { VSymEnt* foundp = m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot); - AstVar* varp = foundp ? foundToVarp(foundp, nodep, nodep->lvalue()) : NULL; + AstVar* varp = foundp ? foundToVarp(foundp, nodep, nodep->lvalue()) : nullptr; nodep->varp(varp); UINFO(7, " Resolved " << nodep << endl); // Also prints varp if (!nodep->varp()) { @@ -2340,7 +2356,7 @@ private: } } else { VSymEnt* foundp = m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot); - AstVarScope* vscp = foundp ? VN_CAST(foundp->nodep(), VarScope) : NULL; + AstVarScope* vscp = foundp ? VN_CAST(foundp->nodep(), VarScope) : nullptr; if (!vscp) { nodep->v3error("Can't find varpin scope of " << AstNode::prettyNameQ(baddot) << " in dotted signal: '" @@ -2365,32 +2381,31 @@ private: } } } - virtual void visit(AstEnumDType* nodep) VL_OVERRIDE { + virtual void visit(AstEnumDType* nodep) override { iterateChildren(nodep); AstRefDType* refdtypep = VN_CAST(nodep->subDTypep(), RefDType); if (refdtypep && (nodep == refdtypep->subDTypep())) { refdtypep->v3error("Self-referential enumerated type definition"); } } - virtual void visit(AstEnumItemRef* nodep) VL_OVERRIDE { + virtual void visit(AstEnumItemRef* nodep) override { // EnumItemRef may be under a dot. Should already be resolved. iterateChildren(nodep); } - virtual void visit(AstMethodCall* nodep) VL_OVERRIDE { + virtual void visit(AstMethodCall* nodep) override { // Created here so should already be resolved. - DotStates lastStates = m_ds; + VL_RESTORER(m_ds); { m_ds.init(m_curSymp); iterateChildren(nodep); } - m_ds = lastStates; } - virtual void visit(AstWith* nodep) VL_OVERRIDE { + virtual void visit(AstWith* nodep) override { nodep->v3warn(E_UNSUPPORTED, "Unsupported: with statements"); nodep->replaceWith(nodep->funcrefp()->unlinkFrBack()); VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { checkNoDot(nodep); iterateChildren(nodep); if (m_statep->forPrimary() && nodep->isIO() && !m_ftaskp && !nodep->user4()) { @@ -2398,7 +2413,7 @@ private: "Input/output/inout does not appear in port list: " << nodep->prettyNameQ()); } } - virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTaskRef* nodep) override { if (nodep->user3SetOnce()) return; UINFO(8, " " << nodep << endl); if (m_ds.m_dotp && m_ds.m_dotPos == DP_PACKAGE) { @@ -2416,14 +2431,14 @@ private: m_ds.m_dotp->lhsp(), "Bad package link"); nodep->packagep(VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef)->packagep()); m_ds.m_dotPos = DP_SCOPE; - m_ds.m_dotp = NULL; + m_ds.m_dotp = nullptr; } else if (m_ds.m_dotp && m_ds.m_dotPos == DP_FINAL) { if (m_ds.m_unresolved && m_ds.m_unlinkedScope) { AstNodeFTaskRef* newftaskp = nodep->cloneTree(false); newftaskp->dotted(m_ds.m_dotText); AstNode* newp = new AstUnlinkedRef(nodep->fileline(), newftaskp, nodep->name(), m_ds.m_unlinkedScope->unlinkFrBack()); - m_ds.m_unlinkedScope = NULL; + m_ds.m_unlinkedScope = nullptr; m_ds.m_unresolved = false; nodep->replaceWith(newp); return; @@ -2434,7 +2449,7 @@ private: // Found a Var, everything following is method call. // {scope}.{var}.HERE {method} ( ARGS ) AstNode* varEtcp = m_ds.m_dotp->lhsp()->unlinkFrBack(); - AstNode* argsp = NULL; + AstNode* argsp = nullptr; if (nodep->pinsp()) argsp = nodep->pinsp()->unlinkFrBackWithNext(); AstNode* newp = new AstMethodCall(nodep->fileline(), varEtcp, VFlagChildDType(), nodep->name(), argsp); @@ -2449,13 +2464,13 @@ private: } else if (!m_modSymp) { // Module that is not in hierarchy. We'll be dead code eliminating it later. UINFO(9, "Dead module for " << nodep << endl); - nodep->taskp(NULL); + nodep->taskp(nullptr); } else if (nodep->dotted() == "" && nodep->taskp()) { // Earlier should have setup the links // Might be under a BEGIN we're not processing, so don't relink it } else { string baddot; - VSymEnt* okSymp = NULL; + VSymEnt* okSymp = nullptr; VSymEnt* dotSymp = m_curSymp; // Start search at module, as a variable // of same name under a subtask isn't a relevant hit however a // function under a begin/end is. So we want begins, but not @@ -2480,11 +2495,11 @@ private: } } dotSymp = m_statep->findDotted(nodep->fileline(), dotSymp, nodep->dotted(), baddot, - okSymp); // Maybe NULL + okSymp); // Maybe nullptr } VSymEnt* foundp = m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot); AstNodeFTask* taskp - = foundp ? VN_CAST(foundp->nodep(), NodeFTask) : NULL; // Maybe NULL + = foundp ? VN_CAST(foundp->nodep(), NodeFTask) : nullptr; // Maybe nullptr if (taskp) { nodep->taskp(taskp); nodep->packagep(foundp->packagep()); @@ -2509,7 +2524,7 @@ private: newp = new AstConst(nodep->fileline(), AstConst::StringToParse(), "'0"); } else { - AstNode* outp = NULL; + AstNode* outp = nullptr; while (nodep->pinsp()) { AstNode* pinp = nodep->pinsp()->unlinkFrBack(); AstNode* addp = pinp; @@ -2547,14 +2562,13 @@ private: } taskFuncSwapCheck(nodep); } - DotStates lastStates = m_ds; { + VL_RESTORER(m_ds); m_ds.init(m_curSymp); iterateChildren(nodep); } - m_ds = lastStates; } - virtual void visit(AstSelBit* nodep) VL_OVERRIDE { + virtual void visit(AstSelBit* nodep) override { if (nodep->user3SetOnce()) return; iterateAndNextNull(nodep->lhsp()); if (m_ds.m_dotPos @@ -2566,13 +2580,14 @@ private: } // Pass dot state down to fromp() iterateAndNextNull(nodep->fromp()); - DotStates lastStates = m_ds; { - m_ds.init(m_curSymp); - iterateAndNextNull(nodep->bitp()); - iterateAndNextNull(nodep->attrp()); + VL_RESTORER(m_ds); + { + m_ds.init(m_curSymp); + iterateAndNextNull(nodep->bitp()); + iterateAndNextNull(nodep->attrp()); + } } - m_ds = lastStates; if (m_ds.m_unresolved && m_ds.m_dotPos == DP_SCOPE) { AstNode* exprp = nodep->bitp()->unlinkFrBack(); AstCellArrayRef* newp @@ -2581,7 +2596,7 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); } } - virtual void visit(AstNodePreSel* nodep) VL_OVERRIDE { + virtual void visit(AstNodePreSel* nodep) override { // Excludes simple AstSelBit, see above if (nodep->user3SetOnce()) return; if (m_ds.m_dotPos @@ -2592,20 +2607,19 @@ private: return; } iterateAndNextNull(nodep->lhsp()); - DotStates lastStates = m_ds; + VL_RESTORER(m_ds); { m_ds.init(m_curSymp); iterateAndNextNull(nodep->rhsp()); iterateAndNextNull(nodep->thsp()); iterateAndNextNull(nodep->attrp()); } - m_ds = lastStates; } - virtual void visit(AstMemberSel* nodep) VL_OVERRIDE { + virtual void visit(AstMemberSel* nodep) override { // checkNoDot not appropriate, can be under a dot iterateChildren(nodep); } - virtual void visit(AstNodeBlock* nodep) VL_OVERRIDE { + virtual void visit(AstNodeBlock* nodep) override { UINFO(5, " " << nodep << endl); checkNoDot(nodep); VSymEnt* oldCurSymp = m_curSymp; @@ -2619,14 +2633,21 @@ private: m_ds.m_dotSymp = m_curSymp = oldCurSymp; UINFO(5, " cur=se" << cvtToHex(m_curSymp) << endl); } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTask* nodep) override { UINFO(5, " " << nodep << endl); checkNoDot(nodep); if (nodep->classMethod() && nodep->lifetime().isStatic()) { nodep->v3warn(E_UNSUPPORTED, "Unsupported: 'static' class method"); } - if (nodep->isExtern()) { - nodep->v3warn(E_UNSUPPORTED, "Unsupported: extern class methods"); + if (nodep->isExternDef()) { + if (!m_curSymp->findIdFallback("extern " + nodep->name())) { + nodep->v3error("extern not found that declares " + nodep->prettyNameQ()); + } + } + if (nodep->isExternProto()) { + if (!m_curSymp->findIdFallback(nodep->name())) { + nodep->v3error("definition not found for extern " + nodep->prettyNameQ()); + } } VSymEnt* oldCurSymp = m_curSymp; { @@ -2635,20 +2656,13 @@ private: iterateChildren(nodep); } m_ds.m_dotSymp = m_curSymp = oldCurSymp; - m_ftaskp = NULL; + m_ftaskp = nullptr; } - virtual void visit(AstClass* nodep) VL_OVERRIDE { + virtual void visit(AstClass* nodep) override { UINFO(5, " " << nodep << endl); checkNoDot(nodep); - for (AstNode* itemp = nodep->membersp(); itemp; itemp = itemp->nextp()) { - if (AstClassExtends* eitemp = VN_CAST(itemp, ClassExtends)) { - // Replace abstract reference with hard pointer - // Will need later resolution when deal with parameters - eitemp->v3warn(E_UNSUPPORTED, "Unsupported: class extends"); - } - } - VSymEnt* oldCurSymp = m_curSymp; - VSymEnt* oldModSymp = m_modSymp; + VL_RESTORER(m_curSymp); + VL_RESTORER(m_modSymp); { m_ds.init(m_curSymp); // Until overridden by a SCOPE @@ -2656,6 +2670,41 @@ private: m_modp = nodep; iterateChildren(nodep); } + for (AstNode* itemp = nodep->extendsp(); itemp; itemp = itemp->nextp()) { + if (AstClassExtends* cextp = VN_CAST(itemp, ClassExtends)) { + // Replace abstract reference with hard pointer + // Will need later resolution when deal with parameters + if (cextp->childDTypep() || cextp->dtypep()) continue; // Already converted + AstClassOrPackageRef* cpackagerefp + = VN_CAST(cextp->classOrPkgsp(), ClassOrPackageRef); + if (!cpackagerefp) { + cextp->v3error("Attempting to extend using a non-class "); + } else { + VSymEnt* foundp = m_curSymp->findIdFallback(cpackagerefp->name()); + bool ok = false; + if (foundp) { + if (AstClass* classp = VN_CAST(foundp->nodep(), Class)) { + AstClassRefDType* newp + = new AstClassRefDType{nodep->fileline(), classp}; + cextp->childDTypep(newp); + classp->isExtended(true); + nodep->isExtended(true); + VL_DO_DANGLING(cpackagerefp->unlinkFrBack()->deleteTree(), + cpackagerefp); + ok = true; + } + } + if (!ok) { + string suggest = m_statep->suggestSymFallback( + m_curSymp, cpackagerefp->name(), LinkNodeMatcherClass{}); + cpackagerefp->v3error( + "Class to extend not found: " + << cpackagerefp->prettyNameQ() << endl + << (suggest.empty() ? "" : cpackagerefp->warnMore() + suggest)); + } + } + } + } // V3Width when determines types needs to find enum values and such // so add members pointing to appropriate enum values { @@ -2672,10 +2721,8 @@ private: } } } - m_curSymp = oldCurSymp; - m_modSymp = oldModSymp; } - virtual void visit(AstRefDType* nodep) VL_OVERRIDE { + virtual void visit(AstRefDType* nodep) override { // Resolve its reference if (nodep->user3SetOnce()) return; if (AstNode* cpackagep = nodep->classOrPackagep()) { @@ -2703,7 +2750,7 @@ private: m_ds.m_dotp->lhsp(), "Bad package link"); nodep->packagep(VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef)->packagep()); m_ds.m_dotPos = DP_SCOPE; - m_ds.m_dotp = NULL; + m_ds.m_dotp = nullptr; } else { checkNoDot(nodep); } @@ -2715,14 +2762,14 @@ private: } else { foundp = m_curSymp->findIdFallback(nodep->name()); } - if (AstTypedef* defp = foundp ? VN_CAST(foundp->nodep(), Typedef) : NULL) { + if (AstTypedef* defp = foundp ? VN_CAST(foundp->nodep(), Typedef) : nullptr) { nodep->typedefp(defp); nodep->packagep(foundp->packagep()); } else if (AstParamTypeDType* defp - = foundp ? VN_CAST(foundp->nodep(), ParamTypeDType) : NULL) { + = foundp ? VN_CAST(foundp->nodep(), ParamTypeDType) : nullptr) { nodep->refDTypep(defp); nodep->packagep(foundp->packagep()); - } else if (AstClass* defp = foundp ? VN_CAST(foundp->nodep(), Class) : NULL) { + } else if (AstClass* defp = foundp ? VN_CAST(foundp->nodep(), Class) : nullptr) { AstClassRefDType* newp = new AstClassRefDType(nodep->fileline(), defp); newp->packagep(foundp->packagep()); nodep->replaceWith(newp); @@ -2735,12 +2782,12 @@ private: } iterateChildren(nodep); } - virtual void visit(AstDpiExport* nodep) VL_OVERRIDE { + virtual void visit(AstDpiExport* nodep) override { // AstDpiExport: Make sure the function referenced exists, then dump it iterateChildren(nodep); checkNoDot(nodep); VSymEnt* foundp = m_curSymp->findIdFallback(nodep->name()); - AstNodeFTask* taskp = foundp ? VN_CAST(foundp->nodep(), NodeFTask) : NULL; + AstNodeFTask* taskp = foundp ? VN_CAST(foundp->nodep(), NodeFTask) : nullptr; if (!taskp) { nodep->v3error( "Can't find definition of exported task/function: " << nodep->prettyNameQ()); @@ -2753,55 +2800,47 @@ private: } VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstPackageImport* nodep) VL_OVERRIDE { + virtual void visit(AstPackageImport* nodep) override { // No longer needed checkNoDot(nodep); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstPackageExport* nodep) VL_OVERRIDE { + virtual void visit(AstPackageExport* nodep) override { // No longer needed checkNoDot(nodep); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstPackageExportStarStar* nodep) VL_OVERRIDE { + virtual void visit(AstPackageExportStarStar* nodep) override { // No longer needed checkNoDot(nodep); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstCellRef* nodep) VL_OVERRIDE { + virtual void visit(AstCellRef* nodep) override { UINFO(5, " AstCellRef: " << nodep << " " << m_ds.ascii() << endl); iterateChildren(nodep); } - virtual void visit(AstCellArrayRef* nodep) VL_OVERRIDE { + virtual void visit(AstCellArrayRef* nodep) override { UINFO(5, " AstCellArrayRef: " << nodep << " " << m_ds.ascii() << endl); // Expression already iterated } - virtual void visit(AstUnlinkedRef* nodep) VL_OVERRIDE { + virtual void visit(AstUnlinkedRef* nodep) override { UINFO(5, " AstCellArrayRef: " << nodep << " " << m_ds.ascii() << endl); // No need to iterate, if we have a UnlinkedVarXRef, we're already done } - virtual void visit(AstNode* nodep) VL_OVERRIDE { + virtual void visit(AstNode* nodep) override { checkNoDot(nodep); iterateChildren(nodep); } public: // CONSTRUCTORS - LinkDotResolveVisitor(AstNetlist* rootp, LinkDotState* statep) { + LinkDotResolveVisitor(AstNetlist* rootp, LinkDotState* statep) + : m_statep{statep} { UINFO(4, __FUNCTION__ << ": " << endl); - m_statep = statep; - m_modSymp = NULL; - m_curSymp = NULL; - m_pinSymp = NULL; - m_cellp = NULL; - m_modp = NULL; - m_ftaskp = NULL; - m_modportNum = 0; - // iterate(rootp); } - virtual ~LinkDotResolveVisitor() {} + virtual ~LinkDotResolveVisitor() override {} }; //###################################################################### diff --git a/src/V3LinkDot.h b/src/V3LinkDot.h index 55371bd55..e0d829a01 100644 --- a/src/V3LinkDot.h +++ b/src/V3LinkDot.h @@ -25,7 +25,7 @@ //============================================================================ -enum VLinkDotStep { LDS_PRIMARY, LDS_PARAMED, LDS_ARRAYED, LDS_SCOPED }; +enum VLinkDotStep : uint8_t { LDS_PRIMARY, LDS_PARAMED, LDS_ARRAYED, LDS_SCOPED }; class V3LinkDot { private: diff --git a/src/V3LinkInc.cpp b/src/V3LinkInc.cpp index 55c7b24cf..fdcdbebed 100644 --- a/src/V3LinkInc.cpp +++ b/src/V3LinkInc.cpp @@ -50,17 +50,17 @@ class LinkIncVisitor : public AstNVisitor { private: // TYPES - enum InsertMode { + enum InsertMode : uint8_t { IM_BEFORE, // Pointing at statement ref is in, insert before this IM_AFTER, // Pointing at last inserted stmt, insert after IM_WHILE_PRECOND // Pointing to for loop, add to body end }; // STATE - int m_modIncrementsNum; // Var name counter - InsertMode m_insMode; // How to insert - AstNode* m_insStmtp; // Where to insert statement - bool m_unsupportedHere; // Used to detect where it's not supported yet + int m_modIncrementsNum = 0; // Var name counter + InsertMode m_insMode = IM_BEFORE; // How to insert + AstNode* m_insStmtp = nullptr; // Where to insert statement + bool m_unsupportedHere = false; // Used to detect where it's not supported yet private: void insertBeforeStmt(AstNode* nodep, AstNode* newp) { @@ -86,41 +86,41 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { + virtual void visit(AstNodeModule* nodep) override { // Reset increments count m_modIncrementsNum = 0; iterateChildren(nodep); } - virtual void visit(AstWhile* nodep) VL_OVERRIDE { + virtual void visit(AstWhile* nodep) override { // Special, as statements need to be put in different places // Preconditions insert first just before themselves (the normal // rule for other statement types) - m_insStmtp = NULL; // First thing should be new statement + m_insStmtp = nullptr; // First thing should be new statement iterateAndNextNull(nodep->precondsp()); // Conditions insert first at end of precondsp. m_insMode = IM_WHILE_PRECOND; m_insStmtp = nodep; iterateAndNextNull(nodep->condp()); // Body insert just before themselves - m_insStmtp = NULL; // First thing should be new statement + m_insStmtp = nullptr; // First thing should be new statement iterateAndNextNull(nodep->bodysp()); iterateAndNextNull(nodep->incsp()); // Done the loop - m_insStmtp = NULL; // Next thing should be new statement + m_insStmtp = nullptr; // Next thing should be new statement } - virtual void visit(AstNodeIf* nodep) VL_OVERRIDE { + virtual void visit(AstNodeIf* nodep) override { m_insStmtp = nodep; iterateAndNextNull(nodep->condp()); - m_insStmtp = NULL; + m_insStmtp = nullptr; iterateAndNextNull(nodep->ifsp()); iterateAndNextNull(nodep->elsesp()); - m_insStmtp = NULL; + m_insStmtp = nullptr; } - 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.cpp"); } - virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE { + virtual void visit(AstNodeStmt* nodep) override { if (!nodep->isStatement()) { iterateChildren(nodep); return; @@ -128,7 +128,7 @@ private: m_insMode = IM_BEFORE; m_insStmtp = nodep; iterateChildren(nodep); - m_insStmtp = NULL; // Next thing should be new statement + m_insStmtp = nullptr; // Next thing should be new statement } void unsupported_visit(AstNode* nodep) { m_unsupportedHere = true; @@ -136,11 +136,11 @@ private: iterateChildren(nodep); m_unsupportedHere = false; } - virtual void visit(AstLogAnd* nodep) VL_OVERRIDE { unsupported_visit(nodep); } - virtual void visit(AstLogOr* nodep) VL_OVERRIDE { unsupported_visit(nodep); } - virtual void visit(AstLogEq* nodep) VL_OVERRIDE { unsupported_visit(nodep); } - virtual void visit(AstLogIf* nodep) VL_OVERRIDE { unsupported_visit(nodep); } - virtual void visit(AstNodeCond* nodep) VL_OVERRIDE { unsupported_visit(nodep); } + virtual void visit(AstLogAnd* nodep) override { unsupported_visit(nodep); } + virtual void visit(AstLogOr* nodep) override { unsupported_visit(nodep); } + virtual void visit(AstLogEq* nodep) override { unsupported_visit(nodep); } + virtual void visit(AstLogIf* nodep) override { unsupported_visit(nodep); } + virtual void visit(AstNodeCond* nodep) override { unsupported_visit(nodep); } void prepost_visit(AstNodeTriop* nodep) { // Check if we are underneath a statement if (!m_insStmtp) { @@ -225,23 +225,17 @@ private: nodep->replaceWith(new AstVarRef(varrefp->fileline(), varp, true)); VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstPreAdd* nodep) VL_OVERRIDE { prepost_visit(nodep); } - virtual void visit(AstPostAdd* nodep) VL_OVERRIDE { prepost_visit(nodep); } - virtual void visit(AstPreSub* nodep) VL_OVERRIDE { prepost_visit(nodep); } - virtual void visit(AstPostSub* nodep) VL_OVERRIDE { prepost_visit(nodep); } - virtual void visit(AstGenFor* nodep) VL_OVERRIDE { iterateChildren(nodep); } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstPreAdd* nodep) override { prepost_visit(nodep); } + virtual void visit(AstPostAdd* nodep) override { prepost_visit(nodep); } + virtual void visit(AstPreSub* nodep) override { prepost_visit(nodep); } + virtual void visit(AstPostSub* nodep) override { prepost_visit(nodep); } + virtual void visit(AstGenFor* nodep) override { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - explicit LinkIncVisitor(AstNetlist* nodep) { - m_modIncrementsNum = 0; - m_insMode = IM_BEFORE; - m_insStmtp = NULL; - m_unsupportedHere = false; - iterate(nodep); - } - virtual ~LinkIncVisitor() {} + explicit LinkIncVisitor(AstNetlist* nodep) { iterate(nodep); } + virtual ~LinkIncVisitor() override {} }; //###################################################################### diff --git a/src/V3LinkJump.cpp b/src/V3LinkJump.cpp index 56ff84b93..076ce57a4 100644 --- a/src/V3LinkJump.cpp +++ b/src/V3LinkJump.cpp @@ -47,12 +47,12 @@ private: typedef std::vector BlockStack; // STATE - AstNodeModule* m_modp; // Current module - AstNodeFTask* m_ftaskp; // Current function/task - AstWhile* m_loopp; // Current loop - bool m_loopInc; // In loop increment - bool m_inFork; // Under fork - int m_modRepeatNum; // Repeat counter + AstNodeModule* m_modp = nullptr; // Current module + AstNodeFTask* m_ftaskp = nullptr; // Current function/task + AstWhile* m_loopp = nullptr; // Current loop + bool m_loopInc = false; // In loop increment + bool m_inFork = false; // Under fork + int m_modRepeatNum = 0; // Repeat counter BlockStack m_blockStack; // All begin blocks above current node // METHODS @@ -63,7 +63,7 @@ private: UINFO(4, "Create label for " << nodep << endl); if (VN_IS(nodep, JumpLabel)) return VN_CAST(nodep, JumpLabel); // Done - AstNode* underp = NULL; + AstNode* underp = nullptr; bool under_and_next = true; if (VN_IS(nodep, NodeBlock)) { underp = VN_CAST(nodep, NodeBlock)->stmtsp(); @@ -80,7 +80,7 @@ private: } } else { nodep->v3fatalSrc("Unknown jump point for break/disable/continue"); - return NULL; + return nullptr; } // Skip over variables as we'll just move them in a moment // Also this would otherwise prevent us from using a label twice @@ -92,7 +92,7 @@ private: if (VN_IS(underp, JumpLabel)) { return VN_CAST(underp, JumpLabel); } else { // Move underp stuff to be under a new label - AstJumpBlock* blockp = new AstJumpBlock(nodep->fileline(), NULL); + AstJumpBlock* blockp = new AstJumpBlock(nodep->fileline(), nullptr); AstJumpLabel* labelp = new AstJumpLabel(nodep->fileline(), blockp); blockp->labelp(labelp); @@ -117,35 +117,32 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { + virtual void visit(AstNodeModule* nodep) override { if (nodep->dead()) return; - AstNodeModule* origModp = m_modp; - int origRepeatNum = m_modRepeatNum; + VL_RESTORER(m_modp); + VL_RESTORER(m_modRepeatNum); { m_modp = nodep; m_modRepeatNum = 0; iterateChildren(nodep); } - m_modp = origModp; - m_modRepeatNum = origRepeatNum; } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTask* nodep) override { m_ftaskp = nodep; iterateChildren(nodep); - m_ftaskp = NULL; + m_ftaskp = nullptr; } - virtual void visit(AstNodeBlock* nodep) VL_OVERRIDE { + virtual void visit(AstNodeBlock* nodep) override { UINFO(8, " " << nodep << endl); - bool oldFork = m_inFork; + VL_RESTORER(m_inFork); m_blockStack.push_back(nodep); { m_inFork = m_inFork || VN_IS(nodep, Fork); iterateChildren(nodep); } m_blockStack.pop_back(); - m_inFork = oldFork; } - virtual void visit(AstRepeat* nodep) VL_OVERRIDE { + virtual void visit(AstRepeat* nodep) override { // So later optimizations don't need to deal with them, // REPEAT(count,body) -> loop=count,WHILE(loop>0) { body, loop-- } // Note var can be signed or unsigned based on original number. @@ -173,7 +170,7 @@ private: nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstWait* nodep) VL_OVERRIDE { + virtual void visit(AstWait* nodep) override { nodep->v3warn(E_UNSUPPORTED, "Unsupported: wait statements"); // Statements we'll just execute immediately; equivalent to if they followed this if (AstNode* bodysp = nodep->bodysp()) { @@ -184,21 +181,21 @@ private: } VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstWhile* nodep) VL_OVERRIDE { + virtual void visit(AstWhile* nodep) override { // Don't need to track AstRepeat/AstFor as they have already been converted - AstWhile* lastLoopp = m_loopp; - bool lastInc = m_loopInc; - m_loopp = nodep; - m_loopInc = false; - iterateAndNextNull(nodep->precondsp()); - iterateAndNextNull(nodep->condp()); - iterateAndNextNull(nodep->bodysp()); - m_loopInc = true; - iterateAndNextNull(nodep->incsp()); - m_loopInc = lastInc; - m_loopp = lastLoopp; + VL_RESTORER(m_loopp); + VL_RESTORER(m_loopInc); + { + m_loopp = nodep; + m_loopInc = false; + iterateAndNextNull(nodep->precondsp()); + iterateAndNextNull(nodep->condp()); + iterateAndNextNull(nodep->bodysp()); + m_loopInc = true; + iterateAndNextNull(nodep->incsp()); + } } - virtual void visit(AstReturn* nodep) VL_OVERRIDE { + virtual void visit(AstReturn* nodep) override { iterateChildren(nodep); AstFunc* funcp = VN_CAST(m_ftaskp, Func); if (m_inFork) { @@ -226,7 +223,7 @@ private: nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstBreak* nodep) VL_OVERRIDE { + virtual void visit(AstBreak* nodep) override { iterateChildren(nodep); if (!m_loopp) { nodep->v3error("break isn't underneath a loop"); @@ -238,7 +235,7 @@ private: nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstContinue* nodep) VL_OVERRIDE { + virtual void visit(AstContinue* nodep) override { iterateChildren(nodep); if (!m_loopp) { nodep->v3error("continue isn't underneath a loop"); @@ -251,12 +248,11 @@ private: nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstDisable* nodep) VL_OVERRIDE { + virtual void visit(AstDisable* nodep) override { UINFO(8, " DISABLE " << nodep << endl); iterateChildren(nodep); - AstNodeBlock* blockp = NULL; - for (BlockStack::reverse_iterator it = m_blockStack.rbegin(); it != m_blockStack.rend(); - ++it) { + AstNodeBlock* blockp = nullptr; + for (auto it = m_blockStack.rbegin(); it != m_blockStack.rend(); ++it) { UINFO(9, " UNDERBLK " << *it << endl); if ((*it)->name() == nodep->name()) { blockp = *it; @@ -277,24 +273,16 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); // if (debug() >= 9) { UINFO(0, "\n"); beginp->dumpTree(cout, " labelo: "); } } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { if (m_loopInc && nodep->varp()) nodep->varp()->usedLoopIdx(true); } - 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: // CONSTRUCTORS - explicit LinkJumpVisitor(AstNetlist* nodep) { - m_modp = NULL; - m_ftaskp = NULL; - m_inFork = false; - m_loopp = NULL; - m_loopInc = false; - m_modRepeatNum = 0; - iterate(nodep); - } - virtual ~LinkJumpVisitor() {} + explicit LinkJumpVisitor(AstNetlist* nodep) { iterate(nodep); } + virtual ~LinkJumpVisitor() override {} }; //###################################################################### diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp index 915501d51..7db59b71c 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -36,14 +36,14 @@ private: // STATE bool m_setRefLvalue; // Set VarRefs to lvalues for pin assignments - AstNodeFTask* m_ftaskp; // Function or task we're inside + AstNodeFTask* m_ftaskp = nullptr; // Function or task we're inside // METHODS VL_DEBUG_FUNC; // Declare debug() // VISITs // Result handing - virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstNodeVarRef* nodep) override { // VarRef: LValue its reference if (m_setRefLvalue) nodep->lvalue(true); if (nodep->varp()) { @@ -56,7 +56,7 @@ private: } // Nodes that start propagating down lvalues - virtual void visit(AstPin* nodep) VL_OVERRIDE { + virtual void visit(AstPin* nodep) override { if (nodep->modVarp() && nodep->modVarp()->isWritable()) { // When the varref's were created, we didn't know the I/O state // Now that we do, and it's from a output, we know it's a lvalue @@ -67,18 +67,17 @@ private: iterateChildren(nodep); } } - virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstNodeAssign* nodep) override { + VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = true; iterateAndNextNull(nodep->lhsp()); m_setRefLvalue = false; iterateAndNextNull(nodep->rhsp()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstFOpen* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstFOpen* nodep) override { + VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = true; iterateAndNextNull(nodep->filep()); @@ -86,102 +85,90 @@ private: iterateAndNextNull(nodep->filenamep()); iterateAndNextNull(nodep->modep()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstFOpenMcd* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstFOpenMcd* nodep) override { + VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = true; iterateAndNextNull(nodep->filep()); m_setRefLvalue = false; iterateAndNextNull(nodep->filenamep()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstFClose* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstFClose* nodep) override { + VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = true; iterateAndNextNull(nodep->filep()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstFError* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstFError* nodep) override { + VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = true; iterateAndNextNull(nodep->filep()); iterateAndNextNull(nodep->strp()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstFFlush* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstFFlush* nodep) override { + VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = true; iterateAndNextNull(nodep->filep()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstFGetC* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstFGetC* nodep) override { + VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = true; iterateAndNextNull(nodep->filep()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstFGetS* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstFGetS* nodep) override { + VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = true; iterateAndNextNull(nodep->filep()); iterateAndNextNull(nodep->strgp()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstFRead* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstFRead* nodep) override { + VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = true; iterateAndNextNull(nodep->memp()); iterateAndNextNull(nodep->filep()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstFScanF* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstFScanF* nodep) override { + VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = true; iterateAndNextNull(nodep->filep()); iterateAndNextNull(nodep->exprsp()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstFUngetC* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstFUngetC* nodep) override { + VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = true; iterateAndNextNull(nodep->filep()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstSScanF* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstSScanF* nodep) override { + VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = true; iterateAndNextNull(nodep->exprsp()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstSysIgnore* nodep) VL_OVERRIDE { + virtual void visit(AstSysIgnore* nodep) override { // Can't know if lvalue or not; presume so as stricter - bool last_setRefLvalue = m_setRefLvalue; + VL_RESTORER(m_setRefLvalue); iterateChildren(nodep); - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstReadMem* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstReadMem* nodep) override { + VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = true; iterateAndNextNull(nodep->memp()); @@ -190,30 +177,27 @@ private: iterateAndNextNull(nodep->lsbp()); iterateAndNextNull(nodep->msbp()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstValuePlusArgs* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstValuePlusArgs* nodep) override { + VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = false; iterateAndNextNull(nodep->searchp()); m_setRefLvalue = true; iterateAndNextNull(nodep->outp()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstSFormat* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstSFormat* nodep) override { + VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = true; iterateAndNextNull(nodep->lhsp()); m_setRefLvalue = false; iterateAndNextNull(nodep->fmtp()); } - m_setRefLvalue = last_setRefLvalue; } void prepost_visit(AstNodeTriop* nodep) { - bool last_setRefLvalue = m_setRefLvalue; + VL_RESTORER(m_setRefLvalue); { m_setRefLvalue = false; iterateAndNextNull(nodep->lhsp()); @@ -221,16 +205,15 @@ private: m_setRefLvalue = true; iterateAndNextNull(nodep->thsp()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstPreAdd* nodep) VL_OVERRIDE { prepost_visit(nodep); } - virtual void visit(AstPostAdd* nodep) VL_OVERRIDE { prepost_visit(nodep); } - virtual void visit(AstPreSub* nodep) VL_OVERRIDE { prepost_visit(nodep); } - virtual void visit(AstPostSub* nodep) VL_OVERRIDE { prepost_visit(nodep); } + virtual void visit(AstPreAdd* nodep) override { prepost_visit(nodep); } + virtual void visit(AstPostAdd* nodep) override { prepost_visit(nodep); } + virtual void visit(AstPreSub* nodep) override { prepost_visit(nodep); } + virtual void visit(AstPostSub* nodep) override { prepost_visit(nodep); } // Nodes that change LValue state - virtual void visit(AstSel* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstSel* nodep) override { + VL_RESTORER(m_setRefLvalue); { iterateAndNextNull(nodep->lhsp()); // Only set lvalues on the from @@ -238,41 +221,37 @@ private: iterateAndNextNull(nodep->rhsp()); iterateAndNextNull(nodep->thsp()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstNodeSel* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstNodeSel* nodep) override { + VL_RESTORER(m_setRefLvalue); { // Only set lvalues on the from iterateAndNextNull(nodep->lhsp()); m_setRefLvalue = false; iterateAndNextNull(nodep->rhsp()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstCellArrayRef* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstCellArrayRef* nodep) override { + VL_RESTORER(m_setRefLvalue); { // selp is not an lvalue m_setRefLvalue = false; iterateAndNextNull(nodep->selp()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstNodePreSel* nodep) VL_OVERRIDE { - bool last_setRefLvalue = m_setRefLvalue; + virtual void visit(AstNodePreSel* nodep) override { + VL_RESTORER(m_setRefLvalue); { // Only set lvalues on the from iterateAndNextNull(nodep->lhsp()); m_setRefLvalue = false; iterateAndNextNull(nodep->rhsp()); iterateAndNextNull(nodep->thsp()); } - m_setRefLvalue = last_setRefLvalue; } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTask* nodep) override { m_ftaskp = nodep; iterateChildren(nodep); - m_ftaskp = NULL; + m_ftaskp = nullptr; } - virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTaskRef* nodep) override { AstNode* pinp = nodep->pinsp(); AstNodeFTask* taskp = nodep->taskp(); // We'll deal with mismatching pins later @@ -294,16 +273,15 @@ private: } } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - LinkLValueVisitor(AstNode* nodep, bool start) { - m_setRefLvalue = start; - m_ftaskp = NULL; + LinkLValueVisitor(AstNode* nodep, bool start) + : m_setRefLvalue{start} { iterate(nodep); } - virtual ~LinkLValueVisitor() {} + virtual ~LinkLValueVisitor() override {} }; //###################################################################### diff --git a/src/V3LinkLevel.cpp b/src/V3LinkLevel.cpp index 70c997d6d..8b6a7d7e7 100644 --- a/src/V3LinkLevel.cpp +++ b/src/V3LinkLevel.cpp @@ -61,8 +61,7 @@ void V3LinkLevel::modSortByLevel() { << "... Suggest see manual; fix the duplicates, or use " "--top-module to select top." << V3Error::warnContextNone()); - for (ModVec::const_iterator it = tops.begin(); it != tops.end(); ++it) { - AstNode* alsop = *it; + for (AstNode* alsop : tops) { std::cout << secp->warnMore() << "... Top module " << alsop->prettyNameQ() << endl << alsop->warnContextSecondary(); } @@ -74,24 +73,20 @@ void V3LinkLevel::modSortByLevel() { // Reorder the netlist's modules to have modules in level sorted order stable_sort(mods.begin(), mods.end(), CmpLevel()); // Sort the vector UINFO(9, "modSortByLevel() sorted\n"); // Comment required for gcc4.6.3 / bug666 - for (ModVec::const_iterator it = mods.begin(); it != mods.end(); ++it) { - AstNodeModule* nodep = *it; + for (AstNodeModule* nodep : mods) { nodep->clearIter(); // Because we didn't iterate to find the node // pointers, may have a stale m_iterp() needing cleanup nodep->unlinkFrBack(); } UASSERT_OBJ(!v3Global.rootp()->modulesp(), v3Global.rootp(), "Unlink didn't work"); - for (ModVec::const_iterator it = mods.begin(); it != mods.end(); ++it) { - AstNodeModule* nodep = *it; - v3Global.rootp()->addModulep(nodep); - } + for (AstNodeModule* nodep : mods) v3Global.rootp()->addModulep(nodep); UINFO(9, "modSortByLevel() done\n"); // Comment required for gcc4.6.3 / bug666 V3Global::dumpCheckGlobalTree("cells", false, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); } void V3LinkLevel::timescaling(const ModVec& mods) { // Timescale determination - AstNodeModule* modTimedp = NULL; + AstNodeModule* modTimedp = nullptr; VTimescale unit(VTimescale::NONE); // Use highest level module as default unit - already sorted in proper order for (ModVec::const_iterator it = mods.begin(); it != mods.end(); ++it) { @@ -105,8 +100,7 @@ void V3LinkLevel::timescaling(const ModVec& mods) { if (unit.isNone()) unit = VTimescale(VTimescale::TS_DEFAULT); v3Global.rootp()->timeunit(unit); - for (ModVec::const_iterator it = mods.begin(); it != mods.end(); ++it) { - AstNodeModule* nodep = *it; + for (AstNodeModule* nodep : mods) { if (nodep->timeunit().isNone()) { if (modTimedp && !VN_IS(nodep, Iface) && !(VN_IS(nodep, Package) && VN_CAST(nodep, Package)->isDollarUnit())) { @@ -160,7 +154,7 @@ void V3LinkLevel::wrapTop(AstNetlist* rootp) { AstCell* cellp = new AstCell(modp->fileline(), modp->fileline(), // Could add __03a__03a="::" to prevent conflict // with module names/"v" - modp->name(), modp->name(), NULL, NULL, NULL); + modp->name(), modp->name(), nullptr, nullptr, nullptr); cellp->modp(modp); newmodp->addStmtp(cellp); } @@ -174,7 +168,7 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) { UASSERT_OBJ(newmodp && newmodp->isTop(), rootp, "No TOP module found to insert under"); // Find all duplicate signal names (if multitop) - typedef vl_unordered_set NameSet; + typedef std::unordered_set NameSet; NameSet ioNames; NameSet dupNames; // For all modules, skipping over new top @@ -203,7 +197,7 @@ void V3LinkLevel::wrapTopCell(AstNetlist* rootp) { AstCell* cellp = new AstCell( newmodp->fileline(), newmodp->fileline(), (!v3Global.opt.l2Name().empty() ? v3Global.opt.l2Name() : oldmodp->name()), - oldmodp->name(), NULL, NULL, NULL); + oldmodp->name(), nullptr, nullptr, nullptr); cellp->modp(oldmodp); newmodp->addStmtp(cellp); diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp index 6d79174fa..9da01d844 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -48,14 +48,15 @@ private: typedef std::set FileLineSet; // STATE - AstVar* m_varp; // Variable we're under + AstVar* m_varp = nullptr; // Variable we're under ImplTypedefMap m_implTypedef; // Created typedefs for each FileLineSet m_filelines; // Filelines that have been seen - bool m_inAlways; // Inside an always - AstNodeModule* m_valueModp; // If set, move AstVar->valuep() initial values to this module - AstNodeModule* m_modp; // Current module - AstNodeFTask* m_ftaskp; // Current task - AstNodeDType* m_dtypep; // Current data type + bool m_inAlways = false; // Inside an always + AstNodeModule* m_valueModp + = nullptr; // If set, move AstVar->valuep() initial values to this module + AstNodeModule* m_modp = nullptr; // Current module + AstNodeFTask* m_ftaskp = nullptr; // Current task + AstNodeDType* m_dtypep = nullptr; // Current data type // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -102,40 +103,40 @@ private: } // VISITs - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTask* nodep) override { V3Config::applyFTask(m_modp, nodep); if (!nodep->user1SetOnce()) { // Process only once. cleanFileline(nodep); m_ftaskp = nodep; iterateChildren(nodep); - m_ftaskp = NULL; + m_ftaskp = nullptr; } } - virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTaskRef* nodep) override { if (!nodep->user1SetOnce()) { // Process only once. cleanFileline(nodep); UINFO(5, " " << nodep << endl); AstNodeModule* upperValueModp = m_valueModp; - m_valueModp = NULL; + m_valueModp = nullptr; iterateChildren(nodep); m_valueModp = upperValueModp; } } - virtual void visit(AstNodeDType* nodep) VL_OVERRIDE { visitIterateNodeDType(nodep); } - virtual void visit(AstEnumDType* nodep) VL_OVERRIDE { + virtual void visit(AstNodeDType* nodep) override { visitIterateNodeDType(nodep); } + virtual void visit(AstEnumDType* nodep) override { if (nodep->name() == "") { nodep->name(nameFromTypedef(nodep)); // Might still remain "" } visitIterateNodeDType(nodep); } - virtual void visit(AstNodeUOrStructDType* nodep) VL_OVERRIDE { + virtual void visit(AstNodeUOrStructDType* nodep) override { if (nodep->name() == "") { nodep->name(nameFromTypedef(nodep)); // Might still remain "" } visitIterateNodeDType(nodep); } - virtual void visit(AstEnumItem* nodep) VL_OVERRIDE { + virtual void visit(AstEnumItem* nodep) override { // Expand ranges cleanFileline(nodep); iterateChildren(nodep); @@ -148,15 +149,16 @@ private: int lsb = nodep->rangep()->lsbConst(); int increment = (msb > lsb) ? -1 : 1; int offset_from_init = 0; - AstNode* addp = NULL; + AstNode* addp = nullptr; for (int i = msb; i != (lsb + increment); i += increment, offset_from_init++) { string name = nodep->name() + cvtToStr(i); - AstNode* valuep = NULL; - if (nodep->valuep()) + AstNode* valuep = nullptr; + if (nodep->valuep()) { valuep = new AstAdd( nodep->fileline(), nodep->valuep()->cloneTree(true), new AstConst(nodep->fileline(), AstConst::Unsized32(), offset_from_init)); - AstNode* newp = new AstEnumItem(nodep->fileline(), name, NULL, valuep); + } + AstNode* newp = new AstEnumItem(nodep->fileline(), name, nullptr, valuep); if (addp) { addp = addp->addNextNull(newp); } else { @@ -168,7 +170,7 @@ private: } } - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { cleanFileline(nodep); if (nodep->isParam() && !nodep->valuep() && nodep->fileline()->language() < V3LangCode::L1800_2009) { @@ -213,7 +215,7 @@ private: m_varp = nodep; iterateChildren(nodep); - m_varp = NULL; + m_varp = nullptr; // temporaries under an always aren't expected to be blocking if (m_inAlways) nodep->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true); if (nodep->valuep()) { @@ -256,7 +258,7 @@ private: } } - virtual void visit(AstAttrOf* nodep) VL_OVERRIDE { + virtual void visit(AstAttrOf* nodep) override { cleanFileline(nodep); iterateChildren(nodep); if (nodep->attrType() == AstAttrType::DT_PUBLIC) { @@ -264,11 +266,6 @@ private: UASSERT_OBJ(typep, nodep, "Attribute not attached to typedef"); typep->attrPublic(true); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - } else if (nodep->attrType() == AstAttrType::VAR_CLOCK) { - UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); - nodep->v3warn(DEPRECATED, "sc_clock is deprecated and will be removed"); - m_varp->attrScClocked(true); - VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } else if (nodep->attrType() == AstAttrType::VAR_CLOCK_ENABLE) { UASSERT_OBJ(m_varp, nodep, "Attribute not attached to variable"); m_varp->attrClockEn(true); @@ -325,7 +322,7 @@ private: } } - virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE { + virtual void visit(AstAlwaysPublic* nodep) override { // AlwaysPublic was attached under a var, but it's a statement that should be // at the same level as the var cleanFileline(nodep); @@ -340,14 +337,14 @@ private: } } - virtual void visit(AstDefImplicitDType* nodep) VL_OVERRIDE { + virtual void visit(AstDefImplicitDType* nodep) override { cleanFileline(nodep); UINFO(8, " DEFIMPLICIT " << nodep << endl); // Must remember what names we've already created, and combine duplicates // so that for "var enum {...} a,b" a & b will share a common typedef // Unique name space under each containerp() so that an addition of // a new type won't change every verilated module. - AstTypedef* defp = NULL; + AstTypedef* defp = nullptr; ImplTypedefMap::iterator it = m_implTypedef.find(make_pair(nodep->containerp(), nodep->name())); if (it != m_implTypedef.end()) { @@ -370,7 +367,7 @@ private: VL_DO_DANGLING(nodep->deleteTree(), nodep); return; } else { - defp = new AstTypedef(nodep->fileline(), nodep->name(), NULL, VFlagChildDType(), + defp = new AstTypedef(nodep->fileline(), nodep->name(), nullptr, VFlagChildDType(), dtypep); m_implTypedef.insert( make_pair(make_pair(nodep->containerp(), defp->name()), defp)); @@ -381,7 +378,7 @@ private: VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstForeach* nodep) VL_OVERRIDE { + virtual void visit(AstForeach* nodep) override { // FOREACH(array,loopvars,body) // -> BEGIN(declare vars, loopa=lowest; WHILE(loopa<=highest, ... body)) // nodep->dumpTree(cout, "-foreach-old:"); @@ -402,7 +399,7 @@ private: // 3. ASTSELLOOPVARS(first, var0..var1)) // 4. DOT(DOT(first, second), ASTSELBIT(third, var0)) AstNode* bracketp = nodep->arrayp(); - AstNode* firstVarsp = NULL; + AstNode* firstVarsp = nullptr; while (AstDot* dotp = VN_CAST(bracketp, Dot)) { bracketp = dotp->rhsp(); } if (AstSelBit* selp = VN_CAST(bracketp, SelBit)) { firstVarsp = selp->rhsp()->unlinkFrBackWithNext(); @@ -419,7 +416,7 @@ private: return; } AstNode* arrayp = nodep->arrayp(); // Maybe different node since bracketp looked - if (!VN_IS(arrayp, ParseRef)) { + if (!VN_IS(arrayp, ParseRef) && !VN_IS(arrayp, Dot)) { // Code below needs to use other then attributes to figure out the bounds // Also need to deal with queues, etc arrayp->v3warn(E_UNSUPPORTED, "Unsupported: foreach on non-simple variable reference"); @@ -440,14 +437,11 @@ private: AstNode* varp = new AstVar(fl, AstVarType::BLOCKTEMP, varsp->name(), nodep->findSigned32DType()); // These will be the left and right dimensions and size of the array: - AstNode* leftp = new AstAttrOf(fl, AstAttrType::DIM_LEFT, - new AstVarRef(fl, arrayp->name(), false), + AstNode* leftp = new AstAttrOf(fl, AstAttrType::DIM_LEFT, arrayp->cloneTree(false), new AstConst(fl, dimension)); - AstNode* rightp = new AstAttrOf(fl, AstAttrType::DIM_RIGHT, - new AstVarRef(fl, arrayp->name(), false), + AstNode* rightp = new AstAttrOf(fl, AstAttrType::DIM_RIGHT, arrayp->cloneTree(false), new AstConst(fl, dimension)); - AstNode* sizep = new AstAttrOf(fl, AstAttrType::DIM_SIZE, - new AstVarRef(fl, arrayp->name(), false), + AstNode* sizep = new AstAttrOf(fl, AstAttrType::DIM_SIZE, arrayp->cloneTree(false), new AstConst(fl, dimension)); AstNode* stmtsp = varp; // Assign left-dimension into the loop var: @@ -479,10 +473,10 @@ private: VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { + virtual void visit(AstNodeModule* nodep) override { V3Config::applyModule(nodep); - AstNodeModule* origModp = m_modp; + VL_RESTORER(m_modp); { // Module: Create sim table for entire module and iterate cleanFileline(nodep); @@ -491,7 +485,6 @@ private: m_valueModp = nodep; iterateChildren(nodep); } - m_modp = origModp; m_valueModp = nodep; } void visitIterateNoValueMod(AstNode* nodep) { @@ -499,20 +492,20 @@ private: cleanFileline(nodep); // AstNodeModule* upperValueModp = m_valueModp; - m_valueModp = NULL; + m_valueModp = nullptr; iterateChildren(nodep); m_valueModp = upperValueModp; } - virtual void visit(AstNodeProcedure* nodep) VL_OVERRIDE { visitIterateNoValueMod(nodep); } - virtual void visit(AstAlways* nodep) VL_OVERRIDE { + virtual void visit(AstNodeProcedure* nodep) override { visitIterateNoValueMod(nodep); } + virtual void visit(AstAlways* nodep) override { m_inAlways = true; visitIterateNoValueMod(nodep); m_inAlways = false; } - virtual void visit(AstCover* nodep) VL_OVERRIDE { visitIterateNoValueMod(nodep); } - virtual void visit(AstRestrict* nodep) VL_OVERRIDE { visitIterateNoValueMod(nodep); } + virtual void visit(AstCover* nodep) override { visitIterateNoValueMod(nodep); } + virtual void visit(AstRestrict* nodep) override { visitIterateNoValueMod(nodep); } - virtual void visit(AstBegin* nodep) VL_OVERRIDE { + virtual void visit(AstBegin* nodep) override { V3Config::applyCoverageBlock(m_modp, nodep); cleanFileline(nodep); AstNode* backp = nodep->backp(); @@ -530,45 +523,47 @@ private: } iterateChildren(nodep); } - virtual void visit(AstCase* nodep) VL_OVERRIDE { + virtual void visit(AstCase* nodep) override { V3Config::applyCase(nodep); cleanFileline(nodep); iterateChildren(nodep); } - virtual void visit(AstPrintTimeScale* nodep) VL_OVERRIDE { + virtual void visit(AstPrintTimeScale* nodep) override { // Inlining may change hierarchy, so just save timescale where needed cleanFileline(nodep); iterateChildren(nodep); nodep->name(m_modp->name()); nodep->timeunit(m_modp->timeunit()); } - virtual void visit(AstSFormatF* nodep) VL_OVERRIDE { + virtual void visit(AstSFormatF* nodep) override { cleanFileline(nodep); iterateChildren(nodep); nodep->timeunit(m_modp->timeunit()); } - virtual void visit(AstTime* nodep) VL_OVERRIDE { + virtual void visit(AstTime* nodep) override { cleanFileline(nodep); iterateChildren(nodep); nodep->timeunit(m_modp->timeunit()); } - virtual void visit(AstTimeD* nodep) VL_OVERRIDE { + virtual void visit(AstTimeD* nodep) override { cleanFileline(nodep); iterateChildren(nodep); nodep->timeunit(m_modp->timeunit()); } - virtual void visit(AstTimeImport* nodep) VL_OVERRIDE { + virtual void visit(AstTimeImport* nodep) override { cleanFileline(nodep); iterateChildren(nodep); nodep->timeunit(m_modp->timeunit()); } - virtual void visit(AstTimingControl* nodep) VL_OVERRIDE { + virtual void visit(AstTimingControl* nodep) override { cleanFileline(nodep); iterateChildren(nodep); AstAlways* alwaysp = VN_CAST(nodep->backp(), Always); if (alwaysp && alwaysp->keyword() == VAlwaysKwd::ALWAYS_COMB) { - alwaysp->v3error("Timing control statements not legal under always_comb\n" + alwaysp->v3error("Timing control statements not legal under always_comb " + "(IEEE 1800-2017 9.2.2.2.2)\n" << nodep->warnMore() << "... Suggest use a normal 'always'"); + VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } else if (alwaysp && !alwaysp->sensesp()) { // Verilator is still ony supporting SenTrees under an always, // so allow the parser to handle everything and shim to @@ -578,16 +573,11 @@ private: alwaysp->sensesp(sensesp); } if (nodep->stmtsp()) alwaysp->addStmtp(nodep->stmtsp()->unlinkFrBackWithNext()); - } else { - nodep->v3warn(E_UNSUPPORTED, "Unsupported: timing control statement in this location\n" - << nodep->warnMore() - << "... Suggest have one timing control statement " - << "per procedure, at the top of the procedure"); + VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstNode* nodep) VL_OVERRIDE { + virtual void visit(AstNode* nodep) override { // Default: Just iterate cleanFileline(nodep); iterateChildren(nodep); @@ -595,16 +585,8 @@ private: public: // CONSTRUCTORS - explicit LinkParseVisitor(AstNetlist* rootp) { - m_varp = NULL; - m_modp = NULL; - m_ftaskp = NULL; - m_dtypep = NULL; - m_inAlways = false; - m_valueModp = NULL; - iterate(rootp); - } - virtual ~LinkParseVisitor() {} + explicit LinkParseVisitor(AstNetlist* rootp) { iterate(rootp); } + virtual ~LinkParseVisitor() override {} }; //###################################################################### diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index 962a615fa..d81e1a6b4 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -47,12 +47,12 @@ private: // STATE // Below state needs to be preserved between each module call. - AstNodeModule* m_modp; // Current module - AstClass* m_classp; // Class we're inside - AstNodeFTask* m_ftaskp; // Function or task we're inside - AstNodeCoverOrAssert* m_assertp; // Current assertion - VLifetime m_lifetime; // Propagating lifetime - int m_senitemCvtNum; // Temporary signal counter + AstNodeModule* m_modp = nullptr; // Current module + AstClass* m_classp = nullptr; // Class we're inside + AstNodeFTask* m_ftaskp = nullptr; // Function or task we're inside + AstNodeCoverOrAssert* m_assertp = nullptr; // Current assertion + VLifetime m_lifetime = VLifetime::STATIC; // Propagating lifetime + int m_senitemCvtNum = 0; // Temporary signal counter // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -61,13 +61,13 @@ private: // TODO: Most of these visitors are here for historical reasons. // TODO: ExpectDecriptor can move to data type resolution, and the rest // TODO: could move to V3LinkParse to get them out of the way of elaboration - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { + virtual void visit(AstNodeModule* nodep) override { // Module: Create sim table for entire module and iterate UINFO(8, "MODULE " << nodep << endl); if (nodep->dead()) return; - AstNodeModule* origModp = m_modp; - VLifetime origLifetime = m_lifetime; - int origSenitemCvtNum = m_senitemCvtNum; + VL_RESTORER(m_modp); + VL_RESTORER(m_lifetime); + VL_RESTORER(m_senitemCvtNum); { m_modp = nodep; m_senitemCvtNum = 0; @@ -75,23 +75,18 @@ private: if (m_lifetime.isNone()) m_lifetime = VLifetime::STATIC; iterateChildren(nodep); } - m_modp = origModp; - m_senitemCvtNum = origSenitemCvtNum; - m_lifetime = origLifetime; } - virtual void visit(AstClass* nodep) VL_OVERRIDE { - AstClass* origClassp = m_classp; - VLifetime origLifetime = m_lifetime; + virtual void visit(AstClass* nodep) override { + VL_RESTORER(m_classp); + VL_RESTORER(m_lifetime); { m_classp = nodep; m_lifetime = nodep->lifetime(); if (m_lifetime.isNone()) m_lifetime = VLifetime::AUTOMATIC; iterateChildren(nodep); } - m_classp = origClassp; - m_lifetime = origLifetime; } - virtual void visit(AstInitial* nodep) VL_OVERRIDE { + virtual void visit(AstInitial* nodep) override { iterateChildren(nodep); // Initial assignments under function/tasks can just be simple // assignments without the initial @@ -99,13 +94,13 @@ private: VL_DO_DANGLING(nodep->replaceWith(nodep->bodysp()->unlinkFrBackWithNext()), nodep); } } - virtual void visit(AstNodeCoverOrAssert* nodep) VL_OVERRIDE { + virtual void visit(AstNodeCoverOrAssert* nodep) override { if (m_assertp) nodep->v3error("Assert not allowed under another assert"); m_assertp = nodep; iterateChildren(nodep); - m_assertp = NULL; + m_assertp = nullptr; } - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { iterateChildren(nodep); if (m_classp && !nodep->isParam()) nodep->varType(AstVarType::MEMBER); if (m_classp && nodep->isParam()) @@ -124,16 +119,23 @@ private: } } - virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstNodeVarRef* nodep) override { // VarRef: Resolve its reference if (nodep->varp()) { nodep->varp()->usedParam(true); } iterateChildren(nodep); } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTask* nodep) override { // NodeTask: Remember its name for later resolution // Remember the existing symbol table scope if (m_classp) nodep->classMethod(true); + // V3LinkDot moved the isExternDef into the class, the extern proto was + // checked to exist, and now isn't needed + nodep->isExternDef(false); + if (nodep->isExternProto()) { + VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); + return; + } VLifetime origLifetime = m_lifetime; { m_lifetime = nodep->lifetime(); @@ -141,18 +143,18 @@ private: m_ftaskp = nodep; iterateChildren(nodep); } - m_ftaskp = NULL; + m_ftaskp = nullptr; m_lifetime = origLifetime; if (nodep->dpiExport()) { nodep->scopeNamep(new AstScopeName(nodep->fileline())); } } - virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTaskRef* nodep) override { iterateChildren(nodep); if (nodep->taskp() && (nodep->taskp()->dpiContext() || nodep->taskp()->dpiExport())) { nodep->scopeNamep(new AstScopeName(nodep->fileline())); } } - virtual void visit(AstSenItem* nodep) VL_OVERRIDE { + virtual void visit(AstSenItem* nodep) override { // Remove bit selects, and bark if it's not a simple variable iterateChildren(nodep); if (nodep->isClocked()) { @@ -219,7 +221,7 @@ private: } } - virtual void visit(AstNodePreSel* nodep) VL_OVERRIDE { + virtual void visit(AstNodePreSel* nodep) override { if (!nodep->attrp()) { iterateChildren(nodep); // Constification may change the fromp() to a constant, which will lose the @@ -245,7 +247,7 @@ private: // From {...}[...] syntax in IEEE 2017 if (basefromp) { UINFO(1, " Related node: " << basefromp << endl); } nodep->v3warn(E_UNSUPPORTED, "Unsupported: Select of concatenation"); - nodep = NULL; + nodep = nullptr; } else { if (basefromp) { UINFO(1, " Related node: " << basefromp << endl); } nodep->v3fatalSrc("Illegal bit select; no signal/member being extracted from"); @@ -253,7 +255,7 @@ private: } } - virtual void visit(AstCaseItem* nodep) VL_OVERRIDE { + virtual void visit(AstCaseItem* nodep) override { // Move default caseItems to the bottom of the list // That saves us from having to search each case list twice, for non-defaults and defaults iterateChildren(nodep); @@ -265,8 +267,18 @@ private: } } - virtual void visit(AstPragma* nodep) VL_OVERRIDE { - if (nodep->pragType() == AstPragmaType::PUBLIC_MODULE) { + virtual void visit(AstPragma* nodep) override { + if (nodep->pragType() == AstPragmaType::HIER_BLOCK) { + UASSERT_OBJ(m_modp, nodep, "HIER_BLOCK not under a module"); + // If this is hierarchical mode which is to create protect-lib, + // sub modules do not have hier_block meta comment in the source code. + // But .vlt files may still mark a module which is actually a protect-lib wrapper + // hier_block. AstNodeModule::hierBlock() can be true only when --hierarchical is + // specified. + m_modp->hierBlock(v3Global.opt.hierarchical()); + nodep->unlinkFrBack(); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } else if (nodep->pragType() == AstPragmaType::PUBLIC_MODULE) { UASSERT_OBJ(m_modp, nodep, "PUBLIC_MODULE not under a module"); m_modp->modPublic(true); nodep->unlinkFrBack(); @@ -294,8 +306,7 @@ private: bool inPct = false; bool inIgnore = false; string fmt; - for (string::const_iterator it = format.begin(); it != format.end(); ++it) { - char ch = *it; + for (const char ch : format) { if (!inPct && ch == '%') { inPct = true; inIgnore = false; @@ -406,39 +417,39 @@ private: if (filep && filep->varp()) filep->varp()->attrFileDescr(true); } - virtual void visit(AstFOpen* nodep) VL_OVERRIDE { + virtual void visit(AstFOpen* nodep) override { iterateChildren(nodep); expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); } - virtual void visit(AstFOpenMcd* nodep) VL_OVERRIDE { + virtual void visit(AstFOpenMcd* nodep) override { iterateChildren(nodep); expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); } - virtual void visit(AstFClose* nodep) VL_OVERRIDE { + virtual void visit(AstFClose* nodep) override { iterateChildren(nodep); expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); } - virtual void visit(AstFError* nodep) VL_OVERRIDE { + virtual void visit(AstFError* nodep) override { iterateChildren(nodep); expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); } - virtual void visit(AstFEof* nodep) VL_OVERRIDE { + virtual void visit(AstFEof* nodep) override { iterateChildren(nodep); expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); } - virtual void visit(AstFRead* nodep) VL_OVERRIDE { + virtual void visit(AstFRead* nodep) override { iterateChildren(nodep); expectDescriptor(nodep, VN_CAST(nodep->filep(), NodeVarRef)); } - virtual void visit(AstFScanF* nodep) VL_OVERRIDE { + virtual void visit(AstFScanF* nodep) override { iterateChildren(nodep); expectFormat(nodep, nodep->text(), nodep->exprsp(), true); } - virtual void visit(AstSScanF* nodep) VL_OVERRIDE { + virtual void visit(AstSScanF* nodep) override { iterateChildren(nodep); expectFormat(nodep, nodep->text(), nodep->exprsp(), true); } - virtual void visit(AstSFormatF* nodep) VL_OVERRIDE { + virtual void visit(AstSFormatF* nodep) override { iterateChildren(nodep); // Cleanup old-school displays without format arguments if (!nodep->hasFormat()) { @@ -461,14 +472,14 @@ private: } } - virtual void visit(AstUdpTable* nodep) VL_OVERRIDE { + virtual void visit(AstUdpTable* nodep) override { UINFO(5, "UDPTABLE " << nodep << endl); if (!v3Global.opt.bboxUnsup()) { // We don't warn until V3Inst, so that UDPs that are in libraries and // never used won't result in any warnings. } else { // Massive hack, just tie off all outputs so our analysis can proceed - AstVar* varoutp = NULL; + AstVar* varoutp = nullptr; for (AstNode* stmtp = m_modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) { if (AstVar* varp = VN_CAST(stmtp, Var)) { if (varp->isReadOnly()) { @@ -491,36 +502,28 @@ private: } } - virtual void visit(AstScCtor* nodep) VL_OVERRIDE { + virtual void visit(AstScCtor* nodep) override { // Constructor info means the module must remain public m_modp->modPublic(true); iterateChildren(nodep); } - virtual void visit(AstScDtor* nodep) VL_OVERRIDE { + virtual void visit(AstScDtor* nodep) override { // Destructor info means the module must remain public m_modp->modPublic(true); iterateChildren(nodep); } - virtual void visit(AstScInt* nodep) VL_OVERRIDE { + virtual void visit(AstScInt* nodep) override { // Special class info means the module must remain public m_modp->modPublic(true); iterateChildren(nodep); } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - explicit LinkResolveVisitor(AstNetlist* rootp) - : m_lifetime(VLifetime::STATIC) { // Static outside a module/class - m_classp = NULL; - m_ftaskp = NULL; - m_modp = NULL; - m_assertp = NULL; - m_senitemCvtNum = 0; - iterate(rootp); - } - virtual ~LinkResolveVisitor() {} + explicit LinkResolveVisitor(AstNetlist* rootp) { iterate(rootp); } + virtual ~LinkResolveVisitor() override {} }; //###################################################################### @@ -531,40 +534,35 @@ public: class LinkBotupVisitor : public AstNVisitor { private: // STATE - AstNodeModule* m_modp; // Current module + AstNodeModule* m_modp = nullptr; // Current module // METHODS VL_DEBUG_FUNC; // Declare debug() // VISITs - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { // Iterate modules backwards, in bottom-up order. 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(AstCell* nodep) VL_OVERRIDE { + virtual void visit(AstCell* nodep) override { // Parent module inherits child's publicity if (nodep->modp()->modPublic()) m_modp->modPublic(true); //** No iteration for speed } - 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 LinkBotupVisitor(AstNetlist* rootp) { - m_modp = NULL; - // - iterate(rootp); - } - virtual ~LinkBotupVisitor() {} + explicit LinkBotupVisitor(AstNetlist* rootp) { iterate(rootp); } + virtual ~LinkBotupVisitor() override {} }; //###################################################################### diff --git a/src/V3List.h b/src/V3List.h index 62de0d093..5022e6d38 100644 --- a/src/V3List.h +++ b/src/V3List.h @@ -31,22 +31,20 @@ template class V3List { // List container for linked list of elements of type *T (T is a pointer type) private: // MEMBERS - T m_headp; // First element - T m_tailp; // Last element + T m_headp = nullptr; // First element + T m_tailp = nullptr; // Last element friend class V3ListEnt; public: - V3List() - : m_headp(NULL) - , m_tailp(NULL) {} + V3List() {} ~V3List() {} // METHODS T begin() const { return m_headp; } - T end() const { return NULL; } - bool empty() const { return m_headp == NULL; } + T end() const { return nullptr; } + bool empty() const { return m_headp == nullptr; } void reset() { // clear() without walking the list - m_headp = NULL; - m_tailp = NULL; + m_headp = nullptr; + m_tailp = nullptr; } }; @@ -56,8 +54,8 @@ template class V3ListEnt { // List entry for linked list of elements of type *T (T is a pointer type) private: // MEMBERS - T m_nextp; // Pointer to next element, NULL=end - T m_prevp; // Pointer to previous element, NULL=beginning + T m_nextp = nullptr; // Pointer to next element, nullptr=end + T m_prevp = nullptr; // Pointer to previous element, nullptr=beginning friend class V3List; static V3ListEnt* baseToListEnt(void* newbasep, size_t offset) { // "this" must be a element inside of *basep @@ -67,9 +65,7 @@ private: } public: - V3ListEnt() - : m_nextp(NULL) - , m_prevp(NULL) {} + V3ListEnt() {} ~V3ListEnt() { #ifdef VL_DEBUG // Load bogus pointers so we can catch deletion bugs @@ -83,7 +79,7 @@ public: // "this" must be a element inside of *newp // cppcheck-suppress thisSubtraction size_t offset = (size_t)(vluint8_t*)(this) - (size_t)(vluint8_t*)(newp); - m_nextp = NULL; + m_nextp = nullptr; if (!listr.m_headp) listr.m_headp = newp; m_prevp = listr.m_tailp; if (m_prevp) baseToListEnt(m_prevp, offset)->m_nextp = newp; @@ -96,7 +92,7 @@ public: m_nextp = listr.m_headp; if (m_nextp) baseToListEnt(m_nextp, offset)->m_prevp = newp; listr.m_headp = newp; - m_prevp = NULL; + m_prevp = nullptr; if (!listr.m_tailp) listr.m_tailp = newp; } // Unlink from side @@ -114,7 +110,7 @@ public: } else { listr.m_headp = m_nextp; } - m_prevp = m_nextp = NULL; + m_prevp = m_nextp = nullptr; } }; diff --git a/src/V3Localize.cpp b/src/V3Localize.cpp index 3a9b17946..c9ee6b9f4 100644 --- a/src/V3Localize.cpp +++ b/src/V3Localize.cpp @@ -72,7 +72,7 @@ private: // See above // METHODS - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { // cppcheck-suppress unreadVariable // cppcheck 1.90 bug VarFlags flags(nodep->varp()); if (flags.m_done) { @@ -80,12 +80,12 @@ private: nodep->hierThis(true); } } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit LocalizeDehierVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~LocalizeDehierVisitor() {} + virtual ~LocalizeDehierVisitor() override {} }; //###################################################################### @@ -101,7 +101,7 @@ private: // STATE VDouble0 m_statLocVars; // Statistic tracking - AstCFunc* m_cfuncp; // Current active function + AstCFunc* m_cfuncp = nullptr; // Current active function std::vector m_varps; // List of variables to consider for deletion // METHODS @@ -118,8 +118,7 @@ private: flags.setNodeFlags(nodep); } void moveVars() { - for (std::vector::iterator it = m_varps.begin(); it != m_varps.end(); ++it) { - AstVar* nodep = *it; + for (AstVar* nodep : m_varps) { if (nodep->valuep()) clearOptimizable(nodep, "HasInitValue"); if (!VarFlags(nodep).m_stdFuncAsn) clearStdOptimizable(nodep, "NoStdAssign"); VarFlags flags(nodep); @@ -145,11 +144,11 @@ private: } // VISITORS - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { iterateChildren(nodep); moveVars(); } - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstCFunc* nodep) override { UINFO(4, " CFUNC " << nodep << endl); m_cfuncp = nodep; searchFuncStmts(nodep->argsp()); @@ -157,7 +156,7 @@ private: searchFuncStmts(nodep->stmtsp()); searchFuncStmts(nodep->finalsp()); iterateChildren(nodep); - m_cfuncp = NULL; + m_cfuncp = nullptr; } void searchFuncStmts(AstNode* nodep) { // Search for basic assignments to allow moving non-blocktemps @@ -180,7 +179,7 @@ private: } } - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { if (!nodep->isSigPublic() && !nodep->isPrimaryIO() && !m_cfuncp) { // Not already inside a function UINFO(4, " BLKVAR " << nodep << endl); @@ -188,7 +187,7 @@ private: } // No iterate; Don't want varrefs under it } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { if (!VarFlags(nodep->varp()).m_notOpt) { if (!m_cfuncp) { // Not in function, can't optimize // Perhaps impossible, but better safe @@ -211,21 +210,18 @@ private: AstVarRef* firstasn = static_cast(nodep->varp()->user4p()); if (firstasn && nodep != firstasn) { clearStdOptimizable(nodep->varp(), "notFirstAsn"); - nodep->varp()->user4p(NULL); + nodep->varp()->user4p(nullptr); } } } // No iterate; Don't want varrefs under it } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - explicit LocalizeVisitor(AstNetlist* nodep) { - m_cfuncp = NULL; - iterate(nodep); - } - virtual ~LocalizeVisitor() { + explicit LocalizeVisitor(AstNetlist* nodep) { iterate(nodep); } + virtual ~LocalizeVisitor() override { V3Stats::addStat("Optimizations, Vars localized", m_statLocVars); } }; diff --git a/src/V3MergeCond.cpp b/src/V3MergeCond.cpp index 2d8d39f36..114898b23 100644 --- a/src/V3MergeCond.cpp +++ b/src/V3MergeCond.cpp @@ -55,7 +55,8 @@ class CheckMergeableVisitor : public AstNVisitor { private: // STATE - bool m_mergeable; // State tracking whether tree being processed is a mergeable condition + bool m_mergeable + = false; // State tracking whether tree being processed is a mergeable condition // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -67,7 +68,7 @@ private: } // VISITORS - virtual void visit(AstNode* nodep) VL_OVERRIDE { + virtual void visit(AstNode* nodep) override { if (!m_mergeable) return; // Clear if node is impure if (!nodep->isPure()) { @@ -76,7 +77,7 @@ private: } iterateChildrenConst(nodep); } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { if (!m_mergeable) return; // Clear if it's an LValue referencing a marked variable if (nodep->lvalue() && nodep->varp()->user1()) { @@ -85,8 +86,7 @@ private: } public: - CheckMergeableVisitor() - : m_mergeable(false) {} + CheckMergeableVisitor() {} // Return false if this node should not be merged at all because: // - It contains an impure expression @@ -104,8 +104,8 @@ private: VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { nodep->varp()->user1(1); } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildrenConst(nodep); } + virtual void visit(AstVarRef* nodep) override { nodep->varp()->user1(1); } + virtual void visit(AstNode* nodep) override { iterateChildrenConst(nodep); } public: // Remove marks from AstVars (clear user1) @@ -126,11 +126,11 @@ private: VDouble0 m_statMergedItems; // Statistic tracking VDouble0 m_statLongestList; // Statistic tracking - AstNode* m_mgFirstp; // First node in merged sequence - AstNode* m_mgCondp; // The condition of the first node - AstNode* m_mgLastp; // Last node in merged sequence - const AstNode* m_mgNextp; // Next node in list being examined - uint32_t m_listLenght; // Length of current list + AstNode* m_mgFirstp = nullptr; // First node in merged sequence + AstNode* m_mgCondp = nullptr; // The condition of the first node + AstNode* m_mgLastp = nullptr; // Last node in merged sequence + const AstNode* m_mgNextp = nullptr; // Next node in list being examined + uint32_t m_listLenght = 0; // Length of current list CheckMergeableVisitor m_checkMergeable; // Sub visitor for encapsulation & speed MarkVarsVisitor m_markVars; // Sub visitor for encapsulation & speed @@ -150,7 +150,7 @@ private: if (VN_IS(andp->lhsp(), Const)) { return condp; } } } - return NULL; + return nullptr; } // Apply (_ & 1'b1). This is necessary because this pass is after V3Clean, @@ -204,7 +204,7 @@ private: // Create equivalent 'if' statement and insert it before the first node AstIf* const ifp - = new AstIf(m_mgCondp->fileline(), m_mgCondp->unlinkFrBack(), NULL, NULL); + = new AstIf(m_mgCondp->fileline(), m_mgCondp->unlinkFrBack(), nullptr, nullptr); m_mgFirstp->replaceWith(ifp); ifp->addNextHere(m_mgFirstp); // Unzip the list and insert under branches @@ -212,7 +212,7 @@ private: do { // Grab next pointer and unlink AstNode* const currp = nextp; - nextp = currp != m_mgLastp ? currp->nextp() : NULL; + nextp = currp != m_mgLastp ? currp->nextp() : nullptr; currp->unlinkFrBack(); // Skip over comments if (VN_IS(currp, Comment)) { @@ -235,10 +235,10 @@ private: } while (nextp); } // Reset state - m_mgFirstp = NULL; - m_mgCondp = NULL; - m_mgLastp = NULL; - m_mgNextp = NULL; + m_mgFirstp = nullptr; + m_mgCondp = nullptr; + m_mgLastp = nullptr; + m_mgNextp = nullptr; m_markVars.clear(); } @@ -264,7 +264,7 @@ private: } // VISITORS - virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { + virtual void visit(AstNodeAssign* nodep) override { AstNode* const rhsp = nodep->rhsp(); if (AstNodeCond* const condp = extractCond(rhsp)) { if (!m_checkMergeable(nodep)) { @@ -292,13 +292,13 @@ private: // Is it a 'lhs = cond & value' or 'lhs = value & cond'? if (AstAnd* const andp = VN_CAST(rhsp, And)) { if (andp->lhsp()->sameTree(m_mgCondp) || andp->rhsp()->sameTree(m_mgCondp)) { - addToList(nodep, NULL); + addToList(nodep, nullptr); return; } } // Is it simply 'lhs = cond'? if (rhsp->sameTree(m_mgCondp)) { - addToList(nodep, NULL); + addToList(nodep, nullptr); return; } } @@ -306,30 +306,25 @@ private: mergeEnd(); } } - virtual void visit(AstComment*) VL_OVERRIDE {} // Skip over comments + virtual void visit(AstComment*) override {} // Skip over comments // For speed, only iterate what is necessary. - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { iterateAndNextNull(nodep->modulesp()); } - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { iterateAndNextNull(nodep->stmtsp()); } - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { iterateAndNextNull(nodep->modulesp()); } + virtual void visit(AstNodeModule* nodep) override { iterateAndNextNull(nodep->stmtsp()); } + virtual void visit(AstCFunc* nodep) override { iterateChildren(nodep); // Close list, if there is one at the end of the function if (m_mgFirstp) mergeEnd(); } - virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE { iterateChildren(nodep); } - virtual void visit(AstNode* nodep) VL_OVERRIDE {} + virtual void visit(AstNodeStmt* nodep) override { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override {} public: // CONSTRUCTORS explicit MergeCondVisitor(AstNetlist* nodep) { - m_mgFirstp = NULL; - m_mgCondp = NULL; - m_mgLastp = NULL; - m_mgNextp = NULL; - m_listLenght = 0; m_markVars.clear(); iterate(nodep); } - virtual ~MergeCondVisitor() { + virtual ~MergeCondVisitor() override { V3Stats::addStat("Optimizations, MergeCond merges", m_statMerges); V3Stats::addStat("Optimizations, MergeCond merged items", m_statMergedItems); V3Stats::addStat("Optimizations, MergeCond longest merge", m_statLongestList); diff --git a/src/V3Name.cpp b/src/V3Name.cpp index d08e1776a..0d5401bf5 100644 --- a/src/V3Name.cpp +++ b/src/V3Name.cpp @@ -40,7 +40,7 @@ private: AstUser1InUse m_inuser1; // STATE - AstNodeModule* m_modp; + AstNodeModule* m_modp = nullptr; // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -67,53 +67,52 @@ 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; } // Add __PVT__ to names of local signals - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { // Don't iterate... Don't need temps for RANGES under the Var. rename(nodep, ((!m_modp || !m_modp->isTop()) && !nodep->isSigPublic() && !nodep->isFuncLocal() // Isn't exposed, and would mess up dpi import wrappers && !nodep->isTemp())); // Don't bother to rename internal signals } - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstCFunc* nodep) override { if (!nodep->user1()) { iterateChildren(nodep); rename(nodep, false); } } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { if (nodep->varp()) { iterate(nodep->varp()); nodep->name(nodep->varp()->name()); } } - virtual void visit(AstCell* nodep) VL_OVERRIDE { + virtual void visit(AstCell* nodep) override { if (!nodep->user1()) { rename(nodep, (!nodep->modp()->modPublic() && !VN_IS(nodep->modp(), ClassPackage))); iterateChildren(nodep); } } - virtual void visit(AstMemberDType* nodep) VL_OVERRIDE { + virtual void visit(AstMemberDType* nodep) override { if (!nodep->user1()) { rename(nodep, false); iterateChildren(nodep); } } - virtual void visit(AstMemberSel* nodep) VL_OVERRIDE { + virtual void visit(AstMemberSel* nodep) override { if (!nodep->user1()) { rename(nodep, false); iterateChildren(nodep); } } - virtual void visit(AstScope* nodep) VL_OVERRIDE { + virtual void visit(AstScope* nodep) override { if (!nodep->user1SetOnce()) { if (nodep->aboveScopep()) iterate(nodep->aboveScopep()); if (nodep->aboveCellp()) iterate(nodep->aboveCellp()); @@ -132,15 +131,12 @@ private: } //-------------------- - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - explicit NameVisitor(AstNetlist* nodep) { - m_modp = NULL; - iterate(nodep); - } - virtual ~NameVisitor() {} + explicit NameVisitor(AstNetlist* nodep) { iterate(nodep); } + virtual ~NameVisitor() override {} }; //###################################################################### diff --git a/src/V3Number.cpp b/src/V3Number.cpp index d684b9ed5..2b4e54494 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -25,7 +25,8 @@ #include #include -#define MAX_SPRINTF_DOUBLE_SIZE 1100 // Maximum characters with a sprintf %e/%f/%g (really 1079) +constexpr int MAX_SPRINTF_DOUBLE_SIZE + = 1100; // Maximum characters with a sprintf %e/%f/%g (really 1079) // Number operations build output in-place so can't call e.g. foo.opX(foo) #define NUM_ASSERT_OP_ARGS1(arg1) \ @@ -567,8 +568,8 @@ string V3Number::displayed(AstNode* nodep, const string& vformat) const { } string V3Number::displayed(FileLine* fl, const string& vformat) const { - string::const_iterator pos = vformat.begin(); - UASSERT(pos != vformat.end() && pos[0] == '%', + auto pos = vformat.cbegin(); + UASSERT(pos != vformat.cend() && pos[0] == '%', "$display-like function with non format argument " << *this); ++pos; bool left = false; @@ -577,7 +578,7 @@ string V3Number::displayed(FileLine* fl, const string& vformat) const { ++pos; } string fmtsize; - for (; pos != vformat.end() && (isdigit(pos[0]) || pos[0] == '.'); ++pos) { + for (; pos != vformat.cend() && (isdigit(pos[0]) || pos[0] == '.'); ++pos) { fmtsize += pos[0]; } string str; @@ -1451,7 +1452,7 @@ V3Number& V3Number::opAtoN(const V3Number& lhs, int base) { str.erase(std::remove(str.begin(), str.end(), '_'), str.end()); errno = 0; - long v = std::strtol(str.c_str(), NULL, base); + auto v = std::strtol(str.c_str(), nullptr, base); if (errno != 0) v = 0; return setLongS(static_cast(v)); } @@ -2160,11 +2161,7 @@ V3Number& V3Number::opExtendXZ(const V3Number& lhs, uint32_t lbits) { NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_LOGIC_ARGS1(lhs); setZero(); - for (int bit = 0; bit < width(); bit++) { - char extendWith = lhs.bitIsExtend(bit, lbits); - if (extendWith == '1' || extendWith == 1) extendWith = 0; - setBit(bit, lhs.bitIsExtend(bit, lbits)); - } + for (int bit = 0; bit < width(); bit++) { setBit(bit, lhs.bitIsExtend(bit, lbits)); } return *this; } @@ -2400,14 +2397,14 @@ V3Number& V3Number::opToLowerN(const V3Number& lhs) { NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_STRING_ARGS1(lhs); std::string out = lhs.toString(); - for (std::string::iterator it = out.begin(); it != out.end(); ++it) { *it = tolower(*it); } + for (auto& cr : out) cr = tolower(cr); return setString(out); } V3Number& V3Number::opToUpperN(const V3Number& lhs) { NUM_ASSERT_OP_ARGS1(lhs); NUM_ASSERT_STRING_ARGS1(lhs); std::string out = lhs.toString(); - for (std::string::iterator it = out.begin(); it != out.end(); ++it) { *it = toupper(*it); } + for (auto& cr : out) cr = toupper(cr); return setString(out); } diff --git a/src/V3Number.h b/src/V3Number.h index 1426cfd6e..e19f4a767 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -164,9 +164,11 @@ public: opCleanThis(); } // Create from a verilog 32'hxxxx number. - V3Number(AstNode* nodep, const char* sourcep) { V3NumberCreate(nodep, sourcep, NULL); } + V3Number(AstNode* nodep, const char* sourcep) { V3NumberCreate(nodep, sourcep, nullptr); } class FileLined {}; // Fileline based errors, for parsing only, otherwise pass nodep - V3Number(FileLined, FileLine* fl, const char* sourcep) { V3NumberCreate(NULL, sourcep, fl); } + V3Number(FileLined, FileLine* fl, const char* sourcep) { + V3NumberCreate(nullptr, sourcep, fl); + } class VerilogStringLiteral {}; // For creator type-overload selection V3Number(VerilogStringLiteral, AstNode* nodep, const string& str); class String {}; @@ -175,11 +177,11 @@ public: setString(value); } explicit V3Number(const V3Number* nump, int width = 1) { - init(NULL, width); + init(nullptr, width); m_fileline = nump->fileline(); } V3Number(const V3Number* nump, int width, uint32_t value) { - init(NULL, width); + init(nullptr, width); m_value[0] = value; opCleanThis(); m_fileline = nump->fileline(); diff --git a/src/V3Options.cpp b/src/V3Options.cpp index f87ba3560..17a63b000 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -53,7 +53,7 @@ class V3OptionsImp { public: // TYPES - typedef std::map > DirMap; // Directory listing + typedef std::map> DirMap; // Directory listing // STATE std::list m_allArgs; // List of every argument encountered @@ -122,7 +122,7 @@ V3LangCode::V3LangCode(const char* textp) { // VTimescale class functions VTimescale::VTimescale(const string& value, bool& badr) - : m_e(VTimescale::NONE) { + : m_e{VTimescale::NONE} { badr = true; string spaceless = VString::removeWhitespace(value); for (int i = TS_100S; i < _ENUM_END; ++i) { @@ -135,6 +135,95 @@ VTimescale::VTimescale(const string& value, bool& badr) } } +//###################################################################### +// V3HierarchicalBlockOption class functions + +// Parse "--hierarchical-block orig_name,mangled_name,param0_name,param0_value,... " option. +// The format of value is as same as -G option. (can be string literal surrounded by ") +V3HierarchicalBlockOption::V3HierarchicalBlockOption(const string& opts) { + V3StringList vals; + bool inStr = false; + string cur; + static const string hierBlock("--hierarchical-block"); + FileLine cmdfl(FileLine::commandLineFilename()); + // Split by ','. If ',' appears between "", that is not a separator. + for (string::const_iterator it = opts.begin(); it != opts.end();) { + if (inStr) { + if (*it == '\\') { + ++it; + if (it == opts.end()) { + cmdfl.v3error(hierBlock + " must not end with \\"); + break; + } + if (*it != '"' && *it != '\\') { + cmdfl.v3error(hierBlock + " does not allow '" + *it + "' after \\"); + break; + } + cur.push_back(*it); + ++it; + } else if (*it == '"') { // end of string + cur.push_back(*it); + vals.push_back(cur); + cur.clear(); + ++it; + if (it != opts.end()) { + if (*it != ',') { + cmdfl.v3error(hierBlock + " expects ',', but '" + *it + "' is passed"); + break; + } + ++it; + if (it == opts.end()) { + cmdfl.v3error(hierBlock + " must not end with ','"); + break; + } + inStr = *it == '"'; + cur.push_back(*it); + ++it; + } + } else { + cur.push_back(*it); + ++it; + } + } else { + if (*it == '"') { + cmdfl.v3error(hierBlock + " does not allow '\"' in the middle of literal"); + break; + } + if (*it == ',') { // end of this parameter + vals.push_back(cur); + cur.clear(); + ++it; + if (it == opts.end()) { + cmdfl.v3error(hierBlock + " must not end with ','"); + break; + } + inStr = *it == '"'; + } + cur.push_back(*it); + ++it; + } + } + if (!cur.empty()) vals.push_back(cur); + if (vals.size() >= 2) { + if (vals.size() % 2) { + cmdfl.v3error(hierBlock + " requires the number of entries to be even"); + } + m_origName = vals[0]; + m_mangledName = vals[1]; + } else { + cmdfl.v3error(hierBlock + " requires at least two comma-separated values"); + } + for (size_t i = 2; i + 1 < vals.size(); i += 2) { + const bool inserted = m_parameters.insert(std::make_pair(vals[i], vals[i + 1])).second; + if (!inserted) { + cmdfl.v3error("Module name '" + vals[i] + "' is duplicated in " + hierBlock); + } + } +} + +//###################################################################### +// V3Options class functions + void VTimescale::parseSlashed(FileLine* fl, const char* textp, VTimescale& unitr, VTimescale& precr, bool allowEmpty) { // Parse `timescale of / @@ -296,10 +385,45 @@ void V3Options::addArg(const string& arg) { m_impp->m_allArgs.push_back(arg); } string V3Options::allArgsString() const { string out; + for (const string& i : m_impp->m_allArgs) { + if (out != "") out += " "; + out += i; + } + return out; +} + +// Delete some options for Verilation of the hierarchical blocks. +string V3Options::allArgsStringForHierBlock(bool forTop) const { + std::set vFiles; + for (V3StringList::const_iterator it = m_vFiles.begin(); it != m_vFiles.end(); ++it) + vFiles.insert(*it); + string out; for (std::list::const_iterator it = m_impp->m_allArgs.begin(); it != m_impp->m_allArgs.end(); ++it) { + int skip = 0; + if (it->length() >= 2 && (*it)[0] == '-' && (*it)[1] == '-') { + skip = 2; + } else if (it->length() >= 1 && (*it)[0] == '-') { + skip = 1; + } + if (skip > 0) { // *it is an option + const string opt = it->substr(skip); // Remove '-' in the beginning + const int numStrip = stripOptionsForChildRun(opt, forTop); + if (numStrip) { + UASSERT(0 <= numStrip && numStrip <= 2, "should be one of 0, 1, 2"); + if (numStrip == 2) ++it; + continue; + } + } else { // Not an option + if (vFiles.find(*it) != vFiles.end() // Remove HDL + || m_cppFiles.find(*it) != m_cppFiles.end()) { // Remove C++ + continue; + } + } if (out != "") out += " "; - out += *it; + // Don't use opt here because '-' is removed in it + // Use double quote because *it may contain whitespaces + out += '"' + VString::quoteAny(*it, '"', '\\') + '"'; } return out; } @@ -344,7 +468,7 @@ string V3Options::fileExists(const string& filename) { string dir = V3Os::filenameDir(filename); string basename = V3Os::filenameNonDir(filename); - V3OptionsImp::DirMap::iterator diriter = m_impp->m_dirMap.find(dir); + auto diriter = m_impp->m_dirMap.find(dir); if (diriter == m_impp->m_dirMap.end()) { // Read the listing m_impp->m_dirMap.insert(std::make_pair(dir, std::set())); @@ -359,7 +483,7 @@ string V3Options::fileExists(const string& filename) { } // Find it std::set* filesetp = &(diriter->second); - std::set::iterator fileiter = filesetp->find(basename); + const auto fileiter = filesetp->find(basename); if (fileiter == filesetp->end()) { return ""; // Not found } @@ -370,9 +494,8 @@ string V3Options::fileExists(const string& filename) { } string V3Options::filePathCheckOneDir(const string& modname, const string& dirname) { - for (std::list::iterator extIter = m_impp->m_libExtVs.begin(); - extIter != m_impp->m_libExtVs.end(); ++extIter) { - string fn = V3Os::filenameFromDirBase(dirname, modname + *extIter); + for (const string& i : m_impp->m_libExtVs) { + string fn = V3Os::filenameFromDirBase(dirname, modname + i); string exists = fileExists(fn); if (exists != "") { // Strip ./, it just looks ugly @@ -383,19 +506,34 @@ string V3Options::filePathCheckOneDir(const string& modname, const string& dirna return ""; } +// Checks if a option needs to be stripped for child run of hierarchical Verilation. +// 0: Keep the option including its argument +// 1: Delete the option which has no argument +// 2: Delete the option and its argument +int V3Options::stripOptionsForChildRun(const string& opt, bool forTop) const { + if (opt == "Mdir" || opt == "clk" || opt == "f" || opt == "j" || opt == "l2-name" + || opt == "mod-prefix" || opt == "prefix" || opt == "protect-lib" || opt == "protect-key" + || opt == "top-module" || opt == "v") { + return 2; + } + if (opt == "build" || (!forTop && (opt == "cc" || opt == "exe" || opt == "sc")) + || opt == "hierarchical" || (opt.length() > 2 && opt.substr(0, 2) == "G=")) { + return 1; + } + return 0; +} + string V3Options::filePath(FileLine* fl, const string& modname, const string& lastpath, const string& errmsg) { // Error prefix or "" to suppress error // Find a filename to read the specified module name, // using the incdir and libext's. // Return "" if not found. - for (std::list::iterator dirIter = m_impp->m_incDirUsers.begin(); - dirIter != m_impp->m_incDirUsers.end(); ++dirIter) { - string exists = filePathCheckOneDir(modname, *dirIter); + for (const string& dir : m_impp->m_incDirUsers) { + string exists = filePathCheckOneDir(modname, dir); if (exists != "") return exists; } - for (std::list::iterator dirIter = m_impp->m_incDirFallbacks.begin(); - dirIter != m_impp->m_incDirFallbacks.end(); ++dirIter) { - string exists = filePathCheckOneDir(modname, *dirIter); + for (const string& dir : m_impp->m_incDirFallbacks) { + string exists = filePathCheckOneDir(modname, dir); if (exists != "") return exists; } @@ -426,19 +564,15 @@ void V3Options::filePathLookedMsg(FileLine* fl, const string& modname) { << endl); } std::cerr << V3Error::warnMore() << "... Looked in:" << endl; - for (std::list::iterator dirIter = m_impp->m_incDirUsers.begin(); - dirIter != m_impp->m_incDirUsers.end(); ++dirIter) { - for (std::list::iterator extIter = m_impp->m_libExtVs.begin(); - extIter != m_impp->m_libExtVs.end(); ++extIter) { - string fn = V3Os::filenameFromDirBase(*dirIter, modname + *extIter); + for (const string& dir : m_impp->m_incDirUsers) { + for (const string& ext : m_impp->m_libExtVs) { + string fn = V3Os::filenameFromDirBase(dir, modname + ext); std::cerr << V3Error::warnMore() << " " << fn << endl; } } - for (std::list::iterator dirIter = m_impp->m_incDirFallbacks.begin(); - dirIter != m_impp->m_incDirFallbacks.end(); ++dirIter) { - for (std::list::iterator extIter = m_impp->m_libExtVs.begin(); - extIter != m_impp->m_libExtVs.end(); ++extIter) { - string fn = V3Os::filenameFromDirBase(*dirIter, modname + *extIter); + for (const string& dir : m_impp->m_incDirFallbacks) { + for (const string& ext : m_impp->m_libExtVs) { + string fn = V3Os::filenameFromDirBase(dir, modname + ext); std::cerr << V3Error::warnMore() << " " << fn << endl; } } @@ -454,7 +588,7 @@ V3LangCode V3Options::fileLanguage(const string& filename) { string::size_type pos; if ((pos = ext.rfind('.')) != string::npos) { ext.erase(0, pos + 1); - std::map::iterator it = m_impp->m_langExts.find(ext); + const auto it = m_impp->m_langExts.find(ext); if (it != m_impp->m_langExts.end()) return it->second; } return m_defaultLanguage; @@ -599,6 +733,19 @@ void V3Options::notify() { // Make sure at least one make system is enabled if (!m_gmake && !m_cmake) m_gmake = true; + if (m_hierarchical && (m_hierChild || !m_hierBlocks.empty())) { + cmdfl->v3error( + "--hierarchical must not be set with --hierarchical-child or --hierarchical-block"); + } + if (m_hierChild && m_hierBlocks.empty()) { + cmdfl->v3error("--hierarchical-block must be set when --hierarchical-child is set"); + } + if (m_hierarchical && m_protectLib.empty() && m_protectKey.empty()) { + // Key for hierarchical Verilation is fixed to be ccache friendly when the aim of this run + // is not to create protec-lib. + m_protectKey = "VL-KEY-HIERARCHICAL"; + } + if (protectIds()) { if (allPublic()) { // We always call protect() on names, we don't check if public or not @@ -672,7 +819,7 @@ string V3Options::protectKeyDefaulted() { void V3Options::throwSigsegv() { // LCOV_EXCL_START #if !(defined(VL_CPPCHECK) || defined(__clang_analyzer__)) // clang-format off - { char* zp = NULL; *zp = 0; } // Intentional core dump, ignore warnings here + { char* zp = nullptr; *zp = 0; } // Intentional core dump, ignore warnings here // clang-format on #endif } // LCOV_EXCL_STOP @@ -868,6 +1015,8 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char m_debugCollision = flag; } else if (onoff(sw, "-debug-exit-parse", flag /*ref*/)) { // Undocumented m_debugExitParse = flag; + } else if (onoff(sw, "-debug-exit-uvm", flag /*ref*/)) { // Undocumented + m_debugExitUvm = flag; } else if (onoff(sw, "-debug-leak", flag /*ref*/)) { m_debugLeak = flag; } else if (onoff(sw, "-debug-nondeterminism", flag /*ref*/)) { @@ -896,6 +1045,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char m_exe = flag; } else if (onoff(sw, "-flatten", flag /*ref*/)) { m_flatten = flag; + } else if (onoff(sw, "-hierarchical", flag /*ref*/)) { + m_hierarchical = flag; + } else if (onoff(sw, "-hierarchical-child", flag /*ref*/)) { + m_hierChild = flag; } else if (onoff(sw, "-ignc", flag /*ref*/)) { m_ignc = flag; } else if (onoff(sw, "-inhibit-sim", flag /*ref*/)) { @@ -1081,6 +1234,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char shift; cout << V3Options::getenvBuiltins(argv[i]) << endl; exit(0); + } else if (!strcmp(sw, "-hierarchical-block") && (i + 1) < argc) { + shift; + V3HierarchicalBlockOption opt(argv[i]); + m_hierBlocks.insert(std::make_pair(opt.mangledName(), opt)); } else if (!strncmp(sw, "-I", 2)) { addIncDirUser(parseFileArg(optdir, string(sw + strlen("-I")))); } else if (!strcmp(sw, "-if-depth") && (i + 1) < argc) { @@ -1423,7 +1580,7 @@ void V3Options::parseOptsFile(FileLine* fl, const string& filename, bool rel) { // Read the specified -f filename and process as arguments UINFO(1, "Reading Options File " << filename << endl); - const vl_unique_ptr ifp(V3File::new_ifstream(filename)); + const std::unique_ptr ifp(V3File::new_ifstream(filename)); if (ifp->fail()) { fl->v3error("Cannot open -f command file: " + filename); return; @@ -1469,7 +1626,12 @@ void V3Options::parseOptsFile(FileLine* fl, const string& filename, bool rel) { std::vector args; // Parse file using a state machine, taking into account quoted strings and escaped chars - enum state { ST_IN_OPTION, ST_ESCAPED_CHAR, ST_IN_QUOTED_STR, ST_IN_DOUBLE_QUOTED_STR }; + enum state : uint8_t { + ST_IN_OPTION, + ST_ESCAPED_CHAR, + ST_IN_QUOTED_STR, + ST_IN_DOUBLE_QUOTED_STR + }; state st = ST_IN_OPTION; state last_st = ST_IN_OPTION; @@ -1545,10 +1707,8 @@ void V3Options::parseOptsFile(FileLine* fl, const string& filename, bool rel) { // Convert to argv style arg list and parse them std::vector argv; argv.reserve(args.size() + 1); - for (std::vector::const_iterator it = args.begin(); it != args.end(); ++it) { - argv.push_back(const_cast(it->c_str())); - } - argv.push_back(NULL); // argv is NULL-terminated + for (const string& i : args) argv.push_back(const_cast(i.c_str())); + argv.push_back(nullptr); // argv is nullptr-terminated parseOptsList(fl, optdir, static_cast(argv.size() - 1), argv.data()); } @@ -1623,106 +1783,9 @@ void V3Options::showVersion(bool verbose) { V3Options::V3Options() { m_impp = new V3OptionsImp; - m_assert = false; - m_autoflush = false; - m_bboxSys = false; - m_bboxUnsup = false; - m_build = false; - m_cdc = false; - m_cmake = false; - m_context = true; - m_coverageLine = false; - m_coverageToggle = false; - m_coverageUnderscore = false; - m_coverageUser = false; - m_debugCheck = false; - m_debugCollision = false; - m_debugExitParse = false; - m_debugLeak = true; - m_debugNondeterminism = false; - m_debugPartition = false; - m_debugProtect = false; - m_debugSelfTest = false; - m_decoration = true; - m_dpiHdrOnly = false; - m_dumpDefines = false; - m_exe = false; - m_flatten = false; - m_ignc = false; - m_inhibitSim = false; - m_lintOnly = false; - m_gmake = false; - m_makePhony = false; - m_main = false; - m_orderClockDly = true; - m_outFormatOk = false; - m_pedantic = false; - m_pinsBv = 65; - m_pinsScUint = false; - m_pinsScBigUint = false; - m_pinsUint8 = false; - m_ppComments = false; - m_profCFuncs = false; - m_profThreads = false; - m_protectIds = false; - m_preprocOnly = false; - m_preprocNoLine = false; - m_public = false; - m_publicFlatRW = false; - m_quietExit = false; - m_relativeCFuncs = true; - m_relativeIncludes = false; - m_reportUnoptflat = false; - m_savable = false; - m_stats = false; - m_statsVars = false; - m_structsPacked = true; - m_systemC = false; - m_threads = 0; - m_threadsDpiPure = true; - m_threadsDpiUnpure = false; - m_threadsCoarsen = true; - m_threadsMaxMTasks = 0; - m_trace = false; - m_traceCoverage = false; m_traceFormat = TraceFormat::VCD; - m_traceParams = true; - m_traceStructs = false; - m_traceUnderscore = false; - m_traceThreads = 0; - m_underlineZero = false; - m_verilate = true; - m_vpi = false; - m_xInitialEdge = false; - m_xmlOnly = false; - - m_buildJobs = 1; - m_convergeLimit = 100; - m_dumpTree = 0; - m_dumpTreeAddrids = false; - m_gateStmts = 100; - m_ifDepth = 0; - m_inlineMult = 2000; - m_maxNumWidth = 65536; - m_moduleRecursion = 100; - m_outputSplit = 20000; - m_outputSplitCFuncs = -1; - m_outputSplitCTrace = -1; - m_traceDepth = 0; - m_traceMaxArray = 32; - m_traceMaxWidth = 256; - m_unrollCount = 64; - m_unrollStmts = 30000; - - m_compLimitBlocks = 0; - m_compLimitMembers = 64; - m_compLimitParens = 0; m_makeDir = "obj_dir"; - m_bin = ""; - m_flags = ""; - m_waiverOutput = ""; - m_l2Name = ""; m_unusedRegexp = "*unused*"; m_xAssign = "fast"; @@ -1739,7 +1802,7 @@ V3Options::V3Options() { addIncDirFallback("."); // Looks better than {long_cwd_path}/... } -V3Options::~V3Options() { VL_DO_CLEAR(delete m_impp, m_impp = NULL); } +V3Options::~V3Options() { VL_DO_CLEAR(delete m_impp, m_impp = nullptr); } void V3Options::setDebugMode(int level) { V3Error::debugDefault(level); @@ -1750,7 +1813,7 @@ void V3Options::setDebugMode(int level) { } void V3Options::setDebugSrcLevel(const string& srcfile, int level) { - DebugSrcMap::iterator iter = m_debugSrcs.find(srcfile); + const auto iter = m_debugSrcs.find(srcfile); if (iter != m_debugSrcs.end()) { iter->second = level; } else { @@ -1762,7 +1825,7 @@ int V3Options::debugSrcLevel(const string& srcfile_path, int default_level) { // For simplicity, calling functions can just use __FILE__ for srcfile. // That means though we need to cleanup the filename from ../Foo.cpp -> Foo string srcfile = V3Os::filenameNonDirExt(srcfile_path); - DebugSrcMap::iterator iter = m_debugSrcs.find(srcfile); + const auto iter = m_debugSrcs.find(srcfile); if (iter != m_debugSrcs.end()) { return iter->second; } else { @@ -1771,7 +1834,7 @@ int V3Options::debugSrcLevel(const string& srcfile_path, int default_level) { } void V3Options::setDumpTreeLevel(const string& srcfile, int level) { - DebugSrcMap::iterator iter = m_dumpTrees.find(srcfile); + const auto iter = m_dumpTrees.find(srcfile); if (iter != m_dumpTrees.end()) { iter->second = level; } else { @@ -1783,7 +1846,7 @@ int V3Options::dumpTreeLevel(const string& srcfile_path) { // For simplicity, calling functions can just use __FILE__ for srcfile. // That means though we need to cleanup the filename from ../Foo.cpp -> Foo string srcfile = V3Os::filenameNonDirExt(srcfile_path); - DebugSrcMap::iterator iter = m_dumpTrees.find(srcfile); + const auto iter = m_dumpTrees.find(srcfile); if (iter != m_dumpTrees.end()) { return iter->second; } else { diff --git a/src/V3Options.h b/src/V3Options.h index 0c3830bcf..d8a0f17b7 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -37,15 +37,15 @@ class VOptionBool { // Class to track options that are either not specified (and default // true/false), versus user setting the option to true or false public: - enum en { OPT_DEFAULT_FALSE = 0, OPT_DEFAULT_TRUE, OPT_TRUE, OPT_FALSE, _ENUM_END }; + enum en : uint8_t { OPT_DEFAULT_FALSE = 0, OPT_DEFAULT_TRUE, OPT_TRUE, OPT_FALSE, _ENUM_END }; enum en m_e; inline VOptionBool() - : m_e(OPT_DEFAULT_FALSE) {} + : m_e{OPT_DEFAULT_FALSE} {} // cppcheck-suppress noExplicitConstructor inline VOptionBool(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline VOptionBool(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } bool isDefault() const { return m_e == OPT_DEFAULT_FALSE || m_e == OPT_DEFAULT_TRUE; } bool isTrue() const { return m_e == OPT_TRUE || m_e == OPT_DEFAULT_TRUE; } @@ -71,7 +71,7 @@ inline std::ostream& operator<<(std::ostream& os, const VOptionBool& rhs) { class VTimescale { public: - enum en { + enum en : uint8_t { // clang-format off TS_100S = 0, TS_10S = 1, TS_1S = 2, TS_100MS = 3, TS_10MS = 4, TS_1MS = 5, @@ -83,16 +83,16 @@ public: NONE = 18, _ENUM_END }; - enum { TS_DEFAULT = TS_1PS }; + enum : uint8_t { TS_DEFAULT = TS_1PS }; enum en m_e; // CONSTRUCTOR inline VTimescale() - : m_e(NONE) {} + : m_e{NONE} {} // cppcheck-suppress noExplicitConstructor inline VTimescale(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline VTimescale(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning // Construct from string VTimescale(const string& value, bool& badr); VTimescale(double value, bool& badr) { @@ -169,12 +169,12 @@ inline std::ostream& operator<<(std::ostream& os, const VTimescale& rhs) { class TraceFormat { public: - enum en { VCD = 0, FST } m_e; + enum en : uint8_t { VCD = 0, FST } m_e; // cppcheck-suppress noExplicitConstructor inline TraceFormat(en _e = VCD) - : m_e(_e) {} + : m_e{_e} {} explicit inline TraceFormat(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } bool fst() const { return m_e == FST; } string classBase() const { @@ -195,6 +195,31 @@ inline bool operator==(TraceFormat::en lhs, const TraceFormat& rhs) { return lhs typedef std::vector V3StringList; typedef std::set V3StringSet; +//###################################################################### + +// Information given by --hierarchical-block option +class V3HierarchicalBlockOption { +public: + // key:parameter name, value:value (as string) + typedef std::map ParamStrMap; + +private: + string m_origName; // module name + // module name after uniquified + // same as m_origName for non-parameterized module + string m_mangledName; + // overriding parameter values specified by -G option + ParamStrMap m_parameters; + +public: + explicit V3HierarchicalBlockOption(const string& optstring); + const string& origName() const { return m_origName; } + const string& mangledName() const { return m_mangledName; } + const ParamStrMap params() const { return m_parameters; } +}; + +typedef std::map V3HierBlockOptSet; + //###################################################################### // V3Options - Command line options @@ -221,107 +246,111 @@ private: DebugSrcMap m_debugSrcs; // argument: --debugi-= DebugSrcMap m_dumpTrees; // argument: --dump-treei-= std::map m_parameters; // Parameters + std::map m_hierBlocks; // main switch: --hierarchical-block - bool m_preprocOnly; // main switch: -E - bool m_makePhony; // main switch: -MP - bool m_preprocNoLine;// main switch: -P - bool m_assert; // main switch: --assert - bool m_autoflush; // main switch: --autoflush - bool m_bboxSys; // main switch: --bbox-sys - bool m_bboxUnsup; // main switch: --bbox-unsup - bool m_build; // main switch: --build - bool m_cdc; // main switch: --cdc - bool m_cmake; // main switch: --make cmake - bool m_context; // main switch: --Wcontext - bool m_coverageLine; // main switch: --coverage-block - bool m_coverageToggle;// main switch: --coverage-toggle - bool m_coverageUnderscore;// main switch: --coverage-underscore - bool m_coverageUser; // main switch: --coverage-func - bool m_debugCheck; // main switch: --debug-check - bool m_debugCollision; // main switch: --debug-collision - bool m_debugExitParse; // main switch: --debug-exit-parse - bool m_debugLeak; // main switch: --debug-leak - bool m_debugNondeterminism; // main switch: --debug-nondeterminism - bool m_debugPartition; // main switch: --debug-partition - bool m_debugProtect; // main switch: --debug-protect - bool m_debugSelfTest; // main switch: --debug-self-test - bool m_decoration; // main switch: --decoration - bool m_dpiHdrOnly; // main switch: --dpi-hdr-only - bool m_dumpDefines; // main switch: --dump-defines - bool m_exe; // main switch: --exe - bool m_flatten; // main switch: --flatten - bool m_ignc; // main switch: --ignc - bool m_inhibitSim; // main switch: --inhibit-sim - bool m_lintOnly; // main switch: --lint-only - bool m_gmake; // main switch: --make gmake - bool m_main; // main swithc: --main - bool m_orderClockDly;// main switch: --order-clock-delay - bool m_outFormatOk; // main switch: --cc, --sc or --sp was specified - bool m_pedantic; // main switch: --Wpedantic - bool m_pinsScUint; // main switch: --pins-sc-uint - bool m_pinsScBigUint;// main switch: --pins-sc-biguint - bool m_pinsUint8; // main switch: --pins-uint8 - bool m_ppComments; // main switch: --pp-comments - bool m_profCFuncs; // main switch: --prof-cfuncs - bool m_profThreads; // main switch: --prof-threads - bool m_protectIds; // main switch: --protect-ids - bool m_public; // main switch: --public - bool m_publicFlatRW; // main switch: --public-flat-rw - bool m_quietExit; // main switch: --quiet-exit - bool m_relativeCFuncs; // main switch: --relative-cfuncs - bool m_relativeIncludes; // main switch: --relative-includes - bool m_reportUnoptflat; // main switch: --report-unoptflat - bool m_savable; // main switch: --savable - bool m_structsPacked; // main switch: --structs-packed - bool m_systemC; // main switch: --sc: System C instead of simple C++ - bool m_stats; // main switch: --stats - bool m_statsVars; // main switch: --stats-vars - bool m_threadsCoarsen; // main switch: --threads-coarsen - bool m_threadsDpiPure; // main switch: --threads-dpi all/pure - bool m_threadsDpiUnpure; // main switch: --threads-dpi all - bool m_trace; // main switch: --trace - bool m_traceCoverage; // main switch: --trace-coverage - bool m_traceParams; // main switch: --trace-params - bool m_traceStructs; // main switch: --trace-structs - bool m_traceUnderscore;// main switch: --trace-underscore - bool m_underlineZero;// main switch: --underline-zero; undocumented old Verilator 2 - bool m_verilate; // main swith: --verilate - bool m_vpi; // main switch: --vpi - bool m_xInitialEdge; // main switch: --x-initial-edge - bool m_xmlOnly; // main switch: --xml-only + bool m_preprocOnly = false; // main switch: -E + bool m_makePhony = false; // main switch: -MP + bool m_preprocNoLine = false; // main switch: -P + bool m_assert = false; // main switch: --assert + bool m_autoflush = false; // main switch: --autoflush + bool m_bboxSys = false; // main switch: --bbox-sys + bool m_bboxUnsup = false; // main switch: --bbox-unsup + bool m_build = false; // main switch: --build + bool m_cdc = false; // main switch: --cdc + bool m_cmake = false; // main switch: --make cmake + bool m_context = true; // main switch: --Wcontext + bool m_coverageLine = false; // main switch: --coverage-block + bool m_coverageToggle = false; // main switch: --coverage-toggle + bool m_coverageUnderscore = false; // main switch: --coverage-underscore + bool m_coverageUser = false; // main switch: --coverage-func + bool m_debugCheck = false; // main switch: --debug-check + bool m_debugCollision = false; // main switch: --debug-collision + bool m_debugExitParse = false; // main switch: --debug-exit-parse + bool m_debugExitUvm = false; // main switch: --debug-exit-uvm + bool m_debugLeak = true; // main switch: --debug-leak + bool m_debugNondeterminism = false; // main switch: --debug-nondeterminism + bool m_debugPartition = false; // main switch: --debug-partition + bool m_debugProtect = false; // main switch: --debug-protect + bool m_debugSelfTest = false; // main switch: --debug-self-test + bool m_decoration = true; // main switch: --decoration + bool m_dpiHdrOnly = false; // main switch: --dpi-hdr-only + bool m_dumpDefines = false; // main switch: --dump-defines + bool m_dumpTreeAddrids = false; // main switch: --dump-tree-addrids + bool m_exe = false; // main switch: --exe + bool m_flatten = false; // main switch: --flatten + bool m_hierarchical = false; // main switch: --hierarchical + bool m_hierChild = false; // main switch: --hierarchical-child + bool m_ignc = false; // main switch: --ignc + bool m_inhibitSim = false; // main switch: --inhibit-sim + bool m_lintOnly = false; // main switch: --lint-only + bool m_gmake = false; // main switch: --make gmake + bool m_main = false; // main swithc: --main + bool m_orderClockDly = true; // main switch: --order-clock-delay + bool m_outFormatOk = false; // main switch: --cc, --sc or --sp was specified + bool m_pedantic = false; // main switch: --Wpedantic + bool m_pinsScUint = false; // main switch: --pins-sc-uint + bool m_pinsScBigUint = false; // main switch: --pins-sc-biguint + bool m_pinsUint8 = false; // main switch: --pins-uint8 + bool m_ppComments = false; // main switch: --pp-comments + bool m_profCFuncs = false; // main switch: --prof-cfuncs + bool m_profThreads = false; // main switch: --prof-threads + bool m_protectIds = false; // main switch: --protect-ids + bool m_public = false; // main switch: --public + bool m_publicFlatRW = false; // main switch: --public-flat-rw + bool m_quietExit = false; // main switch: --quiet-exit + bool m_relativeCFuncs = true; // main switch: --relative-cfuncs + bool m_relativeIncludes = false; // main switch: --relative-includes + bool m_reportUnoptflat = false; // main switch: --report-unoptflat + bool m_savable = false; // main switch: --savable + bool m_structsPacked = true; // main switch: --structs-packed + bool m_systemC = false; // main switch: --sc: System C instead of simple C++ + bool m_stats = false; // main switch: --stats + bool m_statsVars = false; // main switch: --stats-vars + bool m_threadsCoarsen = true; // main switch: --threads-coarsen + bool m_threadsDpiPure = true; // main switch: --threads-dpi all/pure + bool m_threadsDpiUnpure = false; // main switch: --threads-dpi all + bool m_trace = false; // main switch: --trace + bool m_traceCoverage = false; // main switch: --trace-coverage + bool m_traceParams = true; // main switch: --trace-params + bool m_traceStructs = false; // main switch: --trace-structs + bool m_traceUnderscore = false; // main switch: --trace-underscore + bool m_underlineZero = false; // main switch: --underline-zero; undocumented old Verilator 2 + bool m_verilate = true; // main swith: --verilate + bool m_vpi = false; // main switch: --vpi + bool m_xInitialEdge = false; // main switch: --x-initial-edge + bool m_xmlOnly = false; // main switch: --xml-only - int m_buildJobs; // main switch: -j - int m_convergeLimit;// main switch: --converge-limit - int m_dumpTree; // main switch: --dump-tree - bool m_dumpTreeAddrids;// main switch: --dump-tree-addrids - int m_gateStmts; // main switch: --gate-stmts - int m_ifDepth; // main switch: --if-depth - int m_inlineMult; // main switch: --inline-mult + int m_buildJobs = 1; // main switch: -j + int m_convergeLimit = 100; // main switch: --converge-limit + int m_dumpTree = 0; // main switch: --dump-tree + int m_gateStmts = 100; // main switch: --gate-stmts + int m_ifDepth = 0; // main switch: --if-depth + int m_inlineMult = 2000; // main switch: --inline-mult VOptionBool m_makeDepend; // main switch: -MMD - int m_maxNumWidth; // main switch: --max-num-width - int m_moduleRecursion;// main switch: --module-recursion-depth - int m_outputSplit; // main switch: --output-split - int m_outputSplitCFuncs;// main switch: --output-split-cfuncs - int m_outputSplitCTrace;// main switch: --output-split-ctrace - int m_pinsBv; // main switch: --pins-bv + int m_maxNumWidth = 65536; // main switch: --max-num-width + int m_moduleRecursion = 100; // main switch: --module-recursion-depth + int m_outputSplit = 20000; // main switch: --output-split + int m_outputSplitCFuncs = -1; // main switch: --output-split-cfuncs + int m_outputSplitCTrace = -1; // main switch: --output-split-ctrace + int m_pinsBv = 65; // main switch: --pins-bv VOptionBool m_skipIdentical; // main switch: --skip-identical - int m_threads; // main switch: --threads (0 == --no-threads) - int m_threadsMaxMTasks; // main switch: --threads-max-mtasks + int m_threads = 0; // main switch: --threads (0 == --no-threads) + int m_threadsMaxMTasks = 0; // main switch: --threads-max-mtasks VTimescale m_timeDefaultPrec; // main switch: --timescale VTimescale m_timeDefaultUnit; // main switch: --timescale VTimescale m_timeOverridePrec; // main switch: --timescale-override VTimescale m_timeOverrideUnit; // main switch: --timescale-override - int m_traceDepth; // main switch: --trace-depth + int m_traceDepth = 0; // main switch: --trace-depth TraceFormat m_traceFormat; // main switch: --trace or --trace-fst - int m_traceMaxArray;// main switch: --trace-max-array - int m_traceMaxWidth;// main switch: --trace-max-width - int m_traceThreads; // main switch: --trace-threads - int m_unrollCount; // main switch: --unroll-count - int m_unrollStmts; // main switch: --unroll-stmts + int m_traceMaxArray = 32; // main switch: --trace-max-array + int m_traceMaxWidth = 256; // main switch: --trace-max-width + int m_traceThreads = 0; // main switch: --trace-threads + int m_unrollCount = 64; // main switch: --unroll-count + int m_unrollStmts = 30000; // main switch: --unroll-stmts - int m_compLimitBlocks; // compiler selection; number of nested blocks - int m_compLimitMembers; // compiler selection; number of members in struct before make anon array - int m_compLimitParens; // compiler selection; number of nested parens + int m_compLimitBlocks = 0; // compiler selection; number of nested blocks + int m_compLimitMembers = 64; // compiler selection; number of members in struct before make anon array + int m_compLimitParens = 0; // compiler selection; number of nested parens string m_bin; // main switch: --bin {binary} string m_exeName; // main switch: -o {name} @@ -386,6 +415,7 @@ private: string parseFileArg(const string& optdir, const string& relfilename); bool parseLangExt(const char* swp, const char* langswp, const V3LangCode& lc); string filePathCheckOneDir(const string& modname, const string& dirname); + int stripOptionsForChildRun(const string& opt, bool forTop) const; // CONSTRUCTORS VL_UNCOPYABLE(V3Options); @@ -440,6 +470,7 @@ public: bool debugCheck() const { return m_debugCheck; } bool debugCollision() const { return m_debugCollision; } bool debugExitParse() const { return m_debugExitParse; } + bool debugExitUvm() const { return m_debugExitUvm; } bool debugLeak() const { return m_debugLeak; } bool debugNondeterminism() const { return m_debugNondeterminism; } bool debugPartition() const { return m_debugPartition; } @@ -595,10 +626,23 @@ public: return m_traceFormat.sourceName() + (systemC() ? "_sc" : "_c"); } + bool hierarchical() const { return m_hierarchical; } + bool hierChild() const { return m_hierChild; } + bool hierTop() const { return !m_hierChild && !m_hierBlocks.empty(); } + const V3HierBlockOptSet& hierBlocks() const { return m_hierBlocks; } + // Directory to save .tree, .dot, .dat, .vpp for hierarchical block top + // Returns makeDir() unless top module of hierarchical verilation. + string hierTopDataDir() const { + return hierTop() ? (makeDir() + '/' + prefix() + "__hier.dir") : makeDir(); + } + // METHODS (from main) static string version(); static string argString(int argc, char** argv); ///< Return list of arguments as simple string string allArgsString() const; ///< Return all passed arguments as simple string + // Return options for child hierarchical blocks when forTop==false, otherwise returns args for + // the top module. + string allArgsStringForHierBlock(bool forTop) const; void bin(const string& flag) { m_bin = flag; } void parseOpts(FileLine* fl, int argc, char** argv); void parseOptsList(FileLine* fl, const string& optdir, int argc, char** argv); diff --git a/src/V3Order.cpp b/src/V3Order.cpp index 62f273d42..b641e48e5 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -100,8 +100,8 @@ #include #include #include -#include VL_INCLUDE_UNORDERED_MAP -#include VL_INCLUDE_UNORDERED_SET +#include +#include static bool domainsExclusive(const AstSenTree* fromp, const AstSenTree* top); @@ -128,7 +128,7 @@ public: V3ListEnt m_readyDomScopeE; // List of next ready dom scope V3List m_readyVertices; // Ready vertices with same domain & scope private: - bool m_onReadyList; // True if DomScope is already on list of ready dom/scopes + bool m_onReadyList = false; // True if DomScope is already on list of ready dom/scopes const AstSenTree* m_domainp; // Domain all vertices belong to const AstScope* m_scopep; // Scope all vertices belong to @@ -138,9 +138,8 @@ private: public: OrderMoveDomScope(const AstSenTree* domainp, const AstScope* scopep) - : m_onReadyList(false) - , m_domainp(domainp) - , m_scopep(scopep) {} + : m_domainp{domainp} + , m_scopep{scopep} {} OrderMoveDomScope* readyDomScopeNextp() const { return m_readyDomScopeE.nextp(); } const AstSenTree* domainp() const { return m_domainp; } const AstScope* scopep() const { return m_scopep; } @@ -158,7 +157,7 @@ public: V3List& readyVertices() { return m_readyVertices; } static OrderMoveDomScope* findCreate(const AstSenTree* domainp, const AstScope* scopep) { const DomScopeKey key = make_pair(domainp, scopep); - DomScopeMap::iterator iter = s_dsMap.find(key); + const auto iter = s_dsMap.find(key); if (iter != s_dsMap.end()) { return iter->second; } else { @@ -183,17 +182,17 @@ inline std::ostream& operator<<(std::ostream& lhs, const OrderMoveDomScope& rhs) // Order information stored under each AstNode::user1p()... // Types of vertex we can create -enum WhichVertex { WV_STD, WV_PRE, WV_PORD, WV_POST, WV_SETL, WV_MAX }; +enum WhichVertex : uint8_t { WV_STD, WV_PRE, WV_PORD, WV_POST, WV_SETL, WV_MAX }; class OrderUser { // Stored in AstVarScope::user1p, a list of all the various vertices // that can exist for one given variable private: - OrderVarVertex* m_vertexp[WV_MAX]; // Vertex of each type (if non NULL) + OrderVarVertex* m_vertexp[WV_MAX]; // Vertex of each type (if non nullptr) public: // METHODS OrderVarVertex* newVarUserVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varscp, - WhichVertex type, bool* createdp = NULL) { + WhichVertex type, bool* createdp = nullptr) { UASSERT_OBJ(type < WV_MAX, varscp, "Bad case"); OrderVarVertex* vertexp = m_vertexp[type]; if (!vertexp) { @@ -217,7 +216,7 @@ public: public: // CONSTRUCTORS OrderUser() { - for (int i = 0; i < WV_MAX; i++) m_vertexp[i] = NULL; + for (int i = 0; i < WV_MAX; i++) m_vertexp[i] = nullptr; } ~OrderUser() {} }; @@ -254,17 +253,17 @@ struct OrderVarFanoutCmp { // class OrderClkMarkVisitor : public AstNVisitor { private: - bool m_hasClk; // flag indicating whether there is clock signal on rhs - bool m_inClocked; // Currently inside a sequential block + bool m_hasClk = false; // flag indicating whether there is clock signal on rhs + bool m_inClocked = false; // Currently inside a sequential block bool m_newClkMarked; // Flag for deciding whether a new run is needed - bool m_inAss; // Currently inside of a assignment - int m_childClkWidth; // If in hasClk, width of clock signal in child - int m_rightClkWidth; // Clk width on the RHS + bool m_inAss = false; // Currently inside of a assignment + int m_childClkWidth = 0; // If in hasClk, width of clock signal in child + int m_rightClkWidth = 0; // Clk width on the RHS // METHODS VL_DEBUG_FUNC; // Declare debug() - virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { + virtual void visit(AstNodeAssign* nodep) override { m_hasClk = false; if (AstVarRef* varrefp = VN_CAST(nodep->rhsp(), VarRef)) { this->visit(varrefp); @@ -306,7 +305,7 @@ private: } } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { if (m_inAss && nodep->varp()->attrClocker() == VVarAttrClocker::CLOCKER_YES) { if (m_inClocked) { nodep->v3warn(CLKDATA, @@ -319,7 +318,7 @@ private: } } } - virtual void visit(AstConcat* nodep) VL_OVERRIDE { + virtual void visit(AstConcat* nodep) override { if (m_inAss) { iterateAndNextNull(nodep->lhsp()); int lw = m_childClkWidth; @@ -328,20 +327,20 @@ private: m_childClkWidth = lw + rw; // Pass up } } - virtual void visit(AstNodeSel* nodep) VL_OVERRIDE { + virtual void visit(AstNodeSel* nodep) override { if (m_inAss) { iterateChildren(nodep); // Pass up result width if (m_childClkWidth > nodep->width()) m_childClkWidth = nodep->width(); } } - virtual void visit(AstSel* nodep) VL_OVERRIDE { + virtual void visit(AstSel* nodep) override { if (m_inAss) { iterateChildren(nodep); if (m_childClkWidth > nodep->width()) m_childClkWidth = nodep->width(); } } - virtual void visit(AstReplicate* nodep) VL_OVERRIDE { + virtual void visit(AstReplicate* nodep) override { if (m_inAss) { iterateChildren(nodep); if (VN_IS(nodep->rhsp(), Const)) { @@ -351,27 +350,22 @@ private: } } } - virtual void visit(AstActive* nodep) VL_OVERRIDE { + virtual void visit(AstActive* nodep) override { m_inClocked = nodep->hasClocked(); iterateChildren(nodep); m_inClocked = false; } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit OrderClkMarkVisitor(AstNode* nodep) { - m_hasClk = false; - m_inClocked = false; - m_inAss = false; - m_childClkWidth = 0; - m_rightClkWidth = 0; do { m_newClkMarked = false; iterate(nodep); } while (m_newClkMarked); } - virtual ~OrderClkMarkVisitor() {} + virtual ~OrderClkMarkVisitor() override {} }; //###################################################################### @@ -379,10 +373,10 @@ public: class OrderClkAssVisitor : public AstNVisitor { private: - bool m_clkAss; // There is signals marked as clocker in the assignment + bool m_clkAss = false; // There is signals marked as clocker in the assignment // METHODS VL_DEBUG_FUNC; // Declare debug() - virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { + virtual void visit(AstNodeAssign* nodep) override { if (const AstVarRef* varrefp = VN_CAST(nodep->lhsp(), VarRef)) { if (varrefp->varp()->attrClocker() == VVarAttrClocker::CLOCKER_YES) { m_clkAss = true; @@ -391,23 +385,20 @@ private: } iterateChildren(nodep->rhsp()); } - virtual void visit(AstVarRef*) VL_OVERRIDE { + virtual void visit(AstVarRef*) override { // Previous versions checked attrClocker() here, but this breaks // the updated t_clocker VCD test. // If reenable this visitor note AstNodeMath short circuit below } - 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 OrderClkAssVisitor(AstNode* nodep) { - m_clkAss = false; - iterate(nodep); - } - virtual ~OrderClkAssVisitor() {} + explicit OrderClkAssVisitor(AstNode* nodep) { iterate(nodep); } + virtual ~OrderClkAssVisitor() override {} // METHODS - bool isClkAss() { return m_clkAss; } + bool isClkAss() const { return m_clkAss; } }; //###################################################################### @@ -432,16 +423,16 @@ template class ProcessMoveBuildGraph { // TYPES typedef std::pair VxDomPair; // Maps an (original graph vertex, domain) pair to a T_MoveVertex - // Not vl_unordered_map, because std::pair doesn't provide std::hash + // Not std::unordered_map, because std::pair doesn't provide std::hash typedef std::map Var2Move; - typedef vl_unordered_map Logic2Move; + typedef std::unordered_map Logic2Move; public: class MoveVertexMaker { public: // Clients of ProcessMoveBuildGraph must supply MoveVertexMaker // which creates new T_MoveVertex's. Each new vertex wraps lvertexp - // (which may be NULL.) + // (which may be nullptr.) virtual T_MoveVertex* makeVertexp( // OrderLogicVertex* lvertexp, const OrderEitherVertex* varVertexp, const AstScope* scopep, const AstSenTree* domainp) @@ -462,9 +453,9 @@ public: ProcessMoveBuildGraph(const V3Graph* logicGraphp, // Input graph of OrderLogicVertex etc. V3Graph* outGraphp, // Output graph of T_MoveVertex's MoveVertexMaker* vxMakerp) - : m_graphp(logicGraphp) - , m_outGraphp(outGraphp) - , m_vxMakerp(vxMakerp) {} + : m_graphp{logicGraphp} + , m_outGraphp{outGraphp} + , m_vxMakerp{vxMakerp} {} virtual ~ProcessMoveBuildGraph() {} // METHODS @@ -484,8 +475,8 @@ public: // For each logic node, make a T_MoveVertex for (V3GraphVertex* itp = m_graphp->verticesBeginp(); itp; itp = itp->verticesNextp()) { if (OrderLogicVertex* lvertexp = dynamic_cast(itp)) { - T_MoveVertex* moveVxp = m_vxMakerp->makeVertexp(lvertexp, NULL, lvertexp->scopep(), - lvertexp->domainp()); + T_MoveVertex* moveVxp = m_vxMakerp->makeVertexp( + lvertexp, nullptr, lvertexp->scopep(), lvertexp->domainp()); if (moveVxp) { // Cross link so we can find it later m_logic2move[lvertexp] = moveVxp; @@ -532,14 +523,14 @@ private: const OrderEitherVertex* eithp = dynamic_cast(nonLogicVxp); T_MoveVertex* newMoveVxp - = m_vxMakerp->makeVertexp(NULL, eithp, eithp->scopep(), domainp); + = m_vxMakerp->makeVertexp(nullptr, eithp, eithp->scopep(), domainp); m_var2move[key] = newMoveVxp; // Find downstream logics that depend on (var, domain) if (!iterate(newMoveVxp, edgep->top(), domainp)) { // No downstream dependencies, so remove this // intermediate vertex. - m_var2move[key] = NULL; + m_var2move[key] = nullptr; m_vxMakerp->freeVertexp(newMoveVxp); continue; } @@ -567,8 +558,8 @@ class OrderMoveVertexMaker : public ProcessMoveBuildGraph::Move public: // CONSTRUCTORS OrderMoveVertexMaker(V3Graph* pomGraphp, V3List* pomWaitingp) - : m_pomGraphp(pomGraphp) - , m_pomWaitingp(pomWaitingp) {} + : m_pomGraphp{pomGraphp} + , m_pomWaitingp{pomWaitingp} {} // METHODS OrderMoveVertex* makeVertexp(OrderLogicVertex* lvertexp, const OrderEitherVertex*, const AstScope* scopep, const AstSenTree* domainp) { @@ -591,12 +582,12 @@ class OrderMTaskMoveVertexMaker : public ProcessMoveBuildGraph: public: explicit OrderMTaskMoveVertexMaker(V3Graph* pomGraphp) - : m_pomGraphp(pomGraphp) {} + : m_pomGraphp{pomGraphp} {} MTaskMoveVertex* makeVertexp(OrderLogicVertex* lvertexp, const OrderEitherVertex* varVertexp, const AstScope* scopep, const AstSenTree* domainp) { // Exclude initial/settle logic from the mtasks graph. // We'll output time-zero logic separately. - if (domainp->hasInitial() || domainp->hasSettle()) return NULL; + if (domainp->hasInitial() || domainp->hasSettle()) return nullptr; return new MTaskMoveVertex(m_pomGraphp, lvertexp, varVertexp, scopep, domainp); } void freeVertexp(MTaskMoveVertex* freeMep) { freeMep->unlinkDelete(m_pomGraphp); } @@ -661,25 +652,25 @@ private: // STATE OrderGraph m_graph; // Scoreboard of var usages/dependencies SenTreeFinder m_finder; // Find global sentree's and add them - AstSenTree* m_comboDomainp; // Combo activation tree - AstSenTree* m_deleteDomainp; // Delete this from tree - OrderInputsVertex* m_inputsVxp; // Top level vertex all inputs point from - OrderLogicVertex* m_logicVxp; // Current statement being tracked, NULL=ignored - AstTopScope* m_topScopep; // Current top scope being processed - AstScope* m_scopetopp; // Scope under TOPSCOPE - AstNodeModule* m_modp; // Current module - AstScope* m_scopep; // Current scope being processed - AstActive* m_activep; // Current activation block - bool m_inSenTree; // Underneath AstSenItem; any varrefs are clocks - bool m_inClocked; // Underneath clocked block - bool m_inClkAss; // Underneath AstAssign - bool m_inPre; // Underneath AstAssignPre - bool m_inPost; // Underneath AstAssignPost - OrderLogicVertex* m_activeSenVxp; // Sensitivity vertex + AstSenTree* m_comboDomainp = nullptr; // Combo activation tree + AstSenTree* m_deleteDomainp = nullptr; // Delete this from tree + OrderInputsVertex* m_inputsVxp = nullptr; // Top level vertex all inputs point from + OrderLogicVertex* m_logicVxp = nullptr; // Current statement being tracked, nullptr=ignored + AstTopScope* m_topScopep = nullptr; // Current top scope being processed + AstScope* m_scopetopp = nullptr; // Scope under TOPSCOPE + AstNodeModule* m_modp = nullptr; // Current module + AstScope* m_scopep = nullptr; // Current scope being processed + AstActive* m_activep = nullptr; // Current activation block + bool m_inSenTree = false; // Underneath AstSenItem; any varrefs are clocks + bool m_inClocked = false; // Underneath clocked block + bool m_inClkAss = false; // Underneath AstAssign + bool m_inPre = false; // Underneath AstAssignPre + bool m_inPost = false; // Underneath AstAssignPost + OrderLogicVertex* m_activeSenVxp = nullptr; // Sensitivity vertex std::deque m_orderUserps; // All created OrderUser's for later deletion. // STATE... for inside process - AstCFunc* m_pomNewFuncp; // Current function being created - int m_pomNewStmts; // Statements in function being created + AstCFunc* m_pomNewFuncp = nullptr; // Current function being created + int m_pomNewStmts = 0; // Statements in function being created V3Graph m_pomGraph; // Graph of logic elements to move V3List m_pomWaiting; // List of nodes needing inputs to become ready protected: @@ -692,7 +683,7 @@ private: VDouble0 m_statCut[OrderVEdgeType::_ENUM_END]; // Count of each edge type cut // TYPES - enum VarUsage { VU_NONE = 0, VU_CON = 1, VU_GEN = 2 }; + enum VarUsage : uint8_t { VU_NONE = 0, VU_CON = 1, VU_GEN = 2 }; // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -702,10 +693,10 @@ private: UINFO(4, " STMT " << nodep << endl); // VV***** We reset user4p() AstNode::user4ClearTree(); - UASSERT_OBJ(m_activep && m_activep->sensesp(), nodep, "NULL"); + UASSERT_OBJ(m_activep && m_activep->sensesp(), nodep, "nullptr"); // If inside combo logic, ignore the domain, we'll assign one based on interconnect AstSenTree* startDomainp = m_activep->sensesp(); - if (startDomainp->hasCombo()) startDomainp = NULL; + if (startDomainp->hasCombo()) startDomainp = nullptr; m_logicVxp = new OrderLogicVertex(&m_graph, m_scopep, startDomainp, nodep); if (m_activeSenVxp) { // If in a clocked activation, add a link from the sensitivity to this block @@ -714,12 +705,12 @@ private: } nodep->user1p(m_modp); iterateChildren(nodep); - m_logicVxp = NULL; + m_logicVxp = nullptr; } } OrderVarVertex* newVarUserVertex(AstVarScope* varscp, WhichVertex type, - bool* createdp = NULL) { + bool* createdp = nullptr) { if (!varscp->user1p()) { OrderUser* newup = new OrderUser(); m_orderUserps.push_back(newup); @@ -755,15 +746,13 @@ private: // processMTask* routines schedule threaded execution struct MTaskState { typedef std::list Logics; - AstMTaskBody* m_mtaskBodyp; + AstMTaskBody* m_mtaskBodyp = nullptr; Logics m_logics; - ExecMTask* m_execMTaskp; - MTaskState() - : m_mtaskBodyp(NULL) - , m_execMTaskp(NULL) {} + ExecMTask* m_execMTaskp = nullptr; + MTaskState() {} }; void processMTasks(); - typedef enum { LOGIC_INITIAL, LOGIC_SETTLE } InitialLogicE; + typedef enum : uint8_t { LOGIC_INITIAL, LOGIC_SETTLE } InitialLogicE; void processMTasksInitial(InitialLogicE logic_type); string cfuncName(AstNodeModule* modp, AstSenTree* domainp, AstScope* scopep, @@ -786,8 +775,8 @@ private: void nodeMarkCircular(OrderVarVertex* vertexp, OrderEdge* edgep) { AstVarScope* nodep = vertexp->varScp(); - OrderLogicVertex* fromLVtxp = NULL; - OrderLogicVertex* toLVtxp = NULL; + OrderLogicVertex* fromLVtxp = nullptr; + OrderLogicVertex* toLVtxp = nullptr; if (edgep) { fromLVtxp = dynamic_cast(edgep->fromp()); toLVtxp = dynamic_cast(edgep->top()); @@ -877,7 +866,7 @@ private: // elements. Up to 10 of the widest std::cerr << V3Error::warnMore() << "... Widest candidate vars to split:" << endl; std::stable_sort(m_unoptflatVars.begin(), m_unoptflatVars.end(), OrderVarWidthCmp()); - vl_unordered_set canSplitList; + std::unordered_set canSplitList; int lim = m_unoptflatVars.size() < 10 ? m_unoptflatVars.size() : 10; for (int i = 0; i < lim; i++) { OrderVarStdVertex* vsvertexp = m_unoptflatVars[i]; @@ -943,7 +932,7 @@ private: } } // VISITORS - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { { AstUser4InUse m_inuser4; // Used only when building tree, so below iterateChildren(nodep); @@ -951,10 +940,10 @@ private: // We're finished, complete the topscopes if (m_topScopep) { process(); - m_topScopep = NULL; + m_topScopep = nullptr; } } - virtual void visit(AstTopScope* nodep) VL_OVERRIDE { + virtual void visit(AstTopScope* nodep) override { // Process the last thing we're finishing UASSERT_OBJ(!m_topScopep, nodep, "Only one topscope should ever be created"); UINFO(2, " Loading tree...\n"); @@ -962,7 +951,7 @@ private: AstNode::user1ClearTree(); AstNode::user3ClearTree(); m_graph.clear(); - m_activep = NULL; + m_activep = nullptr; m_topScopep = nodep; m_scopetopp = nodep->scopep(); // Find global SenTrees @@ -980,8 +969,8 @@ private: pushDeletep(m_deleteDomainp); // Cleanup when done UINFO(5, " DeleteDomain = " << m_deleteDomainp << endl); // Base vertices - m_activeSenVxp = NULL; - m_inputsVxp = new OrderInputsVertex(&m_graph, NULL); + m_activeSenVxp = nullptr; + m_inputsVxp = new OrderInputsVertex(&m_graph, nullptr); // iterateChildren(nodep); // Done topscope, erase extra user information @@ -989,30 +978,29 @@ private: AstNode::user3ClearTree(); AstNode::user4ClearTree(); } - 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(AstClass*) VL_OVERRIDE {} - virtual void visit(AstScope* nodep) VL_OVERRIDE { + virtual void visit(AstClass*) override {} + virtual void visit(AstScope* nodep) override { UINFO(4, " SCOPE " << nodep << endl); m_scopep = nodep; - m_logicVxp = NULL; - m_activeSenVxp = NULL; + m_logicVxp = nullptr; + m_activeSenVxp = nullptr; nodep->user1p(m_modp); // Iterate iterateChildren(nodep); - m_scopep = NULL; + m_scopep = nullptr; } - virtual void visit(AstActive* nodep) VL_OVERRIDE { + virtual void visit(AstActive* nodep) override { // Create required activation blocks and add to module UINFO(4, " ACTIVE " << nodep << endl); m_activep = nodep; - m_activeSenVxp = NULL; + m_activeSenVxp = nullptr; m_inClocked = nodep->hasClocked(); // Grab the sensitivity list UASSERT_OBJ(!nodep->sensesStorep(), nodep, @@ -1020,11 +1008,11 @@ private: iterate(nodep->sensesp()); // Collect statements under it iterateChildren(nodep); - m_activep = NULL; - m_activeSenVxp = NULL; + m_activep = nullptr; + m_activeSenVxp = nullptr; m_inClocked = false; } - virtual void visit(AstVarScope* nodep) VL_OVERRIDE { + virtual void visit(AstVarScope* nodep) override { // Create links to all input signals UASSERT_OBJ(m_modp, nodep, "Scope not under module"); if (m_modp->isTop() && nodep->varp()->isNonOutput()) { @@ -1032,7 +1020,7 @@ private: new OrderEdge(&m_graph, m_inputsVxp, varVxp, WEIGHT_INPUT); } } - virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstNodeVarRef* nodep) override { if (m_scopep) { AstVarScope* varscp = nodep->varScopep(); UASSERT_OBJ(varscp, nodep, "Var didn't get varscoped in V3Scope.cpp"); @@ -1159,7 +1147,7 @@ private: } } } - virtual void visit(AstSenTree* nodep) VL_OVERRIDE { + virtual void visit(AstSenTree* nodep) override { // Having a node derived from the sentree isn't required for // correctness, it merely makes the graph better connected // and improves graph algorithmic performance @@ -1174,21 +1162,21 @@ private: m_inSenTree = false; } } - virtual void visit(AstAlwaysPost* nodep) VL_OVERRIDE { + virtual void visit(AstAlwaysPost* nodep) override { m_inPost = true; iterateNewStmt(nodep); m_inPost = false; } - virtual void visit(AstAlways* nodep) VL_OVERRIDE { iterateNewStmt(nodep); } - virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE { iterateNewStmt(nodep); } - virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { iterateNewStmt(nodep); } - virtual void visit(AstAssignW* nodep) VL_OVERRIDE { + virtual void visit(AstAlways* nodep) override { iterateNewStmt(nodep); } + virtual void visit(AstAlwaysPublic* nodep) override { iterateNewStmt(nodep); } + virtual void visit(AstAssignAlias* nodep) override { iterateNewStmt(nodep); } + virtual void visit(AstAssignW* nodep) override { OrderClkAssVisitor visitor(nodep); m_inClkAss = visitor.isClkAss(); iterateNewStmt(nodep); m_inClkAss = false; } - virtual void visit(AstAssignPre* nodep) VL_OVERRIDE { + virtual void visit(AstAssignPre* nodep) override { OrderClkAssVisitor visitor(nodep); m_inClkAss = visitor.isClkAss(); m_inPre = true; @@ -1196,7 +1184,7 @@ private: m_inPre = false; m_inClkAss = false; } - virtual void visit(AstAssignPost* nodep) VL_OVERRIDE { + virtual void visit(AstAssignPost* nodep) override { OrderClkAssVisitor visitor(nodep); m_inClkAss = visitor.isClkAss(); m_inPost = true; @@ -1204,43 +1192,27 @@ private: m_inPost = false; m_inClkAss = false; } - virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE { iterateNewStmt(nodep); } - virtual void visit(AstInitial* nodep) VL_OVERRIDE { + virtual void visit(AstCoverToggle* nodep) override { iterateNewStmt(nodep); } + virtual void visit(AstInitial* nodep) override { // We use initials to setup parameters and static consts's which may be referenced // in user initial blocks. So use ordering to sort them all out. iterateNewStmt(nodep); } - virtual void visit(AstCFunc*) VL_OVERRIDE { + virtual void visit(AstCFunc*) override { // Ignore for now // We should detect what variables are set in the function, and make // settlement code for them, then set a global flag, so we call "settle" // on the next evaluation loop. } //-------------------- - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS OrderVisitor() { - m_topScopep = NULL; - m_scopetopp = NULL; - m_modp = NULL; - m_scopep = NULL; - m_activep = NULL; - m_inSenTree = false; - m_inClocked = false; - m_inClkAss = false; - m_inPre = m_inPost = false; - m_comboDomainp = NULL; - m_deleteDomainp = NULL; - m_inputsVxp = NULL; - m_activeSenVxp = NULL; - m_logicVxp = NULL; - m_pomNewFuncp = NULL; - m_pomNewStmts = 0; if (debug()) m_graph.debug(5); // 3 is default if global debug; we want acyc debugging } - virtual ~OrderVisitor() { + virtual ~OrderVisitor() override { // Stats for (int type = 0; type < OrderVEdgeType::_ENUM_END; type++) { double count = double(m_statCut[type]); @@ -1249,10 +1221,7 @@ public: } } // Destruction - for (std::deque::iterator it = m_orderUserps.begin(); - it != m_orderUserps.end(); ++it) { - delete *it; - } + for (OrderUser* ip : m_orderUserps) delete ip; m_graph.debug(V3Error::debugDefault()); } void main(AstNode* nodep) { iterate(nodep); } @@ -1423,10 +1392,10 @@ void OrderVisitor::processCircular() { // other tests such as t_gated_clk_1. if (!v3Global.opt.orderClockDly()) { UINFO(5, "Circular Clock, no-order-clock-delay " << vvertexp << endl); - nodeMarkCircular(vvertexp, NULL); + nodeMarkCircular(vvertexp, nullptr); } else if (vvertexp->isDelayed()) { UINFO(5, "Circular Clock, delayed " << vvertexp << endl); - nodeMarkCircular(vvertexp, NULL); + nodeMarkCircular(vvertexp, nullptr); } else { UINFO(5, "Circular Clock, not delayed " << vvertexp << endl); } @@ -1494,7 +1463,7 @@ void OrderVisitor::processDomainsIterate(OrderEitherVertex* vertexp) { if (vertexp->domainp()) return; // Already processed, or sequential logic UINFO(5, " pdi: " << vertexp << endl); OrderVarVertex* vvertexp = dynamic_cast(vertexp); - AstSenTree* domainp = NULL; + AstSenTree* domainp = nullptr; UASSERT(m_comboDomainp, "not preset"); if (vvertexp && vvertexp->varScp()->varp()->isNonOutput()) domainp = m_comboDomainp; if (vvertexp && vvertexp->varScp()->isCircular()) domainp = m_comboDomainp; @@ -1534,7 +1503,7 @@ void OrderVisitor::processDomainsIterate(OrderEitherVertex* vertexp) { UASSERT_OBJ(newtree2p, fromVertexp->domainp(), "No senitem found under clocked domain"); newtreep->addSensesp(newtree2p); - newtree2p = NULL; // Below edit may replace it + newtree2p = nullptr; // Below edit may replace it V3Const::constifyExpensiveEdit(newtreep); // Remove duplicates newtreep->multi(true); // Comment that it was made from 2 clock domains domainp = m_finder.getSenTree(newtreep); @@ -1571,7 +1540,7 @@ void OrderVisitor::processDomainsIterate(OrderEitherVertex* vertexp) { void OrderVisitor::processEdgeReport() { // Make report of all signal names and what clock edges they have string filename = v3Global.debugFilename("order_edges.txt"); - const vl_unique_ptr logp(V3File::new_ofstream(filename)); + const std::unique_ptr logp(V3File::new_ofstream(filename)); if (logp->fail()) v3fatal("Can't write " << filename); // Testing emitter: V3EmitV::verilogForTree(v3Global.rootp(), *logp); @@ -1600,9 +1569,7 @@ void OrderVisitor::processEdgeReport() { *logp << "Signals and their clock domains:" << endl; stable_sort(report.begin(), report.end()); - for (std::deque::iterator it = report.begin(); it != report.end(); ++it) { - *logp << (*it) << endl; - } + for (const string& i : report) *logp << i << endl; } void OrderVisitor::processMoveClear() { @@ -1617,7 +1584,7 @@ void OrderVisitor::processMoveBuildGraph() { UINFO(5, " MoveBuildGraph\n"); processMoveClear(); m_pomGraph - .userClearVertices(); // Vertex::user->OrderMoveVertex*, last edge added or NULL=none + .userClearVertices(); // Vertex::user->OrderMoveVertex*, last edge added or nullptr=none OrderMoveVertexMaker createOrderMoveVertex(&m_pomGraph, &m_pomWaiting); ProcessMoveBuildGraph serialPMBG(&m_graph, &m_pomGraph, @@ -1654,13 +1621,14 @@ void OrderVisitor::processMove() { while (domScopep) { UINFO(6, " MoveDomain l=" << domScopep->domainp() << endl); // Process all nodes ready under same domain & scope - m_pomNewFuncp = NULL; + m_pomNewFuncp = nullptr; while (OrderMoveVertex* vertexp = domScopep->readyVertices().begin()) { // lintok-begin-on-ref processMoveOne(vertexp, domScopep, 1); } - // Done with scope/domain pair, pick new scope under same domain, or NULL if none left - OrderMoveDomScope* domScopeNextp = NULL; + // Done with scope/domain pair, pick new scope under same domain, or nullptr if none + // left + OrderMoveDomScope* domScopeNextp = nullptr; for (OrderMoveDomScope* huntp = m_pomReadyDomScope.begin(); huntp; huntp = huntp->readyDomScopeNextp()) { if (huntp->domainp() == domScopep->domainp()) { @@ -1745,12 +1713,12 @@ void OrderVisitor::processMoveOne(OrderMoveVertex* vertexp, OrderMoveDomScope* d AstActive* OrderVisitor::processMoveOneLogic(const OrderLogicVertex* lvertexp, AstCFunc*& newFuncpr, int& newStmtsr) { - AstActive* activep = NULL; + AstActive* activep = nullptr; AstScope* scopep = lvertexp->scopep(); AstSenTree* domainp = lvertexp->domainp(); AstNode* nodep = lvertexp->nodep(); AstNodeModule* modp = VN_CAST(scopep->user1p(), NodeModule); // Stashed by visitor func - UASSERT(modp, "NULL"); + UASSERT(modp, "nullptr"); if (VN_IS(nodep, SenTree)) { // Just ignore sensitivities, we'll deal with them when we move statements that need them } else { // Normal logic @@ -1759,7 +1727,7 @@ AstActive* OrderVisitor::processMoveOneLogic(const OrderLogicVertex* lvertexp, || (v3Global.opt.outputSplitCFuncs() && v3Global.opt.outputSplitCFuncs() < newStmtsr)) { // Put every statement into a unique function to ease profiling or reduce function size - newFuncpr = NULL; + newFuncpr = nullptr; } if (!newFuncpr && domainp != m_deleteDomainp) { string name = cfuncName(modp, domainp, scopep, nodep); @@ -1800,8 +1768,8 @@ void OrderVisitor::processMTasksInitial(InitialLogicE logic_type) { // mtask partition, aren't eligible for parallelism. // int initStmts = 0; - AstCFunc* initCFunc = NULL; - AstScope* lastScopep = NULL; + AstCFunc* initCFunc = nullptr; + AstScope* lastScopep = nullptr; for (V3GraphVertex* initVxp = m_graph.verticesBeginp(); initVxp; initVxp = initVxp->verticesNextp()) { OrderLogicVertex* initp = dynamic_cast(initVxp); @@ -1810,7 +1778,7 @@ void OrderVisitor::processMTasksInitial(InitialLogicE logic_type) { if ((logic_type == LOGIC_SETTLE) && !initp->domainp()->hasSettle()) continue; if (initp->scopep() != lastScopep) { // Start new cfunc, don't let the cfunc cross scopes - initCFunc = NULL; + initCFunc = nullptr; lastScopep = initp->scopep(); } AstActive* newActivep = processMoveOneLogic(initp, initCFunc /*ref*/, initStmts /*ref*/); @@ -1846,7 +1814,7 @@ void OrderVisitor::processMTasks() { V3Graph mtasks; partitioner.go(&mtasks); - vl_unordered_map mtaskStates; + std::unordered_map mtaskStates; // Iterate through the entire logicGraph. For each logic node, // attach it to a per-MTask ordered list of logic nodes. @@ -1911,15 +1879,13 @@ void OrderVisitor::processMTasks() { // Create leaf CFunc's to run this mtask's logic, // and create a set of AstActive's to call those CFuncs. // Add the AstActive's into the AstMTaskBody. - const AstSenTree* last_domainp = NULL; - AstCFunc* leafCFuncp = NULL; + const AstSenTree* last_domainp = nullptr; + AstCFunc* leafCFuncp = nullptr; int leafStmts = 0; - for (MTaskState::Logics::iterator it = state.m_logics.begin(); it != state.m_logics.end(); - ++it) { - const OrderLogicVertex* logicp = *it; + for (const OrderLogicVertex* logicp : state.m_logics) { if (logicp->domainp() != last_domainp) { // Start a new leaf function. - leafCFuncp = NULL; + leafCFuncp = nullptr; } last_domainp = logicp->domainp(); @@ -1991,9 +1957,10 @@ void OrderVisitor::process() { if (!v3Global.opt.mtasks()) { UINFO(2, " Construct Move Graph...\n"); processMoveBuildGraph(); - if (debug() >= 4) + if (debug() >= 4) { m_pomGraph.dumpDotFilePrefixed( "ordermv_start"); // Different prefix (ordermv) as it's not the same graph + } m_pomGraph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue); if (debug() >= 4) m_pomGraph.dumpDotFilePrefixed("ordermv_simpl"); @@ -2012,7 +1979,7 @@ void OrderVisitor::process() { m_graph.dumpDotFilePrefixed("orderg_done"); if (false && debug()) { string dfilename = v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "_INT_order"; - const vl_unique_ptr logp(V3File::new_ofstream(dfilename)); + const std::unique_ptr logp(V3File::new_ofstream(dfilename)); if (logp->fail()) v3fatal("Can't write " << dfilename); m_graph.dump(*logp); } diff --git a/src/V3OrderGraph.h b/src/V3OrderGraph.h index fc81aaf44..a0cc562ef 100644 --- a/src/V3OrderGraph.h +++ b/src/V3OrderGraph.h @@ -44,7 +44,7 @@ #include "V3Ast.h" #include "V3Graph.h" -#include VL_INCLUDE_UNORDERED_MAP +#include class OrderVisitor; class OrderMoveVertex; @@ -53,7 +53,7 @@ class OrderMoveDomScope; //###################################################################### -enum OrderWeights { +enum OrderWeights : uint8_t { WEIGHT_INPUT = 1, // Low weight just so dot graph looks nice WEIGHT_COMBO = 1, // Breakable combo logic WEIGHT_POST = 2, // Post-delayed used var @@ -63,7 +63,7 @@ enum OrderWeights { }; // High weight just so dot graph looks nice struct OrderVEdgeType { - enum en { + enum en : uint8_t { VERTEX_UNKNOWN = 0, VERTEX_INPUTS, VERTEX_LOGIC, @@ -89,12 +89,12 @@ struct OrderVEdgeType { } enum en m_e; inline OrderVEdgeType() - : m_e(VERTEX_UNKNOWN) {} + : m_e{VERTEX_UNKNOWN} {} // cppcheck-suppress noExplicitConstructor inline OrderVEdgeType(en _e) - : m_e(_e) {} + : m_e{_e} {} explicit inline OrderVEdgeType(int _e) - : m_e(static_cast(_e)) {} + : m_e(static_cast(_e)) {} // Need () or GCC 4.8 false warning operator en() const { return m_e; } }; inline bool operator==(const OrderVEdgeType& lhs, const OrderVEdgeType& rhs) { @@ -113,9 +113,9 @@ inline bool operator==(OrderVEdgeType::en lhs, const OrderVEdgeType& rhs) { class OrderGraph : public V3Graph { public: OrderGraph() {} - virtual ~OrderGraph() {} + virtual ~OrderGraph() override {} // Methods - virtual void loopsVertexCb(V3GraphVertex* vertexp); + virtual void loopsVertexCb(V3GraphVertex* vertexp) override; }; //###################################################################### @@ -123,27 +123,27 @@ public: class OrderEitherVertex : public V3GraphVertex { AstScope* m_scopep; // Scope the vertex is in - AstSenTree* m_domainp; // Clock domain (NULL = to be computed as we iterate) + AstSenTree* m_domainp; // Clock domain (nullptr = to be computed as we iterate) bool m_isFromInput; // From input, or derived therefrom (conservatively false) protected: OrderEitherVertex(V3Graph* graphp, const OrderEitherVertex& old) - : V3GraphVertex(graphp, old) - , m_scopep(old.m_scopep) - , m_domainp(old.m_domainp) - , m_isFromInput(old.m_isFromInput) {} + : V3GraphVertex{graphp, old} + , m_scopep{old.m_scopep} + , m_domainp{old.m_domainp} + , m_isFromInput{old.m_isFromInput} {} public: OrderEitherVertex(V3Graph* graphp, AstScope* scopep, AstSenTree* domainp) - : V3GraphVertex(graphp) - , m_scopep(scopep) - , m_domainp(domainp) - , m_isFromInput(false) {} - virtual ~OrderEitherVertex() {} - virtual OrderEitherVertex* clone(V3Graph* graphp) const = 0; + : V3GraphVertex{graphp} + , m_scopep{scopep} + , m_domainp{domainp} + , m_isFromInput{false} {} + virtual ~OrderEitherVertex() override {} + virtual OrderEitherVertex* clone(V3Graph* graphp) const override = 0; // Methods virtual OrderVEdgeType type() const = 0; virtual bool domainMatters() = 0; // Must be in same domain when cross edge to this vertex - virtual string dotName() const { return cvtToHex(m_scopep) + "_"; } + virtual string dotName() const override { return cvtToHex(m_scopep) + "_"; } // ACCESSORS void domainp(AstSenTree* domainp) { m_domainp = domainp; } AstScope* scopep() const { return m_scopep; } @@ -154,22 +154,22 @@ public: class OrderInputsVertex : public OrderEitherVertex { OrderInputsVertex(V3Graph* graphp, const OrderInputsVertex& old) - : OrderEitherVertex(graphp, old) {} + : OrderEitherVertex{graphp, old} {} public: OrderInputsVertex(V3Graph* graphp, AstSenTree* domainp) - : OrderEitherVertex(graphp, NULL, domainp) { + : OrderEitherVertex{graphp, nullptr, domainp} { isFromInput(true); // By definition } - virtual ~OrderInputsVertex() {} - virtual OrderInputsVertex* clone(V3Graph* graphp) const { + virtual ~OrderInputsVertex() override {} + virtual OrderInputsVertex* clone(V3Graph* graphp) const override { return new OrderInputsVertex(graphp, *this); } - virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_INPUTS; } - virtual string name() const { return "*INPUTS*"; } - virtual string dotColor() const { return "green"; } - virtual string dotName() const { return ""; } - virtual bool domainMatters() { return false; } + virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_INPUTS; } + virtual string name() const override { return "*INPUTS*"; } + virtual string dotColor() const override { return "green"; } + virtual string dotName() const override { return ""; } + virtual bool domainMatters() override { return false; } }; class OrderLogicVertex : public OrderEitherVertex { @@ -177,25 +177,25 @@ class OrderLogicVertex : public OrderEitherVertex { protected: OrderLogicVertex(V3Graph* graphp, const OrderLogicVertex& old) - : OrderEitherVertex(graphp, old) - , m_nodep(old.m_nodep) {} + : OrderEitherVertex{graphp, old} + , m_nodep{old.m_nodep} {} public: OrderLogicVertex(V3Graph* graphp, AstScope* scopep, AstSenTree* domainp, AstNode* nodep) - : OrderEitherVertex(graphp, scopep, domainp) - , m_nodep(nodep) {} - virtual ~OrderLogicVertex() {} - virtual OrderLogicVertex* clone(V3Graph* graphp) const { + : OrderEitherVertex{graphp, scopep, domainp} + , m_nodep{nodep} {} + virtual ~OrderLogicVertex() override {} + virtual OrderLogicVertex* clone(V3Graph* graphp) const override { return new OrderLogicVertex(graphp, *this); } - virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_LOGIC; } - virtual bool domainMatters() { return true; } + virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_LOGIC; } + virtual bool domainMatters() override { return true; } // ACCESSORS - virtual string name() const { + virtual string name() const override { return (cvtToHex(m_nodep) + "\\n " + cvtToStr(nodep()->typeName())); } AstNode* nodep() const { return m_nodep; } - virtual string dotColor() const { return "yellow"; } + virtual string dotColor() const override { return "yellow"; } }; class OrderVarVertex : public OrderEitherVertex { @@ -204,21 +204,21 @@ class OrderVarVertex : public OrderEitherVertex { bool m_isDelayed; // Set in a delayed assignment protected: OrderVarVertex(V3Graph* graphp, const OrderVarVertex& old) - : OrderEitherVertex(graphp, old) - , m_varScp(old.m_varScp) - , m_isClock(old.m_isClock) - , m_isDelayed(old.m_isDelayed) {} + : OrderEitherVertex{graphp, old} + , m_varScp{old.m_varScp} + , m_isClock{old.m_isClock} + , m_isDelayed{old.m_isDelayed} {} public: OrderVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) - : OrderEitherVertex(graphp, scopep, NULL) - , m_varScp(varScp) - , m_isClock(false) - , m_isDelayed(false) {} - virtual ~OrderVarVertex() {} - virtual OrderVarVertex* clone(V3Graph* graphp) const = 0; - virtual OrderVEdgeType type() const = 0; - virtual FileLine* fileline() const { return varScp()->fileline(); } + : OrderEitherVertex{graphp, scopep, nullptr} + , m_varScp{varScp} + , m_isClock{false} + , m_isDelayed{false} {} + virtual ~OrderVarVertex() override {} + virtual OrderVarVertex* clone(V3Graph* graphp) const override = 0; + virtual OrderVEdgeType type() const override = 0; + virtual FileLine* fileline() const override { return varScp()->fileline(); } // ACCESSORS AstVarScope* varScp() const { return m_varScp; } void isClock(bool flag) { m_isClock = flag; } @@ -229,90 +229,100 @@ public: class OrderVarStdVertex : public OrderVarVertex { OrderVarStdVertex(V3Graph* graphp, const OrderVarStdVertex& old) - : OrderVarVertex(graphp, old) {} + : OrderVarVertex{graphp, old} {} public: OrderVarStdVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) - : OrderVarVertex(graphp, scopep, varScp) {} - virtual ~OrderVarStdVertex() {} - virtual OrderVarStdVertex* clone(V3Graph* graphp) const { + : OrderVarVertex{graphp, scopep, varScp} {} + virtual ~OrderVarStdVertex() override {} + virtual OrderVarStdVertex* clone(V3Graph* graphp) const override { return new OrderVarStdVertex(graphp, *this); } - virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_VARSTD; } - virtual string name() const { return (cvtToHex(varScp()) + "\\n " + varScp()->name()); } - virtual string dotColor() const { return "skyblue"; } - virtual bool domainMatters() { return true; } + virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARSTD; } + virtual string name() const override { + return (cvtToHex(varScp()) + "\\n " + varScp()->name()); + } + virtual string dotColor() const override { return "skyblue"; } + virtual bool domainMatters() override { return true; } }; class OrderVarPreVertex : public OrderVarVertex { OrderVarPreVertex(V3Graph* graphp, const OrderVarPreVertex& old) - : OrderVarVertex(graphp, old) {} + : OrderVarVertex{graphp, old} {} public: OrderVarPreVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) - : OrderVarVertex(graphp, scopep, varScp) {} - virtual ~OrderVarPreVertex() {} - virtual OrderVarPreVertex* clone(V3Graph* graphp) const { + : OrderVarVertex{graphp, scopep, varScp} {} + virtual ~OrderVarPreVertex() override {} + virtual OrderVarPreVertex* clone(V3Graph* graphp) const override { return new OrderVarPreVertex(graphp, *this); } - virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_VARPRE; } - virtual string name() const { return (cvtToHex(varScp()) + " PRE\\n " + varScp()->name()); } - virtual string dotColor() const { return "lightblue"; } - virtual bool domainMatters() { return false; } + virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARPRE; } + virtual string name() const override { + return (cvtToHex(varScp()) + " PRE\\n " + varScp()->name()); + } + virtual string dotColor() const override { return "lightblue"; } + virtual bool domainMatters() override { return false; } }; class OrderVarPostVertex : public OrderVarVertex { OrderVarPostVertex(V3Graph* graphp, const OrderVarPostVertex& old) - : OrderVarVertex(graphp, old) {} + : OrderVarVertex{graphp, old} {} public: OrderVarPostVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) - : OrderVarVertex(graphp, scopep, varScp) {} - virtual OrderVarPostVertex* clone(V3Graph* graphp) const { + : OrderVarVertex{graphp, scopep, varScp} {} + virtual OrderVarPostVertex* clone(V3Graph* graphp) const override { return new OrderVarPostVertex(graphp, *this); } - virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_VARPOST; } - virtual ~OrderVarPostVertex() {} - virtual string name() const { return (cvtToHex(varScp()) + " POST\\n " + varScp()->name()); } - virtual string dotColor() const { return "CadetBlue"; } - virtual bool domainMatters() { return false; } + virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARPOST; } + virtual ~OrderVarPostVertex() override {} + virtual string name() const override { + return (cvtToHex(varScp()) + " POST\\n " + varScp()->name()); + } + virtual string dotColor() const override { return "CadetBlue"; } + virtual bool domainMatters() override { return false; } }; class OrderVarPordVertex : public OrderVarVertex { OrderVarPordVertex(V3Graph* graphp, const OrderVarPordVertex& old) - : OrderVarVertex(graphp, old) {} + : OrderVarVertex{graphp, old} {} public: OrderVarPordVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) - : OrderVarVertex(graphp, scopep, varScp) {} - virtual ~OrderVarPordVertex() {} - virtual OrderVarPordVertex* clone(V3Graph* graphp) const { + : OrderVarVertex{graphp, scopep, varScp} {} + virtual ~OrderVarPordVertex() override {} + virtual OrderVarPordVertex* clone(V3Graph* graphp) const override { return new OrderVarPordVertex(graphp, *this); } - virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_VARPORD; } - virtual string name() const { return (cvtToHex(varScp()) + " PORD\\n " + varScp()->name()); } - virtual string dotColor() const { return "NavyBlue"; } - virtual bool domainMatters() { return false; } + virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARPORD; } + virtual string name() const override { + return (cvtToHex(varScp()) + " PORD\\n " + varScp()->name()); + } + virtual string dotColor() const override { return "NavyBlue"; } + virtual bool domainMatters() override { return false; } }; class OrderVarSettleVertex : public OrderVarVertex { OrderVarSettleVertex(V3Graph* graphp, const OrderVarSettleVertex& old) - : OrderVarVertex(graphp, old) {} + : OrderVarVertex{graphp, old} {} public: OrderVarSettleVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp) - : OrderVarVertex(graphp, scopep, varScp) {} - virtual ~OrderVarSettleVertex() {} - virtual OrderVarSettleVertex* clone(V3Graph* graphp) const { + : OrderVarVertex{graphp, scopep, varScp} {} + virtual ~OrderVarSettleVertex() override {} + virtual OrderVarSettleVertex* clone(V3Graph* graphp) const override { return new OrderVarSettleVertex(graphp, *this); } - virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_VARSETTLE; } - virtual string name() const { return (cvtToHex(varScp()) + " STL\\n " + varScp()->name()); } - virtual string dotColor() const { return "PowderBlue"; } - virtual bool domainMatters() { return false; } + virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARSETTLE; } + virtual string name() const override { + return (cvtToHex(varScp()) + " STL\\n " + varScp()->name()); + } + virtual string dotColor() const override { return "PowderBlue"; } + virtual bool domainMatters() override { return false; } }; //###################################################################### //--- Following only under the move graph, not the main graph class OrderMoveVertex : public V3GraphVertex { - typedef enum { POM_WAIT, POM_READY, POM_MOVED } OrderMState; + typedef enum : uint8_t { POM_WAIT, POM_READY, POM_MOVED } OrderMState; OrderLogicVertex* m_logicp; OrderMState m_state; // Movement state @@ -328,32 +338,32 @@ protected: public: // CONSTRUCTORS OrderMoveVertex(V3Graph* graphp, OrderLogicVertex* logicp) - : V3GraphVertex(graphp) - , m_logicp(logicp) - , m_state(POM_WAIT) - , m_domScopep(NULL) {} - virtual ~OrderMoveVertex() {} - virtual OrderMoveVertex* clone(V3Graph* graphp) const { + : V3GraphVertex{graphp} + , m_logicp{logicp} + , m_state{POM_WAIT} + , m_domScopep{nullptr} {} + virtual ~OrderMoveVertex() override {} + virtual OrderMoveVertex* clone(V3Graph* graphp) const override { v3fatalSrc("Unsupported"); - return NULL; + return nullptr; } // METHODS virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_MOVE; } - virtual string dotColor() const { + virtual string dotColor() const override { if (logicp()) { return logicp()->dotColor(); } else { return ""; } } - virtual FileLine* fileline() const { + virtual FileLine* fileline() const override { if (logicp()) { return logicp()->fileline(); } else { - return NULL; + return nullptr; } } - virtual string name() const { + virtual string name() const override { string nm; if (VL_UNCOVERABLE(!logicp())) { // Avoid crash when debugging nm = "nul"; // LCOV_EXCL_LINE @@ -395,27 +405,27 @@ protected: public: MTaskMoveVertex(V3Graph* graphp, OrderLogicVertex* logicp, const OrderEitherVertex* varp, const AstScope* scopep, const AstSenTree* domainp) - : V3GraphVertex(graphp) - , m_logicp(logicp) - , m_varp(varp) - , m_scopep(scopep) - , m_domainp(domainp) { + : V3GraphVertex{graphp} + , m_logicp{logicp} + , m_varp{varp} + , m_scopep{scopep} + , m_domainp{domainp} { UASSERT(!(logicp && varp), "MTaskMoveVertex: logicp and varp may not both be set!\n"); } - virtual ~MTaskMoveVertex() {} - virtual MTaskMoveVertex* clone(V3Graph* graphp) const { + virtual ~MTaskMoveVertex() override {} + virtual MTaskMoveVertex* clone(V3Graph* graphp) const override { v3fatalSrc("Unsupported"); - return NULL; + return nullptr; } virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_MOVE; } - virtual string dotColor() const { + virtual string dotColor() const override { if (logicp()) { return logicp()->dotColor(); } else { return "yellow"; } } - virtual string name() const { + virtual string name() const override { string nm; if (logicp()) { nm = logicp()->name(); @@ -441,15 +451,16 @@ public: class OrderEdge : public V3GraphEdge { protected: OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, const OrderEdge& old) - : V3GraphEdge(graphp, fromp, top, old) {} + : V3GraphEdge{graphp, fromp, top, old} {} public: OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight, bool cutable = false) - : V3GraphEdge(graphp, fromp, top, weight, cutable) {} - virtual ~OrderEdge() {} + : V3GraphEdge{graphp, fromp, top, weight, cutable} {} + virtual ~OrderEdge() override {} virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_STD; } - virtual OrderEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) const { + virtual OrderEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, + V3GraphVertex* top) const override { return new OrderEdge(graphp, fromp, top, *this); } // When ordering combo blocks with stronglyConnected, follow edges not @@ -468,19 +479,19 @@ class OrderComboCutEdge : public OrderEdge { // in which case we'll need a change detect loop around this var. OrderComboCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, const OrderComboCutEdge& old) - : OrderEdge(graphp, fromp, top, old) {} + : OrderEdge{graphp, fromp, top, old} {} public: OrderComboCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) - : OrderEdge(graphp, fromp, top, WEIGHT_COMBO, CUTABLE) {} - virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_COMBOCUT; } - virtual ~OrderComboCutEdge() {} + : OrderEdge{graphp, fromp, top, WEIGHT_COMBO, CUTABLE} {} + virtual OrderVEdgeType type() const override { return OrderVEdgeType::EDGE_COMBOCUT; } + virtual ~OrderComboCutEdge() override {} virtual OrderComboCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, - V3GraphVertex* top) const { + V3GraphVertex* top) const override { return new OrderComboCutEdge(graphp, fromp, top, *this); } - virtual string dotColor() const { return "yellowGreen"; } - virtual bool followComboConnected() const { return true; } + virtual string dotColor() const override { return "yellowGreen"; } + virtual bool followComboConnected() const override { return true; } }; class OrderPostCutEdge : public OrderEdge { @@ -489,19 +500,19 @@ class OrderPostCutEdge : public OrderEdge { // in which case we'll need a change detect loop around this var. OrderPostCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, const OrderPostCutEdge& old) - : OrderEdge(graphp, fromp, top, old) {} + : OrderEdge{graphp, fromp, top, old} {} public: OrderPostCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) - : OrderEdge(graphp, fromp, top, WEIGHT_COMBO, CUTABLE) {} - virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_POSTCUT; } - virtual ~OrderPostCutEdge() {} + : OrderEdge{graphp, fromp, top, WEIGHT_COMBO, CUTABLE} {} + virtual OrderVEdgeType type() const override { return OrderVEdgeType::EDGE_POSTCUT; } + virtual ~OrderPostCutEdge() override {} virtual OrderPostCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, - V3GraphVertex* top) const { + V3GraphVertex* top) const override { return new OrderPostCutEdge(graphp, fromp, top, *this); } - virtual string dotColor() const { return "PaleGreen"; } - virtual bool followComboConnected() const { return false; } + virtual string dotColor() const override { return "PaleGreen"; } + virtual bool followComboConnected() const override { return false; } }; class OrderPreCutEdge : public OrderEdge { @@ -510,19 +521,19 @@ class OrderPreCutEdge : public OrderEdge { // in which case we can't optimize away the pre/post delayed assignments OrderPreCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, const OrderPreCutEdge& old) - : OrderEdge(graphp, fromp, top, old) {} + : OrderEdge{graphp, fromp, top, old} {} public: OrderPreCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) - : OrderEdge(graphp, fromp, top, WEIGHT_PRE, CUTABLE) {} - virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_PRECUT; } + : OrderEdge{graphp, fromp, top, WEIGHT_PRE, CUTABLE} {} + virtual OrderVEdgeType type() const override { return OrderVEdgeType::EDGE_PRECUT; } virtual OrderPreCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp, - V3GraphVertex* top) const { + V3GraphVertex* top) const override { return new OrderPreCutEdge(graphp, fromp, top, *this); } - virtual ~OrderPreCutEdge() {} - virtual string dotColor() const { return "khaki"; } - virtual bool followComboConnected() const { return false; } + virtual ~OrderPreCutEdge() override {} + virtual string dotColor() const override { return "khaki"; } + virtual bool followComboConnected() const override { return false; } }; #endif // Guard diff --git a/src/V3Os.cpp b/src/V3Os.cpp index 97b1ce552..e7e9a8d5b 100644 --- a/src/V3Os.cpp +++ b/src/V3Os.cpp @@ -137,7 +137,7 @@ string V3Os::filenameNonExt(const string& filename) { string V3Os::filenameSubstitute(const string& filename) { string out; - enum { NONE, PAREN, CURLY } brackets = NONE; + enum : uint8_t { NONE, PAREN, CURLY } brackets = NONE; for (string::size_type pos = 0; pos < filename.length(); ++pos) { if ((filename[pos] == '$') && (pos + 1 < filename.length())) { switch (filename[pos + 1]) { @@ -259,7 +259,7 @@ string V3Os::trueRandom(size_t size) { // Note: std::string.data() returns a non-const Char* from C++17 onwards. // For pre-C++17, this cast is OK in practice, even though it's UB. #if defined(_WIN32) || defined(__MINGW32__) - NTSTATUS hr = BCryptGenRandom(NULL, reinterpret_cast(data), size, + NTSTATUS hr = BCryptGenRandom(nullptr, reinterpret_cast(data), size, BCRYPT_USE_SYSTEM_PREFERRED_RNG); if (!BCRYPT_SUCCESS(hr)) { v3fatal("Could not acquire random data."); } #else @@ -290,7 +290,7 @@ uint64_t V3Os::timeUsecs() { #else // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) timeval tv; - if (gettimeofday(&tv, NULL) < 0) return 0; + if (gettimeofday(&tv, nullptr) < 0) return 0; return static_cast(tv.tv_sec) * 1000000 + tv.tv_usec; #endif } diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 550abe513..3e07a3de2 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -52,14 +52,150 @@ #include "V3Ast.h" #include "V3Case.h" #include "V3Const.h" +#include "V3Os.h" +#include "V3Parse.h" #include "V3Width.h" #include "V3Unroll.h" #include "V3Hashed.h" #include #include +#include #include +//###################################################################### +// Hierarchical block and parameter db (modules without parameter is also handled) +class ParameterizedHierBlocks { + typedef std::multimap HierBlockOptsByOrigName; + typedef HierBlockOptsByOrigName::const_iterator HierMapIt; + typedef std::map HierBlockModMap; + typedef std::map ParamConstMap; + typedef std::map ParamsMap; + + // MEMBERS + // key:Original module name, value:HiearchyBlockOption* + // If a module is parameterized, the module is uniquiefied to overridden parameters. + // This is why HierBlockOptsByOrigName is multimap. + HierBlockOptsByOrigName m_hierBlockOptsByOrigName; + // key:mangled module name, value:AstNodeModule* + HierBlockModMap m_hierBlockMod; + // Overridden parameters of the hierarchical block + ParamsMap m_params; + + // METHODS + VL_DEBUG_FUNC; // Declare debug() + static bool areSame(AstConst* pinValuep, AstConst* hierOptParamp) { + if (pinValuep->isString()) { + return pinValuep->num().toString() == hierOptParamp->num().toString(); + } + + // Bitwidth of hierOptParamp is accurate because V3Width already caluclated in the previous + // run. Bitwidth of pinValuep is before width analysis, so pinValuep is casted to + // hierOptParamp width. + V3Number varNum(pinValuep, hierOptParamp->num().width()); + if (hierOptParamp->isDouble()) { + varNum.isDouble(true); + if (pinValuep->isDouble()) { + varNum.opAssign(pinValuep->num()); + } else { // Cast from integer to real + varNum.opIToRD(pinValuep->num()); + } + return v3EpsilonEqual(varNum.toDouble(), hierOptParamp->num().toDouble()); + } else { // Now integer type is assumed + if (pinValuep->isDouble()) { // Need to cast to int + // Parameter is actually an integral type, but passed value is floating point. + // Conversion from real to integer uses rounding in V3Width.cpp + varNum.opRToIRoundS(pinValuep->num()); + } else if (pinValuep->isSigned()) { + varNum.opExtendS(pinValuep->num(), pinValuep->num().width()); + } else { + varNum.opAssign(pinValuep->num()); + } + V3Number isEq(pinValuep, 1); + isEq.opEq(varNum, hierOptParamp->num()); + return isEq.isNeqZero(); + } + } + +public: + ParameterizedHierBlocks(const V3HierBlockOptSet& hierOpts, AstNetlist* nodep) { + for (V3HierBlockOptSet::const_iterator it = hierOpts.begin(); it != hierOpts.end(); ++it) { + m_hierBlockOptsByOrigName.insert(std::make_pair(it->second.origName(), &it->second)); + const V3HierarchicalBlockOption::ParamStrMap& params = it->second.params(); + ParamConstMap& consts = m_params[&it->second]; + for (V3HierarchicalBlockOption::ParamStrMap::const_iterator pIt = params.begin(); + pIt != params.end(); ++pIt) { + AstConst* constp = AstConst::parseParamLiteral( + new FileLine(FileLine::EmptySecret()), pIt->second); + UASSERT(constp, pIt->second << " is not a valid parameter literal"); + const bool inserted = consts.insert(std::make_pair(pIt->first, constp)).second; + UASSERT(inserted, pIt->first << " is already added"); + } + } + for (AstNodeModule* modp = nodep->modulesp(); modp; + modp = VN_CAST(modp->nextp(), NodeModule)) { + if (hierOpts.find(modp->prettyName()) != hierOpts.end()) { + m_hierBlockMod.insert(std::make_pair(modp->name(), modp)); + } + } + } + ~ParameterizedHierBlocks() { + for (ParamsMap::const_iterator it = m_params.begin(); it != m_params.end(); ++it) { + for (ParamConstMap::const_iterator pIt = it->second.begin(); pIt != it->second.end(); + ++pIt) { + delete pIt->second; + } + } + } + AstNodeModule* findByParams(const string& origName, AstPin* firstPinp, + const AstNodeModule* modp) { + if (m_hierBlockOptsByOrigName.find(origName) == m_hierBlockOptsByOrigName.end()) { + return nullptr; + } + // This module is a hierarchical block. Need to replace it by the protect-lib wrapper. + const std::pair candidates + = m_hierBlockOptsByOrigName.equal_range(origName); + HierMapIt hierIt; + for (hierIt = candidates.first; hierIt != candidates.second; ++hierIt) { + bool found = true; + size_t paramIdx = 0; + const ParamConstMap& params = m_params[hierIt->second]; + UASSERT(params.size() == hierIt->second->params().size(), "not match"); + for (AstPin* pinp = firstPinp; pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { + if (!pinp->exprp()) continue; + UASSERT_OBJ(!pinp->modPTypep(), pinp, + "module with type parameter must not be a hierarchical block"); + if (AstVar* modvarp = pinp->modVarp()) { + AstConst* constp = VN_CAST(pinp->exprp(), Const); + UASSERT_OBJ(constp, pinp, + "parameter for a hierarchical block must have been constified"); + const auto pIt = vlstd::as_const(params).find(modvarp->name()); + UINFO(5, "Comparing " << modvarp->name() << " " << constp << std::endl); + if (pIt == params.end() || paramIdx >= params.size() + || !areSame(constp, pIt->second)) { + found = false; + break; + } + UINFO(5, "Matched " << modvarp->name() << " " << constp << " and " + << pIt->second << std::endl); + ++paramIdx; + } + } + if (found && paramIdx == hierIt->second->params().size()) break; + } + UASSERT_OBJ(hierIt != candidates.second, firstPinp, "No protect-lib wrapper found"); + // parameter settings will be removed in the bottom of caller visitCell(). + const HierBlockModMap::const_iterator modIt + = m_hierBlockMod.find(hierIt->second->mangledName()); + UASSERT_OBJ(modIt != m_hierBlockMod.end(), firstPinp, + hierIt->second->mangledName() << " is not found"); + + const auto it = vlstd::as_const(m_hierBlockMod).find(hierIt->second->mangledName()); + if (it == m_hierBlockMod.end()) return nullptr; + return it->second; + } +}; + //###################################################################### // Param state, as a visitor of each AstNode @@ -79,26 +215,31 @@ private: // TYPES // Note may have duplicate entries - typedef std::deque > IfaceRefRefs; + typedef std::deque> IfaceRefRefs; // STATE typedef std::map CloneMap; struct ModInfo { AstNodeModule* m_modp; // Module with specified name CloneMap m_cloneMap; // Map of old-varp -> new cloned varp - explicit ModInfo(AstNodeModule* modp) { m_modp = modp; } + explicit ModInfo(AstNodeModule* modp) + : m_modp{modp} {} }; typedef std::map ModNameMap; ModNameMap m_modNameMap; // Hash of created module flavors by name typedef std::map LongMap; LongMap m_longMap; // Hash of very long names to unique identity number - int m_longId; + int m_longId = 0; + + // All module names that are loaded from source code + // Generated modules by this visitor is not included + V3StringSet m_allModuleNames; typedef std::pair ValueMapValue; typedef std::map ValueMap; ValueMap m_valueMap; // Hash of node hash to (param value, name) - int m_nextValue; // Next value to use in m_valueMap + int m_nextValue = 1; // Next value to use in m_valueMap typedef std::multimap LevelModMap; LevelModMap m_todoModps; // Modules left to process @@ -106,15 +247,14 @@ private: typedef std::deque CellList; CellList m_cellps; // Cells left to process (in this module) - AstNodeFTask* m_ftaskp; // Function/task reference - - AstNodeModule* m_modp; // Current module being processed - + AstNodeFTask* m_ftaskp = nullptr; // Function/task reference + AstNodeModule* m_modp = nullptr; // Current module being processed string m_unlinkedTxt; // Text for AstUnlinkedRef - UnrollStateful m_unroller; // Loop unroller + string m_generateHierName; // Generate portion of hierarchy name - string m_generateHierName; // Generate portion of hierarchical name + // Database to get protect-lib wrapper that matches parameters in hierarchical Verilation + ParameterizedHierBlocks m_hierBlocks; // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -169,7 +309,7 @@ private: // Force hash collisions -- for testing only if (VL_UNLIKELY(v3Global.opt.debugCollision())) hash = V3Hash(); int num; - ValueMap::iterator it = m_valueMap.find(hash); + const auto it = m_valueMap.find(hash); if (it != m_valueMap.end() && it->second.second == key) { num = it->second.first; } else { @@ -189,7 +329,7 @@ private: if (AstBracketArrayDType* adtypep = VN_CAST(nodep, BracketArrayDType)) { return adtypep->subDTypep(); } - return NULL; + return nullptr; } void collectPins(CloneMap* clonemapp, AstNodeModule* modp) { // Grab all I/O so we can remap our pins later @@ -215,12 +355,12 @@ private: if (pinp->modVarp()) { // Find it in the clone structure // UINFO(8,"Clone find 0x"<modVarp()<find(pinp->modVarp()); + const auto cloneiter = clonemapp->find(pinp->modVarp()); UASSERT_OBJ(cloneiter != clonemapp->end(), pinp, "Couldn't find pin in clone list"); pinp->modVarp(VN_CAST(cloneiter->second, Var)); } else if (pinp->modPTypep()) { - CloneMap::iterator cloneiter = clonemapp->find(pinp->modPTypep()); + const auto cloneiter = clonemapp->find(pinp->modPTypep()); UASSERT_OBJ(cloneiter != clonemapp->end(), pinp, "Couldn't find pin in clone list"); pinp->modPTypep(VN_CAST(cloneiter->second, ParamTypeDType)); @@ -229,13 +369,82 @@ private: } } } + void relinkPinsByName(AstPin* startpinp, AstNodeModule* modp) { + std::map nameToPin; + for (AstNode* stmtp = modp->stmtsp(); stmtp; stmtp = stmtp->nextp()) { + if (AstVar* varp = VN_CAST(stmtp, Var)) { + if (varp->isIO() || varp->isGParam() || varp->isIfaceRef()) { + nameToPin.insert(make_pair(varp->name(), varp)); + } + } + } + for (AstPin* pinp = startpinp; pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { + if (AstVar* varp = pinp->modVarp()) { + const auto varIt = vlstd::as_const(nameToPin).find(varp->name()); + UASSERT_OBJ(varIt != nameToPin.end(), varp, + "Not found in " << modp->prettyNameQ()); + pinp->modVarp(varIt->second); + } + } + } + // Check if parameter setting during instantiation is simple enough for hierarchical verilation + void checkSupportedParam(AstNodeModule* modp, AstPin* pinp) const { + // InitArray and AstParamTypeDType are not supported because that can not be set via -G + // option. + if (pinp->modVarp()) { + bool supported = false; + if (AstConst* constp = VN_CAST(pinp->exprp(), Const)) { + supported = !constp->isOpaque(); + } + if (!supported) { + pinp->v3error(AstNode::prettyNameQ(modp->origName()) + << " has hier_block metacomment, hierarchical verilation" + << " supports only integer/floating point/string parameters"); + } + } else if (VN_IS(pinp->modPTypep(), ParamTypeDType)) { + pinp->v3error(AstNode::prettyNameQ(modp->origName()) + << " has hier_block metacomment, but 'parameter type' is not supported"); + } + } + bool moduleExists(const string& modName) const { + if (m_allModuleNames.find(modName) != m_allModuleNames.end()) return true; + if (m_modNameMap.find(modName) != m_modNameMap.end()) return true; + return false; + } + string parametrizedHierBlockName(const AstNodeModule* modp, AstPin* paramPinsp) const { + VHashSha256 hash; + // Calculate hash using module name, parameter name, and parameter value + // The hash is used as the module suffix to find a module name that is unique in the design + hash.insert(modp->name()); + for (AstPin* pinp = paramPinsp; pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { + if (AstVar* varp = pinp->modVarp()) hash.insert(varp->name()); + if (AstConst* constp = VN_CAST(pinp->exprp(), Const)) { + hash.insert(constp->num().ascii(false)); + } + } + while (true) { + // Copy VHashSha256 just in case of hash collision + VHashSha256 hashStrGen = hash; + // Hex string must be a safe suffix for any symbol + const string hashStr = hashStrGen.digestHex(); + for (string::size_type i = 1; i < hashStr.size(); ++i) { + string newName = modp->name(); + // Don't use '__' not to be encoded when this module is loaded later by Verilator + if (newName.at(newName.size() - 1) != '_') newName += '_'; + newName += hashStr.substr(0, i); + if (!moduleExists(newName)) return newName; + } + // Hash collision. maybe just v3error is practically enough + hash.insert(V3Os::trueRandom(64)); + } + } void visitCell(AstCell* nodep, const string& hierName); void visitModules() { // Loop on all modules left to process // Hitting a cell adds to the appropriate level of this level-sorted list, // so since cells originally exist top->bottom we process in top->bottom order too. while (!m_todoModps.empty()) { - LevelModMap::iterator itm = m_todoModps.begin(); + const auto itm = m_todoModps.cbegin(); AstNodeModule* nodep = itm->second; m_todoModps.erase(itm); if (!nodep->user5SetOnce()) { // Process once; note clone() must clear so we do it @@ -248,8 +457,7 @@ private: // // Process interface cells, then non-interface which may ref an interface cell for (int nonIf = 0; nonIf < 2; ++nonIf) { - for (CellList::iterator it = m_cellps.begin(); it != m_cellps.end(); ++it) { - AstCell* cellp = *it; + for (AstCell* cellp : m_cellps) { if ((nonIf == 0 && VN_IS(cellp->modp(), Iface)) || (nonIf == 1 && !VN_IS(cellp->modp(), Iface))) { string fullName(m_modp->hierName()); @@ -260,25 +468,24 @@ private: } } } - for (CellList::iterator it = m_cellps.begin(); it != m_cellps.end(); ++it) { - AstCell* cellp = *it; + for (AstCell* cellp : m_cellps) { if (string* genHierNamep = (string*)cellp->user5p()) { - cellp->user5p(NULL); + cellp->user5p(nullptr); VL_DO_DANGLING(delete genHierNamep, genHierNamep); } } m_cellps.clear(); - m_modp = NULL; + m_modp = nullptr; } } } // VISITORS - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { // Modules must be done in top-down-order iterateChildren(nodep); } - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { + virtual void visit(AstNodeModule* nodep) override { if (nodep->dead()) { UINFO(4, " MOD-dead. " << nodep << endl); // Marked by LinkDot } else if (nodep->recursiveClone()) { @@ -298,20 +505,20 @@ private: UINFO(4, " MOD-dead? " << nodep << endl); } } - virtual void visit(AstCell* nodep) VL_OVERRIDE { + virtual void visit(AstCell* nodep) override { // Must do ifaces first, so push to list and do in proper order string* genHierNamep = new string(m_generateHierName); nodep->user5p(genHierNamep); m_cellps.push_back(nodep); } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTask* nodep) override { m_ftaskp = nodep; iterateChildren(nodep); - m_ftaskp = NULL; + m_ftaskp = nullptr; } // Make sure all parameters are constantified - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { if (!nodep->user5SetOnce()) { // Process once iterateChildren(nodep); if (nodep->isParam()) { @@ -346,7 +553,7 @@ private: } } // Make sure varrefs cause vars to constify before things above - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { if (nodep->varp()) iterate(nodep->varp()); } bool ifaceParamReplace(AstVarXRef* nodep, AstNode* candp) { @@ -366,7 +573,7 @@ private: } return false; } - virtual void visit(AstVarXRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarXRef* nodep) override { // Check to see if the scope is just an interface because interfaces are special string dotted = nodep->dotted(); if (!dotted.empty() && nodep->varp() && nodep->varp()->isParam()) { @@ -409,10 +616,10 @@ private: } } } - nodep->varp(NULL); // Needs relink, as may remove pointed-to var + nodep->varp(nullptr); // Needs relink, as may remove pointed-to var } - virtual void visit(AstUnlinkedRef* nodep) VL_OVERRIDE { + virtual void visit(AstUnlinkedRef* nodep) override { AstVarXRef* varxrefp = VN_CAST(nodep->op1p(), VarXRef); AstNodeFTaskRef* taskrefp = VN_CAST(nodep->op1p(), NodeFTaskRef); if (varxrefp) { @@ -433,7 +640,7 @@ private: nodep->replaceWith(nodep->op1p()->unlinkFrBack()); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstCellArrayRef* nodep) VL_OVERRIDE { + virtual void visit(AstCellArrayRef* nodep) override { V3Const::constifyParamsEdit(nodep->selp()); if (const AstConst* constp = VN_CAST(nodep->selp(), Const)) { string index = AstNode::encodeNumber(constp->toSInt()); @@ -452,7 +659,7 @@ private: } // Generate Statements - virtual void visit(AstGenIf* nodep) VL_OVERRIDE { + virtual void visit(AstGenIf* nodep) override { UINFO(9, " GENIF " << nodep << endl); iterateAndNextNull(nodep->condp()); // We suppress errors when widthing params since short-circuiting in @@ -480,7 +687,7 @@ private: //! @todo Unlike generated IF, we don't have to worry about short-circuiting the conditional //! expression, since this is currently restricted to simple comparisons. If we ever do //! move to more generic constant expressions, such code will be needed here. - virtual void visit(AstBegin* nodep) VL_OVERRIDE { + virtual void visit(AstBegin* nodep) override { if (nodep->genforp()) { AstGenFor* forp = VN_CAST(nodep->genforp(), GenFor); UASSERT_OBJ(forp, nodep, "Non-GENFOR under generate-for BEGIN"); @@ -513,12 +720,12 @@ private: m_generateHierName = rootHierName; } } - virtual void visit(AstGenFor* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE + virtual void visit(AstGenFor* nodep) override { // LCOV_EXCL_LINE nodep->v3fatalSrc("GENFOR should have been wrapped in BEGIN"); } - virtual void visit(AstGenCase* nodep) VL_OVERRIDE { + virtual void visit(AstGenCase* nodep) override { UINFO(9, " GENCASE " << nodep << endl); - AstNode* keepp = NULL; + AstNode* keepp = nullptr; iterateAndNextNull(nodep->exprp()); V3Case::caseLint(nodep); V3Width::widthParamsEdit(nodep); // Param typed widthing will NOT recurse the body, @@ -567,19 +774,20 @@ 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 - explicit ParamVisitor(AstNetlist* nodep) { - m_longId = 0; - m_ftaskp = NULL; - m_modp = NULL; - m_nextValue = 1; + explicit ParamVisitor(AstNetlist* nodep) + : m_hierBlocks{v3Global.opt.hierBlocks(), nodep} { + for (AstNodeModule* modp = nodep->modulesp(); modp; + modp = VN_CAST(modp->nextp(), NodeModule)) { + m_allModuleNames.insert(modp->name()); + } // iterate(nodep); } - virtual ~ParamVisitor() {} + virtual ~ParamVisitor() override {} }; //---------------------------------------------------------------------- @@ -682,7 +890,7 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) { portIrefp = VN_CAST(arraySubDTypep(modvarp->subDTypep()), IfaceRefDType); } - AstIfaceRefDType* pinIrefp = NULL; + AstIfaceRefDType* pinIrefp = nullptr; AstNode* exprp = pinp->exprp(); if (exprp && VN_IS(exprp, VarRef) && VN_CAST(exprp, VarRef)->varp() && VN_CAST(exprp, VarRef)->varp()->subDTypep() @@ -740,19 +948,31 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) { if (!any_overrides) { UINFO(8, "Cell parameters all match original values, skipping expansion.\n"); + } else if (AstNodeModule* modp + = m_hierBlocks.findByParams(srcModp->name(), nodep->paramsp(), m_modp)) { + nodep->modp(modp); + nodep->modName(modp->name()); + modp->dead(false); + // We need to relink the pins to the new module + relinkPinsByName(nodep->pinsp(), modp); } else { // If the name is very long, we don't want to overwhelm the filename limit // We don't do this always, as it aids debugability to have intuitive naming. // TODO can use new V3Name hash replacement instead of this + // Shorter name is convenient for hierarchical block string newname = longname; - if (longname.length() > 30) { - LongMap::iterator iter = m_longMap.find(longname); + if (longname.length() > 30 || srcModp->hierBlock()) { + const auto iter = m_longMap.find(longname); if (iter != m_longMap.end()) { newname = iter->second; } else { - newname = srcModp->name(); - // We use all upper case above, so lower here can't conflict - newname += "__pi" + cvtToStr(++m_longId); + if (srcModp->hierBlock()) { + newname = parametrizedHierBlockName(srcModp, nodep->paramsp()); + } else { + newname = srcModp->name(); + // We use all upper case above, so lower here can't conflict + newname += "__pi" + cvtToStr(++m_longId); + } m_longMap.insert(make_pair(longname, newname)); } } @@ -760,8 +980,8 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) { // // Already made this flavor? - AstNodeModule* cellmodp = NULL; - ModNameMap::iterator iter = m_modNameMap.find(newname); + AstNodeModule* cellmodp = nullptr; + auto iter = m_modNameMap.find(newname); if (iter != m_modNameMap.end()) cellmodp = iter->second.m_modp; if (!cellmodp) { // Deep clone of new module @@ -772,6 +992,8 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) { cellmodp->user5(false); // We need to re-recurse this module once changed cellmodp->recursive(false); cellmodp->recursiveClone(false); + // Only the first generation of clone holds this property + cellmodp->hierBlock(srcModp->hierBlock() && !srcModp->recursiveClone()); nodep->recursive(false); // Recursion may need level cleanups if (cellmodp->level() <= m_modp->level()) cellmodp->level(m_modp->level() + 1); @@ -814,17 +1036,18 @@ void ParamVisitor::visitCell(AstCell* nodep, const string& hierName) { cloneIrefp->ifacep(pinIrefp->ifaceViaCellp()); UINFO(8, " IfaceNew " << cloneIrefp << endl); } - // Assign parameters to the constants specified // DOES clone() so must be finished with module clonep() before here for (AstPin* pinp = nodep->paramsp(); pinp; pinp = VN_CAST(pinp->nextp(), Pin)) { if (pinp->exprp()) { + if (cellmodp->hierBlock()) checkSupportedParam(cellmodp, pinp); if (AstVar* modvarp = pinp->modVarp()) { AstNode* newp = pinp->exprp(); // Const or InitArray // Remove any existing parameter if (modvarp->valuep()) modvarp->valuep()->unlinkFrBack()->deleteTree(); // Set this parameter to value requested by cell modvarp->valuep(newp->cloneTree(false)); + modvarp->overriddenParam(true); } else if (AstParamTypeDType* modptp = pinp->modPTypep()) { AstNodeDType* dtypep = VN_CAST(pinp->exprp(), NodeDType); UASSERT_OBJ(dtypep, pinp, "unlinked param dtype"); diff --git a/src/V3ParseGrammar.cpp b/src/V3ParseGrammar.cpp index 00c3f4f23..ae478171d 100644 --- a/src/V3ParseGrammar.cpp +++ b/src/V3ParseGrammar.cpp @@ -32,7 +32,7 @@ int V3ParseImp::bisonParse() { const char* V3ParseImp::tokenName(int token) { #if YYDEBUG || YYERROR_VERBOSE - static const char** nameTablep = NULL; + static const char** nameTablep = nullptr; if (!nameTablep) { int size; for (size = 0; yytname[size]; ++size) {} @@ -59,7 +59,7 @@ const char* V3ParseImp::tokenName(int token) { void V3ParseImp::parserClear() { // Clear up any dynamic memory V3Parser required - VARDTYPE(NULL); + VARDTYPE(nullptr); } //====================================================================== @@ -67,8 +67,8 @@ void V3ParseImp::parserClear() { AstNode* V3ParseGrammar::argWrapList(AstNode* nodep) { // Convert list of expressions to list of arguments - if (!nodep) return NULL; - AstNode* outp = NULL; + if (!nodep) return nullptr; + AstNode* outp = nullptr; AstBegin* tempp = new AstBegin(nodep->fileline(), "[EditWrapper]", nodep); while (nodep) { AstNode* nextp = nodep->nextp(); @@ -152,7 +152,7 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, const string& name, if (GRAMMARP->m_varIO == VDirection::NONE && GRAMMARP->m_varDecl == AstVarType::PORT) { // Just a port list with variable name (not v2k format); AstPort already created if (dtypep) fileline->v3warn(E_UNSUPPORTED, "Unsupported: Ranges ignored in port-lists"); - return NULL; + return nullptr; } if (GRAMMARP->m_varDecl == AstVarType::WREAL) { // dtypep might not be null, might be implicit LOGIC before we knew better diff --git a/src/V3ParseImp.cpp b/src/V3ParseImp.cpp index 55e9994c9..c4b1766a4 100644 --- a/src/V3ParseImp.cpp +++ b/src/V3ParseImp.cpp @@ -41,7 +41,7 @@ //====================================================================== // Globals -V3ParseImp* V3ParseImp::s_parsep = NULL; +V3ParseImp* V3ParseImp::s_parsep = nullptr; int V3ParseSym::s_anonNum = 0; @@ -195,7 +195,7 @@ double V3ParseImp::lexParseTimenum(const char* textp) { if (*sp != '_') *dp++ = *sp; } *dp++ = '\0'; - double d = strtod(strgp, NULL); + double d = strtod(strgp, nullptr); string suffix(sp); double divisor = 1; @@ -292,8 +292,8 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i if (v3Global.opt.preprocOnly() || v3Global.opt.keepTempFiles()) { // Create output file with all the preprocessor output we buffered up string vppfilename - = v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "_" + modname + ".vpp"; - std::ofstream* ofp = NULL; + = v3Global.opt.hierTopDataDir() + "/" + v3Global.opt.prefix() + "_" + modname + ".vpp"; + std::ofstream* ofp = nullptr; std::ostream* osp; if (v3Global.opt.preprocOnly()) { osp = &cout; @@ -382,6 +382,7 @@ void V3ParseImp::tokenPipeline() { int token = yylval.token; // If a paren, read another if (token == '(' // + || token == ':' // || token == yCONST__LEX // || token == yGLOBAL__LEX // || token == yLOCAL__LEX // @@ -402,6 +403,12 @@ void V3ParseImp::tokenPipeline() { if (token == '(' && (nexttok == ygenSTRENGTH || nexttok == ySUPPLY0 || nexttok == ySUPPLY1)) { token = yP_PAR__STRENGTH; + } else if (token == ':') { + if (nexttok == yBEGIN) { + token = yP_COLON__BEGIN; + } else if (nexttok == yFORK) { + token = yP_COLON__FORK; + } } else if (token == yCONST__LEX) { if (nexttok == yREF) { token = yCONST__REF; @@ -489,7 +496,7 @@ void V3ParseImp::tokenPipelineSym() { // if (debug() >= 7) V3ParseImp::parsep()->symp()->dump(cout, " -symtree: "); foundp = look_underp->findIdFallback(*(yylval.strp)); // "consume" it. Must set again if want another token under temp scope - V3ParseImp::parsep()->symp()->nextId(NULL); + V3ParseImp::parsep()->symp()->nextId(nullptr); } else { UINFO(7, " tokenPipelineSym: find upward " << V3ParseImp::parsep()->symp()->symCurrentp() << " for '" @@ -519,10 +526,10 @@ void V3ParseImp::tokenPipelineSym() { && (*(yylval.strp) == "mailbox" // IEEE-standard class || *(yylval.strp) == "process" // IEEE-standard class || *(yylval.strp) == "semaphore")) { // IEEE-standard class - yylval.scp = NULL; + yylval.scp = nullptr; if (token == yaID__LEX) token = yaID__aTYPE; } else { // Not found - yylval.scp = NULL; + yylval.scp = nullptr; if (token == yaID__CC) { // IEEE does require this, but we may relax this as UVM breaks it, so allow bbox // for today @@ -531,9 +538,9 @@ void V3ParseImp::tokenPipelineSym() { // is missing package, and this confuses people static int warned = false; if (!warned++) { - yylval.fl->v3error( - "Package/class '" + *yylval.strp - + "' not found, and needs to be predeclared (IEEE 1800-2017 26.3)"); + yylval.fl->v3warn(PKGNODECL, "Package/class '" + *yylval.strp + + "' not found, and needs to be " + "predeclared (IEEE 1800-2017 26.3)"); } } } else if (token == yaID__LEX) { @@ -550,7 +557,7 @@ int V3ParseImp::tokenToBison() { tokenPipelineSym(); // sets yylval m_bisonLastFileline = yylval.fl; - // yylval.scp = NULL; // Symbol table not yet needed - no packages + // yylval.scp = nullptr; // Symbol table not yet needed - no packages if (debugFlex() >= 6 || debugBison() >= 6) { // --debugi-flex and --debugi-bison cout << "tokenToBison " << yylval << endl; } @@ -579,7 +586,7 @@ V3Parse::V3Parse(AstNetlist* rootp, VInFilter* filterp, V3ParseSym* symp) { m_impp = new V3ParseImp(rootp, filterp, symp); } V3Parse::~V3Parse() { // - VL_DO_CLEAR(delete m_impp, m_impp = NULL); + VL_DO_CLEAR(delete m_impp, m_impp = nullptr); } void V3Parse::parseFile(FileLine* fileline, const string& modname, bool inLibrary, const string& errmsg) { diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index d9d5ae2f1..c460ee22a 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -37,9 +37,9 @@ class V3Lexer; //====================================================================== // Types (between parser & lexer) -typedef enum { uniq_NONE, uniq_UNIQUE, uniq_UNIQUE0, uniq_PRIORITY } V3UniqState; +typedef enum : uint8_t { uniq_NONE, uniq_UNIQUE, uniq_UNIQUE0, uniq_PRIORITY } V3UniqState; -typedef enum { iprop_NONE, iprop_CONTEXT, iprop_PURE } V3ImportProperty; +typedef enum : uint8_t { iprop_NONE, iprop_CONTEXT, iprop_PURE } V3ImportProperty; //============================================================================ // Member qualifiers @@ -129,6 +129,7 @@ struct V3ParseBisonYYSType { AstClass* classp; AstConst* constp; AstFork* forkp; + AstFunc* funcp; AstMemberDType* memberp; AstNodeModule* modulep; AstNodeUOrStructDType* uorstructp; @@ -180,7 +181,7 @@ class V3ParseImp { std::deque m_lexLintState; // Current lint state for save/restore std::deque m_ppBuffers; // Preprocessor->lex buffer of characters to process - AstNode* m_tagNodep; // Points to the node to set to m_tag or NULL to not set. + AstNode* m_tagNodep; // Points to the node to set to m_tag or nullptr to not set. VTimescale m_timeLastUnit; // Last `timescale's unit public: @@ -301,16 +302,16 @@ public: public: // CONSTRUCTORS V3ParseImp(AstNetlist* rootp, VInFilter* filterp, V3ParseSym* parserSymp) - : m_rootp(rootp) - , m_filterp(filterp) - , m_symp(parserSymp) { - m_lexFileline = NULL; - m_lexerp = NULL; + : m_rootp{rootp} + , m_filterp{filterp} + , m_symp{parserSymp} { + m_lexFileline = nullptr; + m_lexerp = nullptr; m_inLibrary = false; m_lexKwdDepth = 0; m_lexKwdLast = stateVerilogRecent(); m_lexPrevToken = 0; - m_tagNodep = NULL; + m_tagNodep = nullptr; m_timeLastUnit = v3Global.opt.timeDefaultUnit(); } ~V3ParseImp(); diff --git a/src/V3ParseLex.cpp b/src/V3ParseLex.cpp index 06b2a4024..9ec3731b2 100644 --- a/src/V3ParseLex.cpp +++ b/src/V3ParseLex.cpp @@ -36,7 +36,7 @@ class V3Lexer : public V3LexerBase { public: // CONSTRUCTORS V3Lexer() - : V3LexerBase(NULL) {} + : V3LexerBase{nullptr} {} ~V3Lexer() {} // METHODS void unputString(const char* textp, size_t length) { @@ -68,5 +68,5 @@ void V3ParseImp::lexNew() { } void V3ParseImp::lexDestroy() { - if (m_lexerp) VL_DO_CLEAR(delete m_lexerp, m_lexerp = NULL); + if (m_lexerp) VL_DO_CLEAR(delete m_lexerp, m_lexerp = nullptr); } diff --git a/src/V3ParseSym.h b/src/V3ParseSym.h index 2befc7669..3837aa096 100644 --- a/src/V3ParseSym.h +++ b/src/V3ParseSym.h @@ -38,17 +38,16 @@ private: // MEMBERS static int s_anonNum; // Number of next anonymous object (parser use only) VSymGraph m_syms; // Graph of symbol tree - VSymEnt* m_symTableNextId; // Symbol table for next lexer lookup (parser use only) + VSymEnt* m_symTableNextId = nullptr; // Symbol table for next lexer lookup (parser use only) VSymEnt* m_symCurrentp; // Active symbol table for additions/lookups SymStack m_sympStack; // Stack of upper nodes with pending symbol tables public: // CONSTRUCTORS explicit V3ParseSym(AstNetlist* rootp) - : m_syms(rootp) { + : m_syms{rootp} { s_anonNum = 0; // Number of next anonymous object pushScope(findNewTable(rootp)); - m_symTableNextId = NULL; m_symCurrentp = symCurrentp(); } ~V3ParseSym() {} @@ -77,11 +76,11 @@ public: UINFO(9, "symTableNextId under " << entp << "-" << entp->type().ascii() << endl); m_symTableNextId = getTable(entp); } else { - UINFO(9, "symTableNextId under NULL" << endl); - m_symTableNextId = NULL; + UINFO(9, "symTableNextId under nullptr" << endl); + m_symTableNextId = nullptr; } } - void reinsert(AstNode* nodep, VSymEnt* parentp = NULL) { + void reinsert(AstNode* nodep, VSymEnt* parentp = nullptr) { reinsert(nodep, parentp, nodep->name()); } void reinsert(AstNode* nodep, VSymEnt* parentp, string name) { @@ -91,7 +90,7 @@ public: } parentp->reinsert(name, findNewTable(nodep)); } - void pushNew(AstNode* nodep) { pushNewUnder(nodep, NULL); } + void pushNew(AstNode* nodep) { pushNewUnder(nodep, nullptr); } void pushNewUnder(AstNode* nodep, VSymEnt* parentp) { if (!parentp) parentp = symCurrentp(); VSymEnt* symp @@ -104,7 +103,7 @@ public: if (parentp) { pushNewUnder(nodep, findNewTable(parentp)); } else { - pushNewUnder(nodep, NULL); + pushNewUnder(nodep, nullptr); } } void pushScope(VSymEnt* symp) { @@ -128,8 +127,7 @@ public: } void showUpward() { UINFO(1, "ParseSym Stack:\n"); - for (SymStack::reverse_iterator it = m_sympStack.rbegin(); it != m_sympStack.rend(); - ++it) { + for (auto it = m_sympStack.rbegin(); it != m_sympStack.rend(); ++it) { VSymEnt* symp = *it; UINFO(1, " " << symp->nodep() << endl); } @@ -142,7 +140,7 @@ public: if (foundp) { return foundp->nodep(); } else { - return NULL; + return nullptr; } } void importExtends(AstNode* classp) { diff --git a/src/V3Partition.cpp b/src/V3Partition.cpp index aca9696c1..e15e06c20 100644 --- a/src/V3Partition.cpp +++ b/src/V3Partition.cpp @@ -29,7 +29,7 @@ #include #include -#include VL_INCLUDE_UNORDERED_SET +#include class MergeCandidate; @@ -72,9 +72,9 @@ class MergeCandidate; // If you don't care about partitioner runtime and you want the most // aggressive partition, set the limit very high. If you have huge // vertices, leave this as is. -#define PART_SIBLING_EDGE_LIMIT 25 +constexpr unsigned PART_SIBLING_EDGE_LIMIT = 25; -// PART_STEPPED_COST (boolean) +// PART_STEPPED_COST (defined/undef) // // When computing critical path costs, use a step function on the actual // underlying vertex cost. @@ -106,28 +106,6 @@ class MergeCandidate; // behavior. #define PART_STEPPED_COST true -// PART_STEPPED_RESCORE_LIMIT (boolean) -// -// If false, we always try to merge the absolute lowest (best) scoring -// mtask pair among all candidates. -// -// If true, we're willing to merge mtask pairs with scores up to 5% higher -// (worse) than the best, in exchange for doing a Rescore() operation -// somewhat less often. -// -// A true setting can result in a much faster compile in the presence of -// huge vertices, eg. 45 minutes versus 4.5 minutes for one particular -// model. HOWEVER, a true setting usually results in modestly worse -// partitions, often around 10% more MTasks and 10% longer cycle times. -// -// (TODO: Why does this setting save time with huge vertices? -// Is there a way to get best of both worlds without the trade off?) -// -// If you have huge vertices, you may wish to set this true. If you don't -// have huge vertices (which should be everyone, we think, now that V3Split -// is fixed) leave it set false for the most aggressive partition. -#define PART_STEPPED_RESCORE_LIMIT false - // Don't produce more than a certain maximum number of MTasks. This helps // the TSP variable sort not to blow up (a concern for some of the tests) // and we probably don't want a huge number of mtasks in practice anyway @@ -136,7 +114,7 @@ class MergeCandidate; // If the user doesn't give one with '--threads-max-mtasks', we'll set the // maximum # of MTasks to // (# of threads * PART_DEFAULT_MAX_MTASKS_PER_THREAD) -#define PART_DEFAULT_MAX_MTASKS_PER_THREAD 50 +constexpr unsigned PART_DEFAULT_MAX_MTASKS_PER_THREAD = 50; // end tunables. @@ -185,7 +163,7 @@ private: // // from graph-start to current node, or REVERSE // // from graph-end to current node. T_CostAccessor* m_accessp; // Access cost and CPs on V3GraphVertex's. - vluint64_t m_generation; // Mark each vertex with this number; + vluint64_t m_generation = 0; // Mark each vertex with this number; // // confirm we only process each vertex once. bool m_slowAsserts; // Enable nontrivial asserts typedef SortByValueMap PropCpPendSet; @@ -195,11 +173,10 @@ public: // CONSTRUCTORS PartPropagateCp(V3Graph* graphp, GraphWay way, T_CostAccessor* accessp, bool slowAsserts, V3EdgeFuncP edgeFuncp = &V3GraphEdge::followAlwaysTrue) - : GraphAlg<>(graphp, edgeFuncp) - , m_way(way) - , m_accessp(accessp) - , m_generation(0) - , m_slowAsserts(slowAsserts) {} + : GraphAlg<>{graphp, edgeFuncp} + , m_way{way} + , m_accessp{accessp} + , m_slowAsserts{slowAsserts} {} // METHODS void cpHasIncreased(V3GraphVertex* vxp, uint32_t newInclusiveCp) { @@ -245,7 +222,7 @@ public: // // This generalizes to multiple seed nodes also. while (!m_pending.empty()) { - PropCpPendSet::reverse_iterator it = m_pending.rbegin(); + const auto it = m_pending.rbegin(); V3GraphVertex* updateMep = (*it).key(); uint32_t cpGrowBy = (*it).value(); m_pending.erase(it); @@ -271,7 +248,7 @@ private: // MEMBERS V3Graph m_graph; // A graph V3GraphVertex* m_vx[50]; // All vertices within the graph - typedef vl_unordered_map CpMap; + typedef std::unordered_map CpMap; CpMap m_cp; // Vertex-to-CP map CpMap m_seen; // Set of vertices we've seen @@ -298,12 +275,12 @@ private: // Confirm that we only set each node's CP once. That's an // important property of PartPropagateCp which allows it to be far // faster than a recursive algorithm on some graphs. - CpMap::iterator it = m_seen.find(vxp); + const auto it = m_seen.find(vxp); UASSERT_OBJ(it == m_seen.end(), vxp, "Set CP on node twice"); m_seen[vxp] = cost; } uint32_t critPathCost(V3GraphVertex* vxp, GraphWay way) const { - CpMap::const_iterator it = m_cp.find(vxp); + const auto it = m_cp.find(vxp); if (it != m_cp.end()) return it->second; return 0; } @@ -426,7 +403,7 @@ public: LogicMTask* mtaskp = dynamic_cast(vxp); EdgeSet& edges = mtaskp->m_edges[way.invert()]; // This is mtaskp's relative with longest !wayward inclusive CP: - EdgeSet::reverse_iterator edgeIt = edges.rbegin(); + const auto edgeIt = edges.rbegin(); uint32_t edgeCp = (*edgeIt).value(); UASSERT_OBJ(edgeCp == cp, vxp, "CP doesn't match longest wayward edge"); } @@ -445,7 +422,7 @@ private: // Cost estimate for this LogicMTask, derived from V3InstrCount. // In abstract time units. - uint32_t m_cost; + uint32_t m_cost = 0; // Cost of critical paths going FORWARD from graph-start to the start // of this vertex, and also going REVERSE from the end of the graph to @@ -458,7 +435,7 @@ private: // graph. We'll mark each node with the last generation that scanned // it. We can use this to avoid recursing through the same node twice // while searching for a path. - vluint64_t m_generation; + vluint64_t m_generation = 0; // Redundant with the V3GraphEdge's, store a map of relatives so we can // quickly check if we have a given parent or child. @@ -473,9 +450,7 @@ private: public: // CONSTRUCTORS LogicMTask(V3Graph* graphp, MTaskMoveVertex* mtmvVxp) - : AbstractLogicMTask(graphp) - , m_cost(0) - , m_generation(0) { + : AbstractLogicMTask{graphp} { for (int i = 0; i < GraphWay::NUM_WAYS; ++i) m_critPathCost[i] = 0; if (mtmvVxp) { // Else null for test m_vertices.push_back(mtmvVxp); @@ -495,7 +470,7 @@ public: m_vertices.splice(m_vertices.end(), otherp->m_vertices); m_cost += otherp->m_cost; } - virtual const VxList* vertexListp() const { return &m_vertices; } + virtual const VxList* vertexListp() const override { return &m_vertices; } static vluint64_t incGeneration() { static vluint64_t s_generation = 0; ++s_generation; @@ -505,10 +480,10 @@ public: // Use this instead of pointer-compares to compare LogicMTasks. Avoids // nondeterministic output. Also name mtasks based on this number in // the final C++ output. - virtual uint32_t id() const { return m_serialId; } + virtual uint32_t id() const override { return m_serialId; } void id(uint32_t id) { m_serialId = id; } // Abstract cost of every logic mtask - virtual uint32_t cost() const { return m_cost; } + virtual uint32_t cost() const override { return m_cost; } void setCost(uint32_t cost) { m_cost = cost; } // For tests only uint32_t stepCost() const { return stepCost(m_cost); } static uint32_t stepCost(uint32_t cost) { @@ -559,7 +534,7 @@ public: } } - virtual string name() const { + virtual string name() const override { // Display forward and reverse critical path costs. This gives a quick // read on whether graph partitioning looks reasonable or bad. std::ostringstream out; @@ -628,7 +603,7 @@ private: followp = followp->outNextp()) { if (followp == excludedEdgep) continue; LogicMTask* nextp = dynamic_cast(followp->top()); - if (pathExistsFromInternal(nextp, top, NULL, generation)) return true; + if (pathExistsFromInternal(nextp, top, nullptr, generation)) return true; } return false; } @@ -636,8 +611,8 @@ private: // True if there's a path from 'fromp' to 'top' excluding // 'excludedEdgep', false otherwise. // - // 'excludedEdgep' may be NULL in which case no edge is excluded. If - // 'excludedEdgep' is non-NULL it must connect fromp and top. + // 'excludedEdgep' may be nullptr in which case no edge is excluded. If + // 'excludedEdgep' is non-nullptr it must connect fromp and top. // // TODO: consider changing this API to the 'isTransitiveEdge' API // used by GraphPathChecker @@ -650,12 +625,12 @@ public: static void dumpCpFilePrefixed(const V3Graph* graphp, const string& nameComment) { string filename = v3Global.debugFilename(nameComment) + ".txt"; UINFO(1, "Writing " << filename << endl); - vl_unique_ptr ofp(V3File::new_ofstream(filename)); + std::unique_ptr ofp(V3File::new_ofstream(filename)); std::ostream* osp = &(*ofp); // &* needed to deref unique_ptr if (osp->fail()) v3fatalStatic("Can't write " << filename); // Find start vertex with longest CP - const LogicMTask* startp = NULL; + const LogicMTask* startp = nullptr; for (const V3GraphVertex* vxp = graphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) { const LogicMTask* mtaskp = dynamic_cast(vxp); @@ -679,7 +654,7 @@ public: const EdgeSet& children = nextp->m_edges[GraphWay::FORWARD]; EdgeSet::const_reverse_iterator it = children.rbegin(); if (it == children.rend()) { - nextp = NULL; + nextp = nullptr; } else { nextp = (*it).key(); } @@ -689,8 +664,7 @@ public: << " (should match the computed critical path cost (CP) for the graph)\n"; // Dump - for (std::vector::iterator it = path.begin(); it != path.end(); ++it) { - const LogicMTask* mtaskp = *it; + for (const LogicMTask* mtaskp : path) { *osp << "begin mtask with cost " << mtaskp->cost() << endl; for (VxList::const_iterator lit = mtaskp->vertexListp()->begin(); lit != mtaskp->vertexListp()->end(); ++lit) { @@ -730,12 +704,11 @@ public: // Information associated with scoreboarding an MTask class MergeCandidate { private: - bool m_removedFromSb; // Not on scoreboard, generally ignore + bool m_removedFromSb = false; // Not on scoreboard, generally ignore vluint64_t m_id; // Serial number for ordering public: // CONSTRUCTORS - MergeCandidate() - : m_removedFromSb(false) { + MergeCandidate() { static vluint64_t serial = 0; ++serial; m_id = serial; @@ -754,7 +727,7 @@ private: LogicMTask* m_ap; LogicMTask* m_bp; // CONSTRUCTORS - SiblingMC() VL_EQ_DELETE; + SiblingMC() = delete; public: SiblingMC(LogicMTask* ap, LogicMTask* bp) { @@ -773,8 +746,8 @@ public: LogicMTask* ap() const { return m_ap; } LogicMTask* bp() const { return m_bp; } bool mergeWouldCreateCycle() const { - return (LogicMTask::pathExistsFrom(m_ap, m_bp, NULL) - || LogicMTask::pathExistsFrom(m_bp, m_ap, NULL)); + return (LogicMTask::pathExistsFrom(m_ap, m_bp, nullptr) + || LogicMTask::pathExistsFrom(m_bp, m_ap, nullptr)); } bool operator<(const SiblingMC& other) const { if (m_ap->id() < other.m_ap->id()) { return true; } @@ -788,11 +761,11 @@ class MTaskEdge : public V3GraphEdge, public MergeCandidate { public: // CONSTRUCTORS MTaskEdge(V3Graph* graphp, LogicMTask* fromp, LogicMTask* top, int weight) - : V3GraphEdge(graphp, fromp, top, weight) { + : V3GraphEdge{graphp, fromp, top, weight} { fromp->addRelative(GraphWay::FORWARD, top); top->addRelative(GraphWay::REVERSE, fromp); } - virtual ~MTaskEdge() { + virtual ~MTaskEdge() override { fromMTaskp()->removeRelative(GraphWay::FORWARD, toMTaskp()); toMTaskp()->removeRelative(GraphWay::REVERSE, fromMTaskp()); } @@ -802,11 +775,11 @@ public: } LogicMTask* fromMTaskp() const { return dynamic_cast(fromp()); } LogicMTask* toMTaskp() const { return dynamic_cast(top()); } - virtual bool mergeWouldCreateCycle() const { + virtual bool mergeWouldCreateCycle() const override { return LogicMTask::pathExistsFrom(fromMTaskp(), toMTaskp(), this); } static MTaskEdge* cast(V3GraphEdge* edgep) { - if (!edgep) return NULL; + if (!edgep) return nullptr; MTaskEdge* resultp = dynamic_cast(edgep); UASSERT(resultp, "Failed to cast in MTaskEdge::cast"); return resultp; @@ -852,23 +825,19 @@ class PartParallelismEst { // The ratio of m_totalGraphCost to longestCpCost gives us an estimate // of the parallelizability of this graph which is only as good as the // guess returned by LogicMTask::cost(). - uint32_t m_totalGraphCost; + uint32_t m_totalGraphCost = 0; // Cost of the longest critical path, in abstract units (the same units // returned by the vertexCost) - uint32_t m_longestCpCost; + uint32_t m_longestCpCost = 0; - size_t m_vertexCount; // Number of vertexes calculated - size_t m_edgeCount; // Number of edges calculated + size_t m_vertexCount = 0; // Number of vertexes calculated + size_t m_edgeCount = 0; // Number of edges calculated public: // CONSTRUCTORS explicit PartParallelismEst(const V3Graph* graphp) - : m_graphp(graphp) - , m_totalGraphCost(0) - , m_longestCpCost(0) - , m_vertexCount(0) - , m_edgeCount(0) {} + : m_graphp{graphp} {} // METHODS uint32_t totalGraphCost() const { return m_totalGraphCost; } @@ -881,7 +850,7 @@ public: void traverse() { // For each node, record the critical path cost from the start // of the graph through the end of the node. - vl_unordered_map critPaths; + std::unordered_map critPaths; GraphStreamUnordered serialize(m_graphp); for (const V3GraphVertex* vertexp; (vertexp = serialize.nextp());) { m_vertexCount++; @@ -904,14 +873,14 @@ public: m_totalGraphCost += vertexCost(vertexp); } } - void statsReport(const string& stage) { + void statsReport(const string& stage) const { V3Stats::addStat("MTask graph, " + stage + ", critical path cost", m_longestCpCost); V3Stats::addStat("MTask graph, " + stage + ", total graph cost", m_totalGraphCost); V3Stats::addStat("MTask graph, " + stage + ", mtask count", m_vertexCount); V3Stats::addStat("MTask graph, " + stage + ", edge count", m_edgeCount); V3Stats::addStat("MTask graph, " + stage + ", parallelism factor", parallelismFactor()); } - void debugReport() { + void debugReport() const { UINFO(0, " Critical path cost = " << m_longestCpCost << endl); UINFO(0, " Total graph cost = " << m_totalGraphCost << endl); UINFO(0, " MTask vertex count = " << m_vertexCount << endl); @@ -938,7 +907,7 @@ static void partInitHalfCriticalPaths(GraphWay way, V3Graph* mtasksp, bool check const LogicMTask* mtaskcp = dynamic_cast(vertexp); LogicMTask* mtaskp = const_cast(mtaskcp); uint32_t cpCost = 0; - vl_unordered_set relatives; + std::unordered_set relatives; for (V3GraphEdge* edgep = vertexp->beginp(rev); edgep; edgep = edgep->nextp(rev)) { // Run a few asserts on the initial mtask graph, // while we're iterating through... @@ -1066,11 +1035,11 @@ private: // TYPES // TODO: might get a little more speed by making this a - // vl_unordered_set and defining hash and equal_to functors for the + // std::unordered_set and defining hash and equal_to functors for the // SiblingMC: typedef std::set SibSet; - typedef vl_unordered_set SibpSet; - typedef vl_unordered_map MTask2Sibs; + typedef std::unordered_set SibpSet; + typedef std::unordered_map MTask2Sibs; // New CP information for mtaskp reflecting an upcoming merge struct NewCp { @@ -1082,8 +1051,8 @@ private: // MEMBERS V3Graph* m_mtasksp; // Mtask graph uint32_t m_scoreLimit; // Sloppy score allowed when picking merges - uint32_t m_scoreLimitBeforeRescore; // Next score rescore at - unsigned m_mergesSinceRescore; // Merges since last rescore + uint32_t m_scoreLimitBeforeRescore = 0xffffffff; // Next score rescore at + unsigned m_mergesSinceRescore = 0; // Merges since last rescore bool m_slowAsserts; // Take extra time to validate algorithm V3Scoreboard m_sb; // Scoreboard SibSet m_pairs; // Storage for each SiblingMC @@ -1092,12 +1061,10 @@ private: public: // CONSTRUCTORS PartContraction(V3Graph* mtasksp, uint32_t scoreLimit, bool slowAsserts) - : m_mtasksp(mtasksp) - , m_scoreLimit(scoreLimit) - , m_scoreLimitBeforeRescore(0xffffffff) - , m_mergesSinceRescore(0) - , m_slowAsserts(slowAsserts) - , m_sb(&mergeCandidateScore, slowAsserts) {} + : m_mtasksp{mtasksp} + , m_scoreLimit{scoreLimit} + , m_slowAsserts{slowAsserts} + , m_sb{&mergeCandidateScore, slowAsserts} {} // METHODS void go() { @@ -1121,7 +1088,7 @@ public: // - Incrementally recompute critical paths near the merged mtask. for (V3GraphVertex* itp = m_mtasksp->verticesBeginp(); itp; itp = itp->verticesNextp()) { - vl_unordered_set neighbors; + std::unordered_set neighbors; for (V3GraphEdge* edgep = itp->outBeginp(); edgep; edgep = edgep->outNextp()) { m_sb.addElem(MTaskEdge::cast(edgep)); UASSERT_OBJ(neighbors.find(edgep->top()) == neighbors.end(), itp, @@ -1291,10 +1258,10 @@ private: } void contract(MergeCandidate* mergeCanp) { - LogicMTask* top = NULL; - LogicMTask* fromp = NULL; + LogicMTask* top = nullptr; + LogicMTask* fromp = nullptr; MTaskEdge* mergeEdgep = dynamic_cast(mergeCanp); - SiblingMC* mergeSibsp = NULL; + SiblingMC* mergeSibsp = nullptr; if (mergeEdgep) { top = dynamic_cast(mergeEdgep->top()); fromp = dynamic_cast(mergeEdgep->fromp()); @@ -1340,7 +1307,7 @@ private: // Remove and free the connecting edge. Must do this before // propagating CP's below. m_sb.removeElem(mergeCanp); - VL_DO_CLEAR(mergeEdgep->unlinkDelete(), mergeEdgep = NULL); + VL_DO_CLEAR(mergeEdgep->unlinkDelete(), mergeEdgep = nullptr); } // This also updates cost and stepCost on recipientp @@ -1390,7 +1357,7 @@ private: partMergeEdgesFrom(m_mtasksp, recipientp, donorp, &m_sb); // Delete the donorp mtask from the graph - VL_DO_CLEAR(donorp->unlinkDelete(m_mtasksp), donorp = NULL); + VL_DO_CLEAR(donorp->unlinkDelete(m_mtasksp), donorp = nullptr); m_mergesSinceRescore++; @@ -1533,11 +1500,11 @@ private: // Don't make all NxN/2 possible pairs of prereqs, that's a lot // to cart around. Just make a few pairs. - std::vector::iterator it = shortestPrereqs.begin(); + auto it = shortestPrereqs.cbegin(); for (unsigned i = 0; exhaustive || (i < 3); ++i) { - if (it == shortestPrereqs.end()) break; + if (it == shortestPrereqs.cend()) break; LogicMTask* ap = *(it++); - if (it == shortestPrereqs.end()) break; + if (it == shortestPrereqs.cend()) break; LogicMTask* bp = *(it++); makeSiblingMC(ap, bp); } @@ -1564,9 +1531,9 @@ private: // NOTE: To get a dot file run with --debugi-V3Partition 4 or more. vluint64_t startUsecs = V3Os::timeUsecs(); V3Graph mtasks; - LogicMTask* lastp = NULL; + LogicMTask* lastp = nullptr; for (unsigned i = 0; i < chain_len; ++i) { - LogicMTask* mtp = new LogicMTask(&mtasks, NULL); + LogicMTask* mtp = new LogicMTask(&mtasks, nullptr); mtp->setCost(1); if (lastp) { new MTaskEdge(&mtasks, lastp, mtp, 1); } lastp = mtp; @@ -1615,17 +1582,17 @@ private: static void selfTestX() { // NOTE: To get a dot file run with --debugi-V3Partition 4 or more. V3Graph mtasks; - LogicMTask* center = new LogicMTask(&mtasks, NULL); + LogicMTask* center = new LogicMTask(&mtasks, nullptr); center->setCost(1); unsigned i; for (i = 0; i < 50; ++i) { - LogicMTask* mtp = new LogicMTask(&mtasks, NULL); + LogicMTask* mtp = new LogicMTask(&mtasks, nullptr); mtp->setCost(1); // Edge from every input -> center new MTaskEdge(&mtasks, mtp, center, 1); } for (i = 0; i < 50; ++i) { - LogicMTask* mtp = new LogicMTask(&mtasks, NULL); + LogicMTask* mtp = new LogicMTask(&mtasks, nullptr); mtp->setCost(1); // Edge from center -> every output new MTaskEdge(&mtasks, center, mtp, 1); @@ -1661,7 +1628,7 @@ private: VL_UNCOPYABLE(PartContraction); }; -const GraphWay* PartContraction::s_shortestWaywardCpInclusiveWay = NULL; +const GraphWay* PartContraction::s_shortestWaywardCpInclusiveWay = nullptr; //###################################################################### // DpiImportCallVisitor @@ -1670,12 +1637,12 @@ const GraphWay* PartContraction::s_shortestWaywardCpInclusiveWay = NULL; // routine. class DpiImportCallVisitor : public AstNVisitor { private: - bool m_hasDpiHazard; // Found a DPI import call. - bool m_tracingCall; // Iterating into a CCall to a CFunc + bool m_hasDpiHazard = false; // Found a DPI import call. + bool m_tracingCall = false; // Iterating into a CCall to a CFunc // METHODS VL_DEBUG_FUNC; - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstCFunc* nodep) override { if (!m_tracingCall) return; m_tracingCall = false; if (nodep->dpiImportWrapper()) { @@ -1686,23 +1653,19 @@ private: } iterateChildren(nodep); } - virtual void visit(AstNodeCCall* nodep) VL_OVERRIDE { + virtual void visit(AstNodeCCall* nodep) override { iterateChildren(nodep); // Enter the function and trace it m_tracingCall = true; iterate(nodep->funcp()); } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - explicit DpiImportCallVisitor(AstNode* nodep) - : m_hasDpiHazard(false) - , m_tracingCall(false) { - iterate(nodep); - } + explicit DpiImportCallVisitor(AstNode* nodep) { iterate(nodep); } bool hasDpiHazard() const { return m_hasDpiHazard; } - virtual ~DpiImportCallVisitor() {} + virtual ~DpiImportCallVisitor() override {} private: VL_UNCOPYABLE(DpiImportCallVisitor); @@ -1798,17 +1761,16 @@ private: typedef std::set LogicMTaskSet; typedef std::map TasksByRank; typedef std::set OvvSet; - typedef vl_unordered_map Olv2MTaskMap; + typedef std::unordered_map Olv2MTaskMap; // MEMBERS V3Graph* m_mtasksp; // Mtask graph Olv2MTaskMap m_olv2mtask; // Map OrderLogicVertex to LogicMTask who wraps it - unsigned m_mergesDone; // Number of MTasks merged. For stats only. + unsigned m_mergesDone = 0; // Number of MTasks merged. For stats only. public: // CONSTRUCTORs explicit PartFixDataHazards(V3Graph* mtasksp) - : m_mtasksp(mtasksp) - , m_mergesDone(0) {} + : m_mtasksp{mtasksp} {} // METHODS private: void findAdjacentTasks(OvvSet::iterator ovvIt, TasksByRank* tasksByRankp) { @@ -1830,13 +1792,13 @@ private: } } void mergeSameRankTasks(TasksByRank* tasksByRankp) { - LogicMTask* lastMergedp = NULL; + LogicMTask* lastMergedp = nullptr; for (TasksByRank::iterator rankIt = tasksByRankp->begin(); rankIt != tasksByRankp->end(); ++rankIt) { // Find the largest node at this rank, merge into it. (If we // happen to find a huge node, this saves time in // partMergeEdgesFrom() versus merging into an arbitrary node.) - LogicMTask* mergedp = NULL; + LogicMTask* mergedp = nullptr; for (LogicMTaskSet::iterator it = rankIt->second.begin(); it != rankIt->second.end(); ++it) { LogicMTask* mtaskp = *it; @@ -1849,7 +1811,7 @@ private: rankIt->second.erase(mergedp); while (!rankIt->second.empty()) { - LogicMTaskSet::iterator begin = rankIt->second.begin(); + const auto begin = rankIt->second.cbegin(); LogicMTask* donorp = *begin; UASSERT_OBJ(donorp != mergedp, donorp, "Donor can't be merged edge"); rankIt->second.erase(begin); @@ -1864,7 +1826,7 @@ private: // Move all vertices from donorp to mergedp mergedp->moveAllVerticesFrom(donorp); // Move edges from donorp to recipientp - partMergeEdgesFrom(m_mtasksp, mergedp, donorp, NULL); + partMergeEdgesFrom(m_mtasksp, mergedp, donorp, nullptr); // Remove donorp from the graph VL_DO_DANGLING(donorp->unlinkDelete(m_mtasksp), donorp); m_mergesDone++; @@ -2071,7 +2033,7 @@ private: uint32_t m_sandbagNumerator; // Numerator padding for est runtime uint32_t m_sandbagDenom; // Denomerator padding for est runtime - typedef vl_unordered_map MTaskStateMap; + typedef std::unordered_map MTaskStateMap; MTaskStateMap m_mtaskState; // State for each mtask. MTaskCmp m_mtaskCmp; // Comparison functor @@ -2087,11 +2049,11 @@ public: // CONSTRUCTORS explicit PartPackMTasks(V3Graph* mtasksp, uint32_t nThreads = v3Global.opt.threads(), unsigned sandbagNumerator = 30, unsigned sandbagDenom = 100) - : m_mtasksp(mtasksp) - , m_nThreads(nThreads) - , m_sandbagNumerator(sandbagNumerator) - , m_sandbagDenom(sandbagDenom) - , m_ready(m_mtaskCmp) {} + : m_mtasksp{mtasksp} + , m_nThreads{nThreads} + , m_sandbagNumerator{sandbagNumerator} + , m_sandbagDenom{sandbagDenom} + , m_ready{m_mtaskCmp} {} ~PartPackMTasks() {} // METHODS @@ -2146,7 +2108,7 @@ public: // on each thread (in that thread's local time frame.) uint32_t bestTime = 0xffffffff; uint32_t bestTh = 0; - ExecMTask* bestMtaskp = NULL; + ExecMTask* bestMtaskp = nullptr; for (uint32_t th = 0; th < m_nThreads; ++th) { for (ReadyMTasks::iterator taskIt = m_ready.begin(); taskIt != m_ready.end(); ++taskIt) { @@ -2230,13 +2192,13 @@ public: // SELF TEST static void selfTest() { V3Graph graph; - ExecMTask* t0 = new ExecMTask(&graph, NULL, 0); + ExecMTask* t0 = new ExecMTask(&graph, nullptr, 0); t0->cost(1000); t0->priority(1100); - ExecMTask* t1 = new ExecMTask(&graph, NULL, 1); + ExecMTask* t1 = new ExecMTask(&graph, nullptr, 1); t1->cost(100); t1->priority(100); - ExecMTask* t2 = new ExecMTask(&graph, NULL, 2); + ExecMTask* t2 = new ExecMTask(&graph, nullptr, 2); t2->cost(100); t2->priority(100); @@ -2255,11 +2217,11 @@ public: UASSERT_SELFTEST(uint32_t, t1->thread(), 0); UASSERT_SELFTEST(bool, t1->threadRoot(), false); - UASSERT_SELFTEST(const void*, t1->packNextp(), NULL); + UASSERT_SELFTEST(const void*, t1->packNextp(), nullptr); UASSERT_SELFTEST(uint32_t, t2->thread(), 1); UASSERT_SELFTEST(bool, t2->threadRoot(), true); - UASSERT_SELFTEST(const void*, t2->packNextp(), NULL); + UASSERT_SELFTEST(const void*, t2->packNextp(), nullptr); // On its native thread, we see the actual end time for t0: UASSERT_SELFTEST(uint32_t, packer.completionTime(t0, 0), 1000); @@ -2346,7 +2308,7 @@ void V3Partition::hashGraphDebug(const V3Graph* graphp, const char* debugName) { // Disabled when there are no nondeterminism issues in flight. if (!v3Global.opt.debugNondeterminism()) return; - vl_unordered_map vx2Id; + std::unordered_map vx2Id; unsigned id = 0; for (const V3GraphVertex* vxp = graphp->verticesBeginp(); vxp; vxp = vxp->verticesNextp()) { vx2Id[vxp] = id++; @@ -2375,10 +2337,10 @@ void V3Partition::setupMTaskDeps(V3Graph* mtasksp, const Vx2MTaskMap* vx2mtaskp) UASSERT(outp->weight() > 0, "Mtask not assigned weight"); const MTaskMoveVertex* top = dynamic_cast(outp->top()); UASSERT(top, "MoveVertex not associated to mtask"); - Vx2MTaskMap::const_iterator it = vx2mtaskp->find(top); + const auto it = vlstd::as_const(vx2mtaskp)->find(top); UASSERT(it != vx2mtaskp->end(), "MTask map can't find id"); LogicMTask* otherMTaskp = it->second; - UASSERT(otherMTaskp, "NULL other Mtask"); + UASSERT(otherMTaskp, "nullptr other Mtask"); UASSERT_OBJ(otherMTaskp != mtaskp, mtaskp, "Would create a cycle edge"); // Don't create redundant edges. diff --git a/src/V3Partition.h b/src/V3Partition.h index 9226cb666..231ebf8d2 100644 --- a/src/V3Partition.h +++ b/src/V3Partition.h @@ -26,7 +26,7 @@ #include class LogicMTask; -typedef vl_unordered_map Vx2MTaskMap; +typedef std::unordered_map Vx2MTaskMap; //************************************************************************* /// V3Partition takes the fine-grained logic graph from V3Order and @@ -40,7 +40,7 @@ class V3Partition { public: // CONSTRUCTORS explicit V3Partition(V3Graph* fineDepsGraphp) - : m_fineDepsGraphp(fineDepsGraphp) {} + : m_fineDepsGraphp{fineDepsGraphp} {} ~V3Partition() {} // METHODS @@ -76,18 +76,17 @@ private: class PartPtrIdMap { private: // TYPES - typedef vl_unordered_map PtrMap; + typedef std::unordered_map PtrMap; // MEMBERS - mutable vluint64_t m_nextId; + mutable vluint64_t m_nextId = 0; mutable PtrMap m_id; public: // CONSTRUCTORS - PartPtrIdMap() - : m_nextId(0) {} + PartPtrIdMap() {} // METHODS vluint64_t findId(const void* ptrp) const { - PtrMap::const_iterator it = m_id.find(ptrp); + const auto it = m_id.find(ptrp); if (it != m_id.end()) return it->second; m_id[ptrp] = m_nextId; return m_nextId++; diff --git a/src/V3PartitionGraph.h b/src/V3PartitionGraph.h index 1c2abd59b..d79fa83e7 100644 --- a/src/V3PartitionGraph.h +++ b/src/V3PartitionGraph.h @@ -31,8 +31,8 @@ class AbstractMTask : public V3GraphVertex { public: AbstractMTask(V3Graph* graphp) - : V3GraphVertex(graphp) {} - virtual ~AbstractMTask() {} + : V3GraphVertex{graphp} {} + virtual ~AbstractMTask() override {} virtual uint32_t id() const = 0; virtual uint32_t cost() const = 0; }; @@ -43,45 +43,40 @@ public: typedef std::list VxList; // CONSTRUCTORS AbstractLogicMTask(V3Graph* graphp) - : AbstractMTask(graphp) {} - virtual ~AbstractLogicMTask() {} + : AbstractMTask{graphp} {} + virtual ~AbstractLogicMTask() override {} // METHODS // Set of logic vertices in this mtask. Order is not significant. virtual const VxList* vertexListp() const = 0; - virtual uint32_t id() const = 0; // Unique id of this mtask. - virtual uint32_t cost() const = 0; + virtual uint32_t id() const override = 0; // Unique id of this mtask. + virtual uint32_t cost() const override = 0; }; class ExecMTask : public AbstractMTask { private: AstMTaskBody* m_bodyp; // Task body uint32_t m_id; // Unique id of this mtask. - uint32_t m_priority; // Predicted critical path from the start of + uint32_t m_priority = 0; // Predicted critical path from the start of // this mtask to the ends of the graph that are reachable from this // mtask. In abstract time units. - uint32_t m_cost; // Predicted runtime of this mtask, in the same + uint32_t m_cost = 0; // Predicted runtime of this mtask, in the same // abstract time units as priority(). - uint32_t m_thread; // Thread for static (pack_mtasks) scheduling, + uint32_t m_thread = 0xffffffff; // Thread for static (pack_mtasks) scheduling, // or 0xffffffff if not yet assigned. - const ExecMTask* m_packNextp; // Next for static (pack_mtasks) scheduling - bool m_threadRoot; // Is root thread + const ExecMTask* m_packNextp = nullptr; // Next for static (pack_mtasks) scheduling + bool m_threadRoot = false; // Is root thread VL_UNCOPYABLE(ExecMTask); public: ExecMTask(V3Graph* graphp, AstMTaskBody* bodyp, uint32_t id) - : AbstractMTask(graphp) - , m_bodyp(bodyp) - , m_id(id) - , m_priority(0) - , m_cost(0) - , m_thread(0xffffffff) - , m_packNextp(NULL) - , m_threadRoot(false) {} + : AbstractMTask{graphp} + , m_bodyp{bodyp} + , m_id{id} {} AstMTaskBody* bodyp() const { return m_bodyp; } - virtual uint32_t id() const { return m_id; } + virtual uint32_t id() const override { return m_id; } uint32_t priority() const { return m_priority; } void priority(uint32_t pri) { m_priority = pri; } - virtual uint32_t cost() const { return m_cost; } + virtual uint32_t cost() const override { return m_cost; } void cost(uint32_t cost) { m_cost = cost; } void thread(uint32_t thread) { m_thread = thread; } uint32_t thread() const { return m_thread; } @@ -93,7 +88,7 @@ public: // If this MTask maps to a C function, this should be the name return string("__Vmtask") + "__" + cvtToStr(m_id); } - string name() const { return string("mt") + cvtToStr(id()); } + virtual string name() const override { return string("mt") + cvtToStr(id()); } void dump(std::ostream& str) const { str << name() << "." << cvtToHex(this); if (priority() || cost()) str << " [pr=" << priority() << " c=" << cvtToStr(cost()) << "]"; diff --git a/src/V3PreLex.h b/src/V3PreLex.h index 71e684412..34f978de0 100644 --- a/src/V3PreLex.h +++ b/src/V3PreLex.h @@ -131,17 +131,13 @@ public: FileLine* m_curFilelinep; // Current processing point (see also m_tokFilelinep) V3PreLex* m_lexp; // Lexer, for resource tracking std::deque m_buffers; // Buffer of characters to process - int m_ignNewlines; // Ignore multiline newlines - bool m_eof; // "EOF" buffer - bool m_file; // Buffer is start of new file - int m_termState; // Termination fsm + int m_ignNewlines = 0; // Ignore multiline newlines + bool m_eof = false; // "EOF" buffer + bool m_file = false; // Buffer is start of new file + int m_termState = 0; // Termination fsm VPreStream(FileLine* fl, V3PreLex* lexp) - : m_curFilelinep(fl) - , m_lexp(lexp) - , m_ignNewlines(0) - , m_eof(false) - , m_file(false) - , m_termState(0) { + : m_curFilelinep{fl} + , m_lexp{lexp} { lexStreamDepthAdd(1); } ~VPreStream() { lexStreamDepthAdd(-1); } @@ -157,37 +153,28 @@ class V3PreLex { public: // Used only by V3PreLex.cpp and V3PreProc.cpp V3PreProcImp* m_preimpp; // Preprocessor lexor belongs to std::stack m_streampStack; // Stack of processing files - int m_streamDepth; // Depth of stream processing + int m_streamDepth = 0; // Depth of stream processing YY_BUFFER_STATE m_bufferState; // Flex state FileLine* m_tokFilelinep; // Starting position of current token // State to lexer static V3PreLex* s_currentLexp; ///< Current lexing point - int m_keepComments; ///< Emit comments in output text - int m_keepWhitespace; ///< Emit all whitespace in output text - bool m_pedantic; ///< Obey standard; don't Substitute `error + int m_keepComments = 0; ///< Emit comments in output text + int m_keepWhitespace = 1; ///< Emit all whitespace in output text + bool m_pedantic = false; ///< Obey standard; don't Substitute `error // State from lexer - int m_formalLevel; // Parenthesis counting inside def formals - int m_parenLevel; // Parenthesis counting inside def args - bool m_defCmtSlash; // /*...*/ comment in define had \ ending - bool m_defQuote; // Definition value inside quote + int m_formalLevel = 0; // Parenthesis counting inside def formals + int m_parenLevel = 0; // Parenthesis counting inside def args + bool m_defCmtSlash = false; // /*...*/ comment in define had \ ending + bool m_defQuote = false; // Definition value inside quote string m_defValue; // Definition value being built. - int m_enterExit; // For VL_LINE, the enter/exit level + int m_enterExit = 0; // For VL_LINE, the enter/exit level // CONSTRUCTORS - V3PreLex(V3PreProcImp* preimpp, FileLine* filelinep) { - m_preimpp = preimpp; - m_streamDepth = 0; - m_keepComments = 0; - m_keepWhitespace = 1; - m_pedantic = false; - m_formalLevel = 0; - m_parenLevel = 0; - m_defQuote = false; - m_defCmtSlash = false; - m_tokFilelinep = filelinep; - m_enterExit = 0; + V3PreLex(V3PreProcImp* preimpp, FileLine* filelinep) + : m_preimpp{preimpp} + , m_tokFilelinep{filelinep} { initFirstBuffer(filelinep); } ~V3PreLex() { @@ -195,7 +182,7 @@ public: // Used only by V3PreLex.cpp and V3PreProc.cpp delete m_streampStack.top(); m_streampStack.pop(); } - VL_DO_CLEAR(yy_delete_buffer(m_bufferState), m_bufferState = NULL); + VL_DO_CLEAR(yy_delete_buffer(m_bufferState), m_bufferState = nullptr); } // Called by V3PreLex.l from lexer diff --git a/src/V3PreLex.l b/src/V3PreLex.l index 42765edb7..d706fc07c 100644 --- a/src/V3PreLex.l +++ b/src/V3PreLex.l @@ -34,7 +34,7 @@ /* clang-format on */ -V3PreLex* V3PreLex::s_currentLexp = NULL; // Current lexing point +V3PreLex* V3PreLex::s_currentLexp = nullptr; // Current lexing point #define LEXP V3PreLex::s_currentLexp @@ -482,9 +482,9 @@ void V3PreLex::initFirstBuffer(FileLine* filelinep) { streamp->m_eof = true; m_streampStack.push(streamp); // - m_bufferState = yy_create_buffer(NULL, YY_BUF_SIZE); + m_bufferState = yy_create_buffer(nullptr, YY_BUF_SIZE); yy_switch_to_buffer(m_bufferState); - yyrestart(NULL); + yyrestart(nullptr); } void V3PreLex::scanNewFile(FileLine* filelinep) { @@ -522,7 +522,7 @@ void V3PreLex::scanBytes(const string& str) { void V3PreLex::scanSwitchStream(VPreStream* streamp) { curStreamp()->m_buffers.push_front(currentUnreadChars()); m_streampStack.push(streamp); - yyrestart(NULL); + yyrestart(nullptr); } void V3PreLex::scanBytesBack(const string& str) { diff --git a/src/V3PreProc.cpp b/src/V3PreProc.cpp index de42e8c02..ec9047731 100644 --- a/src/V3PreProc.cpp +++ b/src/V3PreProc.cpp @@ -51,10 +51,10 @@ class VDefine { bool m_cmdline; // Set on command line, don't `undefineall public: VDefine(FileLine* fl, const string& value, const string& params, bool cmdline) - : m_fileline(fl) - , m_value(value) - , m_params(params) - , m_cmdline(cmdline) {} + : m_fileline{fl} + , m_value{value} + , m_params{params} + , m_cmdline{cmdline} {} FileLine* fileline() const { return m_fileline; } string value() const { return m_value; } string params() const { return m_params; } @@ -68,7 +68,7 @@ class VDefineRef { string m_name; // Define last name being defined string m_params; // Define parameter list for next expansion string m_nextarg; // String being built for next argument - int m_parenLevel; // Parenthesis counting inside def args (for PARENT not child) + int m_parenLevel = 0; // Parenthesis counting inside def args (for PARENT not child) std::vector m_args; // List of define arguments public: @@ -80,9 +80,8 @@ public: void parenLevel(int value) { m_parenLevel = value; } std::vector& args() { return m_args; } VDefineRef(const string& name, const string& params) - : m_name(name) - , m_params(params) - , m_parenLevel(0) {} + : m_name{name} + , m_params{params} {} ~VDefineRef() {} }; @@ -97,8 +96,8 @@ public: bool on() const { return m_on; } bool everOn() const { return m_everOn; } VPreIfEntry(bool on, bool everOn) - : m_on(on) - , m_everOn(everOn || on) {} // Note everOn includes new state + : m_on{on} + , m_everOn{everOn || on} {} // Note everOn includes new state ~VPreIfEntry() {} }; @@ -117,13 +116,13 @@ public: DefinesMap m_defines; ///< Map of defines // STATE - V3PreProc* m_preprocp; ///< Object we're holding data for - V3PreLex* m_lexp; ///< Current lexer state (NULL = closed) + V3PreProc* m_preprocp = nullptr; ///< Object we're holding data for + V3PreLex* m_lexp = nullptr; ///< Current lexer state (nullptr = closed) std::stack m_includeStack; ///< Stack of includers above current m_lexp - int m_lastLineno; // Last line number (stall detection) - int m_tokensOnLine; // Number of tokens on line (stall detection) + int m_lastLineno = 0; // Last line number (stall detection) + int m_tokensOnLine = 0; // Number of tokens on line (stall detection) - enum ProcState { + enum ProcState : uint8_t { ps_TOP, ps_DEFNAME_UNDEF, ps_DEFNAME_DEFINE, @@ -150,23 +149,23 @@ public: } std::stack m_states; ///< Current state of parser - int m_off; ///< If non-zero, ifdef level is turned off, don't dump text - bool m_incError; ///< Include error found + int m_off = 0; ///< If non-zero, ifdef level is turned off, don't dump text + bool m_incError = false; ///< Include error found string m_lastSym; ///< Last symbol name found. string m_formals; ///< Last formals found // For getRawToken/ `line insertion string m_lineCmt; ///< Line comment(s) to be returned - bool m_lineCmtNl; ///< Newline needed before inserting lineCmt - int m_lineAdd; ///< Empty lines to return to maintain line count - bool m_rawAtBol; ///< Last rawToken left us at beginning of line + bool m_lineCmtNl = false; ///< Newline needed before inserting lineCmt + int m_lineAdd = 0; ///< Empty lines to return to maintain line count + bool m_rawAtBol = true; ///< Last rawToken left us at beginning of line // For getFinalToken - bool m_finAhead; ///< Have read a token ahead - int m_finToken; ///< Last token read + bool m_finAhead = false; ///< Have read a token ahead + int m_finToken = 0; ///< Last token read string m_finBuf; ///< Last yytext read - bool m_finAtBol; ///< Last getFinalToken left us at beginning of line - FileLine* m_finFilelinep; ///< Location of last returned token (internal only) + bool m_finAtBol = true; ///< Last getFinalToken left us at beginning of line + FileLine* m_finFilelinep = nullptr; ///< Location of last returned token (internal only) // For stringification string m_strify; ///< Text to be stringified @@ -174,8 +173,8 @@ public: // For defines std::stack m_defRefs; ///< Pending define substitution std::stack m_ifdefStack; ///< Stack of true/false emitting evaluations - unsigned m_defDepth; ///< How many `defines deep - bool m_defPutJoin; ///< Insert `` after substitution + unsigned m_defDepth = 0; ///< How many `defines deep + bool m_defPutJoin = false; ///< Insert `` after substitution // For `` join std::stack m_joinStack; ///< Text on lhs of join @@ -261,23 +260,6 @@ public: V3PreProcImp() { m_debug = 0; m_states.push(ps_TOP); - m_off = 0; - m_incError = false; - m_lineChars = ""; - m_lastSym = ""; - m_lineAdd = 0; - m_lineCmtNl = false; - m_rawAtBol = true; - m_finAhead = false; - m_finAtBol = true; - m_defDepth = 0; - m_defPutJoin = false; - m_finToken = 0; - m_finFilelinep = NULL; - m_lexp = NULL; - m_preprocp = NULL; - m_lastLineno = 0; - m_tokensOnLine = 0; } void configure(FileLine* filelinep) { // configure() separate from constructor to avoid calling abstract functions @@ -292,7 +274,7 @@ public: m_lexp->debug(debug() >= 5 ? debug() : 0); // See also V3PreProc::debug() method } ~V3PreProcImp() { - if (m_lexp) VL_DO_CLEAR(delete m_lexp, m_lexp = NULL); + if (m_lexp) VL_DO_CLEAR(delete m_lexp, m_lexp = nullptr); } }; @@ -317,11 +299,11 @@ void V3PreProcImp::undefineall() { } } bool V3PreProcImp::defExists(const string& name) { - DefinesMap::iterator iter = m_defines.find(name); + const auto iter = m_defines.find(name); return (iter != m_defines.end()); } string V3PreProcImp::defValue(const string& name) { - DefinesMap::iterator iter = m_defines.find(name); + const auto iter = m_defines.find(name); if (iter == m_defines.end()) { fileline()->v3error("Define or directive not defined: `" + name); return ""; @@ -329,7 +311,7 @@ string V3PreProcImp::defValue(const string& name) { return iter->second.value(); } string V3PreProcImp::defParams(const string& name) { - DefinesMap::iterator iter = m_defines.find(name); + const auto iter = m_defines.find(name); if (iter == m_defines.end()) { fileline()->v3error("Define or directive not defined: `" + name); return ""; @@ -337,8 +319,8 @@ string V3PreProcImp::defParams(const string& name) { return iter->second.params(); } FileLine* V3PreProcImp::defFileline(const string& name) { - DefinesMap::iterator iter = m_defines.find(name); - if (iter == m_defines.end()) return NULL; + const auto iter = m_defines.find(name); + if (iter == m_defines.end()) return nullptr; return iter->second.fileline(); } void V3PreProcImp::define(FileLine* fl, const string& name, const string& value, @@ -439,16 +421,18 @@ void V3PreProcImp::comment(const string& text) { bool vlcomment = false; if ((cp[0] == 'v' || cp[0] == 'V') && 0 == (strncmp(cp + 1, "erilator", 8))) { cp += strlen("verilator"); - if (*cp == '_') + if (*cp == '_') { fileline()->v3error("Extra underscore in meta-comment;" " use /*verilator {...}*/ not /*verilator_{...}*/"); + } vlcomment = true; } else if (0 == (strncmp(cp, "synopsys", strlen("synopsys")))) { cp += strlen("synopsys"); synth = true; - if (*cp == '_') + if (*cp == '_') { fileline()->v3error("Extra underscore in meta-comment;" " use /*synopsys {...}*/ not /*synopsys_{...}*/"); + } } else if (0 == (strncmp(cp, "cadence", strlen("cadence")))) { cp += strlen("cadence"); synth = true; @@ -687,7 +671,7 @@ string V3PreProcImp::defineSubst(VDefineRef* refp) { string argName; bool quote = false; bool backslashesc = false; // In \.....{space} block - // Note we go through the loop once more at the NULL end-of-string + // Note we go through the loop once more at the nullptr end-of-string for (const char* cp = value.c_str(); (*cp) || argName != ""; cp = (*cp ? cp + 1 : cp)) { // UINFO(4, "CH "<<*cp<<" an "<::iterator iter = argValueByName.find(argName); + const auto iter = argValueByName.find(argName); if (iter != argValueByName.end()) { // Substitute string subst = iter->second; @@ -813,9 +797,7 @@ void V3PreProcImp::openFile(FileLine* fl, VInFilter* filterp, const string& file FileLine* flsp = new FileLine(filename); flsp->lineno(1); flsp->newContent(); - for (StrList::iterator it = wholefile.begin(); it != wholefile.end(); ++it) { - flsp->contentp()->pushText(*it); - } + for (const string& i : wholefile) flsp->contentp()->pushText(i); // Create new stream structure m_lexp->scanNewFile(flsp); @@ -1584,7 +1566,7 @@ string V3PreProcImp::getline() { if (isEof()) return ""; const char* rtnp; bool gotEof = false; - while (NULL == (rtnp = strchr(m_lineChars.c_str(), '\n')) && !gotEof) { + while (nullptr == (rtnp = strchr(m_lineChars.c_str(), '\n')) && !gotEof) { string buf; int tok = getFinalToken(buf /*ref*/); if (debug() >= 5) { diff --git a/src/V3PreShell.cpp b/src/V3PreShell.cpp index 2695051a4..54de5495d 100644 --- a/src/V3PreShell.cpp +++ b/src/V3PreShell.cpp @@ -61,8 +61,6 @@ protected: s_preprocp->defineCmdLine(prefl, "VERILATOR", "1"); // LEAK_OK s_preprocp->defineCmdLine(prefl, "verilator", "1"); // LEAK_OK s_preprocp->defineCmdLine(prefl, "verilator3", "1"); // LEAK_OK - s_preprocp->defineCmdLine(prefl, "systemc_clock", - "/*verilator systemc_clock*/"); // LEAK_OK s_preprocp->defineCmdLine(prefl, "coverage_block_off", "/*verilator coverage_block_off*/"); // LEAK_OK if (prefl->language().systemVerilog()) { @@ -110,6 +108,7 @@ protected: modfileline->language(v3Global.opt.fileLanguage(modfilename)); V3Parse::ppPushText( parsep, (string("`begin_keywords \"") + modfileline->language().ascii() + "\"\n")); + // FileLine tracks and frees modfileline } while (!s_preprocp->isEof()) { @@ -157,8 +156,8 @@ public: }; V3PreShellImp V3PreShellImp::s_preImp; -V3PreProc* V3PreShellImp::s_preprocp = NULL; -VInFilter* V3PreShellImp::s_filterp = NULL; +V3PreProc* V3PreShellImp::s_preprocp = nullptr; +VInFilter* V3PreShellImp::s_filterp = nullptr; //###################################################################### // Perl class functions diff --git a/src/V3Premit.cpp b/src/V3Premit.cpp index 2b75eafa6..154e517ee 100644 --- a/src/V3Premit.cpp +++ b/src/V3Premit.cpp @@ -43,20 +43,20 @@ private: AstUser4InUse m_inuser4; // STATE - bool m_noopt; // Disable optimization of variables in this block + bool m_noopt = false; // Disable optimization of variables in this block // METHODS VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { + virtual void visit(AstNodeAssign* nodep) override { // AstNode::user4ClearTree(); // Implied by AstUser4InUse // LHS first as fewer varrefs iterateAndNextNull(nodep->lhsp()); // Now find vars marked as lhs iterateAndNextNull(nodep->rhsp()); } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { // it's LHS var is used so need a deep temporary if (nodep->lvalue()) { nodep->varp()->user4(true); @@ -67,16 +67,15 @@ private: } } } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit PremitAssignVisitor(AstNodeAssign* nodep) { UINFO(4, " PremitAssignVisitor on " << nodep << endl); - m_noopt = false; iterate(nodep); } - virtual ~PremitAssignVisitor() {} + virtual ~PremitAssignVisitor() override {} bool noOpt() const { return m_noopt; } }; @@ -94,12 +93,12 @@ private: AstUser2InUse m_inuser2; // STATE - AstNodeModule* m_modp; // Current module - AstCFunc* m_funcp; // Current block - AstNode* m_stmtp; // Current statement - AstWhile* m_inWhilep; // Inside while loop, special statement additions - AstTraceInc* m_inTracep; // Inside while loop, special statement additions - bool m_assignLhs; // Inside assignment lhs, don't breakup extracts + AstNodeModule* m_modp = nullptr; // Current module + AstCFunc* m_funcp = nullptr; // Current block + AstNode* m_stmtp = nullptr; // Current statement + AstWhile* m_inWhilep = nullptr; // Inside while loop, special statement additions + AstTraceInc* m_inTracep = nullptr; // Inside while loop, special statement additions + bool m_assignLhs = false; // Inside assignment lhs, don't breakup extracts // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -185,39 +184,38 @@ 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; iterateChildren(nodep); - m_funcp = NULL; + m_funcp = nullptr; } void startStatement(AstNode* nodep) { m_assignLhs = false; if (m_funcp) m_stmtp = nodep; } - virtual void visit(AstWhile* nodep) VL_OVERRIDE { + virtual void visit(AstWhile* nodep) override { UINFO(4, " WHILE " << nodep << endl); startStatement(nodep); iterateAndNextNull(nodep->precondsp()); startStatement(nodep); m_inWhilep = nodep; iterateAndNextNull(nodep->condp()); - m_inWhilep = NULL; + m_inWhilep = nullptr; startStatement(nodep); iterateAndNextNull(nodep->bodysp()); iterateAndNextNull(nodep->incsp()); - m_stmtp = NULL; + m_stmtp = nullptr; } - virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { + virtual void visit(AstNodeAssign* nodep) override { startStatement(nodep); { bool noopt = PremitAssignVisitor(nodep).noOpt(); @@ -231,9 +229,9 @@ private: m_assignLhs = true; iterateAndNextNull(nodep->lhsp()); m_assignLhs = false; - m_stmtp = NULL; + m_stmtp = nullptr; } - virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE { + virtual void visit(AstNodeStmt* nodep) override { if (!nodep->isStatement()) { iterateChildren(nodep); return; @@ -241,14 +239,14 @@ private: UINFO(4, " STMT " << nodep << endl); startStatement(nodep); iterateChildren(nodep); - m_stmtp = NULL; + m_stmtp = nullptr; } - virtual void visit(AstTraceInc* nodep) VL_OVERRIDE { + virtual void visit(AstTraceInc* nodep) override { startStatement(nodep); m_inTracep = nodep; iterateChildren(nodep); - m_inTracep = NULL; - m_stmtp = NULL; + m_inTracep = nullptr; + m_stmtp = nullptr; } void visitShift(AstNodeBiop* nodep) { // Shifts of > 32/64 bits in C++ will wrap-around and generate non-0s @@ -296,62 +294,59 @@ private: iterateChildren(nodep); checkNode(nodep); } - virtual void visit(AstShiftL* nodep) VL_OVERRIDE { visitShift(nodep); } - virtual void visit(AstShiftR* nodep) VL_OVERRIDE { visitShift(nodep); } - virtual void visit(AstShiftRS* nodep) VL_OVERRIDE { visitShift(nodep); } + virtual void visit(AstShiftL* nodep) override { visitShift(nodep); } + virtual void visit(AstShiftR* nodep) override { visitShift(nodep); } + virtual void visit(AstShiftRS* nodep) override { visitShift(nodep); } // Operators - virtual void visit(AstNodeTermop* nodep) VL_OVERRIDE { + virtual void visit(AstNodeTermop* nodep) override { iterateChildren(nodep); checkNode(nodep); } - virtual void visit(AstNodeUniop* nodep) VL_OVERRIDE { + virtual void visit(AstNodeUniop* nodep) override { iterateChildren(nodep); checkNode(nodep); } - virtual void visit(AstNodeBiop* nodep) VL_OVERRIDE { + virtual void visit(AstNodeBiop* nodep) override { iterateChildren(nodep); checkNode(nodep); } - virtual void visit(AstUCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstUCFunc* nodep) override { iterateChildren(nodep); checkNode(nodep); } - virtual void visit(AstSel* nodep) VL_OVERRIDE { + virtual void visit(AstSel* nodep) override { iterateAndNextNull(nodep->fromp()); { // Only the 'from' is part of the assignment LHS - bool prevAssign = m_assignLhs; + VL_RESTORER(m_assignLhs); m_assignLhs = false; iterateAndNextNull(nodep->lsbp()); iterateAndNextNull(nodep->widthp()); - m_assignLhs = prevAssign; } checkNode(nodep); } - virtual void visit(AstArraySel* nodep) VL_OVERRIDE { + virtual void visit(AstArraySel* nodep) override { iterateAndNextNull(nodep->fromp()); { // Only the 'from' is part of the assignment LHS - bool prevAssign = m_assignLhs; + VL_RESTORER(m_assignLhs); m_assignLhs = false; iterateAndNextNull(nodep->bitp()); - m_assignLhs = prevAssign; } checkNode(nodep); } - virtual void visit(AstAssocSel* nodep) VL_OVERRIDE { + virtual void visit(AstAssocSel* nodep) override { iterateAndNextNull(nodep->fromp()); { // Only the 'from' is part of the assignment LHS - bool prevAssign = m_assignLhs; + VL_RESTORER(m_assignLhs); m_assignLhs = false; iterateAndNextNull(nodep->bitp()); - m_assignLhs = prevAssign; } checkNode(nodep); } - virtual void visit(AstConst* nodep) VL_OVERRIDE { + virtual void visit(AstConst* nodep) override { iterateChildren(nodep); checkNode(nodep); } - virtual void visit(AstNodeCond* nodep) VL_OVERRIDE { + virtual void visit(AstNodeCond* nodep) override { iterateChildren(nodep); if (nodep->expr1p()->isWide() && !VN_IS(nodep->condp(), Const) && !VN_IS(nodep->condp(), VarRef)) { @@ -363,10 +358,10 @@ private: } // Autoflush - virtual void visit(AstDisplay* nodep) VL_OVERRIDE { + virtual void visit(AstDisplay* nodep) override { startStatement(nodep); iterateChildren(nodep); - m_stmtp = NULL; + m_stmtp = nullptr; if (v3Global.opt.autoflush()) { AstNode* searchp = nodep->nextp(); while (searchp && VN_IS(searchp, Comment)) searchp = searchp->nextp(); @@ -380,7 +375,7 @@ private: } } } - virtual void visit(AstSFormatF* nodep) VL_OVERRIDE { + virtual void visit(AstSFormatF* nodep) override { iterateChildren(nodep); // Any strings sent to a display must be var of string data type, // to avoid passing a pointer to a temporary. @@ -394,21 +389,13 @@ private: //-------------------- // 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 PremitVisitor(AstNetlist* nodep) { - m_modp = NULL; - m_funcp = NULL; - m_stmtp = NULL; - m_inWhilep = NULL; - m_inTracep = NULL; - m_assignLhs = false; - iterate(nodep); - } - virtual ~PremitVisitor() {} + explicit PremitVisitor(AstNetlist* nodep) { iterate(nodep); } + virtual ~PremitVisitor() override {} }; //---------------------------------------------------------------------- diff --git a/src/V3ProtectLib.cpp b/src/V3ProtectLib.cpp index 5d6c2fe28..b889bd48a 100644 --- a/src/V3ProtectLib.cpp +++ b/src/V3ProtectLib.cpp @@ -30,40 +30,40 @@ class ProtectVisitor : public AstNVisitor { private: - AstVFile* m_vfilep; // DPI-enabled Verilog wrapper - AstCFile* m_cfilep; // C implementation of DPI functions + AstVFile* m_vfilep = nullptr; // DPI-enabled Verilog wrapper + AstCFile* m_cfilep = nullptr; // C implementation of DPI functions // Verilog text blocks - AstTextBlock* m_modPortsp; // Module port list - AstTextBlock* m_comboPortsp; // Combo function port list - AstTextBlock* m_seqPortsp; // Sequential function port list - AstTextBlock* m_comboIgnorePortsp; // Combo ignore function port list - AstTextBlock* m_comboDeclsp; // Combo signal declaration list - AstTextBlock* m_seqDeclsp; // Sequential signal declaration list - AstTextBlock* m_tmpDeclsp; // Temporary signal declaration list - AstTextBlock* m_hashValuep; // CPP hash value - AstTextBlock* m_comboParamsp; // Combo function parameter list - AstTextBlock* m_clkSensp; // Clock sensitivity list - AstTextBlock* m_comboIgnoreParamsp; // Combo ignore parameter list - AstTextBlock* m_seqParamsp; // Sequential parameter list - AstTextBlock* m_nbAssignsp; // Non-blocking assignment list - AstTextBlock* m_seqAssignsp; // Sequential assignment list - AstTextBlock* m_comboAssignsp; // Combo assignment list + AstTextBlock* m_modPortsp = nullptr; // Module port list + AstTextBlock* m_comboPortsp = nullptr; // Combo function port list + AstTextBlock* m_seqPortsp = nullptr; // Sequential function port list + AstTextBlock* m_comboIgnorePortsp = nullptr; // Combo ignore function port list + AstTextBlock* m_comboDeclsp = nullptr; // Combo signal declaration list + AstTextBlock* m_seqDeclsp = nullptr; // Sequential signal declaration list + AstTextBlock* m_tmpDeclsp = nullptr; // Temporary signal declaration list + AstTextBlock* m_hashValuep = nullptr; // CPP hash value + AstTextBlock* m_comboParamsp = nullptr; // Combo function parameter list + AstTextBlock* m_clkSensp = nullptr; // Clock sensitivity list + AstTextBlock* m_comboIgnoreParamsp = nullptr; // Combo ignore parameter list + AstTextBlock* m_seqParamsp = nullptr; // Sequential parameter list + AstTextBlock* m_nbAssignsp = nullptr; // Non-blocking assignment list + AstTextBlock* m_seqAssignsp = nullptr; // Sequential assignment list + AstTextBlock* m_comboAssignsp = nullptr; // Combo assignment list // C text blocks - AstTextBlock* m_cHashValuep; // CPP hash value - AstTextBlock* m_cComboParamsp; // Combo function parameter list - AstTextBlock* m_cComboInsp; // Combo input copy list - AstTextBlock* m_cComboOutsp; // Combo output copy list - AstTextBlock* m_cSeqParamsp; // Sequential parameter list - AstTextBlock* m_cSeqClksp; // Sequential clock copy list - AstTextBlock* m_cSeqOutsp; // Sequential output copy list - AstTextBlock* m_cIgnoreParamsp; // Combo ignore parameter list + AstTextBlock* m_cHashValuep = nullptr; // CPP hash value + AstTextBlock* m_cComboParamsp = nullptr; // Combo function parameter list + AstTextBlock* m_cComboInsp = nullptr; // Combo input copy list + AstTextBlock* m_cComboOutsp = nullptr; // Combo output copy list + AstTextBlock* m_cSeqParamsp = nullptr; // Sequential parameter list + AstTextBlock* m_cSeqClksp = nullptr; // Sequential clock copy list + AstTextBlock* m_cSeqOutsp = nullptr; // Sequential output copy list + AstTextBlock* m_cIgnoreParamsp = nullptr; // Combo ignore parameter list string m_libName; string m_topName; - bool m_foundTop; // Have seen the top module - bool m_hasClk; // True if the top module has sequential logic + bool m_foundTop = false; // Have seen the top module + bool m_hasClk = false; // True if the top module has sequential logic // VISITORS - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { m_vfilep = new AstVFile(nodep->fileline(), v3Global.opt.makeDir() + "/" + m_libName + ".sv"); nodep->addFilesp(m_vfilep); @@ -73,7 +73,7 @@ private: iterateChildren(nodep); } - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { + virtual void visit(AstNodeModule* nodep) override { if (!nodep->isTop()) { return; } else { @@ -376,7 +376,7 @@ private: m_cfilep->tblockp(txtp); } - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { if (!nodep->isIO()) return; if (VN_IS(nodep->dtypep(), UnpackArrayDType)) { nodep->v3warn(E_UNSUPPORTED, "Unsupported: unpacked arrays with protect-lib on " @@ -397,7 +397,7 @@ private: } } - virtual void visit(AstNode*) VL_OVERRIDE {} + virtual void visit(AstNode*) override {} string cInputConnection(AstVar* varp) { string frstmt; @@ -486,35 +486,8 @@ private: public: explicit ProtectVisitor(AstNode* nodep) - : m_vfilep(NULL) - , m_cfilep(NULL) - , m_modPortsp(NULL) - , m_comboPortsp(NULL) - , m_seqPortsp(NULL) - , m_comboIgnorePortsp(NULL) - , m_comboDeclsp(NULL) - , m_seqDeclsp(NULL) - , m_tmpDeclsp(NULL) - , m_hashValuep(NULL) - , m_comboParamsp(NULL) - , m_clkSensp(NULL) - , m_comboIgnoreParamsp(NULL) - , m_seqParamsp(NULL) - , m_nbAssignsp(NULL) - , m_seqAssignsp(NULL) - , m_comboAssignsp(NULL) - , m_cHashValuep(NULL) - , m_cComboParamsp(NULL) - , m_cComboInsp(NULL) - , m_cComboOutsp(NULL) - , m_cSeqParamsp(NULL) - , m_cSeqClksp(NULL) - , m_cSeqOutsp(NULL) - , m_cIgnoreParamsp(NULL) - , m_libName(v3Global.opt.protectLib()) - , m_topName(v3Global.opt.prefix()) - , m_foundTop(false) - , m_hasClk(false) { + : m_libName{v3Global.opt.protectLib()} + , m_topName{v3Global.opt.prefix()} { iterate(nodep); } }; diff --git a/src/V3Reloop.cpp b/src/V3Reloop.cpp index 05b090a72..7122b906c 100644 --- a/src/V3Reloop.cpp +++ b/src/V3Reloop.cpp @@ -39,7 +39,7 @@ #include -#define RELOOP_MIN_ITERS 40 // Need at least this many loops to do this optimization +constexpr unsigned RELOOP_MIN_ITERS = 40; // Need at least this many loops to do this optimization //###################################################################### @@ -55,18 +55,18 @@ private: // STATE VDouble0 m_statReloops; // Statistic tracking VDouble0 m_statReItems; // Statistic tracking - AstCFunc* m_cfuncp; // Current block + AstCFunc* m_cfuncp = nullptr; // Current block AssVec m_mgAssignps; // List of assignments merging - AstCFunc* m_mgCfuncp; // Parent C function - AstNode* m_mgNextp; // Next node - AstNodeSel* m_mgSelLp; // Parent select, NULL = idle - AstNodeSel* m_mgSelRp; // Parent select, NULL = constant - AstNodeVarRef* m_mgVarrefLp; // Parent varref - AstNodeVarRef* m_mgVarrefRp; // Parent varref, NULL = constant - AstConst* m_mgConstRp; // Parent RHS constant, NULL = sel - uint32_t m_mgIndexLo; // Merge range - uint32_t m_mgIndexHi; // Merge range + AstCFunc* m_mgCfuncp = nullptr; // Parent C function + AstNode* m_mgNextp = nullptr; // Next node + AstNodeSel* m_mgSelLp = nullptr; // Parent select, nullptr = idle + AstNodeSel* m_mgSelRp = nullptr; // Parent select, nullptr = constant + AstNodeVarRef* m_mgVarrefLp = nullptr; // Parent varref + AstNodeVarRef* m_mgVarrefRp = nullptr; // Parent varref, nullptr = constant + AstConst* m_mgConstRp = nullptr; // Parent RHS constant, nullptr = sel + uint32_t m_mgIndexLo = 0; // Merge range + uint32_t m_mgIndexHi = 0; // Merge range // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -106,7 +106,7 @@ private: AstNode* incp = new AstAssign( fl, new AstVarRef(fl, itp, true), new AstAdd(fl, new AstConst(fl, 1), new AstVarRef(fl, itp, false))); - AstWhile* whilep = new AstWhile(fl, condp, NULL, incp); + AstWhile* whilep = new AstWhile(fl, condp, nullptr, incp); initp->addNext(whilep); bodyp->replaceWith(initp); whilep->addBodysp(bodyp); @@ -124,8 +124,7 @@ private: if (debug() >= 9) whilep->dumpTree(cout, "-new: "); // Remove remaining assigns - for (AssVec::iterator it = m_mgAssignps.begin(); it != m_mgAssignps.end(); ++it) { - AstNodeAssign* assp = *it; + for (AstNodeAssign* assp : m_mgAssignps) { if (assp != bodyp) { VL_DO_DANGLING(assp->unlinkFrBack()->deleteTree(), assp); } @@ -133,21 +132,21 @@ private: } // Setup for next merge m_mgAssignps.clear(); - m_mgSelLp = NULL; - m_mgSelRp = NULL; - m_mgVarrefLp = NULL; - m_mgVarrefRp = NULL; - m_mgConstRp = NULL; + m_mgSelLp = nullptr; + m_mgSelRp = nullptr; + m_mgVarrefLp = nullptr; + m_mgVarrefRp = nullptr; + m_mgConstRp = nullptr; } } // VISITORS - 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(AstNodeAssign* nodep) VL_OVERRIDE { + virtual void visit(AstNodeAssign* nodep) override { if (!m_cfuncp) return; // Left select WordSel or ArraySel @@ -177,7 +176,7 @@ private: // RHS is a constant or a select AstConst* rconstp = VN_CAST(nodep->rhsp(), Const); AstNodeSel* rselp = VN_CAST(nodep->rhsp(), NodeSel); - AstNodeVarRef* rvarrefp = NULL; + AstNodeVarRef* rvarrefp = nullptr; if (rconstp) { // Ok } else { if (!rselp) { @@ -232,26 +231,14 @@ private: UINFO(9, "Start merge i=" << index << " " << nodep << endl); } //-------------------- - virtual void visit(AstVar*) VL_OVERRIDE {} // Accelerate - virtual void visit(AstNodeMath*) VL_OVERRIDE {} // Accelerate - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstVar*) override {} // Accelerate + virtual void visit(AstNodeMath*) override {} // Accelerate + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - explicit ReloopVisitor(AstNetlist* nodep) { - m_cfuncp = NULL; - m_mgCfuncp = NULL; - m_mgNextp = NULL; - m_mgSelLp = NULL; - m_mgSelRp = NULL; - m_mgVarrefLp = NULL; - m_mgVarrefRp = NULL; - m_mgConstRp = NULL; - m_mgIndexLo = 0; - m_mgIndexHi = 0; - iterate(nodep); - } - virtual ~ReloopVisitor() { + explicit ReloopVisitor(AstNetlist* nodep) { iterate(nodep); } + virtual ~ReloopVisitor() override { V3Stats::addStat("Optimizations, Reloops", m_statReloops); V3Stats::addStat("Optimizations, Reloop iterations", m_statReItems); } diff --git a/src/V3Scope.cpp b/src/V3Scope.cpp index 755ed82e2..7e54b0a30 100644 --- a/src/V3Scope.cpp +++ b/src/V3Scope.cpp @@ -30,8 +30,8 @@ #include #include -#include VL_INCLUDE_UNORDERED_MAP -#include VL_INCLUDE_UNORDERED_SET +#include +#include //###################################################################### // Scope class functions @@ -45,17 +45,17 @@ private: AstUser2InUse m_inuser2; // TYPES - typedef vl_unordered_map PackageScopeMap; + typedef std::unordered_map PackageScopeMap; // These cannot be unordered unless make a specialized hashing pair (gcc-8) typedef std::map, AstVarScope*> VarScopeMap; - typedef std::set > VarRefScopeSet; + typedef std::set> VarRefScopeSet; // STATE, inside processing a single module - AstNodeModule* m_modp; // Current module - AstScope* m_scopep; // Current scope we are building + AstNodeModule* m_modp = nullptr; // Current module + AstScope* m_scopep = nullptr; // Current scope we are building // STATE, for passing down one level of hierarchy (may need save/restore) - AstCell* m_aboveCellp; // Cell that instantiates this module - AstScope* m_aboveScopep; // Scope that instantiates this scope + AstCell* m_aboveCellp = nullptr; // Cell that instantiates this module + AstScope* m_aboveScopep = nullptr; // Scope that instantiates this scope PackageScopeMap m_packageScopes; // Scopes for each package VarScopeMap m_varScopes; // Varscopes created for each scope and var @@ -70,11 +70,11 @@ private: AstVarRef* nodep = it->first; AstScope* scopep = it->second; if (nodep->packagep() && !nodep->varp()->isClassMember()) { - PackageScopeMap::iterator it2 = m_packageScopes.find(nodep->packagep()); + const auto it2 = m_packageScopes.find(nodep->packagep()); UASSERT_OBJ(it2 != m_packageScopes.end(), nodep, "Can't locate package scope"); scopep = it2->second; } - VarScopeMap::iterator it3 = m_varScopes.find(make_pair(nodep->varp(), scopep)); + const auto it3 = m_varScopes.find(make_pair(nodep->varp(), scopep)); UASSERT_OBJ(it3 != m_varScopes.end(), nodep, "Can't locate varref scope"); AstVarScope* varscp = it3->second; nodep->varScopep(varscp); @@ -82,19 +82,19 @@ private: } // VISITORS - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { AstNodeModule* modp = nodep->topModulep(); if (!modp) { nodep->v3error("No top level module found"); return; } // Operate starting at the top of the hierarchy - m_aboveCellp = NULL; - m_aboveScopep = NULL; + m_aboveCellp = nullptr; + m_aboveScopep = nullptr; iterate(modp); cleanupVarRefs(); } - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { + virtual void visit(AstNodeModule* nodep) override { // Create required blocks and add to module string scopename; if (!m_aboveScopep) { @@ -117,9 +117,9 @@ private: // Now for each child cell, iterate the module this cell points to for (AstNode* cellnextp = nodep->stmtsp(); cellnextp; cellnextp = cellnextp->nextp()) { if (AstCell* cellp = VN_CAST(cellnextp, Cell)) { - AstScope* oldScopep = m_scopep; - AstCell* oldAbCellp = m_aboveCellp; - AstScope* oldAbScopep = m_aboveScopep; + VL_RESTORER(m_scopep); + VL_RESTORER(m_aboveCellp); + VL_RESTORER(m_aboveScopep); { m_aboveCellp = cellp; m_aboveScopep = m_scopep; @@ -127,10 +127,6 @@ private: UASSERT_OBJ(modp, cellp, "Unlinked mod"); iterate(modp); // Recursive call to visit(AstNodeModule) } - // Done, restore vars - m_scopep = oldScopep; - m_aboveCellp = oldAbCellp; - m_aboveScopep = oldAbScopep; } } @@ -151,11 +147,11 @@ private: // ***Note m_scopep is passed back to the caller of the routine (above) } - virtual void visit(AstClass* nodep) VL_OVERRIDE { + virtual void visit(AstClass* nodep) override { // Create required blocks and add to module - AstScope* oldScopep = m_scopep; - AstCell* oldAbCellp = m_aboveCellp; - AstScope* oldAbScopep = m_aboveScopep; + VL_RESTORER(m_scopep); + VL_RESTORER(m_aboveCellp); + VL_RESTORER(m_aboveScopep); { m_aboveScopep = m_scopep; @@ -179,18 +175,14 @@ private: iterateChildren(nodep); } - // Done, restore vars - m_scopep = oldScopep; - m_aboveCellp = oldAbCellp; - m_aboveScopep = oldAbScopep; } - virtual void visit(AstCellInline* nodep) VL_OVERRIDE { // + virtual void visit(AstCellInline* nodep) override { // nodep->scopep(m_scopep); } - virtual void visit(AstActive* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE + virtual void visit(AstActive* nodep) override { // LCOV_EXCL_LINE nodep->v3fatalSrc("Actives now made after scoping"); } - virtual void visit(AstNodeProcedure* nodep) VL_OVERRIDE { + virtual void visit(AstNodeProcedure* nodep) override { // Add to list of blocks under this scope UINFO(4, " Move " << nodep << endl); AstNode* clonep = nodep->cloneTree(false); @@ -198,7 +190,7 @@ private: m_scopep->addActivep(clonep); iterateChildren(clonep); // We iterate under the *clone* } - virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { + virtual void visit(AstAssignAlias* nodep) override { // Add to list of blocks under this scope UINFO(4, " Move " << nodep << endl); AstNode* clonep = nodep->cloneTree(false); @@ -206,7 +198,7 @@ private: m_scopep->addActivep(clonep); iterateChildren(clonep); // We iterate under the *clone* } - virtual void visit(AstAssignVarScope* nodep) VL_OVERRIDE { + virtual void visit(AstAssignVarScope* nodep) override { // Copy under the scope but don't recurse UINFO(4, " Move " << nodep << endl); AstNode* clonep = nodep->cloneTree(false); @@ -214,7 +206,7 @@ private: m_scopep->addActivep(clonep); iterateChildren(clonep); // We iterate under the *clone* } - virtual void visit(AstAssignW* nodep) VL_OVERRIDE { + virtual void visit(AstAssignW* nodep) override { // Add to list of blocks under this scope UINFO(4, " Move " << nodep << endl); AstNode* clonep = nodep->cloneTree(false); @@ -222,7 +214,7 @@ private: m_scopep->addActivep(clonep); iterateChildren(clonep); // We iterate under the *clone* } - virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE { + virtual void visit(AstAlwaysPublic* nodep) override { // Add to list of blocks under this scope UINFO(4, " Move " << nodep << endl); AstNode* clonep = nodep->cloneTree(false); @@ -230,7 +222,7 @@ private: m_scopep->addActivep(clonep); iterateChildren(clonep); // We iterate under the *clone* } - virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE { + virtual void visit(AstCoverToggle* nodep) override { // Add to list of blocks under this scope UINFO(4, " Move " << nodep << endl); AstNode* clonep = nodep->cloneTree(false); @@ -238,7 +230,7 @@ private: m_scopep->addActivep(clonep); iterateChildren(clonep); // We iterate under the *clone* } - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstCFunc* nodep) override { // Add to list of blocks under this scope UINFO(4, " CFUNC " << nodep << endl); AstCFunc* clonep = nodep->cloneTree(false); @@ -248,7 +240,7 @@ private: // We iterate under the *clone* iterateChildren(clonep); } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTask* nodep) override { // Add to list of blocks under this scope UINFO(4, " FTASK " << nodep << endl); AstNodeFTask* clonep; @@ -264,7 +256,7 @@ private: // We iterate under the *clone* iterateChildren(clonep); } - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { // Make new scope variable if (!nodep->user1p()) { AstVarScope* varscp = new AstVarScope(nodep->fileline(), m_scopep, nodep); @@ -282,12 +274,12 @@ private: m_scopep->addVarp(varscp); } } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { // VarRef needs to point to VarScope // Make sure variable has made user1p. UASSERT_OBJ(nodep->varp(), nodep, "Unlinked"); if (nodep->varp()->isIfaceRef()) { - nodep->varScopep(NULL); + nodep->varScopep(nullptr); } else { // We may have not made the variable yet, and we can't make it now as // the var's referenced package etc might not be created yet. @@ -295,7 +287,7 @@ private: m_varRefScopes.insert(make_pair(nodep, m_scopep)); } } - 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() string prefix = string("__DOT__") + m_scopep->name(); // TOP and above will be the user's name(). @@ -311,24 +303,17 @@ private: if (afterp) nodep->scopeEntrp(afterp); iterateChildren(nodep); } - virtual void visit(AstScope* nodep) VL_OVERRIDE { + virtual void visit(AstScope* nodep) override { // Scope that was made by this module for different cell; // Want to ignore blocks under it, so just do nothing } //-------------------- - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - explicit ScopeVisitor(AstNetlist* nodep) { - m_aboveCellp = NULL; - m_aboveScopep = NULL; - m_modp = NULL; - m_scopep = NULL; - // - iterate(nodep); - } - virtual ~ScopeVisitor() {} + explicit ScopeVisitor(AstNetlist* nodep) { iterate(nodep); } + virtual ~ScopeVisitor() override {} }; //###################################################################### @@ -337,17 +322,17 @@ public: class ScopeCleanupVisitor : public AstNVisitor { private: // STATE - AstScope* m_scopep; // Current scope we are building + AstScope* m_scopep = nullptr; // Current scope we are building // METHODS VL_DEBUG_FUNC; // Declare debug() // VISITORS - virtual void visit(AstScope* nodep) VL_OVERRIDE { + virtual void visit(AstScope* nodep) override { // Want to ignore blocks under it m_scopep = nodep; iterateChildren(nodep); - m_scopep = NULL; + m_scopep = nullptr; } virtual void movedDeleteOrIterate(AstNode* nodep) { @@ -362,20 +347,20 @@ private: } } - virtual void visit(AstNodeProcedure* nodep) VL_OVERRIDE { movedDeleteOrIterate(nodep); } - virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { movedDeleteOrIterate(nodep); } - virtual void visit(AstAssignVarScope* nodep) VL_OVERRIDE { movedDeleteOrIterate(nodep); } - virtual void visit(AstAssignW* nodep) VL_OVERRIDE { movedDeleteOrIterate(nodep); } - virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE { movedDeleteOrIterate(nodep); } - virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE { movedDeleteOrIterate(nodep); } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { movedDeleteOrIterate(nodep); } - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { movedDeleteOrIterate(nodep); } + virtual void visit(AstNodeProcedure* nodep) override { movedDeleteOrIterate(nodep); } + virtual void visit(AstAssignAlias* nodep) override { movedDeleteOrIterate(nodep); } + virtual void visit(AstAssignVarScope* nodep) override { movedDeleteOrIterate(nodep); } + virtual void visit(AstAssignW* nodep) override { movedDeleteOrIterate(nodep); } + virtual void visit(AstAlwaysPublic* nodep) override { movedDeleteOrIterate(nodep); } + virtual void visit(AstCoverToggle* nodep) override { movedDeleteOrIterate(nodep); } + virtual void visit(AstNodeFTask* nodep) override { movedDeleteOrIterate(nodep); } + virtual void visit(AstCFunc* nodep) override { movedDeleteOrIterate(nodep); } - virtual void visit(AstVarXRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarXRef* nodep) override { // The crossrefs are dealt with in V3LinkDot - nodep->varp(NULL); + nodep->varp(nullptr); } - virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTaskRef* nodep) override { // The crossrefs are dealt with in V3LinkDot UINFO(9, " Old pkg-taskref " << nodep << endl); if (nodep->packagep()) { @@ -386,27 +371,24 @@ private: nodep->taskp(newp); UINFO(9, " New pkg-taskref " << nodep << endl); } else if (!VN_IS(nodep, MethodCall)) { - nodep->taskp(NULL); + nodep->taskp(nullptr); UINFO(9, " New pkg-taskref " << nodep << endl); } iterateChildren(nodep); } - virtual void visit(AstModportFTaskRef* nodep) VL_OVERRIDE { + virtual void visit(AstModportFTaskRef* nodep) override { // The crossrefs are dealt with in V3LinkDot - nodep->ftaskp(NULL); + nodep->ftaskp(nullptr); iterateChildren(nodep); } //-------------------- - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - explicit ScopeCleanupVisitor(AstNetlist* nodep) { - m_scopep = NULL; - iterate(nodep); - } - virtual ~ScopeCleanupVisitor() {} + explicit ScopeCleanupVisitor(AstNetlist* nodep) { iterate(nodep); } + virtual ~ScopeCleanupVisitor() override {} }; //###################################################################### diff --git a/src/V3Scoreboard.cpp b/src/V3Scoreboard.cpp index e0813489f..a4ffda454 100644 --- a/src/V3Scoreboard.cpp +++ b/src/V3Scoreboard.cpp @@ -26,7 +26,7 @@ public: uint32_t m_id; // CONSTRUCTORS explicit ScoreboardTestElem(uint32_t score) - : m_score(score) { + : m_score{score} { static uint32_t s_serial = 0; m_id = ++s_serial; } @@ -52,7 +52,7 @@ void V3ScoreboardBase::selfTest() { UASSERT(sb.needsRescore(), "SelfTest: Newly filled sb should need a rescore."); UASSERT(sb.needsRescore(&e1), "SelfTest: Individual newly-added element should need rescore"); - UASSERT(NULL == sb.bestp(), + UASSERT(nullptr == sb.bestp(), "SelfTest: Newly filled sb should have nothing eligible for Bestp()"); sb.rescore(); diff --git a/src/V3Scoreboard.h b/src/V3Scoreboard.h index 3936d831b..beffd2ca7 100644 --- a/src/V3Scoreboard.h +++ b/src/V3Scoreboard.h @@ -30,8 +30,8 @@ #include "V3Error.h" #include -#include VL_INCLUDE_UNORDERED_MAP -#include VL_INCLUDE_UNORDERED_SET +#include +#include //###################################################################### // SortByValueMap @@ -40,11 +40,11 @@ /// value-sorted order. Values need not be unique. Uses T_KeyCompare to /// break ties in the sort when values collide. -template > +template > class SortByValueMap { // TYPES private: - typedef vl_unordered_map Key2Val; + typedef std::unordered_map Key2Val; typedef std::set KeySet; typedef std::map Val2Keys; @@ -72,18 +72,17 @@ public: typename KeySet::iterator m_keyIt; typename Val2Keys::iterator m_valIt; SortByValueMap* m_sbvmp; - bool m_end; // At the end() + bool m_end = true; // At the end() // CONSTRUCTORS explicit const_iterator(SortByValueMap* sbmvp) // for end() - : m_sbvmp(sbmvp) - , m_end(true) {} + : m_sbvmp{sbmvp} {} const_iterator(typename Val2Keys::iterator valIt, typename KeySet::iterator keyIt, SortByValueMap* sbvmp) - : m_keyIt(keyIt) - , m_valIt(valIt) - , m_sbvmp(sbvmp) - , m_end(false) {} + : m_keyIt{keyIt} + , m_valIt{valIt} + , m_sbvmp{sbvmp} + , m_end{false} {} // METHODS void advanceUntilValid() { @@ -204,10 +203,10 @@ public: // CONSTRUCTORS explicit iterator(SortByValueMap* sbvmp) - : const_iterator(sbvmp) {} + : const_iterator{sbvmp} {} iterator(typename Val2Keys::iterator valIt, typename KeySet::iterator keyIt, SortByValueMap* sbvmp) - : const_iterator(valIt, keyIt, sbvmp) {} + : const_iterator{valIt, keyIt, sbvmp} {} // METHODS iterator& operator++() { @@ -248,16 +247,16 @@ private: public: iterator begin() { - typename Val2Keys::iterator valIt = m_vals.begin(); + const auto valIt = m_vals.begin(); if (valIt == m_vals.end()) return end(); - typename KeySet::const_iterator keyIt = valIt->second.begin(); + const auto keyIt = valIt->second.begin(); return iterator(valIt, keyIt, this); } const_iterator begin() const { SortByValueMap* mutp = const_cast(this); - typename Val2Keys::iterator valIt = mutp->m_vals.begin(); + const auto valIt = mutp->m_vals.begin(); if (valIt == mutp->m_vals.end()) return end(); - typename KeySet::const_iterator keyIt = valIt->second.begin(); + const auto keyIt = valIt->second.begin(); return const_iterator(valIt, keyIt, mutp); } iterator end() { return iterator(this); } @@ -272,24 +271,24 @@ public: const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } iterator find(const T_Key& k) { - typename Key2Val::iterator kvit = m_keys.find(k); + const auto kvit = m_keys.find(k); if (kvit == m_keys.end()) return end(); - typename Val2Keys::iterator valIt = m_vals.find(kvit->second); - typename KeySet::iterator keyIt = valIt->second.find(k); + const auto valIt = m_vals.find(kvit->second); + const auto keyIt = valIt->second.find(k); return iterator(valIt, keyIt, this); } const_iterator find(const T_Key& k) const { SortByValueMap* mutp = const_cast(this); - typename Key2Val::iterator kvit = mutp->m_keys.find(k); + const auto kvit = mutp->m_keys.find(k); if (kvit == mutp->m_keys.end()) return end(); - typename Val2Keys::iterator valIt = mutp->m_vals.find(kvit->second); - typename KeySet::iterator keyIt = valIt->second.find(k); + const auto valIt = mutp->m_vals.find(kvit->second); + const auto keyIt = valIt->second.find(k); return const_iterator(valIt, keyIt, mutp); } void set(const T_Key& k, const T_Value& v) { - typename Key2Val::iterator kvit = m_keys.find(k); + const auto kvit = m_keys.find(k); if (kvit != m_keys.end()) { if (kvit->second == v) { return; // LCOV_EXCL_LINE // Same value already present; stop. @@ -301,7 +300,7 @@ public: m_vals[v].insert(k); } size_t erase(const T_Key& k) { - typename Key2Val::iterator kvit = m_keys.find(k); + const auto kvit = m_keys.find(k); if (kvit == m_keys.end()) return 0; removeKeyFromOldVal(k, kvit->second); m_keys.erase(kvit); @@ -320,7 +319,7 @@ public: // be a const reference, otherwise the client could corrupt the sorted // order of m_byValue by reaching through and changing the value. const T_Value& at(const T_Key& k) const { - typename Key2Val::const_iterator kvit = m_keys.find(k); + const auto kvit = m_keys.find(k); UASSERT(kvit != m_keys.end(), "at() lookup key not found"); return kvit->second; } @@ -350,11 +349,11 @@ private: /// when the subset of elements whose scores change is much smaller than /// the full set size. -template > +template > class V3Scoreboard { private: // TYPES - typedef vl_unordered_set NeedRescoreSet; + typedef std::unordered_set NeedRescoreSet; class CmpElems { public: bool operator()(const T_Elem* const& ap, const T_Elem* const& bp) const { @@ -374,8 +373,8 @@ private: public: // CONSTRUCTORS explicit V3Scoreboard(UserScoreFnp scoreFnp, bool slowAsserts) - : m_scoreFnp(scoreFnp) - , m_slowAsserts(slowAsserts) {} + : m_scoreFnp{scoreFnp} + , m_slowAsserts{slowAsserts} {} ~V3Scoreboard() {} // METHODS @@ -408,7 +407,7 @@ public: } // Get the best element, with the lowest score (lower is better), among - // elements whose scores are known. Returns NULL if no elements with + // elements whose scores are known. Returns nullptr if no elements with // known scores exist. // // Note: This does not automatically rescore. Client must call @@ -416,8 +415,8 @@ public: // reflected in the result of bestp(). Otherwise, bestp() only // considers elements that aren't pending rescore. const T_Elem* bestp() { - typename SortedMap::iterator result = m_sorted.begin(); - if (VL_UNLIKELY(result == m_sorted.end())) return NULL; + const auto result = m_sorted.begin(); + if (VL_UNLIKELY(result == m_sorted.end())) return nullptr; return (*result).key(); } @@ -445,7 +444,7 @@ public: bool needsRescore(const T_Elem* elp) { return (m_unknown.find(elp) != m_unknown.end()); } // Retrieve the last known score for an element. T_Score cachedScore(const T_Elem* elp) { - typename SortedMap::iterator result = m_sorted.find(elp); + const auto result = m_sorted.find(elp); UASSERT(result != m_sorted.end(), "V3Scoreboard::cachedScore() failed to find element"); return (*result).value(); } @@ -453,9 +452,7 @@ public: // call the client's scoring function to get a new score, // and sort all elements by their current score. void rescore() { - for (typename NeedRescoreSet::iterator it = m_unknown.begin(); it != m_unknown.end(); - ++it) { - const T_Elem* elp = *it; + for (const T_Elem* elp : m_unknown) { T_Score sortScore = m_scoreFnp(elp); m_sorted.set(elp, sortScore); } diff --git a/src/V3SenTree.h b/src/V3SenTree.h index d4f5c3ecc..806b5919f 100644 --- a/src/V3SenTree.h +++ b/src/V3SenTree.h @@ -25,7 +25,7 @@ #include "V3Ast.h" #include "V3Hashed.h" -#include VL_INCLUDE_UNORDERED_SET +#include //###################################################################### // Collect SenTrees under the entire scope @@ -48,7 +48,7 @@ private: }; // MEMBERS - typedef vl_unordered_set Set; + typedef std::unordered_set Set; Set m_trees; // Set of sensitive blocks, for folding. public: @@ -59,8 +59,8 @@ public: void add(AstSenTree* nodep) { m_trees.insert(nodep); } AstSenTree* find(AstSenTree* likep) { - AstSenTree* resultp = NULL; - Set::iterator it = m_trees.find(likep); + AstSenTree* resultp = nullptr; + const auto it = m_trees.find(likep); if (it != m_trees.end()) resultp = *it; return resultp; } @@ -74,15 +74,14 @@ private: class SenTreeFinder { private: // STATE - AstTopScope* m_topScopep; // Top scope to add global SenTrees to + AstTopScope* m_topScopep = nullptr; // Top scope to add global SenTrees to SenTreeSet m_trees; // Set of global SenTrees VL_UNCOPYABLE(SenTreeFinder); public: // CONSTRUCTORS - SenTreeFinder() - : m_topScopep(NULL) {} + SenTreeFinder() {} // METHODS AstSenTree* getSenTree(AstSenTree* senTreep) { diff --git a/src/V3Simulate.h b/src/V3Simulate.h index d7cedc099..a2f1eb6f5 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -55,8 +55,8 @@ public: V3TaskConnects* m_tconnects; // CONSTRUCTORS SimStackNode(AstFuncRef* funcp, V3TaskConnects* tconnects) - : m_funcp(funcp) - , m_tconnects(tconnects) {} + : m_funcp{funcp} + , m_tconnects{tconnects} {} ~SimStackNode() {} }; @@ -85,7 +85,7 @@ private: // (and output for non-delayed assignments) // AstVar(Scope)::user2() -> AstCont*. Output value of variable (delayed assignments) - enum VarUsage { VU_NONE = 0, VU_LV = 1, VU_RV = 2, VU_LVDLY = 4 }; + enum VarUsage : uint8_t { VU_NONE = 0, VU_LV = 1, VU_RV = 2, VU_LVDLY = 4 }; // STATE // Major mode @@ -93,7 +93,7 @@ private: bool m_scoped; ///< Running with AstVarScopes instead of AstVars bool m_params; ///< Doing parameter propagation // Checking: - string m_whyNotOptimizable; ///< String explaining why not optimizable or NULL to optimize + string m_whyNotOptimizable; ///< String explaining why not optimizable or nullptr to optimize AstNode* m_whyNotNodep; ///< First node not optimizable bool m_anyAssignDly; ///< True if found a delayed assignment bool m_anyAssignComb; ///< True if found a non-delayed assignment @@ -198,7 +198,7 @@ public: m_whyNotOptimizable += stack.str(); } } - bool optimizable() const { return m_whyNotNodep == NULL; } + bool optimizable() const { return m_whyNotNodep == nullptr; } string whyNotMessage() const { return m_whyNotOptimizable; } AstNode* whyNotNodep() const { return m_whyNotNodep; } @@ -305,12 +305,12 @@ public: V3Number* fetchNumberNull(AstNode* nodep) { AstConst* constp = fetchConstNull(nodep); if (constp) return &constp->num(); - return NULL; + return nullptr; } V3Number* fetchOutNumberNull(AstNode* nodep) { AstConst* constp = fetchOutConstNull(nodep); if (constp) return &constp->num(); - return NULL; + return nullptr; } private: @@ -378,15 +378,15 @@ private: } // VISITORS - virtual void visit(AstAlways* nodep) VL_OVERRIDE { + virtual void visit(AstAlways* nodep) override { if (jumpingOver(nodep)) return; checkNodeInfo(nodep); iterateChildren(nodep); } - virtual void visit(AstSenTree* nodep) VL_OVERRIDE { + virtual void visit(AstSenTree* nodep) override { // Sensitivities aren't inputs per se; we'll keep our tree under the same sens. } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { if (jumpingOver(nodep)) return; if (!optimizable()) return; // Accelerate UASSERT_OBJ(nodep->varp(), nodep, "Unlinked"); @@ -423,7 +423,7 @@ private: } vscp->user1(vscp->user1() | VU_RV); bool isConst = nodep->varp()->isParam() && nodep->varp()->valuep(); - AstNode* valuep = isConst ? fetchValueNull(nodep->varp()->valuep()) : NULL; + AstNode* valuep = isConst ? fetchValueNull(nodep->varp()->valuep()) : nullptr; if (isConst && valuep) { // Propagate PARAM constants for constant function analysis if (!m_checkOnly && optimizable()) newValue(vscp, valuep); @@ -452,7 +452,7 @@ private: } } } - virtual void visit(AstVarXRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarXRef* nodep) override { if (jumpingOver(nodep)) return; if (m_scoped) { badNodeType(nodep); @@ -462,7 +462,7 @@ private: "allowed in constant functions"); } } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTask* nodep) override { if (jumpingOver(nodep)) return; if (!m_params) { badNodeType(nodep); @@ -474,7 +474,7 @@ private: checkNodeInfo(nodep); iterateChildren(nodep); } - virtual void visit(AstNodeIf* nodep) VL_OVERRIDE { + virtual void visit(AstNodeIf* nodep) override { if (jumpingOver(nodep)) return; UINFO(5, " IF " << nodep << endl); checkNodeInfo(nodep); @@ -491,15 +491,15 @@ private: } } } - virtual void visit(AstConst* nodep) VL_OVERRIDE { + virtual void visit(AstConst* nodep) override { checkNodeInfo(nodep); if (!m_checkOnly && optimizable()) newValue(nodep, nodep); } - virtual void visit(AstInitArray* nodep) VL_OVERRIDE { + virtual void visit(AstInitArray* nodep) override { checkNodeInfo(nodep); if (!m_checkOnly && optimizable()) newValue(nodep, nodep); } - virtual void visit(AstEnumItemRef* nodep) VL_OVERRIDE { + virtual void visit(AstEnumItemRef* nodep) override { checkNodeInfo(nodep); UASSERT_OBJ(nodep->itemp(), nodep, "Not linked"); if (!m_checkOnly && optimizable()) { @@ -512,7 +512,7 @@ private: } } } - virtual void visit(AstNodeUniop* nodep) VL_OVERRIDE { + virtual void visit(AstNodeUniop* nodep) override { if (!optimizable()) return; // Accelerate checkNodeInfo(nodep); iterateChildren(nodep); @@ -520,7 +520,7 @@ private: nodep->numberOperate(newConst(nodep)->num(), fetchConst(nodep->lhsp())->num()); } } - virtual void visit(AstNodeBiop* nodep) VL_OVERRIDE { + virtual void visit(AstNodeBiop* nodep) override { if (!optimizable()) return; // Accelerate checkNodeInfo(nodep); iterateChildren(nodep); @@ -529,7 +529,7 @@ private: fetchConst(nodep->rhsp())->num()); } } - virtual void visit(AstNodeTriop* nodep) VL_OVERRIDE { + virtual void visit(AstNodeTriop* nodep) override { if (!optimizable()) return; // Accelerate checkNodeInfo(nodep); iterateChildren(nodep); @@ -539,7 +539,7 @@ private: fetchConst(nodep->thsp())->num()); } } - virtual void visit(AstNodeQuadop* nodep) VL_OVERRIDE { + virtual void visit(AstNodeQuadop* nodep) override { if (!optimizable()) return; // Accelerate checkNodeInfo(nodep); iterateChildren(nodep); @@ -550,7 +550,7 @@ private: fetchConst(nodep->fhsp())->num()); } } - virtual void visit(AstLogAnd* nodep) VL_OVERRIDE { + virtual void visit(AstLogAnd* nodep) override { // Need to short circuit if (!optimizable()) return; // Accelerate checkNodeInfo(nodep); @@ -568,7 +568,7 @@ private: } } } - virtual void visit(AstLogOr* nodep) VL_OVERRIDE { + virtual void visit(AstLogOr* nodep) override { // Need to short circuit if (!optimizable()) return; // Accelerate checkNodeInfo(nodep); @@ -586,7 +586,7 @@ private: } } } - virtual void visit(AstLogIf* nodep) VL_OVERRIDE { + virtual void visit(AstLogIf* nodep) override { // Need to short circuit, same as (!A || B) if (!optimizable()) return; // Accelerate checkNodeInfo(nodep); @@ -605,7 +605,7 @@ private: } } } - virtual void visit(AstNodeCond* nodep) VL_OVERRIDE { + virtual void visit(AstNodeCond* nodep) override { // We could use above visit(AstNodeTriop), but need to do short circuiting. // It's also slower even O(n^2) to evaluate both sides when we // really only need to evaluate one side. @@ -647,7 +647,7 @@ private: } if (!m_checkOnly && optimizable()) { AstNode* vscp = varOrScope(varrefp); - AstInitArray* initp = NULL; + AstInitArray* initp = nullptr; if (AstInitArray* vscpnump = VN_CAST(fetchOutValueNull(vscp), InitArray)) { initp = vscpnump; } else if (AstInitArray* vscpnump = VN_CAST(fetchValueNull(vscp), InitArray)) { @@ -676,7 +676,7 @@ private: } } void handleAssignSel(AstNodeAssign* nodep, AstSel* selp) { - AstVarRef* varrefp = NULL; + AstVarRef* varrefp = nullptr; V3Number lsb(nodep); iterateAndNextNull(nodep->rhsp()); // Value to assign handleAssignSelRecurse(nodep, selp, varrefp /*ref*/, lsb /*ref*/, 0); @@ -684,7 +684,7 @@ private: UASSERT_OBJ(varrefp, nodep, "Indicated optimizable, but no variable found on RHS of select"); AstNode* vscp = varOrScope(varrefp); - AstConst* outconstp = NULL; + AstConst* outconstp = nullptr; if (AstConst* vscpnump = fetchOutConstNull(vscp)) { outconstp = vscpnump; } else if (AstConst* vscpnump = fetchConstNull(vscp)) { @@ -724,7 +724,7 @@ private: } } - virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { + virtual void visit(AstNodeAssign* nodep) override { if (jumpingOver(nodep)) return; if (!optimizable()) return; // Accelerate if (VN_IS(nodep, AssignDly)) { @@ -761,7 +761,7 @@ private: } m_inDlyAssign = false; } - virtual void visit(AstArraySel* nodep) VL_OVERRIDE { + virtual void visit(AstArraySel* nodep) override { checkNodeInfo(nodep); iterateChildren(nodep); if (AstInitArray* initp = VN_CAST(fetchValueNull(nodep->fromp()), InitArray)) { @@ -778,11 +778,11 @@ private: clearOptimizable(nodep, "Array select of non-array"); } } - virtual void visit(AstBegin* nodep) VL_OVERRIDE { + virtual void visit(AstBegin* nodep) override { checkNodeInfo(nodep); iterateChildren(nodep); } - virtual void visit(AstNodeCase* nodep) VL_OVERRIDE { + virtual void visit(AstNodeCase* nodep) override { if (jumpingOver(nodep)) return; UINFO(5, " CASE " << nodep << endl); checkNodeInfo(nodep); @@ -820,20 +820,20 @@ private: } } - virtual void visit(AstCaseItem* nodep) VL_OVERRIDE { + virtual void visit(AstCaseItem* nodep) override { // Real handling is in AstNodeCase if (jumpingOver(nodep)) return; checkNodeInfo(nodep); iterateChildren(nodep); } - virtual void visit(AstComment*) VL_OVERRIDE {} + virtual void visit(AstComment*) override {} - virtual void visit(AstJumpBlock* nodep) VL_OVERRIDE { + virtual void visit(AstJumpBlock* nodep) override { if (jumpingOver(nodep)) return; iterateChildren(nodep); } - virtual void visit(AstJumpGo* nodep) VL_OVERRIDE { + virtual void visit(AstJumpGo* nodep) override { if (jumpingOver(nodep)) return; checkNodeInfo(nodep); if (!m_checkOnly) { @@ -841,7 +841,7 @@ private: m_jumpp = nodep; } } - virtual void visit(AstJumpLabel* nodep) VL_OVERRIDE { + virtual void visit(AstJumpLabel* nodep) override { // This only supports forward jumps. That's all we make at present, // AstJumpGo::broken uses brokeExistsBelow() to check this. if (jumpingOver(nodep)) return; @@ -849,10 +849,10 @@ private: iterateChildren(nodep); if (m_jumpp && m_jumpp->labelp() == nodep) { UINFO(5, " JUMP DONE " << nodep << endl); - m_jumpp = NULL; + m_jumpp = nullptr; } } - virtual void visit(AstStop* nodep) VL_OVERRIDE { + virtual void visit(AstStop* nodep) override { if (jumpingOver(nodep)) return; if (m_params) { // This message seems better than an obscure $stop // The spec says $stop is just ignored, it seems evil to ignore assertions @@ -863,7 +863,7 @@ private: checkNodeInfo(nodep); } - virtual void visit(AstNodeFor* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFor* nodep) override { // Doing lots of Whiles is slow, so only for parameters UINFO(5, " FOR " << nodep << endl); if (!m_params) { @@ -895,7 +895,7 @@ private: } } - virtual void visit(AstWhile* nodep) VL_OVERRIDE { + virtual void visit(AstWhile* nodep) override { // Doing lots of Whiles is slow, so only for parameters if (jumpingOver(nodep)) return; UINFO(5, " WHILE " << nodep << endl); @@ -935,7 +935,7 @@ private: } } - virtual void visit(AstFuncRef* nodep) VL_OVERRIDE { + virtual void visit(AstFuncRef* nodep) override { if (jumpingOver(nodep)) return; if (!optimizable()) return; // Accelerate UINFO(5, " FUNCREF " << nodep << endl); @@ -987,7 +987,7 @@ private: } } - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { if (jumpingOver(nodep)) return; if (!m_params) { badNodeType(nodep); @@ -995,12 +995,12 @@ private: } } - virtual void visit(AstScopeName* nodep) VL_OVERRIDE { + virtual void visit(AstScopeName* nodep) override { if (jumpingOver(nodep)) return; // Ignore } - virtual void visit(AstSFormatF* nodep) VL_OVERRIDE { + virtual void visit(AstSFormatF* nodep) override { if (jumpingOver(nodep)) return; if (!optimizable()) return; // Accelerate iterateChildren(nodep); @@ -1009,9 +1009,9 @@ private: string result; string format = nodep->text(); - string::const_iterator pos = format.begin(); + auto pos = format.cbegin(); bool inPct = false; - for (; pos != format.end(); ++pos) { + for (; pos != format.cend(); ++pos) { if (!inPct && pos[0] == '%') { inPct = true; } else if (!inPct) { // Normal text @@ -1052,7 +1052,7 @@ private: } } - virtual void visit(AstDisplay* nodep) VL_OVERRIDE { + virtual void visit(AstDisplay* nodep) override { if (jumpingOver(nodep)) return; if (!optimizable()) return; // Accelerate iterateChildren(nodep); @@ -1074,7 +1074,7 @@ private: // These types are definitely not reducible // AstCoverInc, AstFinish, // AstRand, AstTime, AstUCFunc, AstCCall, AstCStmt, AstUCStmt - virtual void visit(AstNode* nodep) VL_OVERRIDE { + virtual void visit(AstNode* nodep) override { if (jumpingOver(nodep)) return; badNodeType(nodep); } @@ -1100,13 +1100,13 @@ public: } void clear() { m_whyNotOptimizable = ""; - m_whyNotNodep = NULL; + m_whyNotNodep = nullptr; m_anyAssignComb = false; m_anyAssignDly = false; m_inDlyAssign = false; m_instrCount = 0; m_dataCount = 0; - m_jumpp = NULL; + m_jumpp = nullptr; AstNode::user1ClearTree(); AstNode::user2ClearTree(); @@ -1131,16 +1131,11 @@ public: setMode(false /*scoped*/, false /*checking*/, true /*params*/); mainGuts(nodep); } - virtual ~SimulateVisitor() { - for (ConstPile::iterator it = m_constAllps.begin(); it != m_constAllps.end(); ++it) { - for (ConstDeque::iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) { - delete (*it2); - } - } - for (std::deque::iterator it = m_reclaimValuesp.begin(); - it != m_reclaimValuesp.end(); ++it) { - delete (*it); + virtual ~SimulateVisitor() override { + for (const auto& i : m_constAllps) { + for (AstConst* i2p : i.second) delete i2p; } + for (AstNode* ip : m_reclaimValuesp) delete ip; m_reclaimValuesp.clear(); m_constFreeps.clear(); m_constAllps.clear(); diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index 2c41c1db6..ccf559bbc 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -53,8 +53,8 @@ class SliceVisitor : public AstNVisitor { AstUser1InUse m_inuser1; // STATE - AstNode* m_assignp; // Assignment we are under - bool m_assignError; // True if the current assign already has an error + AstNode* m_assignp = nullptr; // Assignment we are under + bool m_assignError = false; // True if the current assign already has an error // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -123,7 +123,7 @@ class SliceVisitor : public AstNVisitor { return newp; } - virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { + virtual void visit(AstNodeAssign* nodep) override { // Called recursively on newly created assignments if (!nodep->user1() && !VN_IS(nodep, AssignAlias)) { nodep->user1(true); @@ -134,7 +134,7 @@ class SliceVisitor : public AstNVisitor { // Left and right could have different msb/lsbs/endianness, but #elements is common // and all variables are realigned to start at zero // Assign of a little endian'ed slice to a big endian one must reverse the elements - AstNode* newlistp = NULL; + AstNode* newlistp = nullptr; int elements = arrayp->rangep()->elementsConst(); for (int offset = 0; offset < elements; ++offset) { AstNode* newp = nodep->cloneType // AstNodeAssign @@ -152,11 +152,11 @@ class SliceVisitor : public AstNVisitor { } m_assignp = nodep; iterateChildren(nodep); - m_assignp = NULL; + m_assignp = nullptr; } } - virtual void visit(AstInitArray* nodep) VL_OVERRIDE { + virtual void visit(AstInitArray* nodep) override { UASSERT_OBJ(!m_assignp, nodep, "Array initialization should have been removed earlier"); } @@ -167,7 +167,7 @@ class SliceVisitor : public AstNVisitor { AstNodeDType* fromDtp = nodep->lhsp()->dtypep()->skipRefp(); UINFO(9, " Bi-Eq/Neq expansion " << nodep << endl); if (AstUnpackArrayDType* adtypep = VN_CAST(fromDtp, UnpackArrayDType)) { - AstNodeBiop* logp = NULL; + AstNodeBiop* logp = nullptr; if (!VN_IS(nodep->lhsp()->dtypep()->skipRefp(), NodeArrayDType)) { nodep->lhsp()->v3error( "Slice operator " @@ -188,9 +188,9 @@ class SliceVisitor : public AstNVisitor { new AstArraySel(nodep->fileline(), nodep->rhsp()->cloneTree(false), index)), NodeBiop); - if (!logp) + if (!logp) { logp = clonep; - else { + } else { switch (nodep->type()) { case AstType::atEq: // FALLTHRU case AstType::atEqCase: @@ -215,21 +215,17 @@ class SliceVisitor : public AstNVisitor { iterateChildren(nodep); } } - virtual void visit(AstEq* nodep) VL_OVERRIDE { expandBiOp(nodep); } - virtual void visit(AstNeq* nodep) VL_OVERRIDE { expandBiOp(nodep); } - virtual void visit(AstEqCase* nodep) VL_OVERRIDE { expandBiOp(nodep); } - virtual void visit(AstNeqCase* nodep) VL_OVERRIDE { expandBiOp(nodep); } + virtual void visit(AstEq* nodep) override { expandBiOp(nodep); } + virtual void visit(AstNeq* nodep) override { expandBiOp(nodep); } + virtual void visit(AstEqCase* nodep) override { expandBiOp(nodep); } + virtual void visit(AstNeqCase* nodep) override { expandBiOp(nodep); } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - explicit SliceVisitor(AstNetlist* nodep) { - m_assignp = NULL; - m_assignError = false; - iterate(nodep); - } - virtual ~SliceVisitor() {} + explicit SliceVisitor(AstNetlist* nodep) { iterate(nodep); } + virtual ~SliceVisitor() override {} }; //###################################################################### diff --git a/src/V3Split.cpp b/src/V3Split.cpp index bca88e300..69773c2b5 100644 --- a/src/V3Split.cpp +++ b/src/V3Split.cpp @@ -89,8 +89,8 @@ #include #include #include -#include VL_INCLUDE_UNORDERED_MAP -#include VL_INCLUDE_UNORDERED_SET +#include +#include //###################################################################### // Support classes @@ -100,14 +100,16 @@ class SplitNodeVertex : public V3GraphVertex { protected: SplitNodeVertex(V3Graph* graphp, AstNode* nodep) - : V3GraphVertex(graphp) - , m_nodep(nodep) {} - virtual ~SplitNodeVertex() {} + : V3GraphVertex{graphp} + , m_nodep{nodep} {} + virtual ~SplitNodeVertex() override {} // ACCESSORS // Do not make accessor for nodep(), It may change due to // reordering a lower block, but we don't repair it - virtual string name() const { return cvtToHex(m_nodep) + ' ' + m_nodep->prettyTypeName(); } - virtual FileLine* fileline() const { return nodep()->fileline(); } + virtual string name() const override { + return cvtToHex(m_nodep) + ' ' + m_nodep->prettyTypeName(); + } + virtual FileLine* fileline() const override { return nodep()->fileline(); } public: virtual AstNode* nodep() const { return m_nodep; } @@ -116,50 +118,49 @@ public: class SplitPliVertex : public SplitNodeVertex { public: explicit SplitPliVertex(V3Graph* graphp, AstNode* nodep) - : SplitNodeVertex(graphp, nodep) {} - virtual ~SplitPliVertex() {} - virtual string name() const { return "*PLI*"; } - virtual string dotColor() const { return "green"; } + : SplitNodeVertex{graphp, nodep} {} + virtual ~SplitPliVertex() override {} + virtual string name() const override { return "*PLI*"; } + virtual string dotColor() const override { return "green"; } }; class SplitLogicVertex : public SplitNodeVertex { public: SplitLogicVertex(V3Graph* graphp, AstNode* nodep) - : SplitNodeVertex(graphp, nodep) {} - virtual ~SplitLogicVertex() {} - virtual string dotColor() const { return "yellow"; } + : SplitNodeVertex{graphp, nodep} {} + virtual ~SplitLogicVertex() override {} + virtual string dotColor() const override { return "yellow"; } }; class SplitVarStdVertex : public SplitNodeVertex { public: SplitVarStdVertex(V3Graph* graphp, AstNode* nodep) - : SplitNodeVertex(graphp, nodep) {} - virtual ~SplitVarStdVertex() {} - virtual string dotColor() const { return "skyblue"; } + : SplitNodeVertex{graphp, nodep} {} + virtual ~SplitVarStdVertex() override {} + virtual string dotColor() const override { return "skyblue"; } }; class SplitVarPostVertex : public SplitNodeVertex { public: SplitVarPostVertex(V3Graph* graphp, AstNode* nodep) - : SplitNodeVertex(graphp, nodep) {} - virtual ~SplitVarPostVertex() {} - virtual string name() const { return string("POST ") + SplitNodeVertex::name(); } - virtual string dotColor() const { return "CadetBlue"; } + : SplitNodeVertex{graphp, nodep} {} + virtual ~SplitVarPostVertex() override {} + virtual string name() const override { return string("POST ") + SplitNodeVertex::name(); } + virtual string dotColor() const override { return "CadetBlue"; } }; //###################################################################### // Edge types class SplitEdge : public V3GraphEdge { - uint32_t m_ignoreInStep; // Step number that if set to, causes this edge to be ignored + uint32_t m_ignoreInStep = 0; // Step number that if set to, causes this edge to be ignored static uint32_t s_stepNum; // Global step number protected: - enum { WEIGHT_NORMAL = 10 }; + static constexpr int WEIGHT_NORMAL = 10; SplitEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight, bool cutable = CUTABLE) - : V3GraphEdge(graphp, fromp, top, weight, cutable) - , m_ignoreInStep(0) {} - virtual ~SplitEdge() {} + : V3GraphEdge{graphp, fromp, top, weight, cutable} {} + virtual ~SplitEdge() override {} public: // Iterator for graph functions @@ -178,7 +179,7 @@ public: if (!oedgep) v3fatalSrc("Following edge of non-SplitEdge type"); return (!oedgep->ignoreThisStep()); } - virtual string dotStyle() const { + virtual string dotStyle() const override { return ignoreThisStep() ? "dotted" : V3GraphEdge::dotStyle(); } }; @@ -187,37 +188,37 @@ uint32_t SplitEdge::s_stepNum = 0; class SplitPostEdge : public SplitEdge { public: SplitPostEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) - : SplitEdge(graphp, fromp, top, WEIGHT_NORMAL) {} - virtual ~SplitPostEdge() {} - virtual bool followScoreboard() const { return false; } - virtual string dotColor() const { return "khaki"; } + : SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {} + virtual ~SplitPostEdge() override {} + virtual bool followScoreboard() const override { return false; } + virtual string dotColor() const override { return "khaki"; } }; class SplitLVEdge : public SplitEdge { public: SplitLVEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) - : SplitEdge(graphp, fromp, top, WEIGHT_NORMAL) {} - virtual ~SplitLVEdge() {} - virtual bool followScoreboard() const { return true; } - virtual string dotColor() const { return "yellowGreen"; } + : SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {} + virtual ~SplitLVEdge() override {} + virtual bool followScoreboard() const override { return true; } + virtual string dotColor() const override { return "yellowGreen"; } }; class SplitRVEdge : public SplitEdge { public: SplitRVEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) - : SplitEdge(graphp, fromp, top, WEIGHT_NORMAL) {} - virtual ~SplitRVEdge() {} - virtual bool followScoreboard() const { return true; } - virtual string dotColor() const { return "green"; } + : SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {} + virtual ~SplitRVEdge() override {} + virtual bool followScoreboard() const override { return true; } + virtual string dotColor() const override { return "green"; } }; struct SplitScorebdEdge : public SplitEdge { public: SplitScorebdEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) - : SplitEdge(graphp, fromp, top, WEIGHT_NORMAL) {} - virtual ~SplitScorebdEdge() {} - virtual bool followScoreboard() const { return true; } - virtual string dotColor() const { return "blue"; } + : SplitEdge{graphp, fromp, top, WEIGHT_NORMAL} {} + virtual ~SplitScorebdEdge() override {} + virtual bool followScoreboard() const override { return true; } + virtual string dotColor() const override { return "blue"; } }; struct SplitStrictEdge : public SplitEdge { @@ -225,10 +226,10 @@ struct SplitStrictEdge : public SplitEdge { // The only non-cutable edge type public: SplitStrictEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top) - : SplitEdge(graphp, fromp, top, WEIGHT_NORMAL, NOT_CUTABLE) {} - virtual ~SplitStrictEdge() {} - virtual bool followScoreboard() const { return true; } - virtual string dotColor() const { return "blue"; } + : SplitEdge{graphp, fromp, top, WEIGHT_NORMAL, NOT_CUTABLE} {} + virtual ~SplitStrictEdge() override {} + virtual bool followScoreboard() const override { return true; } + virtual string dotColor() const override { return "blue"; } }; //###################################################################### @@ -261,7 +262,7 @@ protected: // CONSTRUCTORS public: SplitReorderBaseVisitor() { scoreboardClear(); } - virtual ~SplitReorderBaseVisitor() { + virtual ~SplitReorderBaseVisitor() override { V3Stats::addStat("Optimizations, Split always", m_statSplits); } @@ -274,7 +275,7 @@ protected: m_inDly = false; m_graph.clear(); m_stmtStackps.clear(); - m_pliVertexp = NULL; + m_pliVertexp = nullptr; m_noReorderWhy = ""; AstNode::user1ClearTree(); AstNode::user2ClearTree(); @@ -339,19 +340,19 @@ protected: virtual void makeRvalueEdges(SplitVarStdVertex* vstdp) = 0; // VISITORS - virtual void visit(AstAlways* nodep) VL_OVERRIDE = 0; - virtual void visit(AstNodeIf* nodep) VL_OVERRIDE = 0; + virtual void visit(AstAlways* nodep) override = 0; + virtual void visit(AstNodeIf* nodep) override = 0; // We don't do AstNodeFor/AstWhile loops, due to the standard question // of what is before vs. after - virtual void visit(AstAssignDly* nodep) VL_OVERRIDE { + virtual void visit(AstAssignDly* nodep) override { m_inDly = true; UINFO(4, " ASSIGNDLY " << nodep << endl); iterateChildren(nodep); m_inDly = false; } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { if (!m_stmtStackps.empty()) { AstVarScope* vscp = nodep->varScopep(); UASSERT_OBJ(vscp, nodep, "Not linked"); @@ -393,18 +394,16 @@ protected: SplitVarPostVertex* vpostp = reinterpret_cast(vscp->user2p()); // Add edges - for (VStack::iterator it = m_stmtStackps.begin(); it != m_stmtStackps.end(); - ++it) { - new SplitLVEdge(&m_graph, vpostp, *it); + for (SplitLogicVertex* vxp : m_stmtStackps) { + new SplitLVEdge(&m_graph, vpostp, vxp); } } else { // Nondelayed assignment if (nodep->lvalue()) { // Non-delay; need to maintain existing ordering // with all consumers of the signal UINFO(4, " VARREFLV: " << nodep << endl); - for (VStack::iterator it = m_stmtStackps.begin(); - it != m_stmtStackps.end(); ++it) { - new SplitLVEdge(&m_graph, vstdp, *it); + for (SplitLogicVertex* ivxp : m_stmtStackps) { + new SplitLVEdge(&m_graph, vstdp, ivxp); } } else { UINFO(4, " VARREF: " << nodep << endl); @@ -415,7 +414,7 @@ protected: } } - virtual void visit(AstJumpGo* nodep) VL_OVERRIDE { + virtual void visit(AstJumpGo* nodep) override { // Jumps will disable reordering at all levels // This is overly pessimistic; we could treat jumps as barriers, and // reorder everything between jumps/labels, however jumps are rare @@ -427,7 +426,7 @@ protected: //-------------------- // Default - virtual void visit(AstNode* nodep) VL_OVERRIDE { + virtual void visit(AstNode* nodep) override { // **** SPECIAL default type that sets PLI_ORDERING if (!m_stmtStackps.empty() && !nodep->isPure()) { UINFO(9, " NotSplittable " << nodep << endl); @@ -444,14 +443,12 @@ class ReorderVisitor : public SplitReorderBaseVisitor { // CONSTRUCTORS public: explicit ReorderVisitor(AstNetlist* nodep) { iterate(nodep); } - virtual ~ReorderVisitor() {} + virtual ~ReorderVisitor() override {} // METHODS protected: - virtual void makeRvalueEdges(SplitVarStdVertex* vstdp) VL_OVERRIDE { - for (VStack::iterator it = m_stmtStackps.begin(); it != m_stmtStackps.end(); ++it) { - new SplitRVEdge(&m_graph, *it, vstdp); - } + virtual void makeRvalueEdges(SplitVarStdVertex* vstdp) override { + for (SplitLogicVertex* vxp : m_stmtStackps) new SplitRVEdge(&m_graph, vxp, vstdp); } void cleanupBlockGraph(AstNode* nodep) { @@ -502,7 +499,7 @@ protected: m_graph.weaklyConnected(&SplitEdge::followScoreboard); // Add hard orderings between all nodes of same color, in the order they appeared - vl_unordered_map lastOfColor; + std::unordered_map lastOfColor; for (AstNode* nextp = nodep; nextp; nextp = nextp->nextp()) { SplitLogicVertex* vvertexp = reinterpret_cast(nextp->user3p()); uint32_t color = vvertexp->color(); @@ -546,7 +543,7 @@ protected: UINFO(6, " No changes\n"); } else { AstNRelinker replaceHandle; // Where to add the list - AstNode* newListp = NULL; + AstNode* newListp = nullptr; for (RankNodeMap::const_iterator it = rankMap.begin(); it != rankMap.end(); ++it) { AstNode* nextp = it->second; UINFO(6, " New order: " << nextp << endl); @@ -572,7 +569,7 @@ protected: // Save recursion state AstNode* firstp = nodep; // We may reorder, and nodep is no longer first. void* oldBlockUser3 = nodep->user3p(); // May be overloaded in below loop, save it - nodep->user3p(NULL); + nodep->user3p(nullptr); UASSERT_OBJ(nodep->firstAbovep(), nodep, "Node passed is in next list; should have processed all list at once"); // Process it @@ -603,7 +600,7 @@ protected: firstp->user3p(oldBlockUser3); } - virtual void visit(AstAlways* nodep) VL_OVERRIDE { + virtual void visit(AstAlways* nodep) override { UINFO(4, " ALW " << nodep << endl); if (debug() >= 9) nodep->dumpTree(cout, " alwIn:: "); scoreboardClear(); @@ -611,7 +608,7 @@ protected: if (debug() >= 9) nodep->dumpTree(cout, " alwOut: "); } - virtual void visit(AstNodeIf* nodep) VL_OVERRIDE { + virtual void visit(AstNodeIf* nodep) override { UINFO(4, " IF " << nodep << endl); iterateAndNextNull(nodep->condp()); processBlock(nodep->ifsp()); @@ -622,7 +619,7 @@ private: VL_UNCOPYABLE(ReorderVisitor); }; -typedef vl_unordered_set ColorSet; +typedef std::unordered_set ColorSet; typedef std::vector AlwaysVec; class IfColorVisitor : public AstNVisitor { @@ -632,7 +629,7 @@ class IfColorVisitor : public AstNVisitor { typedef std::vector IfStack; IfStack m_ifStack; // Stack of nested if-statements we're currently processing - typedef vl_unordered_map IfColorMap; + typedef std::unordered_map IfColorMap; IfColorMap m_ifColors; // Map each if-statement to the set of colors (split blocks) // that will get a copy of that if-statement @@ -641,12 +638,12 @@ public: // Visit through *nodep and map each AstNodeIf within to the set of // colors it will participate in. Also find the whole set of colors. explicit IfColorVisitor(AstAlways* nodep) { iterate(nodep); } - virtual ~IfColorVisitor() {} + virtual ~IfColorVisitor() override {} // METHODS const ColorSet& colors() const { return m_colors; } const ColorSet& colors(AstNodeIf* nodep) const { - IfColorMap::const_iterator it = m_ifColors.find(nodep); + const auto it = m_ifColors.find(nodep); UASSERT_OBJ(it != m_ifColors.end(), nodep, "Node missing from split color() map"); return it->second; } @@ -667,13 +664,13 @@ private: } protected: - virtual void visit(AstNodeIf* nodep) VL_OVERRIDE { + virtual void visit(AstNodeIf* nodep) override { m_ifStack.push_back(nodep); trackNode(nodep); iterateChildren(nodep); m_ifStack.pop_back(); } - virtual void visit(AstNode* nodep) VL_OVERRIDE { + virtual void visit(AstNode* nodep) override { trackNode(nodep); iterateChildren(nodep); } @@ -689,7 +686,7 @@ class EmitSplitVisitor : public AstNVisitor { const IfColorVisitor* m_ifColorp; // Digest of results of prior coloring // Map each color to our current place within the color's new always - typedef vl_unordered_map LocMap; + typedef std::unordered_map LocMap; LocMap m_addAfter; AlwaysVec* m_newBlocksp; // Split always blocks we have generated @@ -700,13 +697,13 @@ public: // and generates its split blocks, writing the split blocks // into *newBlocksp. EmitSplitVisitor(AstAlways* nodep, const IfColorVisitor* ifColorp, AlwaysVec* newBlocksp) - : m_origAlwaysp(nodep) - , m_ifColorp(ifColorp) - , m_newBlocksp(newBlocksp) { + : m_origAlwaysp{nodep} + , m_ifColorp{ifColorp} + , m_newBlocksp{newBlocksp} { UINFO(6, " splitting always " << nodep << endl); } - virtual ~EmitSplitVisitor() {} + virtual ~EmitSplitVisitor() override {} // METHODS void go() { @@ -716,7 +713,7 @@ public: // We don't need to clone m_origAlwaysp->sensesp() here; // V3Activate already moved it to a parent node. AstAlways* alwaysp - = new AstAlways(m_origAlwaysp->fileline(), VAlwaysKwd::ALWAYS, NULL, NULL); + = new AstAlways(m_origAlwaysp->fileline(), VAlwaysKwd::ALWAYS, nullptr, nullptr); // Put a placeholder node into stmtp to track our position. // We'll strip these out after the blocks are fully cloned. AstSplitPlaceholder* placeholderp = makePlaceholderp(); @@ -737,7 +734,7 @@ protected: return new AstSplitPlaceholder(m_origAlwaysp->fileline()); } - virtual void visit(AstNode* nodep) VL_OVERRIDE { + virtual void visit(AstNode* nodep) override { // Anything that's not an if/else we assume is a leaf // (that is, something we won't split.) Don't visit further // into the leaf. @@ -759,9 +756,9 @@ protected: m_addAfter[color] = clonedp; } - virtual void visit(AstNodeIf* nodep) VL_OVERRIDE { + virtual void visit(AstNodeIf* nodep) override { const ColorSet& colors = m_ifColorp->colors(nodep); - typedef vl_unordered_map CloneMap; + typedef std::unordered_map CloneMap; CloneMap clones; for (ColorSet::const_iterator color = colors.begin(); color != colors.end(); ++color) { @@ -785,15 +782,11 @@ protected: iterateAndNextNull(nodep->ifsp()); - for (ColorSet::const_iterator color = colors.begin(); color != colors.end(); ++color) { - m_addAfter[*color] = clones[*color]->elsesp(); - } + for (const auto& color : colors) m_addAfter[color] = clones[color]->elsesp(); iterateAndNextNull(nodep->elsesp()); - for (ColorSet::const_iterator color = colors.begin(); color != colors.end(); ++color) { - m_addAfter[*color] = clones[*color]; - } + for (const auto& color : colors) m_addAfter[color] = clones[color]; } private: @@ -801,20 +794,19 @@ private: }; class RemovePlaceholdersVisitor : public AstNVisitor { - typedef vl_unordered_set NodeSet; + typedef std::unordered_set NodeSet; NodeSet m_removeSet; // placeholders to be removed public: explicit RemovePlaceholdersVisitor(AstNode* nodep) { iterate(nodep); - for (NodeSet::const_iterator it = m_removeSet.begin(); it != m_removeSet.end(); ++it) { - AstNode* np = *it; + for (AstNode* np : m_removeSet) { np->unlinkFrBack(); // Without next VL_DO_DANGLING(np->deleteTree(), np); } } - virtual ~RemovePlaceholdersVisitor() {} - virtual void visit(AstSplitPlaceholder* nodep) VL_OVERRIDE { m_removeSet.insert(nodep); } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual ~RemovePlaceholdersVisitor() override {} + virtual void visit(AstSplitPlaceholder* nodep) override { m_removeSet.insert(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } private: VL_UNCOPYABLE(RemovePlaceholdersVisitor); @@ -825,16 +817,15 @@ private: // Keys are original always blocks pending delete, // values are newly split always blocks pending insertion // at the same position as the originals: - typedef vl_unordered_map ReplaceMap; + typedef std::unordered_map ReplaceMap; ReplaceMap m_replaceBlocks; // AstNodeIf* whose condition we're currently visiting - AstNode* m_curIfConditional; + AstNode* m_curIfConditional = nullptr; // CONSTRUCTORS public: - explicit SplitVisitor(AstNetlist* nodep) - : m_curIfConditional(NULL) { + explicit SplitVisitor(AstNetlist* nodep) { iterate(nodep); // Splice newly-split blocks into the tree. Remove placeholders @@ -853,11 +844,11 @@ public: } } - virtual ~SplitVisitor() {} + virtual ~SplitVisitor() override {} // METHODS protected: - virtual void makeRvalueEdges(SplitVarStdVertex* vstdp) VL_OVERRIDE { + virtual void makeRvalueEdges(SplitVarStdVertex* vstdp) override { // Each 'if' depends on rvalues in its own conditional ONLY, // not rvalues in the if/else bodies. for (VStack::const_iterator it = m_stmtStackps.begin(); it != m_stmtStackps.end(); ++it) { @@ -932,7 +923,7 @@ protected: if (debug() >= 9) m_graph.dumpDotFilePrefixed("splitg_colored", false); } - virtual void visit(AstAlways* nodep) VL_OVERRIDE { + virtual void visit(AstAlways* nodep) override { // build the scoreboard scoreboardClear(); scanBlock(nodep->bodysp()); @@ -964,11 +955,11 @@ protected: emitSplit.go(); } } - virtual void visit(AstNodeIf* nodep) VL_OVERRIDE { + virtual void visit(AstNodeIf* nodep) override { UINFO(4, " IF " << nodep << endl); m_curIfConditional = nodep; iterateAndNextNull(nodep->condp()); - m_curIfConditional = NULL; + m_curIfConditional = nullptr; scanBlock(nodep->ifsp()); scanBlock(nodep->elsesp()); } diff --git a/src/V3SplitAs.cpp b/src/V3SplitAs.cpp index 3aa5a4c2a..793638187 100644 --- a/src/V3SplitAs.cpp +++ b/src/V3SplitAs.cpp @@ -45,23 +45,20 @@ public: class SplitAsFindVisitor : public SplitAsBaseVisitor { private: // STATE - AstVarScope* m_splitVscp; // Variable we want to split + AstVarScope* m_splitVscp = nullptr; // Variable we want to split // METHODS - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { if (nodep->lvalue() && !m_splitVscp && nodep->varp()->attrIsolateAssign()) { m_splitVscp = nodep->varScopep(); } } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - explicit SplitAsFindVisitor(AstAlways* nodep) { - m_splitVscp = NULL; - iterate(nodep); - } - virtual ~SplitAsFindVisitor() {} + explicit SplitAsFindVisitor(AstAlways* nodep) { iterate(nodep); } + virtual ~SplitAsFindVisitor() override {} // METHODS AstVarScope* splitVscp() const { return m_splitVscp; } }; @@ -74,11 +71,11 @@ private: // STATE AstVarScope* m_splitVscp; // Variable we want to split bool m_modeMatch; // Remove matching Vscp, else non-matching - bool m_keepStmt; // Current Statement must be preserved - bool m_matches; // Statement below has matching lvalue reference + bool m_keepStmt = false; // Current Statement must be preserved + bool m_matches = false; // Statement below has matching lvalue reference // METHODS - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { if (nodep->lvalue()) { if (nodep->varScopep() == m_splitVscp) { UINFO(6, " CL VAR " << nodep << endl); @@ -86,7 +83,7 @@ private: } } } - virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE { + virtual void visit(AstNodeStmt* nodep) override { if (!nodep->isStatement()) { iterateChildren(nodep); return; @@ -112,18 +109,16 @@ private: m_keepStmt = oldKeep || m_keepStmt; UINFO(9, " upKeep=" << m_keepStmt << " STMT " << nodep << endl); } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - SplitAsCleanVisitor(AstAlways* nodep, AstVarScope* vscp, bool modeMatch) { - m_splitVscp = vscp; - m_modeMatch = modeMatch; - m_keepStmt = false; - m_matches = false; + SplitAsCleanVisitor(AstAlways* nodep, AstVarScope* vscp, bool modeMatch) + : m_splitVscp{vscp} + , m_modeMatch{modeMatch} { iterate(nodep); } - virtual ~SplitAsCleanVisitor() {} + virtual ~SplitAsCleanVisitor() override {} }; //###################################################################### @@ -137,7 +132,7 @@ private: // STATE VDouble0 m_statSplits; // Statistic tracking - AstVarScope* m_splitVscp; // Variable we want to split + AstVarScope* m_splitVscp = nullptr; // Variable we want to split // METHODS void splitAlways(AstAlways* nodep) { @@ -158,10 +153,10 @@ private: } } - virtual void visit(AstAlways* nodep) VL_OVERRIDE { + virtual void visit(AstAlways* nodep) override { // Are there any lvalue references below this? // There could be more than one. So, we process the first one found first. - AstVarScope* lastSplitVscp = NULL; + AstVarScope* lastSplitVscp = nullptr; while (!nodep->user1()) { // Find any splittable variables SplitAsFindVisitor visitor(nodep); @@ -183,17 +178,16 @@ private: } // Speedup; no always under math - virtual void visit(AstNodeMath*) VL_OVERRIDE {} - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNodeMath*) override {} + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit SplitAsVisitor(AstNetlist* nodep) { - m_splitVscp = NULL; AstNode::user1ClearTree(); // user1p() used on entire tree iterate(nodep); } - virtual ~SplitAsVisitor() { + virtual ~SplitAsVisitor() override { V3Stats::addStat("Optimizations, isolate_assignments blocks", m_statSplits); } }; diff --git a/src/V3SplitVar.cpp b/src/V3SplitVar.cpp index 3cda051f0..b7f308d47 100644 --- a/src/V3SplitVar.cpp +++ b/src/V3SplitVar.cpp @@ -142,28 +142,28 @@ struct SplitVarImpl { // Only SplitUnpackedVarVisitor can split WREAL. SplitPackedVarVisitor cannot. const bool ok = type == type.VAR || type == type.WIRE || type == type.PORT || type == type.WREAL; - if (ok) return NULL; + if (ok) return nullptr; return "it is not one of variable, net, port, nor wreal"; } static const char* cannotSplitVarDirectionReason(VDirection dir) { if (dir == VDirection::REF) return "it is a ref argument"; if (dir == VDirection::INOUT) return "it is an inout port"; - return NULL; + return nullptr; } static const char* cannotSplitConnectedPortReason(AstPin* pinp) { AstVar* varp = pinp->modVarp(); if (!varp) return "it is not connected"; if (const char* reason = cannotSplitVarDirectionReason(varp->direction())) return reason; - return NULL; + return nullptr; } static const char* cannotSplitTaskReason(const AstNodeFTask* taskp) { if (taskp->prototype()) return "the task is prototype declaration"; if (taskp->dpiImport()) return "the task is imported from DPI-C"; if (taskp->dpiOpenChild()) return "the task takes DPI-C open array"; - return NULL; + return nullptr; } static const char* cannotSplitVarCommonReason(const AstVar* varp) { @@ -174,7 +174,7 @@ struct SplitVarImpl { if (const char* reason = cannotSplitVarDirectionReason(varp->direction())) return reason; if (varp->isSigPublic()) return "it is public"; if (varp->isUsedLoopIdx()) return "it is used as a loop variable"; - return NULL; + return nullptr; } static const char* cannotSplitPackedVarReason(const AstVar* varp); @@ -243,29 +243,29 @@ class UnpackRef { bool m_ftask; // true if the reference is in function/task. false if in module. public: UnpackRef(AstNode* stmtp, AstVarRef* nodep, bool ftask) - : m_contextp(stmtp) - , m_nodep(nodep) - , m_index(-1) - , m_msb(0) - , m_lsb(1) - , m_lvalue(nodep->lvalue()) - , m_ftask(ftask) {} + : m_contextp{stmtp} + , m_nodep{nodep} + , m_index{-1} + , m_msb{0} + , m_lsb{1} + , m_lvalue{nodep->lvalue()} + , m_ftask{ftask} {} UnpackRef(AstNode* stmtp, AstArraySel* nodep, int idx, bool lvalue, bool ftask) - : m_contextp(stmtp) - , m_nodep(nodep) - , m_index(idx) - , m_msb(0) - , m_lsb(1) - , m_lvalue(lvalue) - , m_ftask(ftask) {} + : m_contextp{stmtp} + , m_nodep{nodep} + , m_index{idx} + , m_msb{0} + , m_lsb{1} + , m_lvalue{lvalue} + , m_ftask{ftask} {} UnpackRef(AstNode* stmtp, AstSliceSel* nodep, int msb, int lsb, bool lvalue, bool ftask) - : m_contextp(stmtp) - , m_nodep(nodep) - , m_index(msb == lsb ? msb : -1) // Equivalent to ArraySel - , m_msb(msb) - , m_lsb(lsb) - , m_lvalue(lvalue) - , m_ftask(ftask) {} + : m_contextp{stmtp} + , m_nodep{nodep} + , m_index{msb == lsb ? msb : -1} // Equivalent to ArraySel + , m_msb{msb} + , m_lsb{lsb} + , m_lvalue{lvalue} + , m_ftask{ftask} {} AstNode* nodep() const { return m_nodep; } bool isSingleRef() const { return VN_IS(m_nodep, ArraySel) || (m_msb == m_lsb && m_lsb == m_index); @@ -275,10 +275,6 @@ public: return m_index; } AstNode* context() const { return m_contextp; } - std::pair range() const { - UASSERT_OBJ(VN_IS(m_nodep, SliceSel), m_nodep, "not slice sel"); - return std::make_pair(m_msb, m_lsb); - } bool lvalue() const { return m_lvalue; } bool ftask() const { return m_ftask; } bool operator<(const UnpackRef& other) const { @@ -351,15 +347,15 @@ public: void remove(AstNode* nodep) { struct Visitor : public AstNVisitor { RefsInModule& m_parent; - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } - virtual void visit(AstVar* nodep) VL_OVERRIDE { m_parent.m_vars.erase(nodep); } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { m_parent.m_refs.erase(nodep); } - virtual void visit(AstSel* nodep) VL_OVERRIDE { + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + virtual void visit(AstVar* nodep) override { m_parent.m_vars.erase(nodep); } + virtual void visit(AstVarRef* nodep) override { m_parent.m_refs.erase(nodep); } + virtual void visit(AstSel* nodep) override { m_parent.m_sels.erase(nodep); iterateChildren(nodep); } explicit Visitor(RefsInModule& p) - : m_parent(p) {} + : m_parent(p) {} // Need () or GCC 4.8 false warning } v(*this); v.iterate(nodep); } @@ -393,11 +389,11 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { typedef std::set VarSet; VarSet m_foundTargetVar; UnpackRefMap m_refs; - AstNodeModule* m_modp; + AstNodeModule* m_modp = nullptr; // AstNodeStmt, AstCell, AstNodeFTaskRef, or AstAlways(Public) for sensitivity - AstNode* m_contextp; - AstNodeFTask* m_inFTask; - size_t m_numSplit; + AstNode* m_contextp = nullptr; + AstNodeFTask* m_inFTask = nullptr; + size_t m_numSplit = 0; // List for SplitPackedVarVisitor SplitVarRefsMap m_refsForPackedSplit; @@ -405,7 +401,7 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { if (AstVarRef* refp = VN_CAST(nodep, VarRef)) { if (refp->varp()->attrSplitVar()) return refp; } - return NULL; + return nullptr; } static int outerMostSizeOfUnpackedArray(AstVar* nodep) { AstUnpackArrayDType* dtypep = VN_CAST(nodep->dtypep()->skipRefp(), UnpackArrayDType); @@ -414,41 +410,39 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { } void setContextAndIterateChildren(AstNode* nodep) { - AstNode* origContextp = m_contextp; + VL_RESTORER(m_contextp); { m_contextp = nodep; iterateChildren(nodep); } - m_contextp = origContextp; } void setContextAndIterate(AstNode* contextp, AstNode* nodep) { - AstNode* origContextp = m_contextp; + VL_RESTORER(m_contextp); { m_contextp = contextp; iterate(nodep); } - m_contextp = origContextp; } void pushDeletep(AstNode* nodep) { // overriding AstNVisitor::pusDeletep() - UASSERT_OBJ(m_modp, nodep, "Must not NULL"); + UASSERT_OBJ(m_modp, nodep, "Must not nullptr"); m_refsForPackedSplit[m_modp].remove(nodep); AstNVisitor::pushDeletep(nodep); } AstVar* newVar(FileLine* fl, AstVarType type, const std::string& name, AstNodeDType* dtp) { AstVar* varp = new AstVar(fl, type, name, dtp); - UASSERT_OBJ(m_modp, varp, "Must not NULL"); + UASSERT_OBJ(m_modp, varp, "Must not nullptr"); m_refsForPackedSplit[m_modp].add(varp); return varp; } AstVarRef* newVarRef(FileLine* fl, AstVar* varp, bool lvalue) { AstVarRef* refp = new AstVarRef(fl, varp, lvalue); - UASSERT_OBJ(m_modp, refp, "Must not NULL"); + UASSERT_OBJ(m_modp, refp, "Must not nullptr"); m_refsForPackedSplit[m_modp].add(refp); return refp; } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } + virtual void visit(AstNodeModule* nodep) override { UINFO(4, "Start checking " << nodep->prettyNameQ() << "\n"); if (!VN_IS(nodep, Module)) { UINFO(4, "Skip " << nodep->prettyNameQ() << "\n"); @@ -459,33 +453,33 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { m_modp = nodep; iterateChildren(nodep); split(); - m_modp = NULL; + m_modp = nullptr; } - virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE { setContextAndIterateChildren(nodep); } - virtual void visit(AstCell* nodep) VL_OVERRIDE { setContextAndIterateChildren(nodep); } - virtual void visit(AstAlways* nodep) VL_OVERRIDE { + virtual void visit(AstNodeStmt* nodep) override { setContextAndIterateChildren(nodep); } + virtual void visit(AstCell* nodep) override { setContextAndIterateChildren(nodep); } + virtual void visit(AstAlways* nodep) override { if (nodep->sensesp()) { // When visiting sensitivity list, always is the context setContextAndIterate(nodep, nodep->sensesp()); } if (AstNode* bodysp = nodep->bodysp()) iterate(bodysp); }; - virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE { + virtual void visit(AstAlwaysPublic* nodep) override { if (nodep->sensesp()) { // When visiting sensitivity list, always is the context setContextAndIterate(nodep, nodep->sensesp()); } if (AstNode* bodysp = nodep->bodysp()) iterate(bodysp); } - virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { - AstNode* origContextp = m_contextp; + virtual void visit(AstNodeFTaskRef* nodep) override { + VL_RESTORER(m_contextp); { m_contextp = nodep; AstNodeFTask* ftaskp = nodep->taskp(); UASSERT_OBJ(ftaskp, nodep, "Unlinked"); // Iterate arguments of a function/task. for (AstNode *argp = nodep->pinsp(), *paramp = ftaskp->stmtsp(); argp; - argp = argp->nextp(), paramp = paramp ? paramp->nextp() : NULL) { - const char* reason = NULL; - AstVar* vparamp = NULL; + argp = argp->nextp(), paramp = paramp ? paramp->nextp() : nullptr) { + const char* reason = nullptr; + AstVar* vparamp = nullptr; while (paramp) { vparamp = VN_CAST(paramp, Var); if (vparamp && vparamp->isIO()) { @@ -493,7 +487,7 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { break; } paramp = paramp->nextp(); - vparamp = NULL; + vparamp = nullptr; } if (!reason && !vparamp) { reason = "the number of argument to the task/function mismatches"; @@ -512,9 +506,8 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { m_foundTargetVar.clear(); } } - m_contextp = origContextp; } - virtual void visit(AstPin* nodep) VL_OVERRIDE { + virtual void visit(AstPin* nodep) override { UINFO(5, nodep->modVarp()->prettyNameQ() << " pin \n"); AstNode* exprp = nodep->exprp(); if (!exprp) return; // Not connected pin @@ -529,15 +522,15 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { m_foundTargetVar.clear(); } } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTask* nodep) override { UASSERT_OBJ(!m_inFTask, nodep, "Nested func/task"); if (!cannotSplitTaskReason(nodep)) { m_inFTask = nodep; iterateChildren(nodep); - m_inFTask = NULL; + m_inFTask = nullptr; } } - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { if (!nodep->attrSplitVar()) return; // Nothing to do if (!cannotSplitReason(nodep)) { m_refs.registerVar(nodep); @@ -545,18 +538,18 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { } m_refsForPackedSplit[m_modp].add(nodep); } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { if (!nodep->varp()->attrSplitVar()) return; // Nothing to do if (m_refs.tryAdd(m_contextp, nodep, m_inFTask)) { m_foundTargetVar.insert(nodep->varp()); } m_refsForPackedSplit[m_modp].add(nodep); } - virtual void visit(AstSel* nodep) VL_OVERRIDE { + virtual void visit(AstSel* nodep) override { if (VN_IS(nodep->fromp(), VarRef)) m_refsForPackedSplit[m_modp].add(nodep); iterateChildren(nodep); } - virtual void visit(AstArraySel* nodep) VL_OVERRIDE { + virtual void visit(AstArraySel* nodep) override { if (AstVarRef* refp = isTargetVref(nodep->fromp())) { AstConst* indexp = VN_CAST(nodep->bitp(), Const); if (indexp) { // OK @@ -580,20 +573,20 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { iterateChildren(nodep); } } - virtual void visit(AstSliceSel* nodep) VL_OVERRIDE { + virtual void visit(AstSliceSel* nodep) override { if (AstVarRef* refp = isTargetVref(nodep->fromp())) { AstUnpackArrayDType* dtypep = VN_CAST(refp->varp()->dtypep()->skipRefp(), UnpackArrayDType); - if (dtypep->lsb() <= nodep->declRange().lo() - && nodep->declRange().hi() <= dtypep->msb()) { // Range is ok - UINFO(4, "add " << nodep << " for " << refp->varp()->prettyName() << "\n"); - m_refs.tryAdd(m_contextp, refp, nodep, nodep->declRange().hi(), - nodep->declRange().lo(), m_inFTask); - } else { - nodep->v3warn(SPLITVAR, refp->prettyNameQ() - << notSplitMsg << "index if out of range.\n"); - m_refs.remove(refp->varp()); - } + // declRange() of AstSliceSel is shifted by dtypep->declRange().lo() in V3WidthSel.cpp + // restore the original decl range here. + const VNumRange selRange{nodep->declRange().hi() + dtypep->declRange().lo(), + nodep->declRange().lo() + dtypep->declRange().lo(), + nodep->declRange().littleEndian()}; + UASSERT_OBJ(dtypep->lsb() <= selRange.lo() && selRange.hi() <= dtypep->msb(), nodep, + "Range check for AstSliceSel must have been finished in V3Width.cpp"); + UINFO(4, "add " << nodep << " for " << refp->varp()->prettyName() << "\n"); + m_refs.tryAdd(m_contextp, refp, nodep, nodep->declRange().hi(), + nodep->declRange().lo(), m_inFTask); } else { iterateChildren(nodep); } @@ -654,7 +647,7 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { } void connectPort(AstVar* varp, std::vector& vars, AstNode* insertp) { UASSERT_OBJ(varp->isIO(), varp, "must be port"); - insertp = insertp ? toInsertPoint(insertp) : NULL; + insertp = insertp ? toInsertPoint(insertp) : nullptr; const bool lvalue = varp->direction().isWritable(); for (size_t i = 0; i < vars.size(); ++i) { AstNode* nodes[] @@ -702,11 +695,11 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { insertp = newp; newp->attrSplitVar(needNext || !cannotSplitPackedVarReason(newp)); vars.push_back(newp); - setContextAndIterate(NULL, newp); + setContextAndIterate(nullptr, newp); } for (UnpackRefMap::SetIt sit = it->second.begin(), sit_end = it->second.end(); sit != sit_end; ++sit) { - AstNode* newp = NULL; + AstNode* newp = nullptr; if (sit->isSingleRef()) { newp = newVarRef(sit->nodep()->fileline(), vars.at(sit->index()), sit->lvalue()); @@ -741,7 +734,7 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { if (varp->isIO()) { // AssignW will be created, so just once if (!varp->isFuncLocal() && !varp->isFuncReturn()) { - connectPort(varp, vars, NULL); + connectPort(varp, vars, nullptr); } varp->attrSplitVar(!cannotSplitPackedVarReason(varp)); m_refsForPackedSplit[m_modp].add(varp); @@ -766,11 +759,7 @@ class SplitUnpackedVarVisitor : public AstNVisitor, public SplitVarImpl { public: explicit SplitUnpackedVarVisitor(AstNetlist* nodep) - : m_refs() - , m_modp(NULL) - , m_contextp(NULL) - , m_inFTask(NULL) - , m_numSplit(0) { + : m_refs{} { iterate(nodep); } ~SplitUnpackedVarVisitor() { @@ -788,7 +777,7 @@ public: UINFO(7, nodep->prettyNameQ() << " pub:" << nodep->isSigPublic() << " pri:" << nodep->isPrimaryIO() << " io:" << nodep->isInoutish() << " typ:" << nodep->varType() << "\n"); - const char* reason = NULL; + const char* reason = nullptr; // Public variable cannot be split. // at least one unpacked dimension must exist if (dim.second < 1 || !VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType)) @@ -811,15 +800,15 @@ class SplitNewVar { int m_bitwidth; AstVar* m_varp; // The LSB of this variable is always 0, not m_lsb public: - SplitNewVar(int lsb, int bitwidth, AstVar* varp = NULL) - : m_lsb(lsb) - , m_bitwidth(bitwidth) - , m_varp(varp) {} + SplitNewVar(int lsb, int bitwidth, AstVar* varp = nullptr) + : m_lsb{lsb} + , m_bitwidth{bitwidth} + , m_varp{varp} {} int lsb() const { return m_lsb; } int msb() const { return m_lsb + m_bitwidth - 1; } int bitwidth() const { return m_bitwidth; } void varp(AstVar* vp) { - UASSERT_OBJ(!m_varp, m_varp, "must be NULL"); + UASSERT_OBJ(!m_varp, m_varp, "must be nullptr"); m_varp = vp; } AstVar* varp() const { return m_varp; } @@ -839,13 +828,13 @@ class PackedVarRefEntry { public: PackedVarRefEntry(AstSel* selp, int lsb, int bitwidth) - : m_nodep(selp) - , m_lsb(lsb) - , m_bitwidth(bitwidth) {} + : m_nodep{selp} + , m_lsb{lsb} + , m_bitwidth{bitwidth} {} PackedVarRefEntry(AstVarRef* refp, int lsb, int bitwidth) - : m_nodep(refp) - , m_lsb(lsb) - , m_bitwidth(bitwidth) {} + : m_nodep{refp} + , m_lsb{lsb} + , m_bitwidth{bitwidth} {} AstNode* nodep() const { return m_nodep; } int lsb() const { return m_lsb; } int msb() const { return m_lsb + m_bitwidth - 1; } @@ -858,7 +847,7 @@ public: // return the sensitivity item AstSenItem* backSenItemp() const { if (AstVarRef* refp = VN_CAST(m_nodep, VarRef)) { return VN_CAST(refp->backp(), SenItem); } - return NULL; + return nullptr; } }; @@ -872,7 +861,7 @@ class PackedVarRef { }; std::vector m_lhs, m_rhs; AstBasicDType* m_basicp; // Cache the ptr since varp->dtypep()->basicp() is expensive - bool m_dedupDone; + bool m_dedupDone = false; static void dedupRefs(std::vector& refs) { // Use raw pointer to dedup typedef std::map NodeIndices; @@ -901,8 +890,7 @@ public: return m_rhs; } explicit PackedVarRef(AstVar* varp) - : m_basicp(varp->dtypep()->basicp()) - , m_dedupDone(false) {} + : m_basicp{varp->dtypep()->basicp()} {} void append(const PackedVarRefEntry& e, bool lvalue) { UASSERT(!m_dedupDone, "cannot add after dedup()"); if (lvalue) @@ -922,7 +910,7 @@ public: std::vector splitPlan(bool skipUnused) const { UASSERT(m_dedupDone, "dedup() must be called before"); std::vector plan; - std::vector > points; // + std::vector> points; // points.reserve(m_lhs.size() * 2 + 2); // 2 points will be added per one PackedVarRefEntry for (const_iterator it = m_lhs.begin(), itend = m_lhs.end(); it != itend; ++it) { points.push_back(std::make_pair(it->lsb(), false)); // Start of a region @@ -970,10 +958,10 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { int m_numSplit; // Total number of split variables // key:variable to be split. value:location where the variable is referenced. PackedVarRefMap m_refs; - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTask* nodep) override { if (!cannotSplitTaskReason(nodep)) iterateChildren(nodep); } - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { if (!nodep->attrSplitVar()) return; // Nothing to do if (const char* reason = cannotSplitReason(nodep, true)) { nodep->v3warn(SPLITVAR, nodep->prettyNameQ() << notSplitMsg << reason); @@ -983,10 +971,10 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { if (inserted) { UINFO(3, nodep->prettyNameQ() << " is added to candidate list.\n"); } } } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { AstVar* varp = nodep->varp(); visit(varp); - PackedVarRefMap::iterator refit = m_refs.find(varp); + const auto refit = m_refs.find(varp); if (refit == m_refs.end()) return; // variable without split_var metacomment UASSERT_OBJ(varp->attrSplitVar(), varp, "split_var attribute must be attached"); UASSERT_OBJ(!nodep->packagep(), nodep, @@ -997,7 +985,7 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { UINFO(5, varp->prettyName() << " Entire bit of [" << basicp->lsb() << ":+" << varp->width() << "] \n"); } - virtual void visit(AstSel* nodep) VL_OVERRIDE { + virtual void visit(AstSel* nodep) override { AstVarRef* vrefp = VN_CAST(nodep->fromp(), VarRef); if (!vrefp) { iterateChildren(nodep); @@ -1005,7 +993,7 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { } AstVar* varp = vrefp->varp(); - PackedVarRefMap::iterator refit = m_refs.find(varp); + const auto refit = m_refs.find(varp); if (refit == m_refs.end()) { iterateChildren(nodep); return; // Variable without split_var metacomment @@ -1036,7 +1024,7 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { iterateChildren(nodep); } } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } // Extract necessary bit range from a newly created variable to meet ref static AstNode* extractBits(const PackedVarRefEntry& ref, const SplitNewVar& var, @@ -1119,13 +1107,12 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { } static void updateReferences(AstVar* varp, PackedVarRef& ref, const std::vector& vars) { - typedef std::vector NewVars; // Sorted by its lsb for (int lvalue = 0; lvalue <= 1; ++lvalue) { // Refer the new split variables std::vector& refs = lvalue ? ref.lhs() : ref.rhs(); for (PackedVarRef::iterator refit = refs.begin(), refitend = refs.end(); refit != refitend; ++refit) { - NewVars::const_iterator varit = std::upper_bound( - vars.begin(), vars.end(), refit->lsb(), SplitNewVar::Match()); + auto varit = std::upper_bound(vars.begin(), vars.end(), refit->lsb(), + SplitNewVar::Match()); UASSERT_OBJ(varit != vars.end(), refit->nodep(), "Not found"); UASSERT(!(varit->msb() < refit->lsb() || refit->msb() < varit->lsb()), "wrong search result"); @@ -1187,7 +1174,7 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { if (varp->isIO()) { // port cannot be deleted // If varp is a port of a module, single AssignW is sufficient if (!(varp->isFuncLocal() || varp->isFuncReturn())) - connectPortAndVar(vars, varp, NULL); + connectPortAndVar(vars, varp, nullptr); } else if (varp->isTrace()) { // Let's reuse the original variable for tracing AstNode* rhsp @@ -1210,9 +1197,9 @@ class SplitPackedVarVisitor : public AstNVisitor, public SplitVarImpl { public: // When reusing the information from SplitUnpackedVarVisitor SplitPackedVarVisitor(AstNetlist* nodep, SplitVarRefsMap& refs) - : m_netp(nodep) - , m_modp(NULL) - , m_numSplit(0) { + : m_netp{nodep} + , m_modp{nullptr} + , m_numSplit{0} { // If you want ignore refs and walk the tne entire AST, // just call iterateChildren(m_modp) and split() for each module for (SplitVarRefsMap::iterator it = refs.begin(), it_end = refs.end(); it != it_end; @@ -1220,7 +1207,7 @@ public: m_modp = it->first; it->second.visit(this); split(); - m_modp = NULL; + m_modp = nullptr; } } ~SplitPackedVarVisitor() { @@ -1232,7 +1219,7 @@ public: // Even if this function returns true, the variable may not be split // when the access to the variable cannot be determined statically. static const char* cannotSplitReason(const AstVar* nodep, bool checkUnpacked) { - const char* reason = NULL; + const char* reason = nullptr; if (AstBasicDType* const basicp = nodep->dtypep()->basicp()) { const std::pair dim = nodep->dtypep()->dimensions(false); // Unpacked array will be split in SplitUnpackedVarVisitor() beforehand diff --git a/src/V3Stats.cpp b/src/V3Stats.cpp index c5d8e1d8c..e2a954267 100644 --- a/src/V3Stats.cpp +++ b/src/V3Stats.cpp @@ -75,7 +75,7 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { + virtual void visit(AstNodeModule* nodep) override { allNodes(nodep); if (!m_fast) { // Count all CFuncs below this module @@ -84,7 +84,7 @@ private: // Else we recursively trace fast CFuncs from the top _eval // func, see visit(AstNetlist*) } - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { allNodes(nodep); iterateChildrenConst(nodep); if (m_counting && nodep->dtypep()) { @@ -110,7 +110,7 @@ private: } } } - virtual void visit(AstVarScope* nodep) VL_OVERRIDE { + virtual void visit(AstVarScope* nodep) override { allNodes(nodep); iterateChildrenConst(nodep); if (m_counting) { @@ -119,7 +119,7 @@ private: } } } - virtual void visit(AstNodeIf* nodep) VL_OVERRIDE { + virtual void visit(AstNodeIf* nodep) override { UINFO(4, " IF i=" << m_instrs << " " << nodep << endl); allNodes(nodep); // Condition is part of cost allocated to PREVIOUS block @@ -135,28 +135,24 @@ private: double ifInstrs = 0.0; double elseInstrs = 0.0; if (nodep->branchPred() != VBranchPred::BP_UNLIKELY) { // Check if - double prevInstr = m_instrs; - bool prevCounting = m_counting; + VL_RESTORER(m_instrs); + VL_RESTORER(m_counting); { m_counting = false; m_instrs = 0.0; iterateAndNextConstNull(nodep->ifsp()); ifInstrs = m_instrs; } - m_instrs = prevInstr; - m_counting = prevCounting; } if (nodep->branchPred() != VBranchPred::BP_LIKELY) { // Check else - double prevInstr = m_instrs; - bool prevCounting = m_counting; + VL_RESTORER(m_instrs); + VL_RESTORER(m_counting); { m_counting = false; m_instrs = 0.0; iterateAndNextConstNull(nodep->elsesp()); elseInstrs = m_instrs; } - m_instrs = prevInstr; - m_counting = prevCounting; } // Now collect the stats if (m_counting) { @@ -169,9 +165,9 @@ private: } } // While's we assume evaluate once. - // virtual void visit(AstWhile* nodep) VL_OVERRIDE { + // virtual void visit(AstWhile* nodep) override { - virtual void visit(AstNodeCCall* nodep) VL_OVERRIDE { + virtual void visit(AstNodeCCall* nodep) override { allNodes(nodep); iterateChildrenConst(nodep); if (m_fast && !nodep->funcp()->entryPoint()) { @@ -180,7 +176,7 @@ private: iterate(nodep->funcp()); } } - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstCFunc* nodep) override { if (m_fast) { if (!m_tracingCall && !nodep->entryPoint()) return; m_tracingCall = false; @@ -188,13 +184,13 @@ private: m_cfuncp = nodep; allNodes(nodep); iterateChildrenConst(nodep); - m_cfuncp = NULL; + m_cfuncp = nullptr; } - virtual void visit(AstNode* nodep) VL_OVERRIDE { + virtual void visit(AstNode* nodep) override { allNodes(nodep); iterateChildrenConst(nodep); } - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { if (m_fast && nodep->evalp()) { m_instrs = 0; m_counting = true; @@ -208,10 +204,10 @@ private: public: // CONSTRUCTORS StatsVisitor(AstNetlist* nodep, const string& stage, bool fast) - : m_stage(stage) - , m_fast(fast) { + : m_stage{stage} + , m_fast{fast} { UINFO(9, "Starting stats, fast=" << fast << endl); - m_cfuncp = NULL; + m_cfuncp = nullptr; m_counting = !m_fast; m_instrs = 0; m_tracingCall = false; @@ -220,7 +216,7 @@ public: // Process iterate(nodep); } - virtual ~StatsVisitor() { + virtual ~StatsVisitor() override { // Done. Publish statistics V3Stats::addStat(m_stage, "Instruction count, TOTAL", m_statInstr); V3Stats::addStat(m_stage, "Instruction count, fast critical", m_statInstrFast); diff --git a/src/V3Stats.h b/src/V3Stats.h index e43ee539a..ad5985110 100644 --- a/src/V3Stats.h +++ b/src/V3Stats.h @@ -32,12 +32,12 @@ class VDouble0 { public: // METHODS VDouble0() - : m_d(0) {} + : m_d{0.0} {} ~VDouble0() {} // Implicit conversion operators: explicit VDouble0(const vluint64_t v) - : m_d(v) {} + : m_d{static_cast(v)} {} operator double() const { return m_d; } // Explicit operators: @@ -90,12 +90,12 @@ public: // CONSTRUCTORS V3Statistic(const string& stage, const string& name, double count, bool sumit = false, bool perf = false) - : m_name(name) - , m_count(count) - , m_stage(stage) - , m_sumit(sumit) - , m_perf(perf) - , m_printit(true) {} + : m_name{name} + , m_count{count} + , m_stage{stage} + , m_sumit{sumit} + , m_perf{perf} + , m_printit{true} {} virtual ~V3Statistic() {} }; diff --git a/src/V3StatsReport.cpp b/src/V3StatsReport.cpp index 107d1d08d..ae45f6f00 100644 --- a/src/V3StatsReport.cpp +++ b/src/V3StatsReport.cpp @@ -25,7 +25,7 @@ #include #include -#include VL_INCLUDE_UNORDERED_MAP +#include //###################################################################### // Stats dumping @@ -59,7 +59,7 @@ class StatsReport { } // Process duplicates - V3Statistic* lastp = NULL; + V3Statistic* lastp = nullptr; for (ByName::iterator it = byName.begin(); it != byName.end(); ++it) { V3Statistic* repp = it->second; if (lastp && lastp->sumit() && lastp->printit() && lastp->name() == repp->name() @@ -117,7 +117,7 @@ class StatsReport { size_t maxWidth = 0; typedef std::vector Stages; Stages stages; - vl_unordered_map stageInt; + std::unordered_map stageInt; typedef std::multimap ByName; ByName byName; // * is always first @@ -135,12 +135,10 @@ class StatsReport { // Header os << " Stat " << std::left << std::setw(maxWidth - 5 - 2) << ""; - for (Stages::const_iterator it = stages.begin(); it != stages.end(); ++it) { - os << " " << std::left << std::setw(9) << *it; - } + for (const string& i : stages) os << " " << std::left << std::setw(9) << i; os << endl; os << " -------- " << std::left << std::setw(maxWidth - 5 - 2) << ""; - for (Stages::const_iterator it = stages.begin(); it != stages.end(); ++it) { + for (auto it = stages.begin(); it != stages.end(); ++it) { os << " " << std::left << std::setw(9) << "-------"; } // os<fail()) v3fatal("Can't write " << filename); diff --git a/src/V3String.cpp b/src/V3String.cpp index d93b388dc..12db74f7c 100644 --- a/src/V3String.cpp +++ b/src/V3String.cpp @@ -74,30 +74,47 @@ string VString::dot(const string& a, const string& dot, const string& b) { string VString::downcase(const string& str) { string out = str; - for (string::iterator pos = out.begin(); pos != out.end(); ++pos) *pos = tolower(*pos); + for (auto& cr : out) cr = tolower(cr); return out; } string VString::upcase(const string& str) { string out = str; - for (string::iterator pos = out.begin(); pos != out.end(); ++pos) *pos = toupper(*pos); + for (auto& cr : out) cr = toupper(cr); return out; } -string VString::quotePercent(const string& str) { +string VString::quoteAny(const string& str, char tgt, char esc) { string out; - for (string::const_iterator pos = str.begin(); pos != str.end(); ++pos) { - if (*pos == '%') out += '%'; - out += *pos; + for (const char c : str) { + if (c == tgt) out += esc; + out += c; } return out; } +string VString::quoteStringLiteralForShell(const string& str) { + string result; + const char dquote = '"'; + const char escape = '\\'; + result.push_back(dquote); // Start quoted string + result.push_back(escape); + result.push_back(dquote); // " + for (const char c : str) { + if (c == dquote || c == escape) result.push_back(escape); + result.push_back(c); + } + result.push_back(escape); + result.push_back(dquote); // " + result.push_back(dquote); // Terminate quoted string + return result; +} + string VString::spaceUnprintable(const string& str) { string out; - for (string::const_iterator pos = str.begin(); pos != str.end(); ++pos) { - if (isprint(*pos)) { - out += *pos; + for (const char c : str) { + if (isprint(c)) { + out += c; } else { out += ' '; } @@ -108,15 +125,15 @@ string VString::spaceUnprintable(const string& str) { string VString::removeWhitespace(const string& str) { string out; out.reserve(str.size()); - for (string::const_iterator pos = str.begin(); pos != str.end(); ++pos) { - if (!isspace(*pos)) out += *pos; + for (const char c : str) { + if (!isspace(c)) out += c; } return out; } bool VString::isWhitespace(const string& str) { - for (string::const_iterator pos = str.begin(); pos != str.end(); ++pos) { - if (!isspace(*pos)) return false; + for (const char c : str) { + if (!isspace(c)) return false; } return true; } @@ -435,8 +452,7 @@ string VSpellCheck::bestCandidateInfo(const string& goal, EditDistance& distance string bestCandidate; size_t gLen = goal.length(); distancer = LENGTH_LIMIT * 10; - for (Candidates::const_iterator it = m_candidates.begin(); it != m_candidates.end(); ++it) { - const string candidate = *it; + for (const string& candidate : m_candidates) { size_t cLen = candidate.length(); // Min distance must be inserting/deleting to make lengths match diff --git a/src/V3String.h b/src/V3String.h index a3472c3f7..b02ee587f 100644 --- a/src/V3String.h +++ b/src/V3String.h @@ -80,8 +80,15 @@ public: static string downcase(const string& str); // Convert string to upper case (toupper) static string upcase(const string& str); + // Insert esc just before tgt + static string quoteAny(const string& str, char tgt, char esc); + // Replace any \'s with \\ (two consecutive backslashes) + static string quoteBackslash(const string& str) { return quoteAny(str, '\\', '\\'); } // Replace any %'s with %% - static string quotePercent(const string& str); + static string quotePercent(const string& str) { return quoteAny(str, '%', '%'); } + // Surround a raw string by double quote and escape if necessary + // e.g. input abc's becomes "\"abc\'s\"" + static string quoteStringLiteralForShell(const string& str); // Replace any unprintable with space // This includes removing tabs, so column tracking is correct static string spaceUnprintable(const string& str); @@ -105,13 +112,22 @@ class VHashSha256 { // MEMBERS uint32_t m_inthash[8]; // Intermediate hash, in host order string m_remainder; // Unhashed data - bool m_final; // Finalized - size_t m_totLength; // Total all-chunk length as needed by output digest + bool m_final = false; // Finalized + size_t m_totLength = 0; // Total all-chunk length as needed by output digest public: // CONSTRUCTORS - VHashSha256() { init(); } - explicit VHashSha256(const string& data) { - init(); + VHashSha256() { + m_inthash[0] = 0x6a09e667; + m_inthash[1] = 0xbb67ae85; + m_inthash[2] = 0x3c6ef372; + m_inthash[3] = 0xa54ff53a; + m_inthash[4] = 0x510e527f; + m_inthash[5] = 0x9b05688c; + m_inthash[6] = 0x1f83d9ab; + m_inthash[7] = 0x5be0cd19; + } + explicit VHashSha256(const string& data) + : VHashSha256{} { insert(data); } ~VHashSha256() {} @@ -131,18 +147,6 @@ public: void insert(uint64_t value) { insert(cvtToStr(value)); } private: - void init() { - m_inthash[0] = 0x6a09e667; - m_inthash[1] = 0xbb67ae85; - m_inthash[2] = 0x3c6ef372; - m_inthash[3] = 0xa54ff53a; - m_inthash[4] = 0x510e527f; - m_inthash[5] = 0x9b05688c; - m_inthash[6] = 0x1f83d9ab; - m_inthash[7] = 0x5be0cd19; - m_final = false; - m_totLength = 0; - } static void selfTestOne(const string& data, const string& data2, const string& exp, const string& exp64); void finalize(); // Process remaining data @@ -161,7 +165,7 @@ class VName { public: // CONSTRUCTORS explicit VName(const string& name) - : m_name(name) {} + : m_name{name} {} ~VName() {} // METHODS void name(const string& name) { @@ -181,8 +185,8 @@ public: class VSpellCheck { // CONSTANTS - enum { NUM_CANDIDATE_LIMIT = 10000 }; // Avoid searching huge netlists - enum { LENGTH_LIMIT = 100 }; // Maximum string length to search + static constexpr unsigned NUM_CANDIDATE_LIMIT = 10000; // Avoid searching huge netlists + static constexpr unsigned LENGTH_LIMIT = 100; // Maximum string length to search // TYPES typedef unsigned int EditDistance; typedef std::vector Candidates; diff --git a/src/V3Subst.cpp b/src/V3Subst.cpp index d86f50864..ac18e4d08 100644 --- a/src/V3Subst.cpp +++ b/src/V3Subst.cpp @@ -54,7 +54,7 @@ protected: friend class SubstVarEntry; // METHODS void clear() { - m_assignp = NULL; + m_assignp = nullptr; m_step = 0; m_use = false; m_complex = false; @@ -67,18 +67,16 @@ protected: class SubstVarEntry { // MEMBERS AstVar* m_varp; // Variable this tracks - bool m_wordAssign; // True if any word assignments - bool m_wordUse; // True if any individual word usage + bool m_wordAssign = false; // True if any word assignments + bool m_wordUse = false; // True if any individual word usage SubstVarWord m_whole; // Data for whole vector used at once std::vector m_words; // Data for every word, if multi word variable - int debug() { return SubstBaseVisitor::debug(); } + static int debug() { return SubstBaseVisitor::debug(); } public: // CONSTRUCTORS - explicit SubstVarEntry(AstVar* varp) { // Construction for when a var is used - m_varp = varp; - m_wordAssign = false; - m_wordUse = false; + explicit SubstVarEntry(AstVar* varp) + : m_varp{varp} { // Construction for when a var is used m_words.resize(varp->widthWords()); m_whole.clear(); for (int i = 0; i < varp->widthWords(); i++) m_words[i].clear(); @@ -90,7 +88,7 @@ private: bool wordNumOk(int word) const { return word < m_varp->widthWords(); } AstNodeAssign* getWordAssignp(int word) const { if (!wordNumOk(word)) { - return NULL; + return nullptr; } else { return m_words[word].m_assignp; } @@ -133,7 +131,7 @@ public: UASSERT_OBJ(assp, errp, "Reading whole that was never assigned"); return (assp->rhsp()); } else { - return NULL; + return nullptr; } } // Return what to substitute given word number for @@ -143,7 +141,7 @@ public: UASSERT_OBJ(assp, errp, "Reading a word that was never assigned, or bad word #"); return (assp->rhsp()); } else { - return NULL; + return nullptr; } } int getWholeStep() const { return m_whole.m_step; } @@ -161,12 +159,12 @@ public: void deleteUnusedAssign() { // If there are unused assignments in this var, kill them if (!m_whole.m_use && !m_wordUse && m_whole.m_assignp) { - VL_DO_CLEAR(deleteAssign(m_whole.m_assignp), m_whole.m_assignp = NULL); + VL_DO_CLEAR(deleteAssign(m_whole.m_assignp), m_whole.m_assignp = nullptr); } for (unsigned i = 0; i < m_words.size(); i++) { if (!m_whole.m_use && !m_words[i].m_use && m_words[i].m_assignp && !m_words[i].m_complex) { - VL_DO_CLEAR(deleteAssign(m_words[i].m_assignp), m_words[i].m_assignp = NULL); + VL_DO_CLEAR(deleteAssign(m_words[i].m_assignp), m_words[i].m_assignp = nullptr); } } } @@ -183,14 +181,14 @@ private: // // STATE int m_origStep; // Step number where subst was recorded - bool m_ok; // No misassignments found + bool m_ok = true; // No misassignments found // METHODS SubstVarEntry* findEntryp(AstVarRef* nodep) { - return reinterpret_cast(nodep->varp()->user1p()); // Might be NULL + return reinterpret_cast(nodep->varp()->user1p()); // Might be nullptr } // VISITORS - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { SubstVarEntry* entryp = findEntryp(nodep); if (entryp) { // Don't sweat it. We assign a new temp variable for every new assignment, @@ -205,18 +203,17 @@ private: } } } - virtual void visit(AstConst*) VL_OVERRIDE {} // Accelerate - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstConst*) override {} // Accelerate + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - SubstUseVisitor(AstNode* nodep, int origStep) { + SubstUseVisitor(AstNode* nodep, int origStep) + : m_origStep{origStep} { UINFO(9, " SubstUseVisitor " << origStep << " " << nodep << endl); - m_ok = true; - m_origStep = origStep; iterate(nodep); } - virtual ~SubstUseVisitor() {} + virtual ~SubstUseVisitor() override {} // METHODS bool ok() const { return m_ok; } }; @@ -235,8 +232,8 @@ private: // STATE std::vector m_entryps; // Nodes to delete when we are finished - int m_ops; // Number of operators on assign rhs - int m_assignStep; // Assignment number to determine var lifetime + int m_ops = 0; // Number of operators on assign rhs + int m_assignStep = 0; // Assignment number to determine var lifetime VDouble0 m_statSubsts; // Statistic tracking enum { @@ -259,7 +256,7 @@ private: inline bool isSubstVar(AstVar* nodep) { return nodep->isStatementTemp() && !nodep->noSubst(); } // VISITORS - virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { + virtual void visit(AstNodeAssign* nodep) override { m_ops = 0; m_assignStep++; iterateAndNextNull(nodep->rhsp()); @@ -305,7 +302,7 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); ++m_statSubsts; } - virtual void visit(AstWordSel* nodep) VL_OVERRIDE { + virtual void visit(AstWordSel* nodep) override { iterate(nodep->rhsp()); AstVarRef* varrefp = VN_CAST(nodep->lhsp(), VarRef); AstConst* constp = VN_CAST(nodep->rhsp(), Const); @@ -330,7 +327,7 @@ private: iterate(nodep->lhsp()); } } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { // Any variable if (nodep->lvalue()) { m_assignStep++; @@ -358,9 +355,9 @@ private: } } } - virtual void visit(AstVar*) VL_OVERRIDE {} - virtual void visit(AstConst*) VL_OVERRIDE {} - virtual void visit(AstNode* nodep) VL_OVERRIDE { + virtual void visit(AstVar*) override {} + virtual void visit(AstConst*) override {} + virtual void visit(AstNode* nodep) override { m_ops++; if (!nodep->isSubstOptimizable()) m_ops = SUBST_MAX_OPS_NA; iterateChildren(nodep); @@ -371,16 +368,13 @@ public: explicit SubstVisitor(AstNode* nodep) { AstNode::user1ClearTree(); // user1p() used on entire tree AstNode::user2ClearTree(); // user2p() used on entire tree - m_ops = 0; - m_assignStep = 0; iterate(nodep); } - virtual ~SubstVisitor() { + virtual ~SubstVisitor() override { V3Stats::addStat("Optimizations, Substituted temps", m_statSubsts); - for (std::vector::iterator it = m_entryps.begin(); it != m_entryps.end(); - ++it) { - (*it)->deleteUnusedAssign(); - delete (*it); + for (SubstVarEntry* ip : m_entryps) { + ip->deleteUnusedAssign(); + delete ip; } } }; diff --git a/src/V3SymTable.h b/src/V3SymTable.h index a6d66421e..d72925dbe 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -133,7 +133,7 @@ public: } } void reinsert(const string& name, VSymEnt* entp) { - IdNameMap::iterator it = m_idNameMap.find(name); + const auto it = m_idNameMap.find(name); if (name != "" && it != m_idNameMap.end()) { UINFO(9, " SymReinsert se" << cvtToHex(this) << " '" << name << "' se" << cvtToHex(entp) << " " << entp->nodep() << endl); @@ -145,7 +145,7 @@ public: VSymEnt* findIdFlat(const string& name) const { // Find identifier without looking upward through symbol hierarchy // First, scan this begin/end block or module for the name - IdNameMap::const_iterator it = m_idNameMap.find(name); + const auto it = m_idNameMap.find(name); UINFO(9, " SymFind se" << cvtToHex(this) << " '" << name << "' -> " << (it == m_idNameMap.end() @@ -153,7 +153,7 @@ public: : "se" + cvtToHex(it->second) + " n=" + cvtToHex(it->second->nodep())) << endl); if (it != m_idNameMap.end()) return (it->second); - return NULL; + return nullptr; } VSymEnt* findIdFallback(const string& name) const { // Find identifier looking upward through symbol hierarchy @@ -161,7 +161,7 @@ public: if (VSymEnt* entp = findIdFlat(name)) return entp; // Then scan the upper begin/end block or module for the name if (m_fallbackp) return m_fallbackp->findIdFallback(name); - return NULL; + return nullptr; } void candidateIdFlat(VSpellCheck* spellerp, const VNodeMatcher* matcherp) const { // Suggest alternative symbol candidates without looking upward through symbol hierarchy @@ -211,7 +211,7 @@ public: void importFromPackage(VSymGraph* graphp, const VSymEnt* srcp, const string& id_or_star) { // Import tokens from source symbol table into this symbol table if (id_or_star != "*") { - IdNameMap::const_iterator it = srcp->m_idNameMap.find(id_or_star); + const auto it = srcp->m_idNameMap.find(id_or_star); if (it != srcp->m_idNameMap.end()) { importOneSymbol(graphp, it->first, it->second, true); } @@ -225,7 +225,7 @@ public: void exportFromPackage(VSymGraph* graphp, const VSymEnt* srcp, const string& id_or_star) { // Export tokens from source symbol table into this symbol table if (id_or_star != "*") { - IdNameMap::const_iterator it = srcp->m_idNameMap.find(id_or_star); + const auto it = vlstd::as_const(srcp->m_idNameMap).find(id_or_star); if (it != srcp->m_idNameMap.end()) exportOneSymbol(graphp, it->first, it->second); } else { for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin(); @@ -292,7 +292,7 @@ class VSymGraph { public: explicit VSymGraph(AstNetlist* nodep) { m_symRootp = new VSymEnt(this, nodep); } ~VSymGraph() { - for (SymStack::iterator it = m_symsp.begin(); it != m_symsp.end(); ++it) delete (*it); + for (const VSymEnt* entp : m_symsp) delete entp; } // METHODS @@ -317,7 +317,7 @@ public: if (v3Global.opt.dumpTree()) { string filename = v3Global.debugFilename(nameComment) + ".txt"; UINFO(2, "Dumping " << filename << endl); - const vl_unique_ptr logp(V3File::new_ofstream(filename)); + const std::unique_ptr logp(V3File::new_ofstream(filename)); if (logp->fail()) v3fatal("Can't write " << filename); dump(*logp, ""); } @@ -335,9 +335,9 @@ inline VSymEnt::VSymEnt(VSymGraph* graphp, AstNode* nodep) // No argument to set fallbackp, as generally it's wrong to set it in the new call, // Instead it needs to be set on a "findOrNew()" return, as it may have been new'ed // by an earlier search insertion. - m_fallbackp = NULL; - m_parentp = NULL; - m_packagep = NULL; + m_fallbackp = nullptr; + m_parentp = nullptr; + m_packagep = nullptr; m_exported = true; m_imported = false; graphp->pushNewEnt(this); diff --git a/src/V3TSP.cpp b/src/V3TSP.cpp index 617653c0e..6625acf91 100644 --- a/src/V3TSP.cpp +++ b/src/V3TSP.cpp @@ -35,8 +35,8 @@ #include #include #include -#include VL_INCLUDE_UNORDERED_SET -#include VL_INCLUDE_UNORDERED_MAP +#include +#include //###################################################################### // Support classes @@ -57,9 +57,9 @@ private: public: TspVertexTmpl(V3Graph* graphp, const T_Key& k) - : V3GraphVertex(graphp) - , m_key(k) {} - virtual ~TspVertexTmpl() {} + : V3GraphVertex{graphp} + , m_key{k} {} + virtual ~TspVertexTmpl() override {} const T_Key& key() const { return m_key; } private: @@ -74,17 +74,17 @@ public: typedef TspVertexTmpl Vertex; // MEMBERS - typedef vl_unordered_map VMap; + typedef std::unordered_map VMap; VMap m_vertices; // T_Key to Vertex lookup map // CONSTRUCTORS TspGraphTmpl() - : V3Graph() {} - virtual ~TspGraphTmpl() {} + : V3Graph{} {} + virtual ~TspGraphTmpl() override {} // METHODS void addVertex(const T_Key& key) { - typename VMap::iterator itr = m_vertices.find(key); + const auto itr = m_vertices.find(key); UASSERT(itr == m_vertices.end(), "Vertex already exists with same key"); Vertex* v = new Vertex(this, key); m_vertices[key] = v; @@ -149,7 +149,7 @@ public: UASSERT(mstp->empty(), "Output graph must start empty"); // Use Prim's algorithm to efficiently construct the MST. - vl_unordered_set visited_set; + std::unordered_set visited_set; EdgeCmp cmp; typedef std::set PendingEdgeSet; @@ -177,7 +177,7 @@ public: // discard it and repeat again. unsigned edges_made = 0; while (!pendingEdges.empty()) { - typename PendingEdgeSet::iterator firstIt = pendingEdges.begin(); + const auto firstIt = pendingEdges.cbegin(); V3GraphEdge* bestEdgep = *firstIt; pendingEdges.erase(firstIt); @@ -221,7 +221,7 @@ public: UASSERT(outp->empty(), "Output graph must start empty"); std::list odds = keysToVertexList(oddKeys); - vl_unordered_set unmatchedOdds; + std::unordered_set unmatchedOdds; typedef typename std::list::iterator VertexListIt; for (VertexListIt it = odds.begin(); it != odds.end(); ++it) { outp->addVertex((*it)->key()); @@ -274,7 +274,7 @@ public: } void combineGraph(const TspGraphTmpl& g) { - vl_unordered_set edges_done; + std::unordered_set edges_done; for (V3GraphVertex* vxp = g.verticesBeginp(); vxp; vxp = vxp->verticesNextp()) { Vertex* fromp = castVertexp(vxp); for (V3GraphEdge* edgep = fromp->outBeginp(); edgep; edgep = edgep->outNextp()) { @@ -287,7 +287,7 @@ public: } } - void findEulerTourRecurse(vl_unordered_set* markedEdgesp, Vertex* startp, + void findEulerTourRecurse(std::unordered_set* markedEdgesp, Vertex* startp, std::vector* sortedOutp) { Vertex* cur_vertexp = startp; @@ -317,8 +317,7 @@ public: // Look for nodes on the tour that still have // un-marked edges. If we find one, recurse. - for (typename std::vector::iterator it = tour.begin(); it != tour.end(); ++it) { - Vertex* vxp = *it; + for (Vertex* vxp : tour) { bool recursed; do { recursed = false; @@ -338,10 +337,7 @@ public: } UINFO(6, "Tour was: "); - for (typename std::vector::iterator it = tour.begin(); it != tour.end(); ++it) { - Vertex* vxp = *it; - UINFONL(6, " " << vxp->key()); - } + for (const Vertex* vxp : tour) UINFONL(6, " " << vxp->key()); UINFONL(6, "\n"); } @@ -360,7 +356,7 @@ public: void dumpGraphFilePrefixed(const string& nameComment) const { if (v3Global.opt.dumpTree()) { string filename = v3Global.debugFilename(nameComment) + ".txt"; - const vl_unique_ptr logp(V3File::new_ofstream(filename)); + const std::unique_ptr logp(V3File::new_ofstream(filename)); if (logp->fail()) v3fatal("Can't write " << filename); dumpGraph(*logp, nameComment); } @@ -369,7 +365,7 @@ public: void findEulerTour(std::vector* sortedOutp) { UASSERT(sortedOutp->empty(), "Output graph must start empty"); if (debug() >= 6) dumpDotFilePrefixed("findEulerTour"); - vl_unordered_set markedEdges; + std::unordered_set markedEdges; // Pick a start node Vertex* start_vertexp = castVertexp(verticesBeginp()); findEulerTourRecurse(&markedEdges, start_vertexp, sortedOutp); @@ -390,7 +386,7 @@ public: private: Vertex* findVertex(const T_Key& key) const { - typename VMap::const_iterator it = m_vertices.find(key); + const auto it = m_vertices.find(key); UASSERT(it != m_vertices.end(), "Vertex not found"); return it->second; } @@ -446,7 +442,7 @@ void V3TSP::tspSort(const V3TSP::StateVec& states, V3TSP::StateVec* resultp) { // Discard duplicate nodes that the Euler tour might contain. { - vl_unordered_set seen; + std::unordered_set seen; for (V3TSP::StateVec::iterator it = prelim_result.begin(); it != prelim_result.end(); ++it) { const TspStateBase* elemp = *it; @@ -503,11 +499,11 @@ void V3TSP::tspSort(const V3TSP::StateVec& states, V3TSP::StateVec* resultp) { class TspTestState : public V3TSP::TspStateBase { public: TspTestState(unsigned xpos, unsigned ypos) - : m_xpos(xpos) - , m_ypos(ypos) - , m_serial(++m_serialNext) {} + : m_xpos{xpos} + , m_ypos{ypos} + , m_serial{++m_serialNext} {} ~TspTestState() {} - virtual int cost(const TspStateBase* otherp) const { + virtual int cost(const TspStateBase* otherp) const override { return cost(dynamic_cast(otherp)); } static unsigned diff(unsigned a, unsigned b) { @@ -527,7 +523,7 @@ public: unsigned xpos() const { return m_xpos; } unsigned ypos() const { return m_ypos; } - bool operator<(const TspStateBase& other) const { + bool operator<(const TspStateBase& other) const override { return operator<(dynamic_cast(other)); } bool operator<(const TspTestState& other) const { return m_serial < other.m_serial; } @@ -656,9 +652,7 @@ void V3TSP::selfTestString() { expect.push_back("3"); if (VL_UNCOVERABLE(expect != result)) { - for (std::vector::const_iterator it = result.begin(); it != result.end(); ++it) { - cout << *it << " "; - } + for (const string& i : result) cout << i << " "; cout << endl; v3fatalSrc("TSP string self-test fail. Result (above) did not match expectation."); } diff --git a/src/V3Table.cpp b/src/V3Table.cpp index 43eeef696..dc350a4d5 100644 --- a/src/V3Table.cpp +++ b/src/V3Table.cpp @@ -54,11 +54,12 @@ class TableSimulateVisitor : public SimulateVisitor { public: ///< Call other-this function on all new var references - virtual void varRefCb(AstVarRef* nodep); + virtual void varRefCb(AstVarRef* nodep) override; // CONSTRUCTORS - explicit TableSimulateVisitor(TableVisitor* cbthis) { m_cbthis = cbthis; } - virtual ~TableSimulateVisitor() {} + explicit TableSimulateVisitor(TableVisitor* cbthis) + : m_cbthis{cbthis} {} + virtual ~TableSimulateVisitor() override {} }; //###################################################################### @@ -70,22 +71,22 @@ private: // Cleared on each always/assignw // STATE - double m_totalBytes; // Total bytes in tables created + double m_totalBytes = 0; // Total bytes in tables created VDouble0 m_statTablesCre; // Statistic tracking // State cleared on each module - AstNodeModule* m_modp; // Current MODULE - int m_modTables; // Number of tables created in this module + AstNodeModule* m_modp = nullptr; // Current MODULE + int m_modTables = 0; // Number of tables created in this module typedef std::deque ModTableVector; ModTableVector m_modTableVscs; // All tables created // State cleared on each scope - AstScope* m_scopep; // Current SCOPE + AstScope* m_scopep = nullptr; // Current SCOPE // State cleared on each always/assignw - bool m_assignDly; // Consists of delayed assignments instead of normal assignments - int m_inWidth; // Input table width - int m_outWidth; // Output table width + bool m_assignDly = false; // Consists of delayed assignments instead of normal assignments + int m_inWidth = 0; // Input table width + int m_outWidth = 0; // Output table width std::deque m_inVarps; // Input variable list std::deque m_outVarps; // Output variable list std::deque m_outNotSet; // True if output variable is not set at some point @@ -187,7 +188,7 @@ private: AstVar* chgVarp = new AstVar(fl, AstVarType::MODULETEMP, "__Vtablechg" + cvtToStr(m_modTables), dtypep); chgVarp->isConst(true); - chgVarp->valuep(new AstInitArray(nodep->fileline(), dtypep, NULL)); + chgVarp->valuep(new AstInitArray(nodep->fileline(), dtypep, nullptr)); m_modp->addStmtp(chgVarp); AstVarScope* chgVscp = new AstVarScope(chgVarp->fileline(), m_scopep, chgVarp); m_scopep->addVarp(chgVscp); @@ -223,16 +224,14 @@ private: // Create table for each output typedef std::map NameCounts; NameCounts namecounts; - for (std::deque::iterator it = m_outVarps.begin(); it != m_outVarps.end(); - ++it) { - AstVarScope* outvscp = *it; + for (const AstVarScope* outvscp : m_outVarps) { AstVar* outvarp = outvscp->varp(); FileLine* fl = nodep->fileline(); AstNodeArrayDType* dtypep = new AstUnpackArrayDType( fl, outvarp->dtypep(), new AstRange(fl, VL_MASK_I(m_inWidth), 0)); v3Global.rootp()->typeTablep()->addTypesp(dtypep); string name = "__Vtable" + cvtToStr(m_modTables) + "_" + outvarp->name(); - NameCounts::iterator nit = namecounts.find(name); + const auto nit = namecounts.find(name); if (nit != namecounts.end()) { // Multiple scopes can have same var name. We could append the // scope name but that is very long, so just deduplicate. @@ -243,7 +242,7 @@ private: AstVar* tablevarp = new AstVar(fl, AstVarType::MODULETEMP, name, dtypep); tablevarp->isConst(true); tablevarp->isStatic(true); - tablevarp->valuep(new AstInitArray(nodep->fileline(), dtypep, NULL)); + tablevarp->valuep(new AstInitArray(nodep->fileline(), dtypep, nullptr)); m_modp->addStmtp(tablevarp); AstVarScope* tablevscp = new AstVarScope(tablevarp->fileline(), m_scopep, tablevarp); m_scopep->addVarp(tablevscp); @@ -254,10 +253,8 @@ private: AstNode* createLookupInput(AstNode* nodep, AstVarScope* indexVscp) { // Concat inputs into a single temp variable (inside always) // First var in inVars becomes the LSB of the concat - AstNode* concatp = NULL; - for (std::deque::iterator it = m_inVarps.begin(); it != m_inVarps.end(); - ++it) { - AstVarScope* invscp = *it; + AstNode* concatp = nullptr; + for (AstVarScope* invscp : m_inVarps) { AstVarRef* refp = new AstVarRef(nodep->fileline(), invscp, false); if (concatp) { concatp = new AstConcat(nodep->fileline(), refp, concatp); @@ -287,14 +284,12 @@ private: UINFO(8, " Simulating " << std::hex << inValue << endl); // Above simulateVisitor clears user 3, so - // all outputs default to NULL to mean 'recirculating'. + // all outputs default to nullptr to mean 'recirculating'. simvis.clear(); // Set all inputs to the constant uint32_t shift = 0; - for (std::deque::iterator it = m_inVarps.begin(); it != m_inVarps.end(); - ++it) { - AstVarScope* invscp = *it; + for (AstVarScope* invscp : m_inVarps) { // LSB is first variable, so extract it that way AstConst cnst(invscp->fileline(), AstConst::WidthedValue(), invscp->width(), VL_MASK_I(invscp->width()) & (inValue >> shift)); @@ -315,9 +310,7 @@ private: // If a output changed, add it to table int outnum = 0; V3Number outputChgMask(nodep, m_outVarps.size(), 0); - for (std::deque::iterator it = m_outVarps.begin(); - it != m_outVarps.end(); ++it) { - AstVarScope* outvscp = *it; + for (AstVarScope* outvscp : m_outVarps) { V3Number* outnump = simvis.fetchOutNumberNull(outvscp); AstNode* setp; if (!outnump) { @@ -352,9 +345,7 @@ private: // See if another table we've created is identical, if so use it for both. // (A more 'modern' way would be to instead use V3Hashed::findDuplicate) AstVar* var1p = vsc1p->varp(); - for (std::deque::iterator it = m_modTableVscs.begin(); - it != m_modTableVscs.end(); ++it) { - AstVarScope* vsc2p = *it; + for (AstVarScope* vsc2p : m_modTableVscs) { AstVar* var2p = vsc2p->varp(); if (var1p->width() == var2p->width() && (var1p->dtypep()->arrayUnpackedElements() @@ -380,9 +371,7 @@ private: // elimination will remove it for us. // Set each output from array ref into our table int outnum = 0; - for (std::deque::iterator it = m_outVarps.begin(); it != m_outVarps.end(); - ++it) { - AstVarScope* outvscp = *it; + for (AstVarScope* outvscp : m_outVarps) { AstNode* alhsp = new AstVarRef(nodep->fileline(), outvscp, true); AstNode* arhsp = new AstArraySel( nodep->fileline(), new AstVarRef(nodep->fileline(), m_tableVarps[outnum], false), @@ -404,7 +393,7 @@ private: new AstVarRef(nodep->fileline(), chgVscp, false), new AstVarRef(nodep->fileline(), indexVscp, false)), new AstConst(nodep->fileline(), outputChgMask)), - outsetp, NULL); + outsetp, nullptr); } stmtsp->addNext(outsetp); @@ -413,55 +402,43 @@ private: } // VISITORS - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { iterateChildren(nodep); } - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { - AstNodeModule* origModp = m_modp; - int origModTables = m_modTables; - ModTableVector origModTableVscs = m_modTableVscs; + virtual void visit(AstNetlist* nodep) override { iterateChildren(nodep); } + virtual void visit(AstNodeModule* nodep) override { + VL_RESTORER(m_modp); + VL_RESTORER(m_modTables); + VL_RESTORER(m_modTableVscs); { m_modp = nodep; m_modTables = 0; m_modTableVscs.clear(); iterateChildren(nodep); } - m_modp = origModp; - m_modTables = origModTables; - m_modTableVscs = origModTableVscs; } - virtual void visit(AstScope* nodep) VL_OVERRIDE { + virtual void visit(AstScope* nodep) override { UINFO(4, " SCOPE " << nodep << endl); m_scopep = nodep; iterateChildren(nodep); - m_scopep = NULL; + m_scopep = nullptr; } - virtual void visit(AstAlways* nodep) VL_OVERRIDE { + virtual void visit(AstAlways* nodep) override { UINFO(4, " ALWAYS " << nodep << endl); if (treeTest(nodep)) { // Well, then, I'll be a memory hog. VL_DO_DANGLING(createTable(nodep), nodep); } } - virtual void visit(AstAssignAlias*) VL_OVERRIDE {} - virtual void visit(AstAssignW* nodep) VL_OVERRIDE { + virtual void visit(AstAssignAlias*) override {} + virtual void visit(AstAssignW* nodep) override { // It's nearly impossible to have a large enough assign to make this worthwhile // For now we won't bother. // Accelerated: no iterate } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - explicit TableVisitor(AstNetlist* nodep) { - m_modp = NULL; - m_modTables = 0; - m_scopep = NULL; - m_assignDly = 0; - m_inWidth = 0; - m_outWidth = 0; - m_totalBytes = 0; - iterate(nodep); - } - virtual ~TableVisitor() { // + explicit TableVisitor(AstNetlist* nodep) { iterate(nodep); } + virtual ~TableVisitor() override { // V3Stats::addStat("Optimizations, Tables created", m_statTablesCre); } }; diff --git a/src/V3Task.cpp b/src/V3Task.cpp index b9f8f2445..f21ba9488 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -40,15 +40,13 @@ // Graph subclasses class TaskBaseVertex : public V3GraphVertex { - AstNode* m_impurep; // Node causing impure function w/ outside references - bool m_noInline; // Marked with pragma + AstNode* m_impurep = nullptr; // Node causing impure function w/ outside references + bool m_noInline = false; // Marked with pragma public: explicit TaskBaseVertex(V3Graph* graphp) - : V3GraphVertex(graphp) - , m_impurep(NULL) - , m_noInline(false) {} - virtual ~TaskBaseVertex() {} - bool pure() const { return m_impurep == NULL; } + : V3GraphVertex{graphp} {} + virtual ~TaskBaseVertex() override {} + bool pure() const { return m_impurep == nullptr; } AstNode* impureNode() const { return m_impurep; } void impure(AstNode* nodep) { m_impurep = nodep; } bool noInline() const { return m_noInline; } @@ -58,19 +56,17 @@ public: class TaskFTaskVertex : public TaskBaseVertex { // Every task gets a vertex, and we link tasks together based on funcrefs. AstNodeFTask* m_nodep; - AstCFunc* m_cFuncp; + AstCFunc* m_cFuncp = nullptr; public: TaskFTaskVertex(V3Graph* graphp, AstNodeFTask* nodep) - : TaskBaseVertex(graphp) - , m_nodep(nodep) { - m_cFuncp = NULL; - } - virtual ~TaskFTaskVertex() {} + : TaskBaseVertex{graphp} + , m_nodep{nodep} {} + virtual ~TaskFTaskVertex() override {} AstNodeFTask* nodep() const { return m_nodep; } - virtual string name() const { return nodep()->name(); } - virtual string dotColor() const { return pure() ? "black" : "red"; } - virtual FileLine* fileline() const { return nodep()->fileline(); } + virtual string name() const override { return nodep()->name(); } + virtual string dotColor() const override { return pure() ? "black" : "red"; } + virtual FileLine* fileline() const override { return nodep()->fileline(); } AstCFunc* cFuncp() const { return m_cFuncp; } void cFuncp(AstCFunc* nodep) { m_cFuncp = nodep; } }; @@ -79,18 +75,18 @@ class TaskCodeVertex : public TaskBaseVertex { // Top vertex for all calls not under another task public: explicit TaskCodeVertex(V3Graph* graphp) - : TaskBaseVertex(graphp) {} - virtual ~TaskCodeVertex() {} - virtual string name() const { return "*CODE*"; } - virtual string dotColor() const { return "green"; } + : TaskBaseVertex{graphp} {} + virtual ~TaskCodeVertex() override {} + virtual string name() const override { return "*CODE*"; } + virtual string dotColor() const override { return "green"; } }; class TaskEdge : public V3GraphEdge { public: TaskEdge(V3Graph* graphp, TaskBaseVertex* fromp, TaskBaseVertex* top) - : V3GraphEdge(graphp, fromp, top, 1, false) {} - virtual ~TaskEdge() {} - virtual string dotLabel() const { return "w" + cvtToStr(weight()); } + : V3GraphEdge{graphp, fromp, top, 1, false} {} + virtual ~TaskEdge() override {} + virtual string dotLabel() const override { return "w" + cvtToStr(weight()); } }; //###################################################################### @@ -108,11 +104,14 @@ private: // TYPES typedef std::map, AstVarScope*> VarToScopeMap; + typedef std::map FuncToClassMap; typedef std::vector Initials; // MEMBERS VarToScopeMap m_varToScopeMap; // Map for Var -> VarScope mappings - AstAssignW* m_assignwp; // Current assignment - AstNodeFTask* m_ctorp; // Class constructor + FuncToClassMap m_funcToClassMap; // Map for ctor func -> class + AstAssignW* m_assignwp = nullptr; // Current assignment + AstNodeFTask* m_ctorp = nullptr; // Class constructor + AstClass* m_classp = nullptr; // Current class V3Graph m_callGraph; // Task call graph TaskBaseVertex* m_curVxp; // Current vertex we're adding to Initials m_initialps; // Initial blocks to move @@ -125,10 +124,18 @@ public: return scopep; } AstVarScope* findVarScope(AstScope* scopep, AstVar* nodep) { - VarToScopeMap::iterator iter = m_varToScopeMap.find(make_pair(scopep, nodep)); + const auto iter = m_varToScopeMap.find(make_pair(scopep, nodep)); UASSERT_OBJ(iter != m_varToScopeMap.end(), nodep, "No scope for var"); return iter->second; } + AstClass* getClassp(AstNodeFTask* nodep) { + AstClass* classp = m_funcToClassMap[nodep]; + UASSERT_OBJ(classp, nodep, "No class for ctor func"); + return classp; + } + void remapFuncClassp(AstNodeFTask* nodep, AstNodeFTask* newp) { + m_funcToClassMap[newp] = getClassp(nodep); + } bool ftaskNoInline(AstNodeFTask* nodep) { return getFTaskVertex(nodep)->noInline(); } AstCFunc* ftaskCFuncp(AstNodeFTask* nodep) { return getFTaskVertex(nodep)->cFuncp(); } void ftaskCFuncp(AstNodeFTask* nodep, AstCFunc* cfuncp) { @@ -159,7 +166,7 @@ private: } // VISITORS - virtual void visit(AstScope* nodep) VL_OVERRIDE { + virtual void visit(AstScope* nodep) override { // Each FTask is unique per-scope, so AstNodeFTaskRefs do not need // pointers to what scope the FTask is to be invoked under. // However, to create variables, we need to track the scopes involved. @@ -179,25 +186,25 @@ private: } iterateChildren(nodep); } - virtual void visit(AstAssignW* nodep) VL_OVERRIDE { + virtual void visit(AstAssignW* nodep) override { m_assignwp = nodep; VL_DO_DANGLING(iterateChildren(nodep), nodep); // May delete nodep. - m_assignwp = NULL; + m_assignwp = nullptr; } - virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTaskRef* nodep) override { // Includes handling AstMethodCall, AstNew if (m_assignwp) { // Wire assigns must become always statements to deal with insertion // of multiple statements. Perhaps someday make all wassigns into always's? UINFO(5, " IM_WireRep " << m_assignwp << endl); m_assignwp->convertToAlways(); - VL_DO_CLEAR(pushDeletep(m_assignwp), m_assignwp = NULL); + VL_DO_CLEAR(pushDeletep(m_assignwp), m_assignwp = nullptr); } // We make multiple edges if a task is called multiple times from another task. UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked task"); new TaskEdge(&m_callGraph, m_curVxp, getFTaskVertex(nodep->taskp())); } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTask* nodep) override { UINFO(9, " TASK " << nodep << endl); TaskBaseVertex* lastVxp = m_curVxp; m_curVxp = getFTaskVertex(nodep); @@ -206,11 +213,13 @@ private: if (nodep->isConstructor()) { m_curVxp->noInline(true); m_ctorp = nodep; + UASSERT_OBJ(m_classp, nodep, "Ctor not under class"); + m_funcToClassMap[nodep] = m_classp; } iterateChildren(nodep); m_curVxp = lastVxp; } - virtual void visit(AstPragma* nodep) VL_OVERRIDE { + virtual void visit(AstPragma* nodep) override { if (nodep->pragType() == AstPragmaType::NO_INLINE_TASK) { // Just mark for the next steps, and we're done with it. m_curVxp->noInline(true); @@ -219,26 +228,26 @@ private: iterateChildren(nodep); } } - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { iterateChildren(nodep); nodep->user4p(m_curVxp); // Remember what task it's under } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { iterateChildren(nodep); if (nodep->varp()->user4u().toGraphVertex() != m_curVxp) { if (m_curVxp->pure() && !nodep->varp()->isXTemp()) m_curVxp->impure(nodep); } } - virtual void visit(AstClass* nodep) VL_OVERRIDE { + virtual void visit(AstClass* nodep) override { // Move initial statements into the constructor m_initialps.clear(); - m_ctorp = NULL; + m_ctorp = nullptr; + m_classp = nodep; { // Find m_initialps, m_ctor iterateChildren(nodep); } UASSERT_OBJ(m_ctorp, nodep, "class constructor missing"); // LinkDot always makes it - for (Initials::iterator it = m_initialps.begin(); it != m_initialps.end(); ++it) { - AstInitial* initialp = *it; + for (AstInitial* initialp : m_initialps) { if (AstNode* newp = initialp->bodysp()) { newp->unlinkFrBackWithNext(); if (!m_ctorp->stmtsp()) { @@ -250,20 +259,19 @@ private: VL_DO_DANGLING(pushDeletep(initialp->unlinkFrBack()), initialp); } m_initialps.clear(); - m_ctorp = NULL; + m_ctorp = nullptr; + m_classp = nullptr; } - virtual void visit(AstInitial* nodep) VL_OVERRIDE { + virtual void visit(AstInitial* nodep) override { m_initialps.push_back(nodep); iterateChildren(nodep); } //-------------------- - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - explicit TaskStateVisitor(AstNetlist* nodep) - : m_assignwp(NULL) - , m_ctorp(NULL) { + explicit TaskStateVisitor(AstNetlist* nodep) { m_curVxp = new TaskCodeVertex(&m_callGraph); AstNode::user3ClearTree(); AstNode::user4ClearTree(); @@ -273,7 +281,7 @@ public: m_callGraph.removeRedundantEdgesSum(&TaskEdge::followAlwaysTrue); m_callGraph.dumpDotFilePrefixed("task_call"); } - virtual ~TaskStateVisitor() {} + virtual ~TaskStateVisitor() override {} VL_UNCOPYABLE(TaskStateVisitor); }; @@ -287,7 +295,7 @@ private: // AstVar::user2p // AstVarScope* to replace varref with // VISITORS - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { // Similar code in V3Inline if (nodep->varp()->user2p()) { // It's being converted to an alias. UINFO(9, @@ -302,14 +310,14 @@ private: } //-------------------- - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit TaskRelinkVisitor(AstBegin* nodep) { // Passed temporary tree iterate(nodep); } - virtual ~TaskRelinkVisitor() {} + virtual ~TaskRelinkVisitor() override {} }; //###################################################################### @@ -319,7 +327,7 @@ class TaskVisitor : public AstNVisitor { private: // NODE STATE // Each module: - // AstNodeFTask::user // True if its been expanded + // AstNodeFTask::user1 // True if its been expanded // Each funccall // to TaskRelinkVisitor: // AstVar::user2p // AstVarScope* to replace varref with @@ -328,21 +336,21 @@ private: AstUser2InUse m_inuser2; // TYPES - enum InsertMode { + enum InsertMode : uint8_t { IM_BEFORE, // Pointing at statement ref is in, insert before this IM_AFTER, // Pointing at last inserted stmt, insert after IM_WHILE_PRECOND // Pointing to for loop, add to body end }; - typedef std::map > DpiNames; + typedef std::map> DpiNames; // STATE TaskStateVisitor* m_statep; // Common state between visitors - AstNodeModule* m_modp; // Current module - AstTopScope* m_topScopep; // Current top scope - AstScope* m_scopep; // Current scope - InsertMode m_insMode; // How to insert - AstNode* m_insStmtp; // Where to insert statement - int m_modNCalls; // Incrementing func # for making symbols + AstNodeModule* m_modp = nullptr; // Current module + AstTopScope* m_topScopep = nullptr; // Current top scope + AstScope* m_scopep = nullptr; // Current scope + InsertMode m_insMode = IM_BEFORE; // How to insert + AstNode* m_insStmtp = nullptr; // Where to insert statement + int m_modNCalls = 0; // Incrementing func # for making symbols DpiNames m_dpiNames; // Map of all created DPI functions // METHODS @@ -382,9 +390,10 @@ private: AstNode* createInlinedFTask(AstNodeFTaskRef* refp, const string& namePrefix, AstVarScope* outvscp) { - // outvscp is the variable for functions only, if NULL, it's a task + // outvscp is the variable for functions only, if nullptr, it's a task UASSERT_OBJ(refp->taskp(), refp, "Unlinked?"); - AstNode* newbodysp = AstNode::cloneTreeNull(refp->taskp()->stmtsp(), true); // Maybe NULL + AstNode* newbodysp + = AstNode::cloneTreeNull(refp->taskp()->stmtsp(), true); // Maybe nullptr AstNode* beginp = new AstComment(refp->fileline(), string("Function: ") + refp->name(), true); if (newbodysp) beginp->addNext(newbodysp); @@ -502,7 +511,7 @@ private: AstNode* createNonInlinedFTask(AstNodeFTaskRef* refp, const string& namePrefix, AstVarScope* outvscp, AstCNew*& cnewpr) { - // outvscp is the variable for functions only, if NULL, it's a task + // outvscp is the variable for functions only, if nullptr, it's a task UASSERT_OBJ(refp->taskp(), refp, "Unlinked?"); AstCFunc* cfuncp = m_statep->ftaskCFuncp(refp->taskp()); UASSERT_OBJ(cfuncp, refp, "No non-inline task associated with this task call?"); @@ -716,7 +725,7 @@ private: string args; args += ("(" + EmitCBaseVisitor::symClassName() + "*)(__Vscopep->symsp())"); // Upcast w/o overhead - AstNode* argnodesp = NULL; + AstNode* argnodesp = nullptr; for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) { if (AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO() && !portp->isFuncReturn() && portp != rtnvarp) { @@ -817,7 +826,7 @@ private: bool duplicatedDpiProto(AstNodeFTask* nodep, const string& dpiproto) { // Only create one DPI extern prototype for each specified cname // as it's legal for the user to attach multiple tasks to one dpi cname - DpiNames::iterator iter = m_dpiNames.find(nodep->cname()); + const auto iter = m_dpiNames.find(nodep->cname()); if (iter == m_dpiNames.end()) { m_dpiNames.insert(make_pair(nodep->cname(), make_pair(nodep, dpiproto))); return false; @@ -951,7 +960,7 @@ private: // Probably some of this work should be done later, but... // should the type of the function be bool/uint32/64 etc (based on lookup) or IData? AstNode::user2ClearTree(); - AstVar* rtnvarp = NULL; + AstVar* rtnvarp = nullptr; if (nodep->isFunction()) { AstVar* portp = VN_CAST(nodep->fvarp(), Var); UASSERT_OBJ(portp, nodep, "function without function output variable"); @@ -1000,7 +1009,7 @@ private: if (nodep->dpiOpenParent()) { // No need to make more than just the c prototype, children will VL_DO_DANGLING(pushDeletep(nodep), nodep); - return NULL; + return nullptr; } } @@ -1009,7 +1018,7 @@ private: if (!duplicatedDpiProto(nodep, dpiproto)) makeDpiExportWrapper(nodep, rtnvarp); } - AstVarScope* rtnvscp = NULL; + AstVarScope* rtnvscp = nullptr; if (rtnvarp) { rtnvscp = new AstVarScope(rtnvarp->fileline(), m_scopep, rtnvarp); m_scopep->addVarp(rtnvscp); @@ -1027,7 +1036,7 @@ private: // Unless public, v3Descope will not uniquify function names even if duplicate per-scope, // so make it unique now. string suffix; // So, make them unique - if (!nodep->taskPublic()) suffix = "_" + m_scopep->nameDotless(); + if (!nodep->taskPublic() && !nodep->classMethod()) suffix = "_" + m_scopep->nameDotless(); string name = ((nodep->name() == "new") ? "new" : prefix + nodep->name() + suffix); AstCFunc* cfuncp = new AstCFunc( nodep->fileline(), name, m_scopep, @@ -1040,8 +1049,16 @@ private: cfuncp->dpiExport(nodep->dpiExport()); cfuncp->dpiImportWrapper(nodep->dpiImport()); cfuncp->isStatic(!(nodep->dpiImport() || nodep->taskPublic() || nodep->classMethod())); + cfuncp->isVirtual(nodep->isVirtual()); cfuncp->pure(nodep->pure()); - cfuncp->isConstructor(nodep->name() == "new"); + if (nodep->name() == "new") { + cfuncp->isConstructor(true); + AstClass* classp = m_statep->getClassp(nodep); + if (classp->extendsp()) { + cfuncp->ctorInits(EmitCBaseVisitor::prefixNameProtect(classp->extendsp()->classp()) + + "(vlSymsp)"); + } + } // cfuncp->dpiImport // Not set in the wrapper - the called function has it set if (cfuncp->dpiExport()) cfuncp->cname(nodep->cname()); @@ -1137,21 +1154,20 @@ private: void iterateIntoFTask(AstNodeFTask* nodep) { // Iterate into the FTask we are calling. Note it may be under a different // scope then the caller, so we need to restore state. - AstScope* oldscopep = m_scopep; - InsertMode prevInsMode = m_insMode; - AstNode* prevInsStmtp = m_insStmtp; - m_scopep = m_statep->getScope(nodep); - iterate(nodep); - m_scopep = oldscopep; - m_insMode = prevInsMode; - m_insStmtp = prevInsStmtp; + VL_RESTORER(m_scopep); + VL_RESTORER(m_insMode); + VL_RESTORER(m_insStmtp); + { + m_scopep = m_statep->getScope(nodep); + iterate(nodep); + } } AstNode* insertBeforeStmt(AstNode* nodep, AstNode* newp) { // Return node that must be visited, if any // See also AstNode::addBeforeStmt; this predates that function if (debug() >= 9) nodep->dumpTree(cout, "-newstmt:"); UASSERT_OBJ(m_insStmtp, nodep, "Function not underneath a statement"); - AstNode* visitp = NULL; + AstNode* visitp = nullptr; if (m_insMode == IM_BEFORE) { // Add the whole thing before insertAt UINFO(5, " IM_Before " << m_insStmtp << endl); @@ -1175,29 +1191,27 @@ private: } // VISITORS - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { - AstNodeModule* origModp = m_modp; - int origNCalls = m_modNCalls; + virtual void visit(AstNodeModule* nodep) override { + VL_RESTORER(m_modp); + VL_RESTORER(m_modNCalls); { m_modp = nodep; - m_insStmtp = NULL; + m_insStmtp = nullptr; m_modNCalls = 0; iterateChildren(nodep); } - m_modp = origModp; - m_modNCalls = origNCalls; } - virtual void visit(AstTopScope* nodep) VL_OVERRIDE { + virtual void visit(AstTopScope* nodep) override { m_topScopep = nodep; iterateChildren(nodep); } - virtual void visit(AstScope* nodep) VL_OVERRIDE { + virtual void visit(AstScope* nodep) override { m_scopep = nodep; - m_insStmtp = NULL; + m_insStmtp = nullptr; iterateChildren(nodep); - m_scopep = NULL; + m_scopep = nullptr; } - virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTaskRef* nodep) override { // Includes handling AstMethodCall, AstNew UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked?"); iterateIntoFTask(nodep->taskp()); // First, do hierarchical funcs @@ -1207,7 +1221,7 @@ private: string namePrefix = ((VN_IS(nodep, FuncRef) ? "__Vfunc_" : "__Vtask_") + nodep->taskp()->shortName() + "__" + cvtToStr(m_modNCalls++)); // Create output variable - AstVarScope* outvscp = NULL; + AstVarScope* outvscp = nullptr; if (nodep->taskp()->isFunction()) { // Not that it's a FUNCREF, but that we're calling a function (perhaps as a task) outvscp @@ -1215,7 +1229,7 @@ private: } // Create cloned statements AstNode* beginp; - AstCNew* cnewp = NULL; + AstCNew* cnewp = nullptr; if (m_statep->ftaskNoInline(nodep->taskp())) { // This may share VarScope's with a public task, if any. Yuk. beginp = createNonInlinedFTask(nodep, namePrefix, outvscp, cnewp /*ref*/); @@ -1223,7 +1237,7 @@ private: beginp = createInlinedFTask(nodep, namePrefix, outvscp); } // Replace the ref - AstNode* visitp = NULL; + AstNode* visitp = nullptr; if (VN_IS(nodep, New)) { UASSERT_OBJ(!nodep->isStatement(), nodep, "new is non-stmt"); UASSERT_OBJ(cnewp, nodep, "didn't create cnew for new"); @@ -1241,7 +1255,7 @@ private: IGNOREDRETURN, "Ignoring return value of non-void function (IEEE 1800-2017 13.4.1)"); } - // outvscp maybe non-NULL if calling a function in a taskref, + // outvscp maybe non-nullptr if calling a function in a taskref, // but if so we want to simply ignore the function result nodep->replaceWith(beginp); } @@ -1251,10 +1265,10 @@ private: // Visit nodes that normal iteration won't find if (visitp) iterateAndNextNull(visitp); } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTask* nodep) override { UINFO(4, " Inline " << nodep << endl); - InsertMode prevInsMode = m_insMode; - AstNode* prevInsStmtp = m_insStmtp; + VL_RESTORER(m_insMode); + VL_RESTORER(m_insStmtp); m_insMode = IM_BEFORE; m_insStmtp = nodep->stmtsp(); // Might be null if no statements, but we won't use it if (!nodep->user1SetOnce()) { // Just one creation needed per function @@ -1284,6 +1298,8 @@ private: m_statep->checkPurity(nodep); } AstNodeFTask* clonedFuncp = nodep->cloneTree(false); + if (nodep->isConstructor()) m_statep->remapFuncClassp(nodep, clonedFuncp); + AstCFunc* cfuncp = makeUserFunc(clonedFuncp, m_statep->ftaskNoInline(nodep)); if (cfuncp) { nodep->addNextHere(cfuncp); @@ -1316,31 +1332,29 @@ private: nodep->unlinkFrBack(); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - m_insMode = prevInsMode; - m_insStmtp = prevInsStmtp; } - virtual void visit(AstWhile* nodep) VL_OVERRIDE { + virtual void visit(AstWhile* nodep) override { // Special, as statements need to be put in different places // Preconditions insert first just before themselves (the normal // rule for other statement types) - m_insStmtp = NULL; // First thing should be new statement + m_insStmtp = nullptr; // First thing should be new statement iterateAndNextNull(nodep->precondsp()); // Conditions insert first at end of precondsp. m_insMode = IM_WHILE_PRECOND; m_insStmtp = nodep; iterateAndNextNull(nodep->condp()); // Body insert just before themselves - m_insStmtp = NULL; // First thing should be new statement + m_insStmtp = nullptr; // First thing should be new statement iterateAndNextNull(nodep->bodysp()); iterateAndNextNull(nodep->incsp()); // Done the loop - m_insStmtp = NULL; // Next thing should be new statement + m_insStmtp = nullptr; // Next thing should be new statement } - 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.cpp"); } - virtual void visit(AstNodeStmt* nodep) VL_OVERRIDE { + virtual void visit(AstNodeStmt* nodep) override { if (!nodep->isStatement()) { iterateChildren(nodep); return; @@ -1348,25 +1362,19 @@ private: m_insMode = IM_BEFORE; m_insStmtp = nodep; iterateChildren(nodep); - m_insStmtp = NULL; // Next thing should be new statement + m_insStmtp = nullptr; // Next thing should be new statement } //-------------------- - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS TaskVisitor(AstNetlist* nodep, TaskStateVisitor* statep) - : m_statep(statep) { - m_modp = NULL; - m_topScopep = NULL; - m_scopep = NULL; - m_insMode = IM_BEFORE; - m_insStmtp = NULL; - m_modNCalls = 0; + : m_statep{statep} { AstNode::user1ClearTree(); iterate(nodep); } - virtual ~TaskVisitor() {} + virtual ~TaskVisitor() override {} }; //###################################################################### @@ -1375,7 +1383,7 @@ public: V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) { // Output list will be in order of the port declaration variables (so // func calls are made right in C) - // Missing pin/expr? We return (pinvar, NULL) + // Missing pin/expr? We return (pinvar, nullptr) // Extra pin/expr? We clean it up typedef std::map NameToIndex; @@ -1385,11 +1393,11 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) // Find ports int tpinnum = 0; - AstVar* sformatp = NULL; + AstVar* sformatp = nullptr; for (AstNode* stmtp = taskStmtsp; stmtp; stmtp = stmtp->nextp()) { if (AstVar* portp = VN_CAST(stmtp, Var)) { if (portp->isIO()) { - tconnects.push_back(make_pair(portp, static_cast(NULL))); + tconnects.push_back(make_pair(portp, static_cast(nullptr))); nameToIndex.insert( make_pair(portp->name(), tpinnum)); // For name based connections tpinnum++; @@ -1412,7 +1420,7 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) UASSERT_OBJ(argp, pinp, "Non-arg under ftask reference"); if (argp->name() != "") { // By name - NameToIndex::iterator it = nameToIndex.find(argp->name()); + const auto it = nameToIndex.find(argp->name()); if (it == nameToIndex.end()) { pinp->v3error("No such argument " << argp->prettyNameQ() << " in function call to " << nodep->taskp()->prettyTypeName()); @@ -1431,7 +1439,7 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) } else { // By pin number if (ppinnum >= tpinnum) { if (sformatp) { - tconnects.push_back(make_pair(sformatp, static_cast(NULL))); + tconnects.push_back(make_pair(sformatp, static_cast(nullptr))); tconnects[ppinnum].second = argp; tpinnum++; } else { @@ -1451,7 +1459,7 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) for (int i = 0; i < tpinnum; ++i) { AstVar* portp = tconnects[i].first; if (!tconnects[i].second || !tconnects[i].second->exprp()) { - AstNode* newvaluep = NULL; + AstNode* newvaluep = nullptr; if (!portp->valuep()) { nodep->v3error("Missing argument on non-defaulted argument " << portp->prettyNameQ() << " in function call to " @@ -1481,9 +1489,9 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp) // or not, we make this into a pin UINFO(9, "Default pin for " << portp << endl); AstArg* newp = new AstArg(nodep->fileline(), portp->name(), newvaluep); - if (tconnects[i].second) { // Have a "NULL" pin already defined for it + if (tconnects[i].second) { // Have a "nullptr" pin already defined for it VL_DO_CLEAR(tconnects[i].second->unlinkFrBack()->deleteTree(), - tconnects[i].second = NULL); + tconnects[i].second = nullptr); } tconnects[i].second = newp; reorganize = true; diff --git a/src/V3Trace.cpp b/src/V3Trace.cpp index de8e2e50d..cb29a734e 100644 --- a/src/V3Trace.cpp +++ b/src/V3Trace.cpp @@ -60,31 +60,31 @@ public: enum { ACTIVITY_ALWAYS = ((1UL << 31) - 2) }; enum { ACTIVITY_SLOW = 0 }; TraceActivityVertex(V3Graph* graphp, AstNode* nodep, bool slow) - : V3GraphVertex(graphp) - , m_insertp(nodep) { + : V3GraphVertex{graphp} + , m_insertp{nodep} { m_activityCode = 0; m_slow = slow; } TraceActivityVertex(V3Graph* graphp, vlsint32_t code) - : V3GraphVertex(graphp) - , m_insertp(NULL) { + : V3GraphVertex{graphp} + , m_insertp{nullptr} { m_activityCode = code; m_slow = false; } - virtual ~TraceActivityVertex() {} + virtual ~TraceActivityVertex() override {} // ACCESSORS AstNode* insertp() const { if (!m_insertp) v3fatalSrc("Null insertp; probably called on a special always/slow."); return m_insertp; } - virtual string name() const { + virtual string name() const override { if (activityAlways()) { return "*ALWAYS*"; } else { return (string(slow() ? "*SLOW* " : "")) + insertp()->name(); } } - virtual string dotColor() const { return slow() ? "yellowGreen" : "green"; } + virtual string dotColor() const override { return slow() ? "yellowGreen" : "green"; } vlsint32_t activityCode() const { return m_activityCode; } bool activityAlways() const { return activityCode() == ACTIVITY_ALWAYS; } bool activitySlow() const { return activityCode() == ACTIVITY_SLOW; } @@ -100,32 +100,31 @@ class TraceCFuncVertex : public V3GraphVertex { public: TraceCFuncVertex(V3Graph* graphp, AstCFunc* nodep) - : V3GraphVertex(graphp) - , m_nodep(nodep) {} - virtual ~TraceCFuncVertex() {} + : V3GraphVertex{graphp} + , m_nodep{nodep} {} + virtual ~TraceCFuncVertex() override {} // ACCESSORS AstCFunc* nodep() const { return m_nodep; } - virtual string name() const { return nodep()->name(); } - virtual string dotColor() const { return "yellow"; } - virtual FileLine* fileline() const { return nodep()->fileline(); } + virtual string name() const override { return nodep()->name(); } + virtual string dotColor() const override { return "yellow"; } + virtual FileLine* fileline() const override { return nodep()->fileline(); } }; class TraceTraceVertex : public V3GraphVertex { AstTraceDecl* const m_nodep; // TRACEINC this represents - // NULL, or other vertex with the real code() that duplicates this one - TraceTraceVertex* m_duplicatep; + // nullptr, or other vertex with the real code() that duplicates this one + TraceTraceVertex* m_duplicatep = nullptr; public: TraceTraceVertex(V3Graph* graphp, AstTraceDecl* nodep) - : V3GraphVertex(graphp) - , m_nodep(nodep) - , m_duplicatep(NULL) {} - virtual ~TraceTraceVertex() {} + : V3GraphVertex{graphp} + , m_nodep{nodep} {} + virtual ~TraceTraceVertex() override {} // ACCESSORS AstTraceDecl* nodep() const { return m_nodep; } - virtual string name() const { return nodep()->name(); } - virtual string dotColor() const { return "red"; } - virtual FileLine* fileline() const { return nodep()->fileline(); } + virtual string name() const override { return nodep()->name(); } + virtual string dotColor() const override { return "red"; } + virtual FileLine* fileline() const override { return nodep()->fileline(); } TraceTraceVertex* duplicatep() const { return m_duplicatep; } void duplicatep(TraceTraceVertex* dupp) { UASSERT_OBJ(!duplicatep(), nodep(), "Assigning duplicatep() to already duplicated node"); @@ -138,14 +137,14 @@ class TraceVarVertex : public V3GraphVertex { public: TraceVarVertex(V3Graph* graphp, AstVarScope* nodep) - : V3GraphVertex(graphp) - , m_nodep(nodep) {} - virtual ~TraceVarVertex() {} + : V3GraphVertex{graphp} + , m_nodep{nodep} {} + virtual ~TraceVarVertex() override {} // ACCESSORS AstVarScope* nodep() const { return m_nodep; } - virtual string name() const { return nodep()->name(); } - virtual string dotColor() const { return "skyblue"; } - virtual FileLine* fileline() const { return nodep()->fileline(); } + virtual string name() const override { return nodep()->name(); } + virtual string dotColor() const override { return "skyblue"; } + virtual FileLine* fileline() const override { return nodep()->fileline(); } }; //###################################################################### @@ -168,16 +167,16 @@ private: // AstUser4InUse In V3Hashed // STATE - AstNodeModule* m_topModp; // Module to add variables to - AstScope* m_topScopep; // Scope to add variables to - AstCFunc* m_funcp; // C function adding to graph - AstTraceDecl* m_tracep; // Trace function adding to graph - AstVarScope* m_activityVscp; // Activity variable - uint32_t m_activityNumber; // Count of fields in activity variable - uint32_t m_code; // Trace ident code# being assigned + AstNodeModule* m_topModp = nullptr; // Module to add variables to + AstScope* m_topScopep = nullptr; // Scope to add variables to + AstCFunc* m_funcp = nullptr; // C function adding to graph + AstTraceDecl* m_tracep = nullptr; // Trace function adding to graph + AstVarScope* m_activityVscp = nullptr; // Activity variable + uint32_t m_activityNumber = 0; // Count of fields in activity variable + uint32_t m_code = 0; // Trace ident code# being assigned V3Graph m_graph; // Var/CFunc tracking TraceActivityVertex* const m_alwaysVtxp; // "Always trace" vertex - bool m_finding; // Pass one of algorithm? + bool m_finding = false; // Pass one of algorithm? VDouble0 m_statChgSigs; // Statistic tracking VDouble0 m_statUniqSigs; // Statistic tracking @@ -221,7 +220,7 @@ private: if (TraceTraceVertex* const vvertexp = dynamic_cast(itp)) { AstTraceDecl* const nodep = vvertexp->nodep(); if (nodep->valuep() && !vvertexp->duplicatep()) { - V3Hashed::iterator dupit = hashed.findDuplicate(nodep->valuep()); + const auto dupit = hashed.findDuplicate(nodep->valuep()); if (dupit != hashed.end()) { const AstTraceDecl* const dupDeclp = VN_CAST_CONST(hashed.iteratorNodep(dupit)->backp(), TraceDecl); @@ -273,7 +272,7 @@ private: if (const TraceTraceVertex* const vvertexp = dynamic_cast(itp)) { // Search for the incoming always edge - const V3GraphEdge* alwaysEdgep = NULL; + const V3GraphEdge* alwaysEdgep = nullptr; for (const V3GraphEdge* edgep = vvertexp->inBeginp(); edgep; edgep = edgep->inNextp()) { const TraceActivityVertex* const actVtxp @@ -382,10 +381,10 @@ private: // For each activity set with only a small number of signals, make those // signals always traced, as it's cheaper to check a few value changes // than to test a lot of activity flags - TraceVec::iterator it = traces.begin(); - const TraceVec::iterator end = traces.end(); + auto it = traces.begin(); + const auto end = traces.end(); while (it != end) { - TraceVec::iterator head = it; + auto head = it; // Approximate the complexity of the value change check uint32_t complexity = 0; const ActCodeSet& actSet = it->first; @@ -534,10 +533,10 @@ private: int topFuncNum = 0; int subFuncNum = 0; - TraceVec::const_iterator it = traces.begin(); - while (it != traces.end()) { - AstCFunc* topFuncp = NULL; - AstCFunc* subFuncp = NULL; + auto it = traces.cbegin(); + while (it != traces.cend()) { + AstCFunc* topFuncp = nullptr; + AstCFunc* subFuncp = nullptr; int subStmts = 0; const uint32_t maxCodes = (nAllCodes + parallelism - 1) / parallelism; uint32_t nCodes = 0; @@ -566,14 +565,15 @@ private: // Create top function if not yet created if (!topFuncp) { - topFuncp = newCFunc(AstCFuncType::TRACE_FULL, NULL, regFuncp, topFuncNum); + topFuncp + = newCFunc(AstCFuncType::TRACE_FULL, nullptr, regFuncp, topFuncNum); } // Crate new sub function if required if (!subFuncp || subStmts > splitLimit) { subStmts = 0; - subFuncp - = newCFunc(AstCFuncType::TRACE_FULL_SUB, topFuncp, NULL, subFuncNum); + subFuncp = newCFunc(AstCFuncType::TRACE_FULL_SUB, topFuncp, nullptr, + subFuncNum); } // Add TraceInc node @@ -585,7 +585,7 @@ private: nCodes += declp->codeInc(); } } - if (topFuncp) { // might be NULL if all trailing entries were duplicates + if (topFuncp) { // might be nullptr if all trailing entries were duplicates UINFO(5, "traceFullTop" << topFuncNum - 1 << " codes: " << nCodes << "/" << maxCodes << endl); } @@ -600,13 +600,13 @@ private: int subFuncNum = 0; TraceVec::const_iterator it = traces.begin(); while (it != traces.end()) { - AstCFunc* topFuncp = NULL; - AstCFunc* subFuncp = NULL; + AstCFunc* topFuncp = nullptr; + AstCFunc* subFuncp = nullptr; int subStmts = 0; const uint32_t maxCodes = (nAllCodes + parallelism - 1) / parallelism; uint32_t nCodes = 0; - const ActCodeSet* prevActSet = NULL; - AstIf* ifp = NULL; + const ActCodeSet* prevActSet = nullptr; + AstIf* ifp = nullptr; for (; nCodes < maxCodes && it != traces.end(); ++it) { const TraceTraceVertex* const vtxp = it->second; // This is a duplicate decl, no need to add it to incremental dump @@ -617,33 +617,32 @@ private: // Create top function if not yet created if (!topFuncp) { - topFuncp = newCFunc(AstCFuncType::TRACE_CHANGE, NULL, regFuncp, topFuncNum); + topFuncp = newCFunc(AstCFuncType::TRACE_CHANGE, nullptr, regFuncp, topFuncNum); } // Crate new sub function if required if (!subFuncp || subStmts > splitLimit) { subStmts = 0; subFuncp - = newCFunc(AstCFuncType::TRACE_CHANGE_SUB, topFuncp, NULL, subFuncNum); - prevActSet = NULL; - ifp = NULL; + = newCFunc(AstCFuncType::TRACE_CHANGE_SUB, topFuncp, nullptr, subFuncNum); + prevActSet = nullptr; + ifp = nullptr; } // If required, create the conditional node checking the activity flags if (!prevActSet || actSet != *prevActSet) { FileLine* const flp = m_topScopep->fileline(); bool always = actSet.count(TraceActivityVertex::ACTIVITY_ALWAYS) != 0; - AstNode* condp = NULL; + AstNode* condp = nullptr; if (always) { condp = new AstConst(flp, 1); // Always true, will be folded later } else { - for (ActCodeSet::iterator it = actSet.begin(); it != actSet.end(); ++it) { - const uint32_t actCode = *it; + for (const uint32_t actCode : actSet) { AstNode* const selp = selectActivity(flp, actCode, false); condp = condp ? new AstOr(flp, condp, selp) : selp; } } - ifp = new AstIf(flp, condp, NULL, NULL); + ifp = new AstIf(flp, condp, nullptr, nullptr); if (!always) { ifp->branchPred(VBranchPred::BP_UNLIKELY); } subFuncp->addStmtsp(ifp); subStmts += EmitCBaseCounterVisitor(ifp).count(); @@ -659,7 +658,7 @@ private: // Track partitioning nCodes += declp->codeInc(); } - if (topFuncp) { // might be NULL if all trailing entries were duplicates/constants + if (topFuncp) { // might be nullptr if all trailing entries were duplicates/constants UINFO(5, "traceChgTop" << topFuncNum - 1 << " codes: " << nCodes << "/" << maxCodes << endl); } @@ -773,7 +772,7 @@ private: } // VISITORS - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { m_code = 1; // Multiple TopScopes will require fixing how code#s // are assigned as duplicate varscopes must result in the same tracing code#. @@ -788,17 +787,17 @@ private: // Create the trace functions and insert them into the tree createTraceFunctions(); } - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { + virtual void visit(AstNodeModule* nodep) override { if (nodep->isTop()) m_topModp = nodep; iterateChildren(nodep); } - virtual void visit(AstTopScope* nodep) VL_OVERRIDE { + virtual void visit(AstTopScope* nodep) override { AstScope* const scopep = nodep->scopep(); UASSERT_OBJ(scopep, nodep, "No scope found on top level"); m_topScopep = scopep; iterateChildren(nodep); } - virtual void visit(AstCCall* nodep) VL_OVERRIDE { + virtual void visit(AstCCall* nodep) override { UINFO(8, " CCALL " << nodep << endl); if (!m_finding && !nodep->user2()) { // See if there are other calls in same statement list; @@ -817,7 +816,7 @@ private: } iterateChildren(nodep); } - virtual void visit(AstCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstCFunc* nodep) override { UINFO(8, " CFUNC " << nodep << endl); V3GraphVertex* const funcVtxp = getCFuncVertexp(nodep); if (!m_finding) { // If public, we need a unique activity code to allow for sets @@ -829,9 +828,9 @@ private: } m_funcp = nodep; iterateChildren(nodep); - m_funcp = NULL; + m_funcp = nullptr; } - virtual void visit(AstTraceDecl* nodep) VL_OVERRIDE { + virtual void visit(AstTraceDecl* nodep) override { UINFO(8, " TRACE " << nodep << endl); if (!m_finding) { V3GraphVertex* const vertexp = new TraceTraceVertex(&m_graph, nodep); @@ -840,10 +839,10 @@ private: UASSERT_OBJ(m_funcp, nodep, "Trace not under func"); m_tracep = nodep; iterateChildren(nodep); - m_tracep = NULL; + m_tracep = nullptr; } } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { if (m_tracep) { UASSERT_OBJ(nodep->varScopep(), nodep, "No var scope?"); UASSERT_OBJ(!nodep->lvalue(), nodep, "Lvalue in trace? Should be const."); @@ -868,23 +867,15 @@ private: } } //-------------------- - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS explicit TraceVisitor(AstNetlist* nodep) - : m_alwaysVtxp(new TraceActivityVertex(&m_graph, TraceActivityVertex::ACTIVITY_ALWAYS)) { - m_funcp = NULL; - m_tracep = NULL; - m_topModp = NULL; - m_topScopep = NULL; - m_finding = false; - m_activityVscp = NULL; - m_activityNumber = 0; - m_code = 0; + : m_alwaysVtxp{new TraceActivityVertex{&m_graph, TraceActivityVertex::ACTIVITY_ALWAYS}} { iterate(nodep); } - virtual ~TraceVisitor() { + virtual ~TraceVisitor() override { V3Stats::addStat("Tracing, Unique changing signals", m_statChgSigs); V3Stats::addStat("Tracing, Unique traced signals", m_statUniqSigs); V3Stats::addStat("Tracing, Unique trace codes", m_statUniqCodes); diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp index e404efda3..4157347a5 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -36,15 +36,15 @@ private: // NODE STATE // STATE - AstScope* m_topScopep; // Current top scope - AstCFunc* m_initFuncp; // Trace function being built - AstCFunc* m_initSubFuncp; // Trace function being built (under m_init) - int m_initSubStmts; // Number of statements in function - int m_funcNum; // Function number being built - AstVarScope* m_traVscp; // Signal being trace constructed - AstNode* m_traValuep; // Signal being traced's value to trace in it + AstScope* m_topScopep = nullptr; // Current top scope + AstCFunc* m_initFuncp = nullptr; // Trace function being built + AstCFunc* m_initSubFuncp = nullptr; // Trace function being built (under m_init) + int m_initSubStmts = 0; // Number of statements in function + int m_funcNum = 0; // Function number being built + AstVarScope* m_traVscp = nullptr; // Signal being trace constructed + AstNode* m_traValuep = nullptr; // Signal being traced's value to trace in it string m_traShowname; // Signal being traced's component name - bool m_interface; // Currently tracing an interface + bool m_interface = false; // Currently tracing an interface VDouble0 m_statSigs; // Statistic tracking VDouble0 m_statIgnSigs; // Statistic tracking @@ -65,7 +65,7 @@ private: if (!prettyName.empty() && prettyName[0] == '_') return "Leading underscore"; if (prettyName.find("._") != string::npos) return "Inlined leading underscore"; } - return NULL; + return nullptr; } AstCFunc* newCFunc(AstCFuncType type, const string& name) { @@ -91,7 +91,7 @@ private: AstCFunc* newCFuncSub(AstCFunc* basep) { const string name = "traceInitSub" + cvtToStr(m_funcNum++); AstCFunc* const funcp = newCFunc(AstCFuncType::TRACE_INIT_SUB, name); - if (!m_interface) callCFuncSub(basep, funcp, NULL); + if (!m_interface) callCFuncSub(basep, funcp, nullptr); return funcp; } void addTraceDecl(const VNumRange& arrayRange, @@ -124,7 +124,7 @@ private: } // VISITORS - virtual void visit(AstTopScope* nodep) VL_OVERRIDE { + virtual void visit(AstTopScope* nodep) override { m_topScopep = nodep->scopep(); // Create the trace init function m_initFuncp = newCFunc(AstCFuncType::TRACE_INIT, "traceInitTop"); @@ -133,7 +133,7 @@ private: // And find variables iterateChildren(nodep); } - virtual void visit(AstScope* nodep) VL_OVERRIDE { + virtual void visit(AstScope* nodep) override { AstCell* const cellp = VN_CAST(nodep->aboveCellp(), Cell); if (cellp && VN_IS(cellp->modp(), Iface)) { AstCFunc* const origSubFunc = m_initSubFuncp; @@ -171,7 +171,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstVarScope* nodep) VL_OVERRIDE { + virtual void visit(AstVarScope* nodep) override { iterateChildren(nodep); // Prefilter - things that get through this if will either get // traced or get a comment as to why not traced. @@ -191,7 +191,7 @@ private: m_traShowname = AstNode::vcdName(scopep->name() + " " + varp->name()); if (m_traShowname.substr(0, 4) == "TOP ") m_traShowname.erase(0, 4); } - UASSERT_OBJ(m_initSubFuncp, nodep, "NULL"); + UASSERT_OBJ(m_initSubFuncp, nodep, "nullptr"); m_traVscp = nodep; if (const char* const ignoreReasonp = vscIgnoreTrace(nodep)) { @@ -206,20 +206,20 @@ private: // Recurse into data type of the signal; the visitors will call addTraceDecl() iterate(varp->dtypep()->skipRefToEnump()); // Cleanup - if (m_traValuep) VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = NULL); + if (m_traValuep) VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = nullptr); } - m_traVscp = NULL; + m_traVscp = nullptr; m_traShowname = ""; } } // VISITORS - Data types when tracing - virtual void visit(AstConstDType* nodep) VL_OVERRIDE { + virtual void visit(AstConstDType* nodep) override { if (m_traVscp) iterate(nodep->subDTypep()->skipRefToEnump()); } - virtual void visit(AstRefDType* nodep) VL_OVERRIDE { + virtual void visit(AstRefDType* nodep) override { if (m_traVscp) iterate(nodep->subDTypep()->skipRefToEnump()); } - virtual void visit(AstUnpackArrayDType* nodep) VL_OVERRIDE { + virtual void visit(AstUnpackArrayDType* nodep) override { // Note more specific dtypes above if (m_traVscp) { if (static_cast(nodep->arrayUnpackedElements()) > v3Global.opt.traceMaxArray()) { @@ -239,8 +239,8 @@ private: // Unroll now, as have no other method to get right signal names AstNodeDType* const subtypep = nodep->subDTypep()->skipRefToEnump(); for (int i = nodep->lsb(); i <= nodep->msb(); ++i) { - const string oldShowname = m_traShowname; - AstNode* const oldValuep = m_traValuep; + VL_RESTORER(m_traShowname); + VL_RESTORER(m_traValuep); { m_traShowname += string("(") + cvtToStr(i) + string(")"); m_traValuep = new AstArraySel( @@ -248,15 +248,13 @@ private: m_traValuep->dtypep(subtypep); iterate(subtypep); - VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = NULL); + VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = nullptr); } - m_traShowname = oldShowname; - m_traValuep = oldValuep; } } } } - virtual void visit(AstPackArrayDType* nodep) VL_OVERRIDE { + virtual void visit(AstPackArrayDType* nodep) override { if (m_traVscp) { if (!v3Global.opt.traceStructs()) { // Everything downstream is packed, so deal with as one trace unit. @@ -266,8 +264,8 @@ private: } else { AstNodeDType* const subtypep = nodep->subDTypep()->skipRefToEnump(); for (int i = nodep->lsb(); i <= nodep->msb(); ++i) { - const string oldShowname = m_traShowname; - AstNode* const oldValuep = m_traValuep; + VL_RESTORER(m_traShowname); + VL_RESTORER(m_traValuep); { m_traShowname += string("(") + cvtToStr(i) + string(")"); m_traValuep = new AstSel(nodep->fileline(), m_traValuep->cloneTree(true), @@ -275,15 +273,13 @@ private: subtypep->width()); m_traValuep->dtypep(subtypep); iterate(subtypep); - VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = NULL); + VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = nullptr); } - m_traShowname = oldShowname; - m_traValuep = oldValuep; } } } } - virtual void visit(AstNodeUOrStructDType* nodep) VL_OVERRIDE { + virtual void visit(AstNodeUOrStructDType* nodep) override { if (m_traVscp) { if (nodep->packed() && !v3Global.opt.traceStructs()) { // Everything downstream is packed, so deal with as one trace unit @@ -296,8 +292,8 @@ private: for (const AstMemberDType* itemp = nodep->membersp(); itemp; itemp = VN_CAST_CONST(itemp->nextp(), MemberDType)) { AstNodeDType* const subtypep = itemp->subDTypep()->skipRefToEnump(); - const string oldShowname = m_traShowname; - AstNode* const oldValuep = m_traValuep; + VL_RESTORER(m_traShowname); + VL_RESTORER(m_traValuep); { m_traShowname += string(" ") + itemp->prettyName(); if (VN_IS(nodep, StructDType)) { @@ -306,18 +302,16 @@ private: itemp->lsb(), subtypep->width()); m_traValuep->dtypep(subtypep); iterate(subtypep); - VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = NULL); + VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = nullptr); } else { // Else union, replicate fields iterate(subtypep); } } - m_traShowname = oldShowname; - m_traValuep = oldValuep; } } } } - virtual void visit(AstBasicDType* nodep) VL_OVERRIDE { + virtual void visit(AstBasicDType* nodep) override { if (m_traVscp) { if (nodep->isString()) { addIgnore("Unsupported: strings"); @@ -326,30 +320,20 @@ private: } } } - virtual void visit(AstEnumDType* nodep) VL_OVERRIDE { iterate(nodep->skipRefp()); } - virtual void visit(AstNodeDType* nodep) VL_OVERRIDE { + virtual void visit(AstEnumDType* nodep) override { iterate(nodep->skipRefp()); } + virtual void visit(AstNodeDType*) override { // Note more specific dtypes above if (!m_traVscp) return; addIgnore("Unsupported: data type"); } //-------------------- - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - explicit TraceDeclVisitor(AstNetlist* nodep) { - m_topScopep = NULL; - m_initFuncp = NULL; - m_initSubFuncp = NULL; - m_initSubStmts = 0; - m_funcNum = 0; - m_traVscp = NULL; - m_traValuep = NULL; - m_interface = false; - iterate(nodep); - } - virtual ~TraceDeclVisitor() { + explicit TraceDeclVisitor(AstNetlist* nodep) { iterate(nodep); } + virtual ~TraceDeclVisitor() override { V3Stats::addStat("Tracing, Traced signals", m_statSigs); V3Stats::addStat("Tracing, Ignored signals", m_statIgnSigs); } diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index feab69955..7dda34b28 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -80,29 +80,26 @@ public: class TristateVertex : public V3GraphVertex { AstNode* m_nodep; - bool m_isTristate; // Logic indicates a tristate - bool m_feedsTri; // Propagates to a tristate node (on RHS) - bool m_processed; // Tristating was cleaned up + bool m_isTristate = false; // Logic indicates a tristate + bool m_feedsTri = false; // Propagates to a tristate node (on RHS) + bool m_processed = false; // Tristating was cleaned up public: TristateVertex(V3Graph* graphp, AstNode* nodep) - : V3GraphVertex(graphp) - , m_nodep(nodep) - , m_isTristate(false) - , m_feedsTri(false) - , m_processed(false) {} - virtual ~TristateVertex() {} + : V3GraphVertex{graphp} + , m_nodep{nodep} {} + virtual ~TristateVertex() override {} // ACCESSORS AstNode* nodep() const { return m_nodep; } AstVar* varp() const { return VN_CAST(nodep(), Var); } - virtual string name() const { + virtual string name() const override { return ((isTristate() ? "tri\\n" : feedsTri() ? "feed\\n" : "-\\n") + (nodep()->prettyTypeName() + " " + cvtToHex(nodep()))); } - virtual string dotColor() const { + virtual string dotColor() const override { return (varp() ? (isTristate() ? "darkblue" : feedsTri() ? "blue" : "lightblue") : (isTristate() ? "darkgreen" : feedsTri() ? "green" : "lightgreen")); } - virtual FileLine* fileline() const { return nodep()->fileline(); } + virtual FileLine* fileline() const override { return nodep()->fileline(); } void isTristate(bool flag) { m_isTristate = flag; } bool isTristate() const { return m_isTristate; } void feedsTri(bool flag) { m_feedsTri = flag; } @@ -278,7 +275,7 @@ class TristatePinVisitor : public TristateBaseVisitor { TristateGraph& m_tgraph; bool m_lvalue; // Flip to be an LVALUE // VISITORS - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { if (m_lvalue && !nodep->lvalue()) { UINFO(9, " Flip-to-LValue " << nodep << endl); nodep->lvalue(true); @@ -290,26 +287,26 @@ class TristatePinVisitor : public TristateBaseVisitor { m_tgraph.setTristate(nodep->varp()); } } - virtual void visit(AstArraySel* nodep) VL_OVERRIDE { + virtual void visit(AstArraySel* nodep) override { // Doesn't work because we'd set lvalue on the array index's var UASSERT_OBJ(!m_lvalue, nodep, "ArraySel conversion to output, under tristate node"); iterateChildren(nodep); } - virtual void visit(AstSliceSel* nodep) VL_OVERRIDE { + virtual void visit(AstSliceSel* nodep) override { // Doesn't work because we'd set lvalue on the array index's var UASSERT_OBJ(!m_lvalue, nodep, "SliceSel conversion to output, under tristate node"); iterateChildren(nodep); } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS TristatePinVisitor(AstNode* nodep, TristateGraph& tgraph, bool lvalue) - : m_tgraph(tgraph) - , m_lvalue(lvalue) { + : m_tgraph(tgraph) // Need () or GCC 4.8 false warning + , m_lvalue{lvalue} { iterate(nodep); } - virtual ~TristatePinVisitor() {} + virtual ~TristatePinVisitor() override {} }; //###################################################################### @@ -332,21 +329,21 @@ class TristateVisitor : public TristateBaseVisitor { // TYPES typedef std::vector RefVec; typedef std::map VarMap; - enum { + enum : uint8_t { U2_GRAPHING = 1, // bit[0] if did m_graphing visit U2_NONGRAPH = 2, // bit[1] if did !m_graphing visit U2_BOTH = 3 }; // Both bits set // MEMBERS - bool m_graphing; // Major mode - creating graph + bool m_graphing = false; // Major mode - creating graph // - AstNodeModule* m_modp; // Current module - AstCell* m_cellp; // current cell + AstNodeModule* m_modp = nullptr; // Current module + AstCell* m_cellp = nullptr; // current cell VarMap m_lhsmap; // LHS driver map - int m_unique; - bool m_alhs; // On LHS of assignment - AstNode* m_logicp; // Current logic being built + int m_unique = 0; + bool m_alhs = false; // On LHS of assignment + AstNode* m_logicp = nullptr; // Current logic being built TristateGraph m_tgraph; // Logic graph // STATS @@ -424,7 +421,7 @@ class TristateVisitor : public TristateBaseVisitor { void mapInsertLhsVarRef(AstVarRef* nodep) { AstVar* key = nodep->varp(); - VarMap::iterator it = m_lhsmap.find(key); + const auto it = m_lhsmap.find(key); UINFO(9, " mapInsertLhsVarRef " << nodep << endl); if (it == m_lhsmap.end()) { // Not found RefVec* refsp = new RefVec(); @@ -485,7 +482,7 @@ class TristateVisitor : public TristateBaseVisitor { for (TristateGraph::VarVec::iterator ii = vars.begin(); ii != vars.end(); ++ii) { AstVar* varp = (*ii); if (m_tgraph.isTristate(varp)) { - VarMap::iterator it = m_lhsmap.find(varp); + const auto it = m_lhsmap.find(varp); if (it == m_lhsmap.end()) { // set output enable to always be off on this assign // statement so that this var is floating @@ -531,8 +528,8 @@ class TristateVisitor : public TristateBaseVisitor { // original port gets converted to an input. Don't tristate expand // if this is the top level so that we can force the final // tristate resolution at the top. - AstVar* envarp = NULL; - AstVar* outvarp = NULL; // __out + AstVar* envarp = nullptr; + AstVar* outvarp = nullptr; // __out AstVar* lhsp = invarp; // Variable to assign drive-value to ( or __out) if (!nodep->isTop() && invarp->isIO()) { // This var becomes an input @@ -554,9 +551,9 @@ class TristateVisitor : public TristateBaseVisitor { envarp = VN_CAST(invarp->user1p(), Var); // From CASEEQ, foo === 1'bz } - AstNode* orp = NULL; - AstNode* enp = NULL; - AstNode* undrivenp = NULL; + AstNode* orp = nullptr; + AstNode* enp = nullptr; + AstNode* undrivenp = nullptr; // loop through the lhs drivers to build the driver resolution logic for (RefVec::iterator ii = refsp->begin(); ii != refsp->end(); ++ii) { @@ -639,7 +636,7 @@ class TristateVisitor : public TristateBaseVisitor { } // VISITORS - virtual void visit(AstConst* nodep) VL_OVERRIDE { + virtual void visit(AstConst* nodep) override { UINFO(9, dbgState() << nodep << endl); if (m_graphing) { if (!m_alhs && nodep->num().hasZ()) m_tgraph.setTristate(nodep); @@ -672,7 +669,7 @@ class TristateVisitor : public TristateBaseVisitor { } } - virtual void visit(AstCond* nodep) VL_OVERRIDE { + virtual void visit(AstCond* nodep) override { if (m_graphing) { iterateChildren(nodep); if (m_alhs) { @@ -710,13 +707,13 @@ class TristateVisitor : public TristateBaseVisitor { AstNode* enp = new AstCond(nodep->fileline(), condp->cloneTree(false), en1p, en2p); UINFO(9, " newcond " << enp << endl); nodep->user1p(enp); // propagate up COND(lhsp->enable, rhsp->enable) - expr1p->user1p(NULL); - expr2p->user1p(NULL); + expr1p->user1p(nullptr); + expr2p->user1p(nullptr); } } } - virtual void visit(AstSel* nodep) VL_OVERRIDE { + virtual void visit(AstSel* nodep) override { if (m_graphing) { iterateChildren(nodep); if (m_alhs) { @@ -755,7 +752,7 @@ class TristateVisitor : public TristateBaseVisitor { } } - virtual void visit(AstConcat* nodep) VL_OVERRIDE { + virtual void visit(AstConcat* nodep) override { if (m_graphing) { iterateChildren(nodep); if (m_alhs) { @@ -771,7 +768,7 @@ class TristateVisitor : public TristateBaseVisitor { if (nodep->user1p()) { // Each half of the concat gets a select of the enable expression AstNode* enp = nodep->user1p(); - nodep->user1p(NULL); + nodep->user1p(nullptr); nodep->lhsp()->user1p(new AstSel(nodep->fileline(), enp->cloneTree(true), nodep->rhsp()->width(), nodep->lhsp()->width())); @@ -794,14 +791,14 @@ class TristateVisitor : public TristateBaseVisitor { AstNode* enp = new AstConcat(nodep->fileline(), en1p, en2p); UINFO(9, " newconc " << enp << endl); nodep->user1p(enp); // propagate up CONCAT(lhsp->enable, rhsp->enable) - expr1p->user1p(NULL); - expr2p->user1p(NULL); + expr1p->user1p(nullptr); + expr2p->user1p(nullptr); } } } } - virtual void visit(AstBufIf1* nodep) VL_OVERRIDE { + virtual void visit(AstBufIf1* nodep) override { // For BufIf1, the enable is the LHS expression iterateChildren(nodep); UINFO(9, dbgState() << nodep << endl); @@ -824,7 +821,7 @@ class TristateVisitor : public TristateBaseVisitor { } else { enp = expr1p; } - expr1p->user1p(NULL); + expr1p->user1p(nullptr); expr2p->user1p(enp); // Becomes new node // Don't need the BufIf any more, can just have the data direct nodep->replaceWith(expr2p); @@ -881,12 +878,12 @@ class TristateVisitor : public TristateBaseVisitor { new AstAnd(nodep->fileline(), en2p->cloneTree(false), subexpr2p))); UINFO(9, " neweqn " << enp << endl); nodep->user1p(enp); - expr1p->user1p(NULL); - expr2p->user1p(NULL); + expr1p->user1p(nullptr); + expr2p->user1p(nullptr); } } - virtual void visit(AstAnd* nodep) VL_OVERRIDE { visitAndOr(nodep, true); } - virtual void visit(AstOr* nodep) VL_OVERRIDE { visitAndOr(nodep, false); } + virtual void visit(AstAnd* nodep) override { visitAndOr(nodep, true); } + virtual void visit(AstOr* nodep) override { visitAndOr(nodep, false); } void visitAssign(AstNodeAssign* nodep) { if (m_graphing) { @@ -899,7 +896,7 @@ class TristateVisitor : public TristateBaseVisitor { m_alhs = false; associateLogic(nodep->rhsp(), nodep); associateLogic(nodep, nodep->lhsp()); - m_logicp = NULL; + m_logicp = nullptr; } else { if (nodep->user2() & U2_NONGRAPH) { return; // Iterated here, or created assignment to ignore @@ -914,7 +911,7 @@ class TristateVisitor : public TristateBaseVisitor { // the appropriate output signal's VarRef. if (nodep->rhsp()->user1p()) { nodep->lhsp()->user1p(nodep->rhsp()->user1p()); - nodep->rhsp()->user1p(NULL); + nodep->rhsp()->user1p(nullptr); UINFO(9, " enp<-rhs " << nodep->lhsp()->user1p() << endl); m_tgraph.didProcess(nodep); } @@ -923,8 +920,8 @@ class TristateVisitor : public TristateBaseVisitor { m_alhs = false; } } - virtual void visit(AstAssignW* nodep) VL_OVERRIDE { visitAssign(nodep); } - virtual void visit(AstAssign* nodep) VL_OVERRIDE { visitAssign(nodep); } + virtual void visit(AstAssignW* nodep) override { visitAssign(nodep); } + virtual void visit(AstAssign* nodep) override { visitAssign(nodep); } void visitCaseEq(AstNodeBiop* nodep, bool neq) { if (m_graphing) { @@ -946,7 +943,7 @@ class TristateVisitor : public TristateBaseVisitor { FileLine* fl = nodep->fileline(); V3Number oneIfEn = VN_CAST(constp->user1p(), Const) ->num(); // visit(AstConst) already split into en/ones - V3Number oneIfEnOne = constp->num(); + const V3Number& oneIfEnOne = constp->num(); AstVar* envarp = getCreateEnVarp(varrefp->varp()); AstNode* newp = new AstLogAnd( fl, new AstEq(fl, new AstConst(fl, oneIfEn), new AstVarRef(fl, envarp, false)), @@ -976,14 +973,14 @@ class TristateVisitor : public TristateBaseVisitor { return; } } - virtual void visit(AstEqCase* nodep) VL_OVERRIDE { visitCaseEq(nodep, false); } - virtual void visit(AstNeqCase* nodep) VL_OVERRIDE { visitCaseEq(nodep, true); } - virtual void visit(AstEqWild* nodep) VL_OVERRIDE { visitEqNeqWild(nodep); } - virtual void visit(AstNeqWild* nodep) VL_OVERRIDE { visitEqNeqWild(nodep); } + virtual void visit(AstEqCase* nodep) override { visitCaseEq(nodep, false); } + virtual void visit(AstNeqCase* nodep) override { visitCaseEq(nodep, true); } + virtual void visit(AstEqWild* nodep) override { visitEqNeqWild(nodep); } + virtual void visit(AstNeqWild* nodep) override { visitEqNeqWild(nodep); } - virtual void visit(AstPull* nodep) VL_OVERRIDE { + virtual void visit(AstPull* nodep) override { UINFO(9, dbgState() << nodep << endl); - AstVarRef* varrefp = NULL; + AstVarRef* varrefp = nullptr; if (VN_IS(nodep->lhsp(), VarRef)) { varrefp = VN_CAST(nodep->lhsp(), VarRef); } else if (VN_IS(nodep->lhsp(), Sel) @@ -999,7 +996,7 @@ class TristateVisitor : public TristateBaseVisitor { m_logicp = nodep; m_tgraph.setTristate(nodep); associateLogic(nodep, varrefp->varp()); - m_logicp = NULL; + m_logicp = nullptr; } else { // Replace any pullup/pulldowns with assignw logic and set the // direction of the pull in the user3() data on the var. Given @@ -1027,7 +1024,7 @@ class TristateVisitor : public TristateBaseVisitor { associateLogic(nodep, nodep->exprp()); } iterateChildren(nodep); - m_logicp = NULL; + m_logicp = nullptr; } else { // All heavy lifting completed in graph visitor. if (nodep->exprp()) m_tgraph.didProcess(nodep); @@ -1056,7 +1053,7 @@ class TristateVisitor : public TristateBaseVisitor { // __out(to-resolver-only) // const inout Spec says illegal // const output Unsupported; Illegal? - virtual void visit(AstPin* nodep) VL_OVERRIDE { + virtual void visit(AstPin* nodep) override { if (m_graphing) { if (nodep->user2() & U2_GRAPHING) return; // This pin is already expanded nodep->user2(U2_GRAPHING); @@ -1119,8 +1116,8 @@ class TristateVisitor : public TristateBaseVisitor { if (debug() >= 9) enpinp->dumpTree(cout, "-pin-ena: "); } // Create new output pin - AstAssignW* outAssignp = NULL; // If reconnected, the related assignment - AstPin* outpinp = NULL; + AstAssignW* outAssignp = nullptr; // If reconnected, the related assignment + AstPin* outpinp = nullptr; AstVar* outModVarp = static_cast(nodep->modVarp()->user4p()); if (!outModVarp) { // At top, no need for __out as might be input only. Otherwise resolvable. @@ -1165,7 +1162,7 @@ class TristateVisitor : public TristateBaseVisitor { AstVarRef* exprrefp; // Tristate variable that the Pin's expression refers to if (!outAssignp) { if (!outpinp) { - exprrefp = NULL; // Primary input only + exprrefp = nullptr; // Primary input only } else { // pinReconnect should have converted this exprrefp = VN_CAST(outpinp->exprp(), VarRef); @@ -1215,7 +1212,7 @@ class TristateVisitor : public TristateBaseVisitor { } } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { UINFO(9, dbgState() << nodep << endl); if (m_graphing) { if (nodep->lvalue()) { @@ -1249,7 +1246,7 @@ class TristateVisitor : public TristateBaseVisitor { } } - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { iterateChildren(nodep); UINFO(9, dbgState() << nodep << endl); if (m_graphing) { @@ -1282,12 +1279,12 @@ class TristateVisitor : public TristateBaseVisitor { } } - virtual void visit(AstNodeModule* nodep) VL_OVERRIDE { + virtual void visit(AstNodeModule* nodep) override { UINFO(8, nodep << endl); - AstNodeModule* origModp = m_modp; - bool origGraphing = m_graphing; - int origUnique = m_unique; - VarMap origLhsmap = m_lhsmap; + VL_RESTORER(m_modp); + VL_RESTORER(m_graphing); + VL_RESTORER(m_unique); + VL_RESTORER(m_lhsmap); // Not preserved, needs pointer instead: TristateGraph origTgraph = m_tgraph; UASSERT_OBJ(m_tgraph.empty(), nodep, "Unsupported: NodeModule under NodeModule"); { @@ -1295,7 +1292,7 @@ class TristateVisitor : public TristateBaseVisitor { m_graphing = false; m_tgraph.clear(); m_unique = 0; - m_logicp = NULL; + m_logicp = nullptr; m_lhsmap.clear(); m_modp = nodep; // Walk the graph, finding all variables and tristate constructs @@ -1311,36 +1308,32 @@ class TristateVisitor : public TristateBaseVisitor { // Insert new logic for all tristates insertTristates(nodep); } - m_modp = origModp; - m_graphing = origGraphing; - m_unique = origUnique; - m_lhsmap = origLhsmap; m_tgraph.clear(); // Recursion not supported } - virtual void visit(AstClass* nodep) VL_OVERRIDE { + virtual void visit(AstClass* nodep) override { // don't deal with classes } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTask* nodep) override { // don't deal with functions } - virtual void visit(AstCaseItem* nodep) VL_OVERRIDE { + virtual void visit(AstCaseItem* nodep) override { // don't deal with casez compare '???? values iterateAndNextNull(nodep->bodysp()); } - virtual void visit(AstCell* nodep) VL_OVERRIDE { + virtual void visit(AstCell* nodep) override { m_cellp = nodep; m_alhs = false; iterateChildren(nodep); - m_cellp = NULL; + m_cellp = nullptr; } - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { iterateChildrenBackwards(nodep); } + virtual void visit(AstNetlist* nodep) override { iterateChildrenBackwards(nodep); } // Default: Just iterate - virtual void visit(AstNode* nodep) VL_OVERRIDE { + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); checkUnhandled(nodep); } @@ -1348,16 +1341,10 @@ class TristateVisitor : public TristateBaseVisitor { public: // CONSTRUCTORS explicit TristateVisitor(AstNode* nodep) { - m_graphing = false; - m_modp = NULL; - m_cellp = NULL; - m_unique = 0; - m_alhs = false; - m_logicp = NULL; m_tgraph.clear(); iterate(nodep); } - virtual ~TristateVisitor() { + virtual ~TristateVisitor() override { V3Stats::addStat("Tristate, Tristate resolved nets", m_statTriSigs); } }; diff --git a/src/V3Undriven.cpp b/src/V3Undriven.cpp index d0b48debc..01890983f 100644 --- a/src/V3Undriven.cpp +++ b/src/V3Undriven.cpp @@ -43,7 +43,7 @@ class UndrivenVarEntry { std::vector m_wholeFlags; // Used/Driven on whole vector std::vector m_bitFlags; // Used/Driven on each subbit - enum { FLAG_USED = 0, FLAG_DRIVEN = 1, FLAGS_PER_BIT = 2 }; + enum : uint8_t { FLAG_USED = 0, FLAG_DRIVEN = 1, FLAGS_PER_BIT = 2 }; VL_DEBUG_FUNC; // Declare debug() @@ -70,7 +70,7 @@ private: bool drivenFlag(int bit) const { return m_wholeFlags[FLAG_DRIVEN] || m_bitFlags[bit * FLAGS_PER_BIT + FLAG_DRIVEN]; } - enum BitNamesWhich { BN_UNUSED, BN_UNDRIVEN, BN_BOTH }; + enum BitNamesWhich : uint8_t { BN_UNUSED, BN_UNDRIVEN, BN_BOTH }; string bitNames(BitNamesWhich which) { string bits; bool prev = false; @@ -238,11 +238,11 @@ private: // STATE std::vector m_entryps[3]; // Nodes to delete when we are finished - bool m_inBBox; // In black box; mark as driven+used - bool m_inContAssign; // In continuous assignment - bool m_inProcAssign; // In procedural assignment - AstNodeFTask* m_taskp; // Current task - AstAlways* m_alwaysCombp; // Current always if combo, otherwise NULL + bool m_inBBox = false; // In black box; mark as driven+used + bool m_inContAssign = false; // In continuous assignment + bool m_inProcAssign = false; // In procedural assignment + AstNodeFTask* m_taskp = nullptr; // Current task + AstAlways* m_alwaysCombp = nullptr; // Current always if combo, otherwise nullptr // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -282,7 +282,7 @@ private: } // VISITORS - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { for (int usr = 1; usr < (m_alwaysCombp ? 3 : 2); ++usr) { // For assigns and non-combo always, do just usr==1, to look // for module-wide undriven etc. @@ -303,15 +303,15 @@ private: // Discover variables used in bit definitions, etc iterateChildren(nodep); } - virtual void visit(AstArraySel* nodep) VL_OVERRIDE { + virtual void visit(AstArraySel* nodep) override { // Arrays are rarely constant assigned, so for now we punt and do all entries iterateChildren(nodep); } - virtual void visit(AstSliceSel* nodep) VL_OVERRIDE { + virtual void visit(AstSliceSel* nodep) override { // Arrays are rarely constant assigned, so for now we punt and do all entries iterateChildren(nodep); } - virtual void visit(AstSel* nodep) VL_OVERRIDE { + virtual void visit(AstSel* nodep) override { AstNodeVarRef* varrefp = VN_CAST(nodep->fromp(), NodeVarRef); AstConst* constp = VN_CAST(nodep->lsbp(), Const); if (varrefp && constp && !constp->num().isFourState()) { @@ -334,7 +334,7 @@ private: iterateChildren(nodep); } } - virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstNodeVarRef* nodep) override { // Any variable if (nodep->lvalue() && !VN_IS(nodep, VarXRef)) { // Ignore interface variables and similar ugly items @@ -369,94 +369,79 @@ private: } // Don't know what black boxed calls do, assume in+out - virtual void visit(AstSysIgnore* nodep) VL_OVERRIDE { - bool prevMark = m_inBBox; - m_inBBox = true; - iterateChildren(nodep); - m_inBBox = prevMark; + virtual void visit(AstSysIgnore* nodep) override { + VL_RESTORER(m_inBBox); + { + m_inBBox = true; + iterateChildren(nodep); + } } - virtual void visit(AstAssign* nodep) VL_OVERRIDE { - bool prevProc = m_inProcAssign; + virtual void visit(AstAssign* nodep) override { + VL_RESTORER(m_inProcAssign); { m_inProcAssign = true; iterateChildren(nodep); } - m_inProcAssign = prevProc; } - virtual void visit(AstAssignDly* nodep) VL_OVERRIDE { - bool prevProc = m_inProcAssign; + virtual void visit(AstAssignDly* nodep) override { + VL_RESTORER(m_inProcAssign); { m_inProcAssign = true; iterateChildren(nodep); } - m_inProcAssign = prevProc; } - virtual void visit(AstAssignW* nodep) VL_OVERRIDE { - bool prevCont = m_inContAssign; + virtual void visit(AstAssignW* nodep) override { + VL_RESTORER(m_inContAssign); { m_inContAssign = true; iterateChildren(nodep); } - m_inContAssign = prevCont; } - virtual void visit(AstAlways* nodep) VL_OVERRIDE { - AstAlways* prevAlwp = m_alwaysCombp; + virtual void visit(AstAlways* nodep) override { + VL_RESTORER(m_alwaysCombp); { AstNode::user2ClearTree(); if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) UINFO(9, " " << nodep << endl); if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) { m_alwaysCombp = nodep; } else { - m_alwaysCombp = NULL; + m_alwaysCombp = nullptr; } iterateChildren(nodep); if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) UINFO(9, " Done " << nodep << endl); } - m_alwaysCombp = prevAlwp; } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { - AstNodeFTask* prevTaskp = m_taskp; - m_taskp = nodep; - iterateChildren(nodep); - m_taskp = prevTaskp; + virtual void visit(AstNodeFTask* nodep) override { + VL_RESTORER(m_taskp); + { + m_taskp = nodep; + iterateChildren(nodep); + } } // Until we support tables, primitives will have undriven and unused I/Os - virtual void visit(AstPrimitive*) VL_OVERRIDE {} + virtual void visit(AstPrimitive*) override {} // Coverage artifacts etc shouldn't count as a sink - virtual void visit(AstCoverDecl*) VL_OVERRIDE {} - virtual void visit(AstCoverInc*) VL_OVERRIDE {} - virtual void visit(AstCoverToggle*) VL_OVERRIDE {} - virtual void visit(AstTraceDecl*) VL_OVERRIDE {} - virtual void visit(AstTraceInc*) VL_OVERRIDE {} + virtual void visit(AstCoverDecl*) override {} + virtual void visit(AstCoverInc*) override {} + virtual void visit(AstCoverToggle*) override {} + virtual void visit(AstTraceDecl*) override {} + virtual void visit(AstTraceInc*) override {} // iterate - virtual void visit(AstConst* nodep) VL_OVERRIDE {} - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstConst* nodep) override {} + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - explicit UndrivenVisitor(AstNetlist* nodep) { - m_inBBox = false; - m_inContAssign = false; - m_inProcAssign = false; - m_taskp = NULL; - m_alwaysCombp = NULL; - iterate(nodep); - } - virtual ~UndrivenVisitor() { - for (std::vector::iterator it = m_entryps[1].begin(); - it != m_entryps[1].end(); ++it) { - (*it)->reportViolations(); - } + explicit UndrivenVisitor(AstNetlist* nodep) { iterate(nodep); } + virtual ~UndrivenVisitor() override { + for (UndrivenVarEntry* ip : m_entryps[1]) ip->reportViolations(); for (int usr = 1; usr < 3; ++usr) { - for (std::vector::iterator it = m_entryps[usr].begin(); - it != m_entryps[usr].end(); ++it) { - delete (*it); - } + for (UndrivenVarEntry* ip : m_entryps[usr]) delete ip; } } }; diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 3ebaa05ec..15e9a199b 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -52,11 +52,11 @@ private: AstUser2InUse m_inuser2; // STATE - AstNodeModule* m_modp; // Current module - bool m_constXCvt; // Convert X's + AstNodeModule* m_modp = nullptr; // Current module + AstAssignW* m_assignwp = nullptr; // Current assignment + AstAssignDly* m_assigndlyp = nullptr; // Current assignment + bool m_constXCvt = false; // Convert X's VDouble0 m_statUnkVars; // Statistic tracking - AstAssignW* m_assignwp; // Current assignment - AstAssignDly* m_assigndlyp; // Current assignment // METHODS VL_DEBUG_FUNC; // Declare debug() @@ -82,9 +82,9 @@ private: // of multiple statements. Perhaps someday make all wassigns into always's? UINFO(5, " IM_WireRep " << m_assignwp << endl); m_assignwp->convertToAlways(); - VL_DO_CLEAR(pushDeletep(m_assignwp), m_assignwp = NULL); + VL_DO_CLEAR(pushDeletep(m_assignwp), m_assignwp = nullptr); } - bool needDly = (m_assigndlyp != NULL); + bool needDly = (m_assigndlyp != nullptr); if (m_assigndlyp) { // Delayed assignments become normal assignments, // then the temp created becomes the delayed assignment @@ -92,7 +92,7 @@ private: m_assigndlyp->lhsp()->unlinkFrBackWithNext(), m_assigndlyp->rhsp()->unlinkFrBackWithNext()); m_assigndlyp->replaceWith(newp); - VL_DO_CLEAR(pushDeletep(m_assigndlyp), m_assigndlyp = NULL); + VL_DO_CLEAR(pushDeletep(m_assigndlyp), m_assigndlyp = nullptr); } AstNode* prep = nodep; @@ -125,7 +125,7 @@ private: new AstAssignDly(fl, prep, new AstVarRef(fl, varp, false))) : static_cast( new AstAssign(fl, prep, new AstVarRef(fl, varp, false)))), - NULL); + nullptr); newp->branchPred(VBranchPred::BP_LIKELY); if (debug() >= 9) newp->dumpTree(cout, " _new: "); abovep->addNextStmt(newp, abovep); @@ -134,33 +134,32 @@ 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_constXCvt = true; iterateChildren(nodep); } - m_modp = origModp; } - virtual void visit(AstAssignDly* nodep) VL_OVERRIDE { + virtual void visit(AstAssignDly* nodep) override { m_assigndlyp = nodep; VL_DO_DANGLING(iterateChildren(nodep), nodep); // May delete nodep. - m_assigndlyp = NULL; + m_assigndlyp = nullptr; } - virtual void visit(AstAssignW* nodep) VL_OVERRIDE { + virtual void visit(AstAssignW* nodep) override { m_assignwp = nodep; VL_DO_DANGLING(iterateChildren(nodep), nodep); // May delete nodep. - m_assignwp = NULL; + m_assignwp = nullptr; } - virtual void visit(AstCaseItem* nodep) VL_OVERRIDE { + virtual void visit(AstCaseItem* nodep) override { m_constXCvt = false; // Avoid losing the X's in casex iterateAndNextNull(nodep->condsp()); m_constXCvt = true; iterateAndNextNull(nodep->bodysp()); } - virtual void visit(AstNodeDType* nodep) VL_OVERRIDE { + virtual void visit(AstNodeDType* nodep) override { m_constXCvt = false; // Avoid losing the X's in casex iterateChildren(nodep); m_constXCvt = true; @@ -237,11 +236,11 @@ private: } } - virtual void visit(AstEqCase* nodep) VL_OVERRIDE { visitEqNeqCase(nodep); } - virtual void visit(AstNeqCase* nodep) VL_OVERRIDE { visitEqNeqCase(nodep); } - virtual void visit(AstEqWild* nodep) VL_OVERRIDE { visitEqNeqWild(nodep); } - virtual void visit(AstNeqWild* nodep) VL_OVERRIDE { visitEqNeqWild(nodep); } - virtual void visit(AstIsUnknown* nodep) VL_OVERRIDE { + virtual void visit(AstEqCase* nodep) override { visitEqNeqCase(nodep); } + virtual void visit(AstNeqCase* nodep) override { visitEqNeqCase(nodep); } + virtual void visit(AstEqWild* nodep) override { visitEqNeqWild(nodep); } + virtual void visit(AstNeqWild* nodep) override { visitEqNeqWild(nodep); } + virtual void visit(AstIsUnknown* nodep) override { iterateChildren(nodep); // Ahh, we're two state, so this is easy UINFO(4, " ISUNKNOWN->0 " << nodep << endl); @@ -249,7 +248,7 @@ private: nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstConst* nodep) VL_OVERRIDE { + virtual void visit(AstConst* nodep) override { if (m_constXCvt && nodep->num().isFourState()) { UINFO(4, " CONST4 " << nodep << endl); if (debug() >= 9) nodep->dumpTree(cout, " Const_old: "); @@ -306,7 +305,7 @@ private: } } - virtual void visit(AstSel* nodep) VL_OVERRIDE { + virtual void visit(AstSel* nodep) override { iterateChildren(nodep); if (!nodep->user1SetOnce()) { // Guard against reading/writing past end of bit vector array @@ -353,7 +352,7 @@ private: // visit(AstSliceSel) not needed as its bounds are constant and checked // in V3Width. - virtual void visit(AstArraySel* nodep) VL_OVERRIDE { + virtual void visit(AstArraySel* nodep) override { iterateChildren(nodep); if (!nodep->user1SetOnce()) { if (debug() == 9) nodep->dumpTree(cout, "-in: "); @@ -424,18 +423,12 @@ private: } } //-------------------- - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS - explicit UnknownVisitor(AstNetlist* nodep) { - m_modp = NULL; - m_assigndlyp = NULL; - m_assignwp = NULL; - m_constXCvt = false; - iterate(nodep); - } - virtual ~UnknownVisitor() { // + explicit UnknownVisitor(AstNetlist* nodep) { iterate(nodep); } + virtual ~UnknownVisitor() override { // V3Stats::addStat("Unknowns, variables created", m_statUnkVars); } }; diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp index 795d5ec04..968a23c30 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -43,7 +43,7 @@ class UnrollVisitor : public AstNVisitor { private: // STATE AstVar* m_forVarp; // Iterator variable - AstVarScope* m_forVscp; // Iterator variable scope (NULL for generate pass) + AstVarScope* m_forVscp; // Iterator variable scope (nullptr for generate pass) AstConst* m_varValuep; // Current value of loop AstNode* m_ignoreIncp; // Increment node to ignore bool m_varModeCheck; // Just checking RHS assignments @@ -67,7 +67,7 @@ private: return false; } - int unrollCount() { + int unrollCount() const { return m_generate ? v3Global.opt.unrollCount() * 16 : v3Global.opt.unrollCount(); } @@ -144,7 +144,7 @@ private: iterateAndNextNull(bodysp); iterateAndNextNull(incp); m_varModeCheck = false; - m_ignoreIncp = NULL; + m_ignoreIncp = nullptr; if (m_varAssignHit) return cantUnroll(nodep, "genvar assigned *inside* loop"); // @@ -191,7 +191,7 @@ private: SimulateVisitor simvis; AstNode* clonep = nodep->cloneTree(true); simvis.mainCheckTree(clonep); - VL_DO_CLEAR(pushDeletep(clonep), clonep = NULL); + VL_DO_CLEAR(pushDeletep(clonep), clonep = nullptr); return simvis.optimizable(); } @@ -208,8 +208,8 @@ private: m_varModeReplace = false; clonep = tempp->stmtsp()->unlinkFrBackWithNext(); tempp->deleteTree(); - tempp = NULL; - VL_DO_CLEAR(pushDeletep(m_varValuep), m_varValuep = NULL); + tempp = nullptr; + VL_DO_CLEAR(pushDeletep(m_varValuep), m_varValuep = nullptr); } SimulateVisitor simvis; simvis.mainParamEmulate(clonep); @@ -242,12 +242,12 @@ private: bool countLoops(AstAssign* initp, AstNode* condp, AstNode* incp, int max, int& outLoopsr) { outLoopsr = 0; V3Number loopValue = V3Number(initp); - if (!simulateTree(initp->rhsp(), NULL, initp, loopValue)) { // + if (!simulateTree(initp->rhsp(), nullptr, initp, loopValue)) { // return false; } while (true) { V3Number res = V3Number(initp); - if (!simulateTree(condp, &loopValue, NULL, res)) { // + if (!simulateTree(condp, &loopValue, nullptr, res)) { // return false; } if (!res.isEqOne()) break; @@ -270,10 +270,10 @@ private: AstNode* incp, AstNode* bodysp) { UINFO(9, "forUnroller " << nodep << endl); V3Number loopValue = V3Number(nodep); - if (!simulateTree(initp->rhsp(), NULL, initp, loopValue)) { // + if (!simulateTree(initp->rhsp(), nullptr, initp, loopValue)) { // return false; } - AstNode* stmtsp = NULL; + AstNode* stmtsp = nullptr; if (initp) { initp->unlinkFrBack(); // Always a single statement; nextp() may be nodep // Don't add to list, we do it once, and setting loop index isn't @@ -294,14 +294,14 @@ private: // Mark variable to disable some later warnings m_forVarp->usedLoopIdx(true); - AstNode* newbodysp = NULL; + AstNode* newbodysp = nullptr; ++m_statLoops; if (stmtsp) { int times = 0; while (true) { UINFO(8, " Looping " << loopValue << endl); V3Number res = V3Number(nodep); - if (!simulateTree(condp, &loopValue, NULL, res)) { + if (!simulateTree(condp, &loopValue, nullptr, res)) { nodep->v3error("Loop unrolling failed."); return false; } @@ -328,7 +328,7 @@ private: string nname = m_beginName + "__BRA__" + index + "__KET__"; oneloopp = new AstBegin(oneloopp->fileline(), nname, oneloopp, true); } - VL_DO_CLEAR(pushDeletep(m_varValuep), m_varValuep = NULL); + VL_DO_CLEAR(pushDeletep(m_varValuep), m_varValuep = nullptr); if (newbodysp) { newbodysp->addNext(oneloopp); } else { @@ -356,8 +356,8 @@ private: } } if (!newbodysp) { // initp might have effects after the loop - newbodysp = initp; // Maybe NULL - initp = NULL; + newbodysp = initp; // Maybe nullptr + initp = nullptr; } // Replace the FOR() if (newbodysp) { @@ -373,7 +373,7 @@ private: return true; } - virtual void visit(AstWhile* nodep) VL_OVERRIDE { + virtual void visit(AstWhile* nodep) override { iterateChildren(nodep); if (m_varModeCheck || m_varModeReplace) { } else { @@ -383,12 +383,12 @@ private: } if (nodep->condp()) V3Const::constifyEdit(nodep->condp()); // condp may change // Grab initial value - AstNode* initp = NULL; // Should be statement before the while. + AstNode* initp = nullptr; // Should be statement before the while. if (nodep->backp()->nextp() == nodep) initp = nodep->backp(); if (initp) { VL_DO_DANGLING(V3Const::constifyEdit(initp), initp); } if (nodep->backp()->nextp() == nodep) initp = nodep->backp(); // Grab assignment - AstNode* incp = NULL; // Should be last statement + AstNode* incp = nullptr; // Should be last statement AstNode* bodysp = nodep->bodysp(); if (nodep->incsp()) V3Const::constifyEdit(nodep->incsp()); // cppcheck-suppress duplicateCondition @@ -400,7 +400,7 @@ private: // Again, as may have changed bodysp = nodep->bodysp(); for (incp = nodep->bodysp(); incp && incp->nextp(); incp = incp->nextp()) {} - if (incp == bodysp) bodysp = NULL; + if (incp == bodysp) bodysp = nullptr; } // And check it if (forUnrollCheck(nodep, initp, nodep->precondsp(), nodep->condp(), incp, bodysp)) { @@ -408,7 +408,7 @@ private: } } } - virtual void visit(AstGenFor* nodep) VL_OVERRIDE { + virtual void visit(AstGenFor* nodep) override { if (!m_generate || m_varModeReplace) { iterateChildren(nodep); } // else V3Param will recursively call each for loop to be unrolled for us @@ -427,15 +427,15 @@ private: // condition, but they'll become while's which can be // deleted by V3Const. VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); - } else if (forUnrollCheck(nodep, nodep->initsp(), NULL, nodep->condp(), nodep->incsp(), - nodep->bodysp())) { + } else if (forUnrollCheck(nodep, nodep->initsp(), nullptr, nodep->condp(), + nodep->incsp(), nodep->bodysp())) { VL_DO_DANGLING(pushDeletep(nodep), nodep); // Did replacement } else { nodep->v3error("For loop doesn't have genvar index, or is malformed"); } } } - virtual void visit(AstNodeFor* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFor* nodep) override { if (m_generate) { // Ignore for's when expanding genfor's iterateChildren(nodep); } else { @@ -443,7 +443,7 @@ private: } } - virtual void visit(AstVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstVarRef* nodep) override { if (m_varModeCheck && nodep->varp() == m_forVarp && nodep->varScopep() == m_forVscp && nodep->lvalue()) { UINFO(8, " Itervar assigned to: " << nodep << endl); @@ -460,7 +460,7 @@ private: //-------------------- // Default: Just iterate - virtual void visit(AstNode* nodep) VL_OVERRIDE { + virtual void visit(AstNode* nodep) override { if (m_varModeCheck && nodep == m_ignoreIncp) { // Ignore subtree that is the increment } else { @@ -471,16 +471,16 @@ private: public: // CONSTRUCTORS UnrollVisitor() { init(false, ""); } - virtual ~UnrollVisitor() { + virtual ~UnrollVisitor() override { V3Stats::addStatSum("Optimizations, Unrolled Loops", m_statLoops); V3Stats::addStatSum("Optimizations, Unrolled Iterations", m_statIters); } // METHODS void init(bool generate, const string& beginName) { - m_forVarp = NULL; - m_forVscp = NULL; - m_varValuep = NULL; - m_ignoreIncp = NULL; + m_forVarp = nullptr; + m_forVscp = nullptr; + m_varValuep = nullptr; + m_ignoreIncp = nullptr; m_varModeCheck = false; m_varModeReplace = false; m_varAssignHit = false; @@ -497,7 +497,7 @@ public: // Unroll class functions UnrollStateful::UnrollStateful() - : m_unrollerp(new UnrollVisitor) {} + : m_unrollerp{new UnrollVisitor} {} UnrollStateful::~UnrollStateful() { delete m_unrollerp; } void UnrollStateful::unrollGen(AstNodeFor* nodep, const string& beginName) { diff --git a/src/V3Waiver.cpp b/src/V3Waiver.cpp index cc62c823b..6cfa87687 100644 --- a/src/V3Waiver.cpp +++ b/src/V3Waiver.cpp @@ -30,7 +30,7 @@ void V3Waiver::addEntry(V3ErrorCode errorCode, const std::string& filename, } void V3Waiver::write(const std::string& filename) { - const vl_unique_ptr ofp(V3File::new_ofstream(filename)); + const std::unique_ptr ofp(V3File::new_ofstream(filename)); if (ofp->fail()) v3fatal("Can't write " << filename); *ofp << "// DESCR" @@ -47,10 +47,7 @@ void V3Waiver::write(const std::string& filename) { if (s_waiverList.size() == 0) { *ofp << "// No waivers needed - great!" << endl; } - for (V3Waiver::WaiverList::const_iterator it = s_waiverList.begin(); it != s_waiverList.end(); - ++it) { - *ofp << "// " << *it << std::endl << endl; - } + for (const auto& i : s_waiverList) *ofp << "// " << i << std::endl << endl; } V3Waiver::WaiverList V3Waiver::s_waiverList; diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 194e46c18..081dcbd10 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -81,12 +81,16 @@ //###################################################################### -enum Stage { PRELIM = 1, FINAL = 2, BOTH = 3 }; // Numbers are a bitmask <0>=prelim, <1>=final +enum Stage : uint8_t { + PRELIM = 1, + FINAL = 2, + BOTH = 3 +}; // Numbers are a bitmask <0>=prelim, <1>=final std::ostream& operator<<(std::ostream& str, const Stage& rhs) { return str << ("-PFB"[static_cast(rhs)]); } -enum Determ { +enum Determ : uint8_t { SELF, // Self-determined CONTEXT, // Context-determined ASSIGN // Assignment-like where sign comes from RHS only @@ -105,19 +109,19 @@ class WidthVP { Stage m_stage; // If true, report errors public: WidthVP(AstNodeDType* dtypep, Stage stage) - : m_dtypep(dtypep) - , m_stage(stage) { + : m_dtypep{dtypep} + , m_stage{stage} { // Prelim doesn't look at assignments, so shouldn't need a dtype, // however AstPattern uses them } WidthVP(Determ determ, Stage stage) - : m_dtypep(NULL) - , m_stage(stage) { + : m_dtypep{nullptr} + , m_stage{stage} { if (determ != SELF && stage != PRELIM) v3fatalSrc("Context-determined width request only allowed as prelim step"); } WidthVP* p() { return this; } - bool selfDtm() const { return m_dtypep == NULL; } + bool selfDtm() const { return m_dtypep == nullptr; } AstNodeDType* dtypep() const { // Detect where overrideDType is probably the intended call if (!m_dtypep) v3fatalSrc("Width dtype request on self-determined or preliminary VUP"); @@ -184,19 +188,20 @@ private: typedef std::map PatVecMap; // STATE - WidthVP* m_vup; // Current node state + WidthVP* m_vup = nullptr; // Current node state bool m_paramsOnly; // Computing parameter value; limit operation - AstRange* m_cellRangep; // Range for arrayed instantiations, NULL for normal instantiations - AstNodeFTask* m_ftaskp; // Current function/task - AstNodeProcedure* m_procedurep; // Current final/always - AstFunc* m_funcp; // Current function - AstAttrOf* m_attrp; // Current attribute + AstRange* m_cellRangep + = nullptr; // Range for arrayed instantiations, nullptr for normal instantiations + AstNodeFTask* m_ftaskp = nullptr; // Current function/task + AstNodeProcedure* m_procedurep = nullptr; // Current final/always + AstFunc* m_funcp = nullptr; // Current function + AstAttrOf* m_attrp = nullptr; // Current attribute bool m_doGenerate; // Do errors later inside generate statement - int m_dtTables; // Number of created data type tables + int m_dtTables = 0; // Number of created data type tables TableMap m_tableMap; // Created tables so can remove duplicates // ENUMS - enum ExtendRule { + enum ExtendRule : uint8_t { EXTEND_EXP, // Extend if expect sign and node signed, e.g. node=y in ADD(x,y), "x + y" EXTEND_ZERO, // Extend with zeros. e.g. node=y in EQ(x,y), "x == y" EXTEND_LHS, // Extend with sign if node signed. e.g. node=y in ASSIGN(y,x), "x = y" @@ -217,125 +222,125 @@ private: // _Ox=anything // Widths: 1 bit out, lhs 1 bit; Real: converts via compare with 0 - virtual void visit(AstLogNot* nodep) VL_OVERRIDE { visit_log_not(nodep); } + virtual void visit(AstLogNot* nodep) override { visit_log_not(nodep); } // Widths: 1 bit out, lhs 1 bit, rhs 1 bit; Real: converts via compare with 0 - virtual void visit(AstLogAnd* nodep) VL_OVERRIDE { visit_log_and_or(nodep); } - virtual void visit(AstLogOr* nodep) VL_OVERRIDE { visit_log_and_or(nodep); } - virtual void visit(AstLogEq* nodep) VL_OVERRIDE { + virtual void visit(AstLogAnd* nodep) override { visit_log_and_or(nodep); } + virtual void visit(AstLogOr* nodep) override { visit_log_and_or(nodep); } + virtual void visit(AstLogEq* nodep) override { // Conversion from real not in IEEE, but a fallout visit_log_and_or(nodep); } - virtual void visit(AstLogIf* nodep) VL_OVERRIDE { + virtual void visit(AstLogIf* nodep) override { // Conversion from real not in IEEE, but a fallout visit_log_and_or(nodep); } // Widths: 1 bit out, Any width lhs - virtual void visit(AstRedAnd* nodep) VL_OVERRIDE { visit_red_and_or(nodep); } - virtual void visit(AstRedOr* nodep) VL_OVERRIDE { visit_red_and_or(nodep); } - virtual void visit(AstRedXnor* nodep) VL_OVERRIDE { visit_red_and_or(nodep); } - virtual void visit(AstRedXor* nodep) VL_OVERRIDE { visit_red_and_or(nodep); } - virtual void visit(AstOneHot* nodep) VL_OVERRIDE { visit_red_and_or(nodep); } - virtual void visit(AstOneHot0* nodep) VL_OVERRIDE { visit_red_and_or(nodep); } - virtual void visit(AstIsUnknown* nodep) VL_OVERRIDE { + virtual void visit(AstRedAnd* nodep) override { visit_red_and_or(nodep); } + virtual void visit(AstRedOr* nodep) override { visit_red_and_or(nodep); } + virtual void visit(AstRedXnor* nodep) override { visit_red_and_or(nodep); } + virtual void visit(AstRedXor* nodep) override { visit_red_and_or(nodep); } + virtual void visit(AstOneHot* nodep) override { visit_red_and_or(nodep); } + virtual void visit(AstOneHot0* nodep) override { visit_red_and_or(nodep); } + virtual void visit(AstIsUnknown* nodep) override { visit_red_unknown(nodep); // Allow real } // These have different node types, as they operate differently // Must add to case statement below, // Widths: 1 bit out, lhs width == rhs width. real if lhs|rhs real - virtual void visit(AstEq* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstNeq* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstGt* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstGte* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstLt* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstLte* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstGtS* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstGteS* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstLtS* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstLteS* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstEqCase* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } - virtual void visit(AstNeqCase* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstEq* nodep) override { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstNeq* nodep) override { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstGt* nodep) override { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstGte* nodep) override { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstLt* nodep) override { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstLte* nodep) override { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstGtS* nodep) override { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstGteS* nodep) override { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstLtS* nodep) override { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstLteS* nodep) override { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstEqCase* nodep) override { visit_cmp_eq_gt(nodep, true); } + virtual void visit(AstNeqCase* nodep) override { visit_cmp_eq_gt(nodep, true); } // ... These comparisons don't allow reals - virtual void visit(AstEqWild* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, false); } - virtual void visit(AstNeqWild* nodep) VL_OVERRIDE { visit_cmp_eq_gt(nodep, false); } + virtual void visit(AstEqWild* nodep) override { visit_cmp_eq_gt(nodep, false); } + virtual void visit(AstNeqWild* nodep) override { visit_cmp_eq_gt(nodep, false); } // ... Real compares - virtual void visit(AstEqD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); } - virtual void visit(AstNeqD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); } - virtual void visit(AstLtD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); } - virtual void visit(AstLteD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); } - virtual void visit(AstGtD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); } - virtual void visit(AstGteD* nodep) VL_OVERRIDE { visit_cmp_real(nodep); } + virtual void visit(AstEqD* nodep) override { visit_cmp_real(nodep); } + virtual void visit(AstNeqD* nodep) override { visit_cmp_real(nodep); } + virtual void visit(AstLtD* nodep) override { visit_cmp_real(nodep); } + virtual void visit(AstLteD* nodep) override { visit_cmp_real(nodep); } + virtual void visit(AstGtD* nodep) override { visit_cmp_real(nodep); } + virtual void visit(AstGteD* nodep) override { visit_cmp_real(nodep); } // ... String compares - virtual void visit(AstEqN* nodep) VL_OVERRIDE { visit_cmp_string(nodep); } - virtual void visit(AstNeqN* nodep) VL_OVERRIDE { visit_cmp_string(nodep); } - virtual void visit(AstLtN* nodep) VL_OVERRIDE { visit_cmp_string(nodep); } - virtual void visit(AstLteN* nodep) VL_OVERRIDE { visit_cmp_string(nodep); } - virtual void visit(AstGtN* nodep) VL_OVERRIDE { visit_cmp_string(nodep); } - virtual void visit(AstGteN* nodep) VL_OVERRIDE { visit_cmp_string(nodep); } + virtual void visit(AstEqN* nodep) override { visit_cmp_string(nodep); } + virtual void visit(AstNeqN* nodep) override { visit_cmp_string(nodep); } + virtual void visit(AstLtN* nodep) override { visit_cmp_string(nodep); } + virtual void visit(AstLteN* nodep) override { visit_cmp_string(nodep); } + virtual void visit(AstGtN* nodep) override { visit_cmp_string(nodep); } + virtual void visit(AstGteN* nodep) override { visit_cmp_string(nodep); } // Widths: out width = lhs width = rhs width // Signed: Output signed iff LHS & RHS signed. // Real: Not allowed - virtual void visit(AstAnd* nodep) VL_OVERRIDE { visit_boolmath_and_or(nodep); } - virtual void visit(AstOr* nodep) VL_OVERRIDE { visit_boolmath_and_or(nodep); } - virtual void visit(AstXnor* nodep) VL_OVERRIDE { visit_boolmath_and_or(nodep); } - virtual void visit(AstXor* nodep) VL_OVERRIDE { visit_boolmath_and_or(nodep); } - virtual void visit(AstBufIf1* nodep) VL_OVERRIDE { + virtual void visit(AstAnd* nodep) override { visit_boolmath_and_or(nodep); } + virtual void visit(AstOr* nodep) override { visit_boolmath_and_or(nodep); } + virtual void visit(AstXnor* nodep) override { visit_boolmath_and_or(nodep); } + virtual void visit(AstXor* nodep) override { visit_boolmath_and_or(nodep); } + virtual void visit(AstBufIf1* nodep) override { visit_boolmath_and_or(nodep); } // Signed behavior changing in 3.814 // Width: Max(Lhs,Rhs) sort of. // Real: If either side real // Signed: If both sides real - virtual void visit(AstAdd* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, true); } - virtual void visit(AstSub* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, true); } - virtual void visit(AstDiv* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, true); } - virtual void visit(AstMul* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, true); } + virtual void visit(AstAdd* nodep) override { visit_add_sub_replace(nodep, true); } + virtual void visit(AstSub* nodep) override { visit_add_sub_replace(nodep, true); } + virtual void visit(AstDiv* nodep) override { visit_add_sub_replace(nodep, true); } + virtual void visit(AstMul* nodep) override { visit_add_sub_replace(nodep, true); } // These can't promote to real - virtual void visit(AstModDiv* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, false); } - virtual void visit(AstModDivS* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, false); } - virtual void visit(AstMulS* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, false); } - virtual void visit(AstDivS* nodep) VL_OVERRIDE { visit_add_sub_replace(nodep, false); } + virtual void visit(AstModDiv* nodep) override { visit_add_sub_replace(nodep, false); } + virtual void visit(AstModDivS* nodep) override { visit_add_sub_replace(nodep, false); } + virtual void visit(AstMulS* nodep) override { visit_add_sub_replace(nodep, false); } + virtual void visit(AstDivS* nodep) override { visit_add_sub_replace(nodep, false); } // Widths: out width = lhs width, but upper matters // Signed: Output signed iff LHS signed; unary operator // Unary promote to real - virtual void visit(AstNegate* nodep) VL_OVERRIDE { visit_negate_not(nodep, true); } + virtual void visit(AstNegate* nodep) override { visit_negate_not(nodep, true); } // Unary never real - virtual void visit(AstNot* nodep) VL_OVERRIDE { visit_negate_not(nodep, false); } + virtual void visit(AstNot* nodep) override { visit_negate_not(nodep, false); } // Real: inputs and output real - virtual void visit(AstAddD* nodep) VL_OVERRIDE { visit_real_add_sub(nodep); } - virtual void visit(AstSubD* nodep) VL_OVERRIDE { visit_real_add_sub(nodep); } - virtual void visit(AstDivD* nodep) VL_OVERRIDE { visit_real_add_sub(nodep); } - virtual void visit(AstMulD* nodep) VL_OVERRIDE { visit_real_add_sub(nodep); } - virtual void visit(AstPowD* nodep) VL_OVERRIDE { visit_real_add_sub(nodep); } - virtual void visit(AstNodeSystemBiop* nodep) VL_OVERRIDE { visit_real_add_sub(nodep); } + virtual void visit(AstAddD* nodep) override { visit_real_add_sub(nodep); } + virtual void visit(AstSubD* nodep) override { visit_real_add_sub(nodep); } + virtual void visit(AstDivD* nodep) override { visit_real_add_sub(nodep); } + virtual void visit(AstMulD* nodep) override { visit_real_add_sub(nodep); } + virtual void visit(AstPowD* nodep) override { visit_real_add_sub(nodep); } + virtual void visit(AstNodeSystemBiop* nodep) override { visit_real_add_sub(nodep); } // Real: Output real - virtual void visit(AstNegateD* nodep) VL_OVERRIDE { visit_real_neg_ceil(nodep); } - virtual void visit(AstNodeSystemUniop* nodep) VL_OVERRIDE { visit_real_neg_ceil(nodep); } + virtual void visit(AstNegateD* nodep) override { visit_real_neg_ceil(nodep); } + virtual void visit(AstNodeSystemUniop* nodep) override { visit_real_neg_ceil(nodep); } // Widths: out signed/unsigned width = lhs width, input un|signed - virtual void visit(AstSigned* nodep) VL_OVERRIDE { + virtual void visit(AstSigned* nodep) override { visit_signed_unsigned(nodep, VSigning::SIGNED); } - virtual void visit(AstUnsigned* nodep) VL_OVERRIDE { + virtual void visit(AstUnsigned* nodep) override { visit_signed_unsigned(nodep, VSigning::UNSIGNED); } // Widths: Output width from lhs, rhs<33 bits // Signed: If lhs signed - virtual void visit(AstShiftL* nodep) VL_OVERRIDE { visit_shift(nodep); } - virtual void visit(AstShiftR* nodep) VL_OVERRIDE { visit_shift(nodep); } + virtual void visit(AstShiftL* nodep) override { visit_shift(nodep); } + virtual void visit(AstShiftR* nodep) override { visit_shift(nodep); } // ShiftRS converts to ShiftR, but not vice-versa - virtual void visit(AstShiftRS* nodep) VL_OVERRIDE { visit_shift(nodep); } + virtual void visit(AstShiftRS* nodep) override { visit_shift(nodep); } //======== // Widths: Output real, input integer signed - virtual void visit(AstBitsToRealD* nodep) VL_OVERRIDE { visit_Or_Lu64(nodep); } + virtual void visit(AstBitsToRealD* nodep) override { visit_Or_Lu64(nodep); } // Widths: Output integer signed, input real - virtual void visit(AstRToIS* nodep) VL_OVERRIDE { visit_Os32_Lr(nodep); } - virtual void visit(AstRToIRoundS* nodep) VL_OVERRIDE { + virtual void visit(AstRToIS* nodep) override { visit_Os32_Lr(nodep); } + virtual void visit(AstRToIRoundS* nodep) override { // Only created here, size comes from upper expression if (m_vup->prelim()) { // First stage evaluation iterateCheckReal(nodep, "LHS", nodep->lhsp(), BOTH); @@ -344,11 +349,11 @@ private: } // Widths: Output integer unsigned, input real - virtual void visit(AstRealToBits* nodep) VL_OVERRIDE { visit_Ou64_Lr(nodep); } + virtual void visit(AstRealToBits* nodep) override { visit_Ou64_Lr(nodep); } // Output integer, input string - virtual void visit(AstLenN* nodep) VL_OVERRIDE { visit_Os32_string(nodep); } - virtual void visit(AstPutcN* nodep) VL_OVERRIDE { + virtual void visit(AstLenN* nodep) override { visit_Os32_string(nodep); } + virtual void visit(AstPutcN* nodep) override { // CALLER: str.putc() UASSERT_OBJ(nodep->rhsp() && nodep->thsp(), nodep, "For ternary ops only!"); if (m_vup && m_vup->prelim()) { @@ -360,7 +365,7 @@ private: // AstAssign } } - virtual void visit(AstGetcN* nodep) VL_OVERRIDE { + virtual void visit(AstGetcN* nodep) override { // CALLER: str.getc() UASSERT_OBJ(nodep->rhsp(), nodep, "For binary ops only!"); if (m_vup && m_vup->prelim()) { @@ -370,7 +375,7 @@ private: nodep->dtypeSetBitSized(8, VSigning::UNSIGNED); } } - virtual void visit(AstGetcRefN* nodep) VL_OVERRIDE { + virtual void visit(AstGetcRefN* nodep) override { // CALLER: str.getc() UASSERT_OBJ(nodep->rhsp(), nodep, "For binary ops only!"); if (m_vup && m_vup->prelim()) { @@ -380,7 +385,7 @@ private: nodep->dtypeSetBitSized(8, VSigning::UNSIGNED); } } - virtual void visit(AstSubstrN* nodep) VL_OVERRIDE { + virtual void visit(AstSubstrN* nodep) override { // CALLER: str.substr() UASSERT_OBJ(nodep->rhsp() && nodep->thsp(), nodep, "For ternary ops only!"); if (m_vup && m_vup->prelim()) { @@ -391,7 +396,7 @@ private: nodep->dtypeSetString(); } } - virtual void visit(AstCompareNN* nodep) VL_OVERRIDE { + virtual void visit(AstCompareNN* nodep) override { // CALLER: str.compare(), str.icompare() // Widths: 32 bit out UASSERT_OBJ(nodep->rhsp(), nodep, "For binary ops only!"); @@ -402,7 +407,7 @@ private: nodep->dtypeSetSigned32(); } } - virtual void visit(AstAtoN* nodep) VL_OVERRIDE { + virtual void visit(AstAtoN* nodep) override { // CALLER: str.atobin(), atoi(), atohex(), atooct(), atoreal() // Width: 64bit floating point for atoreal(), 32bit out for the others if (m_vup->prelim()) { @@ -417,14 +422,14 @@ private: } // Widths: Constant, terminal - virtual void visit(AstTime* nodep) VL_OVERRIDE { nodep->dtypeSetUInt64(); } - virtual void visit(AstTimeD* nodep) VL_OVERRIDE { nodep->dtypeSetDouble(); } - virtual void visit(AstTestPlusArgs* nodep) VL_OVERRIDE { nodep->dtypeSetSigned32(); } - virtual void visit(AstScopeName* nodep) VL_OVERRIDE { + virtual void visit(AstTime* nodep) override { nodep->dtypeSetUInt64(); } + virtual void visit(AstTimeD* nodep) override { nodep->dtypeSetDouble(); } + virtual void visit(AstTestPlusArgs* nodep) override { nodep->dtypeSetSigned32(); } + virtual void visit(AstScopeName* nodep) override { nodep->dtypeSetUInt64(); // A pointer, but not that it matters } - virtual void visit(AstNodeCond* nodep) VL_OVERRIDE { + virtual void visit(AstNodeCond* nodep) override { // op = cond ? expr1 : expr2 // See IEEE-2012 11.4.11 and Table 11-21. // LHS is self-determined @@ -465,7 +470,7 @@ private: EXTEND_EXP); } } - virtual void visit(AstConcat* nodep) VL_OVERRIDE { + virtual void visit(AstConcat* nodep) override { // Real: Not allowed (assumed) // Signed: unsigned output, input either (assumed) // IEEE-2012 Table 11-21, and 11.8.1: @@ -519,7 +524,7 @@ private: } } } - virtual void visit(AstConcatN* nodep) VL_OVERRIDE { + virtual void visit(AstConcatN* nodep) override { // String concatenate. // Already did AstConcat simplifications if (m_vup->prelim()) { @@ -535,7 +540,7 @@ private: } } } - virtual void visit(AstDelay* nodep) VL_OVERRIDE { + virtual void visit(AstDelay* nodep) override { if (VN_IS(m_procedurep, Final)) { nodep->v3error("Delays are not legal in final blocks (IEEE 1800-2017 9.2.3)"); VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); @@ -550,16 +555,21 @@ private: nodep->v3warn(STMTDLY, "Unsupported: Ignoring delay on this delayed statement."); VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); } - virtual void visit(AstFork* nodep) VL_OVERRIDE { + virtual void visit(AstFork* nodep) override { if (VN_IS(m_ftaskp, Func) && !nodep->joinType().joinNone()) { nodep->v3error("Only fork .. join_none is legal in functions. " "(IEEE 1800-2017 13.4.4)"); VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); return; } - if (v3Global.opt.bboxUnsup()) { - AstBegin* newp - = new AstBegin(nodep->fileline(), nodep->name(), nodep->stmtsp()->unlinkFrBack()); + if (v3Global.opt.bboxUnsup() + // With no statements, begin is identical + || !nodep->stmtsp() + // With one statement, a begin block does as good as a fork/join or join_any + || (!nodep->stmtsp()->nextp() && !nodep->joinType().joinNone())) { + AstNode* stmtsp = nullptr; + if (nodep->stmtsp()) stmtsp = nodep->stmtsp()->unlinkFrBack(); + AstBegin* newp = new AstBegin{nodep->fileline(), nodep->name(), stmtsp}; nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } else { @@ -567,27 +577,27 @@ private: // TBD might support only normal join, if so complain about other join flavors } } - virtual void visit(AstDisableFork* nodep) VL_OVERRIDE { + virtual void visit(AstDisableFork* nodep) override { nodep->v3warn(E_UNSUPPORTED, "Unsupported: disable fork statements"); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstWaitFork* nodep) VL_OVERRIDE { + virtual void visit(AstWaitFork* nodep) override { nodep->v3warn(E_UNSUPPORTED, "Unsupported: wait fork statements"); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } - virtual void visit(AstToLowerN* nodep) VL_OVERRIDE { + virtual void visit(AstToLowerN* nodep) override { if (m_vup->prelim()) { iterateCheckString(nodep, "LHS", nodep->lhsp(), BOTH); nodep->dtypeSetString(); } } - virtual void visit(AstToUpperN* nodep) VL_OVERRIDE { + virtual void visit(AstToUpperN* nodep) override { if (m_vup->prelim()) { iterateCheckString(nodep, "LHS", nodep->lhsp(), BOTH); nodep->dtypeSetString(); } } - virtual void visit(AstReplicate* nodep) VL_OVERRIDE { + virtual void visit(AstReplicate* nodep) override { // IEEE-2012 Table 11-21: // LHS, RHS is self-determined // width: value(LHS) * width(RHS) @@ -634,7 +644,7 @@ private: } } } - virtual void visit(AstReplicateN* nodep) VL_OVERRIDE { + virtual void visit(AstReplicateN* nodep) override { // Replicate with string if (m_vup->prelim()) { iterateCheckString(nodep, "LHS", nodep->lhsp(), BOTH); @@ -661,7 +671,7 @@ private: } } } - virtual void visit(AstNodeStream* nodep) VL_OVERRIDE { + virtual void visit(AstNodeStream* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH); iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH); @@ -694,7 +704,7 @@ private: } } } - virtual void visit(AstRange* nodep) VL_OVERRIDE { + virtual void visit(AstRange* nodep) override { // Real: Not allowed // Signed: unsigned output, input either // Convert all range values to constants @@ -730,7 +740,7 @@ private: } } - virtual void visit(AstSel* nodep) VL_OVERRIDE { + virtual void visit(AstSel* nodep) override { // Signed: always unsigned; Real: Not allowed // LSB is self-determined (IEEE 2012 11.5.1) // We also use SELs to shorten a signed constant etc, in this case they are signed. @@ -837,7 +847,7 @@ private: } } - virtual void visit(AstArraySel* nodep) VL_OVERRIDE { + virtual void visit(AstArraySel* nodep) override { // Signed/Real: Output signed iff LHS signed/real; binary operator // Note by contrast, bit extract selects are unsigned // LSB is self-determined (IEEE 2012 11.5.1) @@ -899,7 +909,7 @@ private: } } - virtual void visit(AstAssocSel* nodep) VL_OVERRIDE { + virtual void visit(AstAssocSel* nodep) override { // Signed/Real: Output type based on array-declared type; binary operator if (m_vup->prelim()) { AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefp(); @@ -914,7 +924,7 @@ private: } } - virtual void visit(AstSliceSel* nodep) VL_OVERRIDE { + virtual void visit(AstSliceSel* nodep) override { // Always creates as output an unpacked array if (m_vup->prelim()) { userIterateAndNext(nodep->fromp(), WidthVP(SELF, BOTH).p()); @@ -936,17 +946,21 @@ private: if (!m_doGenerate) { // Must check bounds before adding a select that truncates the bound // Note we've already subtracted off LSB - if ((nodep->declRange().hi() > adtypep->declRange().hi()) - || nodep->declRange().lo() < adtypep->declRange().lo()) { + const int subtracted = adtypep->declRange().lo(); + // Add subtracted value to get the original range + const VNumRange declRange{nodep->declRange().hi() + subtracted, + nodep->declRange().lo() + subtracted, + nodep->declRange().littleEndian()}; + if ((declRange.hi() > adtypep->declRange().hi()) + || declRange.lo() < adtypep->declRange().lo()) { // Other simulators warn too - nodep->v3error("Slice selection index '" << nodep->declRange() << "'" + nodep->v3error("Slice selection index '" << declRange << "'" << " outside data type's '" << adtypep->declRange() << "'"); - } else if ((nodep->declRange().littleEndian() - != adtypep->declRange().littleEndian()) - && nodep->declRange().hi() != nodep->declRange().lo()) { + } else if ((declRange.littleEndian() != adtypep->declRange().littleEndian()) + && declRange.hi() != declRange.lo()) { nodep->v3error("Slice selection '" - << nodep->declRange() << "'" + << declRange << "'" << " has backward indexing versus data type's '" << adtypep->declRange() << "'"); } @@ -954,7 +968,7 @@ private: } } - virtual void visit(AstSelBit* nodep) VL_OVERRIDE { + virtual void visit(AstSelBit* nodep) override { // Just a quick check as after V3Param these nodes instead are AstSel's userIterateAndNext(nodep->fromp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel userIterateAndNext(nodep->rhsp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel @@ -962,13 +976,13 @@ private: userIterateAndNext(nodep->attrp(), WidthVP(SELF, BOTH).p()); AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp != nodep) { - nodep = NULL; + nodep = nullptr; userIterate(selp, m_vup); return; } nodep->v3fatalSrc("AstSelBit should disappear after widthSel"); } - virtual void visit(AstSelExtract* nodep) VL_OVERRIDE { + virtual void visit(AstSelExtract* nodep) override { // Just a quick check as after V3Param these nodes instead are AstSel's userIterateAndNext(nodep->fromp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel userIterateAndNext(nodep->rhsp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel @@ -976,46 +990,46 @@ private: userIterateAndNext(nodep->attrp(), WidthVP(SELF, BOTH).p()); AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp != nodep) { - nodep = NULL; + nodep = nullptr; userIterate(selp, m_vup); return; } nodep->v3fatalSrc("AstSelExtract should disappear after widthSel"); } - virtual void visit(AstSelPlus* nodep) VL_OVERRIDE { + virtual void visit(AstSelPlus* nodep) override { userIterateAndNext(nodep->fromp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel userIterateAndNext(nodep->rhsp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel userIterateAndNext(nodep->thsp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel userIterateAndNext(nodep->attrp(), WidthVP(SELF, BOTH).p()); AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp != nodep) { - nodep = NULL; + nodep = nullptr; userIterate(selp, m_vup); return; } nodep->v3fatalSrc("AstSelPlus should disappear after widthSel"); } - virtual void visit(AstSelMinus* nodep) VL_OVERRIDE { + virtual void visit(AstSelMinus* nodep) override { userIterateAndNext(nodep->fromp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel userIterateAndNext(nodep->rhsp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel userIterateAndNext(nodep->thsp(), WidthVP(CONTEXT, PRELIM).p()); // FINAL in AstSel userIterateAndNext(nodep->attrp(), WidthVP(SELF, BOTH).p()); AstNode* selp = V3Width::widthSelNoIterEdit(nodep); if (selp != nodep) { - nodep = NULL; + nodep = nullptr; userIterate(selp, m_vup); return; } nodep->v3fatalSrc("AstSelMinus should disappear after widthSel"); } - virtual void visit(AstExtend* nodep) VL_OVERRIDE { + virtual void visit(AstExtend* nodep) override { // Only created by this process, so we know width from here down is correct. } - virtual void visit(AstExtendS* nodep) VL_OVERRIDE { + virtual void visit(AstExtendS* nodep) override { // Only created by this process, so we know width from here down is correct. } - virtual void visit(AstConst* nodep) VL_OVERRIDE { + virtual void visit(AstConst* nodep) override { // The node got setup with the signed/real state of the node. // However a later operation may have changed the node->signed w/o changing // the number's sign. So we don't: nodep->dtypeChgSigned(nodep->num().isSigned()); @@ -1031,13 +1045,13 @@ private: // We don't size the constant until we commit the widths, as need parameters // to remain unsized, and numbers to remain unsized to avoid backp() warnings } - virtual void visit(AstFell* nodep) VL_OVERRIDE { + virtual void visit(AstFell* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH); nodep->dtypeSetLogicBool(); } } - virtual void visit(AstPast* nodep) VL_OVERRIDE { + virtual void visit(AstPast* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH); nodep->dtypeFrom(nodep->exprp()); @@ -1061,46 +1075,59 @@ private: } } } - virtual void visit(AstRose* nodep) VL_OVERRIDE { + virtual void visit(AstRose* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH); nodep->dtypeSetLogicBool(); } } - virtual void visit(AstSampled* nodep) VL_OVERRIDE { + virtual void visit(AstSampled* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH); nodep->dtypeFrom(nodep->exprp()); } } - virtual void visit(AstStable* nodep) VL_OVERRIDE { + virtual void visit(AstStable* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->exprp(), SELF, BOTH); nodep->dtypeSetLogicBool(); } } - virtual void visit(AstRand* nodep) VL_OVERRIDE { + virtual void visit(AstRand* nodep) override { if (m_vup->prelim()) { nodep->dtypeSetSigned32(); // Says the spec } } - virtual void visit(AstUnbounded* nodep) VL_OVERRIDE { + virtual void visit(AstURandom* nodep) override { + if (m_vup->prelim()) { + nodep->dtypeSetUInt32(); // Says the spec + } + } + virtual void visit(AstURandomRange* nodep) override { + if (m_vup->prelim()) { + nodep->dtypeSetUInt32(); // Says the spec + AstNodeDType* expDTypep = nodep->findUInt32DType(); + iterateCheck(nodep, "LHS", nodep->lhsp(), SELF, FINAL, expDTypep, EXTEND_EXP); + iterateCheck(nodep, "RHS", nodep->rhsp(), SELF, FINAL, expDTypep, EXTEND_EXP); + } + } + virtual void visit(AstUnbounded* nodep) override { nodep->dtypeSetSigned32(); // Used in int context if (!VN_IS(nodep->backp(), IsUnbounded) && !VN_IS(nodep->backp(), BracketArrayDType) && !(VN_IS(nodep->backp(), Var) && VN_CAST(nodep->backp(), Var)->isParam())) { nodep->v3warn(E_UNSUPPORTED, "Unsupported/illegal unbounded ('$') in this context."); } } - virtual void visit(AstIsUnbounded* nodep) VL_OVERRIDE { + virtual void visit(AstIsUnbounded* nodep) override { if (m_vup->prelim()) { userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); nodep->dtypeSetLogicBool(); } } - virtual void visit(AstUCFunc* nodep) VL_OVERRIDE { + virtual void visit(AstUCFunc* nodep) override { // Give it the size the user wants. if (m_vup && m_vup->prelim()) { nodep->dtypeSetLogicUnsized(32, 1, VSigning::UNSIGNED); // We don't care @@ -1115,13 +1142,13 @@ private: } } } - virtual void visit(AstCLog2* nodep) VL_OVERRIDE { + virtual void visit(AstCLog2* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH); nodep->dtypeSetSigned32(); } } - virtual void visit(AstPow* nodep) VL_OVERRIDE { + virtual void visit(AstPow* nodep) override { // Pow is special, output sign only depends on LHS sign, but // function result depends on both signs // RHS is self-determined (IEEE) @@ -1146,7 +1173,7 @@ private: nodep->dtypeFrom(expDTypep); // rhs already finalized in iterate_shift_prelim iterateCheck(nodep, "LHS", nodep->lhsp(), SELF, FINAL, nodep->dtypep(), EXTEND_EXP); - AstNode* newp = NULL; // No change + AstNode* newp = nullptr; // No change if (nodep->lhsp()->isSigned() && nodep->rhsp()->isSigned()) { newp = new AstPowSS(nodep->fileline(), nodep->lhsp()->unlinkFrBack(), nodep->rhsp()->unlinkFrBack()); @@ -1165,25 +1192,25 @@ private: } } } - virtual void visit(AstPowSU* nodep) VL_OVERRIDE { + virtual void visit(AstPowSU* nodep) override { // POWSU/SS/US only created here, dtype already determined, so // nothing to do in this function userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->rhsp(), WidthVP(SELF, BOTH).p()); } - virtual void visit(AstPowSS* nodep) VL_OVERRIDE { + virtual void visit(AstPowSS* nodep) override { // POWSU/SS/US only created here, dtype already determined, so // nothing to do in this function userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->rhsp(), WidthVP(SELF, BOTH).p()); } - virtual void visit(AstPowUS* nodep) VL_OVERRIDE { + virtual void visit(AstPowUS* nodep) override { // POWSU/SS/US only created here, dtype already determined, so // nothing to do in this function userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->rhsp(), WidthVP(SELF, BOTH).p()); } - virtual void visit(AstCountBits* nodep) VL_OVERRIDE { + virtual void visit(AstCountBits* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH); iterateCheckSizedSelf(nodep, "RHS", nodep->rhsp(), SELF, BOTH); @@ -1195,7 +1222,7 @@ private: VSigning::UNSIGNED); // Spec doesn't indicate if an integer } } - virtual void visit(AstCountOnes* nodep) VL_OVERRIDE { + virtual void visit(AstCountOnes* nodep) override { if (m_vup->prelim()) { iterateCheckSizedSelf(nodep, "LHS", nodep->lhsp(), SELF, BOTH); // If it's a 32 bit number, we need a 6 bit number as we need to return '32'. @@ -1204,12 +1231,12 @@ private: VSigning::UNSIGNED); // Spec doesn't indicate if an integer } } - virtual void visit(AstCvtPackString* nodep) VL_OVERRIDE { + virtual void visit(AstCvtPackString* nodep) override { // Opaque returns, so arbitrary userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); // Type set in constructor } - virtual void visit(AstTimeImport* nodep) VL_OVERRIDE { + virtual void visit(AstTimeImport* nodep) override { // LHS is a real number in seconds // Need to round to time units and precision userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); @@ -1224,8 +1251,15 @@ private: nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); } - virtual void visit(AstAttrOf* nodep) VL_OVERRIDE { - AstAttrOf* oldAttr = m_attrp; + virtual void visit(AstTimingControl* nodep) override { + nodep->v3warn(E_UNSUPPORTED, "Unsupported: timing control statement in this location\n" + << nodep->warnMore() + << "... Suggest have one timing control statement " + << "per procedure, at the top of the procedure"); + VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); + } + virtual void visit(AstAttrOf* nodep) override { + VL_RESTORER(m_attrp); m_attrp = nodep; userIterateAndNext(nodep->fromp(), WidthVP(SELF, BOTH).p()); if (nodep->dimp()) userIterateAndNext(nodep->dimp(), WidthVP(SELF, BOTH).p()); @@ -1259,7 +1293,7 @@ private: switch (nodep->attrType()) { case AstAttrType::DIM_SIZE: { AstNode* newp = new AstCMethodHard( - nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", NULL); + nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", nullptr); newp->dtypeSetSigned32(); newp->didWidth(true); newp->protect(false); @@ -1277,7 +1311,7 @@ private: case AstAttrType::DIM_RIGHT: case AstAttrType::DIM_HIGH: { AstNode* sizep = new AstCMethodHard( - nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", NULL); + nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", nullptr); sizep->dtypeSetSigned32(); sizep->didWidth(true); sizep->protect(false); @@ -1347,18 +1381,17 @@ private: break; } } - m_attrp = oldAttr; } - virtual void visit(AstPull* nodep) VL_OVERRIDE { + virtual void visit(AstPull* nodep) override { // May have select underneath, let seek natural size userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); } - virtual void visit(AstText* nodep) VL_OVERRIDE { + virtual void visit(AstText* nodep) override { // Only used in CStmts which don't care.... } // DTYPES - virtual void visit(AstNodeArrayDType* nodep) VL_OVERRIDE { + virtual void visit(AstNodeArrayDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed // Iterate into subDTypep() to resolve that type and update pointer. nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); @@ -1374,7 +1407,7 @@ private: } UINFO(4, "dtWidthed " << nodep << endl); } - virtual void visit(AstAssocArrayDType* nodep) VL_OVERRIDE { + virtual void visit(AstAssocArrayDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed // Iterate into subDTypep() to resolve that type and update pointer. nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); @@ -1382,7 +1415,7 @@ private: nodep->dtypep(nodep); // The array itself, not subDtype UINFO(4, "dtWidthed " << nodep << endl); } - virtual void visit(AstBracketArrayDType* nodep) VL_OVERRIDE { + virtual void visit(AstBracketArrayDType* nodep) override { // Type inserted only because parser didn't know elementsp() type // Resolve elementsp's type userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); @@ -1393,7 +1426,7 @@ private: AstNode* elementsp = nodep->elementsp()->unlinkFrBack(); AstNode* newp; if (VN_IS(elementsp, Unbounded)) { - newp = new AstQueueDType(nodep->fileline(), VFlagChildDType(), childp, NULL); + newp = new AstQueueDType(nodep->fileline(), VFlagChildDType(), childp, nullptr); VL_DO_DANGLING(elementsp->deleteTree(), elementsp); } else if (AstNodeDType* keyp = VN_CAST(elementsp, NodeDType)) { newp = new AstAssocArrayDType(nodep->fileline(), VFlagChildDType(), childp, keyp); @@ -1409,26 +1442,26 @@ private: VL_DO_DANGLING(nodep->deleteTree(), nodep); // Normally parent's iteration would cover this, but we might have entered by a specific // visit - VL_DO_DANGLING(userIterate(newp, NULL), newp); + VL_DO_DANGLING(userIterate(newp, nullptr), newp); } - virtual void visit(AstDynArrayDType* nodep) VL_OVERRIDE { + virtual void visit(AstDynArrayDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed // Iterate into subDTypep() to resolve that type and update pointer. nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); nodep->dtypep(nodep); // The array itself, not subDtype UINFO(4, "dtWidthed " << nodep << endl); } - virtual void visit(AstQueueDType* nodep) VL_OVERRIDE { + virtual void visit(AstQueueDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed // Iterate into subDTypep() to resolve that type and update pointer. nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); nodep->dtypep(nodep); // The array itself, not subDtype if (VN_IS(nodep->boundp(), Unbounded)) { - nodep->boundp()->unlinkFrBack()->deleteTree(); // NULL will represent unbounded + nodep->boundp()->unlinkFrBack()->deleteTree(); // nullptr will represent unbounded } UINFO(4, "dtWidthed " << nodep << endl); } - virtual void visit(AstUnsizedArrayDType* nodep) VL_OVERRIDE { + virtual void visit(AstUnsizedArrayDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed // Iterate into subDTypep() to resolve that type and update pointer. nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); @@ -1436,7 +1469,7 @@ private: nodep->dtypep(nodep); // The array itself, not subDtype UINFO(4, "dtWidthed " << nodep << endl); } - virtual void visit(AstBasicDType* nodep) VL_OVERRIDE { + virtual void visit(AstBasicDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed if (nodep->generic()) return; // Already perfect if (nodep->rangep()) { @@ -1459,16 +1492,16 @@ private: // dtype Instead for now doing this in V3WidthCommit UINFO(4, "dtWidthed " << nodep << endl); } - virtual void visit(AstConstDType* nodep) VL_OVERRIDE { + virtual void visit(AstConstDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed // Iterate into subDTypep() to resolve that type and update pointer. nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); - userIterateChildren(nodep, NULL); + userIterateChildren(nodep, nullptr); nodep->dtypep(nodep); // Should already be set, but be clear it's not the subDType nodep->widthFromSub(nodep->subDTypep()); UINFO(4, "dtWidthed " << nodep << endl); } - virtual void visit(AstRefDType* nodep) VL_OVERRIDE { + virtual void visit(AstRefDType* nodep) override { if (nodep->doingWidth()) { // Early exit if have circular parameter definition nodep->v3error("Typedef's type is circular: " << nodep->prettyName()); nodep->dtypeSetLogicBool(); @@ -1481,22 +1514,22 @@ private: // Type comes from expression's type userIterateAndNext(nodep->typeofp(), WidthVP(SELF, BOTH).p()); AstNode* typeofp = nodep->typeofp(); - nodep->typedefp(NULL); + nodep->typedefp(nullptr); nodep->refDTypep(typeofp->dtypep()); VL_DO_DANGLING(typeofp->unlinkFrBack()->deleteTree(), typeofp); // We had to use AstRefDType for this construct as pointers to this type // in type table are still correct (which they wouldn't be if we replaced the node) } - userIterateChildren(nodep, NULL); + userIterateChildren(nodep, nullptr); if (nodep->subDTypep()) { // Normally iterateEditMoveDTypep iterate would work, but the refs are under // the TypeDef which will upset iterateEditMoveDTypep as it can't find it under // this node's childDTypep - userIterate(nodep->subDTypep(), NULL); + userIterate(nodep->subDTypep(), nullptr); nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); - nodep->typedefp(NULL); // Note until line above subDTypep() may have followed this + nodep->typedefp(nullptr); // Note until line above subDTypep() may have followed this // Widths are resolved, but special iterate to check for recurstion - userIterate(nodep->subDTypep(), NULL); + userIterate(nodep->subDTypep(), nullptr); } // Effectively nodep->dtypeFrom(nodep->dtypeSkipRefp()); // But might be recursive, so instead manually recurse into the referenced type @@ -1506,25 +1539,25 @@ private: UINFO(4, "dtWidthed " << nodep << endl); nodep->doingWidth(false); } - virtual void visit(AstTypedef* nodep) VL_OVERRIDE { + virtual void visit(AstTypedef* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed nodep->dtypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); - userIterateChildren(nodep, NULL); + userIterateChildren(nodep, nullptr); } - virtual void visit(AstParamTypeDType* nodep) VL_OVERRIDE { + virtual void visit(AstParamTypeDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed nodep->dtypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); - userIterateChildren(nodep, NULL); + userIterateChildren(nodep, nullptr); nodep->widthFromSub(nodep->subDTypep()); } - virtual void visit(AstCastDynamic* nodep) VL_OVERRIDE { + virtual void visit(AstCastDynamic* nodep) override { nodep->v3warn(E_UNSUPPORTED, "Unsupported: $cast. Suggest try static cast."); AstNode* newp = new AstConst(nodep->fileline(), 1); newp->dtypeSetSigned32(); // Spec says integer return nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstCastParse* nodep) VL_OVERRIDE { + virtual void visit(AstCastParse* nodep) override { // nodep->dtp could be data type, or a primary_constant // Don't iterate lhsp, will deal with that once convert the type V3Const::constifyParamsEdit(nodep->dtp()); // itemp may change @@ -1541,7 +1574,7 @@ private: nodep->replaceWith(nodep->lhsp()->unlinkFrBack()); } } - virtual void visit(AstCast* nodep) VL_OVERRIDE { + virtual void visit(AstCast* nodep) override { nodep->dtypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); // if (debug()) nodep->dumpTree(cout, " CastPre: "); userIterateAndNext(nodep->lhsp(), WidthVP(SELF, PRELIM).p()); @@ -1588,7 +1621,7 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); // if (debug()) newp->dumpTree(cout, " CastOut: "); } - virtual void visit(AstCastSize* nodep) VL_OVERRIDE { + virtual void visit(AstCastSize* nodep) override { // IEEE: Signedness of result is same as self-determined signedness // However, the result is same as BITSEL, so we do not sign extend the LHS UASSERT_OBJ(VN_IS(nodep->rhsp(), Const), nodep, "Unsupported: Non-const cast of size"); @@ -1642,7 +1675,7 @@ private: } // if (debug()) nodep->dumpTree(cout, " CastSizeOut: "); } - virtual void visit(AstVar* nodep) VL_OVERRIDE { + virtual void visit(AstVar* nodep) override { // if (debug()) nodep->dumpTree(cout, " InitPre: "); // Must have deterministic constant width // We can't skip this step when width()!=0, as creating a AstVar @@ -1751,7 +1784,7 @@ private: nodep->didWidth(true); nodep->doingWidth(false); } - virtual void visit(AstNodeVarRef* nodep) VL_OVERRIDE { + virtual void visit(AstNodeVarRef* nodep) override { if (nodep->didWidth()) return; if (!nodep->varp()) { if (m_paramsOnly && VN_IS(nodep, VarXRef)) { @@ -1766,7 +1799,7 @@ private: } if (!nodep->varp()->didWidth()) { // Var hasn't been widthed, so make it so. - userIterate(nodep->varp(), NULL); + userIterate(nodep->varp(), nullptr); } // if (debug()>=9) { nodep->dumpTree(cout, " VRin "); // nodep->varp()->dumpTree(cout, " forvar "); } @@ -1779,7 +1812,7 @@ private: if (nodep->lvalue() && nodep->varp()->direction() == VDirection::CONSTREF) { nodep->v3error("Assigning to const ref variable: " << nodep->prettyNameQ()); } else if (nodep->lvalue() && nodep->varp()->isConst() && !m_paramsOnly - && !VN_IS(m_procedurep, Initial)) { + && (!m_ftaskp || !m_ftaskp->isConstructor()) && !VN_IS(m_procedurep, Initial)) { // Too loose, but need to allow our generated first assignment // Move this to a property of the AstInitial block nodep->v3error("Assigning to const variable: " << nodep->prettyNameQ()); @@ -1787,7 +1820,7 @@ private: nodep->didWidth(true); } - virtual void visit(AstEnumDType* nodep) VL_OVERRIDE { + virtual void visit(AstEnumDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed UINFO(5, " ENUMDTYPE " << nodep << endl); nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); @@ -1815,11 +1848,13 @@ private: // TODO IEEE says assigning sized number that is not same size as enum is illegal } if (!itemp->valuep()) { - if (num.isEqZero() && itemp != nodep->itemsp()) + if (num.isEqZero() && itemp != nodep->itemsp()) { itemp->v3error("Enum value illegally wrapped around (IEEE 1800-2017 6.19)"); - if (num.isFourState()) + } + if (num.isFourState()) { itemp->v3error("Enum value that is unassigned cannot follow value with X/Zs " "(IEEE 1800-2017 6.19)"); + } if (!nodep->dtypep()->basicp() && !nodep->dtypep()->basicp()->keyword().isIntNumeric()) { itemp->v3error("Enum names without values only allowed on numeric types"); @@ -1830,9 +1865,10 @@ private: AstConst* constp = VN_CAST(itemp->valuep(), Const); if (constp->num().isFourState() && nodep->dtypep()->basicp() - && !nodep->dtypep()->basicp()->isFourstate()) + && !nodep->dtypep()->basicp()->isFourstate()) { itemp->v3error("Enum value with X/Zs cannot be assigned to non-fourstate type " "(IEEE 1800-2017 6.19)"); + } num.opAssign(constp->num()); // Look for duplicates if (inits.find(num) != inits.end()) { // IEEE says illegal @@ -1848,7 +1884,7 @@ private: num.opAdd(one, constp->num()); } } - virtual void visit(AstEnumItem* nodep) VL_OVERRIDE { + virtual void visit(AstEnumItem* nodep) override { UINFO(5, " ENUMITEM " << nodep << endl); AstNodeDType* vdtypep = m_vup->dtypep(); UASSERT_OBJ(vdtypep, nodep, "ENUMITEM not under ENUM"); @@ -1862,7 +1898,7 @@ private: EXTEND_EXP); } } - virtual void visit(AstEnumItemRef* nodep) VL_OVERRIDE { + virtual void visit(AstEnumItemRef* nodep) override { if (!nodep->itemp()->didWidth()) { // We need to do the whole enum en-mass AstNode* enump = nodep->itemp(); @@ -1875,10 +1911,10 @@ private: } nodep->dtypeFrom(nodep->itemp()); } - virtual void visit(AstInitItem* nodep) VL_OVERRIDE { // + virtual void visit(AstInitItem* nodep) override { // userIterateChildren(nodep, m_vup); } - virtual void visit(AstInitArray* nodep) VL_OVERRIDE { + virtual void visit(AstInitArray* nodep) override { // InitArray has type of the array; children are array values if (m_vup->prelim()) { // First stage evaluation AstNodeDType* vdtypep = m_vup->dtypep(); @@ -1891,7 +1927,7 @@ private: } } } - virtual void visit(AstInside* nodep) VL_OVERRIDE { + virtual void visit(AstInside* nodep) override { userIterateAndNext(nodep->exprp(), WidthVP(CONTEXT, PRELIM).p()); for (AstNode *nextip, *itemp = nodep->itemsp(); itemp; itemp = nextip) { nextip = itemp->nextp(); // Prelim may cause the node to get replaced @@ -1915,7 +1951,7 @@ private: nodep->dtypeSetLogicBool(); if (debug() >= 9) nodep->dumpTree(cout, "-inside-in: "); // Now rip out the inside and replace with simple math - AstNode* newp = NULL; + AstNode* newp = nullptr; for (AstNode *nextip, *itemp = nodep->itemsp(); itemp; itemp = nextip) { nextip = itemp->nextp(); // Will be unlinking AstNode* inewp; @@ -1938,14 +1974,14 @@ private: nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } - virtual void visit(AstInsideRange* nodep) VL_OVERRIDE { + virtual void visit(AstInsideRange* nodep) override { // Just do each side; AstInside will rip these nodes out later userIterateAndNext(nodep->lhsp(), m_vup); userIterateAndNext(nodep->rhsp(), m_vup); nodep->dtypeFrom(nodep->lhsp()); } - virtual void visit(AstIfaceRefDType* nodep) VL_OVERRIDE { + virtual void visit(AstIfaceRefDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed UINFO(5, " IFACEREF " << nodep << endl); userIterateChildren(nodep, m_vup); @@ -1953,7 +1989,7 @@ private: nodep->widthForce(1, 1); // Not really relevant UINFO(4, "dtWidthed " << nodep << endl); } - virtual void visit(AstNodeUOrStructDType* nodep) VL_OVERRIDE { + virtual void visit(AstNodeUOrStructDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed UINFO(5, " NODECLASS " << nodep << endl); // if (debug() >= 9) nodep->dumpTree("-class-in--"); @@ -1963,7 +1999,7 @@ private: nodep->v3warn(UNPACKED, "Unsupported: --no-structs-packed"); } } - userIterateChildren(nodep, NULL); // First size all members + userIterateChildren(nodep, nullptr); // First size all members nodep->repairMemberCache(); // Determine bit assignments and width nodep->dtypep(nodep); @@ -1988,33 +2024,31 @@ private: nodep->widthForce(width, width); // Signing stays as-is, as parsed from declaration // if (debug() >= 9) nodep->dumpTree("-class-out-"); } - virtual void visit(AstClass* nodep) VL_OVERRIDE { + virtual void visit(AstClass* nodep) override { if (nodep->didWidthAndSet()) return; - userIterateChildren(nodep, NULL); // First size all members - if (nodep->isVirtual()) nodep->v3warn(E_UNSUPPORTED, "Unsupported: virtual class"); + userIterateChildren(nodep, nullptr); // First size all members nodep->repairCache(); } - virtual void visit(AstClassRefDType* nodep) VL_OVERRIDE { + virtual void visit(AstClassRefDType* nodep) override { if (nodep->didWidthAndSet()) return; // TODO this maybe eventually required to properly resolve members, // though causes problems with t_class_forward.v, so for now avoided - // userIterateChildren(nodep->classp(), NULL); + // userIterateChildren(nodep->classp(), nullptr); } - virtual void visit(AstClassExtends* nodep) VL_OVERRIDE { + virtual void visit(AstClassExtends* nodep) override { if (nodep->didWidthAndSet()) return; - nodep->v3warn(E_UNSUPPORTED, "Unsupported: class extends"); // Member/meth access breaks - VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); - // nodep->dtypep(iterateEditMoveDTypep(nodep)); // data_type '{ pattern } - // userIterateChildren(nodep, NULL); + if (VN_IS(nodep->childDTypep(), ClassRefDType)) { + nodep->dtypep(iterateEditMoveDTypep(nodep, nodep->childDTypep())); + } } - virtual void visit(AstMemberDType* nodep) VL_OVERRIDE { + virtual void visit(AstMemberDType* nodep) override { if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed // Iterate into subDTypep() to resolve that type and update pointer. nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); nodep->dtypep(nodep); // The member itself, not subDtype nodep->widthFromSub(nodep->subDTypep()); } - virtual void visit(AstMemberSel* nodep) VL_OVERRIDE { + virtual void visit(AstMemberSel* nodep) override { UINFO(5, " MEMBERSEL " << nodep << endl); if (debug() >= 9) nodep->dumpTree("-mbs-in: "); userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); @@ -2051,7 +2085,7 @@ private: // Method call on enum without following parenthesis, e.g. "ENUM.next" // Convert this into a method call, and let that visitor figure out what to do next AstNode* newp = new AstMethodCall(nodep->fileline(), nodep->fromp()->unlinkFrBack(), - nodep->name(), NULL); + nodep->name(), nullptr); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); userIterate(newp, m_vup); @@ -2072,7 +2106,7 @@ private: UASSERT_OBJ(first_classp, nodep, "Unlinked"); for (AstClass* classp = first_classp; classp;) { if (AstNode* foundp = classp->findMember(nodep->name())) return foundp; - classp = classp->extendsp() ? classp->extendsp()->classp() : NULL; + classp = classp->extendsp() ? classp->extendsp()->classp() : nullptr; } VSpellCheck speller; for (AstClass* classp = first_classp; classp;) { @@ -2081,14 +2115,14 @@ private: speller.pushCandidate(itemp->prettyName()); } } - classp = classp->extendsp() ? classp->extendsp()->classp() : NULL; + classp = classp->extendsp() ? classp->extendsp()->classp() : nullptr; } string suggest = speller.bestCandidateMsg(nodep->prettyName()); nodep->v3error( "Member " << nodep->prettyNameQ() << " not found in class " << first_classp->prettyNameQ() << "\n" << (suggest.empty() ? "" : nodep->fileline()->warnMore() + suggest)); - return NULL; // Caller handles error + return nullptr; // Caller handles error } bool memberSelStruct(AstMemberSel* nodep, AstNodeUOrStructDType* adtypep) { // Returns true if ok @@ -2116,12 +2150,12 @@ private: return false; } - virtual void visit(AstCMethodHard* nodep) VL_OVERRIDE { + virtual void visit(AstCMethodHard* nodep) override { // Never created before V3Width, so no need to redo it UASSERT_OBJ(nodep->dtypep(), nodep, "CMETHODCALLs should have already been sized"); } - virtual void visit(AstMethodCall* nodep) VL_OVERRIDE { + virtual void visit(AstMethodCall* nodep) override { UINFO(5, " METHODCALL " << nodep << endl); if (nodep->didWidth()) return; if (debug() >= 9) nodep->dumpTree("-mts-in: "); @@ -2134,7 +2168,7 @@ private: // Find the fromp dtype - should be a class UASSERT_OBJ(nodep->fromp() && nodep->fromp()->dtypep(), nodep, "Unsized expression"); AstNodeDType* fromDtp = nodep->fromp()->dtypep()->skipRefToEnump(); - AstBasicDType* basicp = fromDtp ? fromDtp->basicp() : NULL; + AstBasicDType* basicp = fromDtp ? fromDtp->basicp() : nullptr; UINFO(9, " from dt " << fromDtp << endl); if (AstEnumDType* adtypep = VN_CAST(fromDtp, EnumDType)) { methodCallEnum(nodep, adtypep); @@ -2193,7 +2227,7 @@ private: || nodep->name() == "first" // || nodep->name() == "last") { // Constant value - AstConst* newp = NULL; + AstConst* newp = nullptr; methodOkArguments(nodep, 0, 0); if (nodep->name() == "num") { int items = 0; @@ -2291,12 +2325,12 @@ private: } } void methodCallAssoc(AstMethodCall* nodep, AstAssocArrayDType* adtypep) { - AstCMethodHard* newp = NULL; + AstCMethodHard* newp = nullptr; if (nodep->name() == "num" // function int num() || nodep->name() == "size") { methodOkArguments(nodep, 0, 0); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", - NULL); // So don't need num() + nullptr); // So don't need num() newp->dtypeSetSigned32(); newp->didWidth(true); newp->protect(false); @@ -2324,10 +2358,10 @@ private: newp->didWidth(true); } else if (nodep->name() == "delete") { // function void delete([input integer index]) methodOkArguments(nodep, 0, 1); - methodCallLValue(nodep, nodep->fromp(), true); + methodCallLValueRecurse(nodep, nodep->fromp(), true); if (!nodep->pinsp()) { newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), - "clear", NULL); + "clear", nullptr); newp->protect(false); newp->makeStatement(); } else { @@ -2353,37 +2387,41 @@ private: VL_DANGLING(index_exprp); // May have been edited return VN_CAST(nodep->pinsp(), Arg)->exprp(); } - void methodCallLValue(AstMethodCall* nodep, AstNode* childp, bool lvalue) { - AstNodeVarRef* varrefp = VN_CAST(childp, NodeVarRef); - if (!varrefp) { + void methodCallLValueRecurse(AstMethodCall* nodep, AstNode* childp, bool lvalue) { + if (AstNodeVarRef* varrefp = VN_CAST(childp, NodeVarRef)) { + if (lvalue) varrefp->lvalue(true); + } else if (AstMemberSel* ichildp = VN_CAST(childp, MemberSel)) { + methodCallLValueRecurse(nodep, ichildp->fromp(), lvalue); + } else if (AstNodeSel* ichildp = VN_CAST(childp, NodeSel)) { + methodCallLValueRecurse(nodep, ichildp->fromp(), lvalue); + } else { + UINFO(1, " Related node: " << childp << endl); nodep->v3warn(E_UNSUPPORTED, "Unsupported: Non-variable on LHS of built-in method '" << nodep->prettyName() << "'"); - } else { - if (lvalue) varrefp->lvalue(true); } } void methodCallDyn(AstMethodCall* nodep, AstDynArrayDType* adtypep) { - AstCMethodHard* newp = NULL; + AstCMethodHard* newp = nullptr; if (nodep->name() == "at") { // Created internally for [] methodOkArguments(nodep, 1, 1); - methodCallLValue(nodep, nodep->fromp(), true); + methodCallLValueRecurse(nodep, nodep->fromp(), true); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "at", - NULL); + nullptr); newp->dtypeFrom(adtypep->subDTypep()); newp->protect(false); newp->didWidth(true); } else if (nodep->name() == "size") { methodOkArguments(nodep, 0, 0); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", - NULL); + nullptr); newp->dtypeSetSigned32(); newp->didWidth(true); newp->protect(false); } else if (nodep->name() == "delete") { // function void delete() methodOkArguments(nodep, 0, 0); - methodCallLValue(nodep, nodep->fromp(), true); + methodCallLValueRecurse(nodep, nodep->fromp(), true); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "clear", - NULL); + nullptr); newp->makeStatement(); } else { nodep->v3warn(E_UNSUPPORTED, "Unsupported/unknown built-in dynamic array method " @@ -2396,12 +2434,12 @@ private: } } void methodCallQueue(AstMethodCall* nodep, AstQueueDType* adtypep) { - AstCMethodHard* newp = NULL; + AstCMethodHard* newp = nullptr; if (nodep->name() == "at") { // Created internally for [] methodOkArguments(nodep, 1, 1); - methodCallLValue(nodep, nodep->fromp(), true); + methodCallLValueRecurse(nodep, nodep->fromp(), true); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "at", - NULL); + nullptr); newp->dtypeFrom(adtypep->subDTypep()); newp->protect(false); newp->didWidth(true); @@ -2409,23 +2447,23 @@ private: || nodep->name() == "size") { methodOkArguments(nodep, 0, 0); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), "size", - NULL); + nullptr); newp->dtypeSetSigned32(); newp->didWidth(true); newp->protect(false); } else if (nodep->name() == "delete") { // function void delete([input integer index]) methodOkArguments(nodep, 0, 1); - methodCallLValue(nodep, nodep->fromp(), true); + methodCallLValueRecurse(nodep, nodep->fromp(), true); if (!nodep->pinsp()) { newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), - "clear", NULL); + "clear", nullptr); newp->protect(false); newp->makeStatement(); } else { AstNode* index_exprp = methodCallQueueIndexExpr(nodep); if (index_exprp->isZero()) { // delete(0) is a pop_front newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), - "pop_front", NULL); + "pop_front", nullptr); newp->dtypeFrom(adtypep->subDTypep()); newp->protect(false); newp->didWidth(true); @@ -2442,7 +2480,7 @@ private: } } else if (nodep->name() == "insert") { methodOkArguments(nodep, 2, 2); - methodCallLValue(nodep, nodep->fromp(), true); + methodCallLValueRecurse(nodep, nodep->fromp(), true); AstNode* index_exprp = methodCallQueueIndexExpr(nodep); AstArg* argp = VN_CAST(nodep->pinsp()->nextp(), Arg); iterateCheckTyped(nodep, "insert value", argp->exprp(), adtypep->subDTypep(), BOTH); @@ -2463,16 +2501,16 @@ private: } } else if (nodep->name() == "pop_front" || nodep->name() == "pop_back") { methodOkArguments(nodep, 0, 0); - methodCallLValue(nodep, nodep->fromp(), true); + methodCallLValueRecurse(nodep, nodep->fromp(), true); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), - nodep->name(), NULL); + nodep->name(), nullptr); newp->dtypeFrom(adtypep->subDTypep()); newp->protect(false); newp->didWidth(true); if (!nodep->firstAbovep()) { newp->makeStatement(); } } else if (nodep->name() == "push_back" || nodep->name() == "push_front") { methodOkArguments(nodep, 1, 1); - methodCallLValue(nodep, nodep->fromp(), true); + methodCallLValueRecurse(nodep, nodep->fromp(), true); AstArg* argp = VN_CAST(nodep->pinsp(), Arg); iterateCheckTyped(nodep, "push value", argp->exprp(), adtypep->subDTypep(), BOTH); newp = new AstCMethodHard(nodep->fileline(), nodep->fromp()->unlinkFrBack(), @@ -2506,7 +2544,7 @@ private: if (VN_IS(ftaskp, Task)) nodep->makeStatement(); return; } - classp = classp->extendsp() ? classp->extendsp()->classp() : NULL; + classp = classp->extendsp() ? classp->extendsp()->classp() : nullptr; } { VSpellCheck speller; @@ -2514,7 +2552,7 @@ private: for (AstNode* itemp = classp->membersp(); itemp; itemp = itemp->nextp()) { if (VN_IS(itemp, NodeFTask)) speller.pushCandidate(itemp->prettyName()); } - classp = classp->extendsp() ? classp->extendsp()->classp() : NULL; + classp = classp->extendsp() ? classp->extendsp()->classp() : nullptr; } string suggest = speller.bestCandidateMsg(nodep->prettyName()); nodep->v3error("Class method " @@ -2525,7 +2563,14 @@ private: nodep->dtypeSetSigned32(); // Guess on error } void methodCallUnpack(AstMethodCall* nodep, AstUnpackArrayDType* adtypep) { - enum { UNKNOWN = 0, ARRAY_OR, ARRAY_AND, ARRAY_XOR, ARRAY_SUM, ARRAY_PRODUCT } methodId; + enum : uint8_t { + UNKNOWN = 0, + ARRAY_OR, + ARRAY_AND, + ARRAY_XOR, + ARRAY_SUM, + ARRAY_PRODUCT + } methodId; methodId = UNKNOWN; if (nodep->name() == "or") { @@ -2543,7 +2588,7 @@ private: if (methodId) { methodOkArguments(nodep, 0, 0); FileLine* fl = nodep->fileline(); - AstNode* newp = NULL; + AstNode* newp = nullptr; for (int i = 0; i < adtypep->elementsConst(); ++i) { AstNode* arrayRef = nodep->fromp()->cloneTree(false); AstNode* selector = new AstArraySel(fl, arrayRef, i); @@ -2678,7 +2723,7 @@ private: } } - virtual void visit(AstNew* nodep) VL_OVERRIDE { + virtual void visit(AstNew* nodep) override { if (nodep->didWidthAndSet()) return; AstClassRefDType* refp = VN_CAST(m_vup->dtypeNullp(), ClassRefDType); if (!refp) { // e.g. int a = new; @@ -2696,12 +2741,15 @@ private: // Either made explicitly or V3LinkDot made implicitly classp->v3fatalSrc("Can't find class's new"); } - - userIterate(nodep->taskp(), NULL); - userIterateChildren(nodep, NULL); + if (classp->isVirtual()) { + nodep->v3error( + "Illegal to call 'new' using an abstract virtual class (IEEE 1800-2017 8.21)"); + } + userIterate(nodep->taskp(), nullptr); + userIterateChildren(nodep, nullptr); processFTaskRefArgs(nodep); } - virtual void visit(AstNewCopy* nodep) VL_OVERRIDE { + virtual void visit(AstNewCopy* nodep) override { if (nodep->didWidthAndSet()) return; AstClassRefDType* refp = VN_CAST(m_vup->dtypeNullp(), ClassRefDType); if (!refp) { // e.g. int a = new; @@ -2716,7 +2764,7 @@ private: << nodep->rhsp()->dtypep()->prettyTypeName() << "'"); } } - virtual void visit(AstNewDynamic* nodep) VL_OVERRIDE { + virtual void visit(AstNewDynamic* nodep) override { if (nodep->didWidthAndSet()) return; AstDynArrayDType* adtypep = VN_CAST(m_vup->dtypeNullp(), DynArrayDType); if (!adtypep) { // e.g. int a = new; @@ -2741,7 +2789,7 @@ private: } } - virtual void visit(AstPattern* nodep) VL_OVERRIDE { + virtual void visit(AstPattern* nodep) override { if (nodep->didWidthAndSet()) return; UINFO(9, "PATTERN " << nodep << endl); if (nodep->childDTypep()) { // data_type '{ pattern } @@ -2783,16 +2831,16 @@ private: patp->unlinkFrBack(&relinkHandle); while (AstNode* movep = patp->lhssp()->nextp()) { movep->unlinkFrBack(); // Not unlinkFrBackWithNext, just one - AstNode* newkeyp = NULL; + AstNode* newkeyp = nullptr; if (patp->keyp()) newkeyp = patp->keyp()->cloneTree(true); AstPatMember* newp - = new AstPatMember(patp->fileline(), movep, newkeyp, NULL); + = new AstPatMember(patp->fileline(), movep, newkeyp, nullptr); patp->addNext(newp); } relinkHandle.relink(patp); } } - AstPatMember* defaultp = NULL; + AstPatMember* defaultp = nullptr; for (AstPatMember* patp = VN_CAST(nodep->itemsp(), PatMember); patp; patp = VN_CAST(patp->nextp(), PatMember)) { if (patp->isDefault()) { @@ -2850,13 +2898,13 @@ private: } if (memp && !patp) { // Missing init elements, warn below - memp = NULL; - patp = NULL; + memp = nullptr; + patp = nullptr; break; } else if (!memp && patp) { patp->v3error("Assignment pattern contains too many elements"); - memp = NULL; - patp = NULL; + memp = nullptr; + patp = nullptr; break; } else { std::pair ret @@ -2872,12 +2920,12 @@ private: if (patp) patp = VN_CAST(patp->nextp(), PatMember); } } - AstNode* newp = NULL; + AstNode* newp = nullptr; for (AstMemberDType* memp = vdtypep->membersp(); memp; memp = VN_CAST(memp->nextp(), MemberDType)) { - PatMap::iterator it = patmap.find(memp); - AstPatMember* newpatp = NULL; - AstPatMember* patp = NULL; + const auto it = patmap.find(memp); + AstPatMember* newpatp = nullptr; + AstPatMember* patp = nullptr; if (it == patmap.end()) { if (defaultp) { newpatp = defaultp->cloneTree(false); @@ -2918,11 +2966,11 @@ private: VNumRange range = arrayp->declRange(); PatVecMap patmap = patVectorMap(nodep, range); UINFO(9, "ent " << range.hi() << " to " << range.lo() << endl); - AstNode* newp = NULL; + AstNode* newp = nullptr; for (int ent = range.hi(); ent >= range.lo(); --ent) { - AstPatMember* newpatp = NULL; - AstPatMember* patp = NULL; - PatVecMap::iterator it = patmap.find(ent); + AstPatMember* newpatp = nullptr; + AstPatMember* patp = nullptr; + const auto it = patmap.find(ent); if (it == patmap.end()) { if (defaultp) { newpatp = defaultp->cloneTree(false); @@ -2941,7 +2989,7 @@ private: AstNode* valuep = patternMemberValueIterate(patp); if (VN_IS(arrayp, UnpackArrayDType)) { if (!newp) { - AstInitArray* newap = new AstInitArray(nodep->fileline(), arrayp, NULL); + AstInitArray* newap = new AstInitArray(nodep->fileline(), arrayp, nullptr); newp = newap; } VN_CAST(newp, InitArray)->addIndexValuep(ent - range.lo(), valuep); @@ -2973,11 +3021,11 @@ private: VNumRange range = bdtypep->declRange(); PatVecMap patmap = patVectorMap(nodep, range); UINFO(9, "ent " << range.hi() << " to " << range.lo() << endl); - AstNode* newp = NULL; + AstNode* newp = nullptr; for (int ent = range.hi(); ent >= range.lo(); --ent) { - AstPatMember* newpatp = NULL; - AstPatMember* patp = NULL; - PatVecMap::iterator it = patmap.find(ent); + AstPatMember* newpatp = nullptr; + AstPatMember* patp = nullptr; + const auto it = patmap.find(ent); if (it == patmap.end()) { if (defaultp) { newpatp = defaultp->cloneTree(false); @@ -3033,7 +3081,7 @@ private: return valuep; } - virtual void visit(AstPatMember* nodep) VL_OVERRIDE { + virtual void visit(AstPatMember* nodep) override { AstNodeDType* vdtypep = m_vup->dtypeNullp(); UASSERT_OBJ(vdtypep, nodep, "Pattern member type not assigned by AstPattern visitor"); nodep->dtypep(vdtypep); @@ -3046,7 +3094,7 @@ private: } int visitPatMemberRep(AstPatMember* nodep) { uint32_t times = 1; - if (nodep->repp()) { // else repp()==NULL shorthand for rep count 1 + if (nodep->repp()) { // else repp()==nullptr shorthand for rep count 1 iterateCheckSizedSelf(nodep, "LHS", nodep->repp(), SELF, BOTH); V3Const::constifyParamsEdit(nodep->repp()); // repp may change const AstConst* constp = VN_CAST(nodep->repp(), Const); @@ -3067,10 +3115,10 @@ private: return times; } - virtual void visit(AstPropClocked* nodep) VL_OVERRIDE { + virtual void visit(AstPropClocked* nodep) override { if (m_vup->prelim()) { // First stage evaluation iterateCheckBool(nodep, "Property", nodep->propp(), BOTH); - userIterateAndNext(nodep->sensesp(), NULL); + userIterateAndNext(nodep->sensesp(), nullptr); if (nodep->disablep()) { iterateCheckBool(nodep, "Disable", nodep->disablep(), BOTH); // it's like an if() condition. @@ -3082,7 +3130,7 @@ private: //-------------------- // Top levels - virtual void visit(AstNodeCase* nodep) VL_OVERRIDE { + virtual void visit(AstNodeCase* nodep) override { // IEEE-2012 12.5: // Width: MAX(expr, all items) // Signed: Only if expr, and all items signed @@ -3091,7 +3139,7 @@ private: for (AstCaseItem *nextip, *itemp = nodep->itemsp(); itemp; itemp = nextip) { nextip = VN_CAST(itemp->nextp(), CaseItem); // Prelim may cause the node to get replaced - if (!VN_IS(nodep, GenCase)) userIterateAndNext(itemp->bodysp(), NULL); + if (!VN_IS(nodep, GenCase)) userIterateAndNext(itemp->bodysp(), nullptr); for (AstNode *nextcp, *condp = itemp->condsp(); condp; condp = nextcp) { nextcp = condp->nextp(); // Prelim may cause the node to get replaced VL_DO_DANGLING(userIterate(condp, WidthVP(CONTEXT, PRELIM).p()), condp); @@ -3127,39 +3175,39 @@ private: } } } - virtual void visit(AstNodeFor* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFor* nodep) override { assertAtStatement(nodep); - userIterateAndNext(nodep->initsp(), NULL); + userIterateAndNext(nodep->initsp(), nullptr); iterateCheckBool(nodep, "For Test Condition", nodep->condp(), BOTH); // it's like an if() condition. - if (!VN_IS(nodep, GenFor)) userIterateAndNext(nodep->bodysp(), NULL); - userIterateAndNext(nodep->incsp(), NULL); + if (!VN_IS(nodep, GenFor)) userIterateAndNext(nodep->bodysp(), nullptr); + userIterateAndNext(nodep->incsp(), nullptr); } - virtual void visit(AstRepeat* nodep) VL_OVERRIDE { + virtual void visit(AstRepeat* nodep) override { assertAtStatement(nodep); userIterateAndNext(nodep->countp(), WidthVP(SELF, BOTH).p()); - userIterateAndNext(nodep->bodysp(), NULL); + userIterateAndNext(nodep->bodysp(), nullptr); } - virtual void visit(AstWhile* nodep) VL_OVERRIDE { + virtual void visit(AstWhile* nodep) override { assertAtStatement(nodep); - userIterateAndNext(nodep->precondsp(), NULL); + userIterateAndNext(nodep->precondsp(), nullptr); iterateCheckBool(nodep, "For Test Condition", nodep->condp(), BOTH); // it's like an if() condition. - userIterateAndNext(nodep->bodysp(), NULL); - userIterateAndNext(nodep->incsp(), NULL); + userIterateAndNext(nodep->bodysp(), nullptr); + userIterateAndNext(nodep->incsp(), nullptr); } - virtual void visit(AstNodeIf* nodep) VL_OVERRIDE { + virtual void visit(AstNodeIf* nodep) override { assertAtStatement(nodep); // if (debug()) nodep->dumpTree(cout, " IfPre: "); if (!VN_IS(nodep, GenIf)) { // for m_paramsOnly - userIterateAndNext(nodep->ifsp(), NULL); - userIterateAndNext(nodep->elsesp(), NULL); + userIterateAndNext(nodep->ifsp(), nullptr); + userIterateAndNext(nodep->elsesp(), nullptr); } iterateCheckBool(nodep, "If", nodep->condp(), BOTH); // it's like an if() condition. // if (debug()) nodep->dumpTree(cout, " IfOut: "); } - virtual void visit(AstNodeAssign* nodep) VL_OVERRIDE { + virtual void visit(AstNodeAssign* nodep) override { // IEEE-2012 10.7, 11.8.2, 11.8.3, 11.5: (Careful of 11.8.1 which is // only one step; final dtype depends on assign LHS.) // Determine RHS type width and signing @@ -3210,7 +3258,7 @@ private: } } - virtual void visit(AstSFormatF* nodep) VL_OVERRIDE { + virtual void visit(AstSFormatF* nodep) override { // Excludes NodeDisplay, see below if (m_vup && !m_vup->prelim()) return; // Can be called as statement or function // Just let all arguments seek their natural sizes @@ -3222,8 +3270,7 @@ private: AstNode* argp = nodep->exprsp(); string txt = nodep->text(); string fmt; - for (string::const_iterator it = txt.begin(); it != txt.end(); ++it) { - char ch = *it; + for (char ch : txt) { if (!inPct && ch == '%') { inPct = true; fmt = ch; @@ -3250,8 +3297,8 @@ private: break; } case 'p': { // Pattern - AstNodeDType* dtypep = argp ? argp->dtypep()->skipRefp() : NULL; - AstBasicDType* basicp = dtypep ? dtypep->basicp() : NULL; + AstNodeDType* dtypep = argp ? argp->dtypep()->skipRefp() : nullptr; + AstBasicDType* basicp = dtypep ? dtypep->basicp() : nullptr; if (basicp && basicp->isString()) { added = true; newFormat += "\"%@\""; @@ -3361,13 +3408,13 @@ private: nodep->text(newFormat); UINFO(9, " Display out " << nodep->text() << endl); } - virtual void visit(AstDisplay* nodep) VL_OVERRIDE { + virtual void visit(AstDisplay* nodep) override { assertAtStatement(nodep); if (nodep->filep()) iterateCheckFileDesc(nodep, nodep->filep(), BOTH); // Just let all arguments seek their natural sizes userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); } - virtual void visit(AstElabDisplay* nodep) VL_OVERRIDE { + virtual void visit(AstElabDisplay* nodep) override { assertAtStatement(nodep); // Just let all arguments seek their natural sizes userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); @@ -3383,28 +3430,28 @@ private: VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } } - virtual void visit(AstDumpCtl* nodep) VL_OVERRIDE { + virtual void visit(AstDumpCtl* nodep) override { assertAtStatement(nodep); // Just let all arguments seek their natural sizes userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); } - virtual void visit(AstFOpen* nodep) VL_OVERRIDE { + virtual void visit(AstFOpen* nodep) override { // Although a system function in IEEE, here a statement which sets the file pointer (MCD) assertAtStatement(nodep); iterateCheckFileDesc(nodep, nodep->filep(), BOTH); userIterateAndNext(nodep->filenamep(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->modep(), WidthVP(SELF, BOTH).p()); } - virtual void visit(AstFOpenMcd* nodep) VL_OVERRIDE { + virtual void visit(AstFOpenMcd* nodep) override { assertAtStatement(nodep); iterateCheckFileDesc(nodep, nodep->filep(), BOTH); userIterateAndNext(nodep->filenamep(), WidthVP(SELF, BOTH).p()); } - virtual void visit(AstFClose* nodep) VL_OVERRIDE { + virtual void visit(AstFClose* nodep) override { assertAtStatement(nodep); iterateCheckFileDesc(nodep, nodep->filep(), BOTH); } - virtual void visit(AstFError* nodep) VL_OVERRIDE { + virtual void visit(AstFError* nodep) override { if (m_vup->prelim()) { iterateCheckFileDesc(nodep, nodep->filep(), BOTH); // We only support string types, not packed array @@ -3412,51 +3459,51 @@ private: nodep->dtypeSetLogicUnsized(32, 1, VSigning::SIGNED); // Spec says integer return } } - virtual void visit(AstFEof* nodep) VL_OVERRIDE { + virtual void visit(AstFEof* nodep) override { if (m_vup->prelim()) { iterateCheckFileDesc(nodep, nodep->filep(), BOTH); nodep->dtypeSetLogicUnsized(32, 1, VSigning::SIGNED); // Spec says integer return } } - virtual void visit(AstFFlush* nodep) VL_OVERRIDE { + virtual void visit(AstFFlush* nodep) override { assertAtStatement(nodep); if (nodep->filep()) iterateCheckFileDesc(nodep, nodep->filep(), BOTH); } - virtual void visit(AstFRewind* nodep) VL_OVERRIDE { + virtual void visit(AstFRewind* nodep) override { iterateCheckFileDesc(nodep, nodep->filep(), BOTH); nodep->dtypeSetLogicUnsized(32, 1, VSigning::SIGNED); // Spec says integer return } - virtual void visit(AstFTell* nodep) VL_OVERRIDE { + virtual void visit(AstFTell* nodep) override { iterateCheckFileDesc(nodep, nodep->filep(), BOTH); nodep->dtypeSetLogicUnsized(32, 1, VSigning::SIGNED); // Spec says integer return } - virtual void visit(AstFSeek* nodep) VL_OVERRIDE { + virtual void visit(AstFSeek* nodep) override { iterateCheckFileDesc(nodep, nodep->filep(), BOTH); iterateCheckSigned32(nodep, "$fseek offset", nodep->offset(), BOTH); iterateCheckSigned32(nodep, "$fseek operation", nodep->operation(), BOTH); nodep->dtypeSetLogicUnsized(32, 1, VSigning::SIGNED); // Spec says integer return } - virtual void visit(AstFGetC* nodep) VL_OVERRIDE { + virtual void visit(AstFGetC* nodep) override { if (m_vup->prelim()) { iterateCheckFileDesc(nodep, nodep->filep(), BOTH); nodep->dtypeSetLogicUnsized(32, 8, VSigning::SIGNED); // Spec says integer return } } - virtual void visit(AstFGetS* nodep) VL_OVERRIDE { + virtual void visit(AstFGetS* nodep) override { if (m_vup->prelim()) { nodep->dtypeSetSigned32(); // Spec says integer return iterateCheckFileDesc(nodep, nodep->filep(), BOTH); userIterateAndNext(nodep->strgp(), WidthVP(SELF, BOTH).p()); } } - virtual void visit(AstFUngetC* nodep) VL_OVERRIDE { + virtual void visit(AstFUngetC* nodep) override { if (m_vup->prelim()) { iterateCheckFileDesc(nodep, nodep->filep(), BOTH); iterateCheckSigned32(nodep, "$fungetc character", nodep->charp(), BOTH); nodep->dtypeSetLogicUnsized(32, 8, VSigning::SIGNED); // Spec says integer return } } - virtual void visit(AstFRead* nodep) VL_OVERRIDE { + virtual void visit(AstFRead* nodep) override { if (m_vup->prelim()) { nodep->dtypeSetSigned32(); // Spec says integer return userIterateAndNext(nodep->memp(), WidthVP(SELF, BOTH).p()); @@ -3469,42 +3516,42 @@ private: } } } - virtual void visit(AstFScanF* nodep) VL_OVERRIDE { + virtual void visit(AstFScanF* nodep) override { if (m_vup->prelim()) { nodep->dtypeSetSigned32(); // Spec says integer return iterateCheckFileDesc(nodep, nodep->filep(), BOTH); userIterateAndNext(nodep->exprsp(), WidthVP(SELF, BOTH).p()); } } - virtual void visit(AstSScanF* nodep) VL_OVERRIDE { + virtual void visit(AstSScanF* nodep) override { if (m_vup->prelim()) { nodep->dtypeSetSigned32(); // Spec says integer return userIterateAndNext(nodep->fromp(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->exprsp(), WidthVP(SELF, BOTH).p()); } } - virtual void visit(AstSysIgnore* nodep) VL_OVERRIDE { + virtual void visit(AstSysIgnore* nodep) override { userIterateAndNext(nodep->exprsp(), WidthVP(SELF, BOTH).p()); } - virtual void visit(AstSystemF* nodep) VL_OVERRIDE { + virtual void visit(AstSystemF* nodep) override { if (m_vup->prelim()) { userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); nodep->dtypeSetSigned32(); // Spec says integer return } } - virtual void visit(AstSysFuncAsTask* nodep) VL_OVERRIDE { + virtual void visit(AstSysFuncAsTask* nodep) override { assertAtStatement(nodep); userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); } - virtual void visit(AstSystemT* nodep) VL_OVERRIDE { + virtual void visit(AstSystemT* nodep) override { assertAtStatement(nodep); userIterateAndNext(nodep->lhsp(), WidthVP(SELF, BOTH).p()); } - virtual void visit(AstNodeReadWriteMem* nodep) VL_OVERRIDE { + virtual void visit(AstNodeReadWriteMem* nodep) override { assertAtStatement(nodep); userIterateAndNext(nodep->filenamep(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->memp(), WidthVP(SELF, BOTH).p()); - AstNodeDType* subp = NULL; + AstNodeDType* subp = nullptr; if (AstAssocArrayDType* adtypep = VN_CAST(nodep->memp()->dtypep()->skipRefp(), AssocArrayDType)) { subp = adtypep->subDTypep(); @@ -3532,41 +3579,41 @@ private: userIterateAndNext(nodep->lsbp(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->msbp(), WidthVP(SELF, BOTH).p()); } - virtual void visit(AstValuePlusArgs* nodep) VL_OVERRIDE { + virtual void visit(AstValuePlusArgs* nodep) override { if (m_vup->prelim()) { userIterateAndNext(nodep->searchp(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->outp(), WidthVP(SELF, BOTH).p()); nodep->dtypeChgWidthSigned(32, 1, VSigning::SIGNED); // Spec says integer return } } - virtual void visit(AstTimeFormat* nodep) VL_OVERRIDE { + virtual void visit(AstTimeFormat* nodep) override { assertAtStatement(nodep); iterateCheckSigned32(nodep, "units", nodep->unitsp(), BOTH); iterateCheckSigned32(nodep, "precision", nodep->precisionp(), BOTH); iterateCheckString(nodep, "suffix", nodep->suffixp(), BOTH); iterateCheckSigned32(nodep, "width", nodep->widthp(), BOTH); } - virtual void visit(AstUCStmt* nodep) VL_OVERRIDE { + virtual void visit(AstUCStmt* nodep) override { // Just let all arguments seek their natural sizes assertAtStatement(nodep); userIterateChildren(nodep, WidthVP(SELF, BOTH).p()); } - virtual void visit(AstAssert* nodep) VL_OVERRIDE { + virtual void visit(AstAssert* nodep) override { assertAtStatement(nodep); iterateCheckBool(nodep, "Property", nodep->propp(), BOTH); // it's like an if() condition. - userIterateAndNext(nodep->passsp(), NULL); - userIterateAndNext(nodep->failsp(), NULL); + userIterateAndNext(nodep->passsp(), nullptr); + userIterateAndNext(nodep->failsp(), nullptr); } - virtual void visit(AstCover* nodep) VL_OVERRIDE { + virtual void visit(AstCover* nodep) override { assertAtStatement(nodep); iterateCheckBool(nodep, "Property", nodep->propp(), BOTH); // it's like an if() condition. - userIterateAndNext(nodep->passsp(), NULL); + userIterateAndNext(nodep->passsp(), nullptr); } - virtual void visit(AstRestrict* nodep) VL_OVERRIDE { + virtual void visit(AstRestrict* nodep) override { assertAtStatement(nodep); iterateCheckBool(nodep, "Property", nodep->propp(), BOTH); // it's like an if() condition. } - virtual void visit(AstPin* nodep) VL_OVERRIDE { + virtual void visit(AstPin* nodep) override { // if (debug()) nodep->dumpTree(cout, "- PinPre: "); // TOP LEVEL NODE if (nodep->modVarp() && nodep->modVarp()->isGParam()) { @@ -3575,7 +3622,7 @@ private: } else if (!m_paramsOnly) { if (!nodep->modVarp()->didWidth()) { // Var hasn't been widthed, so make it so. - userIterate(nodep->modVarp(), NULL); + userIterate(nodep->modVarp(), nullptr); } if (!nodep->exprp()) { // No-connect return; @@ -3677,7 +3724,7 @@ private: } // if (debug()) nodep->dumpTree(cout, "- PinOut: "); } - virtual void visit(AstCell* nodep) VL_OVERRIDE { + virtual void visit(AstCell* nodep) override { if (!m_paramsOnly) { if (VN_IS(nodep->modp(), NotFoundModule)) { // We've resolved parameters and hit a module that we couldn't resolve. It's @@ -3691,12 +3738,12 @@ private: m_cellRangep = nodep->rangep(); userIterateAndNext(nodep->rangep(), WidthVP(SELF, BOTH).p()); } - userIterateAndNext(nodep->pinsp(), NULL); + userIterateAndNext(nodep->pinsp(), nullptr); } - userIterateAndNext(nodep->paramsp(), NULL); - m_cellRangep = NULL; + userIterateAndNext(nodep->paramsp(), nullptr); + m_cellRangep = nullptr; } - virtual void visit(AstGatePin* nodep) VL_OVERRIDE { + virtual void visit(AstGatePin* nodep) override { if (m_vup->prelim()) { userIterateAndNext(nodep->rangep(), WidthVP(SELF, BOTH).p()); userIterateAndNext(nodep->exprp(), WidthVP(CONTEXT, PRELIM).p()); @@ -3720,7 +3767,7 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); } } - virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTask* nodep) override { // Grab width from the output variable (if it's a function) if (nodep->didWidth()) return; if (nodep->doingWidth()) { @@ -3729,14 +3776,11 @@ private: nodep->didWidth(true); return; } - if (nodep->isVirtual() || nodep->pureVirtual()) { - nodep->v3warn(E_UNSUPPORTED, "Unsupported: 'virtual' class method"); - } // Function hasn't been widthed, so make it so. // Would use user1 etc, but V3Width called from too many places to spend a user nodep->doingWidth(true); m_ftaskp = nodep; - userIterateChildren(nodep, NULL); + userIterateChildren(nodep, nullptr); if (nodep->isConstructor()) { // Pretend it's void so less special casing needed when look at dtypes nodep->dtypeSetVoid(); @@ -3747,14 +3791,14 @@ private: } nodep->didWidth(true); nodep->doingWidth(false); - m_funcp = NULL; - m_ftaskp = NULL; + m_funcp = nullptr; + m_ftaskp = nullptr; if (nodep->dpiImport() && !nodep->dpiOpenParent() && markHasOpenArray(nodep)) { nodep->dpiOpenParentInc(); // Mark so V3Task will wait for a child to build calling // func } } - virtual void visit(AstReturn* nodep) VL_OVERRIDE { + virtual void visit(AstReturn* nodep) override { // IEEE: Assignment-like context assertAtStatement(nodep); if (!m_funcp) { @@ -3772,7 +3816,7 @@ private: } } - virtual void visit(AstFuncRef* nodep) VL_OVERRIDE { + virtual void visit(AstFuncRef* nodep) override { visit(VN_CAST(nodep, NodeFTaskRef)); nodep->dtypeFrom(nodep->taskp()); // if (debug()) nodep->dumpTree(cout, " FuncOut: "); @@ -3783,7 +3827,7 @@ private: UINFO(5, " FTASKREF " << nodep << endl); UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked"); if (nodep->didWidth()) return; - userIterate(nodep->taskp(), NULL); + userIterate(nodep->taskp(), nullptr); // // And do the arguments to the task/function too do { @@ -3801,7 +3845,7 @@ private: UINFO(4, " sformat via metacomment: " << nodep << endl); AstNRelinker handle; argp->unlinkFrBackWithNext(&handle); // Format + additional args, if any - AstNode* argsp = NULL; + AstNode* argsp = nullptr; while (AstArg* nextargp = VN_CAST(argp->nextp(), Arg)) { argsp = AstNode::addNext( argsp, nextargp->exprp() @@ -3899,42 +3943,42 @@ private: } } } - virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE { + virtual void visit(AstNodeFTaskRef* nodep) override { // For arguments, is assignment-like context; see IEEE rules in AstNodeAssign // Function hasn't been widthed, so make it so. UINFO(5, " FTASKREF " << nodep << endl); UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked"); if (nodep->didWidth()) return; - userIterate(nodep->taskp(), NULL); + userIterate(nodep->taskp(), nullptr); // And do the arguments to the task/function too processFTaskRefArgs(nodep); nodep->didWidth(true); } - virtual void visit(AstNodeProcedure* nodep) VL_OVERRIDE { + virtual void visit(AstNodeProcedure* nodep) override { assertAtStatement(nodep); m_procedurep = nodep; - userIterateChildren(nodep, NULL); - m_procedurep = NULL; + userIterateChildren(nodep, nullptr); + m_procedurep = nullptr; } - virtual void visit(AstNetlist* nodep) VL_OVERRIDE { + virtual void visit(AstNetlist* nodep) override { // Iterate modules backwards, in bottom-up order. That's faster - userIterateChildrenBackwards(nodep, NULL); + userIterateChildrenBackwards(nodep, nullptr); } //-------------------- // Default - virtual void visit(AstNodeMath* nodep) VL_OVERRIDE { + virtual void visit(AstNodeMath* nodep) override { if (!nodep->didWidth()) { nodep->v3fatalSrc( "Visit function missing? Widthed function missing for math node: " << nodep); } - userIterateChildren(nodep, NULL); + userIterateChildren(nodep, nullptr); } - virtual void visit(AstNode* nodep) VL_OVERRIDE { + virtual void visit(AstNode* nodep) override { // Default: Just iterate UASSERT_OBJ(!m_vup, nodep, "Visit function missing? Widthed expectation for this node: " << nodep); - userIterateChildren(nodep, NULL); + userIterateChildren(nodep, nullptr); } //---------------------------------------------------------------------- @@ -3952,7 +3996,7 @@ private: iterateCheck(nodep, "LHS", nodep->lhsp(), SELF, FINAL, subDTypep, EXTEND_EXP); } } - virtual void visit(AstIToRD* nodep) VL_OVERRIDE { + virtual void visit(AstIToRD* nodep) override { // Real: Output real // LHS presumed self-determined, then coerced to real if (m_vup->prelim()) { // First stage evaluation @@ -3966,7 +4010,7 @@ private: } } } - virtual void visit(AstISToRD* nodep) VL_OVERRIDE { + virtual void visit(AstISToRD* nodep) override { // Real: Output real // LHS presumed self-determined, then coerced to real if (m_vup->prelim()) { // First stage evaluation @@ -4765,7 +4809,7 @@ private: if (expWidthMin == 0) expWidthMin = expWidth; bool bad = widthBad(underp, expDTypep); if ((bad || underp->width() != expWidth) && fixAutoExtend(underp /*ref*/, expWidth)) { - underp = NULL; // Changes underp + underp = nullptr; // Changes underp return; } if (VN_IS(underp, Const) && VN_CAST(underp, Const)->num().isFromString() @@ -4886,26 +4930,26 @@ private: } AstNodeBiop* replaceWithUOrSVersion(AstNodeBiop* nodep, bool signedFlavorNeeded) { // Given a signed/unsigned node type, create the opposite type - // Return new node or NULL if nothing - if (signedFlavorNeeded == nodep->signedFlavor()) return NULL; + // Return new node or nullptr if nothing + if (signedFlavorNeeded == nodep->signedFlavor()) return nullptr; if (!nodep->dtypep()) nodep->dtypeFrom(nodep->lhsp()); // To simplify callers, some node types don't need to change switch (nodep->type()) { - case AstType::atEq: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; - case AstType::atNeq: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; - case AstType::atEqCase: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; - case AstType::atNeqCase: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; - case AstType::atEqWild: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; - case AstType::atNeqWild: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; - case AstType::atAdd: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; - case AstType::atSub: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; - case AstType::atShiftL: nodep->dtypeChgSigned(signedFlavorNeeded); return NULL; + case AstType::atEq: nodep->dtypeChgSigned(signedFlavorNeeded); return nullptr; + case AstType::atNeq: nodep->dtypeChgSigned(signedFlavorNeeded); return nullptr; + case AstType::atEqCase: nodep->dtypeChgSigned(signedFlavorNeeded); return nullptr; + case AstType::atNeqCase: nodep->dtypeChgSigned(signedFlavorNeeded); return nullptr; + case AstType::atEqWild: nodep->dtypeChgSigned(signedFlavorNeeded); return nullptr; + case AstType::atNeqWild: nodep->dtypeChgSigned(signedFlavorNeeded); return nullptr; + case AstType::atAdd: nodep->dtypeChgSigned(signedFlavorNeeded); return nullptr; + case AstType::atSub: nodep->dtypeChgSigned(signedFlavorNeeded); return nullptr; + case AstType::atShiftL: nodep->dtypeChgSigned(signedFlavorNeeded); return nullptr; default: break; } FileLine* fl = nodep->fileline(); AstNode* lhsp = nodep->lhsp()->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); - AstNodeBiop* newp = NULL; + AstNodeBiop* newp = nullptr; switch (nodep->type()) { case AstType::atGt: newp = new AstGtS(fl, lhsp, rhsp); break; case AstType::atGtS: newp = new AstGt(fl, lhsp, rhsp); break; @@ -4935,12 +4979,12 @@ private: } AstNodeBiop* replaceWithDVersion(AstNodeBiop* nodep) { // Given a signed/unsigned node type, create the opposite type - // Return new node or NULL if nothing - if (nodep->doubleFlavor()) { return NULL; } + // Return new node or nullptr if nothing + if (nodep->doubleFlavor()) { return nullptr; } FileLine* fl = nodep->fileline(); AstNode* lhsp = nodep->lhsp()->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); - AstNodeBiop* newp = NULL; + AstNodeBiop* newp = nullptr; // No width change on output;... // All below have bool or double outputs switch (nodep->type()) { case AstType::atAdd: newp = new AstAddD(fl, lhsp, rhsp); break; @@ -4974,12 +5018,12 @@ private: } AstNodeBiop* replaceWithNVersion(AstNodeBiop* nodep) { // Given a signed/unsigned node type, replace with string version - // Return new node or NULL if nothing - if (nodep->stringFlavor()) return NULL; + // Return new node or nullptr if nothing + if (nodep->stringFlavor()) return nullptr; FileLine* fl = nodep->fileline(); AstNode* lhsp = nodep->lhsp()->unlinkFrBack(); AstNode* rhsp = nodep->rhsp()->unlinkFrBack(); - AstNodeBiop* newp = NULL; + AstNodeBiop* newp = nullptr; // No width change on output;... // All below have bool or double outputs switch (nodep->type()) { case AstType::atEq: @@ -5006,11 +5050,11 @@ private: } AstNodeUniop* replaceWithDVersion(AstNodeUniop* nodep) { // Given a signed/unsigned node type, create the opposite type - // Return new node or NULL if nothing - if (nodep->doubleFlavor()) return NULL; + // Return new node or nullptr if nothing + if (nodep->doubleFlavor()) return nullptr; FileLine* fl = nodep->fileline(); AstNode* lhsp = nodep->lhsp()->unlinkFrBack(); - AstNodeUniop* newp = NULL; + AstNodeUniop* newp = nullptr; switch (nodep->type()) { case AstType::atNegate: newp = new AstNegateD(fl, lhsp); break; default: @@ -5047,7 +5091,7 @@ private: // METHODS - data types AstNodeDType* iterateEditMoveDTypep(AstNode* parentp, AstNodeDType* dtnodep) { - UASSERT_OBJ(dtnodep, parentp, "Caller should check for NULL before computing dtype"); + UASSERT_OBJ(dtnodep, parentp, "Caller should check for nullptr before computing dtype"); // Iterate into a data type to resolve that type. // The data type may either: // 1. Be a child (typically getChildDTypep() returns it) @@ -5065,7 +5109,7 @@ private: if (child1 || child2) { UINFO(9, "iterateEditMoveDTypep child iterating " << dtnodep << endl); // Iterate, this might edit the dtypes which means dtnodep now lost - VL_DO_DANGLING(userIterate(dtnodep, NULL), dtnodep); + VL_DO_DANGLING(userIterate(dtnodep, nullptr), dtnodep); // Figure out the new dtnodep, remained a child of parent so find it there dtnodep = child1 ? parentp->getChildDTypep() : parentp->getChild2DTypep(); UASSERT_OBJ(dtnodep, parentp, "iterateEditMoveDTypep lost pointer to child"); @@ -5082,7 +5126,7 @@ private: // See notes in visit(AstBracketArrayDType*) UASSERT_OBJ(!VN_IS(dtnodep, BracketArrayDType), parentp, "Brackets should have been iterated as children"); - userIterate(dtnodep, NULL); + userIterate(dtnodep, nullptr); UASSERT_OBJ(dtnodep->didWidth(), parentp, "iterateEditMoveDTypep didn't get width resolution"); } @@ -5110,7 +5154,7 @@ private: } break; } - AstConst* valp = NULL; // If NULL, construct from val + AstConst* valp = nullptr; // If nullptr, construct from val int val = 0; switch (attrType) { case AstAttrType::DIM_BITS: { @@ -5157,12 +5201,12 @@ private: } AstVar* dimensionVarp(AstNodeDType* nodep, AstAttrType attrType, uint32_t msbdim) { // Return a variable table which has specified dimension properties for this variable - TableMap::iterator pos = m_tableMap.find(make_pair(nodep, attrType)); + const auto pos = m_tableMap.find(make_pair(nodep, attrType)); if (pos != m_tableMap.end()) return pos->second; AstNodeArrayDType* vardtypep = new AstUnpackArrayDType(nodep->fileline(), nodep->findSigned32DType(), new AstRange(nodep->fileline(), msbdim, 0)); - AstInitArray* initp = new AstInitArray(nodep->fileline(), vardtypep, NULL); + AstInitArray* initp = new AstInitArray(nodep->fileline(), vardtypep, nullptr); v3Global.rootp()->typeTablep()->addTypesp(vardtypep); AstVar* varp = new AstVar(nodep->fileline(), AstVarType::MODULETEMP, "__Vdimtab_" + VString::downcase(attrType.ascii()) @@ -5178,13 +5222,13 @@ private: for (unsigned i = 1; i < msbdim + 1; ++i) { initp->addValuep(dimensionValue(nodep->fileline(), nodep, attrType, i)); } - userIterate(varp, NULL); // May have already done $unit so must do this var + userIterate(varp, nullptr); // May have already done $unit so must do this var m_tableMap.insert(make_pair(make_pair(nodep, attrType), varp)); return varp; } AstVar* enumVarp(AstEnumDType* nodep, AstAttrType attrType, uint32_t msbdim) { // Return a variable table which has specified dimension properties for this variable - TableMap::iterator pos = m_tableMap.find(make_pair(nodep, attrType)); + const auto pos = m_tableMap.find(make_pair(nodep, attrType)); if (pos != m_tableMap.end()) return pos->second; UINFO(9, "Construct Venumtab attr=" << attrType.ascii() << " max=" << msbdim << " for " << nodep << endl); @@ -5196,7 +5240,7 @@ private: } AstNodeArrayDType* vardtypep = new AstUnpackArrayDType( nodep->fileline(), basep, new AstRange(nodep->fileline(), msbdim, 0)); - AstInitArray* initp = new AstInitArray(nodep->fileline(), vardtypep, NULL); + AstInitArray* initp = new AstInitArray(nodep->fileline(), vardtypep, nullptr); v3Global.rootp()->typeTablep()->addTypesp(vardtypep); AstVar* varp = new AstVar(nodep->fileline(), AstVarType::MODULETEMP, "__Venumtab_" + VString::downcase(attrType.ascii()) @@ -5221,7 +5265,7 @@ private: UASSERT_OBJ(nodep->itemsp(), nodep, "enum without items"); std::vector values; values.resize(msbdim + 1); - for (unsigned i = 0; i < (msbdim + 1); ++i) values[i] = NULL; + for (unsigned i = 0; i < (msbdim + 1); ++i) values[i] = nullptr; { AstEnumItem* firstp = nodep->itemsp(); AstEnumItem* prevp = firstp; // Prev must start with last item @@ -5249,7 +5293,7 @@ private: AstNode* valp = values[i]; if (valp) initp->addIndexValuep(i, valp); } - userIterate(varp, NULL); // May have already done $unit so must do this var + userIterate(varp, nullptr); // May have already done $unit so must do this var m_tableMap.insert(make_pair(make_pair(nodep, attrType), varp)); return varp; } @@ -5354,7 +5398,7 @@ private: // These functions save/restore the AstNUser information so it can pass to child nodes. AstNode* userIterateSubtreeReturnEdits(AstNode* nodep, WidthVP* vup) { - if (!nodep) return NULL; + if (!nodep) return nullptr; WidthVP* saveVup = m_vup; AstNode* ret; { @@ -5404,22 +5448,14 @@ private: public: // CONSTRUCTORS WidthVisitor(bool paramsOnly, // [in] TRUE if we are considering parameters only. - bool doGenerate) { // [in] TRUE if we are inside a generate statement and + bool doGenerate) // [in] TRUE if we are inside a generate statement and // // don't wish to trigger errors - m_paramsOnly = paramsOnly; - m_cellRangep = NULL; - m_ftaskp = NULL; - m_procedurep = NULL; - m_funcp = NULL; - m_attrp = NULL; - m_doGenerate = doGenerate; - m_dtTables = 0; - m_vup = NULL; - } + : m_paramsOnly{paramsOnly} + , m_doGenerate{doGenerate} {} AstNode* mainAcceptEdit(AstNode* nodep) { return userIterateSubtreeReturnEdits(nodep, WidthVP(SELF, BOTH).p()); } - virtual ~WidthVisitor() {} + virtual ~WidthVisitor() override {} }; //###################################################################### diff --git a/src/V3WidthCommit.h b/src/V3WidthCommit.h index 72436b9d1..ff6e3c03a 100644 --- a/src/V3WidthCommit.h +++ b/src/V3WidthCommit.h @@ -45,18 +45,18 @@ private: } // VISITORS - virtual void visit(AstSigned* nodep) VL_OVERRIDE { + virtual void visit(AstSigned* nodep) override { VL_DO_DANGLING(replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()), nodep); } - virtual void visit(AstUnsigned* nodep) VL_OVERRIDE { + virtual void visit(AstUnsigned* nodep) override { VL_DO_DANGLING(replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()), nodep); } - virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); } + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } public: // CONSTRUCTORS WidthRemoveVisitor() {} - virtual ~WidthRemoveVisitor() {} + virtual ~WidthRemoveVisitor() override {} AstNode* mainAcceptEdit(AstNode* nodep) { return iterateSubtreeReturnEdits(nodep); } }; @@ -81,7 +81,7 @@ public: newp->dtypeFrom(nodep); return newp; } else { - return NULL; + return nullptr; } } @@ -95,7 +95,7 @@ private: // See if the dtype/refDType can be converted to a standard one // This reduces the number of dtypes in the system, and since // dtypep() figures into sameTree() results in better optimizations - if (!nodep) return NULL; + if (!nodep) return nullptr; // Recurse to handle the data type, as may change the size etc of this type if (!nodep->user1()) iterate(nodep); // Look for duplicate @@ -113,7 +113,7 @@ private: return nodep; } // VISITORS - virtual void visit(AstConst* nodep) VL_OVERRIDE { + virtual void visit(AstConst* nodep) override { UASSERT_OBJ(nodep->dtypep(), nodep, "No dtype"); iterate(nodep->dtypep()); // Do datatype first if (AstConst* newp = newIfConstCommitSize(nodep)) { @@ -126,15 +126,15 @@ private: } editDType(nodep); } - virtual void visit(AstNodeDType* nodep) VL_OVERRIDE { // + virtual void visit(AstNodeDType* nodep) override { // visitIterateNodeDType(nodep); } - virtual void visit(AstNodeUOrStructDType* nodep) VL_OVERRIDE { + virtual void visit(AstNodeUOrStructDType* nodep) override { if (nodep->user1SetOnce()) return; // Process once visitIterateNodeDType(nodep); nodep->clearCache(); } - virtual void visit(AstParamTypeDType* nodep) VL_OVERRIDE { + virtual void visit(AstParamTypeDType* nodep) override { if (nodep->user1SetOnce()) return; // Process once visitIterateNodeDType(nodep); // Move to type table as all dtype pointers must resolve there @@ -153,11 +153,11 @@ private: nodep->virtRefDTypep(editOneDType(nodep->virtRefDTypep())); nodep->virtRefDType2p(editOneDType(nodep->virtRefDType2p())); } - virtual void visit(AstNodePreSel* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE + virtual void visit(AstNodePreSel* nodep) override { // LCOV_EXCL_LINE // This check could go anywhere after V3Param nodep->v3fatalSrc("Presels should have been removed before this point"); } - virtual void visit(AstNode* nodep) VL_OVERRIDE { + virtual void visit(AstNode* nodep) override { iterateChildren(nodep); editDType(nodep); } @@ -171,7 +171,7 @@ public: // Don't want to repairCache, as all needed nodes have been added back in // a repair would prevent dead nodes from being detected } - virtual ~WidthCommitVisitor() {} + virtual ~WidthCommitVisitor() override {} }; //###################################################################### diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp index 880b3bf80..b6b248810 100644 --- a/src/V3WidthSel.cpp +++ b/src/V3WidthSel.cpp @@ -63,11 +63,10 @@ private: AstNodeDType* m_errp; // Node that was found, for error reporting if not known type AstNodeDType* m_dtypep; // Data type for the 'from' slice VNumRange m_fromRange; // Numeric range bounds for the 'from' slice - FromData(AstNodeDType* errp, AstNodeDType* dtypep, const VNumRange& fromRange) { - m_errp = errp; - m_dtypep = dtypep; - m_fromRange = fromRange; - } + FromData(AstNodeDType* errp, AstNodeDType* dtypep, const VNumRange& fromRange) + : m_errp{errp} + , m_dtypep{dtypep} + , m_fromRange{fromRange} {} ~FromData() {} }; FromData fromDataForArray(AstNode* nodep, AstNode* basefromp) { @@ -199,7 +198,7 @@ private: // VISITORS // If adding new visitors, ensure V3Width's visit(TYPE) calls into here - virtual void visit(AstSelBit* nodep) VL_OVERRIDE { + virtual void visit(AstSelBit* nodep) override { // Select of a non-width specified part of an array, i.e. "array[2]" // This select style has a lsb and msb (no user specified width) UINFO(6, "SELBIT " << nodep << endl); @@ -276,9 +275,10 @@ private: } else if (VN_IS(ddtypep, BasicDType) && ddtypep->isString()) { // SELBIT(string, index) -> GETC(string, index) AstNodeVarRef* varrefp = VN_CAST(fromp, NodeVarRef); - if (!varrefp) + if (!varrefp) { nodep->v3warn(E_UNSUPPORTED, "Unsupported: String array operation on non-variable"); + } AstNode* newp; if (varrefp && varrefp->lvalue()) { newp = new AstGetcRefN(nodep->fileline(), fromp, rhsp); @@ -308,7 +308,7 @@ private: if (debug() >= 9) newp->dumpTree(cout, "--SELBTn: "); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } else { // NULL=bad extract, or unknown node type + } else { // nullptr=bad extract, or unknown node type nodep->v3error("Illegal bit or array select; type already selected, or bad dimension: " << "data type is" << fromdata.m_errp->prettyDTypeNameQ()); // How to recover? We'll strip a dimension. @@ -317,7 +317,7 @@ private: } if (!rhsp->backp()) { VL_DO_DANGLING(pushDeletep(rhsp), rhsp); } } - virtual void visit(AstSelExtract* nodep) VL_OVERRIDE { + virtual void visit(AstSelExtract* nodep) override { // Select of a range specified part of an array, i.e. "array[2:3]" // SELEXTRACT(from,msb,lsb) -> SEL(from, lsb, 1+msb-lsb) // This select style has a (msb or lsb) and width @@ -351,8 +351,9 @@ private: nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } else { // Slice - AstSliceSel* newp = new AstSliceSel(nodep->fileline(), fromp, - VNumRange(VNumRange::LeftRight(), msb, lsb)); + AstSliceSel* newp = new AstSliceSel( + nodep->fileline(), fromp, + VNumRange(VNumRange::LeftRight(), msb - fromRange.lo(), lsb - fromRange.lo())); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); } @@ -438,7 +439,7 @@ private: // if (debug() >= 9) newp->dumpTree(cout, "--SELEXnew: "); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } else { // NULL=bad extract, or unknown node type + } else { // nullptr=bad extract, or unknown node type nodep->v3error("Illegal range select; type already selected, or bad dimension: " << "data type is " << fromdata.m_errp->prettyDTypeNameQ()); UINFO(1, " Related ddtype: " << ddtypep << endl); @@ -513,7 +514,7 @@ private: newwidthp = new AstConst(nodep->fileline(), AstConst::Unsized32(), width * elwidth); } - AstNode* newlsbp = NULL; + AstNode* newlsbp = nullptr; if (VN_IS(nodep, SelPlus)) { if (fromRange.littleEndian()) { // SELPLUS(from,lsb,width) -> SEL(from, (vector_msb-width+1)-sel, width) @@ -544,7 +545,7 @@ private: if (debug() >= 9) newp->dumpTree(cout, "--SELNEW: "); nodep->replaceWith(newp); VL_DO_DANGLING(pushDeletep(nodep), nodep); - } else { // NULL=bad extract, or unknown node type + } else { // nullptr=bad extract, or unknown node type nodep->v3error("Illegal +: or -: select; type already selected, or bad dimension: " << "data type is " << fromdata.m_errp->prettyDTypeNameQ()); // How to recover? We'll strip a dimension. @@ -556,13 +557,13 @@ private: if (!rhsp->backp()) { VL_DO_DANGLING(pushDeletep(rhsp), rhsp); } if (!widthp->backp()) { VL_DO_DANGLING(pushDeletep(widthp), widthp); } } - virtual void visit(AstSelPlus* nodep) VL_OVERRIDE { replaceSelPlusMinus(nodep); } - virtual void visit(AstSelMinus* nodep) VL_OVERRIDE { replaceSelPlusMinus(nodep); } + virtual void visit(AstSelPlus* nodep) override { replaceSelPlusMinus(nodep); } + virtual void visit(AstSelMinus* nodep) override { replaceSelPlusMinus(nodep); } // If adding new visitors, ensure V3Width's visit(TYPE) calls into here //-------------------- // Default - virtual void visit(AstNode* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE + virtual void visit(AstNode* nodep) override { // LCOV_EXCL_LINE // See notes above; we never iterate nodep->v3fatalSrc("Shouldn't iterate in V3WidthSel"); } @@ -571,7 +572,7 @@ public: // CONSTRUCTORS WidthSelVisitor() {} AstNode* mainAcceptEdit(AstNode* nodep) { return iterateSubtreeReturnEdits(nodep); } - virtual ~WidthSelVisitor() {} + virtual ~WidthSelVisitor() override {} }; //###################################################################### diff --git a/src/Verilator.cpp b/src/Verilator.cpp index dc040cc50..7ffce2b63 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -52,6 +52,7 @@ #include "V3Gate.h" #include "V3GenClk.h" #include "V3Graph.h" +#include "V3HierBlock.h" #include "V3Inline.h" #include "V3Inst.h" #include "V3Life.h" @@ -100,6 +101,13 @@ V3Global v3Global; +static void reportStatsIfEnabled() { + if (v3Global.opt.stats()) { + V3Stats::statsFinalAll(v3Global.rootp()); + V3Stats::statsReport(); + } +} + static void process() { // Sort modules by level so later algorithms don't need to care V3LinkLevel::modSortByLevel(); @@ -111,6 +119,12 @@ static void process() { // Convert parseref's to varrefs, and other directly post parsing fixups V3LinkParse::linkParse(v3Global.rootp()); + if (v3Global.opt.debugExitUvm()) { + V3Error::abortIfErrors(); + cout << "--debug-exit-uvm: Exiting after UVM-supported pass\n"; + exit(0); + } + // Cross-link signal names // Cross-link dotted hierarchical references V3LinkDot::linkDotPrimary(v3Global.rootp()); @@ -139,6 +153,17 @@ static void process() { V3Dead::deadifyModules(v3Global.rootp()); v3Global.checkTree(); + // Create a hierarchical verilation plan + if (!v3Global.opt.lintOnly() && !v3Global.opt.xmlOnly() && v3Global.opt.hierarchical()) { + V3HierBlockPlan::createPlan(v3Global.rootp()); + // If a plan is created, further analysis is not necessary. + // The actual Verilation will be done based on this plan. + if (v3Global.hierPlanp()) { + reportStatsIfEnabled(); + return; + } + } + // Calculate and check widths, edit tree to TRUNC/EXTRACT any width mismatches V3Width::width(v3Global.rootp()); @@ -496,10 +521,7 @@ static void process() { } // Statistics - if (v3Global.opt.stats()) { - V3Stats::statsFinalAll(v3Global.rootp()); - V3Stats::statsReport(); - } + reportStatsIfEnabled(); if (!v3Global.opt.lintOnly() && !v3Global.opt.xmlOnly() && !v3Global.opt.dpiHdrOnly()) { // Makefile must be after all other emitters @@ -517,8 +539,9 @@ static void verilate(const string& argString) { // Can we skip doing everything if times are ok? V3File::addSrcDepend(v3Global.opt.bin()); if (v3Global.opt.skipIdentical().isTrue() - && V3File::checkTimes( - v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "__verFiles.dat", argString)) { + && V3File::checkTimes(v3Global.opt.hierTopDataDir() + "/" + v3Global.opt.prefix() + + "__verFiles.dat", + argString)) { UINFO(1, "--skip-identical: No change to any source files, exiting\n"); return; } @@ -531,9 +554,9 @@ static void verilate(const string& argString) { //--FRONTEND------------------ // Cleanup - V3Os::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix() + "_*.tree"); - V3Os::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix() + "_*.dot"); - V3Os::unlinkRegexp(v3Global.opt.makeDir(), v3Global.opt.prefix() + "_*.txt"); + V3Os::unlinkRegexp(v3Global.opt.hierTopDataDir(), v3Global.opt.prefix() + "_*.tree"); + V3Os::unlinkRegexp(v3Global.opt.hierTopDataDir(), v3Global.opt.prefix() + "_*.dot"); + V3Os::unlinkRegexp(v3Global.opt.hierTopDataDir(), v3Global.opt.prefix() + "_*.txt"); // Internal tests (after option parsing as need debug() setting, // and after removing files as may make debug output) @@ -567,15 +590,32 @@ static void verilate(const string& argString) { V3Error::abortIfWarnings(); + if (v3Global.hierPlanp()) { // This run is for just write a makefile + UASSERT(v3Global.opt.hierarchical(), "hierarchical must be set"); + UASSERT(!v3Global.opt.hierChild(), "This must not be a hierarhcical-child run"); + UASSERT(v3Global.opt.hierBlocks().empty(), "hierarchical-block must not be set"); + if (v3Global.opt.gmake()) { + v3Global.hierPlanp()->writeCommandArgsFiles(false); + V3EmitMk::emitHierVerilation(v3Global.hierPlanp()); + } + if (v3Global.opt.cmake()) { + v3Global.hierPlanp()->writeCommandArgsFiles(true); + V3EmitCMake::emit(); + } + } if (v3Global.opt.makeDepend().isTrue()) { - V3File::writeDepend(v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "__ver.d"); + string filename = v3Global.opt.makeDir() + "/" + v3Global.opt.prefix(); + filename += v3Global.opt.hierTop() ? "__hierVer.d" : "__ver.d"; + V3File::writeDepend(filename); } if (v3Global.opt.protectIds()) { - VIdProtect::writeMapFile(v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + VIdProtect::writeMapFile(v3Global.opt.hierTopDataDir() + "/" + v3Global.opt.prefix() + "__idmap.xml"); } + if (v3Global.opt.skipIdentical().isTrue() || v3Global.opt.makeDepend().isTrue()) { - V3File::writeTimes(v3Global.opt.makeDir() + "/" + v3Global.opt.prefix() + "__verFiles.dat", + V3File::writeTimes(v3Global.opt.hierTopDataDir() + "/" + v3Global.opt.prefix() + + "__verFiles.dat", argString); } @@ -602,10 +642,8 @@ static string buildMakeCmd(const string& makefile, const string& target) { } else if (jobs > 1) { cmd << " -j " << jobs; } - for (V3StringList::const_iterator it = makeFlags.begin(); it != makeFlags.end(); ++it) { - cmd << ' ' << *it; - } - if (!target.empty()) { cmd << ' ' << target; } + for (const string& flag : makeFlags) cmd << ' ' << flag; + if (!target.empty()) cmd << ' ' << target; return cmd.str(); } @@ -624,6 +662,18 @@ static void execBuildJob() { } } +static void execHierVerilation() { + UASSERT(v3Global.hierPlanp(), "must be called only when plan exists"); + const string makefile = v3Global.opt.prefix() + "_hier.mk "; + const string target = v3Global.opt.build() ? " hier_build" : " hier_verilation"; + const string cmdStr = buildMakeCmd(makefile, target); + const int exit_code = V3Os::system(cmdStr); + if (exit_code != 0) { + v3error(cmdStr << " exitted with " << exit_code << std::endl); + exit(exit_code); + } +} + //###################################################################### int main(int argc, char** argv, char** env) { @@ -658,7 +708,14 @@ int main(int argc, char** argv, char** env) { UINFO(1, "Option --no-verilate: Skip Verilation\n"); } - if (v3Global.opt.build()) execBuildJob(); + if (v3Global.hierPlanp() && v3Global.opt.gmake()) { + execHierVerilation(); // execHierVerilation() takes care of --build too + } else if (v3Global.opt.build()) { + execBuildJob(); + } + + // Explicitly release resources + v3Global.shutdown(); UINFO(1, "Done, Exiting...\n"); } diff --git a/src/VlcBucket.h b/src/VlcBucket.h index b422c9e95..97df0c4b1 100644 --- a/src/VlcBucket.h +++ b/src/VlcBucket.h @@ -28,9 +28,9 @@ class VlcBuckets { private: // MEMBERS - vluint64_t* m_datap; ///< Pointer to first bucket (dynamically allocated) - vluint64_t m_dataSize; ///< Current entries in m_datap - vluint64_t m_bucketsCovered; ///< Num buckets with sufficient coverage + vluint64_t* m_datap = nullptr; ///< Pointer to first bucket (dynamically allocated) + vluint64_t m_dataSize = 0; ///< Current entries in m_datap + vluint64_t m_bucketsCovered = 0; ///< Num buckets with sufficient coverage static inline vluint64_t covBit(vluint64_t point) { return 1ULL << (point & 63); } inline vluint64_t allocSize() const { return sizeof(vluint64_t) * m_dataSize / 64; } @@ -51,15 +51,10 @@ private: public: // CONSTRUCTORS - VlcBuckets() { - m_dataSize = 0; - m_datap = NULL; - m_bucketsCovered = 0; - allocate(1024); - } + VlcBuckets() { allocate(1024); } ~VlcBuckets() { m_dataSize = 0; - VL_DO_CLEAR(free(m_datap), m_datap = NULL); + VL_DO_CLEAR(free(m_datap), m_datap = nullptr); } // ACCESSORS diff --git a/src/VlcMain.cpp b/src/VlcMain.cpp index c004e8efc..6375c2a09 100644 --- a/src/VlcMain.cpp +++ b/src/VlcMain.cpp @@ -154,10 +154,7 @@ int main(int argc, char** argv, char** /*env*/) { { const VlStringSet& readFiles = top.opt.readFiles(); - for (VlStringSet::const_iterator it = readFiles.begin(); it != readFiles.end(); ++it) { - string filename = *it; - top.readCoverage(filename); - } + for (const auto& filename : readFiles) top.readCoverage(filename); } if (debug() >= 9) { @@ -179,10 +176,7 @@ int main(int argc, char** argv, char** /*env*/) { V3Error::abortIfWarnings(); if (top.opt.unlink()) { const VlStringSet& readFiles = top.opt.readFiles(); - for (VlStringSet::const_iterator it = readFiles.begin(); it != readFiles.end(); ++it) { - string filename = *it; - unlink(filename.c_str()); - } + for (const auto& filename : readFiles) { unlink(filename.c_str()); } } } diff --git a/src/VlcOptions.h b/src/VlcOptions.h index 74e8c6380..423bfd1eb 100644 --- a/src/VlcOptions.h +++ b/src/VlcOptions.h @@ -35,11 +35,11 @@ class VlcOptions { // MEMBERS (general options) // clang-format off string m_annotateOut; // main switch: --annotate I - bool m_annotateAll; // main switch: --annotate-all - int m_annotateMin; // main switch: --annotate-min I + bool m_annotateAll=false; // main switch: --annotate-all + int m_annotateMin=10; // main switch: --annotate-min I VlStringSet m_readFiles; // main switch: --read - bool m_rank; // main switch: --rank - bool m_unlink; // main switch: --unlink + bool m_rank=false; // main switch: --rank + bool m_unlink=false; // main switch: --unlink string m_writeFile; // main switch: --write string m_writeInfoFile; // main switch: --write-info // clang-format on @@ -51,12 +51,7 @@ private: public: // CONSTRUCTORS - VlcOptions() { - m_annotateAll = false; - m_annotateMin = 10; - m_rank = false; - m_unlink = false; - } + VlcOptions() {} ~VlcOptions() {} // METHODS diff --git a/src/VlcPoint.h b/src/VlcPoint.h index 09e059ab7..83eefd85d 100644 --- a/src/VlcPoint.h +++ b/src/VlcPoint.h @@ -24,7 +24,7 @@ #include #include -#include VL_INCLUDE_UNORDERED_MAP +#include //******************************************************************** // VlcPoint - A coverage point (across all tests) @@ -34,17 +34,14 @@ private: // MEMBERS string m_name; //< Name of the point vluint64_t m_pointNum; //< Point number - vluint64_t m_testsCovering; //< Number tests with non-zero coverage of this point - vluint64_t m_count; //< Count of hits across all tests + vluint64_t m_testsCovering = 0; //< Number tests with non-zero coverage of this point + vluint64_t m_count = 0; //< Count of hits across all tests public: // CONSTRUCTORS - VlcPoint(const string& name, int pointNum) { - m_name = name; - m_pointNum = pointNum; - m_testsCovering = 0; - m_count = 0; - } + VlcPoint(const string& name, vluint64_t pointNum) + : m_name{name} + , m_pointNum{pointNum} {} ~VlcPoint() {} // ACCESSORS const string& name() const { return m_name; } @@ -99,7 +96,7 @@ private: typedef std::map NameMap; // Sorted by name (ordered) NameMap m_nameMap; //< Name to point-number std::vector m_points; //< List of all points - vluint64_t m_numPoints; //< Total unique points + vluint64_t m_numPoints = 0; //< Total unique points public: // ITERATORS @@ -109,23 +106,22 @@ public: ByName::iterator end() { return m_nameMap.end(); } // CONSTRUCTORS - VlcPoints() - : m_numPoints(0) {} + VlcPoints() {} ~VlcPoints() {} // METHODS void dump() { UINFO(2, "dumpPoints...\n"); VlcPoint::dumpHeader(); - for (VlcPoints::ByName::const_iterator it = begin(); it != end(); ++it) { - const VlcPoint& point = pointNumber(it->second); + for (const auto& i : *this) { + const VlcPoint& point = pointNumber(i.second); point.dump(); } } VlcPoint& pointNumber(vluint64_t num) { return m_points[num]; } vluint64_t findAddPoint(const string& name, vluint64_t count) { vluint64_t pointnum; - NameMap::const_iterator iter = m_nameMap.find(name); + const auto iter = m_nameMap.find(name); if (iter != m_nameMap.end()) { pointnum = iter->second; m_points[pointnum].countInc(count); diff --git a/src/VlcSource.h b/src/VlcSource.h index 9e438d9b2..4f8e90e19 100644 --- a/src/VlcSource.h +++ b/src/VlcSource.h @@ -31,17 +31,14 @@ private: // MEMBERS int m_lineno; ///< Line number int m_column; ///< Column number - vluint64_t m_count; ///< Count - bool m_ok; ///< Coverage is above threshold + vluint64_t m_count = 0; ///< Count + bool m_ok = false; ///< Coverage is above threshold public: // CONSTRUCTORS - VlcSourceCount(int lineno, int column) { - m_lineno = lineno; - m_column = column; - m_count = 0; - m_ok = false; - } + VlcSourceCount(int lineno, int column) + : m_lineno{lineno} + , m_column{column} {} ~VlcSourceCount() {} // ACCESSORS @@ -69,15 +66,13 @@ public: private: // MEMBERS string m_name; //< Name of the source file - bool m_needed; //< Need to annotate; has low coverage + bool m_needed = false; //< Need to annotate; has low coverage LinenoMap m_lines; //< Map of each annotated line public: // CONSTRUCTORS - explicit VlcSource(const string& name) { - m_name = name; - m_needed = false; - } + explicit VlcSource(const string& name) + : m_name{name} {} ~VlcSource() {} // ACCESSORS diff --git a/src/VlcTest.h b/src/VlcTest.h index dd0a6ccea..d1489e661 100644 --- a/src/VlcTest.h +++ b/src/VlcTest.h @@ -35,21 +35,17 @@ private: string m_name; //< Name of the test double m_computrons; //< Runtime for the test vluint64_t m_testrun; //< Test run number, for database use - vluint64_t m_rank; //< Execution rank suggestion - vluint64_t m_rankPoints; //< Ranked additional points - vluint64_t m_user; //< User data for algorithms (not persisted in .dat file) + vluint64_t m_rank = 0; //< Execution rank suggestion + vluint64_t m_rankPoints = 0; //< Ranked additional points + vluint64_t m_user = 0; //< User data for algorithms (not persisted in .dat file) VlcBuckets m_buckets; //< Coverage data for each coverage point public: // CONSTRUCTORS - VlcTest(const string& name, vluint64_t testrun, double comp) { - m_name = name; - m_computrons = comp; - m_testrun = testrun; - m_rank = 0; - m_rankPoints = 0; - m_user = 0; - } + VlcTest(const string& name, vluint64_t testrun, double comp) + : m_name{name} + , m_computrons{comp} + , m_testrun{testrun} {} ~VlcTest() {} // ACCESSORS @@ -106,18 +102,14 @@ public: // CONSTRUCTORS VlcTests() {} ~VlcTests() { - for (VlcTests::ByName::iterator it = begin(); it != end(); ++it) { - VL_DO_CLEAR(delete *it, *it = NULL); - } + for (auto it = begin(); it != end(); ++it) { VL_DO_CLEAR(delete *it, *it = nullptr); } } // METHODS void dump(bool bucketsToo) { UINFO(2, "dumpTests...\n"); VlcTest::dumpHeader(); - for (VlcTests::ByName::const_iterator it = begin(); it != end(); ++it) { - (*it)->dump(bucketsToo); - } + for (const auto& testp : m_tests) testp->dump(bucketsToo); } VlcTest* newTest(const string& name, vluint64_t testrun, double comp) { VlcTest* testp = new VlcTest(name, testrun, comp); @@ -125,7 +117,7 @@ public: return testp; } void clearUser() { - for (ByName::iterator it = m_tests.begin(); it != m_tests.end(); ++it) (*it)->user(0); + for (const auto& testp : m_tests) testp->user(0); } }; diff --git a/src/VlcTop.cpp b/src/VlcTop.cpp index 67f74570c..4ff050d5f 100644 --- a/src/VlcTop.cpp +++ b/src/VlcTop.cpp @@ -70,8 +70,8 @@ void VlcTop::writeCoverage(const string& filename) { } os << "# SystemC::Coverage-3" << endl; - for (VlcPoints::ByName::const_iterator it = m_points.begin(); it != m_points.end(); ++it) { - const VlcPoint& point = m_points.pointNumber(it->second); + for (const auto& i : m_points) { + const VlcPoint& point = m_points.pointNumber(i.second); os << "C '" << point.name() << "' " << point.count() << endl; } } @@ -107,17 +107,17 @@ void VlcTop::writeInfo(const string& filename) { // end_of_record os << "TN:verilator_coverage\n"; - for (VlcSources::NameMap::iterator sit = m_sources.begin(); sit != m_sources.end(); ++sit) { - VlcSource& source = sit->second; + for (auto& si : m_sources) { + VlcSource& source = si.second; os << "SF:" << source.name() << endl; VlcSource::LinenoMap& lines = source.lines(); - for (VlcSource::LinenoMap::iterator lit = lines.begin(); lit != lines.end(); ++lit) { - int lineno = lit->first; - VlcSource::ColumnMap& cmap = lit->second; + for (auto& li : lines) { + int lineno = li.first; + VlcSource::ColumnMap& cmap = li.second; bool first = true; vluint64_t min_count = 0; // Minimum across all columns on line - for (VlcSource::ColumnMap::iterator cit = cmap.begin(); cit != cmap.end(); ++cit) { - VlcSourceCount& col = cit->second; + for (auto& ci : cmap) { + VlcSourceCount& col = ci.second; if (first) { min_count = col.count(); first = false; @@ -148,17 +148,16 @@ void VlcTop::rank() { // Sort by computrons, so fast tests get selected first std::vector bytime; - for (VlcTests::ByName::const_iterator it = m_tests.begin(); it != m_tests.end(); ++it) { - VlcTest* testp = *it; + for (const auto& testp : m_tests) { if (testp->bucketsCovered()) { // else no points, so can't help us - bytime.push_back(*it); + bytime.push_back(testp); } } sort(bytime.begin(), bytime.end(), CmpComputrons()); // Sort the vector VlcBuckets remaining; - for (VlcPoints::ByName::const_iterator it = m_points.begin(); it != m_points.end(); ++it) { - VlcPoint* pointp = &points().pointNumber(it->second); + for (const auto& i : m_points) { + VlcPoint* pointp = &points().pointNumber(i.second); // If any tests hit this point, then we'll need to cover it. if (pointp->testsCovering()) remaining.addData(pointp->pointNum(), 1); } @@ -172,10 +171,9 @@ void VlcTop::rank() { UINFO(9, "Left on iter" << nextrank << ": "); // LCOV_EXCL_LINE remaining.dump(); // LCOV_EXCL_LINE } - VlcTest* bestTestp = NULL; + VlcTest* bestTestp = nullptr; vluint64_t bestRemain = 0; - for (std::vector::iterator it = bytime.begin(); it != bytime.end(); ++it) { - VlcTest* testp = *it; + for (const auto& testp : bytime) { if (!testp->rank()) { vluint64_t remain = testp->buckets().dataPopCount(remaining); if (remain > bestRemain) { @@ -198,8 +196,8 @@ void VlcTop::rank() { void VlcTop::annotateCalc() { // Calculate per-line information into filedata structure - for (VlcPoints::ByName::const_iterator it = m_points.begin(); it != m_points.end(); ++it) { - const VlcPoint& point = m_points.pointNumber(it->second); + for (const auto& i : m_points) { + const VlcPoint& point = m_points.pointNumber(i.second); string filename = point.filename(); int lineno = point.lineno(); if (!filename.empty() && lineno != 0) { @@ -244,15 +242,15 @@ void VlcTop::annotateCalcNeeded() { // coverage in all categories int totCases = 0; int totOk = 0; - for (VlcSources::NameMap::iterator sit = m_sources.begin(); sit != m_sources.end(); ++sit) { - VlcSource& source = sit->second; + for (auto& si : m_sources) { + VlcSource& source = si.second; // UINFO(1,"Source "<second; - for (VlcSource::ColumnMap::iterator cit = cmap.begin(); cit != cmap.end(); ++cit) { - VlcSourceCount& col = cit->second; + for (auto& li : lines) { + VlcSource::ColumnMap& cmap = li.second; + for (auto& ci : cmap) { + VlcSourceCount& col = ci.second; // UINFO(0,"Source "<second; + for (auto& si : m_sources) { + VlcSource& source = si.second; if (!source.needed()) continue; string filename = source.name(); string outfilename = dirname + "/" + V3Os::filenameNonDir(filename); @@ -302,11 +300,11 @@ void VlcTop::annotateOutputFiles(const string& dirname) { bool first = true; VlcSource::LinenoMap& lines = source.lines(); - VlcSource::LinenoMap::iterator lit = lines.find(lineno); + const auto lit = lines.find(lineno); if (lit != lines.end()) { VlcSource::ColumnMap& cmap = lit->second; - for (VlcSource::ColumnMap::iterator cit = cmap.begin(); cit != cmap.end(); ++cit) { - VlcSourceCount& col = cit->second; + for (auto& ci : cmap) { + VlcSourceCount& col = ci.second; // UINFO(0,"Source // "<print(" // Generated by astgen with short-circuiting\n", - " virtual void visit(Ast${type}* nodep) VL_OVERRIDE {\n", + " virtual void visit(Ast${type}* nodep) override {\n", " iterateAndNextNull(nodep->lhsp());\n", @out_for_type_sc); $self->print(" iterateAndNextNull(nodep->rhsp());\n", @@ -720,7 +720,7 @@ sub tree_base { } elsif ($out_for_type[0]) { # Other types with something to print my $skip = $self->{tree_skip_visit}{$type}; my $gen = $skip ? "Gen" : ""; - my $override = $skip ? "" : " VL_OVERRIDE"; + my $override = $skip ? "" : " override"; $self->print(" // Generated by astgen\n", " virtual void visit$gen(Ast${type}* nodep)${override} {\n", ($skip?"": diff --git a/src/flexfix b/src/flexfix index 85c8abb72..616ddb5a1 100755 --- a/src/flexfix +++ b/src/flexfix @@ -34,6 +34,8 @@ foreach my $line () { $line =~ s!--accepting rule at line %d !--accepting rule at line %ld !g; # Fix compiler warning filenames $line =~ s!(#line \d+ ".*)_pretmp!$1!; + # Fix 'register' storage class specifier is deprecated and incompatible with C++17 + $line =~ s!register !!g; print "$line"; } diff --git a/src/verilog.l b/src/verilog.l index f21a64f1c..a357f122c 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -116,6 +116,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "coverage_off" { FL; return yVLT_COVERAGE_OFF; } "coverage_on" { FL; return yVLT_COVERAGE_ON; } "full_case" { FL; return yVLT_FULL_CASE; } + "hier_block" { FL; return yVLT_HIER_BLOCK; } "inline" { FL; return yVLT_INLINE; } "isolate_assignments" { FL; return yVLT_ISOLATE_ASSIGNMENTS; } "lint_off" { FL; return yVLT_LINT_OFF; } @@ -255,10 +256,12 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "$tanh" { FL; return yD_TANH; } "$test$plusargs" { FL; return yD_TESTPLUSARGS; } "$time" { FL; return yD_TIME; } - "$timeskew" { FL; return yaTIMINGSPEC; } "$timeformat" { FL; return yD_TIMEFORMAT; } + "$timeskew" { FL; return yaTIMINGSPEC; } "$typename" { FL; return yD_TYPENAME; } "$ungetc" { FL; return yD_UNGETC; } + "$urandom" { FL; return yD_URANDOM; } + "$urandom_range" { FL; return yD_URANDOM_RANGE; } "$value$plusargs" { FL; return yD_VALUEPLUSARGS; } "$width" { FL; return yaTIMINGSPEC; } "$write" { FL; return yD_WRITE; } @@ -417,6 +420,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} { /* System Tasks */ "$bits" { FL; return yD_BITS; } + "$changed" { FL; return yD_CHANGED; } "$countbits" { FL; return yD_COUNTBITS; } "$countones" { FL; return yD_COUNTONES; } "$dimensions" { FL; return yD_DIMENSIONS; } @@ -695,6 +699,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "/*verilator coverage_off*/" { FL_FWD; PARSEP->lexFileline()->coverageOn(false); FL_BRK; } "/*verilator coverage_on*/" { FL_FWD; PARSEP->lexFileline()->coverageOn(true); FL_BRK; } "/*verilator full_case*/" { FL; return yVL_FULL_CASE; } + "/*verilator hier_block*/" { FL; return yVL_HIER_BLOCK; } "/*verilator inline_module*/" { FL; return yVL_INLINE_MODULE; } "/*verilator isolate_assignments*/" { FL; return yVL_ISOLATE_ASSIGNMENTS; } "/*verilator lint_off"[^*]*"*/" { FL; PARSEP->lexVerilatorCmtLint(yylval.fl, yytext, true); FL_BRK; } @@ -711,10 +716,9 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "/*verilator public_flat_rw*/" { FL; return yVL_PUBLIC_FLAT_RW; } // The @(edge) is converted by the preproc "/*verilator public_module*/" { FL; return yVL_PUBLIC_MODULE; } "/*verilator sc_bv*/" { FL; return yVL_SC_BV; } - "/*verilator sc_clock*/" { FL; return yVL_CLOCK; } + "/*verilator sc_clock*/" { FL; yylval.fl->v3warn(DEPRECATED, "sc_clock is ignored"); FL_BRK; } "/*verilator sformat*/" { FL; return yVL_SFORMAT; } "/*verilator split_var*/" { FL; return yVL_SPLIT_VAR; } - "/*verilator systemc_clock*/" { FL; return yVL_CLOCK; } "/*verilator tag"[^*]*"*/" { FL; yylval.strp = PARSEP->newString(V3ParseImp::lexParseTag(yytext)); return yVL_TAG; } "/*verilator tracing_off*/" { FL_FWD; PARSEP->lexFileline()->tracingOn(false); FL_BRK; } diff --git a/src/verilog.y b/src/verilog.y index 9ae8db91a..c9b2e8648 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -50,46 +50,32 @@ class V3ParseGrammar { public: - bool m_impliedDecl; // Allow implied wire declarations + bool m_impliedDecl = false; // Allow implied wire declarations AstVarType m_varDecl; // Type for next signal declaration (reg/wire/etc) - bool m_varDeclTyped; // Var got reg/wire for dedup check + bool m_varDeclTyped = false; // Var got reg/wire for dedup check VDirection m_varIO; // Direction for next signal declaration (reg/wire/etc) VLifetime m_varLifetime; // Static/Automatic for next signal - AstVar* m_varAttrp; // Current variable for attribute adding - AstRange* m_gateRangep; // Current range for gate declarations - AstCase* m_caseAttrp; // Current case statement for attribute adding - AstNodeDType* m_varDTypep; // Pointer to data type for next signal declaration - AstNodeDType* m_memDTypep; // Pointer to data type for next member declaration - AstNodeModule* m_modp; // Last module for timeunits - bool m_pinAnsi; // In ANSI port list - FileLine* m_instModuleFl; // Fileline of module referenced for instantiations + AstVar* m_varAttrp = nullptr; // Current variable for attribute adding + AstRange* m_gateRangep = nullptr; // Current range for gate declarations + AstCase* m_caseAttrp = nullptr; // Current case statement for attribute adding + AstNodeDType* m_varDTypep = nullptr; // Pointer to data type for next signal declaration + AstNodeDType* m_memDTypep = nullptr; // Pointer to data type for next member declaration + AstNodeModule* m_modp = nullptr; // Last module for timeunits + bool m_pinAnsi = false; // In ANSI port list + FileLine* m_instModuleFl = nullptr; // Fileline of module referenced for instantiations string m_instModule; // Name of module referenced for instantiations - AstPin* m_instParamp; // Parameters for instantiations - bool m_tracingParse; // Tracing disable for parser + AstPin* m_instParamp = nullptr; // Parameters for instantiations + bool m_tracingParse = true; // Tracing disable for parser - int m_pinNum; // Pin number currently parsing + int m_pinNum = -1; // Pin number currently parsing std::stack m_pinStack; // Queue of pin numbers being parsed static int s_modTypeImpNum; // Implicit type number, incremented each module // CONSTRUCTORS V3ParseGrammar() { - m_impliedDecl = false; m_varDecl = AstVarType::UNKNOWN; - m_varDeclTyped = false; m_varIO = VDirection::NONE; - m_varDTypep = NULL; - m_gateRangep = NULL; - m_memDTypep = NULL; - m_modp = NULL; - m_pinAnsi = false; - m_pinNum = -1; - m_instModuleFl = NULL; - m_instModule = ""; - m_instParamp = NULL; - m_varAttrp = NULL; - m_caseAttrp = NULL; - m_tracingParse = true; } static V3ParseGrammar* singletonp() { static V3ParseGrammar singleton; @@ -111,7 +97,8 @@ public: return new AstText(fileline, newtext); } AstDisplay* createDisplayError(FileLine* fileline) { - AstDisplay* nodep = new AstDisplay(fileline, AstDisplayType::DT_ERROR, "", NULL, NULL); + AstDisplay* nodep + = new AstDisplay(fileline, AstDisplayType::DT_ERROR, "", nullptr, nullptr); nodep->addNext(new AstStop(fileline, true)); return nodep; } @@ -135,7 +122,7 @@ public: } void setVarDecl(AstVarType type) { m_varDecl = type; } void setDType(AstNodeDType* dtypep) { - if (m_varDTypep) VL_DO_CLEAR(m_varDTypep->deleteTree(), m_varDTypep = NULL); + if (m_varDTypep) VL_DO_CLEAR(m_varDTypep->deleteTree(), m_varDTypep = nullptr); m_varDTypep = dtypep; } void pinPush() { @@ -167,7 +154,7 @@ public: // If rangesp is "wire [3:3][2:2][1:1] foo [5:5][4:4]" // then [1:1] becomes the basicdtype range; everything else is arraying // the final [5:5][4:4] will be passed in another call to createArray - AstNodeRange* rangearraysp = NULL; + AstNodeRange* rangearraysp = nullptr; if (dtypep->isRanged()) { rangearraysp = rangesp; // Already a range; everything is an array } else { @@ -230,7 +217,7 @@ int V3ParseGrammar::s_modTypeImpNum = 0; { \ VARDECL(UNKNOWN); \ VARIO(NONE); \ - VARDTYPE_NDECL(NULL); \ + VARDTYPE_NDECL(nullptr); \ GRAMMARP->m_varLifetime = VLifetime::NONE; \ GRAMMARP->m_varDeclTyped = false; \ } @@ -314,6 +301,15 @@ class AstSenTree; // Bison 3.0 and newer BISONPRE_VERSION(3.0,%define parse.error verbose) +// We run bison with the -d argument. This tells it to generate a +// header file with token names. Old versions of bison pasted the +// contents of that file into the generated source as well; newer +// versions just include it. +// +// Since we run bison through ../bisonpre, it doesn't know the correct +// header file name, so we need to tell it. +BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) + // When writing Bison patterns we use yTOKEN instead of "token", // so Bison will error out on unknown "token"s. @@ -360,6 +356,7 @@ BISONPRE_VERSION(3.0,%define parse.error verbose) %token yVLT_COVERAGE_OFF "coverage_off" %token yVLT_COVERAGE_ON "coverage_on" %token yVLT_FULL_CASE "full_case" +%token yVLT_HIER_BLOCK "hier_block" %token yVLT_INLINE "inline" %token yVLT_ISOLATE_ASSIGNMENTS "isolate_assignments" %token yVLT_LINT_OFF "lint_off" @@ -401,7 +398,7 @@ BISONPRE_VERSION(3.0,%define parse.error verbose) %token '#' %token '%' %token '&' -%token '(' +%token '(' // See also yP_PAR__STRENGTH %token ')' %token '*' %token '+' @@ -409,7 +406,7 @@ BISONPRE_VERSION(3.0,%define parse.error verbose) %token '-' %token '.' %token '/' -%token ':' +%token ':' // See also yP_COLON__BEGIN or yP_COLON__FORK %token ';' %token '<' %token '=' @@ -693,6 +690,7 @@ BISONPRE_VERSION(3.0,%define parse.error verbose) %token yD_C "$c" %token yD_CAST "$cast" %token yD_CEIL "$ceil" +%token yD_CHANGED "$changed" %token yD_CLOG2 "$clog2" %token yD_COS "$cos" %token yD_COSH "$cosh" @@ -791,6 +789,8 @@ BISONPRE_VERSION(3.0,%define parse.error verbose) %token yD_UNIT "$unit" %token yD_UNPACKED_DIMENSIONS "$unpacked_dimensions" %token yD_UNSIGNED "$unsigned" +%token yD_URANDOM "$urandom" +%token yD_URANDOM_RANGE "$urandom_range" %token yD_VALUEPLUSARGS "$value$plusargs" %token yD_WARNING "$warning" %token yD_WRITE "$write" @@ -800,11 +800,11 @@ BISONPRE_VERSION(3.0,%define parse.error verbose) %token yD_WRITEMEMH "$writememh" %token yD_WRITEO "$writeo" -%token yVL_CLOCK "/*verilator sc_clock*/" %token yVL_CLOCKER "/*verilator clocker*/" %token yVL_CLOCK_ENABLE "/*verilator clock_enable*/" %token yVL_COVERAGE_BLOCK_OFF "/*verilator coverage_block_off*/" %token yVL_FULL_CASE "/*verilator full_case*/" +%token yVL_HIER_BLOCK "/*verilator hier_block*/" %token yVL_INLINE_MODULE "/*verilator inline_module*/" %token yVL_ISOLATE_ASSIGNMENTS "/*verilator isolate_assignments*/" %token yVL_NO_CLOCKER "/*verilator no_clocker*/" @@ -842,6 +842,8 @@ BISONPRE_VERSION(3.0,%define parse.error verbose) %token yP_SSRIGHT ">>>" %token yP_POW "**" +%token yP_COLON__BEGIN ":-begin" +%token yP_COLON__FORK ":-fork" //UNSUP %token yP_PAR__IGNORE "(-ignored" // Used when sequence_expr:expr:( is ignored %token yP_PAR__STRENGTH "(-for-strength" @@ -928,7 +930,7 @@ BISONPRE_VERSION(3.0,%define parse.error verbose) // Verilog op precedence %right yP_MINUSGT yP_LTMINUSGT -%right '?' ':' +%right '?' ':' yP_COLON__BEGIN yP_COLON__FORK %left yP_OROR %left yP_ANDAND %left '|' yP_NOR @@ -1025,11 +1027,11 @@ description: // ==IEEE: description timeunits_declaration: // ==IEEE: timeunits_declaration yTIMEUNIT yaTIMENUM ';' - { PARSEP->timescaleMod($2, GRAMMARP->m_modp, true, $2, false, 0); $$ = NULL; } + { PARSEP->timescaleMod($2, GRAMMARP->m_modp, true, $2, false, 0); $$ = nullptr; } | yTIMEUNIT yaTIMENUM '/' yaTIMENUM ';' - { PARSEP->timescaleMod($2, GRAMMARP->m_modp, true, $2, true, $4); $$ = NULL; } + { PARSEP->timescaleMod($2, GRAMMARP->m_modp, true, $2, true, $4); $$ = nullptr; } | yTIMEPRECISION yaTIMENUM ';' - { PARSEP->timescaleMod($2, GRAMMARP->m_modp, false, 0, true, $2); $$ = NULL; } + { PARSEP->timescaleMod($2, GRAMMARP->m_modp, false, 0, true, $2); $$ = nullptr; } ; //********************************************************************** @@ -1039,7 +1041,7 @@ package_declaration: // ==IEEE: package_declaration packageFront package_itemListE yENDPACKAGE endLabelE { $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc if ($2) $1->addStmtp($2); - GRAMMARP->m_modp = NULL; + GRAMMARP->m_modp = nullptr; SYMP->popScope($1); GRAMMARP->endLabel($4,$1,$4); } ; @@ -1057,7 +1059,7 @@ packageFront: ; package_itemListE: // IEEE: [{ package_item }] - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | package_itemList { $$ = $1; } ; @@ -1087,7 +1089,7 @@ package_or_generate_item_declaration: // ==IEEE: package_or_generate_item | parameter_declaration ';' { $$ = $1; } //UNSUP covergroup_declaration { $$ = $1; } //UNSUP assertion_item_declaration { $$ = $1; } - | ';' { $$ = NULL; } + | ';' { $$ = nullptr; } ; package_import_declarationList: @@ -1108,7 +1110,7 @@ package_import_item: // ==IEEE: package_import_item idCC/*package_identifier*/ yP_COLONCOLON package_import_itemObj { if (!VN_CAST($1, Package)) { - $$ = NULL; + $$ = nullptr; $1->v3error("Importing from missing package '" << *$1 << "'"); } else { $$ = new AstPackageImport($2, VN_CAST($1, Package), *$3); @@ -1148,7 +1150,7 @@ module_declaration: // ==IEEE: module_declaration { $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3); if ($5) $1->addStmtp($5); - GRAMMARP->m_modp = NULL; + GRAMMARP->m_modp = nullptr; SYMP->popScope($1); GRAMMARP->endLabel($7,$1,$7); } | udpFront parameter_port_listE portsStarE ';' @@ -1157,7 +1159,7 @@ module_declaration: // ==IEEE: module_declaration if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3); if ($5) $1->addStmtp($5); GRAMMARP->m_tracingParse = true; - GRAMMARP->m_modp = NULL; + GRAMMARP->m_modp = nullptr; SYMP->popScope($1); GRAMMARP->endLabel($7,$1,$7); } // @@ -1198,7 +1200,7 @@ udpFront: ; parameter_value_assignmentE: // IEEE: [ parameter_value_assignment ] - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | parameter_value_assignment { $$ = $1; } ; @@ -1222,8 +1224,8 @@ parameter_value_assignmentClass: // IEEE: [ parameter_value_assignment ] ( ; parameter_port_listE: // IEEE: parameter_port_list + empty == parameter_value_assignment - /* empty */ { $$ = NULL; } - | '#' '(' ')' { $$ = NULL; } + /* empty */ { $$ = nullptr; } + | '#' '(' ')' { $$ = nullptr; } // // IEEE: '#' '(' list_of_param_assignments { ',' parameter_port_declaration } ')' // // IEEE: '#' '(' parameter_port_declaration { ',' parameter_port_declaration } ')' // // Can't just do that as "," conflicts with between vars and between stmts, so @@ -1241,12 +1243,12 @@ paramPortDeclOrArg: // IEEE: param_assignment + parameter_port_declaratio // // We combine the two as we can't tell which follows a comma parameter_port_declarationFrontE param_assignment { $$ = $2; } | parameter_port_declarationTypeFrontE type_assignment { $$ = $2; } - | vlTag { $$ = NULL; } + | vlTag { $$ = nullptr; } ; portsStarE: // IEEE: .* + list_of_ports + list_of_port_declarations + empty - /* empty */ { $$ = NULL; } - | '(' ')' { $$ = NULL; } + /* empty */ { $$ = nullptr; } + | '(' ')' { $$ = nullptr; } // // .* expanded from module_declaration //UNSUP '(' yP_DOTSTAR ')' { UNSUP } | '(' {VARRESET_LIST(PORT);} list_of_ports ')' { $$ = $3; VARRESET_NONLIST(UNKNOWN); } @@ -1281,9 +1283,9 @@ port: // ==IEEE: port VARDTYPE(new AstIfaceRefDType($2, $4, "", *$2, *$4)); $$->addNextNull(VARDONEP($$,$6,$7)); } | portDirNetE yINTERFACE portSig rangeListE sigAttrListE - { $$ = NULL; BBUNSUP($2, "Unsupported: virtual or generic interfaces"); } + { $$ = nullptr; BBUNSUP($2, "Unsupported: virtual or generic interfaces"); } | portDirNetE yINTERFACE '.' idAny/*modport*/ portSig rangeListE sigAttrListE - { $$ = NULL; BBUNSUP($2, "Unsupported: virtual or generic interfaces"); } + { $$ = nullptr; BBUNSUP($2, "Unsupported: virtual or generic interfaces"); } // // // IEEE: ansi_port_declaration, with [port_direction] removed // // IEEE: [ net_port_header | interface_port_header ] port_identifier { unpacked_dimension } [ '=' constant_expression ] @@ -1348,8 +1350,8 @@ portDirNetE: // IEEE: part of port, optional net type and/or direction /* empty */ { } // // Per spec, if direction given default the nettype. // // The higher level rule may override this VARDTYPE with one later in the parse. - | port_direction { VARDECL(PORT); VARDTYPE_NDECL(NULL/*default_nettype*/); } - | port_direction { VARDECL(PORT); } net_type { VARDTYPE_NDECL(NULL/*default_nettype*/); } // net_type calls VARDECL + | port_direction { VARDECL(PORT); VARDTYPE_NDECL(nullptr/*default_nettype*/); } + | port_direction { VARDECL(PORT); } net_type { VARDTYPE_NDECL(nullptr/*default_nettype*/); } // net_type calls VARDECL | net_type { } // net_type calls VARDECL ; @@ -1388,7 +1390,7 @@ intFront: ; interface_itemListE: - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | interface_itemList { $$ = $1; } ; @@ -1403,10 +1405,10 @@ interface_item: // IEEE: interface_item + non_port_interface_item // // IEEE: generate_region | interface_generate_region { $$ = $1; } | interface_or_generate_item { $$ = $1; } - | program_declaration { $$ = NULL; BBUNSUP(CRELINE(), "Unsupported: program decls within interface decls"); } + | program_declaration { $$ = nullptr; BBUNSUP(CRELINE(), "Unsupported: program decls within interface decls"); } // // IEEE 1800-2017: modport_item // // See instead old 2012 position in interface_or_generate_item - | interface_declaration { $$ = NULL; BBUNSUP(CRELINE(), "Unsupported: interface decls within interface decls"); } + | interface_declaration { $$ = nullptr; BBUNSUP(CRELINE(), "Unsupported: interface decls within interface decls"); } | timeunits_declaration { $$ = $1; } // // See note in interface_or_generate item | module_common_item { $$ = $1; } @@ -1414,7 +1416,7 @@ interface_item: // IEEE: interface_item + non_port_interface_item interface_generate_region: // ==IEEE: generate_region yGENERATE interface_itemList yENDGENERATE { $$ = $2; } - | yGENERATE yENDGENERATE { $$ = NULL; } + | yGENERATE yENDGENERATE { $$ = nullptr; } ; interface_or_generate_item: // ==IEEE: interface_or_generate_item @@ -1429,11 +1431,11 @@ interface_or_generate_item: // ==IEEE: interface_or_generate_item anonymous_program: // ==IEEE: anonymous_program // // See the spec - this doesn't change the scope, items still go up "top" - yPROGRAM ';' anonymous_program_itemListE yENDPROGRAM { BBUNSUP($1, "Unsupported: Anonymous programs"); $$ = NULL; } + yPROGRAM ';' anonymous_program_itemListE yENDPROGRAM { BBUNSUP($1, "Unsupported: Anonymous programs"); $$ = nullptr; } ; anonymous_program_itemListE: // IEEE: { anonymous_program_item } - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | anonymous_program_itemList { $$ = $1; } ; @@ -1448,7 +1450,7 @@ anonymous_program_item: // ==IEEE: anonymous_program_item | class_declaration { $$ = $1; } //UNSUP covergroup_declaration { $$ = $1; } // // class_constructor_declaration is part of function_declaration - | ';' { $$ = NULL; } + | ';' { $$ = nullptr; } ; program_declaration: // IEEE: program_declaration + program_nonansi_header + program_ansi_header: @@ -1458,7 +1460,7 @@ program_declaration: // IEEE: program_declaration + program_nonansi_header + pr { $1->modTrace(GRAMMARP->allTracingOn($1->fileline())); // Stash for implicit wires, etc if ($2) $1->addStmtp($2); if ($3) $1->addStmtp($3); if ($5) $1->addStmtp($5); - GRAMMARP->m_modp = NULL; + GRAMMARP->m_modp = nullptr; SYMP->popScope($1); GRAMMARP->endLabel($7,$1,$7); } | yEXTERN pgmFront parameter_port_listE portsStarE ';' @@ -1479,7 +1481,7 @@ pgmFront: ; program_itemListE: // ==IEEE: [{ program_item }] - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | program_itemList { $$ = $1; } ; @@ -1511,9 +1513,9 @@ program_generate_item: // ==IEEE: program_generate_item ; extern_tf_declaration: // ==IEEE: extern_tf_declaration - yEXTERN task_prototype ';' { $$ = NULL; BBUNSUP($1, "Unsupported: extern task"); } - | yEXTERN function_prototype ';' { $$ = NULL; BBUNSUP($1, "Unsupported: extern function"); } - | yEXTERN yFORKJOIN task_prototype ';' { $$ = NULL; BBUNSUP($1, "Unsupported: extern forkjoin"); } + yEXTERN task_prototype ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: extern task"); } + | yEXTERN function_prototype ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: extern function"); } + | yEXTERN yFORKJOIN task_prototype ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: extern forkjoin"); } ; modport_declaration: // ==IEEE: modport_declaration @@ -1544,14 +1546,14 @@ modportPortsDecl: // // IEEE: modport_simple_ports_declaration port_direction modportSimplePort { $$ = new AstModportVarRef($2, *$2, GRAMMARP->m_varIO); } // // IEEE: modport_clocking_declaration - | yCLOCKING idAny/*clocking_identifier*/ { $$ = NULL; BBUNSUP($1, "Unsupported: Modport clocking"); } + | yCLOCKING idAny/*clocking_identifier*/ { $$ = nullptr; BBUNSUP($1, "Unsupported: Modport clocking"); } // // IEEE: yIMPORT modport_tf_port // // IEEE: yEXPORT modport_tf_port // // modport_tf_port expanded here | yIMPORT id/*tf_identifier*/ { $$ = new AstModportFTaskRef($2, *$2, false); } | yEXPORT id/*tf_identifier*/ { $$ = new AstModportFTaskRef($2, *$2, true); } - | yIMPORT method_prototype { $$ = NULL; BBUNSUP($1, "Unsupported: Modport import with prototype"); } - | yEXPORT method_prototype { $$ = NULL; BBUNSUP($1, "Unsupported: Modport export with prototype"); } + | yIMPORT method_prototype { $$ = nullptr; BBUNSUP($1, "Unsupported: Modport import with prototype"); } + | yEXPORT method_prototype { $$ = nullptr; BBUNSUP($1, "Unsupported: Modport export with prototype"); } // Continuations of above after a comma. // // IEEE: modport_simple_ports_declaration | modportSimplePort { $$ = new AstModportVarRef($1,*$1,GRAMMARP->m_varIO); } @@ -1578,7 +1580,7 @@ list_of_genvar_identifiers: // IEEE: list_of_genvar_identifiers (for decl genvar_identifierDecl: // IEEE: genvar_identifier (for declaration) id/*new-genvar_identifier*/ sigAttrListE { VARRESET_NONLIST(GENVAR); VARDTYPE(new AstBasicDType($1,AstBasicDTypeKwd::INTEGER)); - $$ = VARDONEA($1, *$1, NULL, $2); } + $$ = VARDONEA($1, *$1, nullptr, $2); } ; parameter_declaration: // IEEE: local_ or parameter_declaration @@ -1714,7 +1716,7 @@ port_declaration: // ==IEEE: port_declaration /*mid*/ { VARDTYPE_NDECL(new AstBasicDType($3, LOGIC_IMPLICIT, $3)); } /*cont*/ list_of_variable_decl_assignments { $$ = $5; } | port_directionReset port_declNetE /*implicit*/ - /*mid*/ { VARDTYPE_NDECL(NULL);/*default_nettype*/} + /*mid*/ { VARDTYPE_NDECL(nullptr);/*default_nettype*/} /*cont*/ list_of_variable_decl_assignments { $$ = $4; } // // IEEE: interface_declaration // // Looks just like variable declaration unless has a period @@ -1775,7 +1777,7 @@ simple_type: // ==IEEE: simple_type // // Even though we looked up the type and have a AstNode* to it, // // we can't fully resolve it because it may have been just a forward definition. | packageClassScopeE idType - { AstRefDType* refp = new AstRefDType($2, *$2, $1, NULL); + { AstRefDType* refp = new AstRefDType($2, *$2, $1, nullptr); $$ = refp; } // // // { generate_block_identifer ... } '.' @@ -1793,7 +1795,7 @@ data_type: // ==IEEE: data_type // // IEEE: ps_covergroup_identifier // // Don't distinguish between types and classes so all these combined | packageClassScopeE idType packed_dimensionListE - { AstRefDType* refp = new AstRefDType($2, *$2, $1, NULL); + { AstRefDType* refp = new AstRefDType($2, *$2, $1, nullptr); $$ = GRAMMARP->createArray(refp, $3, true); } | packageClassScopeE idType parameter_value_assignmentClass packed_dimensionListE { AstRefDType* refp = new AstRefDType($2, *$2, $1, $3); @@ -1820,8 +1822,8 @@ data_typeNoRef: // ==IEEE: data_type, excluding class_type etc referenc // // IEEE has ['.' modport] but that will conflict with port // // declarations which decode '.' modport themselves, so // // instead see data_typeVar - | yVIRTUAL__INTERFACE yINTERFACE id/*interface*/ { $$ = NULL; BBUNSUP($1, "Unsupported: virtual interface"); } - | yVIRTUAL__anyID id/*interface*/ { $$ = NULL; BBUNSUP($1, "Unsupported: virtual data type"); } + | yVIRTUAL__INTERFACE yINTERFACE id/*interface*/ { $$ = nullptr; BBUNSUP($1, "Unsupported: virtual interface"); } + | yVIRTUAL__anyID id/*interface*/ { $$ = nullptr; BBUNSUP($1, "Unsupported: virtual data type"); } | type_reference { $$ = $1; } // // IEEE: class_scope: see data_type above // // IEEE: class_type: see data_type above @@ -1865,8 +1867,8 @@ struct_union_member: // ==IEEE: struct_union_member // // UNSUP random_qualifer not propagagted until have randomize support random_qualifierE data_type_or_void /*mid*/ { GRAMMARP->m_memDTypep = $2; } // As a list follows, need to attach this dtype to each member. - /*cont*/ list_of_member_decl_assignments ';' { $$ = $4; GRAMMARP->m_memDTypep = NULL; } - | vlTag { $$ = NULL; } + /*cont*/ list_of_member_decl_assignments ';' { $$ = $4; GRAMMARP->m_memDTypep = nullptr; } + | vlTag { $$ = nullptr; } ; list_of_member_decl_assignments: // Derived from IEEE: list_of_variable_decl_assignments @@ -1885,8 +1887,8 @@ member_decl_assignment: // Derived from IEEE: variable_decl_assignment | id variable_dimensionListE '=' variable_declExpr { BBUNSUP($4, "Unsupported: Initial values in struct/union members."); // But still need error if packed according to IEEE 7.2.2 - $$ = NULL; } - | idSVKwd { $$ = NULL; } + $$ = nullptr; } + | idSVKwd { $$ = nullptr; } // // // IEEE: "dynamic_array_variable_identifier '[' ']' [ '=' dynamic_array_new ]" // // Matches above with variable_dimensionE = "[]" @@ -1896,7 +1898,7 @@ member_decl_assignment: // Derived from IEEE: variable_decl_assignment // // // IEEE: "[ covergroup_variable_identifier ] '=' class_new // // Pushed into variable_declExpr:class_new - | '=' class_new { NULL; BBUNSUP($1, "Unsupported: member declaration assignment with new()"); } + | '=' class_new { nullptr; BBUNSUP($1, "Unsupported: member declaration assignment with new()"); } ; list_of_variable_decl_assignments: // ==IEEE: list_of_variable_decl_assignments @@ -1909,7 +1911,7 @@ variable_decl_assignment: // ==IEEE: variable_decl_assignment { $$ = VARDONEA($1,*$1,$2,$3); } | id variable_dimensionListE sigAttrListE '=' variable_declExpr { $$ = VARDONEA($1,*$1,$2,$3); $$->valuep($5); } - | idSVKwd { $$ = NULL; } + | idSVKwd { $$ = nullptr; } // // // IEEE: "dynamic_array_variable_identifier '[' ']' [ '=' dynamic_array_new ]" // // Matches above with variable_dimensionE = "[]" @@ -1919,7 +1921,7 @@ variable_decl_assignment: // ==IEEE: variable_decl_assignment // // // IEEE: "[ covergroup_variable_identifier ] '=' class_new // // Pushed into variable_declExpr:class_new - | '=' class_new { NULL; BBUNSUP($1, "Unsupported: declaration assignment with new()"); } + | '=' class_new { nullptr; BBUNSUP($1, "Unsupported: declaration assignment with new()"); } ; list_of_tf_variable_identifiers: // ==IEEE: list_of_tf_variable_identifiers @@ -1940,7 +1942,7 @@ variable_declExpr: // IEEE: part of variable_decl_assignment - rhs of ex ; variable_dimensionListE: // IEEE: variable_dimension + empty - /*empty*/ { $$ = NULL; } + /*empty*/ { $$ = nullptr; } | variable_dimensionList { $$ = $1; } ; @@ -1958,8 +1960,8 @@ variable_dimension: // ==IEEE: variable_dimension // // IEEE: associative_dimension (if data_type) // // Can't tell which until see if expr is data type or not | '[' exprOrDataType ']' { $$ = new AstBracketRange($1, $2); } - | yP_BRASTAR ']' { $$ = NULL; BBUNSUP($1, "Unsupported: [*] wildcard associative arrays"); } - | '[' '*' ']' { $$ = NULL; BBUNSUP($2, "Unsupported: [*] wildcard associative arrays"); } + | yP_BRASTAR ']' { $$ = nullptr; BBUNSUP($1, "Unsupported: [*] wildcard associative arrays"); } + | '[' '*' ']' { $$ = nullptr; BBUNSUP($2, "Unsupported: [*] wildcard associative arrays"); } // // IEEE: queue_dimension // // '[' '$' ']' -- $ is part of expr, see '[' constExpr ']' // // '[' '$' ':' expr ']' -- anyrange:expr:$ @@ -2011,7 +2013,7 @@ enum_base_typeE: // IEEE: enum_base_type | idAny rangeListE { $$ = GRAMMARP->createArray(new AstRefDType($1, *$1), $2, true); } | packageClassScope idAny rangeListE - { AstRefDType* refp = new AstRefDType($2, *$2, $1, NULL); + { AstRefDType* refp = new AstRefDType($2, *$2, $1, nullptr); $$ = GRAMMARP->createArray(refp, $3, true); } ; @@ -2025,13 +2027,13 @@ enum_name_declaration: // ==IEEE: enum_name_declaration ; enumNameRangeE: // IEEE: second part of enum_name_declaration - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | '[' intnumAsConst ']' { $$ = new AstRange($1, new AstConst($1, 0), new AstConst($1, $2->toSInt()-1)); } | '[' intnumAsConst ':' intnumAsConst ']' { $$ = new AstRange($1,$2,$4); } ; enumNameStartE: // IEEE: third part of enum_name_declaration - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | '=' constExpr { $$ = $2; } ; @@ -2052,7 +2054,7 @@ data_declaration: // ==IEEE: data_declaration // // Therefore the virtual_interface_declaration term isn't used // // 1800-2009: //UNSUP net_type_declaration { $$ = $1; } - | vlTag { $$ = NULL; } + | vlTag { $$ = nullptr; } ; class_property: // ==IEEE: class_property, which is {property_qualifier} data_declaration @@ -2138,7 +2140,7 @@ data_declarationVarFrontClass: // IEEE: part of data_declaration (for class_prop implicit_typeE: // IEEE: part of *data_type_or_implicit // // Also expanded in data_declaration - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | signingE rangeList { $$ = GRAMMARP->addRange(new AstBasicDType($2->fileline(), LOGIC_IMPLICIT, $1),$2,true); } | signing { $$ = new AstBasicDType($1, LOGIC_IMPLICIT, $1); } ; @@ -2153,21 +2155,21 @@ type_declaration: // ==IEEE: type_declaration yTYPEDEF data_type idAny variable_dimensionListE dtypeAttrListE ';' /**/ { $$ = new AstTypedef($3, *$3, $5, VFlagChildDType(), GRAMMARP->createArray($2,$4,false)); SYMP->reinsert($$); PARSEP->tagNodep($$); } - | yTYPEDEF id/*interface*/ '.' idAny/*type*/ idAny/*type*/ ';' { $$ = NULL; BBUNSUP($1, "Unsupported: SystemVerilog 2005 typedef in this context"); } + | yTYPEDEF id/*interface*/ '.' idAny/*type*/ idAny/*type*/ ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: SystemVerilog 2005 typedef in this context"); } // // Combines into above "data_type id" rule // // Verilator: Not important what it is in the AST, just need to make sure the yaID__aTYPE gets returned //UNSUP // Below should be idAny to allow duplicate forward defs; need to expand // // data_type to exclude IDs, or add id__SEMI rule - | yTYPEDEF id ';' { $$ = NULL; $$ = new AstTypedefFwd($2, *$2); SYMP->reinsert($$); PARSEP->tagNodep($$); } - | yTYPEDEF yENUM idAny ';' { $$ = NULL; $$ = new AstTypedefFwd($3, *$3); SYMP->reinsert($$); PARSEP->tagNodep($$); } - | yTYPEDEF ySTRUCT idAny ';' { $$ = NULL; $$ = new AstTypedefFwd($3, *$3); SYMP->reinsert($$); PARSEP->tagNodep($$); } - | yTYPEDEF yUNION idAny ';' { $$ = NULL; $$ = new AstTypedefFwd($3, *$3); SYMP->reinsert($$); PARSEP->tagNodep($$); } - | yTYPEDEF yCLASS idAny ';' { $$ = NULL; $$ = new AstTypedefFwd($3, *$3); SYMP->reinsert($$); PARSEP->tagNodep($$); } - | yTYPEDEF yINTERFACE yCLASS idAny ';' { $$ = NULL; $$ = new AstTypedefFwd($4, *$4); SYMP->reinsert($$); PARSEP->tagNodep($$); } + | yTYPEDEF id ';' { $$ = nullptr; $$ = new AstTypedefFwd($2, *$2); SYMP->reinsert($$); PARSEP->tagNodep($$); } + | yTYPEDEF yENUM idAny ';' { $$ = nullptr; $$ = new AstTypedefFwd($3, *$3); SYMP->reinsert($$); PARSEP->tagNodep($$); } + | yTYPEDEF ySTRUCT idAny ';' { $$ = nullptr; $$ = new AstTypedefFwd($3, *$3); SYMP->reinsert($$); PARSEP->tagNodep($$); } + | yTYPEDEF yUNION idAny ';' { $$ = nullptr; $$ = new AstTypedefFwd($3, *$3); SYMP->reinsert($$); PARSEP->tagNodep($$); } + | yTYPEDEF yCLASS idAny ';' { $$ = nullptr; $$ = new AstTypedefFwd($3, *$3); SYMP->reinsert($$); PARSEP->tagNodep($$); } + | yTYPEDEF yINTERFACE yCLASS idAny ';' { $$ = nullptr; $$ = new AstTypedefFwd($4, *$4); SYMP->reinsert($$); PARSEP->tagNodep($$); } ; dtypeAttrListE: - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | dtypeAttrList { $$ = $1; } ; @@ -2188,7 +2190,7 @@ vlTag: // verilator tag handling // Module Items module_itemListE: // IEEE: Part of module_declaration - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | module_itemList { $$ = $1; } ; @@ -2207,9 +2209,9 @@ non_port_module_item: // ==IEEE: non_port_module_item | module_or_generate_item { $$ = $1; } | specify_block { $$ = $1; } | specparam_declaration { $$ = $1; } - | program_declaration { $$ = NULL; BBUNSUP(CRELINE(), "Unsupported: program decls within module decls"); } - | module_declaration { $$ = NULL; BBUNSUP(CRELINE(), "Unsupported: module decls within module decls"); } - | interface_declaration { $$ = NULL; BBUNSUP(CRELINE(), "Unsupported: interface decls within module decls"); } + | program_declaration { $$ = nullptr; BBUNSUP(CRELINE(), "Unsupported: program decls within module decls"); } + | module_declaration { $$ = nullptr; BBUNSUP(CRELINE(), "Unsupported: module decls within module decls"); } + | interface_declaration { $$ = nullptr; BBUNSUP(CRELINE(), "Unsupported: interface decls within module decls"); } | timeunits_declaration { $$ = $1; } // // Verilator specific | yaSCHDR { $$ = new AstScHdr($1,*$1); } @@ -2218,6 +2220,7 @@ non_port_module_item: // ==IEEE: non_port_module_item | yaSCIMPH { $$ = new AstScImpHdr($1,*$1); } | yaSCCTOR { $$ = new AstScCtor($1,*$1); } | yaSCDTOR { $$ = new AstScDtor($1,*$1); } + | yVL_HIER_BLOCK { $$ = new AstPragma($1,AstPragmaType::HIER_BLOCK); } | yVL_INLINE_MODULE { $$ = new AstPragma($1,AstPragmaType::INLINE_MODULE); } | yVL_NO_INLINE_MODULE { $$ = new AstPragma($1,AstPragmaType::NO_INLINE_MODULE); } | yVL_PUBLIC_MODULE { $$ = new AstPragma($1,AstPragmaType::PUBLIC_MODULE); v3Global.dpi(true); } @@ -2244,21 +2247,21 @@ module_common_item: // ==IEEE: module_common_item | bind_directive { $$ = $1; } | continuous_assign { $$ = $1; } // // IEEE: net_alias - | yALIAS variable_lvalue aliasEqList ';' { $$ = NULL; BBUNSUP($1, "Unsupported: alias statements"); } + | yALIAS variable_lvalue aliasEqList ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: alias statements"); } | initial_construct { $$ = $1; } | final_construct { $$ = $1; } // // IEEE: always_construct // // Verilator only - event_control attached to always - | yALWAYS stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS, NULL, $2); } - | yALWAYS_FF stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS_FF, NULL, $2); } - | yALWAYS_LATCH stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS_LATCH, NULL, $2); } - | yALWAYS_COMB stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS_COMB, NULL, $2); } + | yALWAYS stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS, nullptr, $2); } + | yALWAYS_FF stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS_FF, nullptr, $2); } + | yALWAYS_LATCH stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS_LATCH, nullptr, $2); } + | yALWAYS_COMB stmtBlock { $$ = new AstAlways($1,VAlwaysKwd::ALWAYS_COMB, nullptr, $2); } // | loop_generate_construct { $$ = $1; } | conditional_generate_construct { $$ = $1; } | elaboration_system_task { $$ = $1; } // - | error ';' { $$ = NULL; } + | error ';' { $$ = nullptr; } ; continuous_assign: // IEEE: continuous_assign @@ -2277,7 +2280,7 @@ module_or_generate_item_declaration: // ==IEEE: module_or_generate_item_d package_or_generate_item_declaration { $$ = $1; } | genvar_declaration { $$ = $1; } | clocking_declaration { $$ = $1; } - | yDEFAULT yCLOCKING idAny/*new-clocking_identifier*/ ';' { $$ = NULL; BBUNSUP($1, "Unsupported: default clocking identifier"); } + | yDEFAULT yCLOCKING idAny/*new-clocking_identifier*/ ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: default clocking identifier"); } //UNSUP yDEFAULT yDISABLE yIFF expr/*expression_or_dist*/ ';' { } ; @@ -2291,7 +2294,7 @@ bind_directive: // ==IEEE: bind_directive + bind_target_scope // // We merged the rules - id may be a bind_target_instance or module_identifier or interface_identifier yBIND bind_target_instance bind_instantiation { $$ = new AstBind($2, *$2, $3); } | yBIND bind_target_instance ':' bind_target_instance_list bind_instantiation - { $$ = NULL; BBUNSUP($1, "Unsupported: Bind with instance list"); } + { $$ = nullptr; BBUNSUP($1, "Unsupported: Bind with instance list"); } ; bind_target_instance_list: // ==IEEE: bind_target_instance_list @@ -2322,7 +2325,7 @@ bind_instantiation: // ==IEEE: bind_instantiation generate_region: // ==IEEE: generate_region yGENERATE ~c~genItemList yENDGENERATE { $$ = $2; } - | yGENERATE yENDGENERATE { $$ = NULL; } + | yGENERATE yENDGENERATE { $$ = nullptr; } ; //UNSUPc_generate_region: // IEEE: generate_region (for checkers) @@ -2332,20 +2335,21 @@ generate_region: // ==IEEE: generate_region generate_block_or_null: // IEEE: generate_block_or_null (called from gencase/genif/genfor) // ';' // is included in // // IEEE: generate_block - // // Must always return a BEGIN node, or NULL - see GenFor construction - generate_item { $$ = $1 ? (new AstBegin($1->fileline(),"",$1,true,true)) : NULL; } + // // Must always return a BEGIN node, or nullptr - see GenFor construction + generate_item { $$ = $1 ? (new AstBegin($1->fileline(),"",$1,true,true)) : nullptr; } | genItemBegin { $$ = $1; } ; genItemBegin: // IEEE: part of generate_block yBEGIN ~c~genItemList yEND { $$ = new AstBegin($1,"",$2,true,false); } - | yBEGIN yEND { $$ = NULL; } - | id ':' yBEGIN ~c~genItemList yEND endLabelE + | yBEGIN yEND { $$ = nullptr; } + | id yP_COLON__BEGIN yBEGIN ~c~genItemList yEND endLabelE { $$ = new AstBegin($1,*$1,$4,true,false); GRAMMARP->endLabel($6,*$1,$6); } - | id ':' yBEGIN yEND endLabelE { $$ = NULL; GRAMMARP->endLabel($5,*$1,$5); } + | id yP_COLON__BEGIN yBEGIN yEND endLabelE + { $$ = nullptr; GRAMMARP->endLabel($5,*$1,$5); } | yBEGIN ':' idAny ~c~genItemList yEND endLabelE { $$ = new AstBegin($3,*$3,$4,true,false); GRAMMARP->endLabel($6,*$3,$6); } - | yBEGIN ':' idAny yEND endLabelE { $$ = NULL; GRAMMARP->endLabel($5,*$3,$5); } + | yBEGIN ':' idAny yEND endLabelE { $$ = nullptr; GRAMMARP->endLabel($5,*$3,$5); } ; //UNSUPc_genItemBegin: // IEEE: part of generate_block (for checkers) @@ -2388,7 +2392,7 @@ conditional_generate_construct: // ==IEEE: conditional_generate_construct yCASE '(' expr ')' ~c~case_generate_itemListE yENDCASE { $$ = new AstGenCase($1, $3, $5); } | yIF '(' expr ')' ~c~generate_block_or_null %prec prLOWER_THAN_ELSE - { $$ = new AstGenIf($1, $3, $5, NULL); } + { $$ = new AstGenIf($1, $3, $5, nullptr); } | yIF '(' expr ')' ~c~generate_block_or_null yELSE ~c~generate_block_or_null { $$ = new AstGenIf($1, $3, $5, $7); } ; @@ -2402,11 +2406,11 @@ loop_generate_construct: // ==IEEE: loop_generate_construct { // Convert BEGIN(...) to BEGIN(GENFOR(...)), as we need the BEGIN to hide the local genvar AstBegin* lowerBegp = VN_CAST($9, Begin); UASSERT_OBJ(!($9 && !lowerBegp), $9, "Child of GENFOR should have been begin"); - if (!lowerBegp) lowerBegp = new AstBegin($1, "genblk", NULL, true, true); // Empty body + if (!lowerBegp) lowerBegp = new AstBegin($1, "genblk", nullptr, true, true); // Empty body AstNode* lowerNoBegp = lowerBegp->stmtsp(); if (lowerNoBegp) lowerNoBegp->unlinkFrBackWithNext(); // - AstBegin* blkp = new AstBegin($1, lowerBegp->name(), NULL, true, true); + AstBegin* blkp = new AstBegin($1, lowerBegp->name(), nullptr, true, true); // V3LinkDot detects BEGIN(GENFOR(...)) as a special case AstNode* initp = $3; AstNode* varp = $3; if (VN_IS(varp, Var)) { // Genvar @@ -2453,7 +2457,7 @@ genvar_iteration: // ==IEEE: genvar_iteration ; case_generate_itemListE: // IEEE: [{ case_generate_itemList }] - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | case_generate_itemList { $$ = $1; } ; @@ -2467,9 +2471,9 @@ case_generate_itemList: // IEEE: { case_generate_itemList } //UNSUP ; case_generate_item: // ==IEEE: case_generate_item - caseCondList ':' generate_block_or_null { $$ = new AstCaseItem($2,$1,$3); } - | yDEFAULT ':' generate_block_or_null { $$ = new AstCaseItem($1,NULL,$3); } - | yDEFAULT generate_block_or_null { $$ = new AstCaseItem($1,NULL,$2); } + caseCondList colon generate_block_or_null { $$ = new AstCaseItem($2,$1,$3); } + | yDEFAULT colon generate_block_or_null { $$ = new AstCaseItem($1,nullptr,$3); } + | yDEFAULT generate_block_or_null { $$ = new AstCaseItem($1,nullptr,$2); } ; //UNSUPc_case_generate_item: // IEEE: case_generate_item (for checkers) @@ -2489,7 +2493,7 @@ assignOne: ; //UNSUPdelay_or_event_controlE: // IEEE: delay_or_event_control plus empty -//UNSUP /* empty */ { $$ = NULL; } +//UNSUP /* empty */ { $$ = nullptr; } //UNSUP | delay_control { $$ = $1; } //UNSUP | event_control { $$ = $1; } //UNSUP | yREPEAT '(' expr ')' event_control { } @@ -2536,8 +2540,8 @@ netSigList: // IEEE: list_of_port_identifiers ; netSig: // IEEE: net_decl_assignment - one element from list_of_port_identifiers - netId sigAttrListE { $$ = VARDONEA($1,*$1, NULL, $2); } - | netId sigAttrListE '=' expr { $$ = VARDONEA($1,*$1, NULL, $2); + netId sigAttrListE { $$ = VARDONEA($1,*$1, nullptr, $2); } + | netId sigAttrListE '=' expr { $$ = VARDONEA($1,*$1, nullptr, $2); $$->addNext(new AstAssignW($3, new AstVarRef($1, *$1, true), $4)); } | netId variable_dimensionList sigAttrListE { $$ = VARDONEA($1,*$1, $2, $3); } ; @@ -2548,7 +2552,7 @@ netId: ; sigAttrListE: - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | sigAttrList { $$ = $1; } ; @@ -2558,8 +2562,7 @@ sigAttrList: ; sigAttr: - yVL_CLOCK { $$ = new AstAttrOf($1,AstAttrType::VAR_CLOCK); } - | yVL_CLOCKER { $$ = new AstAttrOf($1,AstAttrType::VAR_CLOCKER); } + yVL_CLOCKER { $$ = new AstAttrOf($1,AstAttrType::VAR_CLOCKER); } | yVL_NO_CLOCKER { $$ = new AstAttrOf($1,AstAttrType::VAR_NO_CLOCKER); } | yVL_CLOCK_ENABLE { $$ = new AstAttrOf($1,AstAttrType::VAR_CLOCK_ENABLE); } | yVL_PUBLIC { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC); v3Global.dpi(true); } @@ -2567,7 +2570,7 @@ sigAttr: | yVL_PUBLIC_FLAT_RD { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RD); v3Global.dpi(true); } | yVL_PUBLIC_FLAT_RW { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RW); v3Global.dpi(true); } | yVL_PUBLIC_FLAT_RW attr_event_control { $$ = new AstAttrOf($1,AstAttrType::VAR_PUBLIC_FLAT_RW); v3Global.dpi(true); - $$ = $$->addNext(new AstAlwaysPublic($1,$2,NULL)); } + $$ = $$->addNext(new AstAlwaysPublic($1,$2,nullptr)); } | yVL_ISOLATE_ASSIGNMENTS { $$ = new AstAttrOf($1,AstAttrType::VAR_ISOLATE_ASSIGNMENTS); } | yVL_SC_BV { $$ = new AstAttrOf($1,AstAttrType::VAR_SC_BV); } | yVL_SFORMAT { $$ = new AstAttrOf($1,AstAttrType::VAR_SFORMAT); } @@ -2575,7 +2578,7 @@ sigAttr: ; rangeListE: // IEEE: [{packed_dimension}] - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | rangeList { $$ = $1; } ; @@ -2585,7 +2588,7 @@ rangeList: // IEEE: {packed_dimension} ; //UNSUPbit_selectE: // IEEE: constant_bit_select (IEEE included empty) -//UNSUP /* empty */ { $$ = NULL; } +//UNSUP /* empty */ { $$ = nullptr; } //UNSUP | '[' constExpr ']' { $$=$1; $$ = "["+$2+"]"; } //UNSUP ; @@ -2597,7 +2600,7 @@ anyrange: ; packed_dimensionListE: // IEEE: [{ packed_dimension }] - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | packed_dimensionList { $$ = $1; } ; @@ -2608,7 +2611,7 @@ packed_dimensionList: // IEEE: { packed_dimension } packed_dimension: // ==IEEE: packed_dimension anyrange { $$ = $1; } - | '[' ']' { $$ = NULL; BBUNSUP($1, "Unsupported: [] dimensions"); } + | '[' ']' { $$ = nullptr; BBUNSUP($1, "Unsupported: [] dimensions"); } ; //************************************************ @@ -2624,7 +2627,7 @@ param_assignment: // ==IEEE: param_assignment if (VSymEnt* foundp = SYMP->symCurrentp()->findIdFallback(refp->name())) { UINFO(9, "declaring type via param assignment" << foundp->nodep() << endl); VARDTYPE(new AstParseTypeDType($1)) - SYMP->reinsert(foundp->nodep()->cloneTree(false), NULL, *$1); }} + SYMP->reinsert(foundp->nodep()->cloneTree(false), nullptr, *$1); }} $$ = VARDONEA($1, *$1, $2, $3); if ($4) $$->valuep($4); } ; @@ -2636,7 +2639,7 @@ list_of_param_assignments: // ==IEEE: list_of_param_assignments type_assignment: // ==IEEE: type_assignment // // note exptOrDataType being a data_type is only for yPARAMETER yTYPE idAny/*new-parameter*/ sigAttrListE '=' data_type - { $$ = VARDONEA($1, *$1, NULL, $2); $$->valuep($4); } + { $$ = VARDONEA($1, *$1, nullptr, $2); $$->valuep($4); } ; list_of_type_assignments: // ==IEEE: list_of_type_assignments @@ -2652,7 +2655,7 @@ list_of_defparam_assignments: //== IEEE: list_of_defparam_assignments defparam_assignment: // ==IEEE: defparam_assignment idAny '.' idAny '=' expr { $$ = new AstDefParam($4, *$1, *$3, $5); } | idAny '.' idAny '.' - { $$ = NULL; + { $$ = nullptr; BBUNSUP($4, "Unsupported: defparam with more than one dot"); } ; @@ -2678,14 +2681,14 @@ instDecl: { $$ = $4; GRAMMARP->m_impliedDecl=false; if (GRAMMARP->m_instParamp) { VL_DO_CLEAR(GRAMMARP->m_instParamp->deleteTree(), - GRAMMARP->m_instParamp = NULL); + GRAMMARP->m_instParamp = nullptr); } } // // IEEE: interface_identifier' .' modport_identifier list_of_interface_identifiers | id/*interface*/ '.' id/*modport*/ /*mid*/ { VARRESET_NONLIST(AstVarType::IFACEREF); VARDTYPE(new AstIfaceRefDType($1, $3, "", *$1, *$3)); } /*cont*/ mpInstnameList ';' - { $$ = VARDONEP($5,NULL,NULL); } + { $$ = VARDONEP($5,nullptr,nullptr); } //UNSUP: strengthSpecE for udp_instantiations ; @@ -2711,7 +2714,7 @@ instnameParen: GRAMMARP->scrubRange($2)); $$->trace(GRAMMARP->allTracingOn($1)); } | id instRangeListE { $$ = new AstCell($1, GRAMMARP->m_instModuleFl, - *$1, GRAMMARP->m_instModule, NULL, + *$1, GRAMMARP->m_instModule, nullptr, AstPin::cloneTreeNull(GRAMMARP->m_instParamp, true), GRAMMARP->scrubRange($2)); $$->trace(GRAMMARP->allTracingOn($1)); } @@ -2722,7 +2725,7 @@ instnameParen: ; instRangeListE: - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | instRangeList { $$ = $1; } ; @@ -2756,15 +2759,15 @@ cellpinItList: // IEEE: list_of_port_connections cellparamItemE: // IEEE: named_parameter_assignment + empty // // Note empty can match either () or (,); V3LinkCells cleans up () - /* empty: ',,' is legal */ { $$ = new AstPin(CRELINE(), PINNUMINC(), "", NULL); } - | yP_DOTSTAR { $$ = new AstPin($1,PINNUMINC(),".*",NULL); } + /* empty: ',,' is legal */ { $$ = new AstPin(CRELINE(), PINNUMINC(), "", nullptr); } + | yP_DOTSTAR { $$ = new AstPin($1,PINNUMINC(),".*",nullptr); } | '.' idSVKwd { $$ = new AstPin($2,PINNUMINC(), *$2, - new AstParseRef($2,VParseRefExp::PX_TEXT,*$2,NULL,NULL)); + new AstParseRef($2,VParseRefExp::PX_TEXT,*$2,nullptr,nullptr)); $$->svImplicit(true);} | '.' idAny { $$ = new AstPin($2,PINNUMINC(), *$2, - new AstParseRef($2,VParseRefExp::PX_TEXT,*$2,NULL,NULL)); + new AstParseRef($2,VParseRefExp::PX_TEXT,*$2,nullptr,nullptr)); $$->svImplicit(true);} - | '.' idAny '(' ')' { $$ = new AstPin($2,PINNUMINC(),*$2,NULL); } + | '.' idAny '(' ')' { $$ = new AstPin($2,PINNUMINC(),*$2,nullptr); } // // mintypmax is expanded here, as it might be a UDP or gate primitive // // data_type for 'parameter type' hookups | '.' idAny '(' exprOrDataType ')' { $$ = new AstPin($2, PINNUMINC(), *$2, $4); } @@ -2778,11 +2781,11 @@ cellparamItemE: // IEEE: named_parameter_assignment + empty cellpinItemE: // IEEE: named_port_connection + empty // // Note empty can match either () or (,); V3LinkCells cleans up () - /* empty: ',,' is legal */ { $$ = new AstPin(CRELINE(), PINNUMINC(), "", NULL); } - | yP_DOTSTAR { $$ = new AstPin($1,PINNUMINC(),".*",NULL); } - | '.' idSVKwd { $$ = new AstPin($2,PINNUMINC(),*$2,new AstParseRef($2,VParseRefExp::PX_TEXT,*$2,NULL,NULL)); $$->svImplicit(true);} - | '.' idAny { $$ = new AstPin($2,PINNUMINC(),*$2,new AstParseRef($2,VParseRefExp::PX_TEXT,*$2,NULL,NULL)); $$->svImplicit(true);} - | '.' idAny '(' ')' { $$ = new AstPin($2,PINNUMINC(),*$2,NULL); } + /* empty: ',,' is legal */ { $$ = new AstPin(CRELINE(), PINNUMINC(), "", nullptr); } + | yP_DOTSTAR { $$ = new AstPin($1,PINNUMINC(),".*",nullptr); } + | '.' idSVKwd { $$ = new AstPin($2,PINNUMINC(),*$2,new AstParseRef($2,VParseRefExp::PX_TEXT,*$2,nullptr,nullptr)); $$->svImplicit(true);} + | '.' idAny { $$ = new AstPin($2,PINNUMINC(),*$2,new AstParseRef($2,VParseRefExp::PX_TEXT,*$2,nullptr,nullptr)); $$->svImplicit(true);} + | '.' idAny '(' ')' { $$ = new AstPin($2,PINNUMINC(),*$2,nullptr); } // // mintypmax is expanded here, as it might be a UDP or gate primitive //UNSUP pev_expr below | '.' idAny '(' expr ')' { $$ = new AstPin($2,PINNUMINC(),*$2,$4); } @@ -2798,20 +2801,20 @@ cellpinItemE: // IEEE: named_port_connection + empty // EventControl lists attr_event_controlE: - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | attr_event_control { $$ = $1; } ; attr_event_control: // ==IEEE: event_control '@' '(' event_expression ')' { $$ = new AstSenTree($1,$3); } - | '@' '(' '*' ')' { $$ = NULL; } - | '@' '*' { $$ = NULL; } + | '@' '(' '*' ')' { $$ = nullptr; } + | '@' '*' { $$ = nullptr; } ; event_control: // ==IEEE: event_control '@' '(' event_expression ')' { $$ = new AstSenTree($1,$3); } - | '@' '(' '*' ')' { $$ = NULL; } - | '@' '*' { $$ = NULL; } + | '@' '(' '*' ')' { $$ = nullptr; } + | '@' '*' { $$ = nullptr; } // // IEEE: hierarchical_event_identifier // // UNSUP below should be idClassSel | '@' senitemVar { $$ = new AstSenTree($1,$2); } /* For events only */ @@ -2844,8 +2847,8 @@ senitem: // IEEE: part of event_expression, non-'OR' ',' terms | senitem yP_ANDAND senitem { $$ = new AstSenItem($2, AstSenItem::Illegal()); } //UNSUP expr yIFF expr { UNSUP } // Since expr is unsupported we allow and ignore constants (removed in V3Const) - | yaINTNUM { $$ = NULL; } - | yaFLOATNUM { $$ = NULL; } + | yaINTNUM { $$ = nullptr; } + | yaFLOATNUM { $$ = nullptr; } ; senitemVar: @@ -2879,47 +2882,68 @@ stmtBlock: // IEEE: statement + seq_block + par_block seq_block: // ==IEEE: seq_block // // IEEE doesn't allow declarations in unnamed blocks, but several simulators do. // // So need AstBegin's even if unnamed to scope variables down - seq_blockFront blockDeclStmtList yEND endLabelE { $$=$1; $1->addStmtsp($2); SYMP->popScope($1); GRAMMARP->endLabel($4,$1,$4); } - | seq_blockFront /**/ yEND endLabelE { $$=$1; SYMP->popScope($1); GRAMMARP->endLabel($3,$1,$3); } + seq_blockFront blockDeclStmtListE yEND endLabelE + { $$ = $1; $1->addStmtsp($2); + SYMP->popScope($1); GRAMMARP->endLabel($4, $1, $4); } + ; + +seq_blockPreId: // IEEE: seq_block, but called with leading ID + seq_blockFrontPreId blockDeclStmtListE yEND endLabelE + { $$ = $1; $1->addStmtsp($2); + SYMP->popScope($1); GRAMMARP->endLabel($4, $1, $4); } ; par_block: // ==IEEE: par_block - par_blockFront blockDeclStmtList yJOIN endLabelE + par_blockFront blockDeclStmtListE yJOIN endLabelE { $$ = $1; $1->addStmtsp($2); $1->joinType(VJoinType::JOIN); SYMP->popScope($1); GRAMMARP->endLabel($4, $1, $4); } - | par_blockFront /**/ yJOIN endLabelE - { $$ = $1; + | par_blockFront blockDeclStmtListE yJOIN_ANY endLabelE + { $$ = $1; $1->addStmtsp($2); + $1->joinType(VJoinType::JOIN_ANY); + SYMP->popScope($1); GRAMMARP->endLabel($4, $1, $4); } + | par_blockFront blockDeclStmtListE yJOIN_NONE endLabelE + { $$ = $1; $1->addStmtsp($2); + $1->joinType(VJoinType::JOIN_NONE); + SYMP->popScope($1); GRAMMARP->endLabel($4, $1, $4); } + ; + +par_blockPreId: // ==IEEE: par_block but called with leading ID + par_blockFrontPreId blockDeclStmtListE yJOIN endLabelE + { $$ = $1; $1->addStmtsp($2); $1->joinType(VJoinType::JOIN); - SYMP->popScope($1); GRAMMARP->endLabel($3, $1, $3); } - | par_blockFront blockDeclStmtList yJOIN_ANY endLabelE + SYMP->popScope($1); GRAMMARP->endLabel($4, $1, $4); } + | par_blockFrontPreId blockDeclStmtListE yJOIN_ANY endLabelE { $$ = $1; $1->addStmtsp($2); $1->joinType(VJoinType::JOIN_ANY); SYMP->popScope($1); GRAMMARP->endLabel($4, $1, $4); } - | par_blockFront /**/ yJOIN_ANY endLabelE - { $$ = $1; - $1->joinType(VJoinType::JOIN_ANY); - SYMP->popScope($1); GRAMMARP->endLabel($3, $1, $3); } - | par_blockFront blockDeclStmtList yJOIN_NONE endLabelE + | par_blockFrontPreId blockDeclStmtListE yJOIN_NONE endLabelE { $$ = $1; $1->addStmtsp($2); $1->joinType(VJoinType::JOIN_NONE); SYMP->popScope($1); GRAMMARP->endLabel($4, $1, $4); } - | par_blockFront /**/ yJOIN_NONE endLabelE - { $$ = $1; - $1->joinType(VJoinType::JOIN_NONE); - SYMP->popScope($1); GRAMMARP->endLabel($3, $1, $3); } ; seq_blockFront: // IEEE: part of seq_block - yBEGIN { $$ = new AstBegin($1,"",NULL); SYMP->pushNew($$); } - | yBEGIN ':' idAny/*new-block_identifier*/ { $$ = new AstBegin($3, *$3, NULL); SYMP->pushNew($$); } + yBEGIN { $$ = new AstBegin($1,"",nullptr); SYMP->pushNew($$); } + | yBEGIN ':' idAny/*new-block_identifier*/ { $$ = new AstBegin($3, *$3, nullptr); SYMP->pushNew($$); } ; par_blockFront: // IEEE: part of par_block - yFORK { $$ = new AstFork($1, "", NULL); SYMP->pushNew($$); } - | yFORK ':' idAny/*new-block_identifier*/ { $$ = new AstFork($3, *$3, NULL); SYMP->pushNew($$); } + yFORK { $$ = new AstFork($1, "", nullptr); SYMP->pushNew($$); } + | yFORK ':' idAny/*new-block_identifier*/ { $$ = new AstFork($3, *$3, nullptr); SYMP->pushNew($$); } ; +seq_blockFrontPreId: // IEEE: part of seq_block/stmt with leading id + id/*block_identifier*/ yP_COLON__BEGIN yBEGIN + { $$ = new AstBegin($3, *$1, nullptr); SYMP->pushNew($$); } + ; + +par_blockFrontPreId: // IEEE: part of par_block/stmt with leading id + id/*block_identifier*/ yP_COLON__FORK yFORK + { $$ = new AstFork($3, *$1, nullptr); SYMP->pushNew($$); } + ; + + blockDeclStmtList: // IEEE: { block_item_declaration } { statement or null } // // The spec seems to suggest a empty declaration isn't ok, but most simulators take it block_item_declarationList { $$ = $1; } @@ -2927,6 +2951,11 @@ blockDeclStmtList: // IEEE: { block_item_declaration } { statement or nul | stmtList { $$ = $1; } ; +blockDeclStmtListE: // IEEE: [ { block_item_declaration } { statement or null } ] + /*empty*/ { $$ = nullptr; } + | blockDeclStmtList { $$ = $1; } + ; + block_item_declarationList: // IEEE: [ block_item_declaration ] block_item_declaration { $$ = $1; } | block_item_declarationList block_item_declaration { $$ = $1->addNextNull($2); } @@ -2940,7 +2969,7 @@ block_item_declaration: // ==IEEE: block_item_declaration stmtList: stmtBlock { $$ = $1; } - | stmtList stmtBlock { $$ = ($2==NULL)?($1):($1->addNext($2)); } + | stmtList stmtBlock { $$ = ($2==nullptr)?($1):($1->addNext($2)); } ; stmt: // IEEE: statement_or_null == function_statement_or_null @@ -2948,7 +2977,10 @@ stmt: // IEEE: statement_or_null == function_statement_or_null // // S05 block creation rule | id/*block_identifier*/ ':' statement_item { $$ = new AstBegin($1, *$1, $3); } // // from _or_null - | ';' { $$ = NULL; } + | ';' { $$ = nullptr; } + // // labeled par_block/seq_block with leading ':' + | seq_blockPreId { $$ = $1; } + | par_blockPreId { $$ = $1; } ; statement_item: // IEEE: statement_item @@ -2968,9 +3000,9 @@ statement_item: // IEEE: statement_item // // IEEE: procedural_continuous_assignment | yASSIGN idClassSel '=' delayE expr ';' { $$ = new AstAssign($1,$2,$5); } //UNSUP: delay_or_event_controlE above - | yDEASSIGN variable_lvalue ';' { $$ = NULL; BBUNSUP($1, "Unsupported: Verilog 1995 deassign"); } - | yFORCE expr '=' expr ';' { $$ = NULL; BBUNSUP($1, "Unsupported: Verilog 1995 force"); } - | yRELEASE variable_lvalue ';' { $$ = NULL; BBUNSUP($1, "Unsupported: Verilog 1995 release"); } + | yDEASSIGN variable_lvalue ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: Verilog 1995 deassign"); } + | yFORCE expr '=' expr ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: Verilog 1995 force"); } + | yRELEASE variable_lvalue ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: Verilog 1995 release"); } // // // IEEE: case_statement | unique_priorityE caseStart caseAttrE case_itemListE yENDCASE { $$ = $2; if ($4) $2->addItemsp($4); @@ -2987,7 +3019,7 @@ statement_item: // IEEE: statement_item // // // IEEE: conditional_statement | unique_priorityE yIF '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE - { AstIf* newp = new AstIf($2,$4,$6,NULL); + { AstIf* newp = new AstIf($2,$4,$6,nullptr); $$ = newp; if ($1 == uniq_UNIQUE) newp->uniquePragma(true); if ($1 == uniq_UNIQUE0) newp->unique0Pragma(true); @@ -3056,7 +3088,7 @@ statement_item: // IEEE: statement_item $$ = $2->cloneTree(true); $$->addNext(new AstWhile($1,$5,$2)); } - else $$ = new AstWhile($1,$5,NULL); } + else $$ = new AstWhile($1,$5,nullptr); } // // IEEE says array_identifier here, but dotted accepted in VMM and 1800-2009 | yFOREACH '(' idClassSelForeach ')' stmtBlock { $$ = new AstForeach($1, $3, $5); } // @@ -3092,11 +3124,11 @@ statement_item: // IEEE: statement_item //UNSUP randsequence_statement { $$ = $1; } // // // IEEE: randcase_statement - | yRANDCASE case_itemList yENDCASE { $$ = NULL; BBUNSUP($1, "Unsupported: SystemVerilog 2005 randcase statements"); } + | yRANDCASE case_itemList yENDCASE { $$ = nullptr; BBUNSUP($1, "Unsupported: SystemVerilog 2005 randcase statements"); } // //UNSUP expect_property_statement { $$ = $1; } // - | error ';' { $$ = NULL; } + | error ';' { $$ = nullptr; } ; statementFor: // IEEE: part of statement @@ -3180,13 +3212,13 @@ finc_or_dec_expression: // ==IEEE: inc_or_dec_expression class_new: // ==IEEE: class_new // // Special precence so (...) doesn't match expr - yNEW__ETC { $$ = new AstNew($1, NULL); } + yNEW__ETC { $$ = new AstNew($1, nullptr); } | yNEW__ETC expr { $$ = new AstNewCopy($1, $2); } | yNEW__PAREN '(' list_of_argumentsE ')' { $$ = new AstNew($1, $3); } ; dynamic_array_new: // ==IEEE: dynamic_array_new - yNEW__ETC '[' expr ']' { $$ = new AstNewDynamic($1, $3, NULL); } + yNEW__ETC '[' expr ']' { $$ = new AstNewDynamic($1, $3, nullptr); } | yNEW__ETC '[' expr ']' '(' expr ')' { $$ = new AstNewDynamic($1, $3, $6); } ; @@ -3201,9 +3233,9 @@ unique_priorityE: // IEEE: unique_priority + empty ; caseStart: // IEEE: part of case_statement - yCASE '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,VCaseType::CT_CASE,$3,NULL); } - | yCASEX '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,VCaseType::CT_CASEX,$3,NULL); } - | yCASEZ '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,VCaseType::CT_CASEZ,$3,NULL); } + yCASE '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,VCaseType::CT_CASE,$3,nullptr); } + | yCASEX '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,VCaseType::CT_CASEX,$3,nullptr); } + | yCASEZ '(' expr ')' { $$ = GRAMMARP->m_caseAttrp = new AstCase($1,VCaseType::CT_CASEZ,$3,nullptr); } ; caseAttrE: @@ -3218,31 +3250,31 @@ caseAttrE: //UNSUP ; case_itemListE: // IEEE: [ { case_item } ] - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | case_itemList { $$ = $1; } ; case_insideListE: // IEEE: [ { case_inside_item } ] - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | case_inside_itemList { $$ = $1; } ; case_itemList: // IEEE: { case_item + ... } - caseCondList ':' stmtBlock { $$ = new AstCaseItem($2,$1,$3); } - | yDEFAULT ':' stmtBlock { $$ = new AstCaseItem($1,NULL,$3); } - | yDEFAULT stmtBlock { $$ = new AstCaseItem($1,NULL,$2); } - | case_itemList caseCondList ':' stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($3,$2,$4)); } - | case_itemList yDEFAULT stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($2,NULL,$3)); } - | case_itemList yDEFAULT ':' stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($2,NULL,$4)); } + caseCondList colon stmtBlock { $$ = new AstCaseItem($2,$1,$3); } + | yDEFAULT colon stmtBlock { $$ = new AstCaseItem($1,nullptr,$3); } + | yDEFAULT stmtBlock { $$ = new AstCaseItem($1,nullptr,$2); } + | case_itemList caseCondList colon stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($3,$2,$4)); } + | case_itemList yDEFAULT stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($2,nullptr,$3)); } + | case_itemList yDEFAULT colon stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($2,nullptr,$4)); } ; case_inside_itemList: // IEEE: { case_inside_item + open_range_list ... } - open_range_list ':' stmtBlock { $$ = new AstCaseItem($2,$1,$3); } - | yDEFAULT ':' stmtBlock { $$ = new AstCaseItem($1,NULL,$3); } - | yDEFAULT stmtBlock { $$ = new AstCaseItem($1,NULL,$2); } - | case_inside_itemList open_range_list ':' stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($3,$2,$4)); } - | case_inside_itemList yDEFAULT stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($2,NULL,$3)); } - | case_inside_itemList yDEFAULT ':' stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($2,NULL,$4)); } + open_range_list colon stmtBlock { $$ = new AstCaseItem($2,$1,$3); } + | yDEFAULT colon stmtBlock { $$ = new AstCaseItem($1,nullptr,$3); } + | yDEFAULT stmtBlock { $$ = new AstCaseItem($1,nullptr,$2); } + | case_inside_itemList open_range_list colon stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($3,$2,$4)); } + | case_inside_itemList yDEFAULT stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($2,nullptr,$3)); } + | case_inside_itemList yDEFAULT colon stmtBlock { $$ = $1;$1->addNext(new AstCaseItem($2,nullptr,$4)); } ; open_range_list: // ==IEEE: open_range_list + open_value_range @@ -3270,11 +3302,11 @@ caseCondList: // IEEE: part of case_item ; patternNoExpr: // IEEE: pattern **Excluding Expr* - '.' id/*variable*/ { $$ = NULL; BBUNSUP($1, "Unsupported: '{} tagged patterns"); } - | yP_DOTSTAR { $$ = NULL; BBUNSUP($1, "Unsupported: '{} tagged patterns"); } + '.' id/*variable*/ { $$ = nullptr; BBUNSUP($1, "Unsupported: '{} tagged patterns"); } + | yP_DOTSTAR { $$ = nullptr; BBUNSUP($1, "Unsupported: '{} tagged patterns"); } // // IEEE: "expr" excluded; expand in callers // // "yTAGGED id [expr]" Already part of expr - //UNSUP yTAGGED id/*member_identifier*/ patternNoExpr { $$ = NULL; BBUNSUP($1, "Unsupported: '{} tagged patterns"); } + //UNSUP yTAGGED id/*member_identifier*/ patternNoExpr { $$ = nullptr; BBUNSUP($1, "Unsupported: '{} tagged patterns"); } // // "yP_TICKBRA patternList '}'" part of expr under assignment_pattern ; @@ -3284,8 +3316,8 @@ patternList: // IEEE: part of pattern ; patternOne: // IEEE: part of pattern - expr { if ($1) { $$ = new AstPatMember($1->fileline(),$1,NULL,NULL); } else { $$=NULL; } } - | expr '{' argsExprList '}' { $$ = new AstPatMember($2,$3,NULL,$1); } + expr { if ($1) { $$ = new AstPatMember($1->fileline(),$1,nullptr,nullptr); } else { $$=nullptr; } } + | expr '{' argsExprList '}' { $$ = new AstPatMember($2,$3,nullptr,$1); } | patternNoExpr { $$ = $1; } ; @@ -3295,11 +3327,11 @@ patternMemberList: // IEEE: part of pattern and assignment_pattern ; patternMemberOne: // IEEE: part of pattern and assignment_pattern - patternKey ':' expr { $$ = new AstPatMember($1->fileline(),$3,$1,NULL); } - | patternKey ':' patternNoExpr { $$ = NULL; BBUNSUP($2, "Unsupported: '{} .* patterns"); } + patternKey ':' expr { $$ = new AstPatMember($1->fileline(),$3,$1,nullptr); } + | patternKey ':' patternNoExpr { $$ = nullptr; BBUNSUP($2, "Unsupported: '{} .* patterns"); } // // From assignment_pattern_key - | yDEFAULT ':' expr { $$ = new AstPatMember($1,$3,NULL,NULL); $$->isDefault(true); } - | yDEFAULT ':' patternNoExpr { $$ = NULL; BBUNSUP($2, "Unsupported: '{} .* patterns"); } + | yDEFAULT ':' expr { $$ = new AstPatMember($1,$3,nullptr,nullptr); $$->isDefault(true); } + | yDEFAULT ':' patternNoExpr { $$ = nullptr; BBUNSUP($2, "Unsupported: '{} .* patterns"); } ; patternKey: // IEEE: merge structure_pattern_key, array_pattern_key, assignment_pattern_key @@ -3333,7 +3365,7 @@ assignment_pattern: // ==IEEE: assignment_pattern | yP_TICKBRA patternMemberList '}' { $$ = new AstPattern($1,$2); } // // IEEE: Not in grammar, but in VMM | yP_TICKBRA '}' - { $$ = new AstPattern($1, NULL); $1->v3warn(E_UNSUPPORTED, "Unsupported: Empty '{}"); } + { $$ = new AstPattern($1, nullptr); $1->v3warn(E_UNSUPPORTED, "Unsupported: Empty '{}"); } ; // "datatype id = x {, id = x }" | "yaId = x {, id=x}" is legal @@ -3341,7 +3373,7 @@ for_initialization: // ==IEEE: for_initialization + for_variable_declarat // // IEEE: for_variable_declaration for_initializationItemList ';' { $$ = $1; } // // IEEE: 1800-2017 empty initialization - | ';' { $$ = NULL; } + | ';' { $$ = nullptr; } ; for_initializationItemList: // IEEE: [for_variable_declaration...] @@ -3353,12 +3385,12 @@ for_initializationItem: // IEEE: variable_assignment + for_variable_decl // // IEEE: for_variable_declaration data_type idAny/*new*/ '=' expr { VARRESET_NONLIST(VAR); VARDTYPE($1); - $$ = VARDONEA($2,*$2,NULL,NULL); + $$ = VARDONEA($2,*$2,nullptr,nullptr); $$->addNext(new AstAssign($3, new AstVarRef($2, *$2, true), $4));} // // IEEE-2012: | yVAR data_type idAny/*new*/ '=' expr { VARRESET_NONLIST(VAR); VARDTYPE($2); - $$ = VARDONEA($3,*$3,NULL,NULL); + $$ = VARDONEA($3,*$3,nullptr,nullptr); $$->addNext(new AstAssign($4, new AstVarRef($3, *$3, true), $5));} // // IEEE: variable_assignment // // UNSUP variable_lvalue below @@ -3366,7 +3398,7 @@ for_initializationItem: // IEEE: variable_assignment + for_variable_decl ; for_stepE: // IEEE: for_step + empty - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | for_step { $$ = $1; } ; @@ -3398,7 +3430,7 @@ loop_variables: // IEEE: loop_variables // Functions/tasks taskRef: // IEEE: part of tf_call - id { $$ = new AstTaskRef($1,*$1,NULL); } + id { $$ = new AstTaskRef($1,*$1,nullptr); } | id '(' list_of_argumentsE ')' { $$ = new AstTaskRef($1,*$1,$3); } | packageClassScope id '(' list_of_argumentsE ')' { $$ = AstDot::newIfPkg($2, $1, new AstTaskRef($2, *$2, $4)); } @@ -3428,7 +3460,7 @@ task_subroutine_callNoMethod: // function_subroutine_callNoMethod (as tas // // funcref below not task ref to avoid conflict, must later handle either | funcRef yWITH__PAREN '(' expr ')' { $$ = new AstWith($2, true, $1, $4); } // // can call as method and yWITH without parenthesis - | id yWITH__PAREN '(' expr ')' { $$ = new AstWith($2, true, new AstFuncRef($1, *$1, NULL), $4); } + | id yWITH__PAREN '(' expr ')' { $$ = new AstWith($2, true, new AstFuncRef($1, *$1, nullptr), $4); } | system_t_call { $$ = $1; } // // IEEE: method_call requires a "." so is in expr // // IEEE: ['std::'] not needed, as normal std package resolution will find it @@ -3443,7 +3475,7 @@ function_subroutine_callNoMethod: // IEEE: function_subroutine_call (as f funcRef { $$ = $1; } | funcRef yWITH__PAREN '(' expr ')' { $$ = new AstWith($2, false, $1, $4); } // // can call as method and yWITH without parenthesis - | id yWITH__PAREN '(' expr ')' { $$ = new AstWith($2, false, new AstFuncRef($1, *$1, NULL), $4); } + | id yWITH__PAREN '(' expr ')' { $$ = new AstWith($2, false, new AstFuncRef($1, *$1, nullptr), $4); } | system_f_call { $$ = $1; } // // IEEE: method_call requires a "." so is in expr // // IEEE: ['std::'] not needed, as normal std package resolution will find it @@ -3451,7 +3483,7 @@ function_subroutine_callNoMethod: // IEEE: function_subroutine_call (as f // // We implement randomize as a normal funcRef, since randomize isn't a keyword // // Note yNULL is already part of expressions, so they come for free | funcRef yWITH__CUR constraint_block { $$ = $1; BBUNSUP($2, "Unsupported: randomize() 'with' constraint"); } - | funcRef yWITH__CUR '{' '}' { $$ = new AstWith($2, false, $1, NULL); } + | funcRef yWITH__CUR '{' '}' { $$ = new AstWith($2, false, $1, nullptr); } ; system_t_call: // IEEE: system_tf_call (as task) @@ -3480,11 +3512,11 @@ system_t_call: // IEEE: system_tf_call (as task) | yD_DUMPON parenE { $$ = new AstDumpCtl($1, VDumpCtlType::ON); } | yD_DUMPON '(' expr ')' { $$ = new AstDumpCtl($1, VDumpCtlType::ON); DEL($3); } // - | yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCStmt($1,$3)); } + | yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? nullptr : new AstUCStmt($1,$3)); } | yD_SYSTEM '(' expr ')' { $$ = new AstSystemT($1, $3); } // | yD_FCLOSE '(' idClassSel ')' { $$ = new AstFClose($1, $3); } - | yD_FFLUSH parenE { $$ = new AstFFlush($1, NULL); } + | yD_FFLUSH parenE { $$ = new AstFFlush($1, nullptr); } | yD_FFLUSH '(' expr ')' { $$ = new AstFFlush($1, $3); } | yD_FINISH parenE { $$ = new AstFinish($1); } | yD_FINISH '(' expr ')' { $$ = new AstFinish($1); DEL($3); } @@ -3497,61 +3529,61 @@ system_t_call: // IEEE: system_tf_call (as task) | yD_SWRITEH '(' expr ',' exprDispList ')' { $$ = new AstSFormat($1, $3, $5, 'h'); } | yD_SWRITEO '(' expr ',' exprDispList ')' { $$ = new AstSFormat($1, $3, $5, 'o'); } // - | yD_DISPLAY parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, NULL, NULL); } - | yD_DISPLAY '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, NULL, $3); } - | yD_DISPLAYB parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, NULL, NULL, 'b'); } - | yD_DISPLAYB '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, NULL, $3, 'b'); } - | yD_DISPLAYH parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, NULL, NULL, 'h'); } - | yD_DISPLAYH '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, NULL, $3, 'h'); } - | yD_DISPLAYO parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, NULL, NULL, 'o'); } - | yD_DISPLAYO '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, NULL, $3, 'o'); } - | yD_WRITE parenE { $$ = NULL; } // NOP - | yD_WRITE '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, NULL, $3); } - | yD_WRITEB parenE { $$ = NULL; } // NOP - | yD_WRITEB '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, NULL, $3, 'b'); } - | yD_WRITEH parenE { $$ = NULL; } // NOP - | yD_WRITEH '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, NULL, $3, 'h'); } - | yD_WRITEO parenE { $$ = NULL; } // NOP - | yD_WRITEO '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, NULL, $3, 'o'); } - | yD_FDISPLAY '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, NULL); } + | yD_DISPLAY parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, nullptr); } + | yD_DISPLAY '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, $3); } + | yD_DISPLAYB parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, nullptr, 'b'); } + | yD_DISPLAYB '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, $3, 'b'); } + | yD_DISPLAYH parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, nullptr, 'h'); } + | yD_DISPLAYH '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, $3, 'h'); } + | yD_DISPLAYO parenE { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, nullptr, 'o'); } + | yD_DISPLAYO '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, nullptr, $3, 'o'); } + | yD_WRITE parenE { $$ = nullptr; } // NOP + | yD_WRITE '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, nullptr, $3); } + | yD_WRITEB parenE { $$ = nullptr; } // NOP + | yD_WRITEB '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, nullptr, $3, 'b'); } + | yD_WRITEH parenE { $$ = nullptr; } // NOP + | yD_WRITEH '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, nullptr, $3, 'h'); } + | yD_WRITEO parenE { $$ = nullptr; } // NOP + | yD_WRITEO '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, nullptr, $3, 'o'); } + | yD_FDISPLAY '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, nullptr); } | yD_FDISPLAY '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, $5); } - | yD_FDISPLAYB '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, NULL, 'b'); } + | yD_FDISPLAYB '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, nullptr, 'b'); } | yD_FDISPLAYB '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, $5, 'b'); } - | yD_FDISPLAYH '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, NULL, 'h'); } + | yD_FDISPLAYH '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, nullptr, 'h'); } | yD_FDISPLAYH '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, $5, 'h'); } - | yD_FDISPLAYO '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, NULL, 'o'); } + | yD_FDISPLAYO '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, nullptr, 'o'); } | yD_FDISPLAYO '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_DISPLAY, $3, $5, 'o'); } | yD_FWRITE '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, $3, $5); } | yD_FWRITEB '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, $3, $5, 'b'); } | yD_FWRITEO '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, $3, $5, 'h'); } | yD_FWRITEH '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WRITE, $3, $5, 'o'); } - | yD_INFO parenE { $$ = new AstDisplay($1,AstDisplayType::DT_INFO, NULL, NULL); } - | yD_INFO '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_INFO, NULL, $3); } - | yD_WARNING parenE { $$ = new AstDisplay($1,AstDisplayType::DT_WARNING, NULL, NULL); } - | yD_WARNING '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WARNING, NULL, $3); } + | yD_INFO parenE { $$ = new AstDisplay($1,AstDisplayType::DT_INFO, nullptr, nullptr); } + | yD_INFO '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_INFO, nullptr, $3); } + | yD_WARNING parenE { $$ = new AstDisplay($1,AstDisplayType::DT_WARNING, nullptr, nullptr); } + | yD_WARNING '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_WARNING, nullptr, $3); } | yD_ERROR parenE { $$ = GRAMMARP->createDisplayError($1); } - | yD_ERROR '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_ERROR, NULL, $3); $$->addNext(new AstStop($1, true)); } - | yD_FATAL parenE { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, NULL, NULL); $$->addNext(new AstStop($1, false)); } - | yD_FATAL '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, NULL, NULL); $$->addNext(new AstStop($1, false)); DEL($3); } - | yD_FATAL '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, NULL, $5); $$->addNext(new AstStop($1, false)); DEL($3); } + | yD_ERROR '(' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_ERROR, nullptr, $3); $$->addNext(new AstStop($1, true)); } + | yD_FATAL parenE { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, nullptr, nullptr); $$->addNext(new AstStop($1, false)); } + | yD_FATAL '(' expr ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, nullptr, nullptr); $$->addNext(new AstStop($1, false)); DEL($3); } + | yD_FATAL '(' expr ',' exprDispList ')' { $$ = new AstDisplay($1,AstDisplayType::DT_FATAL, nullptr, $5); $$->addNext(new AstStop($1, false)); DEL($3); } // | yD_PRINTTIMESCALE { $$ = new AstPrintTimeScale($1); } | yD_PRINTTIMESCALE '(' ')' { $$ = new AstPrintTimeScale($1); } | yD_PRINTTIMESCALE '(' idClassSel ')' { $$ = new AstPrintTimeScale($1); DEL($3); } | yD_TIMEFORMAT '(' expr ',' expr ',' expr ',' expr ')' { $$ = new AstTimeFormat($1, $3, $5, $7, $9); } // - | yD_READMEMB '(' expr ',' idClassSel ')' { $$ = new AstReadMem($1,false,$3,$5,NULL,NULL); } - | yD_READMEMB '(' expr ',' idClassSel ',' expr ')' { $$ = new AstReadMem($1,false,$3,$5,$7,NULL); } + | yD_READMEMB '(' expr ',' idClassSel ')' { $$ = new AstReadMem($1,false,$3,$5,nullptr,nullptr); } + | yD_READMEMB '(' expr ',' idClassSel ',' expr ')' { $$ = new AstReadMem($1,false,$3,$5,$7,nullptr); } | yD_READMEMB '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstReadMem($1,false,$3,$5,$7,$9); } - | yD_READMEMH '(' expr ',' idClassSel ')' { $$ = new AstReadMem($1,true, $3,$5,NULL,NULL); } - | yD_READMEMH '(' expr ',' idClassSel ',' expr ')' { $$ = new AstReadMem($1,true, $3,$5,$7,NULL); } + | yD_READMEMH '(' expr ',' idClassSel ')' { $$ = new AstReadMem($1,true, $3,$5,nullptr,nullptr); } + | yD_READMEMH '(' expr ',' idClassSel ',' expr ')' { $$ = new AstReadMem($1,true, $3,$5,$7,nullptr); } | yD_READMEMH '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstReadMem($1,true, $3,$5,$7,$9); } // - | yD_WRITEMEMB '(' expr ',' idClassSel ')' { $$ = new AstWriteMem($1, false, $3, $5, NULL, NULL); } - | yD_WRITEMEMB '(' expr ',' idClassSel ',' expr ')' { $$ = new AstWriteMem($1, false, $3, $5, $7, NULL); } + | yD_WRITEMEMB '(' expr ',' idClassSel ')' { $$ = new AstWriteMem($1, false, $3, $5, nullptr, nullptr); } + | yD_WRITEMEMB '(' expr ',' idClassSel ',' expr ')' { $$ = new AstWriteMem($1, false, $3, $5, $7, nullptr); } | yD_WRITEMEMB '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstWriteMem($1, false, $3, $5, $7, $9); } - | yD_WRITEMEMH '(' expr ',' idClassSel ')' { $$ = new AstWriteMem($1, true, $3, $5, NULL, NULL); } - | yD_WRITEMEMH '(' expr ',' idClassSel ',' expr ')' { $$ = new AstWriteMem($1, true, $3, $5, $7, NULL); } + | yD_WRITEMEMH '(' expr ',' idClassSel ')' { $$ = new AstWriteMem($1, true, $3, $5, nullptr, nullptr); } + | yD_WRITEMEMH '(' expr ',' idClassSel ',' expr ')' { $$ = new AstWriteMem($1, true, $3, $5, $7, nullptr); } | yD_WRITEMEMH '(' expr ',' idClassSel ',' expr ',' expr ')' { $$ = new AstWriteMem($1, true, $3, $5, $7, $9); } // // Any system function as a task @@ -3561,14 +3593,14 @@ system_t_call: // IEEE: system_tf_call (as task) system_f_call: // IEEE: system_tf_call (as func) yaD_PLI systemDpiArgsE { $$ = new AstFuncRef($1, *$1, $2); VN_CAST($$, FuncRef)->pli(true); } // - | yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? NULL : new AstUCFunc($1,$3)); } + | yD_C '(' cStrList ')' { $$ = (v3Global.opt.ignc() ? nullptr : new AstUCFunc($1,$3)); } | yD_SYSTEM '(' expr ')' { $$ = new AstSystemF($1,$3); } // | system_f_call_or_t { $$ = $1; } ; systemDpiArgsE: // IEEE: part of system_if_call for aruments of $dpi call - parenE { $$ = NULL; } + parenE { $$ = nullptr; } | '(' exprList ')' { $$ = GRAMMARP->argWrapList($2); } ; @@ -3586,6 +3618,8 @@ system_f_call_or_t: // IEEE: part of system_tf_call (can be task or func) | yD_BITSTOSHORTREAL '(' expr ')' { $$ = new AstBitsToRealD($1,$3); UNSUPREAL($1); } | yD_CAST '(' expr ',' expr ')' { $$ = new AstCastDynamic($1, $3, $5); } | yD_CEIL '(' expr ')' { $$ = new AstCeilD($1,$3); } + | yD_CHANGED '(' expr ')' { $$ = new AstLogNot($1, new AstStable($1, $3)); } + | yD_CHANGED '(' expr ',' expr ')' { $$ = $3; BBUNSUP($1, "Unsupported: $changed and clock arguments"); } | yD_CLOG2 '(' expr ')' { $$ = new AstCLog2($1,$3); } | yD_COS '(' expr ')' { $$ = new AstCosD($1,$3); } | yD_COSH '(' expr ')' { $$ = new AstCoshD($1,$3); } @@ -3604,31 +3638,31 @@ system_f_call_or_t: // IEEE: part of system_tf_call (can be task or func) | yD_FERROR '(' idClassSel ',' idClassSel ')' { $$ = new AstFError($1, $3, $5); } | yD_FGETC '(' expr ')' { $$ = new AstFGetC($1,$3); } | yD_FGETS '(' idClassSel ',' expr ')' { $$ = new AstFGetS($1,$3,$5); } - | yD_FREAD '(' idClassSel ',' expr ')' { $$ = new AstFRead($1,$3,$5,NULL,NULL); } - | yD_FREAD '(' idClassSel ',' expr ',' expr ')' { $$ = new AstFRead($1,$3,$5,$7,NULL); } + | yD_FREAD '(' idClassSel ',' expr ')' { $$ = new AstFRead($1,$3,$5,nullptr,nullptr); } + | yD_FREAD '(' idClassSel ',' expr ',' expr ')' { $$ = new AstFRead($1,$3,$5,$7,nullptr); } | yD_FREAD '(' idClassSel ',' expr ',' expr ',' expr ')' { $$ = new AstFRead($1,$3,$5,$7,$9); } | yD_FREWIND '(' idClassSel ')' { $$ = new AstFRewind($1, $3); } | yD_FLOOR '(' expr ')' { $$ = new AstFloorD($1,$3); } | yD_FSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstFScanF($1,*$5,$3,$6); } | yD_FSEEK '(' idClassSel ',' expr ',' expr ')' { $$ = new AstFSeek($1,$3,$5,$7); } | yD_FTELL '(' idClassSel ')' { $$ = new AstFTell($1, $3); } - | yD_HIGH '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,NULL); } + | yD_HIGH '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,nullptr); } | yD_HIGH '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_HIGH,$3,$5); } | yD_HYPOT '(' expr ',' expr ')' { $$ = new AstHypotD($1,$3,$5); } - | yD_INCREMENT '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_INCREMENT,$3,NULL); } + | yD_INCREMENT '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_INCREMENT,$3,nullptr); } | yD_INCREMENT '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_INCREMENT,$3,$5); } | yD_ISUNBOUNDED '(' expr ')' { $$ = new AstIsUnbounded($1, $3); } | yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown($1, $3); } | yD_ITOR '(' expr ')' { $$ = new AstIToRD($1,$3); } - | yD_LEFT '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LEFT,$3,NULL); } + | yD_LEFT '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LEFT,$3,nullptr); } | yD_LEFT '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LEFT,$3,$5); } | yD_LN '(' expr ')' { $$ = new AstLogD($1,$3); } | yD_LOG10 '(' expr ')' { $$ = new AstLog10D($1,$3); } - | yD_LOW '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LOW,$3,NULL); } + | yD_LOW '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LOW,$3,nullptr); } | yD_LOW '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_LOW,$3,$5); } | yD_ONEHOT '(' expr ')' { $$ = new AstOneHot($1,$3); } | yD_ONEHOT0 '(' expr ')' { $$ = new AstOneHot0($1,$3); } - | yD_PAST '(' expr ')' { $$ = new AstPast($1,$3, NULL); } + | yD_PAST '(' expr ')' { $$ = new AstPast($1,$3, nullptr); } | yD_PAST '(' expr ',' expr ')' { $$ = new AstPast($1,$3, $5); } | yD_PAST '(' expr ',' expr ',' expr ')' { $$ = $3; BBUNSUP($1, "Unsupported: $past expr2 and clock arguments"); } | yD_PAST '(' expr ',' expr ',' expr ',' expr')' { $$ = $3; BBUNSUP($1, "Unsupported: $past expr2 and clock arguments"); } @@ -3639,7 +3673,7 @@ system_f_call_or_t: // IEEE: part of system_tf_call (can be task or func) | yD_REALTIME parenE { $$ = new AstTimeD($1, VTimescale(VTimescale::NONE)); } | yD_REALTOBITS '(' expr ')' { $$ = new AstRealToBits($1,$3); } | yD_REWIND '(' idClassSel ')' { $$ = new AstFSeek($1, $3, new AstConst($1, 0), new AstConst($1, 0)); } - | yD_RIGHT '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_RIGHT,$3,NULL); } + | yD_RIGHT '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_RIGHT,$3,nullptr); } | yD_RIGHT '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_RIGHT,$3,$5); } | yD_ROSE '(' expr ')' { $$ = new AstRose($1,$3); } | yD_ROSE '(' expr ',' expr ')' { $$ = $3; BBUNSUP($1, "Unsupported: $rose and clock arguments"); } @@ -3650,7 +3684,7 @@ system_f_call_or_t: // IEEE: part of system_tf_call (can be task or func) | yD_SIGNED '(' expr ')' { $$ = new AstSigned($1,$3); } | yD_SIN '(' expr ')' { $$ = new AstSinD($1,$3); } | yD_SINH '(' expr ')' { $$ = new AstSinhD($1,$3); } - | yD_SIZE '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_SIZE,$3,NULL); } + | yD_SIZE '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_SIZE,$3,nullptr); } | yD_SIZE '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_SIZE,$3,$5); } | yD_SQRT '(' expr ')' { $$ = new AstSqrtD($1,$3); } | yD_SSCANF '(' expr ',' str commaVRDListE ')' { $$ = new AstSScanF($1,*$5,$3,$6); } @@ -3665,7 +3699,10 @@ system_f_call_or_t: // IEEE: part of system_tf_call (can be task or func) | yD_UNGETC '(' expr ',' expr ')' { $$ = new AstFUngetC($1, $5, $3); } // Arg swap to file first | yD_UNPACKED_DIMENSIONS '(' exprOrDataType ')' { $$ = new AstAttrOf($1,AstAttrType::DIM_UNPK_DIMENSIONS,$3); } | yD_UNSIGNED '(' expr ')' { $$ = new AstUnsigned($1,$3); } - | yD_VALUEPLUSARGS '(' expr ',' expr ')' { $$ = new AstValuePlusArgs($1,$3,$5); } + | yD_URANDOM '(' expr ')' { $$ = new AstURandom($1); BBUNSUP($1, "Unsupported: Seed on $urandom. Suggest use +verilator+seed+ runtime flag"); } + | yD_URANDOM parenE { $$ = new AstURandom($1); } + | yD_URANDOM_RANGE '(' expr ',' expr ')' { $$ = new AstURandomRange($1, $3, $5); } + | yD_VALUEPLUSARGS '(' expr ',' expr ')' { $$ = new AstValuePlusArgs($1, $3, $5); } ; elaboration_system_task: // IEEE: elaboration_system_task (1800-2009) @@ -3675,14 +3712,14 @@ elaboration_system_task: // IEEE: elaboration_system_task (1800-2009) elaboration_system_task_guts: // IEEE: part of elaboration_system_task (1800-2009) // // $fatal first argument is exit number, must be constant - yD_INFO parenE { $$ = new AstElabDisplay($1, AstDisplayType::DT_INFO, NULL); } + yD_INFO parenE { $$ = new AstElabDisplay($1, AstDisplayType::DT_INFO, nullptr); } | yD_INFO '(' exprList ')' { $$ = new AstElabDisplay($1, AstDisplayType::DT_INFO, $3); } - | yD_WARNING parenE { $$ = new AstElabDisplay($1, AstDisplayType::DT_WARNING, NULL); } + | yD_WARNING parenE { $$ = new AstElabDisplay($1, AstDisplayType::DT_WARNING, nullptr); } | yD_WARNING '(' exprList ')' { $$ = new AstElabDisplay($1, AstDisplayType::DT_WARNING, $3); } - | yD_ERROR parenE { $$ = new AstElabDisplay($1, AstDisplayType::DT_ERROR, NULL); } + | yD_ERROR parenE { $$ = new AstElabDisplay($1, AstDisplayType::DT_ERROR, nullptr); } | yD_ERROR '(' exprList ')' { $$ = new AstElabDisplay($1, AstDisplayType::DT_ERROR, $3); } - | yD_FATAL parenE { $$ = new AstElabDisplay($1, AstDisplayType::DT_FATAL, NULL); } - | yD_FATAL '(' expr ')' { $$ = new AstElabDisplay($1, AstDisplayType::DT_FATAL, NULL); DEL($3); } + | yD_FATAL parenE { $$ = new AstElabDisplay($1, AstDisplayType::DT_FATAL, nullptr); } + | yD_FATAL '(' expr ')' { $$ = new AstElabDisplay($1, AstDisplayType::DT_FATAL, nullptr); DEL($3); } | yD_FATAL '(' expr ',' exprListE ')' { $$ = new AstElabDisplay($1, AstDisplayType::DT_FATAL, $5); DEL($3); } ; @@ -3720,7 +3757,7 @@ list_of_argumentsE: // IEEE: [list_of_arguments] argsDottedList { $$ = $1; } | argsExprListE { if (VN_IS($1, Arg) && VN_CAST($1, Arg)->emptyConnectNoNext()) { - $1->deleteTree(); $$ = NULL; // Mis-created when have 'func()' + $1->deleteTree(); $$ = nullptr; // Mis-created when have 'func()' } else { $$ = $1; } } | argsExprListE ',' argsDottedList { $$ = $1->addNextNull($3); } ; @@ -3782,63 +3819,79 @@ lifetime: // ==IEEE: lifetime ; taskId: - tfIdScoped - { $$ = new AstTask($1, *$1, NULL); + id + { $$ = new AstTask($$, *$1, nullptr); + SYMP->pushNewUnderNodeOrCurrent($$, nullptr); } + // + | id/*interface_identifier*/ '.' id + { $$ = new AstTask($$, *$3, nullptr); + BBUNSUP($2, "Unsupported: Out of block function declaration"); + SYMP->pushNewUnderNodeOrCurrent($$, nullptr); } + // + | packageClassScope id + { $$ = new AstTask($$, *$2, nullptr); + $$->packagep($1); SYMP->pushNewUnderNodeOrCurrent($$, $1); } ; funcId: // IEEE: function_data_type_or_implicit + part of function_body_declaration // // IEEE: function_data_type_or_implicit must be expanded here to prevent conflict // // function_data_type expanded here to prevent conflicts with implicit_type:empty vs data_type:ID - /**/ tfIdScoped - { $$ = new AstFunc($1,*$1,NULL, - new AstBasicDType($1, LOGIC_IMPLICIT)); + /**/ fIdScoped + { $$ = $1; + $$->addFvarp(new AstBasicDType($1, LOGIC_IMPLICIT)); SYMP->pushNewUnderNodeOrCurrent($$, $1); } - | signingE rangeList tfIdScoped - { $$ = new AstFunc($3,*$3,NULL, - GRAMMARP->addRange(new AstBasicDType($3, LOGIC_IMPLICIT, $1), $2,true)); + | signingE rangeList fIdScoped + { $$ = $3; + $$->addFvarp(GRAMMARP->addRange(new AstBasicDType($3, LOGIC_IMPLICIT, $1), $2,true)); SYMP->pushNewUnderNodeOrCurrent($$, $3); } - | signing tfIdScoped - { $$ = new AstFunc($2,*$2,NULL, - new AstBasicDType($2, LOGIC_IMPLICIT, $1)); + | signing fIdScoped + { $$ = $2; + $$->addFvarp(new AstBasicDType($2, LOGIC_IMPLICIT, $1)); SYMP->pushNewUnderNodeOrCurrent($$, $2); } - | data_type tfIdScoped - { $$ = new AstFunc($2,*$2,NULL,$1); + | data_type fIdScoped + { $$ = $2; + $$->addFvarp($1); SYMP->pushNewUnderNodeOrCurrent($$, $2); } // // To verilator tasks are the same as void functions (we separately detect time passing) - | yVOID tfIdScoped - { $$ = new AstTask($2, *$2, NULL); - SYMP->pushNewUnderNodeOrCurrent($$, $2); } + | yVOID taskId + { $$ = $2; } ; funcIdNew: // IEEE: from class_constructor_declaration yNEW__ETC - { $$ = new AstFunc($1, "new", NULL, NULL); + { $$ = new AstFunc($1, "new", nullptr, nullptr); $$->isConstructor(true); - SYMP->pushNewUnder($$, NULL); } + SYMP->pushNewUnder($$, nullptr); } | yNEW__PAREN - { $$ = new AstFunc($1, "new", NULL, NULL); + { $$ = new AstFunc($1, "new", nullptr, nullptr); $$->isConstructor(true); - SYMP->pushNewUnder($$, NULL); } + SYMP->pushNewUnder($$, nullptr); } | packageClassScopeNoId yNEW__PAREN - { $$ = new AstFunc($2, "new", NULL, NULL); - BBUNSUP($2, "Unsupported: scoped new constructor"); + { $$ = new AstFunc($2, "new", nullptr, nullptr); + $$->packagep($1); $$->isConstructor(true); SYMP->pushNewUnderNodeOrCurrent($$, $1); } ; -tfIdScoped: // IEEE: part of function_body_declaration/task_body_declaration +fIdScoped: // IEEE: part of function_body_declaration/task_body_declaration // // IEEE: [ interface_identifier '.' | class_scope ] function_identifier id - { $$ = $1; $$ = NULL; $$ = $1; } + { $$ = $1; + $$ = nullptr; + $$ = new AstFunc($$, *$1, nullptr, nullptr); } // | id/*interface_identifier*/ '.' id - { $$ = $3; $$ = NULL; $$ = $3; + { $$ = $1; + $$ = nullptr; + $$ = new AstFunc($$, *$1, nullptr, nullptr); BBUNSUP($2, "Unsupported: Out of block function declaration"); } // | packageClassScope id - { $$ = $2; $$ = $1; $$ = $2; - BBUNSUP($1, "Unsupported: Out of class block function declaration"); } + { $$ = $1; + $$ = $1; + $$ = new AstFunc($$, *$2, nullptr, nullptr); + $$->packagep($1); } ; tfGuts: @@ -3847,7 +3900,7 @@ tfGuts: ; tfBodyE: // IEEE: part of function_body_declaration/task_body_declaration - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | tf_item_declarationList { $$ = $1; } | tf_item_declarationList stmtList { $$ = $1->addNextNull($2); } | stmtList { $$ = $1; } @@ -3883,7 +3936,7 @@ tf_port_listList: // IEEE: part of tf_port_list tf_port_item: // ==IEEE: tf_port_item // // We split tf_port_item into the type and assignment as don't know what follows a comma - /* empty */ { $$ = NULL; PINNUMINC(); } // For example a ",," port + /* empty */ { $$ = nullptr; PINNUMINC(); } // For example a ",," port | tf_port_itemFront tf_port_itemAssignment { $$ = $2; } | tf_port_itemAssignment { $$ = $1; } ; @@ -3895,7 +3948,7 @@ tf_port_itemFront: // IEEE: part of tf_port_item, which has the data type | yVAR data_type { VARDTYPE($2); } | yVAR implicit_typeE { VARDTYPE($2); } // - | tf_port_itemDir /*implicit*/ { VARDTYPE(NULL); /*default_nettype-see spec*/ } + | tf_port_itemDir /*implicit*/ { VARDTYPE(nullptr); /*default_nettype-see spec*/ } | tf_port_itemDir data_type { VARDTYPE($2); } | tf_port_itemDir signingE rangeList { VARDTYPE(GRAMMARP->addRange(new AstBasicDType($3->fileline(), LOGIC_IMPLICIT, $2),$3,true)); } | tf_port_itemDir signing { VARDTYPE(new AstBasicDType($2, LOGIC_IMPLICIT, $2)); } @@ -3925,10 +3978,10 @@ parenE: // // method_call_root not needed, part of expr resolution // // What's left is below array_methodNoRoot array_methodNoRoot: - yOR { $$ = new AstFuncRef($1, "or", NULL); } - | yAND { $$ = new AstFuncRef($1, "and", NULL); } - | yXOR { $$ = new AstFuncRef($1, "xor", NULL); } - | yUNIQUE { $$ = new AstFuncRef($1, "unique", NULL); } + yOR { $$ = new AstFuncRef($1, "or", nullptr); } + | yAND { $$ = new AstFuncRef($1, "and", nullptr); } + | yXOR { $$ = new AstFuncRef($1, "xor", nullptr); } + | yUNIQUE { $$ = new AstFuncRef($1, "unique", nullptr); } ; array_methodWith: @@ -3944,13 +3997,13 @@ dpi_import_export: // ==IEEE: dpi_import_export { $$ = $5; if (*$4 != "") $5->cname(*$4); $5->dpiContext($3==iprop_CONTEXT); $5->pure($3==iprop_PURE); $5->dpiImport(true); GRAMMARP->checkDpiVer($1,*$2); v3Global.dpi(true); - if ($$->prettyName()[0]=='$') SYMP->reinsert($$,NULL,$$->prettyName()); // For $SysTF overriding + if ($$->prettyName()[0]=='$') SYMP->reinsert($$,nullptr,$$->prettyName()); // For $SysTF overriding SYMP->reinsert($$); } | yIMPORT yaSTRING dpi_tf_import_propertyE dpi_importLabelE task_prototype ';' { $$ = $5; if (*$4 != "") $5->cname(*$4); $5->dpiContext($3==iprop_CONTEXT); $5->pure($3==iprop_PURE); $5->dpiImport(true); $5->dpiTask(true); GRAMMARP->checkDpiVer($1,*$2); v3Global.dpi(true); - if ($$->prettyName()[0]=='$') SYMP->reinsert($$,NULL,$$->prettyName()); // For $SysTF overriding + if ($$->prettyName()[0]=='$') SYMP->reinsert($$,nullptr,$$->prettyName()); // For $SysTF overriding SYMP->reinsert($$); } | yEXPORT yaSTRING dpi_importLabelE yFUNCTION idAny ';' { $$ = new AstDpiExport($5, *$5, *$3); @@ -3984,13 +4037,13 @@ dpi_tf_import_propertyE: // IEEE: [ dpi_function_import_property + dpi_ta exprEqE: // IEEE: optional '=' expression (part of param_assignment) // // constant_param_expression: '$' is in expr - /*empty*/ { $$ = NULL; } + /*empty*/ { $$ = nullptr; } | '=' expr { $$ = $2; } ; exprOrDataTypeEqE: // IEEE: optional '=' expression (part of param_assignment) // // constant_param_expression: '$' is in expr - /*empty*/ { $$ = NULL; } + /*empty*/ { $$ = nullptr; } | '=' exprOrDataType { $$ = $2; } ; @@ -4305,7 +4358,7 @@ cateList: ; exprListE: - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | exprList { $$ = $1; } ; @@ -4328,7 +4381,7 @@ vrdList: ; commaVRDListE: - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | ',' vrdList { $$ = $2; } ; @@ -4348,12 +4401,12 @@ argsExprListE: // IEEE: part of list_of_arguments //UNSUP ; argsExprOneE: // IEEE: part of list_of_arguments - /*empty*/ { $$ = new AstArg(CRELINE(), "", NULL); } + /*empty*/ { $$ = new AstArg(CRELINE(), "", nullptr); } | expr { $$ = new AstArg($1->fileline(), "", $1); } ; //UNSUPpev_argsExprOneE: // IEEE: part of list_of_arguments - pev_expr at bottom -//UNSUP /*empty*/ { $$ = NULL; } // ,, is legal in list_of_arguments +//UNSUP /*empty*/ { $$ = nullptr; } // ,, is legal in list_of_arguments //UNSUP | pev_expr { $$ = $1; } //UNSUP ; @@ -4368,12 +4421,12 @@ argsDottedList: // IEEE: part of list_of_arguments //UNSUP ; argsDotted: // IEEE: part of list_of_arguments - '.' idAny '(' ')' { $$ = new AstArg($2, *$2, NULL); } + '.' idAny '(' ')' { $$ = new AstArg($2, *$2, nullptr); } | '.' idAny '(' expr ')' { $$ = new AstArg($2, *$2, $4); } ; //UNSUPpev_argsDotted: // IEEE: part of list_of_arguments - pev_expr at bottom -//UNSUP '.' idAny '(' ')' { $$ = new AstArg($2, *$2, NULL); } +//UNSUP '.' idAny '(' ')' { $$ = new AstArg($2, *$2, nullptr); } //UNSUP | '.' idAny '(' pev_expr ')' { $$ = new AstArg($2, *$2, $4); } //UNSUP ; @@ -4635,15 +4688,15 @@ tableEntryList: // IEEE: { combinational_entry | sequential_entry } tableEntry: // IEEE: combinational_entry + sequential_entry yaTABLELINE { $$ = new AstUdpTableLine($1,*$1); } - | error { $$ = NULL; } + | error { $$ = nullptr; } ; //************************************************ // Specify specify_block: // ==IEEE: specify_block - ySPECIFY specifyJunkList yENDSPECIFY { $$ = NULL; } - | ySPECIFY yENDSPECIFY { $$ = NULL; } + ySPECIFY specifyJunkList yENDSPECIFY { $$ = nullptr; } + | ySPECIFY yENDSPECIFY { $$ = nullptr; } ; specifyJunkList: @@ -4658,7 +4711,7 @@ specifyJunk: ; specparam_declaration: // ==IEEE: specparam_declaration - ySPECPARAM junkToSemiList ';' { $$ = NULL; } + ySPECPARAM junkToSemiList ';' { $$ = nullptr; } ; junkToSemiList: @@ -4781,7 +4834,7 @@ idDottedMoreForeach: // enum_identifier idArrayed: // IEEE: id + select id - { $$ = new AstParseRef($1, VParseRefExp::PX_TEXT, *$1, NULL, NULL); } + { $$ = new AstParseRef($1, VParseRefExp::PX_TEXT, *$1, nullptr, nullptr); } // // IEEE: id + part_select_range/constant_part_select_range | idArrayed '[' expr ']' { $$ = new AstSelBit($2, $1, $3); } // Or AstArraySel, don't know yet. | idArrayed '[' constExpr ':' constExpr ']' { $$ = new AstSelExtract($2, $1, $3, $5); } @@ -4792,7 +4845,7 @@ idArrayed: // IEEE: id + select idArrayedForeach: // IEEE: id + select (under foreach expression) id - { $$ = new AstParseRef($1, VParseRefExp::PX_TEXT, *$1, NULL, NULL); } + { $$ = new AstParseRef($1, VParseRefExp::PX_TEXT, *$1, nullptr, nullptr); } // // IEEE: id + part_select_range/constant_part_select_range | idArrayed '[' expr ']' { $$ = new AstSelBit($2, $1, $3); } // Or AstArraySel, don't know yet. | idArrayed '[' constExpr ':' constExpr ']' { $$ = new AstSelExtract($2, $1, $3, $5); } @@ -4820,7 +4873,7 @@ strAsInt: ; strAsIntIgnore: // strAsInt, but never matches for when expr shouldn't parse strings - yaSTRING__IGNORE { $$ = NULL; yyerror("Impossible token"); } + yaSTRING__IGNORE { $$ = nullptr; yyerror("Impossible token"); } ; strAsText: @@ -4828,7 +4881,7 @@ strAsText: ; endLabelE: - /* empty */ { $$ = NULL; $$=NULL; } + /* empty */ { $$ = nullptr; $$=nullptr; } | ':' idAny { $$ = $2; $$=$2; } | ':' yNEW__ETC { static string n = "new"; $$ = &n; $$=$2; } ; @@ -4839,7 +4892,7 @@ endLabelE: clocking_declaration: // IEEE: clocking_declaration (INCOMPLETE) //UNSUP: vvv remove this -- vastly simplified grammar: yDEFAULT yCLOCKING '@' '(' senitemEdge ')' ';' yENDCLOCKING - { $$ = new AstClocking($2, $5, NULL); } + { $$ = new AstClocking($2, $5, nullptr); } //UNSUP: ^^^ remove this -- vastly simplified grammar: //UNSUP clockingFront clocking_event ';' //UNSUP clocking_itemListE yENDCLOCKING endLabelE { SYMP->popScope($$); } @@ -4860,7 +4913,7 @@ clocking_declaration: // IEEE: clocking_declaration (INCOMPLETE) //UNSUP ; //UNSUPclocking_itemListE: -//UNSUP /* empty */ { $$ = NULL; } +//UNSUP /* empty */ { $$ = nullptr; } //UNSUP | clocking_itemList { $$ = $1; } //UNSUP ; @@ -4898,7 +4951,7 @@ clocking_declaration: // IEEE: clocking_declaration (INCOMPLETE) //UNSUP ; //UNSUPclocking_skewE: // IEEE: [clocking_skew] -//UNSUP /* empty */ { $$ = NULL;} +//UNSUP /* empty */ { $$ = nullptr;} //UNSUP | clocking_skew { $$ = $1; } //UNSUP ; @@ -4930,7 +4983,7 @@ clocking_declaration: // IEEE: clocking_declaration (INCOMPLETE) assertion_item: // ==IEEE: assertion_item concurrent_assertion_item { $$ = $1; } | deferred_immediate_assertion_item - { $$ = $1 ? new AstAlways($1->fileline(), VAlwaysKwd::ALWAYS_COMB, NULL, $1) : NULL; } + { $$ = $1 ? new AstAlways($1->fileline(), VAlwaysKwd::ALWAYS_COMB, nullptr, $1) : nullptr; } ; deferred_immediate_assertion_item: // ==IEEE: deferred_immediate_assertion_item @@ -4954,12 +5007,12 @@ immediate_assertion_statement: // ==IEEE: immediate_assertion_statement simple_immediate_assertion_statement: // ==IEEE: simple_immediate_assertion_statement // // action_block expanded here, for compatibility with AstAssert - yASSERT '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE { $$ = new AstAssert($1, $3, $5, NULL, true); } - | yASSERT '(' expr ')' yELSE stmtBlock { $$ = new AstAssert($1, $3, NULL, $6, true); } + yASSERT '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE { $$ = new AstAssert($1, $3, $5, nullptr, true); } + | yASSERT '(' expr ')' yELSE stmtBlock { $$ = new AstAssert($1, $3, nullptr, $6, true); } | yASSERT '(' expr ')' stmtBlock yELSE stmtBlock { $$ = new AstAssert($1, $3, $5, $7, true); } // // action_block expanded here, for compatibility with AstAssert - | yASSUME '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE { $$ = new AstAssert($1, $3, $5, NULL, true); } - | yASSUME '(' expr ')' yELSE stmtBlock { $$ = new AstAssert($1, $3, NULL, $6, true); } + | yASSUME '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE { $$ = new AstAssert($1, $3, $5, nullptr, true); } + | yASSUME '(' expr ')' yELSE stmtBlock { $$ = new AstAssert($1, $3, nullptr, $6, true); } | yASSUME '(' expr ')' stmtBlock yELSE stmtBlock { $$ = new AstAssert($1, $3, $5, $7, true); } // // IEEE: simple_immediate_cover_statement | yCOVER '(' expr ')' stmt { $$ = new AstCover($1, $3, $5, true); } @@ -4974,12 +5027,12 @@ final_zero: // IEEE: part of deferred_immediate_assertion_statement deferred_immediate_assertion_statement: // ==IEEE: deferred_immediate_assertion_statement // // IEEE: deferred_immediate_assert_statement - yASSERT final_zero '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE { $$ = new AstAssert($1, $4, $6, NULL, true); } - | yASSERT final_zero '(' expr ')' yELSE stmtBlock { $$ = new AstAssert($1, $4, NULL, $7, true); } + yASSERT final_zero '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE { $$ = new AstAssert($1, $4, $6, nullptr, true); } + | yASSERT final_zero '(' expr ')' yELSE stmtBlock { $$ = new AstAssert($1, $4, nullptr, $7, true); } | yASSERT final_zero '(' expr ')' stmtBlock yELSE stmtBlock { $$ = new AstAssert($1, $4, $6, $8, true); } // // IEEE: deferred_immediate_assume_statement - | yASSUME final_zero '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE { $$ = new AstAssert($1, $4, $6, NULL, true); } - | yASSUME final_zero '(' expr ')' yELSE stmtBlock { $$ = new AstAssert($1, $4, NULL, $7, true); } + | yASSUME final_zero '(' expr ')' stmtBlock %prec prLOWER_THAN_ELSE { $$ = new AstAssert($1, $4, $6, nullptr, true); } + | yASSUME final_zero '(' expr ')' yELSE stmtBlock { $$ = new AstAssert($1, $4, nullptr, $7, true); } | yASSUME final_zero '(' expr ')' stmtBlock yELSE stmtBlock { $$ = new AstAssert($1, $4, $6, $8, true); } // // IEEE: deferred_immediate_cover_statement | yCOVER final_zero '(' expr ')' stmt { $$ = new AstCover($1, $4, $6, true); } @@ -5000,9 +5053,10 @@ concurrent_assertion_item: // IEEE: concurrent_assertion_item concurrent_assertion_statement: // ==IEEE: concurrent_assertion_statement // // IEEE: assert_property_statement //UNSUP remove below: - yASSERT yPROPERTY '(' property_spec ')' elseStmtBlock { $$ = new AstAssert($1, $4, NULL, $6, false); } + yASSERT yPROPERTY '(' property_spec ')' elseStmtBlock { $$ = new AstAssert($1, $4, nullptr, $6, false); } //UNSUP yASSERT yPROPERTY '(' property_spec ')' action_block { } // // IEEE: assume_property_statement + | yASSUME yPROPERTY '(' property_spec ')' elseStmtBlock { $$ = new AstAssert($1, $4, nullptr, $6, false); } //UNSUP yASSUME yPROPERTY '(' property_spec ')' action_block { } // // IEEE: cover_property_statement | yCOVER yPROPERTY '(' property_spec ')' stmtBlock { $$ = new AstCover($1, $4, $6, false); } @@ -5017,7 +5071,7 @@ concurrent_assertion_statement: // ==IEEE: concurrent_assertion_statement ; elseStmtBlock: // Part of concurrent_assertion_statement - ';' { $$ = NULL; } + ';' { $$ = nullptr; } | yELSE stmtBlock { $$ = $2; } ; @@ -5033,7 +5087,7 @@ elseStmtBlock: // Part of concurrent_assertion_statement //UNSUP ; //UNSUPproperty_port_listE: // IEEE: [ ( [ property_port_list ] ) ] -//UNSUP /* empty */ { $$ = NULL; } +//UNSUP /* empty */ { $$ = nullptr; } //UNSUP | '(' {VARRESET_LIST(""); VARIO("input"); } property_port_list ')' //UNSUP { VARRESET_NONLIST(""); } //UNSUP ; @@ -5070,7 +5124,7 @@ elseStmtBlock: // Part of concurrent_assertion_statement //UNSUP ; //UNSUPproperty_port_itemDirE: -//UNSUP /* empty */ { $$ = NULL; } +//UNSUP /* empty */ { $$ = nullptr; } //UNSUP | yLOCAL__ETC { } //UNSUP | yLOCAL__ETC port_direction { } //UNSUP ; @@ -5135,10 +5189,10 @@ property_spec: // IEEE: property_spec //UNSUP remove below '@' '(' senitemEdge ')' yDISABLE yIFF '(' expr ')' pexpr { $$ = new AstPropClocked($1, $3, $8, $10); } - | '@' '(' senitemEdge ')' pexpr { $$ = new AstPropClocked($1, $3, NULL, $5); } + | '@' '(' senitemEdge ')' pexpr { $$ = new AstPropClocked($1, $3, nullptr, $5); } //UNSUP remove above - | yDISABLE yIFF '(' expr ')' pexpr { $$ = new AstPropClocked($4->fileline(), NULL, $4, $6); } - | pexpr { $$ = new AstPropClocked($1->fileline(), NULL, NULL, $1); } + | yDISABLE yIFF '(' expr ')' pexpr { $$ = new AstPropClocked($4->fileline(), nullptr, $4, $6); } + | pexpr { $$ = new AstPropClocked($1->fileline(), nullptr, nullptr, $1); } ; //UNSUPproperty_statement_spec: // ==IEEE: property_statement_spec @@ -5213,7 +5267,7 @@ pexpr: // IEEE: property_expr (The name pexpr is important as regexps j //UNSUP: This rule has been super-specialized to what is supported now //UNSUP remove below expr yP_ORMINUSGT pexpr { $$ = new AstLogOr($2, new AstLogNot($2, $1), $3); } - //UNSUP expr yP_OREQGT pexpr { $$ = new AstLogOr($2, new AstLogNot($2, new AstPast($2, $1, NULL)), $3); } // This handles disable iff in the past time step incorrectly + //UNSUP expr yP_OREQGT pexpr { $$ = new AstLogOr($2, new AstLogNot($2, new AstPast($2, $1, nullptr)), $3); } // This handles disable iff in the past time step incorrectly | expr { $$ = $1; } //UNSUP remove above, use below: // @@ -5405,7 +5459,7 @@ pexpr: // IEEE: property_expr (The name pexpr is important as regexps j //UNSUP ; //UNSUPcoverage_spec_or_optionListE: // IEEE: [{coverage_spec_or_option}] -//UNSUP /* empty */ { $$ = NULL; } +//UNSUP /* empty */ { $$ = nullptr; } //UNSUP | coverage_spec_or_optionList { $$ = $1; } //UNSUP ; @@ -5419,7 +5473,7 @@ pexpr: // IEEE: property_expr (The name pexpr is important as regexps j //UNSUP cover_point { $$ = $1; } //UNSUP | cover_cross { $$ = $1; } //UNSUP | coverage_option ';' { $$ = $1; } -//UNSUP | error { $$ = NULL; } +//UNSUP | error { $$ = nullptr; } //UNSUP ; //UNSUPcoverage_option: // ==IEEE: coverage_option @@ -5440,14 +5494,14 @@ pexpr: // IEEE: property_expr (The name pexpr is important as regexps j //UNSUP ; //UNSUPiffE: // IEEE: part of cover_point, others -//UNSUP /* empty */ { $$ = NULL; } +//UNSUP /* empty */ { $$ = nullptr; } //UNSUP | yIFF '(' expr ')' { } //UNSUP ; //UNSUPbins_or_empty: // ==IEEE: bins_or_empty //UNSUP '{' bins_or_optionsList '}' { $$ = $2; } -//UNSUP | '{' '}' { $$ = NULL; } -//UNSUP | ';' { $$ = NULL; } +//UNSUP | '{' '}' { $$ = nullptr; } +//UNSUP | ';' { $$ = nullptr; } //UNSUP ; //UNSUPbins_or_optionsList: // IEEE: { bins_or_options ';' } @@ -5475,7 +5529,7 @@ pexpr: // IEEE: property_expr (The name pexpr is important as regexps j //UNSUP ; //UNSUPbins_orBraE: // IEEE: part of bins_or_options: -//UNSUP /* empty */ { $$ = NULL; } +//UNSUP /* empty */ { $$ = nullptr; } //UNSUP | '[' ']' { } //UNSUP | '[' cgexpr ']' { } //UNSUP ; @@ -5529,7 +5583,7 @@ pexpr: // IEEE: property_expr (The name pexpr is important as regexps j //UNSUP ; //UNSUPcross_itemList: // IEEE: part of list_of_cross_items -//UNSUP cross_item { $$ = NULL; } +//UNSUP cross_item { $$ = nullptr; } //UNSUP | cross_itemList ',' cross_item { $$ = AstNode::addNextNull($1, $3); } //UNSUP ; @@ -5538,10 +5592,10 @@ pexpr: // IEEE: property_expr (The name pexpr is important as regexps j //UNSUP ; //UNSUPcross_body: // ==IEEE: cross_body -//UNSUP '{' '}' { $$ = NULL; } +//UNSUP '{' '}' { $$ = nullptr; } //UNSUP // // IEEE-2012: No semicolon here, mistake in spec //UNSUP | '{' cross_body_itemSemiList '}' { $$ = $1; } -//UNSUP | ';' { $$ = NULL; } +//UNSUP | ';' { $$ = nullptr; } //UNSUP ; //UNSUPcross_body_itemSemiList: // IEEE: part of cross_body @@ -5592,7 +5646,7 @@ pexpr: // IEEE: property_expr (The name pexpr is important as regexps j //UNSUP ; //UNSUPcoverage_eventE: // IEEE: [ coverage_event ] -//UNSUP /* empty */ { $$ = NULL; } +//UNSUP /* empty */ { $$ = nullptr; } //UNSUP | clocking_event { $$ = $1; } //UNSUP | yWITH__ETC function idAny/*"sample"*/ '(' tf_port_listE ')' { } //UNSUP | yP_ATAT '(' block_event_expression ')' { } @@ -5664,7 +5718,7 @@ pexpr: // IEEE: property_expr (The name pexpr is important as regexps j //UNSUP ; //UNSUPrs_code_block: // ==IEEE: rs_code_block -//UNSUP '{' '}' { $$ = NULL; } +//UNSUP '{' '}' { $$ = nullptr; } //UNSUP | '{' rs_code_blockItemList '}' { $$ = $2; } //UNSUP ; @@ -5737,7 +5791,7 @@ pexpr: // IEEE: property_expr (The name pexpr is important as regexps j //UNSUP ; //UNSUPchecker_or_generate_itemListE: // IEEE: [{ checker_or_generate_itemList }] -//UNSUP /* empty */ { $$ = NULL; } +//UNSUP /* empty */ { $$ = nullptr; } //UNSUP | checker_or_generate_itemList { $$ = $1; } //UNSUP ; @@ -5769,7 +5823,7 @@ pexpr: // IEEE: property_expr (The name pexpr is important as regexps j //UNSUP | clocking_declaration { $$ = $1; } //UNSUP | yDEFAULT yCLOCKING id/*clocking_identifier*/ ';' { } //UNSUP | yDEFAULT yDISABLE yIFF expr/*expression_or_dist*/ ';' { } -//UNSUP | ';' { $$ = NULL; } +//UNSUP | ';' { $$ = nullptr; } //UNSUP ; //UNSUPchecker_generate_item: // ==IEEE: checker_generate_item @@ -5830,7 +5884,7 @@ classVirtualE: classExtendsE: // IEEE: part of class_declaration // // The classExtendsE rule relys on classFront having the // // new class scope correct via classFront - /* empty */ { $$ = NULL; $$ = NULL; } + /* empty */ { $$ = nullptr; $$ = nullptr; } | yEXTENDS classExtendsList { $$ = $2; $$ = $2; } ; @@ -5855,13 +5909,13 @@ classExtendsOne: // IEEE: part of class_declaration classImplementsE: // IEEE: part of class_declaration // // All 1800-2012 - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | yIMPLEMENTS classImplementsList { $$ = $2; } ; classImplementsList: // IEEE: part of class_declaration // // All 1800-2012 - class_typeExtImpList { $$ = NULL; BBUNSUP($1, "Unsupported: implements class"); } + class_typeExtImpList { $$ = nullptr; BBUNSUP($1, "Unsupported: implements class"); } | classImplementsList ',' class_typeExtImpList { $$ = AstNode::addNextNull($1, $3); } ; @@ -5890,13 +5944,13 @@ class_typeExtImpOne: // part of IEEE: class_type, where we either get a p // // // package_sopeIdFollows expanded | yD_UNIT yP_COLONCOLON - { $$ = new AstClassOrPackageRef($1, "$unit", NULL, NULL); - $$ = NULL; // No purpose otherwise, every symtab can see root + { $$ = new AstClassOrPackageRef($1, "$unit", nullptr, nullptr); + $$ = nullptr; // No purpose otherwise, every symtab can see root SYMP->nextId(PARSEP->rootp()); } // | yLOCAL__COLONCOLON yP_COLONCOLON - { $$ = new AstClassOrPackageRef($1, "local::", NULL, NULL); - $$ = NULL; // UNSUP + { $$ = new AstClassOrPackageRef($1, "local::", nullptr, nullptr); + $$ = nullptr; // UNSUP SYMP->nextId(PARSEP->rootp()); BBUNSUP($1, "Unsupported: Randomize 'local::'"); } ; @@ -5909,7 +5963,7 @@ class_typeExtImpOne: // part of IEEE: class_type, where we either get a p //=== Below rules assume special scoping per above packageClassScopeNoId: // IEEE: [package_scope] not followed by yaID - packageClassScope { $$ = $1; $$ = $1; SYMP->nextId(NULL); } + packageClassScope { $$ = $1; $$ = $1; SYMP->nextId(nullptr); } ; packageClassScopeE: // IEEE: [package_scope] @@ -5917,7 +5971,7 @@ packageClassScopeE: // IEEE: [package_scope] // // if not needed must use packageClassScopeNoId // // TODO: To support classes should return generic type, not packagep // // class_qualifier := [ yLOCAL '::' ] [ implicit_class_handle '.' class_scope ] - /* empty */ { $$ = NULL; $$ = NULL; } + /* empty */ { $$ = nullptr; $$ = nullptr; } | packageClassScope { $$ = $1; $$ = $1; } ; @@ -5953,7 +6007,7 @@ packageClassScopeItem: // IEEE: package_scope or [package_scope]::[class_ idCC /*mid*/ { SYMP->nextId($1); } /*cont*/ yP_COLONCOLON - { $$ = new AstClassOrPackageRef($1, *$1, $1, NULL); $$ = $1; } + { $$ = new AstClassOrPackageRef($1, *$1, $1, nullptr); $$ = $1; } // | idCC parameter_value_assignment /*mid*/ { SYMP->nextId($1); } // Change next *after* we handle parameters, not before @@ -5966,7 +6020,7 @@ dollarUnitNextId: // $unit // // if not needed must use packageClassScopeNoId // // Must call nextId without any additional tokens following yD_UNIT - { $$ = new AstClassOrPackageRef($1, "$unit", GRAMMARP->unitPackage($1), NULL); + { $$ = new AstClassOrPackageRef($1, "$unit", GRAMMARP->unitPackage($1), nullptr); SYMP->nextId(PARSEP->rootp()); } ; @@ -5975,7 +6029,7 @@ localNextId: // local // // if not needed must use packageClassScopeNoId // // Must call nextId without any additional tokens following yLOCAL__COLONCOLON - { $$ = new AstClassOrPackageRef($1, "local::", GRAMMARP->unitPackage($1), NULL); + { $$ = new AstClassOrPackageRef($1, "local::", GRAMMARP->unitPackage($1), nullptr); SYMP->nextId(PARSEP->rootp()); BBUNSUP($1, "Unsupported: Randomize 'local::'"); } ; @@ -5983,7 +6037,7 @@ localNextId: // local //^^^========= class_itemListE: - /* empty */ { $$ = NULL; } + /* empty */ { $$ = nullptr; } | class_itemList { $$ = $1; } ; @@ -5997,14 +6051,14 @@ class_item: // ==IEEE: class_item | class_method { $$ = $1; } | class_constraint { $$ = $1; } // - | class_declaration { $$ = NULL; BBUNSUP($1, "Unsupported: class within class"); } + | class_declaration { $$ = nullptr; BBUNSUP($1, "Unsupported: class within class"); } | timeunits_declaration { $$ = $1; } //UNSUP covergroup_declaration { $$ = $1; } // // local_parameter_declaration under parameter_declaration | parameter_declaration ';' { $$ = $1; BBUNSUP($2, "Unsupported: class parameters"); } // 1800-2009 - | ';' { $$ = NULL; } + | ';' { $$ = nullptr; } // - | error ';' { $$ = NULL; } + | error ';' { $$ = nullptr; } ; class_method: // ==IEEE: class_method @@ -6013,11 +6067,11 @@ class_method: // ==IEEE: class_method | yPURE yVIRTUAL__ETC memberQualListE method_prototype ';' { $$ = $4; $3.applyToNodes($4); $4->pureVirtual(true); $4->isVirtual(true); } | yEXTERN memberQualListE method_prototype ';' - { $$ = $3; $2.applyToNodes($3); $3->isExtern(true); } + { $$ = $3; $2.applyToNodes($3); $3->isExternProto(true); } // // IEEE: "method_qualifierE class_constructor_declaration" // // part of function_declaration | yEXTERN memberQualListE class_constructor_prototype - { $$ = $3; $2.applyToNodes($3); $3->isExtern(true); } + { $$ = $3; $2.applyToNodes($3); $3->isExternProto(true); } ; // IEEE: class_constructor_prototype @@ -6058,11 +6112,11 @@ class_constraint: // ==IEEE: class_constraint // // IEEE: constraint_declaration // // UNSUP: We have the unsupported warning on the randomize() call, so don't bother on // // constraint blocks. When we support randomize we need to make AST nodes for below rules - constraintStaticE yCONSTRAINT idAny constraint_block { $$ = NULL; /*UNSUP*/ } + constraintStaticE yCONSTRAINT idAny constraint_block { $$ = nullptr; /*UNSUP*/ } // // IEEE: constraint_prototype + constraint_prototype_qualifier - | constraintStaticE yCONSTRAINT idAny ';' { $$ = NULL; } - | yEXTERN constraintStaticE yCONSTRAINT idAny ';' { $$ = NULL; BBUNSUP($1, "Unsupported: extern constraint"); } - | yPURE constraintStaticE yCONSTRAINT idAny ';' { $$ = NULL; BBUNSUP($1, "Unsupported: pure constraint"); } + | constraintStaticE yCONSTRAINT idAny ';' { $$ = nullptr; } + | yEXTERN constraintStaticE yCONSTRAINT idAny ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: extern constraint"); } + | yPURE constraintStaticE yCONSTRAINT idAny ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: pure constraint"); } ; constraint_block: // ==IEEE: constraint_block @@ -6076,7 +6130,7 @@ constraint_block_itemList: // IEEE: { constraint_block_item } constraint_block_item: // ==IEEE: constraint_block_item constraint_expression { $$ = $1; } - | ySOLVE solve_before_list yBEFORE solve_before_list ';' { $$ = NULL; BBUNSUP($2, "Unsupported: solve before"); } + | ySOLVE solve_before_list yBEFORE solve_before_list ';' { $$ = nullptr; BBUNSUP($2, "Unsupported: solve before"); } ; solve_before_list: // ==IEEE: solve_before_list @@ -6097,19 +6151,19 @@ constraint_expressionList: // ==IEEE: { constraint_expression } constraint_expression: // ==IEEE: constraint_expression expr/*expression_or_dist*/ ';' { $$ = $1; } // // 1800-2012: - | ySOFT expr/*expression_or_dist*/ ';' { $$ = NULL; /*UNSUP-no-UVM*/ } + | ySOFT expr/*expression_or_dist*/ ';' { $$ = nullptr; /*UNSUP-no-UVM*/ } // // 1800-2012: // // IEEE: uniqueness_constraint ';' - | yUNIQUE '{' open_range_list '}' { $$ = NULL; /*UNSUP-no-UVM*/ } + | yUNIQUE '{' open_range_list '}' { $$ = nullptr; /*UNSUP-no-UVM*/ } // // IEEE: expr yP_MINUSGT constraint_set // // Conflicts with expr:"expr yP_MINUSGT expr"; rule moved there // - | yIF '(' expr ')' constraint_set %prec prLOWER_THAN_ELSE { $$ = NULL; /*UNSUP-UVM*/ } - | yIF '(' expr ')' constraint_set yELSE constraint_set { $$ = NULL; /*UNSUP-UVM*/ } + | yIF '(' expr ')' constraint_set %prec prLOWER_THAN_ELSE { $$ = nullptr; /*UNSUP-UVM*/ } + | yIF '(' expr ')' constraint_set yELSE constraint_set { $$ = nullptr; /*UNSUP-UVM*/ } // // IEEE says array_identifier here, but dotted accepted in VMM + 1800-2009 - | yFOREACH '(' idClassSelForeach ')' constraint_set { $$ = NULL; /*UNSUP-UVM*/ } + | yFOREACH '(' idClassSelForeach ')' constraint_set { $$ = nullptr; /*UNSUP-UVM*/ } // // soft is 1800-2012 - | yDISABLE ySOFT expr/*constraint_primary*/ ';' { $$ = NULL; /*UNSUP-no-UVM*/ } + | yDISABLE ySOFT expr/*constraint_primary*/ ';' { $$ = nullptr; /*UNSUP-no-UVM*/ } ; constraint_set: // ==IEEE: constraint_set @@ -6145,6 +6199,15 @@ timeNumAdjusted: // Time constant, adjusted to module's time units/preci { $$ = new AstTimeImport($1, new AstConst($1, AstConst::RealDouble(), $1)); } ; +//********************************************************************** +// Generic tokens + +colon: // Generic colon that isn't making a label (e.g. in a case_item) + ':' { $$ = $1; } + | yP_COLON__BEGIN { $$ = $1; } + | yP_COLON__FORK { $$ = $1; } + ; + //********************************************************************** // VLT Files @@ -6184,6 +6247,8 @@ vltItem: { V3Config::addCaseFull(*$3, 0); } | yVLT_FULL_CASE yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM { V3Config::addCaseFull(*$3, $5->toUInt()); } + | yVLT_HIER_BLOCK vltDModuleE + { V3Config::addModulePragma(*$2, AstPragmaType::HIER_BLOCK); } | yVLT_PARALLEL_CASE yVLT_D_FILE yaSTRING { V3Config::addCaseParallel(*$3, 0); } | yVLT_PARALLEL_CASE yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM diff --git a/test_regress/driver.pl b/test_regress/driver.pl index d4b12ddb5..eadd21b69 100755 --- a/test_regress/driver.pl +++ b/test_regress/driver.pl @@ -1848,11 +1848,7 @@ sub _print_advance_time { else { $set = "topp->"; } if ($self->sc) { - print $fh "#if (SYSTEMC_VERSION>=20070314)\n"; print $fh " sc_start(${time}, $Self->{sc_time_resolution});\n"; - print $fh "#else\n"; - print $fh " sc_start(${time});\n"; - print $fh "#endif\n"; } else { if ($action) { print $fh " ${set}eval();\n"; @@ -2250,10 +2246,8 @@ sub cxx_version { return $_Cxx_Version; } -our $_Cfg_With_Threaded; sub cfg_with_threaded { - $_Cfg_With_Threaded ||= `$ENV{MAKE} -C $ENV{VERILATOR_ROOT} -f Makefile print-cfg-with-threaded`; - return ($_Cfg_With_Threaded =~ /yes/i) ? 1:0; + return 1; # C++11 now always required } sub tries { diff --git a/test_regress/t/t_array_backw_index_bad.out b/test_regress/t/t_array_backw_index_bad.out index 65c2aee38..83ee4b870 100644 --- a/test_regress/t/t_array_backw_index_bad.out +++ b/test_regress/t/t_array_backw_index_bad.out @@ -1,21 +1,29 @@ -%Error: t/t_array_backw_index_bad.v:14:19: Slice selection '[1:3]' has backward indexing versus data type's '[3:0]' +%Error: t/t_array_backw_index_bad.v:17:19: Slice selection '[1:3]' has backward indexing versus data type's '[3:0]' : ... In instance t - 14 | array_assign[1:3] = '{32'd4, 32'd3, 32'd2}; + 17 | array_assign[1:3] = '{32'd4, 32'd3, 32'd2}; | ^ -%Error: t/t_array_backw_index_bad.v:15:20: Slice selection '[3:1]' has backward indexing versus data type's '[0:3]' +%Error: t/t_array_backw_index_bad.v:18:20: Slice selection '[3:1]' has backward indexing versus data type's '[0:3]' : ... In instance t - 15 | larray_assign[3:1] = '{32'd4, 32'd3, 32'd2}; + 18 | larray_assign[3:1] = '{32'd4, 32'd3, 32'd2}; | ^ -%Error: t/t_array_backw_index_bad.v:17:19: Slice selection index '[4:3]' outside data type's '[3:0]' +%Error: t/t_array_backw_index_bad.v:19:20: Slice selection '[4:6]' has backward indexing versus data type's '[6:3]' : ... In instance t - 17 | array_assign[4:3] = '{32'd4, 32'd3}; + 19 | array_assign2[4:6] = '{32'd4, 32'd3, 32'd2}; + | ^ +%Error: t/t_array_backw_index_bad.v:20:21: Slice selection '[6:4]' has backward indexing versus data type's '[3:6]' + : ... In instance t + 20 | larray_assign2[6:4] = '{32'd4, 32'd3, 32'd2}; + | ^ +%Error: t/t_array_backw_index_bad.v:22:19: Slice selection index '[4:3]' outside data type's '[3:0]' + : ... In instance t + 22 | array_assign[4:3] = '{32'd4, 32'd3}; | ^ -%Error: t/t_array_backw_index_bad.v:18:19: Slice selection index '[1:-1]' outside data type's '[3:0]' +%Error: t/t_array_backw_index_bad.v:23:19: Slice selection index '[1:-1]' outside data type's '[3:0]' : ... In instance t - 18 | array_assign[1:-1] = '{32'd4, 32'd3}; + 23 | array_assign[1:-1] = '{32'd4, 32'd3}; | ^ -%Error: t/t_array_backw_index_bad.v:18:28: Assignment pattern missed initializing elements: -1 +%Error: t/t_array_backw_index_bad.v:23:28: Assignment pattern missed initializing elements: -1 : ... In instance t - 18 | array_assign[1:-1] = '{32'd4, 32'd3}; + 23 | array_assign[1:-1] = '{32'd4, 32'd3}; | ^~ %Error: Exiting due to diff --git a/test_regress/t/t_array_backw_index_bad.v b/test_regress/t/t_array_backw_index_bad.v index b76aceba1..7056a29fa 100644 --- a/test_regress/t/t_array_backw_index_bad.v +++ b/test_regress/t/t_array_backw_index_bad.v @@ -10,14 +10,21 @@ module t (/*AUTOARG*/); logic [31:0] larray_assign [0:3]; + logic [31:0] array_assign2 [6:3]; + + logic [31:0] larray_assign2 [3:6]; initial begin array_assign[1:3] = '{32'd4, 32'd3, 32'd2}; larray_assign[3:1] = '{32'd4, 32'd3, 32'd2}; + array_assign2[4:6] = '{32'd4, 32'd3, 32'd2}; + larray_assign2[6:4] = '{32'd4, 32'd3, 32'd2}; array_assign[4:3] = '{32'd4, 32'd3}; array_assign[1:-1] = '{32'd4, 32'd3}; array_assign[1:1] = '{32'd4}; // Ok larray_assign[1:1] = '{32'd4}; // Ok + array_assign2[4:4] = '{32'd4}; // Ok + larray_assign2[4:4] = '{32'd4}; // Ok $write("*-* All Finished *-*\n"); $finish; diff --git a/test_regress/t/t_assert_property.v b/test_regress/t/t_assert_property.v index 797a48b52..f530048b2 100644 --- a/test_regress/t/t_assert_property.v +++ b/test_regress/t/t_assert_property.v @@ -38,13 +38,17 @@ module Test `ifdef FAIL_ASSERT_1 assert property (@(posedge clk) cyc==3) else $display("cyc != 3, cyc == %0d", cyc); + assume property (@(posedge clk) cyc==3) + else $display("cyc != 3, cyc == %0d", cyc); `endif `ifdef FAIL_ASSERT_2 assert property (@(posedge clk) cyc!=3); + assume property (@(posedge clk) cyc!=3); `endif assert property (@(posedge clk) cyc < 100); + assume property (@(posedge clk) cyc < 100); restrict property (@(posedge clk) cyc==1); // Ignored in simulators diff --git a/test_regress/t/t_class_class.v b/test_regress/t/t_class_class.v index ef8596298..7453ffac1 100644 --- a/test_regress/t/t_class_class.v +++ b/test_regress/t/t_class_class.v @@ -12,6 +12,7 @@ class Cls; class SubCls; int smembera; int smemberb; + // TODO put extern function here or in t_class_extern.v to check link endclass : SubCls SubCls sc; endclass : Cls diff --git a/test_regress/t/t_class_extends.out b/test_regress/t/t_class_extends.out index 8cd0d95fd..fc51e85d6 100644 --- a/test_regress/t/t_class_extends.out +++ b/test_regress/t/t_class_extends.out @@ -1,16 +1,4 @@ -%Error-UNSUPPORTED: t/t_class_extends.v:13:21: Unsupported: class extends - 13 | class Base1 extends Base0; - | ^~~~~ -%Error-UNSUPPORTED: t/t_class_extends.v:18:21: Unsupported: class extends - 18 | class Base2 extends Base1; - | ^~~~~ -%Error-UNSUPPORTED: t/t_class_extends.v:22:19: Unsupported: class extends - 22 | class Cls extends Base2; - | ^~~~~ %Error: t/t_class_extends.v:25:4: Can't find typedef: 'T' 25 | T imemberc; | ^ -%Error-UNSUPPORTED: t/t_class_extends.v:33:43: Unsupported: class extends - 33 | class uvm__registry #(type T=int) extends uvm_object_wrapper; - | ^~~~~~~~~~~~~~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_class_extends1.pl b/test_regress/t/t_class_extends1.pl new file mode 100755 index 000000000..aabcde63e --- /dev/null +++ b/test_regress/t/t_class_extends1.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 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 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_class_extends1.v b/test_regress/t/t_class_extends1.v new file mode 100644 index 000000000..c0f8ceeec --- /dev/null +++ b/test_regress/t/t_class_extends1.v @@ -0,0 +1,45 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Base0; + int baseonly; + int baseover; + + function void b_set_bo(int v); baseover = v; endfunction + function int b_get_bo(); return baseover; endfunction + function int get_bo(); return baseover; endfunction +endclass + +class Ext extends Base0; + int baseover; + int extonly; + + function void e_set_bo(int v); baseover = v; endfunction + function int e_get_bo(); return baseover; endfunction + function int get_bo(); return baseover; endfunction +endclass + +module t (/*AUTOARG*/); + initial begin + Ext c; + c = new; + c.baseonly = 10; + c.baseover = 20; + c.extonly = 30; + if (c.baseonly != 10) $stop; + if (c.baseover != 20) $stop; + if (c.extonly != 30) $stop; + + c.b_set_bo(100); + c.e_set_bo(200); + if (c.b_get_bo() != 100) $stop; + if (c.e_get_bo() != 200) $stop; + if (c.get_bo() != 200) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_class_extends_nf_bad.out b/test_regress/t/t_class_extends_nf_bad.out new file mode 100644 index 000000000..62fc4e306 --- /dev/null +++ b/test_regress/t/t_class_extends_nf_bad.out @@ -0,0 +1,5 @@ +%Error: t/t_class_extends_nf_bad.v:10:19: Class to extend not found: 'IsNotFound' + : ... Suggested alternative: 'IsFound' + 10 | class Cls extends IsNotFound; + | ^~~~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_class_extends_nf_bad.pl b/test_regress/t/t_class_extends_nf_bad.pl new file mode 100755 index 000000000..7be596e0f --- /dev/null +++ b/test_regress/t/t_class_extends_nf_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 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 + +scenarios(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_class_extends_nf_bad.v b/test_regress/t/t_class_extends_nf_bad.v new file mode 100644 index 000000000..2285ba8e6 --- /dev/null +++ b/test_regress/t/t_class_extends_nf_bad.v @@ -0,0 +1,14 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class IsFound; +endclass + +class Cls extends IsNotFound; +endclass + +module t (/*AUTOARG*/); +endmodule diff --git a/test_regress/t/t_class_extends_this.out b/test_regress/t/t_class_extends_this.out index 6f0456393..364b929f1 100644 --- a/test_regress/t/t_class_extends_this.out +++ b/test_regress/t/t_class_extends_this.out @@ -4,9 +4,6 @@ %Error: t/t_class_extends_this.v:13:11: Can't find definition of scope/variable: 'this' 13 | if (this.value != 1) $stop; | ^~~~ -%Error-UNSUPPORTED: t/t_class_extends_this.v:17:19: Unsupported: class extends - 17 | class Cls extends Base; - | ^~~~ %Error-UNSUPPORTED: t/t_class_extends_this.v:21:11: Unsupported: this 21 | if (this.value != 2) $stop; | ^~~~ diff --git a/test_regress/t/t_class_extern.out b/test_regress/t/t_class_extern.out deleted file mode 100644 index 6adffc70c..000000000 --- a/test_regress/t/t_class_extern.out +++ /dev/null @@ -1,4 +0,0 @@ -%Error-UNSUPPORTED: t/t_class_extern.v:11:15: Unsupported: Out of class block function declaration - 11 | function void Cls::extfunc(); - | ^~~ -%Error: Exiting due to diff --git a/test_regress/t/t_class_extern.pl b/test_regress/t/t_class_extern.pl index b8b56e6f0..aabcde63e 100755 --- a/test_regress/t/t_class_extern.pl +++ b/test_regress/t/t_class_extern.pl @@ -11,13 +11,11 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di scenarios(simulator => 1); compile( - fails => $Self->{vlt_all}, - expect_filename => $Self->{golden_filename}, ); -#execute( -# check_finished => 1, -# ); +execute( + check_finished => 1, + ); ok(1); 1; diff --git a/test_regress/t/t_class_extern.v b/test_regress/t/t_class_extern.v index 231031ff1..eb15c625b 100644 --- a/test_regress/t/t_class_extern.v +++ b/test_regress/t/t_class_extern.v @@ -5,17 +5,23 @@ // SPDX-License-Identifier: CC0-1.0 class Cls; - extern function void extfunc(); + extern task extcls(); + extern function int extone(); endclass -function void Cls::extfunc(); +function int Cls::extone(); + return 1; +endfunction + +task Cls::extcls(); $write("*-* All Finished *-*\n"); $finish; -endfunction +endtask module t (/*AUTOARG*/); initial begin - Cls c; - c.extfunc(); + Cls c = new; + if (c.extone() != 1) $stop; + c.extcls(); end endmodule diff --git a/test_regress/t/t_class_extern_bad.out b/test_regress/t/t_class_extern_bad.out new file mode 100644 index 000000000..e324308c0 --- /dev/null +++ b/test_regress/t/t_class_extern_bad.out @@ -0,0 +1,16 @@ +%Error: t/t_class_extern_bad.v:9:16: Duplicate declaration of task: 'nodef' + 9 | extern task nodef(); + | ^~~~~ + t/t_class_extern_bad.v:8:16: ... Location of original declaration + 8 | extern task nodef(); + | ^~~~~ +%Error: t/t_class_extern_bad.v:8:16: definition not found for extern 'nodef' + 8 | extern task nodef(); + | ^~~~~ +%Error: t/t_class_extern_bad.v:9:16: definition not found for extern 'nodef' + 9 | extern task nodef(); + | ^~~~~ +%Error: t/t_class_extern_bad.v:12:6: extern not found that declares 'noproto' + 12 | task Base1::noproto(); + | ^~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_class_extern_bad.pl b/test_regress/t/t_class_extern_bad.pl new file mode 100755 index 000000000..7be596e0f --- /dev/null +++ b/test_regress/t/t_class_extern_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 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 + +scenarios(linter => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_class_extern_bad.v b/test_regress/t/t_class_extern_bad.v new file mode 100644 index 000000000..86b921820 --- /dev/null +++ b/test_regress/t/t_class_extern_bad.v @@ -0,0 +1,16 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Base1; + extern task nodef(); + extern task nodef(); // duplicate +endclass + +task Base1::noproto(); // no such prototype +endtask + +module t (/*AUTOARG*/); +endmodule diff --git a/test_regress/t/t_class_member_bad.out b/test_regress/t/t_class_member_bad.out index 1251ff9af..ef2eaedc8 100644 --- a/test_regress/t/t_class_member_bad.out +++ b/test_regress/t/t_class_member_bad.out @@ -1,4 +1,11 @@ -%Error-UNSUPPORTED: t/t_class_member_bad.v:11:20: Unsupported: class extends - 11 | class Cls2 extends Base1; - | ^~~~~ +%Error: t/t_class_member_bad.v:18:9: Member 'memb3' not found in class 'Cls2' + : ... In instance t + : ... Suggested alternative: 'memb2' + 18 | c.memb3 = 3; + | ^~~~~ +%Warning-WIDTH: t/t_class_member_bad.v:18:15: Operator ASSIGN expects 1 bits on the Assign RHS, but Assign RHS's CONST '?32?sh3' generates 32 or 2 bits. + : ... In instance t + 18 | c.memb3 = 3; + | ^ + ... Use "/* verilator lint_off WIDTH */" and lint_on around source to disable this message. %Error: Exiting due to diff --git a/test_regress/t/t_class_method_bad.out b/test_regress/t/t_class_method_bad.out index bb2dbc0f6..5a2cbc931 100644 --- a/test_regress/t/t_class_method_bad.out +++ b/test_regress/t/t_class_method_bad.out @@ -1,4 +1,6 @@ -%Error-UNSUPPORTED: t/t_class_method_bad.v:11:20: Unsupported: class extends - 11 | class Cls2 extends Base1; - | ^~~~~ +%Error: t/t_class_method_bad.v:18:9: Class method 'meth3' not found in class 'Cls2' + : ... In instance t + : ... Suggested alternative: 'meth2' + 18 | c.meth3(); + | ^~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_class_new.v b/test_regress/t/t_class_new.v index e370e2e49..88b6fc787 100644 --- a/test_regress/t/t_class_new.v +++ b/test_regress/t/t_class_new.v @@ -5,7 +5,7 @@ // SPDX-License-Identifier: CC0-1.0 class ClsNoArg; - int imembera; + const int imembera; // Ok for new() to assign to a const function new(); imembera = 5; endfunction diff --git a/test_regress/t/t_class_virtual.out b/test_regress/t/t_class_virtual.out deleted file mode 100644 index 7dbccdbfd..000000000 --- a/test_regress/t/t_class_virtual.out +++ /dev/null @@ -1,4 +0,0 @@ -%Error-UNSUPPORTED: t/t_class_virtual.v:7:9: Unsupported: virtual class - 7 | virtual class VC; - | ^~~~~ -%Error: Exiting due to diff --git a/test_regress/t/t_class_virtual.pl b/test_regress/t/t_class_virtual.pl index 009248fc5..aabcde63e 100755 --- a/test_regress/t/t_class_virtual.pl +++ b/test_regress/t/t_class_virtual.pl @@ -8,11 +8,13 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di # Version 2.0. # SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 -scenarios(vlt => 1); +scenarios(simulator => 1); -lint( - fails => 1, - expect_filename => $Self->{golden_filename}, +compile( + ); + +execute( + check_finished => 1, ); ok(1); diff --git a/test_regress/t/t_class_virtual.v b/test_regress/t/t_class_virtual.v index b386c6b8b..9daf4cd65 100644 --- a/test_regress/t/t_class_virtual.v +++ b/test_regress/t/t_class_virtual.v @@ -4,5 +4,38 @@ // any use, without warranty, 2019 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 -virtual class VC; +virtual class VBase; + virtual function int hello; + return 1; + endfunction endclass + +class VA extends VBase; + virtual function int hello; + return 2; + endfunction +endclass + +class VB extends VBase; + virtual function int hello; + return 3; + endfunction +endclass + +module t; + initial begin + VA va = new; + VB vb = new; + VBase b; + + if (va.hello() != 2) $stop; + if (vb.hello() != 3) $stop; + + b = va; + if (b.hello() != 2) $stop; + b = vb; + if (b.hello() != 3) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_class_virtual_bad.out b/test_regress/t/t_class_virtual_bad.out new file mode 100644 index 000000000..4b1e2878b --- /dev/null +++ b/test_regress/t/t_class_virtual_bad.out @@ -0,0 +1,5 @@ +%Error: t/t_class_virtual_bad.v:12:17: Illegal to call 'new' using an abstract virtual class (IEEE 1800-2017 8.21) + : ... In instance t + 12 | VBase b = new; + | ^~~ +%Error: Exiting due to diff --git a/test_regress/t/t_class_virtual_bad.pl b/test_regress/t/t_class_virtual_bad.pl new file mode 100755 index 000000000..009248fc5 --- /dev/null +++ b/test_regress/t/t_class_virtual_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 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 + +scenarios(vlt => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_class_virtual_bad.v b/test_regress/t/t_class_virtual_bad.v new file mode 100644 index 000000000..5e87644a4 --- /dev/null +++ b/test_regress/t/t_class_virtual_bad.v @@ -0,0 +1,14 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2019 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +virtual class VBase; +endclass + +module t; + initial begin + VBase b = new; // Error + end +endmodule diff --git a/test_regress/t/t_class_virtual_pure.pl b/test_regress/t/t_class_virtual_pure.pl index 009248fc5..aabcde63e 100755 --- a/test_regress/t/t_class_virtual_pure.pl +++ b/test_regress/t/t_class_virtual_pure.pl @@ -8,11 +8,13 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di # Version 2.0. # SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 -scenarios(vlt => 1); +scenarios(simulator => 1); -lint( - fails => 1, - expect_filename => $Self->{golden_filename}, +compile( + ); + +execute( + check_finished => 1, ); ok(1); diff --git a/test_regress/t/t_class_virtual_pure.v b/test_regress/t/t_class_virtual_pure.v index a87698cb4..cfbe9c03d 100644 --- a/test_regress/t/t_class_virtual_pure.v +++ b/test_regress/t/t_class_virtual_pure.v @@ -4,6 +4,21 @@ // any use, without warranty, 2019 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 -virtual class VC; - pure virtual task hello(); +virtual class VBase; + pure virtual function int hello(); endclass + +class VA extends VBase; + virtual function int hello; + return 2; + endfunction +endclass + +module t; + initial begin + VA va = new; + if (va.hello() != 2) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_clk_2in.cpp b/test_regress/t/t_clk_2in.cpp index a102ec98a..ba601f846 100644 --- a/test_regress/t/t_clk_2in.cpp +++ b/test_regress/t/t_clk_2in.cpp @@ -13,7 +13,7 @@ unsigned int main_time = 0; double sc_time_stamp() { return main_time; } -VM_PREFIX* topp = NULL; +VM_PREFIX* topp = nullptr; void clockit(int clk1, int clk0) { topp->clks = clk1 << 1 | clk0; diff --git a/test_regress/t/t_clk_first_bad.out b/test_regress/t/t_clk_first_bad.out index a640ff6c4..d12bc84d9 100644 --- a/test_regress/t/t_clk_first_bad.out +++ b/test_regress/t/t_clk_first_bad.out @@ -1,4 +1,4 @@ -%Warning-DEPRECATED: t/t_clk_first_deprecated.v:12:14: sc_clock is deprecated and will be removed +%Warning-DEPRECATED: t/t_clk_first_deprecated.v:12:14: sc_clock is ignored 12 | input clk /*verilator sc_clock*/ ; | ^~~~~~~~~~~~~~~~~~~~~~ ... Use "/* verilator lint_off DEPRECATED */" and lint_on around source to disable this message. diff --git a/test_regress/t/t_dist_tabs.pl b/test_regress/t/t_dist_tabs.pl index 1d86b976b..cd830d4fc 100755 --- a/test_regress/t/t_dist_tabs.pl +++ b/test_regress/t/t_dist_tabs.pl @@ -13,7 +13,8 @@ scenarios(dist => 1); my $root = ".."; my $Tabs_Exempt_Re = qr!(\.out$)|(/gtkwave)|(Makefile)|(\.mk$)|(nodist/fastcov.py)!; -my $Wide_Exempt_Re = qr!(\.l$)|(\.y$)!; +#my $Wide_Exempt_Re = qr!(\.l$)|(\.y$)!; +my $Wide_Exempt_Re = qr!.*!; # clang-tidy generally cleans up if (!-r "$root/.git") { skip("Not in a git repository"); diff --git a/test_regress/t/t_dpi_arg_inout_type.cpp b/test_regress/t/t_dpi_arg_inout_type.cpp index 04b8165de..0c0609784 100644 --- a/test_regress/t/t_dpi_arg_inout_type.cpp +++ b/test_regress/t/t_dpi_arg_inout_type.cpp @@ -159,7 +159,7 @@ void i_shortreal(float* x) { void i_chandle(void** x) { static int n = 0; printf("i_chandle %d\n", n); - if (*x != NULL) stop(); + if (*x) stop(); *x = (n % 2) ? reinterpret_cast(&i_chandle) : 0; n++; } @@ -287,7 +287,7 @@ void i_shortreal_t(float* x) { void i_chandle_t(void** x) { static int n = 0; printf("i_chandle_t %d\n", n); - if (*x != NULL) stop(); + if (*x) stop(); *x = (n % 2) ? 0 : reinterpret_cast(&i_chandle_t); n++; } @@ -961,10 +961,10 @@ void check_exports() { e_chandle(&x_chandle); e_string(&x_string); if ((n % 2) == 0) { - if (x_chandle != NULL) stop(); + if (x_chandle) stop(); if (strcmp(x_string, "Hello") != 0) stop(); } else { - if (x_chandle != NULL) stop(); + if (x_chandle) stop(); if (strcmp(x_string, "World") != 0) stop(); } diff --git a/test_regress/t/t_dpi_arg_input_type.cpp b/test_regress/t/t_dpi_arg_input_type.cpp index e794bd745..fe792ea45 100644 --- a/test_regress/t/t_dpi_arg_input_type.cpp +++ b/test_regress/t/t_dpi_arg_input_type.cpp @@ -145,7 +145,7 @@ void i_shortreal(float i) { void i_chandle(void* i) { static int n = 0; printf("i_chandle %d\n", n); - if (i != NULL) stop(); + if (i) stop(); n++; } @@ -256,7 +256,7 @@ void i_shortreal_t(float i) { void i_chandle_t(void* i) { static int n = 0; printf("i_chandle_t %d\n", n); - if (i != NULL) stop(); + if (i) stop(); n++; } diff --git a/test_regress/t/t_dpi_export_context_bad.cpp b/test_regress/t/t_dpi_export_context_bad.cpp index a4bad53d4..7f0a9f4b3 100644 --- a/test_regress/t/t_dpi_export_context_bad.cpp +++ b/test_regress/t/t_dpi_export_context_bad.cpp @@ -33,7 +33,7 @@ unsigned int main_time = 0; double sc_time_stamp() { return main_time; } -VM_PREFIX* topp = NULL; +VM_PREFIX* topp = nullptr; int main(int argc, char* argv[]) { topp = new VM_PREFIX; diff --git a/test_regress/t/t_dpi_result_type.cpp b/test_regress/t/t_dpi_result_type.cpp index 2f5bbe7f5..1ecbf0d94 100644 --- a/test_regress/t/t_dpi_result_type.cpp +++ b/test_regress/t/t_dpi_result_type.cpp @@ -299,7 +299,7 @@ void check_exports() { #ifndef NO_SHORTREAL if (e_shortreal() != 1.0f * n + 0.25f) stop(); #endif - if (e_chandle() != NULL) stop(); + if (e_chandle()) stop(); if ((n % 2) == 0) { if (strcmp(e_string(), "Hello") != 0) stop(); } else { @@ -323,7 +323,7 @@ void check_exports() { #ifndef NO_SHORTREAL if (e_shortreal_t() != 1.0f * (2 * n) + 0.25f) stop(); #endif - if (e_chandle_t() != NULL) stop(); + if (e_chandle_t()) stop(); if ((n % 2) == 0) { if (strcmp(e_string_t(), "Hello") != 0) stop(); } else { diff --git a/test_regress/t/t_dpi_vams.cpp b/test_regress/t/t_dpi_vams.cpp index a7473f174..2a0b44465 100644 --- a/test_regress/t/t_dpi_vams.cpp +++ b/test_regress/t/t_dpi_vams.cpp @@ -36,7 +36,7 @@ unsigned int main_time = 0; double sc_time_stamp() { return main_time; } -VM_PREFIX* topp = NULL; +VM_PREFIX* topp = nullptr; int main(int argc, char* argv[]) { topp = new VM_PREFIX; diff --git a/test_regress/t/t_embed1_c.cpp b/test_regress/t/t_embed1_c.cpp index ff9cf19ca..8feeea826 100644 --- a/test_regress/t/t_embed1_c.cpp +++ b/test_regress/t/t_embed1_c.cpp @@ -46,7 +46,7 @@ Vt_embed1_child* __get_modelp() { svScope scope = svGetScope(); if (!scope) { vl_fatal(__FILE__, __LINE__, __FILE__, "svGetScope failed"); - return NULL; + return nullptr; } void* __modelp = svGetUserData(scope, &T_Embed_Child_Unique); diff --git a/test_regress/t/t_event_control_unsup.out b/test_regress/t/t_event_control_unsup.out index 7e0f28123..03d17ac22 100644 --- a/test_regress/t/t_event_control_unsup.out +++ b/test_regress/t/t_event_control_unsup.out @@ -1,8 +1,10 @@ %Error-UNSUPPORTED: t/t_event_control_unsup.v:14:7: Unsupported: timing control statement in this location + : ... In instance t : ... Suggest have one timing control statement per procedure, at the top of the procedure 14 | @(clk); | ^ %Error-UNSUPPORTED: t/t_event_control_unsup.v:16:7: Unsupported: timing control statement in this location + : ... In instance t : ... Suggest have one timing control statement per procedure, at the top of the procedure 16 | @(clk); | ^ diff --git a/test_regress/t/t_fell.v b/test_regress/t/t_fell.v deleted file mode 100644 index eff06f114..000000000 --- a/test_regress/t/t_fell.v +++ /dev/null @@ -1,81 +0,0 @@ -// DESCRIPTION: Verilator: Verilog Test module -// -// This file ONLY is placed into the Public Domain, for any use, -// without warranty, 2020 by Peter Monsson. - -module t (/*AUTOARG*/ - // Inputs - clk - ); - - input clk; - integer cyc; initial cyc=2; - wire [31:0] in = cyc; - - Test test (/*AUTOINST*/ - // Inputs - .clk (clk), - .in (in[31:0])); - - Test2 test2 (/*AUTOINST*/ - // Inputs - .clk (clk), - .in (in[31:0])); - - always @ (posedge clk) begin - if (cyc!=0) begin - cyc <= cyc + 1; - if (cyc==10) begin - $write("*-* All Finished *-*\n"); - $finish; - end - end - end - -endmodule - -module Test (/*AUTOARG*/ - // Inputs - clk, in - ); - - input clk; - input [31:0] in; - - reg [31:0] dly0 = 1; - - // If called in an assertion, sequence, or property, the appropriate clocking event. - // Otherwise, if called in a disable condition or a clock expression in an assertion, sequence, or prop, explicit. - // Otherwise, if called in an action block of an assertion, the leading clock of the assertion is used. - // Otherwise, if called in a procedure, the inferred clock - // Otherwise, default clocking - - always @(posedge clk) begin - dly0 <= in; - // In clock expression - $write("in=%0d, dly0=%0d, fell=%0d, past=%0d\n", in, dly0, $fell(dly0), $past(dly0)); - if ($fell(dly0[4])) $stop; - end - - assert property (@(posedge clk) $fell(dly0) || dly0%2==1); -endmodule - - -module Test2 (/*AUTOARG*/ - // Inputs - clk, in - ); - - input clk; - input [31:0] in; - - reg [31:0] dly0 = 1; - - always @(posedge clk) begin - dly0 <= in; - if ($fell(dly0[31:4])) $stop; - end - - default clocking @(posedge clk); endclocking - assert property ($fell(dly0[0]) || dly0%2==1); -endmodule diff --git a/test_regress/t/t_flag_csplit_eval.pl b/test_regress/t/t_flag_csplit_eval.pl new file mode 100755 index 000000000..c2012b9f4 --- /dev/null +++ b/test_regress/t/t_flag_csplit_eval.pl @@ -0,0 +1,40 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +sub check_evals { + my $got = 0; + foreach my $file (glob("$Self->{obj_dir}/*.cpp")) { + my $fh = IO::File->new("<$file"); + local $/; undef $/; + my $wholefile = <$fh>; + + if ($wholefile =~ /::_eval[0-9]+/) { + ++$got; + } + } + $got >= 3 or error("Too few _eval functions found: $got"); +} + + +scenarios(vlt_all => 1); + +compile( + v_flags2 => ["--output-split 1 --output-split-cfuncs 1 --exe ../$Self->{main_filename}"], +# verilator_make_gmake => 0, + ); + +# Very slow to compile, so generally skip it +execute( + check_finished => 1, + ); + +check_evals(); +ok(1); +1; diff --git a/test_regress/t/t_flag_csplit_eval.v b/test_regress/t/t_flag_csplit_eval.v new file mode 100644 index 000000000..685fc7612 --- /dev/null +++ b/test_regress/t/t_flag_csplit_eval.v @@ -0,0 +1,31 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2005 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/ + // Outputs + cnt0, cnt1, + // Inputs + clk, clk1 + ); + input clk; + input clk1; + + output int cnt0; + output int cnt1; + + always @ (posedge clk) cnt0 <= cnt0 + 1; + always @ (posedge clk1) cnt1 <= cnt1 + 1; + + final if (cnt0 == 0) $stop; + final if (cnt1 != 0) $stop; + + always_comb begin + if (cnt0==99) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule diff --git a/test_regress/t/t_flag_fi.cpp b/test_regress/t/t_flag_fi.cpp index afad2c751..4c0a89ed1 100644 --- a/test_regress/t/t_flag_fi.cpp +++ b/test_regress/t/t_flag_fi.cpp @@ -15,7 +15,7 @@ unsigned int main_time = 0; double sc_time_stamp() { return main_time; } -VM_PREFIX* topp = NULL; +VM_PREFIX* topp = nullptr; bool gotit = false; void myfunction() { gotit = true; } diff --git a/test_regress/t/t_flag_hier0_bad.out b/test_regress/t/t_flag_hier0_bad.out new file mode 100644 index 000000000..50beec083 --- /dev/null +++ b/test_regress/t/t_flag_hier0_bad.out @@ -0,0 +1,9 @@ +%Error: --hierarchical-block requires the number of entries to be even +%Error: Module name 'param0' is duplicated in --hierarchical-block +%Error: --hierarchical-block requires at least two comma-separated values +%Error: --hierarchical-block must not end with \ +%Error: --hierarchical-block does not allow 'a' after \ +%Error: --hierarchical-block expects ',', but 'a' is passed +%Error: --hierarchical-block must not end with ',' +%Error: --hierarchical-block does not allow '"' in the middle of literal +%Error: Exiting due to diff --git a/test_regress/t/t_flag_hier0_bad.pl b/test_regress/t/t_flag_hier0_bad.pl new file mode 100755 index 000000000..fb589c623 --- /dev/null +++ b/test_regress/t/t_flag_hier0_bad.pl @@ -0,0 +1,38 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); +top_filename("t/t_hier_block.v"); + +lint( + fails => 1, + verilator_flags2 => ['--hierarchical-block', + 'modName,mangledName,param0,"paramValue0",param0,"paramValue1",param1,2,param3', + '--hierarchical-block', + 'modName', + '--hierarchical-block', + 'mod0,mod1,\'"str\\\'', # end with backslash + '--hierarchical-block', + 'mod2,mod3,\'"str\\a\'', # unexpected 'a' after backslash + '--hierarchical-block', + 'mod4,mod5,\'"str"abc\',', # not end with " + '--hierarchical-block', + 'mod6,mod7,\'"str"\',', # end with , + '--hierarchical-block', + 'mod8,mod9,\'s"tr"\',', # unexpected " + '--hierarchical-block', + 'modA,modB,param,', # end with , + ], + expect_filename => $Self->{golden_filename}, + ); + +ok(1); + +1; diff --git a/test_regress/t/t_flag_make_cmake.pl b/test_regress/t/t_flag_make_cmake.pl index c4b3d0ebe..ba6828b85 100755 --- a/test_regress/t/t_flag_make_cmake.pl +++ b/test_regress/t/t_flag_make_cmake.pl @@ -16,8 +16,7 @@ compile( verilator_make_cmake => 1, ); -system("cmake --version"); -if ($? != 0) { +if (!$Self->have_cmake) { skip("cmake is not installed"); } else { my $cmakecache = $Self->{obj_dir}."/CMakeCache.txt"; diff --git a/test_regress/t/t_foreach_bad.out b/test_regress/t/t_foreach_bad.out index 0a9fed94a..cbb916320 100644 --- a/test_regress/t/t_foreach_bad.out +++ b/test_regress/t/t_foreach_bad.out @@ -1,7 +1,4 @@ %Error: t/t_foreach_bad.v:14:7: Syntax error; foreach missing bracketed index variable (IEEE 1800-2017 12.7.3) 14 | foreach (array); | ^~~~~~~ -%Error-UNSUPPORTED: t/t_foreach_bad.v:16:21: Unsupported: foreach on non-simple variable reference - 16 | foreach (array.array[a]); - | ^ %Error: Exiting due to diff --git a/test_regress/t/t_fork.v b/test_regress/t/t_fork.v index 06f9ed036..33eb0b485 100644 --- a/test_regress/t/t_fork.v +++ b/test_regress/t/t_fork.v @@ -8,6 +8,9 @@ module t (/*AUTOARG*/); initial begin fork : fblk + begin + $write("Forked"); + end begin $write("*-* All Finished *-*\n"); $finish; diff --git a/test_regress/t/t_fork_label.pl b/test_regress/t/t_fork_label.pl new file mode 100755 index 000000000..1c4ba9485 --- /dev/null +++ b/test_regress/t/t_fork_label.pl @@ -0,0 +1,18 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile(); + +execute(); + +ok(1); +1; diff --git a/test_regress/t/t_fork_label.v b/test_regress/t/t_fork_label.v new file mode 100644 index 000000000..a5d6112da --- /dev/null +++ b/test_regress/t/t_fork_label.v @@ -0,0 +1,34 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2003 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + + initial begin + // Label checks + begin : b1 + end : b1 + // + b2 : begin + end : b2 + // With no statements this is a NOP + fork : f1 + join : f1 + // + f2: fork + join_any : f2 + // + fork + join_none + // With one statement this is supported and optimized to a begin/end + fork : fblk + begin + $write("*-* All Finished *-*\n"); + $finish; + end + join : fblk + end + +endmodule diff --git a/test_regress/t/t_hier_block.cpp b/test_regress/t/t_hier_block.cpp new file mode 100644 index 000000000..298d13513 --- /dev/null +++ b/test_regress/t/t_hier_block.cpp @@ -0,0 +1,17 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// +// Copyright 2020 by Yutetsu TAKATSUKASA. 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 +// +//************************************************************************* + + +extern "C" int dpi_export_func(int); + +extern "C" int dpi_import_func(int v) { + return dpi_export_func(v) - 1; +} diff --git a/test_regress/t/t_hier_block.pl b/test_regress/t/t_hier_block.pl new file mode 100755 index 000000000..e334fd536 --- /dev/null +++ b/test_regress/t/t_hier_block.pl @@ -0,0 +1,38 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +# stats will be deleted but generation will be skipped if libs of hierarchical blocks exist. +clean_objs(); + +scenarios(vlt_all => 1); + +# Travis environment offers 2 VCPUs, 2 thread setting causes the following warning. +# %Warning-UNOPTTHREADS: Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads. +# So use 6 threads here though it's not optimal in performace wise, but ok. + +compile( + v_flags2 => ['t/t_hier_block.cpp'], + verilator_flags2 => ['--stats', ($Self->{vltmt} ? ' --threads 6' : ''), + '--hierarchical', + '--CFLAGS', '"-pipe -DCPP_MACRO=cplusplus"' + ], + ); + +execute( + check_finished => 1, + ); + +file_grep($Self->{obj_dir} . "/Vsub0/sub0.sv", /^module\s+(\S+)\s+/, "sub0"); +file_grep($Self->{obj_dir} . "/Vsub1/sub1.sv", /^module\s+(\S+)\s+/, "sub1"); +file_grep($Self->{obj_dir} . "/Vsub2/sub2.sv", /^module\s+(\S+)\s+/, "sub2"); +file_grep($Self->{stats}, qr/HierBlock,\s+Hierarchical blocks\s+(\d+)/i, 10); +file_grep($Self->{run_log_filename}, qr/MACRO:(\S+) is defined/i, "cplusplus"); + +ok(1); +1; diff --git a/test_regress/t/t_hier_block.v b/test_regress/t/t_hier_block.v new file mode 100644 index 000000000..d4701b2ac --- /dev/null +++ b/test_regress/t/t_hier_block.v @@ -0,0 +1,230 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2020 by Yutetsu TAKATSUKASA + +`ifdef USE_VLT +`define HIER_BLOCK +`else +`define HIER_BLOCK /*verilator hier_block*/ +`endif + +interface byte_ifs(input clk); + logic [7:0] data; + modport sender(input clk, output data); + modport receiver(input clk, input data); +endinterface; + +`ifdef AS_PROT_LIB +module secret ( + clk + ); +`else +module t (/*AUTOARG*/ + // Inputs + clk + ); +`endif + input clk; + +`ifdef PROTLIB_TOP + secret i_secred(.clk(clk)); +`else + wire [7:0] out0; + wire [7:0] out1; + wire [7:0] out2; + /* verilator lint_off UNOPTFLAT */ + wire [7:0] out3; + wire [7:0] out3_2; + /* verilator lint_on UNOPTFLAT */ + wire [7:0] out5; + wire [7:0] out6; + int count = 0; + + non_hier_sub0 i_sub0(.clk(clk), .in(out3), .out(out0)); + sub1 i_sub1(.clk(clk), .in(out0), .out(out1)); + sub2 i_sub2(.clk(clk), .in(out1), .out(out2)); + sub3 #(.P0(1)) i_sub3(.clk(clk), .in(out2), .out(out3)); + // Must not use the same wrapper + sub3 #(.STR("abc"), .P0(1)) i_sub3_2(.clk(clk), .in(out2), .out(out3_2)); + delay #(.N(2), 8) i_delay0(clk, out3, out5); + delay #(.N(3), 8) i_delay1(clk, out5, out6); + + always_ff @(posedge clk) begin + if (out3 != out3_2) $stop; + $display("%d out0:%d %d %d %d %d", count, out0, out1, out2, out3, out5, out6); + if (count == 16) begin + if (out6 == 19) begin + $write("*-* All Finished *-*\n"); + $finish; + end else begin + $write("Missmatch\n"); + $stop; + end + end + count <= count + 1; + end + +`ifdef CPP_MACRO + initial begin + $display("Macro for C++ compiler is defined for Verilator"); + $stop; + end +`endif + +`systemc_implementation +#include +#define STRINGIFY_IMPL(str) #str +#define STRINGIFY(str) STRINGIFY_IMPL(str) +namespace { +struct statically_initialized { + statically_initialized() { + std::cout << "MACRO:" << STRINGIFY(CPP_MACRO) << " is defined" << std::endl; + } +} g_statically_initialized; +} +`verilog + +`endif // PROTLIB_TOP + +endmodule + +module non_hier_sub0( + input wire clk, + input wire[7:0] in, + output wire [7:0] out); + + sub0 i_sub0(.*); + +endmodule + +module sub0( + input wire clk, + input wire [7:0] in, + output wire [7:0] out); `HIER_BLOCK + + logic [7:0] ff; + + always_ff @(posedge clk) ff <= in; + assign out = ff; +endmodule + +module sub1( + input wire clk, + input wire [7:0] in, + output wire [7:0] out); `HIER_BLOCK + + logic [7:0] ff; + + always_ff @(posedge clk) ff <= in + 1; + assign out = ff; +endmodule + +module sub2( + input wire clk, + input wire [7:0] in, + output wire [7:0] out); `HIER_BLOCK + + logic [7:0] ff; + + // dpi_import_func returns (dpi_eport_func(v) -1) + import "DPI-C" context function int dpi_import_func(int v); + export "DPI-C" function dpi_export_func; + + function int dpi_export_func(int v); + return v + 1; + endfunction + + always_ff @(posedge clk) ff <= 8'(dpi_import_func({24'b0, in})) + 8'd2; + + byte_ifs in_ifs(.clk(clk)); + byte_ifs out_ifs(.clk(clk)); + assign in_ifs.data = ff; + assign out = out_ifs.data; + non_hier_sub3 i_sub3(.in(in_ifs), .out(out_ifs)); + + always @(posedge clk) + // dotted access within a hierarchical block should be OK + if (i_sub3.in_wire != ff) begin + $display("Error mismatch in %m"); + $stop; + end +endmodule + +module non_hier_sub3( + byte_ifs.receiver in, + byte_ifs.sender out); + + wire [7:0] in_wire, out_1, out_2; + assign in_wire = in.data; + localparam string sparam = "single quote escape comma:'\\,"; + // Parameter appears in the different order from module declaration + sub3 #(.STR(sparam), .UNUSED(-16'sd3), .P0(8'd3)) i_sub3(.clk(in.clk), .in(in.data), .out(out_1)); + // Instantiate again, should use the same wrapper + sub3 #(.STR(sparam), .UNUSED(-16'sd3), .P0(8'd3)) i_sub3_2(.clk(in.clk), .in(in.data), .out(out_2)); + always @(posedge in.clk) + if (out_1 != out_2) $stop; + + assign out.data = out_1; +endmodule + +module sub3 #( + parameter logic [7:0] P0 = 2 + 1, + type TYPE = logic, + parameter int UNPACKED_ARRAY[2] = '{0, 1}, + parameter logic signed [15:0] UNUSED = -3, + parameter string STR = "str") ( + input wire clk, + input wire [7:0] in, + output wire [7:0] out); `HIER_BLOCK + + initial $display("P0:%d UNUSED:%d %s", P0, UNUSED, STR); + + TYPE [7:0] ff; + always_ff @(posedge clk) ff <= in + P0; + always_ff @(posedge clk) if (out4 != out4_2) $stop; + + wire [7:0] out4; + wire [7:0] out4_2; + assign out = out4; + /* verilator lint_off REALCVT */ + sub4 #(.P0(1.6), .P1(3.1), .P3(4.1)) i_sub4_0(.clk(clk), .in(ff), .out(out4)); // incr 2 + sub4 #(.P0(2.4), .P1(3.1), .P3(5)) i_sub4_1(.clk(clk), .in(ff), .out(out4_2)); + /* verilator lint_on REALCVT */ +endmodule + +module sub4 #( + parameter int P0 = 1.1, + parameter P1 = 2, + parameter real P3 = 3) ( + input wire clk, + input wire [7:0] in, + output wire[7:0] out); `HIER_BLOCK + + initial begin + if (P1 == 2) begin + $display("P1(%f) is not properly set", P1); + $stop; + end + end + + reg [7:0] ff; + always_ff @(posedge clk) ff <= in + 8'(P0); + assign out = ff; +endmodule + +module delay #( + parameter N = 1, + parameter WIDTH = 8) ( + input wire clk, + input wire[WIDTH-1:0] in, + output wire [WIDTH-1:0]out); `HIER_BLOCK + + reg [WIDTH-1:0] tmp; + always_ff @(posedge clk) tmp <= in; + if (N > 1) begin + delay #(.N(N - 1), WIDTH) i_delay(clk, tmp, out); + end else begin + assign out = tmp; + end +endmodule diff --git a/test_regress/t/t_hier_block0_bad.out b/test_regress/t/t_hier_block0_bad.out new file mode 100644 index 000000000..6f145312f --- /dev/null +++ b/test_regress/t/t_hier_block0_bad.out @@ -0,0 +1,12 @@ +%Error: t/t_hier_block0_bad.v:20:11: 'sub0' has hier_block metacomment, hierarchical verilation supports only integer/floating point/string parameters + : ... In instance t + 20 | sub0 #(UNPACKED) i_sub0(.clk(clk), .in(8'(count)), .out(out0)); + | ^~~~~~~~ +%Error: t/t_hier_block0_bad.v:22:12: 'sub1' has hier_block metacomment, but 'parameter type' is not supported + : ... In instance t + 22 | sub1 #(.T(logic[7:0])) i_sub1(.in(out0), .out(out1)); + | ^ +%Error: t/t_hier_block0_bad.v:26:42: Cannot access inside hierarchical block + 26 | $display("%d %d %d", count, i_sub0.ff, out1); + | ^~ +%Error: Exiting due to diff --git a/test_regress/t/t_stable.pl b/test_regress/t/t_hier_block0_bad.pl old mode 100644 new mode 100755 similarity index 74% rename from test_regress/t/t_stable.pl rename to test_regress/t/t_hier_block0_bad.pl index c1a6773e9..640769ddd --- a/test_regress/t/t_stable.pl +++ b/test_regress/t/t_hier_block0_bad.pl @@ -7,15 +7,13 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. -scenarios(simulator => 1); +scenarios(vlt => 1); -compile( - verilator_flags2 => ['--assert'], - ); - -execute( - check_finished => 1, - ); +lint( + fails => 1, + verilator_flags2 => ['--hierarchical'], + expect_filename => $Self->{golden_filename}, +); ok(1); 1; diff --git a/test_regress/t/t_hier_block0_bad.v b/test_regress/t/t_hier_block0_bad.v new file mode 100644 index 000000000..bcb4ee144 --- /dev/null +++ b/test_regress/t/t_hier_block0_bad.v @@ -0,0 +1,59 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2020 by Yutetsu TAKATSUKASA + +`define HIER_BLOCK /*verilator hier_block*/ + +module t (/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + wire [7:0] out0; + wire [7:0] out1; + int count = 0; + + // unpacked array cannot be passed to hierarchical block + localparam logic UNPACKED[0:1] = '{1'b1, 1'b0}; + sub0 #(UNPACKED) i_sub0(.clk(clk), .in(8'(count)), .out(out0)); + // Passing type parameter is not supported + sub1 #(.T(logic[7:0])) i_sub1(.in(out0), .out(out1)); + + always_ff @(posedge clk) begin + // dotted access under hierarchical block is not allowed + $display("%d %d %d", count, i_sub0.ff, out1); + if (count == 16) begin + if (out1 == 15) begin + $write("*-* All Finished *-*\n"); + $finish; + end else begin + $write("Missmatch\n"); + $stop; + end + end + count <= count + 1; + end + +endmodule + +module sub0 #( + parameter logic UNPACKED[0:1] = '{1'b0, 1'b1} + ) ( + input wire clk, + input wire [7:0] in, + output wire [7:0] out); `HIER_BLOCK + + logic [7:0] ff; + + always_ff @(posedge clk) ff <= in; + assign out = ff; +endmodule + +module sub1 #( + parameter type T = logic + ) ( + input wire T in, output wire T out); `HIER_BLOCK + assign out = in; +endmodule diff --git a/test_regress/t/t_hier_block1_bad.out b/test_regress/t/t_hier_block1_bad.out new file mode 100644 index 000000000..ba3f864b1 --- /dev/null +++ b/test_regress/t/t_hier_block1_bad.out @@ -0,0 +1,15 @@ +%Warning-HIERBLOCK: t/t_hier_block1_bad.v:15:8: Top module illegally marked hierarchical block, ignoring marking + : ... In instance t + ... Suggest remove verilator hier_block on this module + 15 | module t ( + | ^ + ... Use "/* verilator lint_off HIERBLOCK */" and lint_on around source to disable this message. +%Error: t/t_hier_block1_bad.v:44:32: Modport cannot be used at the hierarchical block boundary + : ... In instance t.i_sub1 + 44 | module sub1 (byte_ifs.receiver in, byte_ifs.sender out); /*verilator hier_block*/ + | ^~ +%Error: t/t_hier_block1_bad.v:44:52: Modport cannot be used at the hierarchical block boundary + : ... In instance t.i_sub1 + 44 | module sub1 (byte_ifs.receiver in, byte_ifs.sender out); /*verilator hier_block*/ + | ^~~ +%Error: Exiting due to diff --git a/test_regress/t/t_hier_block1_bad.pl b/test_regress/t/t_hier_block1_bad.pl new file mode 100755 index 000000000..640769ddd --- /dev/null +++ b/test_regress/t/t_hier_block1_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +scenarios(vlt => 1); + +lint( + fails => 1, + verilator_flags2 => ['--hierarchical'], + expect_filename => $Self->{golden_filename}, +); + +ok(1); +1; diff --git a/test_regress/t/t_hier_block1_bad.v b/test_regress/t/t_hier_block1_bad.v new file mode 100644 index 000000000..c42918a47 --- /dev/null +++ b/test_regress/t/t_hier_block1_bad.v @@ -0,0 +1,46 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2020 by Yutetsu TAKATSUKASA + +`define HIER_BLOCK /*verilator hier_block*/ + +interface byte_ifs(input clk); + logic [7:0] data; + modport sender(input clk, output data); + modport receiver(input clk, input data); +endinterface; + + +module t (/*AUTOARG*/ + // Inputs + clk + ); `HIER_BLOCK // Top module can not be a hierarchy block + input wire clk; + + wire [7:0] out0; + int count = 0; + + byte_ifs in_ifs(.clk(clk)); + byte_ifs out_ifs(.clk(clk)); + assign in_ifs.data = out0; + + sub0 i_sub0(.clk(clk), .in(count), .out(out0)); + sub1 i_sub1(.in(in_ifs), .out(out_ifs)); + +endmodule + +module sub0 ( + input wire clk, + input wire [7:0] in, + output wire [7:0] out); `HIER_BLOCK + + logic [7:0] ff; + + always_ff @(posedge clk) ff <= in; + assign out = ff; +endmodule + +module sub1 (byte_ifs.receiver in, byte_ifs.sender out); `HIER_BLOCK + assign out.data = in.data; +endmodule diff --git a/test_regress/t/t_hier_block_cmake.pl b/test_regress/t/t_hier_block_cmake.pl new file mode 100755 index 000000000..24760fe3c --- /dev/null +++ b/test_regress/t/t_hier_block_cmake.pl @@ -0,0 +1,51 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +# If a test fails, broken .cmake may distrub the next run +clean_objs(); + +scenarios(simulator => 1); +top_filename("t/t_hier_block.v"); + +# Travis environment offers 2 VCPUs, 2 thread setting causes the following warning. +# %Warning-UNOPTTHREADS: Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads. +# So use 6 threads here though it's not optimal in performace wise, but ok. +compile( + verilator_make_gmake => 0, + verilator_make_cmake => 1, + v_flags2 => ['t/t_hier_block.cpp'], + verilator_flags2 => ['--stats', + '--hierarchical', + '--CFLAGS', "'-pipe -DCPP_MACRO=cplusplus '", + '--make cmake', + ($Self->{vltmt} ? ' --threads 6' : '')], + ); + +if (!$Self->have_cmake) { + skip("cmake is not installed"); +} else { + my $cmakecache = $Self->{obj_dir}."/CMakeCache.txt"; + if (! -e $cmakecache) { + error("$cmakecache does not exist.") + } + + execute( + check_finished => 1, + ); + +file_grep($Self->{obj_dir} . "/Vsub0/sub0.sv", /^module\s+(\S+)\s+/, "sub0"); +file_grep($Self->{obj_dir} . "/Vsub1/sub1.sv", /^module\s+(\S+)\s+/, "sub1"); +file_grep($Self->{obj_dir} . "/Vsub2/sub2.sv", /^module\s+(\S+)\s+/, "sub2"); +file_grep($Self->{obj_dir} . '/Vt_hier_block_cmake__stats.txt', qr/HierBlock,\s+Hierarchical blocks\s+(\d+)/i, 10); +file_grep($Self->{run_log_filename}, qr/MACRO:(\S+) is defined/i, "cplusplus"); + +} + +ok(1); +1; diff --git a/test_regress/t/t_hier_block_nohier.pl b/test_regress/t/t_hier_block_nohier.pl new file mode 100755 index 000000000..ef6ebf31a --- /dev/null +++ b/test_regress/t/t_hier_block_nohier.pl @@ -0,0 +1,38 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +# This test makes sure that the intenral check of t_hier_block.v is correct. +# --hierarchical option is not set intentionally. + +# stats will be deleted but generation will be skipped if libs of hierarchical blocks exist. +clean_objs(); + +scenarios(vlt_all => 1); +top_filename("t/t_hier_block.v"); + +# Travis environment offers 2 VCPUs, 2 thread setting causes the following warning. +# %Warning-UNOPTTHREADS: Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads. +# So use 6 threads here though it's not optimal in performace wise, but ok. +compile( + v_flags2 => ['t/t_hier_block.cpp'], + verilator_flags2 => ['--stats', + '+define+USE_VLT', 't/t_hier_block_vlt.vlt', + '--CFLAGS', '"-pipe -DCPP_MACRO=cplusplus"', + ($Self->{vltmt} ? ' --threads 6' : '')], + ); + +execute( + check_finished => 1, + ); + +file_grep_not($Self->{stats}, qr/HierBlock,\s+Hierarchical blocks\s+(\d+)/i); +file_grep($Self->{run_log_filename}, qr/MACRO:(\S+) is defined/i, "cplusplus"); + +ok(1); +1; diff --git a/test_regress/t/t_hier_block_prot_lib.pl b/test_regress/t/t_hier_block_prot_lib.pl new file mode 100755 index 000000000..c48b890ec --- /dev/null +++ b/test_regress/t/t_hier_block_prot_lib.pl @@ -0,0 +1,65 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +top_filename("t/t_hier_block.v"); + +scenarios(vlt_all => 1, xsim => 1); + +my $secret_prefix = "secret"; +my $secret_dir = "$Self->{obj_dir}/$secret_prefix"; +mkdir $secret_dir; + +while (1) { + # Always compile the secret file with Verilator no matter what simulator + # we are testing with + run(logfile => "$secret_dir/vlt_compile.log", + cmd => ["perl", + "$ENV{VERILATOR_ROOT}/bin/verilator", + "-cc", + "--hierarchical", + "-Mdir", + $secret_dir, + "--protect-lib", + $secret_prefix, + "--protect-key", + "PROTECT_KEY", + "t/t_hier_block.v", + "-DAS_PROT_LIB", + '--CFLAGS', '"-pipe -DCPP_MACRO=cplusplus"', + $Self->{vltmt} ? ' --threads 1' : '', + "--build"], + verilator_run => 1, + ); + last if $Self->{errors}; + + compile( + v_flags2 => ['t/t_hier_block.cpp'], + verilator_flags2 => ["$secret_dir/secret.sv", + "-DPROTLIB_TOP", + "--top-module t", + "-LDFLAGS", + "'$secret_prefix/libsecret.a'"], + ); + + execute( + check_finished => 1, + ); + + + ok(1); + last; +} + +file_grep($secret_dir . "/Vsub0/sub0.sv", /^module\s+(\S+)\s+/, "sub0"); +file_grep($secret_dir . "/Vsub1/sub1.sv", /^module\s+(\S+)\s+/, "sub1"); +file_grep($secret_dir . "/Vsub2/sub2.sv", /^module\s+(\S+)\s+/, "sub2"); +file_grep($Self->{run_log_filename}, qr/MACRO:(\S+) is defined/i, "cplusplus"); + +ok(1); +1; diff --git a/test_regress/t/t_hier_block_prot_lib_shared.pl b/test_regress/t/t_hier_block_prot_lib_shared.pl new file mode 100755 index 000000000..0abe249aa --- /dev/null +++ b/test_regress/t/t_hier_block_prot_lib_shared.pl @@ -0,0 +1,67 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +top_filename("t/t_hier_block.v"); + +scenarios(vlt_all => 1, xsim => 1); + +my $secret_prefix = "secret"; +my $secret_dir = "$Self->{obj_dir}/$secret_prefix"; +mkdir $secret_dir; +my $abs_secret_dir = File::Spec->rel2abs($secret_dir); + +while (1) { + # Always compile the secret file with Verilator no matter what simulator + # we are testing with + run(logfile => "$secret_dir/vlt_compile.log", + cmd => ["perl", + "$ENV{VERILATOR_ROOT}/bin/verilator", + "-cc", + "--hierarchical", + "-Mdir", + $secret_dir, + "--protect-lib", + $secret_prefix, + "--protect-key", + "PROTECT_KEY", + "t/t_hier_block.v", + "-DAS_PROT_LIB", + '--CFLAGS', '"-pipe -DCPP_MACRO=cplusplus"', + $Self->{vltmt} ? ' --threads 1' : '', + "--build"], + verilator_run => 1, + ); + last if $Self->{errors}; + + compile( + v_flags2 => ['t/t_hier_block.cpp'], + verilator_flags2 => ["$secret_dir/secret.sv", + "-DPROTLIB_TOP", + "--top-module t", + "-LDFLAGS", + "'-Wl,-rpath,$abs_secret_dir -L$abs_secret_dir -l$secret_prefix'"], + ); + + execute( + check_finished => 1, + run_env => "DYLD_FALLBACK_LIBRARY_PATH=$abs_secret_dir" + ); + + + ok(1); + last; +} + +file_grep($secret_dir . "/Vsub0/sub0.sv", /^module\s+(\S+)\s+/, "sub0"); +file_grep($secret_dir . "/Vsub1/sub1.sv", /^module\s+(\S+)\s+/, "sub1"); +file_grep($secret_dir . "/Vsub2/sub2.sv", /^module\s+(\S+)\s+/, "sub2"); +file_grep($Self->{run_log_filename}, qr/MACRO:(\S+) is defined/i, "cplusplus"); + +ok(1); +1; diff --git a/test_regress/t/t_hier_block_sc.pl b/test_regress/t/t_hier_block_sc.pl new file mode 100755 index 000000000..731aec401 --- /dev/null +++ b/test_regress/t/t_hier_block_sc.pl @@ -0,0 +1,41 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +# stats will be deleted but generation will be skipped if libs of hierarchical blocks exist. +clean_objs(); + +top_filename("t/t_hier_block.v"); + +# Travis environment offers 2 VCPUs, 2 thread setting causes the following warning. +# %Warning-UNOPTTHREADS: Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads. +# So use 6 threads here though it's not optimal in performace wise, but ok. +scenarios(vlt_all => 1); + +compile( + v_flags2 => ['t/t_hier_block.cpp'], + verilator_flags2 => ['--sc', + '--stats', + '--hierarchical', + ($Self->{vltmt} ? ' --threads 6' : ''), + '--CFLAGS', '"-pipe -DCPP_MACRO=cplusplus"' + ], + ); + +execute( + check_finished => 1, + ); + +file_grep($Self->{obj_dir} . "/Vsub0/sub0.sv", /^module\s+(\S+)\s+/, "sub0"); +file_grep($Self->{obj_dir} . "/Vsub1/sub1.sv", /^module\s+(\S+)\s+/, "sub1"); +file_grep($Self->{obj_dir} . "/Vsub2/sub2.sv", /^module\s+(\S+)\s+/, "sub2"); +file_grep($Self->{stats}, qr/HierBlock,\s+Hierarchical blocks\s+(\d+)/i, 10); +file_grep($Self->{run_log_filename}, qr/MACRO:(\S+) is defined/i, "cplusplus"); + +ok(1); +1; diff --git a/test_regress/t/t_hier_block_vlt.pl b/test_regress/t/t_hier_block_vlt.pl new file mode 100755 index 000000000..fc4e7ccc9 --- /dev/null +++ b/test_regress/t/t_hier_block_vlt.pl @@ -0,0 +1,39 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +# stats will be deleted but generation will be skipped if libs of hierarchical blocks exist. +clean_objs(); + +scenarios(vlt_all => 1); +top_filename("t/t_hier_block.v"); + +# Travis environment offers 2 VCPUs, 2 thread setting causes the following warning. +# %Warning-UNOPTTHREADS: Thread scheduler is unable to provide requested parallelism; consider asking for fewer threads. +# So use 6 threads here though it's not optimal in performace wise, but ok. +compile( + v_flags2 => ['t/t_hier_block.cpp'], + verilator_flags2 => ['--stats', + '--hierarchical', + '+define+USE_VLT', 't/t_hier_block_vlt.vlt', + '--CFLAGS', '"-pipe -DCPP_MACRO=cplusplus"', + ($Self->{vltmt} ? ' --threads 6' : '')], + ); + +execute( + check_finished => 1, + ); + +file_grep($Self->{obj_dir} . "/Vsub0/sub0.sv", /^module\s+(\S+)\s+/, "sub0"); +file_grep($Self->{obj_dir} . "/Vsub1/sub1.sv", /^module\s+(\S+)\s+/, "sub1"); +file_grep($Self->{obj_dir} . "/Vsub2/sub2.sv", /^module\s+(\S+)\s+/, "sub2"); +file_grep($Self->{stats}, qr/HierBlock,\s+Hierarchical blocks\s+(\d+)/i, 10); +file_grep($Self->{run_log_filename}, qr/MACRO:(\S+) is defined/i, "cplusplus"); + +ok(1); +1; diff --git a/test_regress/t/t_hier_block_vlt.vlt b/test_regress/t/t_hier_block_vlt.vlt new file mode 100644 index 000000000..b8e6105c9 --- /dev/null +++ b/test_regress/t/t_hier_block_vlt.vlt @@ -0,0 +1,8 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2020 by Yutetsu TAKATSUKASA + +`verilator_config +hier_block -module "sub?" +hier_block -module "delay" diff --git a/test_regress/t/t_lint_comb_bad.out b/test_regress/t/t_lint_comb_bad.out index 391b09a97..176774ef6 100644 --- a/test_regress/t/t_lint_comb_bad.out +++ b/test_regress/t/t_lint_comb_bad.out @@ -1,4 +1,4 @@ -%Error: t/t_lint_comb_bad.v:14:4: Timing control statements not legal under always_comb +%Error: t/t_lint_comb_bad.v:14:4: Timing control statements not legal under always_comb (IEEE 1800-2017 9.2.2.2.2) : ... Suggest use a normal 'always' 14 | always_comb @(*) begin | ^~~~~~~~~~~ diff --git a/test_regress/t/t_lint_declfilename_bbox.pl b/test_regress/t/t_lint_declfilename_bbox.pl new file mode 100755 index 000000000..f73da325a --- /dev/null +++ b/test_regress/t/t_lint_declfilename_bbox.pl @@ -0,0 +1,18 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +lint( + verilator_flags2 => ["--lint-only -Wall"], + ); + +ok(1); +1; diff --git a/test_regress/t/t_lint_declfilename_bbox.v b/test_regress/t/t_lint_declfilename_bbox.v new file mode 100644 index 000000000..c9bea6e23 --- /dev/null +++ b/test_regress/t/t_lint_declfilename_bbox.v @@ -0,0 +1,13 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2010 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t_lint_declfilename_bbox (); + parameter IN = 0; + if (IN) begin + // Should not warn, see bug2430 + BLACKBOXED bboxed (); + end +endmodule diff --git a/test_regress/t/t_lint_import_name2_bad.out b/test_regress/t/t_lint_import_name2_bad.out index 21eace02e..2bcdce56d 100644 --- a/test_regress/t/t_lint_import_name2_bad.out +++ b/test_regress/t/t_lint_import_name2_bad.out @@ -1,4 +1,4 @@ -%Error: t/t_lint_import_name2_bad.v:7:8: Package/class 'missing' not found, and needs to be predeclared (IEEE 1800-2017 26.3) +%Error-PKGNODECL: t/t_lint_import_name2_bad.v:7:8: Package/class 'missing' not found, and needs to be predeclared (IEEE 1800-2017 26.3) 7 | import missing::sigs; | ^~~~~~~ %Error: t/t_lint_import_name2_bad.v:7:8: Importing from missing package 'missing' diff --git a/test_regress/t/t_lint_pkg_colon_bad.out b/test_regress/t/t_lint_pkg_colon_bad.out index 51ef13962..f6a9c2149 100644 --- a/test_regress/t/t_lint_pkg_colon_bad.out +++ b/test_regress/t/t_lint_pkg_colon_bad.out @@ -1,4 +1,4 @@ -%Error: t/t_lint_pkg_colon_bad.v:7:17: Package/class 'mispkg' not found, and needs to be predeclared (IEEE 1800-2017 26.3) +%Error-PKGNODECL: t/t_lint_pkg_colon_bad.v:7:17: Package/class 'mispkg' not found, and needs to be predeclared (IEEE 1800-2017 26.3) 7 | module t (input mispkg::foo_t a); | ^~~~~~ %Error: t/t_lint_pkg_colon_bad.v:7:25: syntax error, unexpected IDENTIFIER, expecting TYPE-IDENTIFIER diff --git a/test_regress/t/t_mailbox_parse.pl b/test_regress/t/t_mailbox_parse.pl index 99f2d36c4..6074d4d9a 100755 --- a/test_regress/t/t_mailbox_parse.pl +++ b/test_regress/t/t_mailbox_parse.pl @@ -13,7 +13,7 @@ scenarios(vlt => 1); top_filename("t_mailbox.v"); lint( - verilator_flags2 => ["--debug-exit-parse"], + verilator_flags2 => ["--debug-exit-uvm"], ); ok(1); diff --git a/test_regress/t/t_mem_multi_io2.cpp b/test_regress/t/t_mem_multi_io2.cpp index ea00ec3e6..6598388cf 100644 --- a/test_regress/t/t_mem_multi_io2.cpp +++ b/test_regress/t/t_mem_multi_io2.cpp @@ -6,7 +6,7 @@ #include VM_PREFIX_INCLUDE -VM_PREFIX* tb = NULL; +VM_PREFIX* tb = nullptr; bool pass = true; double sc_time_stamp() { return 0; } diff --git a/test_regress/t/t_mem_multi_io3.cpp b/test_regress/t/t_mem_multi_io3.cpp index 6191d051d..9068af3f9 100644 --- a/test_regress/t/t_mem_multi_io3.cpp +++ b/test_regress/t/t_mem_multi_io3.cpp @@ -6,7 +6,7 @@ #include VM_PREFIX_INCLUDE -VM_PREFIX* tb = NULL; +VM_PREFIX* tb = nullptr; bool pass = true; double sc_time_stamp() { return 0; } diff --git a/test_regress/t/t_order_quad.cpp b/test_regress/t/t_order_quad.cpp index fb9da0545..89773b790 100644 --- a/test_regress/t/t_order_quad.cpp +++ b/test_regress/t/t_order_quad.cpp @@ -15,7 +15,7 @@ unsigned int main_time = 0; double sc_time_stamp() { return main_time; } -VM_PREFIX* topp = NULL; +VM_PREFIX* topp = nullptr; bool fail = false; void check(QData got, QData exp) { diff --git a/test_regress/t/t_fell.pl b/test_regress/t/t_past_funcs.pl old mode 100644 new mode 100755 similarity index 100% rename from test_regress/t/t_fell.pl rename to test_regress/t/t_past_funcs.pl diff --git a/test_regress/t/t_rose.v b/test_regress/t/t_past_funcs.v similarity index 71% rename from test_regress/t/t_rose.v rename to test_regress/t/t_past_funcs.v index 1eadaa61d..2ee24f4a5 100644 --- a/test_regress/t/t_rose.v +++ b/test_regress/t/t_past_funcs.v @@ -43,6 +43,8 @@ module Test (/*AUTOARG*/ input [31:0] in; reg [31:0] dly0 = 0; + reg [31:0] dly1 = 1; + reg [31:0] dly2 = -1; // If called in an assertion, sequence, or property, the appropriate clocking event. // Otherwise, if called in a disable condition or a clock expression in an assertion, sequence, or prop, explicit. @@ -52,12 +54,20 @@ module Test (/*AUTOARG*/ always @(posedge clk) begin dly0 <= in; + dly1 <= in; + dly2 <= in; // In clock expression $write("in=%0d, dly0=%0d, rose=%0d, past=%0d\n", in, dly0, $rose(dly0), $past(dly0)); if ($rose(dly0[4])) $stop; + if ($fell(dly1[4])) $stop; + if ($stable(dly2)) $stop; + if (!$changed(dly2)) $stop; end assert property (@(posedge clk) $rose(dly0) || dly0%2==0); + assert property (@(posedge clk) $fell(dly1) || dly1%2==1); + assert property (@(posedge clk) !$stable(dly2)); + assert property (@(posedge clk) $changed(dly2)); endmodule @@ -70,12 +80,26 @@ module Test2 (/*AUTOARG*/ input [31:0] in; reg [31:0] dly0; + reg [31:0] dly1 = 1; + reg [31:0] dly2; always @(posedge clk) begin dly0 <= in; + dly1 <= in; + dly2 <= in; if ($rose(dly0[31:4])) $stop; + if ($fell(dly1[31:4])) $stop; + if (!$stable(dly2[31:4])) $stop; + if ($changed(dly2[31:4])) $stop; end default clocking @(posedge clk); endclocking assert property ($rose(dly0[0]) || dly0%2==0); + + default clocking @(posedge clk); endclocking + assert property ($fell(dly1[0]) || dly1%2==1); + + default clocking @(posedge clk); endclocking + assert property ($stable(dly2[31:4])); + assert property (!$changed(dly2[31:4])); endmodule diff --git a/test_regress/t/t_past_unsup_bad.out b/test_regress/t/t_past_unsup_bad.out index 6d635d12b..9f8b2bb83 100644 --- a/test_regress/t/t_past_unsup_bad.out +++ b/test_regress/t/t_past_unsup_bad.out @@ -1,4 +1,19 @@ %Error-UNSUPPORTED: t/t_past_unsup_bad.v:13:11: Unsupported: $past expr2 and clock arguments - 13 | if ($past(d, 0, 0, 0)) $stop; + 13 | if ($past(d, 0, 0)) $stop; | ^~~~~ +%Error-UNSUPPORTED: t/t_past_unsup_bad.v:14:11: Unsupported: $past expr2 and clock arguments + 14 | if ($past(d, 0, 0, clk)) $stop; + | ^~~~~ +%Error-UNSUPPORTED: t/t_past_unsup_bad.v:15:11: Unsupported: $fell and clock arguments + 15 | if ($fell(d, clk)) $stop; + | ^~~~~ +%Error-UNSUPPORTED: t/t_past_unsup_bad.v:16:11: Unsupported: $rose and clock arguments + 16 | if ($rose(d, clk)) $stop; + | ^~~~~ +%Error-UNSUPPORTED: t/t_past_unsup_bad.v:17:11: Unsupported: $stable and clock arguments + 17 | if ($stable(d, clk)) $stop; + | ^~~~~~~ +%Error-UNSUPPORTED: t/t_past_unsup_bad.v:18:11: Unsupported: $changed and clock arguments + 18 | if ($changed(d, clk)) $stop; + | ^~~~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_past_unsup_bad.v b/test_regress/t/t_past_unsup_bad.v index 750897cb2..edcc5c490 100644 --- a/test_regress/t/t_past_unsup_bad.v +++ b/test_regress/t/t_past_unsup_bad.v @@ -10,6 +10,11 @@ module t (d, clk); always @ (posedge clk) begin // Unsupported - if ($past(d, 0, 0, 0)) $stop; + if ($past(d, 0, 0)) $stop; + if ($past(d, 0, 0, clk)) $stop; + if ($fell(d, clk)) $stop; + if ($rose(d, clk)) $stop; + if ($stable(d, clk)) $stop; + if ($changed(d, clk)) $stop; end endmodule diff --git a/test_regress/t/t_preproc_defines.out b/test_regress/t/t_preproc_defines.out index a1eaedd69..e410899bc 100644 --- a/test_regress/t/t_preproc_defines.out +++ b/test_regress/t/t_preproc_defines.out @@ -20,6 +20,5 @@ `define VERILATOR 1 `define WITH_ARG(a) (a)(a) `define coverage_block_off /*verilator coverage_block_off*/ -`define systemc_clock /*verilator systemc_clock*/ `define verilator 1 `define verilator3 1 diff --git a/test_regress/t/t_process.v b/test_regress/t/t_process.v index 301cb878b..f6ee27bac 100644 --- a/test_regress/t/t_process.v +++ b/test_regress/t/t_process.v @@ -34,6 +34,7 @@ module t(/*AUTOARG*/); if (0) p.await(); if (0) p.suspend(); if (0) p.resume(); + // See also t_urandom.pl p.srandom(0); p.set_randstate(p.get_randstate()); diff --git a/test_regress/t/t_process_parse.pl b/test_regress/t/t_process_parse.pl index b06c6fba8..71e0db056 100755 --- a/test_regress/t/t_process_parse.pl +++ b/test_regress/t/t_process_parse.pl @@ -13,7 +13,7 @@ scenarios(vlt => 1); top_filename("t_process.v"); lint( - verilator_flags2 => ["--debug-exit-parse"], + verilator_flags2 => ["--debug-exit-uvm"], ); ok(1); diff --git a/test_regress/t/t_rose.pl b/test_regress/t/t_process_redecl.pl old mode 100644 new mode 100755 similarity index 78% rename from test_regress/t/t_rose.pl rename to test_regress/t/t_process_redecl.pl index c1a6773e9..f697727ea --- a/test_regress/t/t_rose.pl +++ b/test_regress/t/t_process_redecl.pl @@ -7,14 +7,9 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. -scenarios(simulator => 1); +scenarios(linter => 1); -compile( - verilator_flags2 => ['--assert'], - ); - -execute( - check_finished => 1, +lint( ); ok(1); diff --git a/test_regress/t/t_process_redecl.v b/test_regress/t/t_process_redecl.v new file mode 100644 index 000000000..0263e5c56 --- /dev/null +++ b/test_regress/t/t_process_redecl.v @@ -0,0 +1,23 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t ( + ); + + // Overrides standard class + class process; + endclass + class mailbox; + endclass + class semaphore; + endclass + + initial begin + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_prot_lib_shared.pl b/test_regress/t/t_prot_lib_shared.pl new file mode 100755 index 000000000..a595a4866 --- /dev/null +++ b/test_regress/t/t_prot_lib_shared.pl @@ -0,0 +1,81 @@ +#!/usr/bin/env perl +# Makes the test run with tracing enabled by default, can be overridden +# with --notrace +unshift(@ARGV, "--trace"); +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2019 by Todd Strader. 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 + +scenarios( + vlt => 1, + vltmt => 1, + xsim => 1, + ); +top_filename("t/t_prot_lib.v"); + +$Self->{sim_time} = $Self->{benchmark} * 100 if $Self->{benchmark}; + +my $secret_prefix = "secret"; +my $secret_dir = "$Self->{obj_dir}/$secret_prefix"; +my $abs_secret_dir = File::Spec->rel2abs($secret_dir); +mkdir $secret_dir; + +while (1) { + # Always compile the secret file with Verilator no matter what simulator + # we are testing with + run(logfile => "$secret_dir/vlt_compile.log", + cmd => ["perl", + "$ENV{VERILATOR_ROOT}/bin/verilator", + ($Self->{vltmt} ? ' --threads 6' : ''), + "--prefix", + "Vt_prot_lib_secret", + "-cc", + "-Mdir", + $secret_dir, + "--protect-lib", + $secret_prefix, + "t/t_prot_lib_secret.v"], + verilator_run => 1, + ); + last if $Self->{errors}; + + run(logfile => "$secret_dir/secret_gcc.log", + cmd=>[$ENV{MAKE}, + "-C", + $secret_dir, + "-f", + "Vt_prot_lib_secret.mk"]); + last if $Self->{errors}; + + compile( + verilator_flags2 => ["$secret_dir/secret.sv", + ($Self->{vltmt} ? ' --threads 1' : ''), + "-LDFLAGS", + "'-Wl,-rpath,$abs_secret_dir -L$abs_secret_dir -l$secret_prefix'"], + xsim_flags2 => ["$secret_dir/secret.sv"], + ); + + execute( + check_finished => 1, + run_env => "DYLD_FALLBACK_LIBRARY_PATH=$abs_secret_dir", + xsim_run_flags2 => ["--sv_lib", + "$secret_dir/libsecret", + "--dpi_absolute"], + ); + + if ($Self->{vlt} && $Self->{trace}) { + # We can see the ports of the secret module + file_grep("$Self->{obj_dir}/simx.vcd", qr/accum_in/); + # but we can't see what's inside + file_grep_not("$Self->{obj_dir}/simx.vcd", qr/secret_/); + } + + ok(1); + last; +} +1; diff --git a/test_regress/t/t_queue.v b/test_regress/t/t_queue.v index a51ed63fe..0d3ded455 100644 --- a/test_regress/t/t_queue.v +++ b/test_regress/t/t_queue.v @@ -41,6 +41,7 @@ module t (/*AUTOARG*/ `checkh($high(q), -1); `checkh($size(q), 0); `checkh($dimensions(q), 1); + // $bits is unsupported in several other simulators, see bug1646 // Unsup: `checkh($bits(q), 0); q.push_back(1'b1); diff --git a/test_regress/t/t_queue_class.pl b/test_regress/t/t_queue_class.pl new file mode 100755 index 000000000..b46d46042 --- /dev/null +++ b/test_regress/t/t_queue_class.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_queue_class.v b/test_regress/t/t_queue_class.v new file mode 100644 index 000000000..7424ff429 --- /dev/null +++ b/test_regress/t/t_queue_class.v @@ -0,0 +1,32 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2019 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + class Cls; + int que[$]; + + task push_data(int val); + que.push_back(val); + endtask + endclass + + initial begin + Cls c2 [1:0]; + + c2[0] = new(); + + c2[0].push_data(20); // Works + + if (c2[0].que.size() != 1) $stop; + + c2[0].que.push_back(10); // Unsupported + if (c2[0].que.size() != 2) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_sc_names.cpp b/test_regress/t/t_sc_names.cpp index 13316602e..00a7503f4 100644 --- a/test_regress/t/t_sc_names.cpp +++ b/test_regress/t/t_sc_names.cpp @@ -6,7 +6,7 @@ #include VM_PREFIX_INCLUDE #include "Vt_sc_names.h" -VM_PREFIX* tb = NULL; +VM_PREFIX* tb = nullptr; int sc_main(int argc, char* argv[]) { tb = new VM_PREFIX("tb"); diff --git a/test_regress/t/t_scope_map.cpp b/test_regress/t/t_scope_map.cpp index 65fcd125a..90fd2c63f 100644 --- a/test_regress/t/t_scope_map.cpp +++ b/test_regress/t/t_scope_map.cpp @@ -43,24 +43,23 @@ int main(int argc, char** argv, char** env) { it->second->scopeDump(); #endif VerilatedVarNameMap* varNameMap = it->second->varsp(); - if (varNameMap == NULL) { + if (!varNameMap) { VL_PRINTF("%%Error: Bad varsp()\n"); return -1; } - for (VerilatedVarNameMap::iterator varIt = varNameMap->begin(); varIt != varNameMap->end(); - ++varIt) { - VerilatedVar* var = &varIt->second; - int varLeft = var->packed().left(); - int varRight = var->packed().right(); + for (const auto& varname : *varNameMap) { + const VerilatedVar* varp = &(varname.second); + int varLeft = varp->packed().left(); + int varRight = varp->packed().right(); #ifdef TEST_VERBOSE - VL_PRINTF("\tVar = %s\n", varIt->first); - VL_PRINTF("\t Type = %d\n", var->vltype()); - VL_PRINTF("\t EntSize = %d\n", var->entSize()); - VL_PRINTF("\t Dims = %d\n", var->dims()); + VL_PRINTF("\tVar = %s\n", varname.first); + VL_PRINTF("\t Type = %d\n", varp->vltype()); + VL_PRINTF("\t EntSize = %d\n", varp->entSize()); + VL_PRINTF("\t Dims = %d\n", varp->dims()); VL_PRINTF("\t Range = %d:%d\n", varLeft, varRight); - VL_PRINTF("\t Is RW = %d\n", var->isPublicRW()); + VL_PRINTF("\t Is RW = %d\n", varp->isPublicRW()); #endif if (varRight != 0) { @@ -71,7 +70,7 @@ int main(int argc, char** argv, char** env) { int varBits = varLeft + 1; // First expect an incrementing byte pattern - vluint8_t* varData = reinterpret_cast(var->datap()); + vluint8_t* varData = reinterpret_cast(varp->datap()); for (int i = 0; i < varBits / 8; i++) { #ifdef TEST_VERBOSE VL_PRINTF("%02x ", varData[i]); @@ -119,24 +118,23 @@ int main(int argc, char** argv, char** env) { for (VerilatedScopeNameMap::const_iterator it = scopeMapp->begin(); it != scopeMapp->end(); ++it) { VerilatedVarNameMap* varNameMap = it->second->varsp(); - if (varNameMap == NULL) { + if (!varNameMap) { VL_PRINTF("%%Error: Bad varsp()\n"); return -1; } - for (VerilatedVarNameMap::iterator varIt = varNameMap->begin(); varIt != varNameMap->end(); - ++varIt) { - VerilatedVar* var = &varIt->second; - int varLeft = var->packed().left(); + for (const auto& varname : *varNameMap) { + const VerilatedVar* varp = &(varname.second); + int varLeft = varp->packed().left(); int varBits = varLeft + 1; - vluint8_t* varData = reinterpret_cast(var->datap()); + vluint8_t* varData = reinterpret_cast(varp->datap()); // Check that all bits are high now for (int i = 0; i < varBits / 8; i++) { vluint8_t expected = 0xff; if (varData[i] != expected) { VL_PRINTF("%%Error: Data mismatch (%s), got 0x%02x, expected 0x%02x\n", - varIt->first, varData[i], expected); + varname.first, varData[i], expected); return -1; } } @@ -146,7 +144,7 @@ int main(int argc, char** argv, char** env) { vluint8_t expected = ~(0xff << (varBits % 8)); if (got != expected) { VL_PRINTF("%%Error: Data mismatch (%s), got 0x%02x, expected 0x%02x\n", - varIt->first, got, expected); + varname.first, got, expected); return -1; } } diff --git a/test_regress/t/t_semaphore_parse.pl b/test_regress/t/t_semaphore_parse.pl index abc1f79f3..8149e4600 100755 --- a/test_regress/t/t_semaphore_parse.pl +++ b/test_regress/t/t_semaphore_parse.pl @@ -13,7 +13,7 @@ scenarios(vlt => 1); top_filename("t_semaphore.v"); lint( - verilator_flags2 => ["--debug-exit-parse"], + verilator_flags2 => ["--debug-exit-uvm"], ); ok(1); diff --git a/test_regress/t/t_split_var_0.pl b/test_regress/t/t_split_var_0.pl index 0e94ef9ad..ee21699a3 100755 --- a/test_regress/t/t_split_var_0.pl +++ b/test_regress/t/t_split_var_0.pl @@ -23,6 +23,6 @@ execute( ); file_grep($Self->{stats}, qr/SplitVar,\s+Split packed variables\s+(\d+)/i, 13); -file_grep($Self->{stats}, qr/SplitVar,\s+Split unpacked arrays\s+(\d+)/i, 23); +file_grep($Self->{stats}, qr/SplitVar,\s+Split unpacked arrays\s+(\d+)/i, 27); ok(1); 1; diff --git a/test_regress/t/t_split_var_0.v b/test_regress/t/t_split_var_0.v index c28e03c67..08295706a 100644 --- a/test_regress/t/t_split_var_0.v +++ b/test_regress/t/t_split_var_0.v @@ -381,6 +381,39 @@ module through #(parameter WIDTH = 8) endmodule +module delay (input wire clk); + logic unpack_sig0 [10:16] /*verilator split_var*/; + logic unpack_sig1 [13:16] /*verilator split_var*/; + logic unpack_sig2 [16:10] /*verilator split_var*/; + logic unpack_sig3 [16:13] /*verilator split_var*/; + + always @(posedge clk) begin + if (c <= 5) begin + unpack_sig0[13] <= 1'b1; + unpack_sig1[13] <= 1'b1; + unpack_sig0 [13+1:16] <= unpack_sig0[13:16-1]; + unpack_sig1 [13+1:16] <= unpack_sig1[13:16-1]; + unpack_sig2[13] <= 1'b1; + unpack_sig3[13] <= 1'b1; + unpack_sig2 [16:13+1] <= unpack_sig2[16-1:13]; + unpack_sig3 [16:13+1] <= unpack_sig3[16-1:13]; + end + end + + int c = 0; + always @(posedge clk) begin + c <= c + 1; + if (c >= 4) begin + if (!unpack_sig0[16] || !unpack_sig1[16]) $stop; + if (!unpack_sig2[16] || !unpack_sig3[16]) $stop; + end else begin + if (unpack_sig0[16] || unpack_sig1[16]) $stop; + if (unpack_sig2[16] || unpack_sig3[16]) $stop; + end + end +endmodule + + module t(/*AUTOARG*/ clk); input clk; localparam DEPTH = 3; @@ -403,6 +436,7 @@ module t(/*AUTOARG*/ clk); barshift_1d_packed_struct shifter7(.in(in), .out(out[7]), .shift(shift)); barshift_bitslice #(.DEPTH(DEPTH)) shifter8(.in(in), .out(out[8]), .shift(shift)); through #(.WIDTH(WIDTH)) though0 (.in(out[8]), .out(through_tmp)); + delay delay0(.clk(clk)); var_decl_with_init i_var_decl_with_init(); t_array_rev i_t_array_rev(clk); diff --git a/test_regress/t/t_split_var_2_trace.out b/test_regress/t/t_split_var_2_trace.out index 6b7342255..7bbee9244 100644 --- a/test_regress/t/t_split_var_2_trace.out +++ b/test_regress/t/t_split_var_2_trace.out @@ -1,363 +1,389 @@ $version Generated by VerilatedVcd $end -$date Tue Feb 11 16:07:02 2020 +$date Mon Aug 24 21:54:18 2020 $end $timescale 1ps $end $scope module top $end - $var wire 1 o2 clk $end + $var wire 1 U" clk $end $scope module t $end - $var wire 32 w2 DEPTH [31:0] $end - $var wire 32 )3 NUMSUB [31:0] $end - $var wire 32 !3 WIDTH [31:0] $end - $var wire 1 o2 clk $end - $var wire 64 93 expc [63:0] $end - $var wire 8 13 in [7:0] $end - $var wire 8 M- out(0) [7:0] $end - $var wire 8 N- out(1) [7:0] $end - $var wire 8 O- out(2) [7:0] $end - $var wire 8 P- out(3) [7:0] $end - $var wire 8 Q- out(4) [7:0] $end - $var wire 8 R- out(5) [7:0] $end - $var wire 8 S- out(6) [7:0] $end - $var wire 8 T- out(7) [7:0] $end - $var wire 8 U- out(8) [7:0] $end - $var wire 3 s shift [2:0] $end - $var wire 8 ?. through_tmp [7:0] $end + $var wire 32 V" DEPTH [31:0] $end + $var wire 32 X" NUMSUB [31:0] $end + $var wire 32 W" WIDTH [31:0] $end + $var wire 1 U" clk $end + $var wire 64 Z" expc [63:0] $end + $var wire 8 Y" in [7:0] $end + $var wire 8 x! out(0) [7:0] $end + $var wire 8 y! out(1) [7:0] $end + $var wire 8 z! out(2) [7:0] $end + $var wire 8 {! out(3) [7:0] $end + $var wire 8 |! out(4) [7:0] $end + $var wire 8 }! out(5) [7:0] $end + $var wire 8 ~! out(6) [7:0] $end + $var wire 8 !" out(7) [7:0] $end + $var wire 8 "" out(8) [7:0] $end + $var wire 3 - shift [2:0] $end + $var wire 8 $" through_tmp [7:0] $end $scope module always_block $end - $var wire 1 O2 failed $end + $var wire 1 . failed $end $scope module unnamedblk1 $end - $var wire 32 W2 i [31:0] $end + $var wire 32 / i [31:0] $end $upscope $end $upscope $end + $scope module delay0 $end + $var wire 32 u! c [31:0] $end + $var wire 1 U" clk $end + $var wire 1 z" unpack_sig0(10) $end + $var wire 1 {" unpack_sig0(11) $end + $var wire 1 |" unpack_sig0(12) $end + $var wire 1 e! unpack_sig0(13) $end + $var wire 1 f! unpack_sig0(14) $end + $var wire 1 g! unpack_sig0(15) $end + $var wire 1 h! unpack_sig0(16) $end + $var wire 1 i! unpack_sig1(13) $end + $var wire 1 j! unpack_sig1(14) $end + $var wire 1 k! unpack_sig1(15) $end + $var wire 1 l! unpack_sig1(16) $end + $var wire 1 }" unpack_sig2(10) $end + $var wire 1 ~" unpack_sig2(11) $end + $var wire 1 !# unpack_sig2(12) $end + $var wire 1 m! unpack_sig2(13) $end + $var wire 1 n! unpack_sig2(14) $end + $var wire 1 o! unpack_sig2(15) $end + $var wire 1 p! unpack_sig2(16) $end + $var wire 1 q! unpack_sig3(13) $end + $var wire 1 r! unpack_sig3(14) $end + $var wire 1 s! unpack_sig3(15) $end + $var wire 1 t! unpack_sig3(16) $end + $upscope $end $scope module i_t_array_rev $end - $var wire 1 C arrd(0) $end - $var wire 1 K arrd(1) $end - $var wire 1 o2 clk $end - $var wire 32 }5 cyc [31:0] $end - $var wire 1 _2 localbkw(0) $end - $var wire 1 g2 localbkw(1) $end - $var wire 1 S y0 $end - $var wire 1 [ y1 $end + $var wire 1 ' arrd(0) $end + $var wire 1 ( arrd(1) $end + $var wire 1 U" clk $end + $var wire 32 "# cyc [31:0] $end + $var wire 1 v! localbkw(0) $end + $var wire 1 w! localbkw(1) $end + $var wire 1 ) y0 $end + $var wire 1 * y1 $end $scope module arr_rev_u $end - $var wire 1 c arrbkw(0) $end - $var wire 1 d arrbkw(1) $end - $var wire 1 S y0 $end - $var wire 1 [ y1 $end + $var wire 1 + arrbkw(0) $end + $var wire 1 , arrbkw(1) $end + $var wire 1 ) y0 $end + $var wire 1 * y1 $end $upscope $end $upscope $end $scope module i_var_decl_with_init $end $var wire 32 # var0 [-1:30] $end - $var wire 32 3 var1 [30:-1] $end - $var wire 32 + var2 [-1:30] $end - $var wire 32 ; var3 [30:-1] $end + $var wire 32 % var1 [30:-1] $end + $var wire 32 $ var2 [-1:30] $end + $var wire 32 & var3 [30:-1] $end $upscope $end $scope module shifter0 $end - $var wire 32 w2 DEPTH [31:0] $end - $var wire 32 I3 OFFSET [31:0] $end - $var wire 32 !3 WIDTH [31:0] $end - $var wire 8 13 in [7:0] $end - $var wire 8 { out [7:0] $end - $var wire 3 s shift [2:0] $end - $var wire 8 -! tmp(-1) [7:0] $end - $var wire 8 %! tmp(-2) [7:0] $end - $var wire 8 13 tmp(-3) [7:0] $end - $var wire 8 5! tmp(0) [7:0] $end + $var wire 32 V" DEPTH [31:0] $end + $var wire 32 \" OFFSET [31:0] $end + $var wire 32 W" WIDTH [31:0] $end + $var wire 8 Y" in [7:0] $end + $var wire 8 0 out [7:0] $end + $var wire 3 - shift [2:0] $end + $var wire 8 2 tmp(-1) [7:0] $end + $var wire 8 1 tmp(-2) [7:0] $end + $var wire 8 Y" tmp(-3) [7:0] $end + $var wire 8 3 tmp(0) [7:0] $end $upscope $end $scope module shifter1 $end - $var wire 32 w2 DEPTH [31:0] $end - $var wire 32 I3 OFFSET [31:0] $end - $var wire 32 !3 WIDTH [31:0] $end - $var wire 8 13 in [7:0] $end - $var wire 8 =! out [7:0] $end - $var wire 3 s shift [2:0] $end - $var wire 8 E! tmp(-1) [7:0] $end - $var wire 8 %! tmp(-2) [7:0] $end - $var wire 8 13 tmp(-3) [7:0] $end - $var wire 8 =! tmp(0) [7:0] $end + $var wire 32 V" DEPTH [31:0] $end + $var wire 32 \" OFFSET [31:0] $end + $var wire 32 W" WIDTH [31:0] $end + $var wire 8 Y" in [7:0] $end + $var wire 8 4 out [7:0] $end + $var wire 3 - shift [2:0] $end + $var wire 8 5 tmp(-1) [7:0] $end + $var wire 8 1 tmp(-2) [7:0] $end + $var wire 8 Y" tmp(-3) [7:0] $end + $var wire 8 4 tmp(0) [7:0] $end $upscope $end $scope module shifter2 $end - $var wire 32 w2 DEPTH [31:0] $end - $var wire 32 Q3 OFFSET [31:0] $end - $var wire 32 !3 WIDTH [31:0] $end - $var wire 8 13 in [7:0] $end - $var wire 8 M! out [7:0] $end - $var wire 3 s shift [2:0] $end - $var wire 8 13 tmp(1) [7:0] $end - $var wire 8 U! tmp(2) [7:0] $end - $var wire 8 ]! tmp(3) [7:0] $end - $var wire 8 M! tmp(4) [7:0] $end + $var wire 32 V" DEPTH [31:0] $end + $var wire 32 ]" OFFSET [31:0] $end + $var wire 32 W" WIDTH [31:0] $end + $var wire 8 Y" in [7:0] $end + $var wire 8 6 out [7:0] $end + $var wire 3 - shift [2:0] $end + $var wire 8 Y" tmp(1) [7:0] $end + $var wire 8 7 tmp(2) [7:0] $end + $var wire 8 8 tmp(3) [7:0] $end + $var wire 8 6 tmp(4) [7:0] $end $upscope $end $scope module shifter3 $end - $var wire 32 w2 DEPTH [31:0] $end - $var wire 32 w2 N [31:0] $end - $var wire 32 Q3 OFFSET [31:0] $end - $var wire 32 !3 WIDTH [31:0] $end - $var wire 8 13 in [7:0] $end - $var wire 8 G. out [7:0] $end - $var wire 3 s shift [2:0] $end - $var wire 8 13 tmp0(1)(1) [7:0] $end - $var wire 8 13 tmp0(1)(2) [7:0] $end - $var wire 8 13 tmp0(1)(3) [7:0] $end - $var wire 8 %! tmp0(2)(1) [7:0] $end - $var wire 8 %! tmp0(2)(2) [7:0] $end - $var wire 8 %! tmp0(2)(3) [7:0] $end - $var wire 8 e! tmp0(3)(1) [7:0] $end - $var wire 8 m! tmp0(3)(2) [7:0] $end - $var wire 8 u! tmp0(3)(3) [7:0] $end - $var wire 8 }! tmp0(4)(1) [7:0] $end - $var wire 8 '" tmp0(4)(2) [7:0] $end - $var wire 8 /" tmp0(4)(3) [7:0] $end - $var wire 8 7" tmp1(1)(1) [7:0] $end - $var wire 8 ?" tmp1(1)(2) [7:0] $end - $var wire 8 G" tmp1(1)(3) [7:0] $end - $var wire 8 O" tmp1(2)(1) [7:0] $end - $var wire 8 W" tmp1(2)(2) [7:0] $end - $var wire 8 _" tmp1(2)(3) [7:0] $end - $var wire 8 g" tmp1(3)(1) [7:0] $end - $var wire 8 o" tmp1(3)(2) [7:0] $end - $var wire 8 w" tmp1(3)(3) [7:0] $end - $var wire 8 !# tmp1(4)(1) [7:0] $end - $var wire 8 )# tmp1(4)(2) [7:0] $end - $var wire 8 1# tmp1(4)(3) [7:0] $end - $var wire 8 I+ tmp10(1)(1) [7:0] $end - $var wire 8 Q+ tmp10(1)(2) [7:0] $end - $var wire 8 Y+ tmp10(1)(3) [7:0] $end - $var wire 8 a+ tmp10(2)(1) [7:0] $end - $var wire 8 i+ tmp10(2)(2) [7:0] $end - $var wire 8 q+ tmp10(2)(3) [7:0] $end - $var wire 8 y+ tmp10(3)(1) [7:0] $end - $var wire 8 #, tmp10(3)(2) [7:0] $end - $var wire 8 +, tmp10(3)(3) [7:0] $end - $var wire 8 3, tmp10(4)(1) [7:0] $end - $var wire 8 ;, tmp10(4)(2) [7:0] $end - $var wire 8 C, tmp10(4)(3) [7:0] $end - $var wire 8 O. tmp12(-1)(1)(1) [7:0] $end - $var wire 8 W. tmp12(-1)(1)(2) [7:0] $end - $var wire 8 _. tmp12(-1)(1)(3) [7:0] $end - $var wire 8 g. tmp12(-1)(2)(1) [7:0] $end - $var wire 8 o. tmp12(-1)(2)(2) [7:0] $end - $var wire 8 w. tmp12(-1)(2)(3) [7:0] $end - $var wire 8 !/ tmp12(-1)(3)(1) [7:0] $end - $var wire 8 )/ tmp12(-1)(3)(2) [7:0] $end - $var wire 8 1/ tmp12(-1)(3)(3) [7:0] $end - $var wire 8 G. tmp12(-1)(4)(1) [7:0] $end - $var wire 8 9/ tmp12(-1)(4)(2) [7:0] $end - $var wire 8 A/ tmp12(-1)(4)(3) [7:0] $end - $var wire 8 I/ tmp12(0)(1)(1) [7:0] $end - $var wire 8 Q/ tmp12(0)(1)(2) [7:0] $end - $var wire 8 Y/ tmp12(0)(1)(3) [7:0] $end - $var wire 8 a/ tmp12(0)(2)(1) [7:0] $end - $var wire 8 i/ tmp12(0)(2)(2) [7:0] $end - $var wire 8 q/ tmp12(0)(2)(3) [7:0] $end - $var wire 8 y/ tmp12(0)(3)(1) [7:0] $end - $var wire 8 #0 tmp12(0)(3)(2) [7:0] $end - $var wire 8 +0 tmp12(0)(3)(3) [7:0] $end - $var wire 8 30 tmp12(0)(4)(1) [7:0] $end - $var wire 8 ;0 tmp12(0)(4)(2) [7:0] $end - $var wire 8 C0 tmp12(0)(4)(3) [7:0] $end - $var wire 8 [4 tmp13(1)(1) [7:0] $end - $var wire 8 c4 tmp13(1)(2) [7:0] $end - $var wire 8 k4 tmp13(1)(3) [7:0] $end - $var wire 8 s4 tmp13(2)(1) [7:0] $end - $var wire 8 {4 tmp13(2)(2) [7:0] $end - $var wire 8 %5 tmp13(2)(3) [7:0] $end - $var wire 8 -5 tmp13(3)(1) [7:0] $end - $var wire 8 55 tmp13(3)(2) [7:0] $end - $var wire 8 =5 tmp13(3)(3) [7:0] $end - $var wire 8 E5 tmp13(4)(1) [7:0] $end - $var wire 8 M5 tmp13(4)(2) [7:0] $end - $var wire 8 U5 tmp13(4)(3) [7:0] $end - $var wire 8 9# tmp2(1)(1) [7:0] $end - $var wire 8 A# tmp2(1)(2) [7:0] $end - $var wire 8 I# tmp2(1)(3) [7:0] $end - $var wire 8 Q# tmp2(2)(1) [7:0] $end - $var wire 8 Y# tmp2(2)(2) [7:0] $end - $var wire 8 a# tmp2(2)(3) [7:0] $end - $var wire 8 i# tmp2(3)(1) [7:0] $end - $var wire 8 q# tmp2(3)(2) [7:0] $end - $var wire 8 y# tmp2(3)(3) [7:0] $end - $var wire 8 #$ tmp2(4)(1) [7:0] $end - $var wire 8 +$ tmp2(4)(2) [7:0] $end - $var wire 8 3$ tmp2(4)(3) [7:0] $end - $var wire 8 ;$ tmp3(1)(1) [7:0] $end - $var wire 8 C$ tmp3(1)(2) [7:0] $end - $var wire 8 K$ tmp3(1)(3) [7:0] $end - $var wire 8 S$ tmp3(2)(1) [7:0] $end - $var wire 8 [$ tmp3(2)(2) [7:0] $end - $var wire 8 c$ tmp3(2)(3) [7:0] $end - $var wire 8 k$ tmp3(3)(1) [7:0] $end - $var wire 8 s$ tmp3(3)(2) [7:0] $end - $var wire 8 {$ tmp3(3)(3) [7:0] $end - $var wire 8 %% tmp3(4)(1) [7:0] $end - $var wire 8 -% tmp3(4)(2) [7:0] $end - $var wire 8 5% tmp3(4)(3) [7:0] $end - $var wire 8 =% tmp4(1)(1) [7:0] $end - $var wire 8 E% tmp4(1)(2) [7:0] $end - $var wire 8 M% tmp4(1)(3) [7:0] $end - $var wire 8 U% tmp4(2)(1) [7:0] $end - $var wire 8 ]% tmp4(2)(2) [7:0] $end - $var wire 8 e% tmp4(2)(3) [7:0] $end - $var wire 8 m% tmp4(3)(1) [7:0] $end - $var wire 8 u% tmp4(3)(2) [7:0] $end - $var wire 8 }% tmp4(3)(3) [7:0] $end - $var wire 8 '& tmp4(4)(1) [7:0] $end - $var wire 8 /& tmp4(4)(2) [7:0] $end - $var wire 8 7& tmp4(4)(3) [7:0] $end - $var wire 8 ?& tmp5(1)(1) [7:0] $end - $var wire 8 G& tmp5(1)(2) [7:0] $end - $var wire 8 O& tmp5(1)(3) [7:0] $end - $var wire 8 W& tmp5(2)(1) [7:0] $end - $var wire 8 _& tmp5(2)(2) [7:0] $end - $var wire 8 g& tmp5(2)(3) [7:0] $end - $var wire 8 o& tmp5(3)(1) [7:0] $end - $var wire 8 w& tmp5(3)(2) [7:0] $end - $var wire 8 !' tmp5(3)(3) [7:0] $end - $var wire 8 )' tmp5(4)(1) [7:0] $end - $var wire 8 1' tmp5(4)(2) [7:0] $end - $var wire 8 9' tmp5(4)(3) [7:0] $end - $var wire 8 A' tmp6(1)(1) [7:0] $end - $var wire 8 I' tmp6(1)(2) [7:0] $end - $var wire 8 Q' tmp6(1)(3) [7:0] $end - $var wire 8 Y' tmp6(2)(1) [7:0] $end - $var wire 8 a' tmp6(2)(2) [7:0] $end - $var wire 8 i' tmp6(2)(3) [7:0] $end - $var wire 8 q' tmp6(3)(1) [7:0] $end - $var wire 8 y' tmp6(3)(2) [7:0] $end - $var wire 8 #( tmp6(3)(3) [7:0] $end - $var wire 8 +( tmp6(4)(1) [7:0] $end - $var wire 8 3( tmp6(4)(2) [7:0] $end - $var wire 8 ;( tmp6(4)(3) [7:0] $end - $var wire 8 C( tmp7(2)(1) [7:0] $end - $var wire 8 K( tmp7(2)(2) [7:0] $end - $var wire 8 S( tmp7(2)(3) [7:0] $end - $var wire 8 [( tmp7(3)(1) [7:0] $end - $var wire 8 c( tmp7(3)(2) [7:0] $end - $var wire 8 k( tmp7(3)(3) [7:0] $end - $var wire 8 s( tmp7(4)(1) [7:0] $end - $var wire 8 {( tmp7(4)(2) [7:0] $end - $var wire 8 %) tmp7(4)(3) [7:0] $end - $var wire 8 -) tmp7(5)(1) [7:0] $end - $var wire 8 5) tmp7(5)(2) [7:0] $end - $var wire 8 =) tmp7(5)(3) [7:0] $end - $var wire 8 Y3 tmp8(0)(1) [7:0] $end - $var wire 8 a3 tmp8(0)(2) [7:0] $end - $var wire 8 i3 tmp8(0)(3) [7:0] $end - $var wire 8 q3 tmp8(1)(1) [7:0] $end - $var wire 8 y3 tmp8(1)(2) [7:0] $end - $var wire 8 #4 tmp8(1)(3) [7:0] $end - $var wire 8 E) tmp8(2)(1) [7:0] $end - $var wire 8 M) tmp8(2)(2) [7:0] $end - $var wire 8 U) tmp8(2)(3) [7:0] $end - $var wire 8 ]) tmp8(3)(1) [7:0] $end - $var wire 8 e) tmp8(3)(2) [7:0] $end - $var wire 8 m) tmp8(3)(3) [7:0] $end - $var wire 8 u) tmp8(4)(1) [7:0] $end - $var wire 8 }) tmp8(4)(2) [7:0] $end - $var wire 8 '* tmp8(4)(3) [7:0] $end - $var wire 8 /* tmp8(5)(1) [7:0] $end - $var wire 8 7* tmp8(5)(2) [7:0] $end - $var wire 8 ?* tmp8(5)(3) [7:0] $end - $var wire 8 +4 tmp8(6)(1) [7:0] $end - $var wire 8 34 tmp8(6)(2) [7:0] $end - $var wire 8 ;4 tmp8(6)(3) [7:0] $end - $var wire 8 C4 tmp8(7)(1) [7:0] $end - $var wire 8 K4 tmp8(7)(2) [7:0] $end - $var wire 8 S4 tmp8(7)(3) [7:0] $end - $var wire 8 G* tmp9(4)(1) [7:0] $end - $var wire 8 O* tmp9(4)(2) [7:0] $end - $var wire 8 W* tmp9(4)(3) [7:0] $end - $var wire 8 _* tmp9(5)(1) [7:0] $end - $var wire 8 g* tmp9(5)(2) [7:0] $end - $var wire 8 o* tmp9(5)(3) [7:0] $end - $var wire 8 w* tmp9(6)(1) [7:0] $end - $var wire 8 !+ tmp9(6)(2) [7:0] $end - $var wire 8 )+ tmp9(6)(3) [7:0] $end - $var wire 8 1+ tmp9(7)(1) [7:0] $end - $var wire 8 9+ tmp9(7)(2) [7:0] $end - $var wire 8 A+ tmp9(7)(3) [7:0] $end + $var wire 32 V" DEPTH [31:0] $end + $var wire 32 V" N [31:0] $end + $var wire 32 ]" OFFSET [31:0] $end + $var wire 32 W" WIDTH [31:0] $end + $var wire 8 Y" in [7:0] $end + $var wire 8 %" out [7:0] $end + $var wire 3 - shift [2:0] $end + $var wire 8 Y" tmp0(1)(1) [7:0] $end + $var wire 8 Y" tmp0(1)(2) [7:0] $end + $var wire 8 Y" tmp0(1)(3) [7:0] $end + $var wire 8 1 tmp0(2)(1) [7:0] $end + $var wire 8 1 tmp0(2)(2) [7:0] $end + $var wire 8 1 tmp0(2)(3) [7:0] $end + $var wire 8 9 tmp0(3)(1) [7:0] $end + $var wire 8 : tmp0(3)(2) [7:0] $end + $var wire 8 ; tmp0(3)(3) [7:0] $end + $var wire 8 < tmp0(4)(1) [7:0] $end + $var wire 8 = tmp0(4)(2) [7:0] $end + $var wire 8 > tmp0(4)(3) [7:0] $end + $var wire 8 ? tmp1(1)(1) [7:0] $end + $var wire 8 @ tmp1(1)(2) [7:0] $end + $var wire 8 A tmp1(1)(3) [7:0] $end + $var wire 8 B tmp1(2)(1) [7:0] $end + $var wire 8 C tmp1(2)(2) [7:0] $end + $var wire 8 D tmp1(2)(3) [7:0] $end + $var wire 8 E tmp1(3)(1) [7:0] $end + $var wire 8 F tmp1(3)(2) [7:0] $end + $var wire 8 G tmp1(3)(3) [7:0] $end + $var wire 8 H tmp1(4)(1) [7:0] $end + $var wire 8 I tmp1(4)(2) [7:0] $end + $var wire 8 J tmp1(4)(3) [7:0] $end + $var wire 8 M! tmp10(1)(1) [7:0] $end + $var wire 8 N! tmp10(1)(2) [7:0] $end + $var wire 8 O! tmp10(1)(3) [7:0] $end + $var wire 8 P! tmp10(2)(1) [7:0] $end + $var wire 8 Q! tmp10(2)(2) [7:0] $end + $var wire 8 R! tmp10(2)(3) [7:0] $end + $var wire 8 S! tmp10(3)(1) [7:0] $end + $var wire 8 T! tmp10(3)(2) [7:0] $end + $var wire 8 U! tmp10(3)(3) [7:0] $end + $var wire 8 V! tmp10(4)(1) [7:0] $end + $var wire 8 W! tmp10(4)(2) [7:0] $end + $var wire 8 X! tmp10(4)(3) [7:0] $end + $var wire 8 &" tmp12(-1)(1)(1) [7:0] $end + $var wire 8 '" tmp12(-1)(1)(2) [7:0] $end + $var wire 8 (" tmp12(-1)(1)(3) [7:0] $end + $var wire 8 )" tmp12(-1)(2)(1) [7:0] $end + $var wire 8 *" tmp12(-1)(2)(2) [7:0] $end + $var wire 8 +" tmp12(-1)(2)(3) [7:0] $end + $var wire 8 ," tmp12(-1)(3)(1) [7:0] $end + $var wire 8 -" tmp12(-1)(3)(2) [7:0] $end + $var wire 8 ." tmp12(-1)(3)(3) [7:0] $end + $var wire 8 %" tmp12(-1)(4)(1) [7:0] $end + $var wire 8 /" tmp12(-1)(4)(2) [7:0] $end + $var wire 8 0" tmp12(-1)(4)(3) [7:0] $end + $var wire 8 1" tmp12(0)(1)(1) [7:0] $end + $var wire 8 2" tmp12(0)(1)(2) [7:0] $end + $var wire 8 3" tmp12(0)(1)(3) [7:0] $end + $var wire 8 4" tmp12(0)(2)(1) [7:0] $end + $var wire 8 5" tmp12(0)(2)(2) [7:0] $end + $var wire 8 6" tmp12(0)(2)(3) [7:0] $end + $var wire 8 7" tmp12(0)(3)(1) [7:0] $end + $var wire 8 8" tmp12(0)(3)(2) [7:0] $end + $var wire 8 9" tmp12(0)(3)(3) [7:0] $end + $var wire 8 :" tmp12(0)(4)(1) [7:0] $end + $var wire 8 ;" tmp12(0)(4)(2) [7:0] $end + $var wire 8 <" tmp12(0)(4)(3) [7:0] $end + $var wire 8 j" tmp13(1)(1) [7:0] $end + $var wire 8 k" tmp13(1)(2) [7:0] $end + $var wire 8 l" tmp13(1)(3) [7:0] $end + $var wire 8 m" tmp13(2)(1) [7:0] $end + $var wire 8 n" tmp13(2)(2) [7:0] $end + $var wire 8 o" tmp13(2)(3) [7:0] $end + $var wire 8 p" tmp13(3)(1) [7:0] $end + $var wire 8 q" tmp13(3)(2) [7:0] $end + $var wire 8 r" tmp13(3)(3) [7:0] $end + $var wire 8 s" tmp13(4)(1) [7:0] $end + $var wire 8 t" tmp13(4)(2) [7:0] $end + $var wire 8 u" tmp13(4)(3) [7:0] $end + $var wire 8 K tmp2(1)(1) [7:0] $end + $var wire 8 L tmp2(1)(2) [7:0] $end + $var wire 8 M tmp2(1)(3) [7:0] $end + $var wire 8 N tmp2(2)(1) [7:0] $end + $var wire 8 O tmp2(2)(2) [7:0] $end + $var wire 8 P tmp2(2)(3) [7:0] $end + $var wire 8 Q tmp2(3)(1) [7:0] $end + $var wire 8 R tmp2(3)(2) [7:0] $end + $var wire 8 S tmp2(3)(3) [7:0] $end + $var wire 8 T tmp2(4)(1) [7:0] $end + $var wire 8 U tmp2(4)(2) [7:0] $end + $var wire 8 V tmp2(4)(3) [7:0] $end + $var wire 8 W tmp3(1)(1) [7:0] $end + $var wire 8 X tmp3(1)(2) [7:0] $end + $var wire 8 Y tmp3(1)(3) [7:0] $end + $var wire 8 Z tmp3(2)(1) [7:0] $end + $var wire 8 [ tmp3(2)(2) [7:0] $end + $var wire 8 \ tmp3(2)(3) [7:0] $end + $var wire 8 ] tmp3(3)(1) [7:0] $end + $var wire 8 ^ tmp3(3)(2) [7:0] $end + $var wire 8 _ tmp3(3)(3) [7:0] $end + $var wire 8 ` tmp3(4)(1) [7:0] $end + $var wire 8 a tmp3(4)(2) [7:0] $end + $var wire 8 b tmp3(4)(3) [7:0] $end + $var wire 8 c tmp4(1)(1) [7:0] $end + $var wire 8 d tmp4(1)(2) [7:0] $end + $var wire 8 e tmp4(1)(3) [7:0] $end + $var wire 8 f tmp4(2)(1) [7:0] $end + $var wire 8 g tmp4(2)(2) [7:0] $end + $var wire 8 h tmp4(2)(3) [7:0] $end + $var wire 8 i tmp4(3)(1) [7:0] $end + $var wire 8 j tmp4(3)(2) [7:0] $end + $var wire 8 k tmp4(3)(3) [7:0] $end + $var wire 8 l tmp4(4)(1) [7:0] $end + $var wire 8 m tmp4(4)(2) [7:0] $end + $var wire 8 n tmp4(4)(3) [7:0] $end + $var wire 8 o tmp5(1)(1) [7:0] $end + $var wire 8 p tmp5(1)(2) [7:0] $end + $var wire 8 q tmp5(1)(3) [7:0] $end + $var wire 8 r tmp5(2)(1) [7:0] $end + $var wire 8 s tmp5(2)(2) [7:0] $end + $var wire 8 t tmp5(2)(3) [7:0] $end + $var wire 8 u tmp5(3)(1) [7:0] $end + $var wire 8 v tmp5(3)(2) [7:0] $end + $var wire 8 w tmp5(3)(3) [7:0] $end + $var wire 8 x tmp5(4)(1) [7:0] $end + $var wire 8 y tmp5(4)(2) [7:0] $end + $var wire 8 z tmp5(4)(3) [7:0] $end + $var wire 8 { tmp6(1)(1) [7:0] $end + $var wire 8 | tmp6(1)(2) [7:0] $end + $var wire 8 } tmp6(1)(3) [7:0] $end + $var wire 8 ~ tmp6(2)(1) [7:0] $end + $var wire 8 !! tmp6(2)(2) [7:0] $end + $var wire 8 "! tmp6(2)(3) [7:0] $end + $var wire 8 #! tmp6(3)(1) [7:0] $end + $var wire 8 $! tmp6(3)(2) [7:0] $end + $var wire 8 %! tmp6(3)(3) [7:0] $end + $var wire 8 &! tmp6(4)(1) [7:0] $end + $var wire 8 '! tmp6(4)(2) [7:0] $end + $var wire 8 (! tmp6(4)(3) [7:0] $end + $var wire 8 )! tmp7(2)(1) [7:0] $end + $var wire 8 *! tmp7(2)(2) [7:0] $end + $var wire 8 +! tmp7(2)(3) [7:0] $end + $var wire 8 ,! tmp7(3)(1) [7:0] $end + $var wire 8 -! tmp7(3)(2) [7:0] $end + $var wire 8 .! tmp7(3)(3) [7:0] $end + $var wire 8 /! tmp7(4)(1) [7:0] $end + $var wire 8 0! tmp7(4)(2) [7:0] $end + $var wire 8 1! tmp7(4)(3) [7:0] $end + $var wire 8 2! tmp7(5)(1) [7:0] $end + $var wire 8 3! tmp7(5)(2) [7:0] $end + $var wire 8 4! tmp7(5)(3) [7:0] $end + $var wire 8 ^" tmp8(0)(1) [7:0] $end + $var wire 8 _" tmp8(0)(2) [7:0] $end + $var wire 8 `" tmp8(0)(3) [7:0] $end + $var wire 8 a" tmp8(1)(1) [7:0] $end + $var wire 8 b" tmp8(1)(2) [7:0] $end + $var wire 8 c" tmp8(1)(3) [7:0] $end + $var wire 8 5! tmp8(2)(1) [7:0] $end + $var wire 8 6! tmp8(2)(2) [7:0] $end + $var wire 8 7! tmp8(2)(3) [7:0] $end + $var wire 8 8! tmp8(3)(1) [7:0] $end + $var wire 8 9! tmp8(3)(2) [7:0] $end + $var wire 8 :! tmp8(3)(3) [7:0] $end + $var wire 8 ;! tmp8(4)(1) [7:0] $end + $var wire 8 ! tmp8(5)(1) [7:0] $end + $var wire 8 ?! tmp8(5)(2) [7:0] $end + $var wire 8 @! tmp8(5)(3) [7:0] $end + $var wire 8 d" tmp8(6)(1) [7:0] $end + $var wire 8 e" tmp8(6)(2) [7:0] $end + $var wire 8 f" tmp8(6)(3) [7:0] $end + $var wire 8 g" tmp8(7)(1) [7:0] $end + $var wire 8 h" tmp8(7)(2) [7:0] $end + $var wire 8 i" tmp8(7)(3) [7:0] $end + $var wire 8 A! tmp9(4)(1) [7:0] $end + $var wire 8 B! tmp9(4)(2) [7:0] $end + $var wire 8 C! tmp9(4)(3) [7:0] $end + $var wire 8 D! tmp9(5)(1) [7:0] $end + $var wire 8 E! tmp9(5)(2) [7:0] $end + $var wire 8 F! tmp9(5)(3) [7:0] $end + $var wire 8 G! tmp9(6)(1) [7:0] $end + $var wire 8 H! tmp9(6)(2) [7:0] $end + $var wire 8 I! tmp9(6)(3) [7:0] $end + $var wire 8 J! tmp9(7)(1) [7:0] $end + $var wire 8 K! tmp9(7)(2) [7:0] $end + $var wire 8 L! tmp9(7)(3) [7:0] $end $upscope $end $scope module shifter4 $end - $var wire 32 w2 DEPTH [31:0] $end - $var wire 32 ]5 OFFSET [31:0] $end - $var wire 32 !3 WIDTH [31:0] $end - $var wire 8 13 in [7:0] $end - $var wire 8 K, out [7:0] $end - $var wire 24 m5 pad [23:0] $end - $var wire 3 s shift [2:0] $end - $var wire 32 e5 tmp(2) [31:0] $end - $var wire 32 S, tmp(3) [31:0] $end - $var wire 32 [, tmp(4) [31:0] $end - $var wire 32 c, tmp(5) [31:0] $end + $var wire 32 V" DEPTH [31:0] $end + $var wire 32 v" OFFSET [31:0] $end + $var wire 32 W" WIDTH [31:0] $end + $var wire 8 Y" in [7:0] $end + $var wire 8 Y! out [7:0] $end + $var wire 24 x" pad [23:0] $end + $var wire 3 - shift [2:0] $end + $var wire 32 w" tmp(2) [31:0] $end + $var wire 32 Z! tmp(3) [31:0] $end + $var wire 32 [! tmp(4) [31:0] $end + $var wire 32 \! tmp(5) [31:0] $end $upscope $end $scope module shifter5 $end - $var wire 32 w2 DEPTH [31:0] $end - $var wire 32 u5 OFFSET [31:0] $end - $var wire 32 !3 WIDTH [31:0] $end - $var wire 8 13 in [7:0] $end - $var wire 8 k, out [7:0] $end - $var wire 3 s shift [2:0] $end - $var wire 32 s, tmp [31:0] $end + $var wire 32 V" DEPTH [31:0] $end + $var wire 32 y" OFFSET [31:0] $end + $var wire 32 W" WIDTH [31:0] $end + $var wire 8 Y" in [7:0] $end + $var wire 8 ]! out [7:0] $end + $var wire 3 - shift [2:0] $end + $var wire 32 ^! tmp [31:0] $end $upscope $end $scope module shifter6 $end - $var wire 32 w2 DEPTH [31:0] $end - $var wire 32 u5 OFFSET [31:0] $end - $var wire 32 !3 WIDTH [31:0] $end - $var wire 8 13 in [7:0] $end - $var wire 8 {, out [7:0] $end - $var wire 3 s shift [2:0] $end - $var wire 32 %- tmp [31:0] $end + $var wire 32 V" DEPTH [31:0] $end + $var wire 32 y" OFFSET [31:0] $end + $var wire 32 W" WIDTH [31:0] $end + $var wire 8 Y" in [7:0] $end + $var wire 8 _! out [7:0] $end + $var wire 3 - shift [2:0] $end + $var wire 32 `! tmp [31:0] $end $upscope $end $scope module shifter7 $end - $var wire 32 w2 DEPTH [31:0] $end - $var wire 32 !3 WIDTH [31:0] $end - $var wire 8 13 in [7:0] $end - $var wire 8 -- out [7:0] $end - $var wire 3 s shift [2:0] $end - $var wire 32 5- tmp [31:0] $end + $var wire 32 V" DEPTH [31:0] $end + $var wire 32 W" WIDTH [31:0] $end + $var wire 8 Y" in [7:0] $end + $var wire 8 a! out [7:0] $end + $var wire 3 - shift [2:0] $end + $var wire 32 b! tmp [31:0] $end $upscope $end $scope module shifter8 $end - $var wire 32 w2 DEPTH [31:0] $end - $var wire 32 !3 WIDTH [31:0] $end - $var wire 8 13 in [7:0] $end - $var wire 8 =- out [7:0] $end - $var wire 3 s shift [2:0] $end - $var wire 32 E- tmp [0:31] $end + $var wire 32 V" DEPTH [31:0] $end + $var wire 32 W" WIDTH [31:0] $end + $var wire 8 Y" in [7:0] $end + $var wire 8 c! out [7:0] $end + $var wire 3 - shift [2:0] $end + $var wire 32 d! tmp [0:31] $end $upscope $end $scope module though0 $end - $var wire 32 !3 WIDTH [31:0] $end - $var wire 8 7. in [7:0] $end - $var wire 8 ?. out [7:0] $end - $var wire 1 K0 unpack_tmp(0) $end - $var wire 1 S0 unpack_tmp(1) $end - $var wire 1 [0 unpack_tmp(2) $end - $var wire 1 c0 unpack_tmp(3) $end - $var wire 1 k0 unpack_tmp(4) $end - $var wire 1 s0 unpack_tmp(5) $end - $var wire 1 {0 unpack_tmp(6) $end - $var wire 1 %1 unpack_tmp(7) $end + $var wire 32 W" WIDTH [31:0] $end + $var wire 8 #" in [7:0] $end + $var wire 8 $" out [7:0] $end + $var wire 1 =" unpack_tmp(0) $end + $var wire 1 >" unpack_tmp(1) $end + $var wire 1 ?" unpack_tmp(2) $end + $var wire 1 @" unpack_tmp(3) $end + $var wire 1 A" unpack_tmp(4) $end + $var wire 1 B" unpack_tmp(5) $end + $var wire 1 C" unpack_tmp(6) $end + $var wire 1 D" unpack_tmp(7) $end $scope module i_pack2unpack $end - $var wire 32 !3 WIDTH [31:0] $end - $var wire 8 7. in [7:0] $end - $var wire 1 -1 out(0) $end - $var wire 1 .1 out(1) $end - $var wire 1 /1 out(2) $end - $var wire 1 01 out(3) $end - $var wire 1 11 out(4) $end - $var wire 1 21 out(5) $end - $var wire 1 31 out(6) $end - $var wire 1 41 out(7) $end + $var wire 32 W" WIDTH [31:0] $end + $var wire 8 #" in [7:0] $end + $var wire 1 E" out(0) $end + $var wire 1 F" out(1) $end + $var wire 1 G" out(2) $end + $var wire 1 H" out(3) $end + $var wire 1 I" out(4) $end + $var wire 1 J" out(5) $end + $var wire 1 K" out(6) $end + $var wire 1 L" out(7) $end $upscope $end $scope module i_unpack2pack $end - $var wire 32 !3 WIDTH [31:0] $end - $var wire 1 m1 in(0) $end - $var wire 1 n1 in(1) $end - $var wire 1 o1 in(2) $end - $var wire 1 p1 in(3) $end - $var wire 1 q1 in(4) $end - $var wire 1 r1 in(5) $end - $var wire 1 s1 in(6) $end - $var wire 1 t1 in(7) $end - $var wire 8 ?. out [7:0] $end + $var wire 32 W" WIDTH [31:0] $end + $var wire 1 M" in(0) $end + $var wire 1 N" in(1) $end + $var wire 1 O" in(2) $end + $var wire 1 P" in(3) $end + $var wire 1 Q" in(4) $end + $var wire 1 R" in(5) $end + $var wire 1 S" in(6) $end + $var wire 1 T" in(7) $end + $var wire 8 $" out [7:0] $end $upscope $end $upscope $end $upscope $end @@ -367,1564 +393,1611 @@ $enddefinitions $end #0 b00000001001000110100010101100111 # -b00100000000000000000000000000000 + -b00000001001000110100000000100111 3 -b00000000000000000000000000000011 ; -1C -0K -0S -1[ -0c -1d -b000 s +b00100000000000000000000000000000 $ +b00000001001000110100000000100111 % +b00000000000000000000000000000011 & +1' +0( +0) +1* +0+ +1, +b000 - +0. +b00000000000000000000000000000000 / +b10001110 0 +b10001110 1 +b10001110 2 +b10001110 3 +b10001110 4 +b10001110 5 +b10001110 6 +b10001110 7 +b10001110 8 +b10001110 9 +b10001110 : +b10001110 ; +b10001110 < +b10001110 = +b10001110 > +b10001110 ? +b10001110 @ +b10001110 A +b10001110 B +b10001110 C +b10001110 D +b10001110 E +b10001110 F +b10001110 G +b10001110 H +b10001110 I +b10001110 J +b10001110 K +b10001110 L +b10001110 M +b10001110 N +b10001110 O +b10001110 P +b10001110 Q +b10001110 R +b10001110 S +b10001110 T +b10001110 U +b10001110 V +b10001110 W +b10001110 X +b10001110 Y +b10001110 Z +b10001110 [ +b10001110 \ +b10001110 ] +b10001110 ^ +b10001110 _ +b10001110 ` +b10001110 a +b10001110 b +b10001110 c +b10001110 d +b10001110 e +b10001110 f +b10001110 g +b10001110 h +b10001110 i +b10001110 j +b10001110 k +b10001110 l +b10001110 m +b10001110 n +b10001110 o +b10001110 p +b10001110 q +b10001110 r +b10001110 s +b10001110 t +b10001110 u +b10001110 v +b10001110 w +b10001110 x +b10001110 y +b10001110 z b10001110 { +b10001110 | +b10001110 } +b10001110 ~ +b10001110 !! +b10001110 "! +b10001110 #! +b10001110 $! b10001110 %! +b10001110 &! +b10001110 '! +b10001110 (! +b10001110 )! +b10001110 *! +b10001110 +! +b10001110 ,! b10001110 -! +b10001110 .! +b10001110 /! +b10001110 0! +b10001110 1! +b10001110 2! +b10001110 3! +b10001110 4! b10001110 5! +b10001110 6! +b10001110 7! +b10001110 8! +b10001110 9! +b10001110 :! +b10001110 ;! +b10001110 ! +b10001110 ?! +b10001110 @! +b10001110 A! +b10001110 B! +b10001110 C! +b10001110 D! b10001110 E! +b10001110 F! +b10001110 G! +b10001110 H! +b10001110 I! +b10001110 J! +b10001110 K! +b10001110 L! b10001110 M! +b10001110 N! +b10001110 O! +b10001110 P! +b10001110 Q! +b10001110 R! +b10001110 S! +b10001110 T! b10001110 U! +b10001110 V! +b10001110 W! +b10001110 X! +b10001110 Y! +b00000000000000000000000010001110 Z! +b00000000000000000000000010001110 [! +b00000000000000000000000010001110 \! b10001110 ]! -b10001110 e! -b10001110 m! -b10001110 u! +b10001110100011101000111010001110 ^! +b10001110 _! +b10001110100011101000111010001110 `! +b10001110 a! +b10001110100011101000111010001110 b! +b10001110 c! +b10001110100011101000111010001110 d! +0e! +0f! +0g! +0h! +0i! +0j! +0k! +0l! +0m! +0n! +0o! +0p! +0q! +0r! +0s! +0t! +b00000000000000000000000000000000 u! +0v! +0w! +b10001110 x! +b10001110 y! +b10001110 z! +b10001110 {! +b10001110 |! b10001110 }! +b10001110 ~! +b10001110 !" +b10001110 "" +b10001110 #" +b10001110 $" +b10001110 %" +b10001110 &" b10001110 '" +b10001110 (" +b10001110 )" +b10001110 *" +b10001110 +" +b10001110 ," +b10001110 -" +b10001110 ." b10001110 /" +b10001110 0" +b10001110 1" +b10001110 2" +b10001110 3" +b10001110 4" +b10001110 5" +b10001110 6" b10001110 7" -b10001110 ?" -b10001110 G" -b10001110 O" -b10001110 W" -b10001110 _" -b10001110 g" -b10001110 o" -b10001110 w" -b10001110 !# -b10001110 )# -b10001110 1# -b10001110 9# -b10001110 A# -b10001110 I# -b10001110 Q# -b10001110 Y# -b10001110 a# -b10001110 i# -b10001110 q# -b10001110 y# -b10001110 #$ -b10001110 +$ -b10001110 3$ -b10001110 ;$ -b10001110 C$ -b10001110 K$ -b10001110 S$ -b10001110 [$ -b10001110 c$ -b10001110 k$ -b10001110 s$ -b10001110 {$ -b10001110 %% -b10001110 -% -b10001110 5% -b10001110 =% -b10001110 E% -b10001110 M% -b10001110 U% -b10001110 ]% -b10001110 e% -b10001110 m% -b10001110 u% -b10001110 }% -b10001110 '& -b10001110 /& -b10001110 7& -b10001110 ?& -b10001110 G& -b10001110 O& -b10001110 W& -b10001110 _& -b10001110 g& -b10001110 o& -b10001110 w& -b10001110 !' -b10001110 )' -b10001110 1' -b10001110 9' -b10001110 A' -b10001110 I' -b10001110 Q' -b10001110 Y' -b10001110 a' -b10001110 i' -b10001110 q' -b10001110 y' -b10001110 #( -b10001110 +( -b10001110 3( -b10001110 ;( -b10001110 C( -b10001110 K( -b10001110 S( -b10001110 [( -b10001110 c( -b10001110 k( -b10001110 s( -b10001110 {( -b10001110 %) -b10001110 -) -b10001110 5) -b10001110 =) -b10001110 E) -b10001110 M) -b10001110 U) -b10001110 ]) -b10001110 e) -b10001110 m) -b10001110 u) -b10001110 }) -b10001110 '* -b10001110 /* -b10001110 7* -b10001110 ?* -b10001110 G* -b10001110 O* -b10001110 W* -b10001110 _* -b10001110 g* -b10001110 o* -b10001110 w* -b10001110 !+ -b10001110 )+ -b10001110 1+ -b10001110 9+ -b10001110 A+ -b10001110 I+ -b10001110 Q+ -b10001110 Y+ -b10001110 a+ -b10001110 i+ -b10001110 q+ -b10001110 y+ -b10001110 #, -b10001110 +, -b10001110 3, -b10001110 ;, -b10001110 C, -b10001110 K, -b00000000000000000000000010001110 S, -b00000000000000000000000010001110 [, -b00000000000000000000000010001110 c, -b10001110 k, -b10001110100011101000111010001110 s, -b10001110 {, -b10001110100011101000111010001110 %- -b10001110 -- -b10001110100011101000111010001110 5- -b10001110 =- -b10001110100011101000111010001110 E- -b10001110 M- -b10001110 N- -b10001110 O- -b10001110 P- -b10001110 Q- -b10001110 R- -b10001110 S- -b10001110 T- -b10001110 U- -b10001110 7. -b10001110 ?. -b10001110 G. -b10001110 O. -b10001110 W. -b10001110 _. -b10001110 g. -b10001110 o. -b10001110 w. -b10001110 !/ -b10001110 )/ -b10001110 1/ -b10001110 9/ -b10001110 A/ -b10001110 I/ -b10001110 Q/ -b10001110 Y/ -b10001110 a/ -b10001110 i/ -b10001110 q/ -b10001110 y/ -b10001110 #0 -b10001110 +0 -b10001110 30 -b10001110 ;0 -b10001110 C0 -1K0 -0S0 -0[0 -0c0 -1k0 -1s0 -1{0 -0%1 -0-1 -1.1 -1/1 -101 -011 -021 -031 -141 -0m1 -1n1 -1o1 -1p1 -0q1 -0r1 -0s1 -1t1 -0O2 -b00000000000000000000000000000000 W2 -0_2 -0g2 -0o2 -b00000000000000000000000000000011 w2 -b00000000000000000000000000001000 !3 -b00000000000000000000000000001001 )3 -b10001110 13 -b1000111001000111101000111101000111101000011101000011101000011101 93 -b11111111111111111111111111111101 I3 -b00000000000000000000000000000001 Q3 -b00000000 Y3 -b00000000 a3 -b00000000 i3 -b00000000 q3 -b00000000 y3 -b00000000 #4 -b00000000 +4 -b00000000 34 -b00000000 ;4 -b00000000 C4 -b00000000 K4 -b00000000 S4 -b00000000 [4 -b00000000 c4 -b00000000 k4 -b00000000 s4 -b00000000 {4 -b00000000 %5 -b00000000 -5 -b00000000 55 -b00000000 =5 -b00000000 E5 -b00000000 M5 -b00000000 U5 -b00000000000000000000000000000010 ]5 -b00000000000000000000000010001110 e5 -b000000000000000000000000 m5 -b11111111111111111111111111111110 u5 -b00000000000000000000000000000000 }5 +b10001110 8" +b10001110 9" +b10001110 :" +b10001110 ;" +b10001110 <" +1=" +0>" +0?" +0@" +1A" +1B" +1C" +0D" +0E" +1F" +1G" +1H" +0I" +0J" +0K" +1L" +0M" +1N" +1O" +1P" +0Q" +0R" +0S" +1T" +0U" +b00000000000000000000000000000011 V" +b00000000000000000000000000001000 W" +b00000000000000000000000000001001 X" +b10001110 Y" +b1000111001000111101000111101000111101000011101000011101000011101 Z" +b11111111111111111111111111111101 \" +b00000000000000000000000000000001 ]" +b00000000 ^" +b00000000 _" +b00000000 `" +b00000000 a" +b00000000 b" +b00000000 c" +b00000000 d" +b00000000 e" +b00000000 f" +b00000000 g" +b00000000 h" +b00000000 i" +b00000000 j" +b00000000 k" +b00000000 l" +b00000000 m" +b00000000 n" +b00000000 o" +b00000000 p" +b00000000 q" +b00000000 r" +b00000000 s" +b00000000 t" +b00000000 u" +b00000000000000000000000000000010 v" +b00000000000000000000000010001110 w" +b000000000000000000000000 x" +b11111111111111111111111111111110 y" +0z" +0{" +0|" +0}" +0~" +0!# +b00000000000000000000000000000000 "# #10 -b001 s -b01000111 { +b001 - +b00000000000000000000000000001001 / +b01000111 0 +b01000111 1 +b01000111 2 +b01000111 3 +b01000111 4 +b01000111 5 +b01000111 6 +b01000111 7 +b01000111 8 +b01000111 9 +b01000111 : +b01000111 ; +b01000111 < +b01000111 = +b01000111 > +b01000111 B +b01000111 C +b01000111 D +b01000111 E +b01000111 F +b01000111 G +b01000111 H +b01000111 I +b01000111 J +b01000111 N +b01000111 O +b01000111 P +b01000111 Q +b01000111 R +b01000111 S +b01000111 T +b01000111 U +b01000111 V +b01000111 Z +b01000111 [ +b01000111 \ +b01000111 ] +b01000111 ^ +b01000111 _ +b01000111 ` +b01000111 a +b01000111 b +b01000111 f +b01000111 g +b01000111 h +b01000111 i +b01000111 j +b01000111 k +b01000111 l +b01000111 m +b01000111 n +b01000111 r +b01000111 s +b01000111 t +b01000111 u +b01000111 v +b01000111 w +b01000111 x +b01000111 y +b01000111 z +b01000111 ~ +b01000111 !! +b01000111 "! +b01000111 #! +b01000111 $! b01000111 %! +b01000111 &! +b01000111 '! +b01000111 (! +b01000111 ,! b01000111 -! -b01000111 5! +b01000111 .! +b01000111 /! +b01000111 0! +b01000111 1! +b01000111 2! +b01000111 3! +b01000111 4! +b01000111 8! +b01000111 9! +b01000111 :! +b01000111 ;! +b01000111 ! +b01000111 ?! +b01000111 @! +b01000111 D! b01000111 E! -b01000111 M! +b01000111 F! +b01000111 G! +b01000111 H! +b01000111 I! +b01000111 J! +b01000111 K! +b01000111 L! +b01000111 P! +b01000111 Q! +b01000111 R! +b01000111 S! +b01000111 T! b01000111 U! +b01000111 V! +b01000111 W! +b01000111 X! +b01000111 Y! +b00000000000000000000000001000111 Z! +b00000000000000000000000001000111 [! +b00000000000000000000000001000111 \! b01000111 ]! -b01000111 e! -b01000111 m! -b01000111 u! +b10001110010001110100011101000111 ^! +b01000111 _! +b10001110010001110100011101000111 `! +b01000111 a! +b10001110010001110100011101000111 b! +b01000111 c! +b10001110010001110100011101000111 d! +1e! +1i! +1m! +1q! +b00000000000000000000000000000001 u! +1w! +b01000111 x! +b01000111 y! +b01000111 z! +b01000111 {! +b01000111 |! b01000111 }! -b01000111 '" +b01000111 ~! +b01000111 !" +b01000111 "" +b01000111 #" +b01000111 $" +b01000111 %" +b01000111 )" +b01000111 *" +b01000111 +" +b01000111 ," +b01000111 -" +b01000111 ." b01000111 /" -b01000111 O" -b01000111 W" -b01000111 _" -b01000111 g" -b01000111 o" -b01000111 w" -b01000111 !# -b01000111 )# -b01000111 1# -b01000111 Q# -b01000111 Y# -b01000111 a# -b01000111 i# -b01000111 q# -b01000111 y# -b01000111 #$ -b01000111 +$ -b01000111 3$ -b01000111 S$ -b01000111 [$ -b01000111 c$ -b01000111 k$ -b01000111 s$ -b01000111 {$ -b01000111 %% -b01000111 -% -b01000111 5% -b01000111 U% -b01000111 ]% -b01000111 e% -b01000111 m% -b01000111 u% -b01000111 }% -b01000111 '& -b01000111 /& -b01000111 7& -b01000111 W& -b01000111 _& -b01000111 g& -b01000111 o& -b01000111 w& -b01000111 !' -b01000111 )' -b01000111 1' -b01000111 9' -b01000111 Y' -b01000111 a' -b01000111 i' -b01000111 q' -b01000111 y' -b01000111 #( -b01000111 +( -b01000111 3( -b01000111 ;( -b01000111 [( -b01000111 c( -b01000111 k( -b01000111 s( -b01000111 {( -b01000111 %) -b01000111 -) -b01000111 5) -b01000111 =) -b01000111 ]) -b01000111 e) -b01000111 m) -b01000111 u) -b01000111 }) -b01000111 '* -b01000111 /* -b01000111 7* -b01000111 ?* -b01000111 _* -b01000111 g* -b01000111 o* -b01000111 w* -b01000111 !+ -b01000111 )+ -b01000111 1+ -b01000111 9+ -b01000111 A+ -b01000111 a+ -b01000111 i+ -b01000111 q+ -b01000111 y+ -b01000111 #, -b01000111 +, -b01000111 3, -b01000111 ;, -b01000111 C, -b01000111 K, -b00000000000000000000000001000111 S, -b00000000000000000000000001000111 [, -b00000000000000000000000001000111 c, -b01000111 k, -b10001110010001110100011101000111 s, -b01000111 {, -b10001110010001110100011101000111 %- -b01000111 -- -b10001110010001110100011101000111 5- -b01000111 =- -b10001110010001110100011101000111 E- -b01000111 M- -b01000111 N- -b01000111 O- -b01000111 P- -b01000111 Q- -b01000111 R- -b01000111 S- -b01000111 T- -b01000111 U- -b01000111 7. -b01000111 ?. -b01000111 G. -b01000111 g. -b01000111 o. -b01000111 w. -b01000111 !/ -b01000111 )/ -b01000111 1/ -b01000111 9/ -b01000111 A/ -b01000111 a/ -b01000111 i/ -b01000111 q/ -b01000111 y/ -b01000111 #0 -b01000111 +0 -b01000111 30 -b01000111 ;0 -b01000111 C0 -0K0 -1S0 -0k0 -1%1 -1-1 -001 -131 -041 -1m1 -0p1 -1s1 -0t1 -b00000000000000000000000000001001 W2 -1g2 -1o2 +b01000111 0" +b01000111 4" +b01000111 5" +b01000111 6" +b01000111 7" +b01000111 8" +b01000111 9" +b01000111 :" +b01000111 ;" +b01000111 <" +0=" +1>" +0A" +1D" +1E" +0H" +1K" +0L" +1M" +0P" +1S" +0T" +1U" #15 -0o2 +0U" #20 -b010 s -b10100011 { -b10001110 %! -b10100011 -! -b10100011 5! +b010 - +b10100011 0 +b10001110 1 +b10100011 2 +b10100011 3 +b10100011 4 +b10100011 5 +b10100011 6 +b10001110 7 +b10100011 8 +b10100011 9 +b10100011 : +b10100011 ; +b10100011 < +b10100011 = +b10100011 > +b10001110 B +b10001110 C +b10001110 D +b10100011 E +b10100011 F +b10100011 G +b10100011 H +b10100011 I +b10100011 J +b10001110 N +b10001110 O +b10001110 P +b10100011 Q +b10100011 R +b10100011 S +b10100011 T +b10100011 U +b10100011 V +b10001110 Z +b10001110 [ +b10001110 \ +b10100011 ] +b10100011 ^ +b10100011 _ +b10100011 ` +b10100011 a +b10100011 b +b10001110 f +b10001110 g +b10001110 h +b10100011 i +b10100011 j +b10100011 k +b10100011 l +b10100011 m +b10100011 n +b10001110 r +b10001110 s +b10001110 t +b10100011 u +b10100011 v +b10100011 w +b10100011 x +b10100011 y +b10100011 z +b10001110 ~ +b10001110 !! +b10001110 "! +b10100011 #! +b10100011 $! +b10100011 %! +b10100011 &! +b10100011 '! +b10100011 (! +b10001110 ,! +b10001110 -! +b10001110 .! +b10100011 /! +b10100011 0! +b10100011 1! +b10100011 2! +b10100011 3! +b10100011 4! +b10001110 8! +b10001110 9! +b10001110 :! +b10100011 ;! +b10100011 ! +b10100011 ?! +b10100011 @! +b10001110 D! +b10001110 E! +b10001110 F! +b10100011 G! +b10100011 H! +b10100011 I! +b10100011 J! +b10100011 K! +b10100011 L! +b10001110 P! +b10001110 Q! +b10001110 R! +b10100011 S! +b10100011 T! +b10100011 U! +b10100011 V! +b10100011 W! +b10100011 X! +b10100011 Y! +b00000000000000000000000010001110 Z! +b00000000000000000000000010100011 [! +b00000000000000000000000010100011 \! b10100011 ]! -b10100011 e! -b10100011 m! -b10100011 u! +b10001110100011101010001110100011 ^! +b10100011 _! +b10001110100011101010001110100011 `! +b10100011 a! +b10001110100011101010001110100011 b! +b10100011 c! +b10001110100011101010001110100011 d! +1f! +1j! +1n! +1r! +b00000000000000000000000000000010 u! +b10100011 x! +b10100011 y! +b10100011 z! +b10100011 {! +b10100011 |! b10100011 }! -b10100011 '" +b10100011 ~! +b10100011 !" +b10100011 "" +b10100011 #" +b10100011 $" +b10100011 %" +b10001110 )" +b10001110 *" +b10001110 +" +b10100011 ," +b10100011 -" +b10100011 ." b10100011 /" -b10001110 O" -b10001110 W" -b10001110 _" -b10100011 g" -b10100011 o" -b10100011 w" -b10100011 !# -b10100011 )# -b10100011 1# -b10001110 Q# -b10001110 Y# -b10001110 a# -b10100011 i# -b10100011 q# -b10100011 y# -b10100011 #$ -b10100011 +$ -b10100011 3$ -b10001110 S$ -b10001110 [$ -b10001110 c$ -b10100011 k$ -b10100011 s$ -b10100011 {$ -b10100011 %% -b10100011 -% -b10100011 5% -b10001110 U% -b10001110 ]% -b10001110 e% -b10100011 m% -b10100011 u% -b10100011 }% -b10100011 '& -b10100011 /& -b10100011 7& -b10001110 W& -b10001110 _& -b10001110 g& -b10100011 o& -b10100011 w& -b10100011 !' -b10100011 )' -b10100011 1' -b10100011 9' -b10001110 Y' -b10001110 a' -b10001110 i' -b10100011 q' -b10100011 y' -b10100011 #( -b10100011 +( -b10100011 3( -b10100011 ;( -b10001110 [( -b10001110 c( -b10001110 k( -b10100011 s( -b10100011 {( -b10100011 %) -b10100011 -) -b10100011 5) -b10100011 =) -b10001110 ]) -b10001110 e) -b10001110 m) -b10100011 u) -b10100011 }) -b10100011 '* -b10100011 /* -b10100011 7* -b10100011 ?* -b10001110 _* -b10001110 g* -b10001110 o* -b10100011 w* -b10100011 !+ -b10100011 )+ -b10100011 1+ -b10100011 9+ -b10100011 A+ -b10001110 a+ -b10001110 i+ -b10001110 q+ -b10100011 y+ -b10100011 #, -b10100011 +, -b10100011 3, -b10100011 ;, -b10100011 C, -b10100011 K, -b00000000000000000000000010001110 S, -b00000000000000000000000010100011 [, -b00000000000000000000000010100011 c, -b10100011 k, -b10001110100011101010001110100011 s, -b10100011 {, -b10001110100011101010001110100011 %- -b10100011 -- -b10001110100011101010001110100011 5- -b10100011 =- -b10001110100011101010001110100011 E- -b10100011 M- -b10100011 N- -b10100011 O- -b10100011 P- -b10100011 Q- -b10100011 R- -b10100011 S- -b10100011 T- -b10100011 U- -b10100011 7. -b10100011 ?. -b10100011 G. -b10001110 g. -b10001110 o. -b10001110 w. -b10100011 !/ -b10100011 )/ -b10100011 1/ -b10100011 9/ -b10100011 A/ -b10001110 a/ -b10001110 i/ -b10001110 q/ -b10100011 y/ -b10100011 #0 -b10100011 +0 -b10100011 30 -b10100011 ;0 -b10100011 C0 -1K0 -0S0 -1[0 -0s0 -0/1 -121 -031 -141 -0o1 -1r1 -0s1 -1t1 -1o2 +b10100011 0" +b10001110 4" +b10001110 5" +b10001110 6" +b10100011 7" +b10100011 8" +b10100011 9" +b10100011 :" +b10100011 ;" +b10100011 <" +1=" +0>" +1?" +0B" +0G" +1J" +0K" +1L" +0O" +1R" +0S" +1T" +1U" #25 -0o2 +0U" #30 -b011 s -b11010001 { -b01000111 %! -b11010001 -! -b11010001 5! -b11010001 =! -b11010001 E! -b11010001 M! -b01000111 U! -b11010001 ]! -b11010001 e! -b11010001 m! -b11010001 u! -b11010001 }! -b11010001 '" -b11010001 /" -b01000111 O" -b01000111 W" -b01000111 _" -b11010001 g" -b11010001 o" -b11010001 w" -b11010001 !# -b11010001 )# -b11010001 1# -b01000111 Q# -b01000111 Y# -b01000111 a# -b11010001 i# -b11010001 q# -b11010001 y# -b11010001 #$ -b11010001 +$ -b11010001 3$ -b01000111 S$ -b01000111 [$ -b01000111 c$ -b11010001 k$ -b11010001 s$ -b11010001 {$ -b11010001 %% -b11010001 -% -b11010001 5% -b01000111 U% -b01000111 ]% -b01000111 e% -b11010001 m% -b11010001 u% -b11010001 }% -b11010001 '& -b11010001 /& -b11010001 7& -b01000111 W& -b01000111 _& -b01000111 g& -b11010001 o& -b11010001 w& -b11010001 !' -b11010001 )' -b11010001 1' -b11010001 9' -b01000111 Y' -b01000111 a' -b01000111 i' -b11010001 q' -b11010001 y' -b11010001 #( -b11010001 +( -b11010001 3( -b11010001 ;( -b01000111 [( -b01000111 c( -b01000111 k( -b11010001 s( -b11010001 {( -b11010001 %) -b11010001 -) -b11010001 5) -b11010001 =) -b01000111 ]) -b01000111 e) -b01000111 m) -b11010001 u) -b11010001 }) -b11010001 '* -b11010001 /* -b11010001 7* -b11010001 ?* -b01000111 _* -b01000111 g* -b01000111 o* -b11010001 w* -b11010001 !+ -b11010001 )+ -b11010001 1+ -b11010001 9+ -b11010001 A+ -b01000111 a+ -b01000111 i+ -b01000111 q+ -b11010001 y+ -b11010001 #, -b11010001 +, -b11010001 3, -b11010001 ;, -b11010001 C, -b11010001 K, -b00000000000000000000000001000111 S, -b00000000000000000000000011010001 [, -b00000000000000000000000011010001 c, -b11010001 k, -b10001110010001111101000111010001 s, -b11010001 {, -b10001110010001111101000111010001 %- -b11010001 -- -b10001110010001111101000111010001 5- -b11010001 =- -b10001110010001111101000111010001 E- -b11010001 M- -b11010001 N- -b11010001 O- -b11010001 P- -b11010001 Q- -b11010001 R- -b11010001 S- -b11010001 T- -b11010001 U- -b11010001 7. -b11010001 ?. -b11010001 G. -b01000111 g. -b01000111 o. -b01000111 w. -b11010001 !/ -b11010001 )/ -b11010001 1/ -b11010001 9/ -b11010001 A/ -b01000111 a/ -b01000111 i/ -b01000111 q/ -b11010001 y/ -b11010001 #0 -b11010001 +0 -b11010001 30 -b11010001 ;0 -b11010001 C0 -1S0 -0[0 -1c0 -0{0 -0.1 -111 -021 -131 -0n1 -1q1 -0r1 -1s1 -1o2 -#35 -0o2 -#40 -b100 s -b11101000 { -b10001110 %! -b10001110 -! -b11101000 5! -b11101000 =! -b10001110 E! -b11101000 M! -b10001110 U! -b10001110 ]! -b10001110 e! -b10001110 m! -b10001110 u! -b11101000 }! -b11101000 '" -b11101000 /" -b10001110 O" -b10001110 W" -b10001110 _" -b10001110 g" -b10001110 o" -b10001110 w" -b11101000 !# -b11101000 )# -b11101000 1# -b10001110 Q# -b10001110 Y# -b10001110 a# -b10001110 i# -b10001110 q# -b10001110 y# -b11101000 #$ -b11101000 +$ -b11101000 3$ -b10001110 S$ -b10001110 [$ -b10001110 c$ -b10001110 k$ -b10001110 s$ -b10001110 {$ -b11101000 %% -b11101000 -% -b11101000 5% -b10001110 U% -b10001110 ]% -b10001110 e% -b10001110 m% -b10001110 u% -b10001110 }% -b11101000 '& -b11101000 /& -b11101000 7& -b10001110 W& -b10001110 _& -b10001110 g& -b10001110 o& -b10001110 w& -b10001110 !' -b11101000 )' -b11101000 1' -b11101000 9' -b10001110 Y' -b10001110 a' -b10001110 i' -b10001110 q' -b10001110 y' -b10001110 #( -b11101000 +( -b11101000 3( -b11101000 ;( -b10001110 [( -b10001110 c( -b10001110 k( -b10001110 s( -b10001110 {( -b10001110 %) -b11101000 -) -b11101000 5) -b11101000 =) -b10001110 ]) -b10001110 e) -b10001110 m) -b10001110 u) -b10001110 }) -b10001110 '* -b11101000 /* -b11101000 7* -b11101000 ?* -b10001110 _* -b10001110 g* -b10001110 o* -b10001110 w* -b10001110 !+ -b10001110 )+ -b11101000 1+ -b11101000 9+ -b11101000 A+ -b10001110 a+ -b10001110 i+ -b10001110 q+ -b10001110 y+ -b10001110 #, -b10001110 +, -b11101000 3, -b11101000 ;, -b11101000 C, -b11101000 K, -b00000000000000000000000010001110 S, -b00000000000000000000000010001110 [, -b00000000000000000000000011101000 c, -b11101000 k, -b10001110100011101000111011101000 s, -b11101000 {, -b10001110100011101000111011101000 %- -b11101000 -- -b10001110100011101000111011101000 5- -b11101000 =- -b10001110100011101000111011101000 E- -b11101000 M- -b11101000 N- -b11101000 O- -b11101000 P- -b11101000 Q- -b11101000 R- -b11101000 S- -b11101000 T- -b11101000 U- -b11101000 7. -b11101000 ?. -b11101000 G. -b10001110 g. -b10001110 o. -b10001110 w. -b10001110 !/ -b10001110 )/ -b10001110 1/ -b11101000 9/ -b11101000 A/ -b10001110 a/ -b10001110 i/ -b10001110 q/ -b10001110 y/ -b10001110 #0 -b10001110 +0 -b11101000 30 -b11101000 ;0 -b11101000 C0 -1[0 -0c0 -1k0 -0%1 -0-1 -101 -011 -121 -0m1 -1p1 -0q1 -1r1 -1o2 -#45 -0o2 -#50 -b101 s -b01110100 { -b01000111 %! +b011 - +b11010001 0 +b01000111 1 +b11010001 2 +b11010001 3 +b11010001 4 +b11010001 5 +b11010001 6 +b01000111 7 +b11010001 8 +b11010001 9 +b11010001 : +b11010001 ; +b11010001 < +b11010001 = +b11010001 > +b01000111 B +b01000111 C +b01000111 D +b11010001 E +b11010001 F +b11010001 G +b11010001 H +b11010001 I +b11010001 J +b01000111 N +b01000111 O +b01000111 P +b11010001 Q +b11010001 R +b11010001 S +b11010001 T +b11010001 U +b11010001 V +b01000111 Z +b01000111 [ +b01000111 \ +b11010001 ] +b11010001 ^ +b11010001 _ +b11010001 ` +b11010001 a +b11010001 b +b01000111 f +b01000111 g +b01000111 h +b11010001 i +b11010001 j +b11010001 k +b11010001 l +b11010001 m +b11010001 n +b01000111 r +b01000111 s +b01000111 t +b11010001 u +b11010001 v +b11010001 w +b11010001 x +b11010001 y +b11010001 z +b01000111 ~ +b01000111 !! +b01000111 "! +b11010001 #! +b11010001 $! +b11010001 %! +b11010001 &! +b11010001 '! +b11010001 (! +b01000111 ,! b01000111 -! -b01110100 5! -b01110100 =! +b01000111 .! +b11010001 /! +b11010001 0! +b11010001 1! +b11010001 2! +b11010001 3! +b11010001 4! +b01000111 8! +b01000111 9! +b01000111 :! +b11010001 ;! +b11010001 ! +b11010001 ?! +b11010001 @! +b01000111 D! b01000111 E! -b01110100 M! -b01000111 U! -b01000111 ]! -b01000111 e! -b01000111 m! -b01000111 u! -b01110100 }! -b01110100 '" -b01110100 /" -b01000111 O" -b01000111 W" -b01000111 _" -b01000111 g" -b01000111 o" -b01000111 w" -b01110100 !# -b01110100 )# -b01110100 1# -b01000111 Q# -b01000111 Y# -b01000111 a# -b01000111 i# -b01000111 q# -b01000111 y# -b01110100 #$ -b01110100 +$ -b01110100 3$ -b01000111 S$ -b01000111 [$ -b01000111 c$ -b01000111 k$ -b01000111 s$ -b01000111 {$ -b01110100 %% -b01110100 -% -b01110100 5% -b01000111 U% -b01000111 ]% -b01000111 e% -b01000111 m% -b01000111 u% -b01000111 }% -b01110100 '& -b01110100 /& -b01110100 7& -b01000111 W& -b01000111 _& -b01000111 g& -b01000111 o& -b01000111 w& -b01000111 !' -b01110100 )' -b01110100 1' -b01110100 9' -b01000111 Y' -b01000111 a' -b01000111 i' -b01000111 q' -b01000111 y' -b01000111 #( -b01110100 +( -b01110100 3( -b01110100 ;( -b01000111 [( -b01000111 c( -b01000111 k( -b01000111 s( -b01000111 {( -b01000111 %) -b01110100 -) -b01110100 5) -b01110100 =) -b01000111 ]) -b01000111 e) -b01000111 m) -b01000111 u) -b01000111 }) -b01000111 '* -b01110100 /* -b01110100 7* -b01110100 ?* -b01000111 _* -b01000111 g* -b01000111 o* -b01000111 w* -b01000111 !+ -b01000111 )+ -b01110100 1+ -b01110100 9+ -b01110100 A+ -b01000111 a+ -b01000111 i+ -b01000111 q+ -b01000111 y+ -b01000111 #, -b01000111 +, -b01110100 3, -b01110100 ;, -b01110100 C, -b01110100 K, -b00000000000000000000000001000111 S, -b00000000000000000000000001000111 [, -b00000000000000000000000001110100 c, -b01110100 k, -b10001110010001110100011101110100 s, -b01110100 {, -b10001110010001110100011101110100 %- -b01110100 -- -b10001110010001110100011101110100 5- -b01110100 =- -b10001110010001110100011101110100 E- -b01110100 M- -b01110100 N- -b01110100 O- -b01110100 P- -b01110100 Q- -b01110100 R- -b01110100 S- -b01110100 T- -b01110100 U- -b01110100 7. -b01110100 ?. -b01110100 G. -b01000111 g. -b01000111 o. -b01000111 w. -b01000111 !/ -b01000111 )/ -b01000111 1/ -b01110100 9/ -b01110100 A/ -b01000111 a/ -b01000111 i/ -b01000111 q/ -b01000111 y/ -b01000111 #0 -b01000111 +0 -b01110100 30 -b01110100 ;0 -b01110100 C0 -0K0 -1c0 -0k0 -1s0 -1/1 -001 -111 -041 -1o1 -0p1 -1q1 -0t1 -1o2 -#55 -0o2 -#60 -b110 s -b00111010 { -b10001110 %! -b10100011 -! -b00111010 5! -b00111010 =! -b10100011 E! -b00111010 M! -b10001110 U! -b10100011 ]! -b10100011 e! -b10100011 m! -b10100011 u! -b00111010 }! -b00111010 '" -b00111010 /" -b10001110 O" -b10001110 W" -b10001110 _" -b10100011 g" -b10100011 o" -b10100011 w" -b00111010 !# -b00111010 )# -b00111010 1# -b10001110 Q# -b10001110 Y# -b10001110 a# -b10100011 i# -b10100011 q# -b10100011 y# -b00111010 #$ -b00111010 +$ -b00111010 3$ -b10001110 S$ -b10001110 [$ -b10001110 c$ -b10100011 k$ -b10100011 s$ -b10100011 {$ -b00111010 %% -b00111010 -% -b00111010 5% -b10001110 U% -b10001110 ]% -b10001110 e% -b10100011 m% -b10100011 u% -b10100011 }% -b00111010 '& -b00111010 /& -b00111010 7& -b10001110 W& -b10001110 _& -b10001110 g& -b10100011 o& -b10100011 w& -b10100011 !' -b00111010 )' -b00111010 1' -b00111010 9' -b10001110 Y' -b10001110 a' -b10001110 i' -b10100011 q' -b10100011 y' -b10100011 #( -b00111010 +( -b00111010 3( -b00111010 ;( -b10001110 [( -b10001110 c( -b10001110 k( -b10100011 s( -b10100011 {( -b10100011 %) -b00111010 -) -b00111010 5) -b00111010 =) -b10001110 ]) -b10001110 e) -b10001110 m) -b10100011 u) -b10100011 }) -b10100011 '* -b00111010 /* -b00111010 7* -b00111010 ?* -b10001110 _* -b10001110 g* -b10001110 o* -b10100011 w* -b10100011 !+ -b10100011 )+ -b00111010 1+ -b00111010 9+ -b00111010 A+ -b10001110 a+ -b10001110 i+ -b10001110 q+ -b10100011 y+ -b10100011 #, -b10100011 +, -b00111010 3, -b00111010 ;, -b00111010 C, -b00111010 K, -b00000000000000000000000010001110 S, -b00000000000000000000000010100011 [, -b00000000000000000000000000111010 c, -b00111010 k, -b10001110100011101010001100111010 s, -b00111010 {, -b10001110100011101010001100111010 %- -b00111010 -- -b10001110100011101010001100111010 5- -b00111010 =- -b10001110100011101010001100111010 E- -b00111010 M- -b00111010 N- -b00111010 O- -b00111010 P- -b00111010 Q- -b00111010 R- -b00111010 S- -b00111010 T- -b00111010 U- -b00111010 7. -b00111010 ?. -b00111010 G. -b10001110 g. -b10001110 o. -b10001110 w. -b10100011 !/ -b10100011 )/ -b10100011 1/ -b00111010 9/ -b00111010 A/ -b10001110 a/ -b10001110 i/ -b10001110 q/ -b10100011 y/ -b10100011 #0 -b10100011 +0 -b00111010 30 -b00111010 ;0 -b00111010 C0 -0S0 -1k0 -0s0 -1{0 -1.1 -0/1 -101 -031 -1n1 -0o1 -1p1 -0s1 -1o2 -#65 -0o2 -#70 -b111 s -b00011101 { -b01000111 %! -b11010001 -! -b00011101 5! -b00011101 =! -b11010001 E! -b00011101 M! -b01000111 U! +b01000111 F! +b11010001 G! +b11010001 H! +b11010001 I! +b11010001 J! +b11010001 K! +b11010001 L! +b01000111 P! +b01000111 Q! +b01000111 R! +b11010001 S! +b11010001 T! +b11010001 U! +b11010001 V! +b11010001 W! +b11010001 X! +b11010001 Y! +b00000000000000000000000001000111 Z! +b00000000000000000000000011010001 [! +b00000000000000000000000011010001 \! b11010001 ]! -b11010001 e! -b11010001 m! -b11010001 u! -b00011101 }! -b00011101 '" -b00011101 /" -b01000111 O" -b01000111 W" -b01000111 _" -b11010001 g" -b11010001 o" -b11010001 w" -b00011101 !# -b00011101 )# -b00011101 1# -b01000111 Q# -b01000111 Y# -b01000111 a# -b11010001 i# -b11010001 q# -b11010001 y# -b00011101 #$ -b00011101 +$ -b00011101 3$ -b01000111 S$ -b01000111 [$ -b01000111 c$ -b11010001 k$ -b11010001 s$ -b11010001 {$ -b00011101 %% -b00011101 -% -b00011101 5% -b01000111 U% -b01000111 ]% -b01000111 e% -b11010001 m% -b11010001 u% -b11010001 }% -b00011101 '& -b00011101 /& -b00011101 7& -b01000111 W& -b01000111 _& -b01000111 g& -b11010001 o& -b11010001 w& -b11010001 !' -b00011101 )' -b00011101 1' -b00011101 9' -b01000111 Y' -b01000111 a' -b01000111 i' -b11010001 q' -b11010001 y' -b11010001 #( -b00011101 +( -b00011101 3( -b00011101 ;( -b01000111 [( -b01000111 c( -b01000111 k( -b11010001 s( -b11010001 {( -b11010001 %) -b00011101 -) -b00011101 5) -b00011101 =) -b01000111 ]) -b01000111 e) -b01000111 m) -b11010001 u) -b11010001 }) -b11010001 '* -b00011101 /* -b00011101 7* -b00011101 ?* -b01000111 _* -b01000111 g* -b01000111 o* -b11010001 w* -b11010001 !+ -b11010001 )+ -b00011101 1+ -b00011101 9+ -b00011101 A+ -b01000111 a+ -b01000111 i+ -b01000111 q+ -b11010001 y+ -b11010001 #, -b11010001 +, -b00011101 3, -b00011101 ;, -b00011101 C, -b00011101 K, -b00000000000000000000000001000111 S, -b00000000000000000000000011010001 [, -b00000000000000000000000000011101 c, -b00011101 k, -b10001110010001111101000100011101 s, -b00011101 {, -b10001110010001111101000100011101 %- -b00011101 -- -b10001110010001111101000100011101 5- -b00011101 =- -b10001110010001111101000100011101 E- -b00011101 M- -b00011101 N- -b00011101 O- -b00011101 P- -b00011101 Q- -b00011101 R- -b00011101 S- -b00011101 T- -b00011101 U- -b00011101 7. -b00011101 ?. -b00011101 G. -b01000111 g. -b01000111 o. -b01000111 w. -b11010001 !/ -b11010001 )/ -b11010001 1/ -b00011101 9/ -b00011101 A/ -b01000111 a/ -b01000111 i/ -b01000111 q/ -b11010001 y/ -b11010001 #0 -b11010001 +0 -b00011101 30 -b00011101 ;0 -b00011101 C0 -0[0 -1s0 -0{0 -1%1 -1-1 -0.1 -1/1 -021 -1m1 -0n1 -1o1 -0r1 -1o2 -#75 -0o2 -#80 -b000 s -b10001110 { +b10001110010001111101000111010001 ^! +b11010001 _! +b10001110010001111101000111010001 `! +b11010001 a! +b10001110010001111101000111010001 b! +b11010001 c! +b10001110010001111101000111010001 d! +1g! +1k! +1o! +1s! +b00000000000000000000000000000011 u! +b11010001 x! +b11010001 y! +b11010001 z! +b11010001 {! +b11010001 |! +b11010001 }! +b11010001 ~! +b11010001 !" +b11010001 "" +b11010001 #" +b11010001 $" +b11010001 %" +b01000111 )" +b01000111 *" +b01000111 +" +b11010001 ," +b11010001 -" +b11010001 ." +b11010001 /" +b11010001 0" +b01000111 4" +b01000111 5" +b01000111 6" +b11010001 7" +b11010001 8" +b11010001 9" +b11010001 :" +b11010001 ;" +b11010001 <" +1>" +0?" +1@" +0C" +0F" +1I" +0J" +1K" +0N" +1Q" +0R" +1S" +1U" +#35 +0U" +#40 +b100 - +b11101000 0 +b10001110 1 +b10001110 2 +b11101000 3 +b11101000 4 +b10001110 5 +b11101000 6 +b10001110 7 +b10001110 8 +b10001110 9 +b10001110 : +b10001110 ; +b11101000 < +b11101000 = +b11101000 > +b10001110 B +b10001110 C +b10001110 D +b10001110 E +b10001110 F +b10001110 G +b11101000 H +b11101000 I +b11101000 J +b10001110 N +b10001110 O +b10001110 P +b10001110 Q +b10001110 R +b10001110 S +b11101000 T +b11101000 U +b11101000 V +b10001110 Z +b10001110 [ +b10001110 \ +b10001110 ] +b10001110 ^ +b10001110 _ +b11101000 ` +b11101000 a +b11101000 b +b10001110 f +b10001110 g +b10001110 h +b10001110 i +b10001110 j +b10001110 k +b11101000 l +b11101000 m +b11101000 n +b10001110 r +b10001110 s +b10001110 t +b10001110 u +b10001110 v +b10001110 w +b11101000 x +b11101000 y +b11101000 z +b10001110 ~ +b10001110 !! +b10001110 "! +b10001110 #! +b10001110 $! b10001110 %! +b11101000 &! +b11101000 '! +b11101000 (! +b10001110 ,! b10001110 -! -b10001110 5! +b10001110 .! +b10001110 /! +b10001110 0! +b10001110 1! +b11101000 2! +b11101000 3! +b11101000 4! +b10001110 8! +b10001110 9! +b10001110 :! +b10001110 ;! +b10001110 ! +b11101000 ?! +b11101000 @! +b10001110 D! b10001110 E! -b10001110 M! +b10001110 F! +b10001110 G! +b10001110 H! +b10001110 I! +b11101000 J! +b11101000 K! +b11101000 L! +b10001110 P! +b10001110 Q! +b10001110 R! +b10001110 S! +b10001110 T! b10001110 U! +b11101000 V! +b11101000 W! +b11101000 X! +b11101000 Y! +b00000000000000000000000010001110 Z! +b00000000000000000000000010001110 [! +b00000000000000000000000011101000 \! +b11101000 ]! +b10001110100011101000111011101000 ^! +b11101000 _! +b10001110100011101000111011101000 `! +b11101000 a! +b10001110100011101000111011101000 b! +b11101000 c! +b10001110100011101000111011101000 d! +1h! +1l! +1p! +1t! +b00000000000000000000000000000100 u! +b11101000 x! +b11101000 y! +b11101000 z! +b11101000 {! +b11101000 |! +b11101000 }! +b11101000 ~! +b11101000 !" +b11101000 "" +b11101000 #" +b11101000 $" +b11101000 %" +b10001110 )" +b10001110 *" +b10001110 +" +b10001110 ," +b10001110 -" +b10001110 ." +b11101000 /" +b11101000 0" +b10001110 4" +b10001110 5" +b10001110 6" +b10001110 7" +b10001110 8" +b10001110 9" +b11101000 :" +b11101000 ;" +b11101000 <" +1?" +0@" +1A" +0D" +0E" +1H" +0I" +1J" +0M" +1P" +0Q" +1R" +1U" +#45 +0U" +#50 +b101 - +b01110100 0 +b01000111 1 +b01000111 2 +b01110100 3 +b01110100 4 +b01000111 5 +b01110100 6 +b01000111 7 +b01000111 8 +b01000111 9 +b01000111 : +b01000111 ; +b01110100 < +b01110100 = +b01110100 > +b01000111 B +b01000111 C +b01000111 D +b01000111 E +b01000111 F +b01000111 G +b01110100 H +b01110100 I +b01110100 J +b01000111 N +b01000111 O +b01000111 P +b01000111 Q +b01000111 R +b01000111 S +b01110100 T +b01110100 U +b01110100 V +b01000111 Z +b01000111 [ +b01000111 \ +b01000111 ] +b01000111 ^ +b01000111 _ +b01110100 ` +b01110100 a +b01110100 b +b01000111 f +b01000111 g +b01000111 h +b01000111 i +b01000111 j +b01000111 k +b01110100 l +b01110100 m +b01110100 n +b01000111 r +b01000111 s +b01000111 t +b01000111 u +b01000111 v +b01000111 w +b01110100 x +b01110100 y +b01110100 z +b01000111 ~ +b01000111 !! +b01000111 "! +b01000111 #! +b01000111 $! +b01000111 %! +b01110100 &! +b01110100 '! +b01110100 (! +b01000111 ,! +b01000111 -! +b01000111 .! +b01000111 /! +b01000111 0! +b01000111 1! +b01110100 2! +b01110100 3! +b01110100 4! +b01000111 8! +b01000111 9! +b01000111 :! +b01000111 ;! +b01000111 ! +b01110100 ?! +b01110100 @! +b01000111 D! +b01000111 E! +b01000111 F! +b01000111 G! +b01000111 H! +b01000111 I! +b01110100 J! +b01110100 K! +b01110100 L! +b01000111 P! +b01000111 Q! +b01000111 R! +b01000111 S! +b01000111 T! +b01000111 U! +b01110100 V! +b01110100 W! +b01110100 X! +b01110100 Y! +b00000000000000000000000001000111 Z! +b00000000000000000000000001000111 [! +b00000000000000000000000001110100 \! +b01110100 ]! +b10001110010001110100011101110100 ^! +b01110100 _! +b10001110010001110100011101110100 `! +b01110100 a! +b10001110010001110100011101110100 b! +b01110100 c! +b10001110010001110100011101110100 d! +b00000000000000000000000000000101 u! +b01110100 x! +b01110100 y! +b01110100 z! +b01110100 {! +b01110100 |! +b01110100 }! +b01110100 ~! +b01110100 !" +b01110100 "" +b01110100 #" +b01110100 $" +b01110100 %" +b01000111 )" +b01000111 *" +b01000111 +" +b01000111 ," +b01000111 -" +b01000111 ." +b01110100 /" +b01110100 0" +b01000111 4" +b01000111 5" +b01000111 6" +b01000111 7" +b01000111 8" +b01000111 9" +b01110100 :" +b01110100 ;" +b01110100 <" +0=" +1@" +0A" +1B" +1G" +0H" +1I" +0L" +1O" +0P" +1Q" +0T" +1U" +#55 +0U" +#60 +b110 - +b00111010 0 +b10001110 1 +b10100011 2 +b00111010 3 +b00111010 4 +b10100011 5 +b00111010 6 +b10001110 7 +b10100011 8 +b10100011 9 +b10100011 : +b10100011 ; +b00111010 < +b00111010 = +b00111010 > +b10001110 B +b10001110 C +b10001110 D +b10100011 E +b10100011 F +b10100011 G +b00111010 H +b00111010 I +b00111010 J +b10001110 N +b10001110 O +b10001110 P +b10100011 Q +b10100011 R +b10100011 S +b00111010 T +b00111010 U +b00111010 V +b10001110 Z +b10001110 [ +b10001110 \ +b10100011 ] +b10100011 ^ +b10100011 _ +b00111010 ` +b00111010 a +b00111010 b +b10001110 f +b10001110 g +b10001110 h +b10100011 i +b10100011 j +b10100011 k +b00111010 l +b00111010 m +b00111010 n +b10001110 r +b10001110 s +b10001110 t +b10100011 u +b10100011 v +b10100011 w +b00111010 x +b00111010 y +b00111010 z +b10001110 ~ +b10001110 !! +b10001110 "! +b10100011 #! +b10100011 $! +b10100011 %! +b00111010 &! +b00111010 '! +b00111010 (! +b10001110 ,! +b10001110 -! +b10001110 .! +b10100011 /! +b10100011 0! +b10100011 1! +b00111010 2! +b00111010 3! +b00111010 4! +b10001110 8! +b10001110 9! +b10001110 :! +b10100011 ;! +b10100011 ! +b00111010 ?! +b00111010 @! +b10001110 D! +b10001110 E! +b10001110 F! +b10100011 G! +b10100011 H! +b10100011 I! +b00111010 J! +b00111010 K! +b00111010 L! +b10001110 P! +b10001110 Q! +b10001110 R! +b10100011 S! +b10100011 T! +b10100011 U! +b00111010 V! +b00111010 W! +b00111010 X! +b00111010 Y! +b00000000000000000000000010001110 Z! +b00000000000000000000000010100011 [! +b00000000000000000000000000111010 \! +b00111010 ]! +b10001110100011101010001100111010 ^! +b00111010 _! +b10001110100011101010001100111010 `! +b00111010 a! +b10001110100011101010001100111010 b! +b00111010 c! +b10001110100011101010001100111010 d! +b00000000000000000000000000000110 u! +b00111010 x! +b00111010 y! +b00111010 z! +b00111010 {! +b00111010 |! +b00111010 }! +b00111010 ~! +b00111010 !" +b00111010 "" +b00111010 #" +b00111010 $" +b00111010 %" +b10001110 )" +b10001110 *" +b10001110 +" +b10100011 ," +b10100011 -" +b10100011 ." +b00111010 /" +b00111010 0" +b10001110 4" +b10001110 5" +b10001110 6" +b10100011 7" +b10100011 8" +b10100011 9" +b00111010 :" +b00111010 ;" +b00111010 <" +0>" +1A" +0B" +1C" +1F" +0G" +1H" +0K" +1N" +0O" +1P" +0S" +1U" +#65 +0U" +#70 +b111 - +b00011101 0 +b01000111 1 +b11010001 2 +b00011101 3 +b00011101 4 +b11010001 5 +b00011101 6 +b01000111 7 +b11010001 8 +b11010001 9 +b11010001 : +b11010001 ; +b00011101 < +b00011101 = +b00011101 > +b01000111 B +b01000111 C +b01000111 D +b11010001 E +b11010001 F +b11010001 G +b00011101 H +b00011101 I +b00011101 J +b01000111 N +b01000111 O +b01000111 P +b11010001 Q +b11010001 R +b11010001 S +b00011101 T +b00011101 U +b00011101 V +b01000111 Z +b01000111 [ +b01000111 \ +b11010001 ] +b11010001 ^ +b11010001 _ +b00011101 ` +b00011101 a +b00011101 b +b01000111 f +b01000111 g +b01000111 h +b11010001 i +b11010001 j +b11010001 k +b00011101 l +b00011101 m +b00011101 n +b01000111 r +b01000111 s +b01000111 t +b11010001 u +b11010001 v +b11010001 w +b00011101 x +b00011101 y +b00011101 z +b01000111 ~ +b01000111 !! +b01000111 "! +b11010001 #! +b11010001 $! +b11010001 %! +b00011101 &! +b00011101 '! +b00011101 (! +b01000111 ,! +b01000111 -! +b01000111 .! +b11010001 /! +b11010001 0! +b11010001 1! +b00011101 2! +b00011101 3! +b00011101 4! +b01000111 8! +b01000111 9! +b01000111 :! +b11010001 ;! +b11010001 ! +b00011101 ?! +b00011101 @! +b01000111 D! +b01000111 E! +b01000111 F! +b11010001 G! +b11010001 H! +b11010001 I! +b00011101 J! +b00011101 K! +b00011101 L! +b01000111 P! +b01000111 Q! +b01000111 R! +b11010001 S! +b11010001 T! +b11010001 U! +b00011101 V! +b00011101 W! +b00011101 X! +b00011101 Y! +b00000000000000000000000001000111 Z! +b00000000000000000000000011010001 [! +b00000000000000000000000000011101 \! +b00011101 ]! +b10001110010001111101000100011101 ^! +b00011101 _! +b10001110010001111101000100011101 `! +b00011101 a! +b10001110010001111101000100011101 b! +b00011101 c! +b10001110010001111101000100011101 d! +b00000000000000000000000000000111 u! +b00011101 x! +b00011101 y! +b00011101 z! +b00011101 {! +b00011101 |! +b00011101 }! +b00011101 ~! +b00011101 !" +b00011101 "" +b00011101 #" +b00011101 $" +b00011101 %" +b01000111 )" +b01000111 *" +b01000111 +" +b11010001 ," +b11010001 -" +b11010001 ." +b00011101 /" +b00011101 0" +b01000111 4" +b01000111 5" +b01000111 6" +b11010001 7" +b11010001 8" +b11010001 9" +b00011101 :" +b00011101 ;" +b00011101 <" +0?" +1B" +0C" +1D" +1E" +0F" +1G" +0J" +1M" +0N" +1O" +0R" +1U" +#75 +0U" +#80 +b000 - +b10001110 0 +b10001110 1 +b10001110 2 +b10001110 3 +b10001110 4 +b10001110 5 +b10001110 6 +b10001110 7 +b10001110 8 +b10001110 9 +b10001110 : +b10001110 ; +b10001110 < +b10001110 = +b10001110 > +b10001110 B +b10001110 C +b10001110 D +b10001110 E +b10001110 F +b10001110 G +b10001110 H +b10001110 I +b10001110 J +b10001110 N +b10001110 O +b10001110 P +b10001110 Q +b10001110 R +b10001110 S +b10001110 T +b10001110 U +b10001110 V +b10001110 Z +b10001110 [ +b10001110 \ +b10001110 ] +b10001110 ^ +b10001110 _ +b10001110 ` +b10001110 a +b10001110 b +b10001110 f +b10001110 g +b10001110 h +b10001110 i +b10001110 j +b10001110 k +b10001110 l +b10001110 m +b10001110 n +b10001110 r +b10001110 s +b10001110 t +b10001110 u +b10001110 v +b10001110 w +b10001110 x +b10001110 y +b10001110 z +b10001110 ~ +b10001110 !! +b10001110 "! +b10001110 #! +b10001110 $! +b10001110 %! +b10001110 &! +b10001110 '! +b10001110 (! +b10001110 ,! +b10001110 -! +b10001110 .! +b10001110 /! +b10001110 0! +b10001110 1! +b10001110 2! +b10001110 3! +b10001110 4! +b10001110 8! +b10001110 9! +b10001110 :! +b10001110 ;! +b10001110 ! +b10001110 ?! +b10001110 @! +b10001110 D! +b10001110 E! +b10001110 F! +b10001110 G! +b10001110 H! +b10001110 I! +b10001110 J! +b10001110 K! +b10001110 L! +b10001110 P! +b10001110 Q! +b10001110 R! +b10001110 S! +b10001110 T! +b10001110 U! +b10001110 V! +b10001110 W! +b10001110 X! +b10001110 Y! +b00000000000000000000000010001110 Z! +b00000000000000000000000010001110 [! +b00000000000000000000000010001110 \! b10001110 ]! -b10001110 e! -b10001110 m! -b10001110 u! +b10001110100011101000111010001110 ^! +b10001110 _! +b10001110100011101000111010001110 `! +b10001110 a! +b10001110100011101000111010001110 b! +b10001110 c! +b10001110100011101000111010001110 d! +b00000000000000000000000000001000 u! +b10001110 x! +b10001110 y! +b10001110 z! +b10001110 {! +b10001110 |! b10001110 }! -b10001110 '" +b10001110 ~! +b10001110 !" +b10001110 "" +b10001110 #" +b10001110 $" +b10001110 %" +b10001110 )" +b10001110 *" +b10001110 +" +b10001110 ," +b10001110 -" +b10001110 ." b10001110 /" -b10001110 O" -b10001110 W" -b10001110 _" -b10001110 g" -b10001110 o" -b10001110 w" -b10001110 !# -b10001110 )# -b10001110 1# -b10001110 Q# -b10001110 Y# -b10001110 a# -b10001110 i# -b10001110 q# -b10001110 y# -b10001110 #$ -b10001110 +$ -b10001110 3$ -b10001110 S$ -b10001110 [$ -b10001110 c$ -b10001110 k$ -b10001110 s$ -b10001110 {$ -b10001110 %% -b10001110 -% -b10001110 5% -b10001110 U% -b10001110 ]% -b10001110 e% -b10001110 m% -b10001110 u% -b10001110 }% -b10001110 '& -b10001110 /& -b10001110 7& -b10001110 W& -b10001110 _& -b10001110 g& -b10001110 o& -b10001110 w& -b10001110 !' -b10001110 )' -b10001110 1' -b10001110 9' -b10001110 Y' -b10001110 a' -b10001110 i' -b10001110 q' -b10001110 y' -b10001110 #( -b10001110 +( -b10001110 3( -b10001110 ;( -b10001110 [( -b10001110 c( -b10001110 k( -b10001110 s( -b10001110 {( -b10001110 %) -b10001110 -) -b10001110 5) -b10001110 =) -b10001110 ]) -b10001110 e) -b10001110 m) -b10001110 u) -b10001110 }) -b10001110 '* -b10001110 /* -b10001110 7* -b10001110 ?* -b10001110 _* -b10001110 g* -b10001110 o* -b10001110 w* -b10001110 !+ -b10001110 )+ -b10001110 1+ -b10001110 9+ -b10001110 A+ -b10001110 a+ -b10001110 i+ -b10001110 q+ -b10001110 y+ -b10001110 #, -b10001110 +, -b10001110 3, -b10001110 ;, -b10001110 C, -b10001110 K, -b00000000000000000000000010001110 S, -b00000000000000000000000010001110 [, -b00000000000000000000000010001110 c, -b10001110 k, -b10001110100011101000111010001110 s, -b10001110 {, -b10001110100011101000111010001110 %- -b10001110 -- -b10001110100011101000111010001110 5- -b10001110 =- -b10001110100011101000111010001110 E- -b10001110 M- -b10001110 N- -b10001110 O- -b10001110 P- -b10001110 Q- -b10001110 R- -b10001110 S- -b10001110 T- -b10001110 U- -b10001110 7. -b10001110 ?. -b10001110 G. -b10001110 g. -b10001110 o. -b10001110 w. -b10001110 !/ -b10001110 )/ -b10001110 1/ -b10001110 9/ -b10001110 A/ -b10001110 a/ -b10001110 i/ -b10001110 q/ -b10001110 y/ -b10001110 #0 -b10001110 +0 -b10001110 30 -b10001110 ;0 -b10001110 C0 -1K0 -0c0 -1{0 -0%1 -0-1 -1.1 -011 -141 -0m1 -1n1 -0q1 -1t1 -1o2 +b10001110 0" +b10001110 4" +b10001110 5" +b10001110 6" +b10001110 7" +b10001110 8" +b10001110 9" +b10001110 :" +b10001110 ;" +b10001110 <" +1=" +0@" +1C" +0D" +0E" +1F" +0I" +1L" +0M" +1N" +0Q" +1T" +1U" diff --git a/test_regress/t/t_split_var_2_trace.pl b/test_regress/t/t_split_var_2_trace.pl index 959d96d7c..49fd37f82 100755 --- a/test_regress/t/t_split_var_2_trace.pl +++ b/test_regress/t/t_split_var_2_trace.pl @@ -25,7 +25,7 @@ execute( vcd_identical("$Self->{obj_dir}/simx.vcd", $Self->{golden_filename}); file_grep($Self->{stats}, qr/SplitVar,\s+Split packed variables\s+(\d+)/i, 12); -file_grep($Self->{stats}, qr/SplitVar,\s+Split unpacked arrays\s+(\d+)/i, 23); +file_grep($Self->{stats}, qr/SplitVar,\s+Split unpacked arrays\s+(\d+)/i, 27); ok(1); 1; diff --git a/test_regress/t/t_stable.v b/test_regress/t/t_stable.v deleted file mode 100644 index 9b9a831b7..000000000 --- a/test_regress/t/t_stable.v +++ /dev/null @@ -1,81 +0,0 @@ -// DESCRIPTION: Verilator: Verilog Test module -// -// This file ONLY is placed into the Public Domain, for any use, -// without warranty, 2020 by Peter Monsson. - -module t (/*AUTOARG*/ - // Inputs - clk - ); - - input clk; - integer cyc; initial cyc=1; - wire [31:0] in = cyc; - - Test test (/*AUTOINST*/ - // Inputs - .clk (clk), - .in (in[31:0])); - - Test2 test2 (/*AUTOINST*/ - // Inputs - .clk (clk), - .in (in[31:0])); - - - always @ (posedge clk) begin - if (cyc!=0) begin - cyc <= cyc + 1; - if (cyc==10) begin - $write("*-* All Finished *-*\n"); - $finish; - end - end - end - -endmodule - -module Test (/*AUTOARG*/ - // Inputs - clk, in - ); - - input clk; - input [31:0] in; - - reg [31:0] dly0 = -1; - - // If called in an assertion, sequence, or property, the appropriate clocking event. - // Otherwise, if called in a disable condition or a clock expression in an assertion, sequence, or prop, explicit. - // Otherwise, if called in an action block of an assertion, the leading clock of the assertion is used. - // Otherwise, if called in a procedure, the inferred clock - // Otherwise, default clocking - - always @(posedge clk) begin - dly0 <= in; - // In clock expression - $write("dly0=%0d, in=%0d, stable=%0d, past=%0d\n", dly0, in, $stable(dly0), $past(dly0)); - if ($stable(dly0)) $stop; - end - - assert property (@(posedge clk) !$stable(dly0)); -endmodule - -module Test2 (/*AUTOARG*/ - // Inputs - clk, in - ); - - input clk; - input [31:0] in; - - reg [31:0] dly0; - - always @(posedge clk) begin - dly0 <= in; - if (!$stable(dly0[31:4])) $stop; - end - - default clocking @(posedge clk); endclocking - assert property ($stable(dly0[31:4])); -endmodule diff --git a/test_regress/t/t_sys_rand_seed.out b/test_regress/t/t_sys_rand_seed.out index c227b2acd..a9ae64425 100644 --- a/test_regress/t/t_sys_rand_seed.out +++ b/test_regress/t/t_sys_rand_seed.out @@ -4,4 +4,10 @@ %Error-UNSUPPORTED: t/t_sys_rand_seed.v:14:16: Unsupported: Seed on $random. Suggest use +verilator+seed+ runtime flag 14 | valueb = $random(10); | ^~~~~~~ +%Error-UNSUPPORTED: t/t_sys_rand_seed.v:16:16: Unsupported: Seed on $urandom. Suggest use +verilator+seed+ runtime flag + 16 | valuea = $urandom(10); + | ^~~~~~~~ +%Error-UNSUPPORTED: t/t_sys_rand_seed.v:17:16: Unsupported: Seed on $urandom. Suggest use +verilator+seed+ runtime flag + 17 | valueb = $urandom(10); + | ^~~~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_sys_rand_seed.v b/test_regress/t/t_sys_rand_seed.v index 2780345a3..53dc8eee5 100644 --- a/test_regress/t/t_sys_rand_seed.v +++ b/test_regress/t/t_sys_rand_seed.v @@ -13,6 +13,9 @@ module t; valuea = $random(10); valueb = $random(10); if (valuea !== valueb) $stop; + valuea = $urandom(10); + valueb = $urandom(10); + if (valuea !== valueb) $stop; $write("*-* All Finished *-*\n"); $finish; end diff --git a/test_regress/t/t_timescale_parse.cpp b/test_regress/t/t_timescale_parse.cpp index c77eebde1..eb9fcc18a 100644 --- a/test_regress/t/t_timescale_parse.cpp +++ b/test_regress/t/t_timescale_parse.cpp @@ -5,7 +5,7 @@ #include "Vt_timescale_parse.h" -VM_PREFIX* tb = NULL; +VM_PREFIX* tb = nullptr; double sc_time_stamp() { return 2 * 1e9; // e.g. 2 seconds in ns units diff --git a/test_regress/t/t_trace_two_sc.cpp b/test_regress/t/t_trace_two_sc.cpp index 21a7a954b..66e145145 100644 --- a/test_regress/t/t_trace_two_sc.cpp +++ b/test_regress/t/t_trace_two_sc.cpp @@ -48,19 +48,11 @@ int sc_main(int argc, char** argv) { #endif { clk = false; -#if (SYSTEMC_VERSION>=20070314) sc_start(10, SC_NS); -#else - sc_start(10); -#endif } while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) { clk = !clk; -#if (SYSTEMC_VERSION>=20070314) sc_start(5, SC_NS); -#else - sc_start(5); -#endif } if (!Verilated::gotFinish()) { vl_fatal(__FILE__, __LINE__, "main", "%Error: Timeout; never got a $finish"); diff --git a/test_regress/t/t_tri_gate.cpp b/test_regress/t/t_tri_gate.cpp index 8a6cce86a..6b1c881a6 100644 --- a/test_regress/t/t_tri_gate.cpp +++ b/test_regress/t/t_tri_gate.cpp @@ -6,7 +6,7 @@ #include VM_PREFIX_INCLUDE -VM_PREFIX* tb = NULL; +VM_PREFIX* tb = nullptr; double sc_time_stamp() { return 0; } diff --git a/test_regress/t/t_tri_inout.cpp b/test_regress/t/t_tri_inout.cpp index c9c591cb7..bd0cb1426 100644 --- a/test_regress/t/t_tri_inout.cpp +++ b/test_regress/t/t_tri_inout.cpp @@ -6,7 +6,7 @@ #include "Vt_tri_inout.h" -Vt_tri_inout* tb = NULL; +VM_PREFIX* tb = nullptr; double sc_time_stamp() { return 0; } diff --git a/test_regress/t/t_tri_inz.cpp b/test_regress/t/t_tri_inz.cpp index a2674bda5..752274f44 100644 --- a/test_regress/t/t_tri_inz.cpp +++ b/test_regress/t/t_tri_inz.cpp @@ -5,7 +5,7 @@ #include "Vt_tri_inz.h" -Vt_tri_inz* tb = NULL; +VM_PREFIX* tb = nullptr; bool pass = true; double sc_time_stamp() { return 0; } diff --git a/test_regress/t/t_tri_pullup.cpp b/test_regress/t/t_tri_pullup.cpp index 4906ed218..7885093fd 100644 --- a/test_regress/t/t_tri_pullup.cpp +++ b/test_regress/t/t_tri_pullup.cpp @@ -6,7 +6,7 @@ #include "Vt_tri_pullup.h" -Vt_tri_pullup* tb = NULL; +VM_PREFIX* tb = nullptr; double sc_time_stamp() { return 0; } diff --git a/test_regress/t/t_tri_select.cpp b/test_regress/t/t_tri_select.cpp index 6e76584e9..d034b85f9 100644 --- a/test_regress/t/t_tri_select.cpp +++ b/test_regress/t/t_tri_select.cpp @@ -5,7 +5,7 @@ #include "Vt_tri_select.h" -Vt_tri_select* tb = NULL; +VM_PREFIX* tb = nullptr; double sc_time_stamp() { return 0; } diff --git a/test_regress/t/t_unpacked_slice_range.pl b/test_regress/t/t_unpacked_slice_range.pl new file mode 100755 index 000000000..b46d46042 --- /dev/null +++ b/test_regress/t/t_unpacked_slice_range.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_unpacked_slice_range.v b/test_regress/t/t_unpacked_slice_range.v new file mode 100644 index 000000000..58c1bc6a1 --- /dev/null +++ b/test_regress/t/t_unpacked_slice_range.v @@ -0,0 +1,63 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2020 by Yutetsu TAKATSUKASA + +module t ( + clk + ); + input clk; + + int c = 0; + + t2 #(0) i_0(.*); + t2 #(-1) i_1(.*); // lo is -1, hi is 5 + t2 #(-4) i_2(.*); // lo is -4, hi is 1 + t2 #(-10) i_3(.*); // lo is -10, hi is -4 + t2 #(+1) i_4(.*); // lo is 1, hi is 7 + t2 #(+4) i_5(.*); // lo is 4, hi is 10 + t2 #(+10) i_6(.*); // lo is 10, hi is 16 + + always @(posedge clk) begin + c <= c + 1; + if (c == 5) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule + +module t2 #(parameter ORIGIN = 0) (input wire clk, input int c); + localparam WIDTH = 7; + localparam OFFSET = 3; + localparam FULL_LO = ORIGIN; + localparam FULL_HI = ORIGIN + WIDTH - 1; + localparam PART_LO = FULL_LO + OFFSET; + localparam PART_HI = FULL_HI; + logic unpack_sig0 [FULL_LO:FULL_HI]; + logic unpack_sig1 [PART_LO:PART_HI]; + logic unpack_sig2 [FULL_HI:FULL_LO]; + logic unpack_sig3 [PART_HI:PART_LO]; + initial $display("%m ORIGIN:%d [%d:%d] [%d:%d]", ORIGIN, FULL_LO, FULL_HI, PART_LO, PART_HI); + + always @(posedge clk) begin + unpack_sig0[PART_LO] <= 1'b1; + unpack_sig1[PART_LO] <= 1'b1; + unpack_sig0 [PART_LO+1:FULL_HI] <= unpack_sig0[PART_LO:FULL_HI-1]; + unpack_sig1 [PART_LO+1:PART_HI] <= unpack_sig1[PART_LO:PART_HI-1]; + unpack_sig2[PART_LO] <= 1'b1; + unpack_sig3[PART_LO] <= 1'b1; + unpack_sig2 [FULL_HI:PART_LO+1] <= unpack_sig2[FULL_HI-1:PART_LO]; + unpack_sig3 [PART_HI:PART_LO+1] <= unpack_sig3[PART_HI-1:PART_LO]; + end + + always @(posedge clk) begin + if (c >= 4) begin + if (!unpack_sig0[FULL_HI] || !unpack_sig1[PART_HI]) $stop; + if (!unpack_sig2[FULL_HI] || !unpack_sig3[PART_HI]) $stop; + end else begin + if (unpack_sig0[FULL_HI] || unpack_sig1[PART_HI]) $stop; + if (unpack_sig2[FULL_HI] || unpack_sig3[PART_HI]) $stop; + end + end +endmodule diff --git a/test_regress/t/t_urandom.pl b/test_regress/t/t_urandom.pl new file mode 100755 index 000000000..aabcde63e --- /dev/null +++ b/test_regress/t/t_urandom.pl @@ -0,0 +1,21 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 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 + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_urandom.v b/test_regress/t/t_urandom.v new file mode 100644 index 000000000..3bb04f64f --- /dev/null +++ b/test_regress/t/t_urandom.v @@ -0,0 +1,79 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +// Methods defined by IEEE: +// function int unsigned $urandom [ (int seed ) ] ; +// function int unsigned $urandom_range( int unsigned maxval, +// int unsigned minval = 0 ); + +module t(/*AUTOARG*/); +`ifndef VERILATOR + `define PROC +`endif +`ifdef PROC + process p; +`endif + + int unsigned v1; + int unsigned v2; + int unsigned v3; + string s; + + initial begin +`ifdef PROC + if (p != null) $stop; + p = process::self(); +`endif + + v1 = $urandom; + v2 = $urandom; + v3 = $urandom(); + if (v1 == v2 && v1 == v3) $stop; // Possible, but 2^-64 + + // Range + for (int test = 0; test < 20; ++test) begin + v1 = $urandom_range(0, 2); + if (v1 != 0 && v1 != 1) $stop; + v1 = $urandom_range(2, 0); + if (v1 != 0 && v1 != 1) $stop; + end + +`ifndef VERILATOR + // Seed stability + // Note UVM doesn't use $urandom seeding + v1 = $urandom(1); + v2 = $urandom(1); + if (v1 != v2) $stop; + v2 = $urandom(1); + if (v1 != v2) $stop; +`endif + +`ifdef PROC + // Seed stability via process.srandom + p.srandom(1); + v1 = $urandom(); + p.srandom(1); + v2 = $urandom(); + if (v1 != v2) $stop; + p.srandom(1); + v2 = $urandom(); + if (v1 != v2) $stop; + + // Seed stability via process.get_randstate + s = p.get_randstate(); + v1 = $urandom(); + p.set_randstate(s); + v2 = $urandom(); + if (v1 != v2) $stop; + p.set_randstate(s); + v2 = $urandom(); + if (v1 != v2) $stop; +`endif + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_var_pinsizes.cpp b/test_regress/t/t_var_pinsizes.cpp index 3b74de365..32624893c 100644 --- a/test_regress/t/t_var_pinsizes.cpp +++ b/test_regress/t/t_var_pinsizes.cpp @@ -5,7 +5,7 @@ #include VM_PREFIX_INCLUDE -VM_PREFIX* tb = NULL; +VM_PREFIX* tb = nullptr; double sc_time_stamp() { return 0; } diff --git a/test_regress/t/t_vpi_sc.cpp b/test_regress/t/t_vpi_sc.cpp index e6be1c64b..6cdf5adf9 100644 --- a/test_regress/t/t_vpi_sc.cpp +++ b/test_regress/t/t_vpi_sc.cpp @@ -5,7 +5,7 @@ #include "Vt_vpi_sc.h" -VM_PREFIX* tb = NULL; +VM_PREFIX* tb = nullptr; int sc_main(int argc, char* argv[]) { tb = new VM_PREFIX("tb"); diff --git a/verilator-config.cmake.in b/verilator-config.cmake.in index b13b32301..68c187e41 100644 --- a/verilator-config.cmake.in +++ b/verilator-config.cmake.in @@ -312,12 +312,7 @@ function(verilate TARGET) "$<$>:${VERILATOR_MT_CFLAGS}>" ) - # SystemC requires the C++ version to match the library version, avoid setting anything here - set(GEN_THREADED $>) - set(GEN_SYSTEMC $>) - target_compile_features(${TARGET} PRIVATE - $<$>:cxx_std_11> - ) + target_compile_features(${TARGET} PRIVATE cxx_std_11) endfunction() function(_verilator_find_systemc)