diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 073721400..6e504dcfa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -29,7 +29,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-22.04, ubuntu-20.04, ubuntu-18.04] + os: [ubuntu-22.04, ubuntu-20.04] compiler: - { cc: clang, cxx: clang++ } - { cc: gcc, cxx: g++ } @@ -97,7 +97,7 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-22.04, ubuntu-20.04, ubuntu-18.04] + os: [ubuntu-22.04, ubuntu-20.04] compiler: - { cc: clang, cxx: clang++ } - { cc: gcc, cxx: g++ } diff --git a/.github/workflows/msbuild.yml b/.github/workflows/msbuild.yml new file mode 100644 index 000000000..dd25c2669 --- /dev/null +++ b/.github/workflows/msbuild.yml @@ -0,0 +1,51 @@ +# DESCRIPTION: Github actions config +# This name is key to badges in README.rst, so we use the name build +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +name: msbuild + +on: + push: + pull_request: + workflow_dispatch: + schedule: + - cron: '0 0 * * 0' # weekly + +env: + CI_OS_NAME: win + CI_COMMIT: ${{ github.sha }} + CCACHE_COMPRESS: 1 + CCACHE_DIR: ${{ github.workspace }}/.ccache + CCACHE_LIMIT_MULTIPLE: 0.95 + +defaults: + run: + working-directory: repo + +jobs: + + windows: + name: run on windows + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + with: + path: repo + - name: Cache $CCACHE_DIR + uses: actions/cache@v3 + with: + path: ${{ env.CCACHE_DIR }} + key: msbuild-msvc-cmake + - name: compile + env: + WIN_FLEX_BISON: ${{ github.workspace }}/.ccache + run: ./ci/ci-win-compile.ps1 + - name: test build + run: ./ci/ci-win-test.ps1 + - name: Zip up repository + run: Compress-Archive -LiteralPath install -DestinationPath verilator.zip + - name: Upload zip archive + uses: actions/upload-artifact@v3 + with: + path: ${{ github.workspace }}/repo/verilator.zip + name: verilator-win.zip diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..537caf740 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,123 @@ +#***************************************************************************** +# +# DESCRIPTION: Script for build tool cmake on both unix and windows +# +#***************************************************************************** +# +# Copyright 2003-2023 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 +# +#****************************************************************************/ + +cmake_minimum_required(VERSION 3.15) +cmake_policy(SET CMP0091 NEW) # Use MSVC_RUNTIME_LIBRARY to select the runtime +project(Verilator + VERSION 5.003 + HOMEPAGE_URL https://verilator.org + LANGUAGES CXX +) + +option(DEBUG_AND_RELEASE_AND_COVERAGE + "Builds both the debug and release binaries, overriding CMAKE_BUILD_TYPE. Not supported under MSBuild.") + +set(PYTHON3 python) +set(CMAKE_INSTALL_DATADIR ${CMAKE_INSTALL_PREFIX}) +include(GNUInstallDirs) +include(CMakePackageConfigHelpers) +include(CheckStructHasMember) +include(ExternalProject) + +if (NOT WIN32) + message(WARNING "CMake support on Linux/OSX is experimental.") +endif() + +if (MSVC) + if (DEFINED ENV{WIN_FLEX_BISON}) + set(WIN_FLEX_BISON "$ENV{WIN_FLEX_BISON}") + endif() + if (EXISTS ${WIN_FLEX_BISON}) + list(APPEND CMAKE_PREFIX_PATH ${WIN_FLEX_BISON}) + endif() + if (NOT WIN_FLEX_BISON) + message(FATAL_ERROR "Please install https://github.com/lexxmark/winflexbison and set WIN_FLEX_BISON environment variable. Please use install cmake target after a successful build.") + endif() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++20") +else() + if (NOT DEFINED ENV{FLEX_INCLUDE}) + message(FATAL_ERROR "Please set environment variable FLEX_INCLUDE to the directory containing FlexLexer.h") + endif() + set(WIN_FLEX_BISON "$ENV{FLEX_INCLUDE}") + if (WIN32 AND NOT MINGW) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++20") + endif() +endif() + +find_package(BISON) +find_package(FLEX) + +# Build +#set_property(GLOBAL PROPERTY JOB_POOLS one_job=1) + +if (DEBUG_AND_RELEASE_AND_COVERAGE) + if (CMAKE_GENERATOR MATCHES "^Visual Studio ") + error("%Error: The DEBUG_AND_RELEASE_AND_COVERAGE option is not supported in MSBuild-based builds.") + endif() + set(saved_build_type ${CMAKE_BUILD_TYPE}) + set(CMAKE_BUILD_TYPE Debug) + add_subdirectory(src build-Debug) + set(CMAKE_BUILD_TYPE Release) + add_subdirectory(src build-Release) + set(CMAKE_BUILD_TYPE Coverage) + add_subdirectory(src build-Coverage) + set(CMAKE_BUILD_TYPE ${saved_build_type}) +else() + add_subdirectory(src) +endif() + +# Configuration and Installation + +set(PACKAGE_NAME ${PROJECT_NAME}) +set(PACKAGE_VERSION ${PROJECT_VERSION}) + +configure_file(include/verilated_config.h.in include/verilated_config.h @ONLY) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/include/verilated_config.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include) + +configure_package_config_file(verilator-config.cmake.in verilator-config.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX} +) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/verilator-config.cmake DESTINATION ${CMAKE_INSTALL_PREFIX}) + +configure_package_config_file(verilator-config-version.cmake.in verilator-config-version.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_PREFIX} +) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/verilator-config-version.cmake DESTINATION ${CMAKE_INSTALL_PREFIX}) + +foreach (program + verilator_gantt + verilator_ccache_report + verilator_difftree + verilator_profcfunc +) + install(PROGRAMS bin/${program} TYPE BIN) +endforeach() + +install(DIRECTORY examples TYPE DATA FILES_MATCHING + PATTERN "examples/*/*.[chv]*" + PATTERN "examples/*/Makefile*" + PATTERN "examples/*/CMakeLists.txt" +) + +install(DIRECTORY include TYPE DATA FILES_MATCHING + PATTERN "include/verilated_config.h" + PATTERN "include/verilated.mk" + PATTERN "include/*.[chv]" + PATTERN "include/*.cpp" + PATTERN "include/gtkwave/*.[chv]*" + PATTERN "include/vltstd/*.[chv]*" +) diff --git a/Changes b/Changes index 7cc019b34..57790292d 100644 --- a/Changes +++ b/Changes @@ -8,6 +8,44 @@ The changes in each Verilator version are described below. The contributors that suggested a given feature are shown in []. Thanks! +Verilator 5.006 2022-01-22 +========================== + +**Minor:** + +* Support clocking blocks (#3674). [Krzysztof Bieganski, Antmicro Ltd] +* Support packed structs (#3802). [Aleksander Kiryk, Antmicro Ltd] +* Support Windows-native builds using cmake (#3814). [Kritik Bhimani] +* Support p format for UnpackArray (#3877). [Aleksander Kiryk, Antmicro Ltd] +* Support property calls without parenthesis (#3879) (#3893). [Ryszard Rozak, Antmicro Ltd] +* Support import/export lists in modport (#3886). [Gökçe Aydos] +* Support class queue equality (#3895). [Ilya Barkov] +* Add IMPLICITSTATIC warning when a ftask/function is implicitly static (#3839). [Ryszard Rozak, Antmicro Ltd] +* Add VL_VALUE_STRING_MAX_WORDS override (#3869). [Andrew Nolte] +* Optimize expansion of extend operators. +* Internal multithreading tests. [Mariusz Glebocki, et al, Antmicro Ltd] +* Fix VPI one-time timed callbacks (#2778). [Marlon James, et al] +* Fix initiation of function variables (#3815). [Dan Gisselquist] +* Fix to zero possibly uninitialized bits in replications (#3815). +* Fix crash in DFT due to width use after free (#3817) (#3820). [Jevin Sweval] +* Fix signed/unsigned comparison compile warning (#3822). [Kamil Rakoczy] +* Fix OS-X weak symbols with -U linker flag (#3823). [Jevin Sweval] +* Fix wrong bit op tree optimization (#3824) (#3825). [Yutetsu TAKATSUKASA] +* Fix self references when param class instantiated (#3833). [Ryszard Rozak, Antmicro Ltd] +* Fix memory leak in V3Sched, etc. (#3834). [Geza Lore] +* Fix compatibility with musl libc / Alpine Linux (#3845). [Sören Tempel] +* Fix empty case items crash (#3851). [rporter] +* Fix VL_CPU_RELAX on MIPS/Armel/s390/sparc (#3843) (#3891). [Kamil Rakoczy] +* Fix module parameter name collision (#3854) (#3855). [James Shi] +* Fix unpacked array expansion (#3861). [Joey Liu] +* Fix signed/unsigned parameter types (#3866). [James Shi] +* Fix chain call of abstract class constructor (#3868) (#3883). [Ilya Barkov] +* Fix to use same std in Verilator and Verilated compile (#3881). [Kamil Rakoczy, Antmicro Ltd] +* Fix foreach unnamedblk duplicate error (#3885). [Ilya Barkov] +* Fix elaboration of member selected classes (#3890). [Ilya Barkov] +* Fix mismatched widths in DFG (#3872). [Geza Lore, Yike Zhou] + + Verilator 5.004 2022-12-14 ========================== @@ -36,7 +74,7 @@ Verilator 5.004 2022-12-14 * Add error when use --exe with --lib-create (#3785). [Yinan Xu] * Fix jump handling in do while loops (#3731). [Ryszard Rozak, Antmicro Ltd] * Fix 'with' clause handling in functions (#3739). [Ryszard Rozak, Antmicro Ltd] -* Fix CONTEXT compile error on mingw64 (#3741). [William D. Jones] +* Fix CONTEXT compile error on MingW (#3741). [William D. Jones] * Fix MSVC compiler errors (#3742) (#3746). [Kritik Bhimani] * Fix CASEINCOMPLETE when covers all enum values (#3745) (#3782). [Guy-Armand Kamendje] * Fix return type of $countbits functions to int (#3725). [Ryszard Rozak, Antmicro Ltd] @@ -45,9 +83,9 @@ Verilator 5.004 2022-12-14 * Fix missing UNUSED warnings with --coverage (#3736). [alejandro-castro-ortegon] * Fix tracing parameters overridden with -G (#3723). [Iztok Jeras] * Fix folding of LogAnd with non-bool operands (#3726). [Geza Lore] -* Fix Dfg optimization issues (#3740) (#3771). [Geza Lore] +* Fix DFG optimization issues (#3740) (#3771). [Geza Lore] * Fix pre/postincrement operations (#3744) (#3756). [Ryszard Rozak, Antmicro Ltd] -* Fix cross-compile for MingW, Arm and RiscV (#3752). [Miodrag Milanović] +* Fix cross-compile for MingW, Arm and RISC-V (#3752). [Miodrag Milanović] * Fix $unit as base package for other packages (#3755). [Ryszard Rozak, Antmicro Ltd] * Fix make jobserver with submakes (#3758). [Gus Smith] * Fix to escape VERILATOR_ROOT file paths (#3764) (#3765). [Jiacheng Qian] @@ -4041,7 +4079,7 @@ Verilator 0.0 1994-07-08 Copyright ========= -Copyright 2001-2022 by Wilson Snyder. This program is free software; you +Copyright 2001-2023 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. diff --git a/Makefile.in b/Makefile.in index fdc785945..ba14a84d7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -7,7 +7,7 @@ # #***************************************************************************** # -# Copyright 2003-2022 by Wilson Snyder. This program is free software; you +# Copyright 2003-2023 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. @@ -53,7 +53,6 @@ INSTALL_DATA = @INSTALL_DATA@ MAKEINFO = makeinfo POD2TEXT = pod2text MKINSTALLDIRS = $(SHELL) $(srcdir)/src/mkinstalldirs -PERL = @PERL@ # Version (for docs/guide/conf.py) PACKAGE_VERSION_NUMBER = @PACKAGE_VERSION_NUMBER@ @@ -126,7 +125,12 @@ EXAMPLES_FIRST = \ EXAMPLES = $(EXAMPLES_FIRST) $(filter-out $(EXAMPLES_FIRST), $(sort $(wildcard examples/*))) # See uninstall also - don't put wildcards in this variable, it might uninstall other stuff -VL_INST_MAN_FILES = verilator.1 verilator_coverage.1 +# No verilator_ccache_report.1, verilator_difftree.1 as those are not bin/ installed +VL_INST_MAN_FILES = \ + verilator.1 \ + verilator_coverage.1 \ + verilator_gantt.1 \ + verilator_profcfunc.1 \ default: all all: all_nomsg msg_test @@ -179,8 +183,12 @@ docs: info info: $(INFOS) -%.1: ${srcdir}/bin/% +verilator.1: ${srcdir}/bin/verilator pod2man $< $@ +verilator_coverage.1: ${srcdir}/bin/verilator_coverage + pod2man $< $@ +%.1: ${srcdir}/bin/% + help2man --no-info --no-discard-stderr --version-string=- $< -o $@ .PHONY: verilator.html verilator.html: @@ -193,7 +201,7 @@ verilator.pdf: Makefile # See uninstall also - don't put wildcards in this variable, it might uninstall other stuff VL_INST_BIN_FILES = verilator verilator_bin$(EXEEXT) verilator_bin_dbg$(EXEEXT) verilator_coverage_bin_dbg$(EXEEXT) \ - verilator_ccache_report verilator_coverage verilator_gantt verilator_includer verilator_profcfunc + verilator_ccache_report verilator_coverage verilator_difftree verilator_gantt verilator_includer verilator_profcfunc # Some scripts go into both the search path and pkgdatadir, # so they can be found by the user, and under $VERILATOR_ROOT. @@ -226,6 +234,7 @@ installbin: $(MKINSTALLDIRS) $(DESTDIR)$(pkgdatadir)/bin ( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_includer $(DESTDIR)$(pkgdatadir)/bin/verilator_includer ) ( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_ccache_report $(DESTDIR)$(pkgdatadir)/bin/verilator_ccache_report ) + ( cd ${srcdir}/bin ; $(INSTALL_PROGRAM) verilator_difftree $(DESTDIR)$(pkgdatadir)/bin/verilator_difftree ) # Man files can either be part of the original kit, or built in current directory # So important we use $^ so VPATH is searched @@ -384,6 +393,7 @@ PY_PROGRAMS = \ bin/verilator_ccache_report \ bin/verilator_difftree \ bin/verilator_gantt \ + bin/verilator_includer \ bin/verilator_profcfunc \ examples/xml_py/vl_file_copy \ examples/xml_py/vl_hier_graph \ @@ -397,6 +407,7 @@ PY_PROGRAMS = \ src/flexfix \ src/vlcovgen \ test_regress/t/*.pf \ + nodist/clang_check_attributes \ nodist/code_coverage \ nodist/dot_importer \ nodist/fuzzer/actual_fail \ diff --git a/README.rst b/README.rst index 02b0593e1..8e8e57bb8 100644 --- a/README.rst +++ b/README.rst @@ -139,7 +139,7 @@ Related Projects Open License ============ -Verilator is Copyright 2003-2022 by Wilson Snyder. (Report bugs to +Verilator is Copyright 2003-2023 by Wilson Snyder. (Report bugs to `Verilator Issues `_.) Verilator is free software; you can redistribute it and/or modify it under diff --git a/bin/verilator b/bin/verilator index be1156d0f..7d4c84bd4 100755 --- a/bin/verilator +++ b/bin/verilator @@ -1,7 +1,7 @@ #!/usr/bin/env perl ###################################################################### # -# Copyright 2003-2022 by Wilson Snyder. This program is free software; you +# Copyright 2003-2023 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. @@ -416,6 +416,7 @@ detailed descriptions of these arguments. --no-skip-identical Disable skipping identical output --stats Create statistics file --stats-vars Provide statistics on variables + --structs-packed Convert all unpacked structures to packed structures -sv Enable SystemVerilog parsing +systemverilogext+ Synonym for +1800-2017ext+ --threads Enable multithreading @@ -444,7 +445,7 @@ detailed descriptions of these arguments. --unused-regexp Tune UNUSED lint signals -V Verbose version and config -v Verilog library - --no-verilate Skip verilation and just compile previously Verilated code + --no-verilate Skip Verilation and just compile previously Verilated code +verilog1995ext+ Synonym for +1364-1995ext+ +verilog2001ext+ Synonym for +1364-2001ext+ --version Displays program version and exits @@ -495,7 +496,7 @@ description of these arguments. The latest version is available from L. -Copyright 2003-2022 by Wilson Snyder. This program is free software; you can +Copyright 2003-2023 by Wilson Snyder. This program is free software; you can redistribute it and/or modify the Verilator internals under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. diff --git a/bin/verilator_ccache_report b/bin/verilator_ccache_report index bbb69b9af..31e3b9cdb 100755 --- a/bin/verilator_ccache_report +++ b/bin/verilator_ccache_report @@ -12,9 +12,12 @@ from datetime import datetime parser = argparse.ArgumentParser( allow_abbrev=False, formatter_class=argparse.RawDescriptionHelpFormatter, - description="""Report ccache behavior of a Verilated model build.""", + description="""Report ccache behavior of a Verilated model build. + + For documentation see + https://verilator.org/guide/latest/exe_verilator_ccache_report.html""", epilog= - """Copyright 2002-2022 by Wilson Snyder. This program is free software; you + """Copyright 2002-2023 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. diff --git a/bin/verilator_coverage b/bin/verilator_coverage index 4b73550c5..92f1a7c20 100755 --- a/bin/verilator_coverage +++ b/bin/verilator_coverage @@ -1,7 +1,7 @@ #!/usr/bin/env perl ###################################################################### # -# Copyright 2003-2022 by Wilson Snyder. This program is free software; you +# Copyright 2003-2023 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. @@ -187,7 +187,7 @@ L. The latest version is available from L. -Copyright 2003-2022 by Wilson Snyder. This program is free software; you +Copyright 2003-2023 by Wilson Snyder. This program is free software; you can redistribute it and/or modify the Verilator internals under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. diff --git a/bin/verilator_difftree b/bin/verilator_difftree index 2bede0e8d..f298bcf07 100755 --- a/bin/verilator_difftree +++ b/bin/verilator_difftree @@ -104,16 +104,13 @@ def filterf(fn1, fn2): parser = argparse.ArgumentParser( allow_abbrev=False, formatter_class=argparse.RawDescriptionHelpFormatter, - description="""Compare two Verilator debugging trees""", - epilog= - """Verilator_difftree is used for debugging Verilator tree output files. + description="""Compare two Verilator debugging trees. + +Verilator_difftree is used for debugging Verilator tree output files. It performs a diff between two files, or all files common between two -directories, ignoring irrelevant pointer differences. - -For documentation see -https://verilator.org/guide/latest/exe_verilator_difftree.html - -Copyright 2005-2022 by Wilson Snyder. This program is free software; you +directories, ignoring irrelevant pointer differences.""", + epilog= + """Copyright 2005-2023 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. diff --git a/bin/verilator_gantt b/bin/verilator_gantt index cfab96456..0015cb57f 100755 --- a/bin/verilator_gantt +++ b/bin/verilator_gantt @@ -475,16 +475,16 @@ def write_vcd(filename): parser = argparse.ArgumentParser( allow_abbrev=False, formatter_class=argparse.RawDescriptionHelpFormatter, - description="""Create Gantt chart of multi-threaded execution""", - epilog= - """Verilator_gantt creates a visual representation to help analyze Verilator + description="""Create Gantt chart of multi-threaded execution. + +Verilator_gantt creates a visual representation to help analyze Verilator #xmultithreaded simulation performance, by showing when each macro-task #xstarts and ends, and showing when each thread is busy or idle. For documentation see -https://verilator.org/guide/latest/exe_verilator_gantt.html - -Copyright 2018-2022 by Wilson Snyder. This program is free software; you +https://verilator.org/guide/latest/exe_verilator_gantt.html""", + epilog= + """Copyright 2018-2023 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. diff --git a/bin/verilator_includer b/bin/verilator_includer index 5fe3ce6c5..08076063e 100755 --- a/bin/verilator_includer +++ b/bin/verilator_includer @@ -1,20 +1,29 @@ -#!/usr/bin/env perl -# DESCRIPTION: Print include statements for each ARGV +#!/usr/bin/env python3 +# pylint: disable=C0114,C0209 +# +# Copyright 2003-2023 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify the Verilator internals under the terms +# of either the GNU Lesser General Public License Version 3 or the Perl +# Artistic License Version 2.0. # -# Copyright 2003-2022 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 ###################################################################### -require 5.005; -use warnings; -print "// DESCR" . "IPTION: Generated by verilator_includer via makefile\n"; -foreach my $param (@ARGV) { - if ($param =~ /^-D([^=]+)=(.*)/) { - print "#define $1 $2\n"; - } else { - print "#include \"$param\"\n"; - } -} +import re +import sys + +print("// DESCR" + "IPTION: Generated by verilator_includer via makefile") + +re_arg_d = re.compile(r'^-D([^=]+)=(.*)') + +for arg in sys.argv[1:]: + match_d = re_arg_d.match(arg) + if match_d: + print("#define %s %s" % (match_d.group(1), match_d.group(2))) + else: + print("#include \"%s\"" % (arg)) + +###################################################################### +# Local Variables: +# compile-command: "./verilator_includer -Ddef=value -Ddef2=value2 file1.h file2.h" +# End: diff --git a/bin/verilator_profcfunc b/bin/verilator_profcfunc index abf1c06b8..cd72060df 100755 --- a/bin/verilator_profcfunc +++ b/bin/verilator_profcfunc @@ -171,17 +171,17 @@ def profcfunc(filename): parser = argparse.ArgumentParser( allow_abbrev=False, formatter_class=argparse.RawDescriptionHelpFormatter, - description="""Read gprof report created with --prof-cfuncs""", - epilog= - """Verilator_profcfunc reads a profile report created by gprof. The names of + description="""Read gprof report created with --prof-cfuncs. + +Verilator_profcfunc reads a profile report created by gprof. The names of the functions are then transformed, assuming the user used Verilator's --prof-cfuncs, and a report printed showing the percentage of time, etc, in each Verilog block. For documentation see -https://verilator.org/guide/latest/exe_verilator_profcfunc.html - -Copyright 2002-2022 by Wilson Snyder. This program is free software; you +https://verilator.org/guide/latest/exe_verilator_profcfunc.html""", + epilog= + """Copyright 2002-2023 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. diff --git a/ci/ci-install.bash b/ci/ci-install.bash index 2e7325cea..d3372a798 100755 --- a/ci/ci-install.bash +++ b/ci/ci-install.bash @@ -57,19 +57,24 @@ if [ "$CI_BUILD_STAGE_NAME" = "build" ]; then # build Verilator if [ "$CI_OS_NAME" = "linux" ]; then + sudo apt-get update || sudo apt-get update - sudo apt-get install libfl-dev ccache + sudo apt-get install ccache help2man libfl-dev || + sudo apt-get install ccache help2man libfl-dev if [ "$CI_RUNS_ON" != "ubuntu-22.04" ]; then # Some conflict of libunwind verison on 22.04, can live without it for now + sudo apt-get install libgoogle-perftools-dev || sudo apt-get install libgoogle-perftools-dev fi if [ "$CI_RUNS_ON" = "ubuntu-20.04" ] || [ "$CI_RUNS_ON" = "ubuntu-22.04" ]; then + sudo apt-get install libsystemc libsystemc-dev || sudo apt-get install libsystemc libsystemc-dev fi if [ "$COVERAGE" = 1 ]; then yes yes | sudo cpan -fi Parallel::Forker fi if [ "$CI_M32" = 1 ]; then + sudo apt-get install gcc-multilib g++-multilib || sudo apt-get install gcc-multilib g++-multilib fi elif [ "$CI_OS_NAME" = "osx" ]; then @@ -90,13 +95,23 @@ elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then # run the tests if [ "$CI_OS_NAME" = "linux" ]; then + sudo apt-get update || sudo apt-get update # libfl-dev needed for internal coverage's test runs + sudo apt-get install gdb gtkwave lcov libfl-dev ccache || sudo apt-get install gdb gtkwave lcov libfl-dev ccache + # Required for test_regress/t/t_dist_attributes.pl + if [ "$CI_RUNS_ON" = "ubuntu-22.04" ]; then + sudo apt-get install libclang-dev || + sudo apt-get install libclang-dev + pip3 install clang==14.0 + fi if [ "$CI_RUNS_ON" = "ubuntu-20.04" ] || [ "$CI_RUNS_ON" = "ubuntu-22.04" ]; then + sudo apt-get install libsystemc-dev || sudo apt-get install libsystemc-dev fi if [ "$CI_M32" = 1 ]; then + sudo apt-get install lib32z1-dev gcc-multilib g++-multilib || sudo apt-get install lib32z1-dev gcc-multilib g++-multilib fi elif [ "$CI_OS_NAME" = "osx" ]; then diff --git a/ci/ci-script.bash b/ci/ci-script.bash index 0e02a9371..225c9b50c 100755 --- a/ci/ci-script.bash +++ b/ci/ci-script.bash @@ -69,7 +69,7 @@ elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then if [ "$CI_OS_NAME" = "osx" ]; then export VERILATOR_TEST_NO_GDB=1 # Pain to get GDB to work on OS X - # TODO below may no longer be requried as configure checks for -pg + # TODO below may no longer be required as configure checks for -pg export VERILATOR_TEST_NO_GPROF=1 # Apple Clang has no -pg # export PATH="/Applications/gtkwave.app/Contents/Resources/bin:$PATH" # fst2vcd file bin/verilator_bin @@ -85,7 +85,7 @@ elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then "$MAKE" -j "$NPROC" -k elif [ "$CI_OS_NAME" = "freebsd" ]; then export VERILATOR_TEST_NO_GDB=1 # Disable for now, ideally should run - # TODO below may no longer be requried as configure checks for -pg + # TODO below may no longer be required as configure checks for -pg export VERILATOR_TEST_NO_GPROF=1 # gprof is a bit different on FreeBSD, disable fi diff --git a/ci/ci-win-compile.ps1 b/ci/ci-win-compile.ps1 new file mode 100644 index 000000000..20a744539 --- /dev/null +++ b/ci/ci-win-compile.ps1 @@ -0,0 +1,15 @@ +if (-Not (Test-Path $PWD/../.ccache/win_bison.exe)) { + git clone --depth 1 https://github.com/lexxmark/winflexbison + cd winflexbison + mkdir build + cd build + cmake .. --install-prefix $PWD/../../../.ccache + cmake --build . --config Release + cmake --install . --prefix $PWD/../../../.ccache + cd ../.. +} +mkdir build +cd build +cmake .. --install-prefix $PWD/../install +cmake --build . --config Release +cmake --install . --prefix $PWD/../install diff --git a/ci/ci-win-test.ps1 b/ci/ci-win-test.ps1 new file mode 100644 index 000000000..1900bd4a5 --- /dev/null +++ b/ci/ci-win-test.ps1 @@ -0,0 +1,10 @@ +cd install +$Env:VERILATOR_ROOT=$PWD +cd examples/cmake_tracing_c +mkdir build +cd build +cmake .. +cmake --build . --config Release +Release/example.exe +cd .. +Remove-Item -path build -recurse diff --git a/ci/docker/buildenv/Dockerfile b/ci/docker/buildenv/Dockerfile index 7adf4b3d2..3e3fbe177 100644 --- a/ci/docker/buildenv/Dockerfile +++ b/ci/docker/buildenv/Dockerfile @@ -23,6 +23,7 @@ RUN apt-get update \ gdb \ git \ gtkwave \ + help2man \ libfl2 \ libfl-dev \ libgoogle-perftools-dev \ diff --git a/ci/docker/buildenv/README.rst b/ci/docker/buildenv/README.rst index 3ff025fc9..e131917ac 100644 --- a/ci/docker/buildenv/README.rst +++ b/ci/docker/buildenv/README.rst @@ -1,3 +1,6 @@ +.. Copyright 2003-2023 by Wilson Snyder. +.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + Verilator Build Docker Container ================================ diff --git a/ci/docker/run/README.rst b/ci/docker/run/README.rst index dd778f4fb..db9d0de1d 100644 --- a/ci/docker/run/README.rst +++ b/ci/docker/run/README.rst @@ -1,3 +1,6 @@ +.. Copyright 2003-2023 by Wilson Snyder. +.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + Verilator Executable Docker Container ===================================== diff --git a/codecov.yml b/codecov.yml index 315072af8..a6705db0a 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,6 +1,6 @@ # DESCRIPTION: codecov.io config # -# Copyright 2020-2022 by Wilson Snyder. This program is free software; you +# Copyright 2020-2023 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. diff --git a/configure.ac b/configure.ac index 1b2ca1a77..d3be24f47 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ # DESCRIPTION: Process this file with autoconf to produce a configure script. # -# Copyright 2003-2022 by Wilson Snyder. Verilator is free software; you +# Copyright 2003-2023 by Wilson Snyder. Verilator is free software; you # can redistribute it and/or modify it under the terms of either the GNU Lesser # General Public License Version 3 or the Perl Artistic License Version 2.0. # SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 @@ -10,7 +10,7 @@ # Then 'make maintainer-dist' #AC_INIT([Verilator],[#.### YYYY-MM-DD]) #AC_INIT([Verilator],[#.### devel]) -AC_INIT([Verilator],[5.004 2022-12-14], +AC_INIT([Verilator],[5.006 2023-01-22], [https://verilator.org], [verilator],[https://verilator.org]) @@ -112,7 +112,7 @@ AC_MSG_CHECKING(whether to show and stop on compilation warnings) AC_ARG_ENABLE([ccwarn], [AS_HELP_STRING([--enable-ccwarn], [enable showing and stopping on compilation warnings - in Verilator binrary and Verilated makefiles])], + in Verilator binary and Verilated makefiles])], [case "${enableval}" in yes) CFG_WITH_CCWARN=yes ;; no) CFG_WITH_CCWARN=no ;; @@ -351,15 +351,11 @@ AC_SUBST(CFG_CXXFLAGS_PROFILE) # Currently enable c++17/c++14 due to packaged SystemC dependency # c++17 is the newest that Verilator is regularly tested to support # c++11 is the oldest that Verilator supports -# gnu is requried for Cygwin to compile verilated.h successfully +# gnu is required for Cygwin to compile verilated.h successfully #_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++20) #_MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++20) -case "$(which lsb_release 2>&1 > /dev/null && lsb_release -d)" in -*Arch*Linux* | *Ubuntu*22.04*) _MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++17) _MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++17) -;; -esac _MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++14) _MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=c++14) _MY_CXX_CHECK_SET(CFG_CXXFLAGS_STD_NEWEST,-std=gnu++11) @@ -532,15 +528,22 @@ AC_DEFUN([_MY_CXX_CHECK_CXX_VER], [_my_result=no]) ]) +# Add $CFG_CXXFLAGS_STD only if can't compile correctly otherwise, +# as adding std= when not needed can cause errors with the C++ std library. +CFG_CXXFLAGS_STD=$CFG_CXXFLAGS_STD_NEWEST 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) + CXXFLAGS="$CXXFLAGS $CFG_CXXFLAGS_STD" + CFG_CXX_FLAGS_CMAKE="$CFG_CXX_FLAGS_CMAKE $CFG_CXXFLAGS_STD" + AC_MSG_CHECKING(whether $CXX supports C++11 with $CFG_CXXFLAGS_STD) _MY_CXX_CHECK_CXX_VER() AC_MSG_RESULT($_my_result) +else + # CFG_CXXFLAGS_STD is also propagated to include/verilated.mk.in + # make sure we use the same std flag while compiling verilator and verilated design + CFG_CXXFLAGS_STD="" fi if test "$_my_result" = "no" ; then AC_MSG_NOTICE([[]]) @@ -549,6 +552,7 @@ if test "$_my_result" = "no" ; then Verilator requires a C++11 or newer compiler.]]) fi +AC_SUBST(CFG_CXXFLAGS_STD) # Checks for library functions. AC_CHECK_MEMBER([struct stat.st_mtim.tv_nsec], diff --git a/docs/CONTRIBUTING.rst b/docs/CONTRIBUTING.rst index 15f2fed27..1e81842ad 100644 --- a/docs/CONTRIBUTING.rst +++ b/docs/CONTRIBUTING.rst @@ -59,7 +59,7 @@ Did you write a patch that fixes a bug? Creative Commons Public Domain (CC0), unless you request otherwise or put a GNU/Artistic license on your file. -- Most important is we get your patch. If you’d like to clean up +- Most important is we get your patch. If you'd like to clean up indentation and related issues ahead of our feedback, that is appreciated; please see the coding conventions in `docs/internals `__. diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index 29af74174..ed105e78f 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -33,6 +33,7 @@ Garrett Smith Geza Lore Gianfranco Costamagna Glen Gibb +Gökçe Aydos Graham Rushton Guokai Chen Gustav Svensk @@ -45,18 +46,22 @@ HungMingWu HyungKi Jeong Iru Cai Ivan Vnučec +Ilya Barkov Iztok Jeras Jake Merdich James Hanlon James Hutchinson James Pallister +James Shi Jamey Hicks Jamie Iles Jan Van Winkel Jean Berniolles Jeremy Bennett +Jevin Sweval Jiacheng Qian Jiuyang Liu +Joey Liu John Coiner John Demme Jonathan Drolet @@ -117,6 +122,7 @@ Sergi Granell Stefan Wallentowitz Stephen Henry Steven Hugg +Sören Tempel Teng Huang Tim Snyder Tobias Rosenkranz diff --git a/docs/Makefile b/docs/Makefile index 8a5d1af7d..a1e151b35 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -5,7 +5,7 @@ # # Code available from: https://verilator.org # -# Copyright 2003-2022 by Wilson Snyder. This program is free software; you +# Copyright 2003-2023 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. diff --git a/docs/bin/vl_sphinx_extract b/docs/bin/vl_sphinx_extract index c829482bf..5c446a327 100755 --- a/docs/bin/vl_sphinx_extract +++ b/docs/bin/vl_sphinx_extract @@ -40,7 +40,7 @@ parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description="""Read a file and extract documentation data.""", epilog= - """ Copyright 2021-2022 by Wilson Snyder. This package is free software; + """ Copyright 2021-2023 by Wilson Snyder. This package 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. diff --git a/docs/bin/vl_sphinx_fix b/docs/bin/vl_sphinx_fix index cc03c3b83..780250d44 100755 --- a/docs/bin/vl_sphinx_fix +++ b/docs/bin/vl_sphinx_fix @@ -55,7 +55,7 @@ parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description="""Post-process Sphinx HTML.""", epilog= - """ Copyright 2021-2022 by Wilson Snyder. This package is free software; + """ Copyright 2021-2023 by Wilson Snyder. This package 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. diff --git a/docs/guide/changes.rst b/docs/guide/changes.rst index f8baf257a..315d2abea 100644 --- a/docs/guide/changes.rst +++ b/docs/guide/changes.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 **************** diff --git a/docs/guide/conf.py b/docs/guide/conf.py index a10484a35..bcf574cc7 100644 --- a/docs/guide/conf.py +++ b/docs/guide/conf.py @@ -1,6 +1,7 @@ # pylint: disable=C0103,C0114,C0116,C0301,E0402,W0622 # # Configuration file for Verilator's Sphinx documentation builder. +# Copyright 2003-2023 by Wilson Snyder. # SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 # # This file only contains overridden options. For a full list: diff --git a/docs/guide/connecting.rst b/docs/guide/connecting.rst index 177af7520..35c1c6aec 100644 --- a/docs/guide/connecting.rst +++ b/docs/guide/connecting.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 .. _Connecting: diff --git a/docs/guide/contributing.rst b/docs/guide/contributing.rst index 4593f9355..215b58a83 100644 --- a/docs/guide/contributing.rst +++ b/docs/guide/contributing.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 ******************************* diff --git a/docs/guide/contributors.rst b/docs/guide/contributors.rst index b743bddc5..2af72be9d 100644 --- a/docs/guide/contributors.rst +++ b/docs/guide/contributors.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 ************************ diff --git a/docs/guide/copyright.rst b/docs/guide/copyright.rst index 245141c1d..2eba06d51 100644 --- a/docs/guide/copyright.rst +++ b/docs/guide/copyright.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 ********* @@ -8,7 +8,7 @@ Copyright The latest version of Verilator is available from `https://verilator.org `_. -Copyright 2003-2022 by Wilson Snyder. This program is free software; you +Copyright 2003-2023 by Wilson Snyder. This program is free software; you can redistribute it and/or modify the Verilator internals under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. diff --git a/docs/guide/deprecations.rst b/docs/guide/deprecations.rst index 3214ef8ab..eb3f05f2c 100644 --- a/docs/guide/deprecations.rst +++ b/docs/guide/deprecations.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 Deprecations diff --git a/docs/guide/environment.rst b/docs/guide/environment.rst index 03edf7754..dc037cc8f 100644 --- a/docs/guide/environment.rst +++ b/docs/guide/environment.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 Environment diff --git a/docs/guide/example_binary.rst b/docs/guide/example_binary.rst index fbcda7e86..4a238c922 100644 --- a/docs/guide/example_binary.rst +++ b/docs/guide/example_binary.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 .. _Example Create-Binary Execution: diff --git a/docs/guide/example_cc.rst b/docs/guide/example_cc.rst index bc4e578f2..6e5d7f465 100644 --- a/docs/guide/example_cc.rst +++ b/docs/guide/example_cc.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 .. _Example C++ Execution: diff --git a/docs/guide/example_common_install.rst b/docs/guide/example_common_install.rst index c834a7cda..916d7ce31 100644 --- a/docs/guide/example_common_install.rst +++ b/docs/guide/example_common_install.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 First you need Verilator installed, see :ref:`Installation`. In brief, if diff --git a/docs/guide/example_dist.rst b/docs/guide/example_dist.rst index c68509e11..b776ecdfd 100644 --- a/docs/guide/example_dist.rst +++ b/docs/guide/example_dist.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 .. _Examples in the Distribution: diff --git a/docs/guide/example_sc.rst b/docs/guide/example_sc.rst index 987554f81..b482b1ffd 100644 --- a/docs/guide/example_sc.rst +++ b/docs/guide/example_sc.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 .. _Example SystemC Execution: diff --git a/docs/guide/examples.rst b/docs/guide/examples.rst index b92fe9a78..7eca1c636 100644 --- a/docs/guide/examples.rst +++ b/docs/guide/examples.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 .. _Examples: diff --git a/docs/guide/exe_sim.rst b/docs/guide/exe_sim.rst index 48b85f4fe..f538d4836 100644 --- a/docs/guide/exe_sim.rst +++ b/docs/guide/exe_sim.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 .. _Simulation Runtime Arguments: diff --git a/docs/guide/exe_verilator.rst b/docs/guide/exe_verilator.rst index 8230d3e6b..e610fa926 100644 --- a/docs/guide/exe_verilator.rst +++ b/docs/guide/exe_verilator.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 verilator Arguments @@ -1203,11 +1203,10 @@ Summary: .. option:: --structs-packed - Converts all unpacked structures to packed structures and issues an - :option:`UNPACKED` warning. Currently, this is the default, and - :vlopt:`--no-structs-packed <--structs-packed>` will not work. - Specifying this option allows forward compatibility when a future - version of Verilator no longer always packs unpacked structures. + Converts all unpacked structures to packed structures, and issues an + :option:`UNPACKED` warning. Specifying this option allows for backward + compatibility with versions before Verilator 5.006, when Verilator would + always pack unpacked structures. .. option:: -sv @@ -1503,7 +1502,7 @@ Summary: Disable all lint-related warning messages, and all style warnings. This is equivalent to ``-Wno-ALWCOMBORDER -Wno-BSSPACE -Wno-CASEINCOMPLETE -Wno-CASEOVERLAP -Wno-CASEX -Wno-CASTCONST -Wno-CASEWITHX -Wno-CMPCONST -Wno-COLONPLUS - -Wno-IMPLICIT -Wno-LITENDIAN -Wno-PINCONNECTEMPTY + -Wno-IMPLICIT -Wno-IMPLICITSTATIC -Wno-LITENDIAN -Wno-PINCONNECTEMPTY -Wno-PINMISSING -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSEDGENVAR -Wno-UNUSEDPARAM -Wno-UNUSEDSIGNAL -Wno-WIDTH`` plus the list shown for Wno-style. diff --git a/docs/guide/exe_verilator_coverage.rst b/docs/guide/exe_verilator_coverage.rst index a041b5064..57eb02808 100644 --- a/docs/guide/exe_verilator_coverage.rst +++ b/docs/guide/exe_verilator_coverage.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 verilator_coverage diff --git a/docs/guide/exe_verilator_gantt.rst b/docs/guide/exe_verilator_gantt.rst index 3c933407d..59c570ebe 100644 --- a/docs/guide/exe_verilator_gantt.rst +++ b/docs/guide/exe_verilator_gantt.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 verilator_gantt diff --git a/docs/guide/exe_verilator_profcfunc.rst b/docs/guide/exe_verilator_profcfunc.rst index b33a5f5fc..900f7e2e2 100644 --- a/docs/guide/exe_verilator_profcfunc.rst +++ b/docs/guide/exe_verilator_profcfunc.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 verilator_profcfunc diff --git a/docs/guide/executables.rst b/docs/guide/executables.rst index 9bbb50f8c..11b1173a5 100644 --- a/docs/guide/executables.rst +++ b/docs/guide/executables.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 ********************************* diff --git a/docs/guide/extensions.rst b/docs/guide/extensions.rst index 03c2f4f47..6f71cf947 100644 --- a/docs/guide/extensions.rst +++ b/docs/guide/extensions.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 ******************* diff --git a/docs/guide/faq.rst b/docs/guide/faq.rst index 8ca36573c..4b161bc2d 100644 --- a/docs/guide/faq.rst +++ b/docs/guide/faq.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 ****************************** diff --git a/docs/guide/files.rst b/docs/guide/files.rst index ffd33a7b8..d34ea6aa7 100644 --- a/docs/guide/files.rst +++ b/docs/guide/files.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 ***** diff --git a/docs/guide/index.rst b/docs/guide/index.rst index 38f36b9e9..e828272a8 100644 --- a/docs/guide/index.rst +++ b/docs/guide/index.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 ###################### @@ -12,6 +12,7 @@ Verilator User's Guide overview.rst examples.rst install.rst + install-cmake.rst .. toctree:: diff --git a/docs/guide/install-cmake.rst b/docs/guide/install-cmake.rst new file mode 100644 index 000000000..8da441329 --- /dev/null +++ b/docs/guide/install-cmake.rst @@ -0,0 +1,72 @@ +.. Copyright 2003-2023 by Wilson Snyder. +.. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +.. _CMakeInstallation: + +****************** +CMake Installation +****************** + +This section discusses how to build and install Verilator using cmake. +Currently cmake is only officially supported for Windows builds (not Linux). + +.. _Tools Install: + +Quick Install +============= + +1. Install Python for your platform from https://www.python.org/downloads/. +2. Install CMake for your platform from https://cmake.org/download/ or build it from source. +3. If the compiler of your choice is MSVC, then install https://visualstudio.microsoft.com/downloads/. + If the compiler of your choice is Clang, then install https://releases.llvm.org/download.html or build it from source. +4. For flex and bison use https://github.com/lexxmark/winflexbison to build and install. +5. For build on Windows using MSVC set environment variable WIN_FLEX_BISON to install directory. + For build on Windows/Linux/OS-X using ninja set the environment variable + FLEX_INCLUDE to the directory containing FlexLexer.h and ensure that flex/bison + is available within the PATH. + +To obtain verilator sources download https://github.com/verilator/verilator/archive/refs/heads/master.zip +or clone https://github.com/verilator/verilator using git :ref:`Obtain Sources`. + +To build using MSVC: + +:: + + cd verilator # directory containing source files of verilator + mkdir build + cmake .. -DCMAKE_BUILD_TYPE=Release --install-prefix $PWD/../install + cmake --build . --config Release + cmake --install . --prefix $PWD/../install + + +To build using ninja: + +:: + + cd verilator + mkdir build + cmake -G Ninja .. -DCMAKE_BUILD_TYPE=Release --install-prefix $PWD/../install -DCMAKE_MAKE_PROGRAM= -DBISON_EXECUTABLE= -DFLEX_EXECUTABLE= + #execute ninja + cmake --install . --prefix $PWD/../install + + +.. _CMake Usage: + +Usage +===== + +To use Verilator set the environment variable ``VERILATOR_ROOT`` to the +install directory specified in the above build. + +Example +======= + +:: + + cd verilator/examples + cd cmake_hello_c + mkdir build + cd build + cmake .. # cmake -G Ninja .. + cmake --build . --config Release # ninja + # execute the generated binary diff --git a/docs/guide/install.rst b/docs/guide/install.rst index bb519adf8..b6e50d16b 100644 --- a/docs/guide/install.rst +++ b/docs/guide/install.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 .. _Installation: @@ -91,7 +91,7 @@ To build or run Verilator, you need these standard packages: :: - sudo apt-get install git perl python3 make + sudo apt-get install git help2man perl python3 make sudo apt-get install g++ # Alternatively, clang sudo apt-get install libgz # Non-Ubuntu (ignore if gives error) sudo apt-get install libfl2 # Ubuntu only (ignore if gives error) @@ -125,8 +125,8 @@ Those developing Verilator itself may also want these (see internals.rst): :: sudo apt-get install gdb graphviz cmake clang clang-format-14 gprof lcov - sudo apt-get install yapf3 - sudo pip3 install sphinx sphinx_rtd_theme sphinxcontrib-spelling breathe + sudo apt-get install libclang-dev yapf3 + sudo pip3 install clang sphinx sphinx_rtd_theme sphinxcontrib-spelling breathe cpan install Pod::Perldoc cpan install Parallel::Forker @@ -150,6 +150,8 @@ To make use of Verilator FST tracing you will want `GTKwave required at Verilator build time. +.. _Obtain Sources: + Obtain Sources -------------- diff --git a/docs/guide/languages.rst b/docs/guide/languages.rst index 64a623030..4865f5375 100644 --- a/docs/guide/languages.rst +++ b/docs/guide/languages.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 *************** @@ -130,11 +130,11 @@ simulation (perhaps using :vlopt:`--build`) and run it. With :vlopt:`--no-timing`, all timing controls cause the :option:`NOTIMING` error, except: -* delay statements – they are ignored (as they are in synthesis), though they +* delay statements - they are ignored (as they are in synthesis), though they do issue a :option:`STMTDLY` warning, -* intra-assignment timing controls – they are ignored, though they do issue an +* intra-assignment timing controls - they are ignored, though they do issue an :option:`ASSIGNDLY` warning, -* net delays – they are ignored, +* net delays - they are ignored, * event controls at the top of the procedure, Forks cause this error as well, except: diff --git a/docs/guide/overview.rst b/docs/guide/overview.rst index 85198aeaa..cecbfab14 100644 --- a/docs/guide/overview.rst +++ b/docs/guide/overview.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 ******** diff --git a/docs/guide/simulating.rst b/docs/guide/simulating.rst index 94966afb2..b65573be1 100644 --- a/docs/guide/simulating.rst +++ b/docs/guide/simulating.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 .. _Simulating: diff --git a/docs/guide/verilating.rst b/docs/guide/verilating.rst index f50303b0d..e1b031c5a 100644 --- a/docs/guide/verilating.rst +++ b/docs/guide/verilating.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 ********** diff --git a/docs/guide/warnings.rst b/docs/guide/warnings.rst index 3e5c8645a..7f0011153 100644 --- a/docs/guide/warnings.rst +++ b/docs/guide/warnings.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2022 by Wilson Snyder. +.. Copyright 2003-2023 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 ******************* @@ -727,6 +727,27 @@ List Of Warnings implicit definition of wire '...'". +.. option:: IMPLICITSTATIC + + Warns that the lifetime of a task or a function was not provided and so + was implicitly set to static. The warning is suppressed when no + variables inside the task or a function are assigned to. + + This is a warning because the static default differs from C++, differs + from class member function/tasks. Static is a more dangerous default + then automatic as static prevents the function from being reinterant, + which may be a source of bugs, and/or performance issues. + + If the function does not require static behavior, change it to "function + automatic". + + If the function requires static behavior, change it to "function + static". + + Ignoring this warning will only suppress the lint check; it will + simulate correctly. + + .. option:: IMPORTSTAR .. TODO better example diff --git a/docs/internals.rst b/docs/internals.rst index 47801dac1..12cbd720c 100644 --- a/docs/internals.rst +++ b/docs/internals.rst @@ -1,8 +1,8 @@ |Logo| -******************* -Verilator Internals -******************* +===================== + Verilator Internals +===================== .. contents:: :depth: 3 @@ -81,7 +81,7 @@ Key Classes Used in the Verilator Flow ``AstNode`` -^^^^^^^^^^^ +~~~~~~~~~~~ The AST is represented at the top level by the class ``AstNode``. This abstract class has derived classes for the individual components (e.g. @@ -123,7 +123,7 @@ There are notable sub-hierarchies of the ``AstNode`` sub-types, namely: ``VNVisitor`` -^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~ The passes are implemented by AST visitor classes. These are implemented by subclasses of the abstract class, ``VNVisitor``. Each pass creates an @@ -132,7 +132,7 @@ the pass. ``V3Graph`` -^^^^^^^^^^^ +~~~~~~~~~~~ A number of passes use graph algorithms, and the class ``V3Graph`` is provided to represent those graphs. Graphs are directed, and algorithms are @@ -142,7 +142,7 @@ documentation of this class. ``V3GraphVertex`` -^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~ ``V3GraphVertex`` is the base class for vertices in a graph. Vertices have an associated ``fanout``, ``color`` and ``rank``, which may be used in @@ -164,7 +164,7 @@ in the form: ``V3GraphEdge`` -^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~ ``V3GraphEdge`` is the base class for directed edges between pairs of vertices. Edges have an associated ``weight`` and may also be made @@ -179,7 +179,7 @@ used in dot output. Typically users provided derived classes from ``V3GraphAlg`` -^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~ This is the base class for graph algorithms. It implements a ``bool`` method, ``followEdge`` which algorithms can use to decide whether an edge @@ -192,7 +192,7 @@ provided and documented in ``V3GraphAlg.cpp``. ``DfgGraph`` -^^^^^^^^^^^^^ +~~~~~~~~~~~~ The data-flow graph-based combinational logic optimizer (DFG optimizer) converts an ``AstModule`` into a ``DfgGraph``. The graph represents the @@ -208,7 +208,7 @@ writing DFG passes easier. ``DfgVertex`` -^^^^^^^^^^^^^ +~~~~~~~~~~~~~ The ``DfgGraph`` represents combinational logic equations as a graph of ``DfgVertex`` vertices. Each sub-class of ``DfgVertex`` corresponds to an @@ -243,7 +243,7 @@ without initialization or other miscellaneous constructs. Classes of logic -^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~ The first step in the scheduling algorithm is to gather all the logic present in the design, and classify it based on the conditions under which the logic @@ -289,7 +289,7 @@ Details of this process and the hybrid logic class are described below. Scheduling of simple classes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SystemVerilog ``initial`` and ``final`` blocks can be scheduled (executed) in an arbitrary order. @@ -307,7 +307,7 @@ the corresponding logic constructs. Scheduling of clocked and combinational logic -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ For performance, clocked and combinational logic needs to be ordered. Conceptually this minimizes the iterations through the evaluation loop @@ -358,7 +358,7 @@ avoid this circularity problem whenever possible, this is not always possible). Breaking combinational loops -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Combinational loops are broken by the introduction of instances of the 'hybrid' logic class. As described in the previous section, combinational loops require @@ -405,15 +405,15 @@ combinational (including hybrid) logic have settled. One might wonder if there can be a race condition between clocked logic triggered due to a combinational signal change from the previous evaluation pass, and a combinational loop settling due to hybrid logic, if the clocked -logic reads the not yet settled combinationally driven signal. Such a race is -indeed possible, but our evaluation is consistent with the SystemVerilog -scheduling semantics (IEEE 1800-2017 chapter 4), and therefore any program that -exhibits such a race has non-deterministic behaviour according to the +logic reads the not yet settled combinationally driven signal. Such a race +is indeed possible, but our evaluation is consistent with the SystemVerilog +scheduling semantics (IEEE 1800-2017 chapter 4), and therefore any program +that exhibits such a race has non-deterministic behavior according to the SystemVerilog semantics, so we accept this. Settling combinational logic after initialization -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ At the beginning of simulation, once static initializer and ``initial`` blocks have been executed, we need to evaluate all combinational logic, in order to @@ -427,7 +427,7 @@ invoked at the beginning of simulation after the `_eval_initial`. Partitioning logic for correct NBA updates -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``V3Order`` can order logic corresponding to non-blocking assignments (NBAs) to yield correct simulation results, as long as all the sensitivity expressions of @@ -469,7 +469,7 @@ The partitioning described above is performed by ``V3Sched::partition``. Replication of combinational logic -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We will separately invoke ``V3Order::order`` on the 'act' and 'nba' region logic. @@ -495,7 +495,7 @@ Verilator). Constructing the top level `_eval` function -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To construct the top level `_eval` function, which updates the state of the circuit to the end of the current time step, we invoke ``V3Order::order`` @@ -505,39 +505,38 @@ corresponding functions that compute the respective trigger expressions into the top level `_eval` function, which on the high level has the form: :: - void _eval() { - // Update combinational logic dependent on top level inputs ('ico' region) - while (true) { - _eval__triggers__ico(); - // If no 'ico' region trigger is active - if (!ico_triggers.any()) break; - _eval_ico(); - } - - // Iterate 'act' and 'nba' regions together - while (true) { - - // Iterate 'act' region, this computes all derived clocks updaed in the - // Active scheduling region, but does not commit any NBAs that executed - // in 'act' region logic. + void _eval() { + // Update combinational logic dependent on top level inputs ('ico' region) while (true) { - _eval__triggers__act(); - // If no 'act' region trigger is active - if (!act_triggers.any()) break; - // Remember what 'act' triggers were active, 'nba' uses the same - latch_act_triggers_for_nba(); - _eval_act(); + _eval__triggers__ico(); + // If no 'ico' region trigger is active + if (!ico_triggers.any()) break; + _eval_ico(); } + // Iterate 'act' and 'nba' regions together + while (true) { - // If no 'nba' region trigger is active - if (!nba_triggers.any()) break; + // Iterate 'act' region, this computes all derived clocks updaed in the + // Active scheduling region, but does not commit any NBAs that executed + // in 'act' region logic. + while (true) { + _eval__triggers__act(); + // If no 'act' region trigger is active + if (!act_triggers.any()) break; + // Remember what 'act' triggers were active, 'nba' uses the same + latch_act_triggers_for_nba(); + _eval_act(); + } - // Evaluate all other Active region logic, and commit NBAs - _eval_nba(); - } - } + // If no 'nba' region trigger is active + if (!nba_triggers.any()) break; + + // Evaluate all other Active region logic, and commit NBAs + _eval_nba(); + } + } Timing @@ -553,7 +552,7 @@ There are several runtime classes used for managing such coroutines defined in ``verilated_timing.h`` and ``verilated_timing.cpp``. ``VlCoroutineHandle`` -^^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~~ A thin wrapper around an ``std::coroutine_handle<>``. It forces move semantics, destroys the coroutine if it remains suspended at the end of the design's @@ -561,17 +560,17 @@ lifetime, and prevents multiple ``resume`` calls in the case of ``fork..join_any``. ``VlCoroutine`` -^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~ Return value of all coroutines. Together with the promise type contained -within, it allows for chaining coroutines – resuming coroutines from up the +within, it allows for chaining coroutines - resuming coroutines from up the call stack. The calling coroutine's handle is saved in the promise object as a continuation, that is, the coroutine that must be resumed after the promise's coroutine finishes. This is necessary as C++ coroutines are stackless, meaning each one is suspended independently of others in the call graph. ``VlDelayScheduler`` -^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~ This class manages processes suspended by delays. There is one instance of this class per design. Coroutines ``co_await`` this object's ``delay`` function. @@ -581,11 +580,11 @@ coroutines awaiting the current simulation time are resumed. The current simulation time is retrieved from a ``VerilatedContext`` object. ``VlTriggerScheduler`` -^^^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~~~ This class manages processes that await events (triggers). There is one such object per each trigger awaited by coroutines. Coroutines ``co_await`` this -object's ``trigger`` function. They are stored in two stages – `uncommitted` +object's ``trigger`` function. They are stored in two stages - `uncommitted` and `ready`. First, they land in the `uncommitted` stage, and cannot be resumed. The ``resume`` function resumes all coroutines from the `ready` stage and moves `uncommitted` coroutines into `ready`. The ``commit`` function only @@ -596,7 +595,7 @@ times. See the `Scheduling with timing` section for details on how this is used. ``VlDynamicTriggerScheduler`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Like ``VlTriggerScheduler``, ``VlDynamicTriggerScheduler`` manages processes that await triggers. However, it does not rely on triggers evaluated externally @@ -605,23 +604,24 @@ evaluation. Coroutines that make use of this scheduler must adhere to a certain procedure: :: - __Vtrigger = 0; - - while (!__Vtrigger) { - co_await __VdynSched.evaluation(); -
;
-      __Vtrigger = ;
-      [optionally] co_await __VdynSched.postUpdate();
-      ;
-  }
-  co_await __VdynSched.resumption();
+
+   __Vtrigger = 0;
+   
+   while (!__Vtrigger) {
+       co_await __VdynSched.evaluation();
+       
;
+       __Vtrigger = ;
+       [optionally] co_await __VdynSched.postUpdate();
+       ;
+   }
+   co_await __VdynSched.resumption();
 
 The coroutines get resumed at trigger evaluation time, evaluate their local
 triggers, optionally await the post update step, and if the trigger is set,
 await proper resumption in the 'act' eval step.
 
 ``VlForkSync``
-^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~
 
 Used for synchronizing ``fork..join`` and ``fork..join_any``. Forking
 coroutines ``co_await`` its ``join`` function, and forked ones call ``done``
@@ -629,7 +629,7 @@ when they're finished. Once the required number of coroutines (set using
 ``setCounter``) finish execution, the forking coroutine is resumed.
 
 Awaitable Utilities
-^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~
 
 There are also two small utility awaitable types:
 
@@ -640,7 +640,7 @@ There are also two small utility awaitable types:
   section for more detail.
 
 Timing Pass
-^^^^^^^^^^^
+~~~~~~~~~~~
 
 The visitor in ``V3Timing.cpp`` transforms each timing control into a ``co_await``.
 
@@ -684,7 +684,7 @@ coroutines. The visitor keeps a dependency graph of functions and processes to
 handle such cases.
 
 Scheduling with timing
-^^^^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~~~~
 
 Timing features in Verilator are built on top of the static scheduler. Triggers
 are used for determining which delay or trigger schedulers should resume. A
@@ -711,35 +711,36 @@ All coroutines are committed and resumed in the 'act' eval loop. With timing
 features enabled, the ``_eval()`` function takes this form:
 
 ::
-  void _eval() {
-    while (true) {
-      _eval__triggers__ico();
-      if (!ico_triggers.any()) break;
-      _eval_ico();
-    }
 
-    while (true) {
-      while (true) {
-        _eval__triggers__act();
+   void _eval() {
+     while (true) {
+       _eval__triggers__ico();
+       if (!ico_triggers.any()) break;
+       _eval_ico();
+     }
 
-        // Commit all non-triggered coroutines
-        _timing_commit();
+     while (true) {
+       while (true) {
+         _eval__triggers__act();
 
-        if (!act_triggers.any()) break;
-        latch_act_triggers_for_nba();
+         // Commit all non-triggered coroutines
+         _timing_commit();
 
-        // Resume all triggered coroutines
-        _timing_resume();
+         if (!act_triggers.any()) break;
+         latch_act_triggers_for_nba();
 
-        _eval_act();
-      }
-      if (!nba_triggers.any()) break;
-      _eval_nba();
-    }
-  }
+         // Resume all triggered coroutines
+         _timing_resume();
+
+         _eval_act();
+       }
+       if (!nba_triggers.any()) break;
+       _eval_nba();
+     }
+   }
 
 Forks
-^^^^^
+~~~~~
 
 After the scheduling step, forks sub-statements are transformed into separate
 functions, and these functions are called in place of the sub-statements. These
@@ -774,7 +775,7 @@ synchronization cost is reasonable with so few nodes.
 
 
 Partitioning
-^^^^^^^^^^^^
+~~~~~~~~~~~~
 
 Our partitioner is similar to the one Vivek Sarkar described in his 1989
 paper *Partitioning and Scheduling Parallel Programs for Multiprocessors*.
@@ -783,7 +784,7 @@ Let's define some terms:
 
 
 Par Factor
-^^^^^^^^^^
+~~~~~~~~~~
 
 The available parallelism or "par-factor" of a DAG is the total cost to
 execute all nodes, divided by the cost to execute the longest critical path
@@ -793,7 +794,7 @@ synchronization is zero.
 
 
 Macro Task
-^^^^^^^^^^
+~~~~~~~~~~
 
 When the partitioner coarsens the graph, it combines nodes together.  Each
 fine-grained node represents an atomic "task"; combined nodes in the
@@ -805,7 +806,7 @@ ends.)
 
 
 Edge Contraction
-^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~
 
 Verilator's partitioner, like Sarkar's, primarily relies on "edge
 contraction" to coarsen the graph. It starts with one macro-task per atomic
@@ -813,7 +814,7 @@ task and iteratively combines pairs of edge-connected macro-tasks.
 
 
 Local Critical Path
-^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~
 
 Each node in the graph has a "local" critical path. That's the critical
 path from the start of the graph to the start of the node, plus the node's
@@ -834,7 +835,7 @@ NP-hard).
 
 
 Estimating Logic Costs
-^^^^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~~~~
 
 To compute the cost of any given path through the graph, Verilator
 estimates an execution cost for each task. Each macro-task has an execution
@@ -855,7 +856,7 @@ runtime costs estimates. This is an area to improve.
 
 
 Scheduling Macro-Tasks at Runtime
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 After coarsening the graph, we must schedule the macro-tasks for
 runtime. Sarkar describes two options: you can dynamically schedule tasks
@@ -877,7 +878,7 @@ fragmentation.
 
 
 Locating Variables for Best Spatial Locality
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 After scheduling all code, we attempt to locate variables in memory, such
 that variables accessed by a single macro-task are close together in
@@ -910,11 +911,11 @@ locality in serial mode; that is a possible area for improvement.)
 
 
 Improving Multithreaded Performance Further (a TODO list)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 
 Wave Scheduling
-"""""""""""""""
++++++++++++++++
 
 To allow the Verilated model to run in parallel with the testbench, it
 might be nice to support "wave" scheduling, in which work on a cycle begins
@@ -926,7 +927,7 @@ however, it's probably the best bet for hiding testbench latency.
 
 
 Efficient Dynamic Scheduling
-""""""""""""""""""""""""""""
+++++++++++++++++++++++++++++
 
 To scale to more than a few threads, we may revisit a fully dynamic
 scheduler. For large (>16 core) systems, it might make sense to dedicate an
@@ -936,7 +937,7 @@ would not be prohibitive.
 
 
 Static Scheduling with Runtime Repack
-"""""""""""""""""""""""""""""""""""""
++++++++++++++++++++++++++++++++++++++
 
 We could modify the static scheduling approach by gathering actual
 macro-task execution times at run time, and dynamically re-packing the
@@ -948,7 +949,7 @@ or nonuniform competing memory traffic or whatever.
 
 
 Clock Domain Balancing
-""""""""""""""""""""""
+++++++++++++++++++++++
 
 Right now Verilator makes no attempt to balance clock domains across
 macro-tasks. For a multi-domain model, that could lead to bad gantt chart
@@ -956,7 +957,7 @@ fragmentation. This could be improved if it's a real problem in practice.
 
 
 Other Forms of MTask Balancing
-""""""""""""""""""""""""""""""
+++++++++++++++++++++++++++++++
 
 The largest source of runtime overhead is idle CPUs, which happens due to
 variance between our predicted runtime for each MTask and its actual
@@ -980,7 +981,7 @@ scheduling, but this does not yet guide the packing into mtasks.
 
 
 Performance Regression
-""""""""""""""""""""""
+++++++++++++++++++++++
 
 It would be nice if we had a regression of large designs, with some
 diversity of design styles, to test on both single- and multithreaded
@@ -989,7 +990,7 @@ evaluate the optimizations while minimizing the impact of parasitic noise.
 
 
 Per-Instance Classes
-""""""""""""""""""""
+++++++++++++++++++++
 
 If we have multiple instances of the same module, and they partition
 differently (likely; we make no attempt to partition them the same), then
@@ -1079,7 +1080,7 @@ description of the more advanced features of ``astgen`` are provided here.
 
 
 Generating ``AstNode`` members
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Some of the member s of ``AstNode`` sub-classes are generated by ``astgen``.
 These are emitted as pre-processor macro definitions, which then need to be
@@ -1092,7 +1093,7 @@ comment sections in the body of the ``AstNode`` sub-class definitions.
 
 
 List of ``@astgen`` directives
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 ``@astgen`` directives in comments contained in the body of ``AstNode``
 sub-class definitions are parsed and contribute to the code generated by
@@ -1103,7 +1104,7 @@ a ```` dependent description of the definition. The list of
 
 
 ``op`` operand  directives
-"""""""""""""""""""""""""""""
++++++++++++++++++++++++++++++
 
 The ``op1``, ``op2``, ``op3`` and ``op4`` directives are used to describe the
 name and type of the up to 4 child operands of a node. The syntax of the
@@ -1134,7 +1135,7 @@ that appends new nodes (or lists of nodes) to the child list.
 
 
 ``alias op`` operand alias directives
-""""""""""""""""""""""""""""""""""""""""
+++++++++++++++++++++++++++++++++++++++++
 
 If a super-class already defined a name and type for a child node using the
 ``op`` directive, but a more appropriate name exists in the context of a
@@ -1147,14 +1148,14 @@ Example: ``@astgen alias op1 := condp``
 
 
 Generating ``DfgVertex`` sub-classes
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Most of the ``DfgVertex`` sub-classes are generated by ``astgen``, from the
 definitions of the corresponding ``AstNode`` vertices.
 
 
 Additional features of ``astgen``
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 In addition to generating ``AstNode`` members as described above,
 ``astgen`` is also use to handle some of the repetitive implementation code
@@ -1290,7 +1291,7 @@ and takes an argument type ``AstNode*``.
 
 
 Caution on Using Iterators When Child Changes
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 Visitors often replace one node with another node; V3Width and V3Const
 are major examples. A visitor which is the parent of such a replacement
@@ -1394,56 +1395,20 @@ For all tests to pass, you must install the following packages:
 Controlling the Test Driver
 ---------------------------
 
-Test drivers are written in PERL. All invoke the main test driver script,
-which can provide detailed help on all the features available when writing
-a test driver.
+The test driver script `driver.pl` runs tests; see the `Test Driver`
+section.  The individual test drivers are written in PERL; see `Test
+Language`.
+
+
+Manual Test Execution
+---------------------
+
+A specific regression test can be executed manually. To start the
+"EXAMPLE" test, run the following command.
 
 ::
 
-   test_regress/driver.pl --help
-
-For convenience, a summary of the most commonly used features is provided
-here. All drivers require a call to ``compile`` subroutine to compile the
-test. For run-time tests, this is followed by a call to the ``execute``
-subroutine. Both of these functions can optionally be provided with a hash
-table as argument specifying additional options.
-
-The driver.pl script assumes by default that the source Verilog file name
-matches the test script name. So a test whose driver is
-``t/t_mytest.pl`` will expect a Verilog source file ``t/t_mytest.v``.
-This can be changed using the ``top_filename`` subroutine, for example
-
-::
-
-   top_filename("t/t_myothertest.v");
-
-By default, all tests will run with major simulators (Icarus Verilog, NC,
-VCS, ModelSim, etc.) as well as Verilator, to allow results to be
-compared. However, if you wish a test only to be used with Verilator, you
-can use the following:
-
-::
-
-   scenarios(vlt => 1);
-
-Of the many options that can be set through arguments to ``compiler`` and
-``execute``, the following are particularly useful:
-
-``verilator_flags2``
-  A list of flags to be passed to verilator when compiling.
-
-``fails``
-  Set to 1 to indicate that the compilation or execution is intended to fail.
-
-For example, the following would specify that compilation requires two
-defines and is expected to fail.
-
-::
-
-   compile(
-      verilator_flags2 => ["-DSMALL_CLOCK -DGATED_COMMENT"],
-      fails => 1,
-      );
+   test_regress/t/t_EXAMPLE.pl
 
 
 Regression Testing for Developers
@@ -1494,17 +1459,6 @@ There are some traps to avoid when running regression tests
   ``/etc/security/limits.conf`` file as root.
 
 
-Manual Test Execution
----------------------
-
-A specific regression test can be executed manually. To start the
-"EXAMPLE" test, run the following command.
-
-::
-
-   test_regress/t/t_EXAMPLE.pl
-
-
 Continuous Integration
 ----------------------
 
@@ -1562,7 +1516,7 @@ placed into the obj_dir, .tree and .dot files.
 .dot Output
 -----------
 
-Dot files are dumps of internal graphs in `Graphviz
+Dot files are dumps of internal graphs in `GraphViz
 `__ dot format. When a dot file is dumped,
 Verilator will also print a line on stdout that can be used to format the
 output, for example:
@@ -1717,17 +1671,16 @@ Similarly, the ``NETLIST`` has a list of modules referred to by its
 .tree.dot Output
 ----------------
 
-``*.tree.dot`` files are dumps of the AST Tree in `Graphviz
-`__ dot format. This can be used to
-visualize the AST Tree. The vertices correspond to ``AstNode``
-instances, and the edges represent the pointers (``op1p``,
- ``op2p``, etc) between the nodes.
+``*.tree.dot`` files are dumps of the AST Tree in `GraphViz
+`__ dot format. This can be used to visualize the
+AST Tree. The vertices correspond to ``AstNode`` instances, and the edges
+represent the pointers (``op1p``, ``op2p``, etc) between the nodes.
 
 
 Debugging with GDB
 ------------------
 
-The test_regress/driver.pl script accepts ``--debug --gdb`` to start
+The `driver.pl` script accepts ``--debug --gdb`` to start
 Verilator under gdb and break when an error is hit, or the program is about
 to exit. You can also use ``--debug --gdbbt`` to just backtrace and then
 exit gdb. To debug the Verilated executable, use ``--gdbsim``.
@@ -1810,8 +1763,7 @@ Generally, what would you do to add a new feature?
 1. File an issue (if there isn't already) so others know what you're
    working on.
 
-2. Make a testcase in the test_regress/t/t_EXAMPLE format, see
-   :ref:`Testing`.
+2. Make a testcase in the test_regress/t/t_EXAMPLE format, see `Testing`.
 
 3. If grammar changes are needed, look at the git version of VerilogPerl's
    src/VParseGrammar.y, as this grammar supports the full SystemVerilog
@@ -1822,9 +1774,9 @@ Generally, what would you do to add a new feature?
    Follow the convention described above about the AstNode type hierarchy.
    Ordering of definitions is enforced by ``astgen``.
 
-5. Now you can run "test_regress/t/t_.pl --debug" and it'll
+5. Now you can run ``test_regress/t/t_.pl --debug`` and it'll
    probably fail, but you'll see a
-   "test_regress/obj_dir/t_/*.tree" file which you can examine
+   ``test_regress/obj_dir/t_/*.tree`` file which you can examine
    to see if the parsing worked. See also the sections above on debugging.
 
 6. Modify the later visitor functions to process the new feature as needed.
@@ -1866,14 +1818,403 @@ IEEE 1800-2017 31 Timing checks
 IEEE 1800-2017 32 SDF annotation
     No longer relevant with static timing analysis tools.
 IEEE 1800-2017 33 Config
-    Little/no tool support or industry use.
+    Little industry use.
+
+
+
+Test Driver
+===========
+
+This section documents the test driver script, `driver.pl`.  driver.pl
+invokes Verilator or another simulator on each test file.  For test file
+contents description see `Test Language`.
+
+The driver reports the number of tests which pass, fail, or skipped (some
+resource required by the test is not available, such as SystemC).
+
+There are thousands of tests, and for faster completion you may want to run
+the regression tests with OBJCACHE enabled and in parallel on a machine
+with many cores.  See the -j option and OBJCACHE environment variable.
+
+
+driver.pl Non-Scenario Arguments
+--------------------------------
+
+--benchmark []
+  Show execution times of each step.  If an optional number is given,
+  specifies the number of simulation cycles (for tests that support it).
+
+--debug
+  Same as ``verilator --debug``: Use the debug version of Verilator which
+  enables additional assertions, debugging messages, and structure dump
+  files.
+
+--debugi(-) 
+  Same as ``verilator --debugi level``: Set Verilator internal debugging
+  level globally to the specified debug level (1-10).
+
+--dump-tree
+  Same as ``verilator --dump-tree``: Enable Verilator writing .tree debug
+  files with dumping level 3, which dumps the standard critical stages.
+  For details on the format see `.tree Output`.
+
+--gdb
+  Same as ``verilator --gdb``: Run Verilator under the debugger.
+
+--gdbbt
+  Same as ``verilator --gdbbt``: Run Verilator under the debugger, only to
+  print backtrace information.  Requires ``--debug``.
+
+--gdbsim
+  Run Verilator generated executable under the debugger.
+
+--golden
+  Update golden files, equivalent to ``export HARNESS_UPDATE_GOLDEN=1``.
+
+--hashset /
+  Split tests based on a hash of the test names into  and run only
+  tests in set number  (0..-1).
+
+--help
+  Displays help message and exits.
+
+--j #
+  Run number of parallel tests, or 0 to determine the count based on the
+  number of cores installed.  Requires Perl's Parallel::Forker package.
+
+--quiet
+  Suppress all output except for failures and progress messages every 15
+  seconds.  Intended for use only in automated regressions.  See also
+  ``--rerun``, and ``--verbose`` which is not the opposite of ``--quiet``.
+
+--rerun
+  Rerun all tests that failed in this run. Reruns force the flags
+  ``--no-quiet --j 1``.
+
+--rr
+  Same as ``verilator --rr``: Run Verilator and record with ``rr``.
+
+--rrsim
+  Run Verilator generated executable and record with ``rr``.
+
+--sanitize
+  Enable address sanitizer to compile Verilated C++ code.  This may detect
+  misuses of memory, such as out-of-bound accesses, use-after-free, and
+  memory leaks.
+
+--site
+  Run site specific tests also.
+
+--stop
+  Stop on the first error.
+
+--trace
+  Set the simulator specific flags to request waveform tracing.
+
+--verbose
+  Compile and run the test in verbose mode. This means ``TEST_VERBOSE``
+  will be defined for the test (Verilog and any C++/SystemC wrapper).
+
+--verilated-debug
+  For tests using the standard C++ wrapper, enable runtime debug mode.
+
+
+driver.pl Scenario Arguments
+----------------------------
+
+The following options control which simulator is used, and which tests are
+run.  Multiple flags may be used to run multiple simulators/scenarios
+simultaneously.
+
+--atsim
+  Run ATSIM simulator tests.
+
+--dist
+  Run simulator-agnostic distribution tests.
+
+--ghdl
+  Run GHDL simulator tests.
+
+--iv
+  Run Icarus Verilog simulator tests.
+
+--ms
+  Run ModelSim simulator tests.
+
+--nc
+  Run Cadence NC-Verilog simulator tests.
+
+--vcs
+  Run Synopsys VCS simulator tests.
+
+--vlt
+  Run Verilator tests in single-threaded mode.  Default unless another
+  scenario flag is provided.
+
+--vltmt
+  Run Verilator tests in multithreaded mode.
+
+--xsim
+  Run Xilinx XSim simulator tests.
+
+
+driver.pl Environment
+---------------------
+
+HARNESS_UPDATE_GOLDEN
+  If true, update all .out golden reference files.  Typically, instead the
+  ``--golden`` option is used to update only a single test's reference.
+
+SYSTEMC
+  Root directory name of SystemC kit.  Only used if ``SYSTEMC_INCLUDE`` not
+  set.
+
+SYSTEMC_INCLUDE
+  Directory name with systemc.h in it.
+
+VERILATOR_ATSIM
+  Command to use to invoke Atsim.
+
+VERILATOR_GHDL
+  Command to use to invoke GHDL.
+
+VERILATOR_GDB
+  Command to use to invoke GDB debugger.
+
+VERILATOR_IVERILOG
+  Command to use to invoke Icarus Verilog.
+
+VERILATOR_MAKE
+  Command to use to rebuild Verilator and run single test.
+
+VERILATOR_MODELSIM
+  Command to use to invoke ModelSim.
+
+VERILATOR_NCVERILOG
+  Command to use to invoke ncverilog.
+
+VERILATOR_ROOT
+  Standard path to Verilator distribution root; see primary Verilator
+  documentation.
+
+VERILATOR_TESTS_SITE
+  Used with ``--site``, a colon-separated list of directories with tests to
+  be added to testlist.
+
+VERILATOR_VCS
+  Command to use to invoke VCS.
+
+VERILATOR_XELAB
+  Command to use to invoke XSim xelab
+
+VERILATOR_XVLOG
+  Command to use to invoke XSim xvlog
+
+
+Test Language
+=============
+
+This section describes the format of the ``test_regress/t/*.pl`` test
+language files, executed by `driver.pl`.
+
+Test Language Summary
+---------------------
+
+For convenience, a summary of the most commonly used features is provided
+here, with a reference in a later section. All test files typically have a
+call to the ``lint`` or ``compile`` subroutine to compile the test. For
+run-time tests, this is followed by a call to the ``execute``
+subroutine. Both of these functions can optionally be provided with
+arguments specifying additional options.
+
+If those complete, the script calls ``ok`` to increment the count of
+successful tests and then returns 1 as its result.
+
+The driver.pl script assumes by default that the source Verilog file name
+matches the test script name. So a test whose driver is
+``t/t_mytest.pl`` will expect a Verilog source file ``t/t_mytest.v``.
+This can be changed using the ``top_filename`` subroutine, for example
+
+::
+
+   top_filename("t/t_myothertest.v");
+
+By default, all tests will run with major simulators (Icarus Verilog, NC,
+VCS, ModelSim, etc.) as well as Verilator, to allow results to be
+compared. However, if you wish a test only to be used with Verilator, you
+can use the following:
+
+::
+
+   scenarios(vlt => 1);
+
+Of the many options that can be set through arguments to ``compiler`` and
+``execute``, the following are particularly useful:
+
+``verilator_flags2``
+  A list of flags to be passed to verilator when compiling.
+
+``fails``
+  Set to 1 to indicate that the compilation or execution is intended to fail.
+
+For example, the following would specify that compilation requires two
+defines and is expected to fail.
+
+::
+
+   compile(
+      verilator_flags2 => ["-DSMALL_CLOCK -DGATED_COMMENT"],
+      fails => 1,
+      );
+
+Hints On Writing Tests
+----------------------
+
+There is generally no need for the test to create its own main program or
+top level shell as the driver creates one automatically, however some tests
+require their own C++ or SystemC test harness. This is commonly given the
+same name as the test, but with .cpp as suffix
+(``test_regress/t/t_EXAMPLE.cpp``). This can be specified as follows:
+
+::
+
+   compile(
+      make_top_shell   => 0,
+      make_main        => 0,
+      verilator_flags2 => ["--exe $Self->{t_dir}/$Self->{name}.cpp"], );
+
+Tests should be self-checking, rather than producing lots of output. If a
+test succeeds it should print ``*-* All Finished *-*`` to standard output
+and terminate (in Verilog ``$finish``), if not it should just stop (in
+Verilog ``$stop``) as that signals an error.
+
+If termination should be triggered from the C++ wrapper, the following code
+can be used:
+
+::
+
+   vl_fatal(__FILE__, __LINE__, "dut", "");
+   exit(1);
+
+Where it might be useful for a test to produce output, it should qualify
+this with ``TEST_VERBOSE``. For example in Verilog:
+
+::
+
+   `ifdef TEST_VERBOSE
+       $write("Conditional generate if MASK [%1d] = %d\n", g, MASK[g]);
+   `endif
+
+Or in a hand-written C++ wrapper:
+
+::
+
+   #ifdef TEST_VERBOSE
+      cout << "Read a=" << a << endl;
+   #endif
+
+A filename that should be used to check the output results is given with
+``expect_filename``. This should not generally be used to decide if a test
+has succeeded. However, in the case of tests that are designed to fail at
+compile time, it is the only option. For example:
+
+::
+
+   compile(
+      fails => 1,
+      expect_filename => $Self->{golden_filename},
+      );
+
+Note ``expect_filename`` strips some debugging information from the logfile
+when comparing.
+
+
+Test Language Compile/Lint/Run Arguments
+----------------------------------------
+
+This section describes common arguments to ``compile()``, ``lint()``, and
+``run()``.  The full list of arguments can be found by looking at the
+``driver.pl`` source code.
+
+all_run_flags
+  A list of flags to be passed when running the simulator (Verilated model
+  or one of the other simulators).
+
+check_finished
+  True to indicate successful completion of the test is indicated by the
+  string ``*-* All Finished *-*`` being printed on standard output. This is
+  the normal way for successful tests to finish.
+
+expect
+  A quoted list of strings or regular expression to be matched in the
+  output. See `Hints On Writing Tests` for more detail on how this argument
+  should be used.
+
+fails
+  True to indicate this step is expected to fail.  Tests that are expected
+  to fail generally have _bad in their filename.
+
+make_main
+  False to disable the automatic creation of a C++ test wrapper (for
+  example when a hand-written test wrapper is provided using ``verilator
+  --exe``).
+
+make_top_shell
+  False to disable the automatic creation of a top level shell to run the
+  executable (for example when a hand-written test wrapper is provided
+  using ``verilator --exe``).
+
+ms_flags / ms_flags2 / ms_run_flags
+  The equivalent of ``v_flags``, ``v_flags2`` and ``all_run_flags``, but
+  only for use with the ModelSim simulator.
+
+nc_flags / nc_flags2 / nc_run_flags
+  The equivalent of ``v_flags``, ``v_flags2`` and ``all_run_flags``, but
+  only for use with the Cadence NC simulator.
+
+iv_flags / iv_flags2 / iv_run_flags
+  The equivalent of ``v_flags``, ``v_flags2`` and ``all_run_flags``, but
+  only for use with the Icarus Verilog simulator.
+
+v_flags
+  A list of standard Verilog simulator flags to be passed to the simulator
+  compiler (Verilator or one of the other simulators).  This list is create
+  by the driver and rarely changed, use ``v_flags2`` instead.
+
+v_flags2
+  A list of standard Verilog simulator flags to be passed to the simulator
+  compiler (Verilator or one of the other simulators). Unlike ``v_flags``,
+  these options may be overridden in some simulation files.
+
+  Similar sets of flags exist for atsim, GHDL, Cadence NC, ModelSim and
+  Synopsys VCS.
+
+vcs_flags / vcs_flags2 / vcs_run_flags
+  The equivalent of ``v_flags``, ``v_flags2`` and ``all_run_flags``, but
+  only for use with the Synopsys VCS simulator.
+
+verilator_flags / verilator_flags2
+  The equivalent of ``v_flags`` and ``v_flags2``, but only for use with
+  Verilator.  If a flag is a standard flag, ``+incdir`` for example, pass
+  it with ``v_flags2`` instead.
+
+benchmarksim
+  Output the number of model evaluations and execution time of a test to
+  ``test_output_dir>/_benchmarksim.csv``. Multiple invocations
+  of the same test file will append to to the same .csv file.
+
+xsim_flags / xsim_flags2 / xsim_run_flags
+  The equivalent of ``v_flags``, ``v_flags2`` and ``all_run_flags``, but
+  only for use with the Xilinx XSim simulator.
 
 
 Distribution
 ============
 
-Copyright 2008-2022 by Wilson Snyder. Verilator is free software; you can
+Copyright 2008-2023 by Wilson Snyder. Verilator is free software; you can
 redistribute it and/or modify it under the terms of either the GNU Lesser
 General Public License Version 3 or the Perl Artistic License Version 2.0.
 
+SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
+
 .. |Logo| image:: https://www.veripool.org/img/verilator_256_200_min.png
diff --git a/docs/spelling.txt b/docs/spelling.txt
index a8b15ca87..b77ffb233 100644
--- a/docs/spelling.txt
+++ b/docs/spelling.txt
@@ -213,6 +213,7 @@ Milanovic
 Millis
 MinW
 Mindspeed
+MingW
 Miodrag
 ModelSim
 Modport
@@ -416,6 +417,7 @@ bitop
 bitstoreal
 blackbox
 bokke
+bool
 brancoliticus
 buf
 bufif
@@ -626,6 +628,7 @@ iostream
 ish
 isunbounded
 isunknown
+jobserver
 killua
 lang
 lcov
@@ -731,6 +734,8 @@ portlists
 posedge
 posix
 postfix
+postincreemnt
+postincrement
 pragma
 pragmas
 pre
@@ -820,6 +825,7 @@ structs
 subcell
 subcells
 subexpressions
+submakes
 submodule
 submodules
 substring
@@ -932,3 +938,4 @@ ypq
 yurivict
 zdave
 Øyvind
+
diff --git a/docs/verilated.dox b/docs/verilated.dox
index 67841f4b1..85d1ef529 100644
--- a/docs/verilated.dox
+++ b/docs/verilated.dox
@@ -1,4 +1,4 @@
-PROJECT_NAME           = "Verilog to Routing - ABC"
+PROJECT_NAME           = "Verilator"
 INPUT                  = ../../include
 OUTPUT_DIRECTORY       = _build/doxygen/verilated
 
diff --git a/docs/xml.rst b/docs/xml.rst
index 9a0656680..9d18a93d1 100644
--- a/docs/xml.rst
+++ b/docs/xml.rst
@@ -70,8 +70,10 @@ The XML document consists of 4 sections within the top level
 Distribution
 ============
 
-Copyright 2020-2022 by Wilson Snyder. Verilator is free software; you can
+Copyright 2020-2023 by Wilson Snyder. Verilator is free software; you can
 redistribute it and/or modify it under the terms of either the GNU Lesser
 General Public License Version 3 or the Perl Artistic License Version 2.0.
 
+SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
+
 .. |Logo| image:: https://www.veripool.org/img/verilator_256_200_min.png
diff --git a/include/verilated.cpp b/include/verilated.cpp
index 7c08480f8..2b1c6f997 100644
--- a/include/verilated.cpp
+++ b/include/verilated.cpp
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2003-2023 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.
@@ -67,7 +67,7 @@
 #if defined(_WIN32) || defined(__MINGW32__)
 # include   // mkdir
 #endif
-#ifdef __linux__
+#ifdef __GLIBC__
 # include 
 # define _VL_HAVE_STACKTRACE
 #endif
@@ -355,10 +355,9 @@ WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE {
     outwp[VL_WORDS_I(obits) - 1] = VL_RAND_RESET_I(32) & VL_MASK_E(obits);
     return outwp;
 }
-
 WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE {
-    for (int i = 0; i < VL_WORDS_I(obits); ++i) outwp[i] = 0;
-    return outwp;
+    // Not inlined to speed up compilation of slowpath code
+    return VL_ZERO_W(obits, outwp);
 }
 
 //===========================================================================
@@ -611,7 +610,7 @@ std::string VL_DECIMAL_NW(int width, const WDataInP lwp) VL_MT_SAFE {
     const int maxdecwidth = (width + 3) * 4 / 3;
     // Or (maxdecwidth+7)/8], but can't have more than 4 BCD bits per word
     VlWide bcd;
-    VL_ZERO_RESET_W(maxdecwidth, bcd);
+    VL_ZERO_W(maxdecwidth, bcd);
     VlWide tmp;
     VlWide tmp2;
     int from_bit = width - 1;
@@ -622,7 +621,7 @@ std::string VL_DECIMAL_NW(int width, const WDataInP lwp) VL_MT_SAFE {
         // Any digits >= 5 need an add 3 (via tmp)
         for (int nibble_bit = 0; nibble_bit < maxdecwidth; nibble_bit += 4) {
             if ((VL_BITRSHIFT_W(bcd, nibble_bit) & 0xf) >= 5) {
-                VL_ZERO_RESET_W(maxdecwidth, tmp2);
+                VL_ZERO_W(maxdecwidth, tmp2);
                 tmp2[VL_BITWORD_E(nibble_bit)] |= VL_EUL(0x3) << VL_BITBIT_E(nibble_bit);
                 VL_ASSIGN_W(maxdecwidth, tmp, bcd);
                 VL_ADD_W(VL_WORDS_I(maxdecwidth), bcd, tmp, tmp2);
@@ -1083,7 +1082,8 @@ static void _vl_vsss_read_str(FILE* fp, int& floc, const WDataInP fromp, const s
     // VL_DBG_MSGF(" _read got='"<>= 1) { VL_ASSIGNBIT_WI(lsb, owp, ld & 1); }
+static void _vl_vsss_setbit(WDataOutP iowp, int obits, int lsb, int nbits, IData ld) VL_MT_SAFE {
+    for (; nbits && lsb < obits; nbits--, lsb++, ld >>= 1) VL_ASSIGNBIT_WI(lsb, iowp, ld & 1);
 }
 static void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const char* strp,
                            size_t posstart, size_t posend) VL_MT_SAFE {
     // Read in base "2^^baseLog2" digits from strp[posstart..posend-1] into owp of size obits.
+    VL_ZERO_W(obits, owp);
     int lsb = 0;
     for (int i = 0, pos = static_cast(posend) - 1;
          i < obits && pos >= static_cast(posstart); --pos) {
@@ -1381,7 +1382,7 @@ static IData getLine(std::string& str, IData fpi, size_t maxLen) VL_MT_SAFE {
         str.push_back(c);
         if (c == '\n') break;
     }
-    return str.size();
+    return static_cast(str.size());
 }
 
 IData VL_FGETS_IXI(int obits, void* destp, IData fpi) VL_MT_SAFE {
@@ -1612,7 +1613,7 @@ IData VL_FREAD_I(int width, int array_lsb, int array_size, void* memp, IData fpi
             *datap |= ((static_cast(c) << static_cast(shift)) & VL_MASK_Q(width));
         } else {
             WDataOutP datap = &(reinterpret_cast(memp))[entry * VL_WORDS_I(width)];
-            if (shift == start_shift) VL_ZERO_RESET_W(width, datap);
+            if (shift == start_shift) VL_ZERO_W(width, datap);
             datap[VL_BITWORD_E(shift)] |= (static_cast(c) << VL_BITBIT_E(shift));
         }
         // Prep for next
@@ -1631,12 +1632,12 @@ std::string VL_STACKTRACE_N() VL_MT_SAFE {
     static VerilatedMutex s_stackTraceMutex;
     const VerilatedLockGuard lock{s_stackTraceMutex};
 
-    constexpr int BT_BUF_SIZE = 100;
-    void* buffer[BT_BUF_SIZE];
     int nptrs = 0;
     char** strings = nullptr;
 
 #ifdef _VL_HAVE_STACKTRACE
+    constexpr int BT_BUF_SIZE = 100;
+    void* buffer[BT_BUF_SIZE];
     nptrs = backtrace(buffer, BT_BUF_SIZE);
     strings = backtrace_symbols(buffer, nptrs);
 #endif
@@ -1701,7 +1702,7 @@ IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_M
     const char* const dp = match.c_str() + 1 /*leading + */ + prefix.length();
     if (match.empty()) return 0;
 
-    VL_ZERO_RESET_W(rbits, rwp);
+    VL_ZERO_W(rbits, rwp);
     switch (std::tolower(fmt)) {
     case 'd': {
         int64_t lld = 0;
@@ -1807,7 +1808,7 @@ std::string VL_TOUPPER_NN(const std::string& ld) VL_PURE {
     return out;
 }
 
-std::string VL_CVT_PACK_STR_NW(int lwords, const WDataInP lwp) VL_MT_SAFE {
+std::string VL_CVT_PACK_STR_NW(int lwords, const WDataInP lwp) VL_PURE {
     // See also _vl_vint_to_string
     char destout[VL_VALUE_STRING_MAX_CHARS + 1];
     const int obits = lwords * VL_EDATASIZE;
@@ -2023,7 +2024,7 @@ void VlReadMem::setData(void* valuep, const std::string& rhs) {
                      & VL_MASK_Q(m_bits);
         } else {
             WDataOutP datap = reinterpret_cast(valuep);
-            if (!innum) VL_ZERO_RESET_W(m_bits, datap);
+            if (!innum) VL_ZERO_W(m_bits, datap);
             _vl_shiftl_inplace_w(m_bits, datap, static_cast(shift));
             datap[0] |= value;
         }
@@ -2567,7 +2568,7 @@ std::pair VerilatedContextImp::argc_argv() VL_MT_SAFE_EXCLUDES(m_ar
     static char** s_argvp = nullptr;
     if (VL_UNLIKELY(!s_loaded)) {
         s_loaded = true;
-        s_argc = m_args.m_argVec.size();
+        s_argc = static_cast(m_args.m_argVec.size());
         s_argvp = new char*[s_argc + 1];
         int in = 0;
         for (const auto& i : m_args.m_argVec) {
@@ -2789,27 +2790,38 @@ static struct {
     VoidPCbList s_exitCbs VL_GUARDED_BY(s_exitMutex);
 } VlCbStatic;
 
-static void addCb(Verilated::VoidPCb cb, void* datap, VoidPCbList& cbs) VL_MT_UNSAFE {
+static void addCbFlush(Verilated::VoidPCb cb, void* datap)
+    VL_MT_SAFE_EXCLUDES(VlCbStatic.s_flushMutex) {
+    const VerilatedLockGuard lock{VlCbStatic.s_flushMutex};
     std::pair pair(cb, datap);
-    cbs.remove(pair);  // Just in case it's a duplicate
-    cbs.push_back(pair);
+    VlCbStatic.s_flushCbs.remove(pair);  // Just in case it's a duplicate
+    VlCbStatic.s_flushCbs.push_back(pair);
 }
-static void removeCb(Verilated::VoidPCb cb, void* datap, VoidPCbList& cbs) VL_MT_UNSAFE {
+static void addCbExit(Verilated::VoidPCb cb, void* datap)
+    VL_MT_SAFE_EXCLUDES(VlCbStatic.s_exitMutex) {
+    const VerilatedLockGuard lock{VlCbStatic.s_exitMutex};
     std::pair pair(cb, datap);
-    cbs.remove(pair);
+    VlCbStatic.s_exitCbs.remove(pair);  // Just in case it's a duplicate
+    VlCbStatic.s_exitCbs.push_back(pair);
+}
+static void removeCbFlush(Verilated::VoidPCb cb, void* datap)
+    VL_MT_SAFE_EXCLUDES(VlCbStatic.s_flushMutex) {
+    const VerilatedLockGuard lock{VlCbStatic.s_flushMutex};
+    std::pair pair(cb, datap);
+    VlCbStatic.s_flushCbs.remove(pair);
+}
+static void removeCbExit(Verilated::VoidPCb cb, void* datap)
+    VL_MT_SAFE_EXCLUDES(VlCbStatic.s_exitMutex) {
+    const VerilatedLockGuard lock{VlCbStatic.s_exitMutex};
+    std::pair pair(cb, datap);
+    VlCbStatic.s_exitCbs.remove(pair);
 }
 static void runCallbacks(const VoidPCbList& cbs) VL_MT_SAFE {
     for (const auto& i : cbs) i.first(i.second);
 }
 
-void Verilated::addFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE {
-    const VerilatedLockGuard lock{VlCbStatic.s_flushMutex};
-    addCb(cb, datap, VlCbStatic.s_flushCbs);
-}
-void Verilated::removeFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE {
-    const VerilatedLockGuard lock{VlCbStatic.s_flushMutex};
-    removeCb(cb, datap, VlCbStatic.s_flushCbs);
-}
+void Verilated::addFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE { addCbFlush(cb, datap); }
+void Verilated::removeFlushCb(VoidPCb cb, void* datap) VL_MT_SAFE { removeCbFlush(cb, datap); }
 void Verilated::runFlushCallbacks() VL_MT_SAFE {
     // Flush routines may call flush, so avoid mutex deadlock
     static std::atomic s_recursing;
@@ -2826,14 +2838,8 @@ void Verilated::runFlushCallbacks() VL_MT_SAFE {
     VL_GCOV_DUMP();
 }
 
-void Verilated::addExitCb(VoidPCb cb, void* datap) VL_MT_SAFE {
-    const VerilatedLockGuard lock{VlCbStatic.s_exitMutex};
-    addCb(cb, datap, VlCbStatic.s_exitCbs);
-}
-void Verilated::removeExitCb(VoidPCb cb, void* datap) VL_MT_SAFE {
-    const VerilatedLockGuard lock{VlCbStatic.s_exitMutex};
-    removeCb(cb, datap, VlCbStatic.s_exitCbs);
-}
+void Verilated::addExitCb(VoidPCb cb, void* datap) VL_MT_SAFE { addCbExit(cb, datap); }
+void Verilated::removeExitCb(VoidPCb cb, void* datap) VL_MT_SAFE { removeCbExit(cb, datap); }
 void Verilated::runExitCallbacks() VL_MT_SAFE {
     static std::atomic s_recursing;
     if (!s_recursing++) {
diff --git a/include/verilated.h b/include/verilated.h
index 9186ed69c..0b4592b27 100644
--- a/include/verilated.h
+++ b/include/verilated.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2003-2023 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.
@@ -364,7 +364,7 @@ protected:
     // assumption is that the restore is allowed to pass different arguments
     struct NonSerializedCommandArgs {
         // Medium speed
-        std::vector m_argVec;  // Aargument list
+        std::vector m_argVec;  // Argument list
         bool m_argVecLoaded = false;  // Ever loaded argument list
     } m_args VL_GUARDED_BY(m_argMutex);
 
@@ -469,7 +469,7 @@ public:
     int randSeed() const VL_MT_SAFE { return m_s.m_randSeed; }
 
     // Time handling
-    /// Returns current simulation time.
+    /// Returns current simulation time in units of timeprecision().
     ///
     /// How Verilator runtime gets the current simulation time:
     ///
@@ -600,7 +600,7 @@ private:
     // Fastpath:
     VerilatedSyms* m_symsp = nullptr;  // Symbol table
     void** m_callbacksp = nullptr;  // Callback table pointer (Fastpath)
-    int m_funcnumMax = 0;  // Maxium function number stored (Fastpath)
+    int m_funcnumMax = 0;  // Maximum function number stored (Fastpath)
     // 4 bytes padding (on -m64), for rent.
     VerilatedVarNameMap* m_varsp = nullptr;  // Variable map
     const char* m_namep = nullptr;  // Scope name (Slowpath)
diff --git a/include/verilated.mk.in b/include/verilated.mk.in
index 9dcff5121..8e040cd79 100644
--- a/include/verilated.mk.in
+++ b/include/verilated.mk.in
@@ -2,7 +2,7 @@
 ######################################################################
 # DESCRIPTION: Makefile commands for all verilated target files
 #
-# Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+# Copyright 2003-2023 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.
@@ -21,7 +21,9 @@ CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@
 
 # Compiler flags to enable profiling
 CFG_CXXFLAGS_PROFILE = @CFG_CXXFLAGS_PROFILE@
-# Select newest language
+# Select language required to compile (often empty)
+CFG_CXXFLAGS_STD = @CFG_CXXFLAGS_STD@
+# Select newest language (unused by this Makefile, for some test's Makefiles)
 CFG_CXXFLAGS_STD_NEWEST = @CFG_CXXFLAGS_STD_NEWEST@
 # Compiler flags to use to turn off unused and generated code warnings, such as -Wno-div-by-zero
 CFG_CXXFLAGS_NO_UNUSED = @CFG_CXXFLAGS_NO_UNUSED@
@@ -36,7 +38,7 @@ CFG_LDLIBS_THREADS = @CFG_LDLIBS_THREADS@
 # Programs
 
 VERILATOR_COVERAGE = $(PERL) $(VERILATOR_ROOT)/bin/verilator_coverage
-VERILATOR_INCLUDER = $(PERL) $(VERILATOR_ROOT)/bin/verilator_includer
+VERILATOR_INCLUDER = $(PYTHON3) $(VERILATOR_ROOT)/bin/verilator_includer
 VERILATOR_CCACHE_REPORT = $(PYTHON3) $(VERILATOR_ROOT)/bin/verilator_ccache_report
 
 ######################################################################
@@ -46,6 +48,10 @@ ifneq ($(words $(CURDIR)),1)
  $(error Unsupported: GNU Make cannot build in directories containing spaces, build elsewhere: '$(CURDIR)')
 endif
 
+######################################################################
+# OS detection
+UNAME_S := $(shell uname -s)
+
 ######################################################################
 # C Preprocessor flags
 
@@ -78,6 +84,12 @@ CPPFLAGS += $(OPT)
 CPPFLAGS += $(M32)
 LDFLAGS  += $(M32)
 
+# On macOS, specify all weak symbols as dynamic_lookup.
+# Otherwise, you get undefined symbol errors.
+ifeq ($(UNAME_S),Darwin)
+	LDFLAGS += -Wl,-U,__Z15vl_time_stamp64v,-U,__Z13sc_time_stampv
+endif
+
 # Allow upper level user makefiles to specify flags they want.
 # These aren't ever set by Verilator, so users are free to override them.
 CPPFLAGS += $(USER_CPPFLAGS)
@@ -130,7 +142,7 @@ endif
 #######################################################################
 ##### Threaded builds
 
-CPPFLAGS += $(CFG_CXXFLAGS_STD_NEWEST)
+CPPFLAGS += $(CFG_CXXFLAGS_STD)
 LDLIBS += $(CFG_LDLIBS_THREADS)
 
 ifneq ($(VM_TIMING),0)
diff --git a/include/verilated.v b/include/verilated.v
index 9de7d615c..e55dbc99d 100644
--- a/include/verilated.v
+++ b/include/verilated.v
@@ -2,7 +2,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2003-2023 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.
diff --git a/include/verilated_config.h.in b/include/verilated_config.h.in
index d64a0b9eb..524ee861f 100644
--- a/include/verilated_config.h.in
+++ b/include/verilated_config.h.in
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2003-2023 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.
diff --git a/include/verilated_cov.cpp b/include/verilated_cov.cpp
index c442bbae7..23953173c 100644
--- a/include/verilated_cov.cpp
+++ b/include/verilated_cov.cpp
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2001-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2001-2023 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.
diff --git a/include/verilated_cov.h b/include/verilated_cov.h
index f3bde5eb4..447ddf6fb 100644
--- a/include/verilated_cov.h
+++ b/include/verilated_cov.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2001-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2001-2023 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.
diff --git a/include/verilated_cov_key.h b/include/verilated_cov_key.h
index ee7ed06a9..e81abecb4 100644
--- a/include/verilated_cov_key.h
+++ b/include/verilated_cov_key.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2001-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2001-2023 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.
diff --git a/include/verilated_dpi.cpp b/include/verilated_dpi.cpp
index a9c1b3aed..afd7b6f67 100644
--- a/include/verilated_dpi.cpp
+++ b/include/verilated_dpi.cpp
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2009-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2009-2023 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.
diff --git a/include/verilated_dpi.h b/include/verilated_dpi.h
index 31989b0b5..18af2fcb1 100644
--- a/include/verilated_dpi.h
+++ b/include/verilated_dpi.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2003-2023 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.
diff --git a/include/verilated_fst_c.cpp b/include/verilated_fst_c.cpp
index 6dd5bbd84..ed93bdf64 100644
--- a/include/verilated_fst_c.cpp
+++ b/include/verilated_fst_c.cpp
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2001-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2001-2023 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.
@@ -191,7 +191,7 @@ void VerilatedFst::declare(uint32_t code, const char* name, int dtypenum, fstVar
         if ((new_it->back() & 0x80)) {
             tmpModName = *new_it;
             tmpModName.pop_back();
-            // If the scope ends with a non-ascii character, it will be 0x80 + fstScopeType
+            // If the scope ends with a non-ASCII character, it will be 0x80 + fstScopeType
             fstWriterSetScope(m_fst, static_cast(new_it->back() & 0x7f),
                               tmpModName.c_str(), nullptr);
         } else {
diff --git a/include/verilated_fst_c.h b/include/verilated_fst_c.h
index dea14aeb6..57671e0d7 100644
--- a/include/verilated_fst_c.h
+++ b/include/verilated_fst_c.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2001-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2001-2023 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.
diff --git a/include/verilated_fst_sc.cpp b/include/verilated_fst_sc.cpp
index 807d2beff..fca25f937 100644
--- a/include/verilated_fst_sc.cpp
+++ b/include/verilated_fst_sc.cpp
@@ -3,7 +3,7 @@
 //
 // THIS MODULE IS PUBLICLY LICENSED
 //
-// Copyright 2001-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2001-2023 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.
diff --git a/include/verilated_fst_sc.h b/include/verilated_fst_sc.h
index f65342146..0f0cc9e2d 100644
--- a/include/verilated_fst_sc.h
+++ b/include/verilated_fst_sc.h
@@ -1,7 +1,7 @@
 // -*- mode: C++; c-file-style: "cc-mode" -*-
 //=============================================================================
 //
-// Copyright 2001-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2001-2023 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.
diff --git a/include/verilated_funcs.h b/include/verilated_funcs.h
index b8d30a793..013193354 100644
--- a/include/verilated_funcs.h
+++ b/include/verilated_funcs.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2003-2023 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.
@@ -100,12 +100,11 @@ inline IData VL_URANDOM_RANGE_I(IData hi, IData lo) {
     }
 }
 
-// These are init time only, so slow is fine
-/// Random reset a signal of given width
+/// Random reset a signal of given width (init time only)
 extern IData VL_RAND_RESET_I(int obits) VL_MT_SAFE;
-/// Random reset a signal of given width
+/// Random reset a signal of given width (init time only)
 extern QData VL_RAND_RESET_Q(int obits) VL_MT_SAFE;
-/// Random reset a signal of given width
+/// Random reset a signal of given width (init time only)
 extern WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE;
 /// Zero reset a signal (slow - else use VL_ZERO_W)
 extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE;
@@ -507,7 +506,7 @@ static inline void VL_ASSIGNBIT_WO(int bit, WDataOutP owp) VL_MT_SAFE {
         int32_t lsb = 0; \
         uint32_t* chunkp = _butemp.get_raw(); \
         while (lsb + VL_SC_BITS_PER_DIGIT < (obits)) { \
-            static_assert(std::is_same::value, "IData and EData missmatch"); \
+            static_assert(std::is_same::value, "IData and EData mismatch"); \
             const uint32_t data = VL_SEL_IWII(lsb + VL_SC_BITS_PER_DIGIT + 1, (rwp).data(), lsb, \
                                               VL_SC_BITS_PER_DIGIT); \
             *chunkp = data & VL_MASK_E(VL_SC_BITS_PER_DIGIT); \
@@ -1246,7 +1245,7 @@ static inline void _vl_insert_QQ(QData& lhsr, QData ld, int hbit, int lbit, int
     const QData insmask = (VL_MASK_Q(hbit - lbit + 1)) << lbit;
     lhsr = (lhsr & ~insmask) | ((ld << lbit) & (insmask & cleanmask));
 }
-static inline void _vl_insert_WI(WDataOutP owp, IData ld, int hbit, int lbit,
+static inline void _vl_insert_WI(WDataOutP iowp, IData ld, int hbit, int lbit,
                                  int rbits = 0) VL_MT_SAFE {
     const int hoffset = VL_BITBIT_E(hbit);
     const int loffset = VL_BITBIT_E(lbit);
@@ -1258,28 +1257,28 @@ static inline void _vl_insert_WI(WDataOutP owp, IData ld, int hbit, int lbit,
 
     if (hoffset == VL_SIZEBITS_E && loffset == 0) {
         // Fast and common case, word based insertion
-        owp[VL_BITWORD_E(lbit)] = ld & cleanmask;
+        iowp[VL_BITWORD_E(lbit)] = ld & cleanmask;
     } else {
         const EData lde = static_cast(ld);
         if (hword == lword) {  // know < EData bits because above checks it
             // Assignment is contained within one word of destination
             const EData insmask = (VL_MASK_E(hoffset - loffset + 1)) << loffset;
-            owp[lword] = (owp[lword] & ~insmask) | ((lde << loffset) & (insmask & cleanmask));
+            iowp[lword] = (iowp[lword] & ~insmask) | ((lde << loffset) & (insmask & cleanmask));
         } else {
             // Assignment crosses a word boundary in destination
             const EData hinsmask = (VL_MASK_E(hoffset - 0 + 1)) << 0;
             const EData linsmask = (VL_MASK_E((VL_EDATASIZE - 1) - loffset + 1)) << loffset;
             const int nbitsonright = VL_EDATASIZE - loffset;  // bits that end up in lword
-            owp[lword] = (owp[lword] & ~linsmask) | ((lde << loffset) & linsmask);
-            owp[hword]
-                = (owp[hword] & ~hinsmask) | ((lde >> nbitsonright) & (hinsmask & cleanmask));
+            iowp[lword] = (iowp[lword] & ~linsmask) | ((lde << loffset) & linsmask);
+            iowp[hword]
+                = (iowp[hword] & ~hinsmask) | ((lde >> nbitsonright) & (hinsmask & cleanmask));
         }
     }
 }
 
 // INTERNAL: Stuff large LHS bit 0++ into OUTPUT at specified offset
 // lwp may be "dirty"
-static inline void _vl_insert_WW(WDataOutP owp, WDataInP const lwp, int hbit, int lbit,
+static inline void _vl_insert_WW(WDataOutP iowp, WDataInP const lwp, int hbit, int lbit,
                                  int rbits = 0) VL_MT_SAFE {
     const int hoffset = VL_BITBIT_E(hbit);
     const int loffset = VL_BITBIT_E(lbit);
@@ -1294,14 +1293,14 @@ static inline void _vl_insert_WW(WDataOutP owp, WDataInP const lwp, int hbit, in
 
     if (hoffset == VL_SIZEBITS_E && loffset == 0) {
         // Fast and common case, word based insertion
-        for (int i = 0; i < (words - 1); ++i) owp[lword + i] = lwp[i];
-        owp[hword] = lwp[words - 1] & cleanmask;
+        for (int i = 0; i < (words - 1); ++i) iowp[lword + i] = lwp[i];
+        iowp[hword] = lwp[words - 1] & cleanmask;
     } else if (loffset == 0) {
         // Non-32bit, but nicely aligned, so stuff all but the last word
-        for (int i = 0; i < (words - 1); ++i) owp[lword + i] = lwp[i];
+        for (int i = 0; i < (words - 1); ++i) iowp[lword + i] = lwp[i];
         // Know it's not a full word as above fast case handled it
         const EData hinsmask = (VL_MASK_E(hoffset - 0 + 1));
-        owp[hword] = (owp[hword] & ~hinsmask) | (lwp[words - 1] & (hinsmask & cleanmask));
+        iowp[hword] = (iowp[hword] & ~hinsmask) | (lwp[words - 1] & (hinsmask & cleanmask));
     } else {
         const EData hinsmask = (VL_MASK_E(hoffset - 0 + 1)) << 0;
         const EData linsmask = (VL_MASK_E((VL_EDATASIZE - 1) - loffset + 1)) << loffset;
@@ -1312,22 +1311,22 @@ static inline void _vl_insert_WW(WDataOutP owp, WDataInP const lwp, int hbit, in
             {  // Lower word
                 const int oword = lword + i;
                 const EData d = lwp[i] << loffset;
-                const EData od = (owp[oword] & ~linsmask) | (d & linsmask);
+                const EData od = (iowp[oword] & ~linsmask) | (d & linsmask);
                 if (oword == hword) {
-                    owp[oword] = (owp[oword] & ~hinsmask) | (od & (hinsmask & cleanmask));
+                    iowp[oword] = (iowp[oword] & ~hinsmask) | (od & (hinsmask & cleanmask));
                 } else {
-                    owp[oword] = od;
+                    iowp[oword] = od;
                 }
             }
             {  // Upper word
                 const int oword = lword + i + 1;
                 if (oword <= hword) {
                     const EData d = lwp[i] >> nbitsonright;
-                    const EData od = (d & ~linsmask) | (owp[oword] & linsmask);
+                    const EData od = (d & ~linsmask) | (iowp[oword] & linsmask);
                     if (oword == hword) {
-                        owp[oword] = (owp[oword] & ~hinsmask) | (od & (hinsmask & cleanmask));
+                        iowp[oword] = (iowp[oword] & ~hinsmask) | (od & (hinsmask & cleanmask));
                     } else {
-                        owp[oword] = od;
+                        iowp[oword] = od;
                     }
                 }
             }
@@ -1335,11 +1334,11 @@ static inline void _vl_insert_WW(WDataOutP owp, WDataInP const lwp, int hbit, in
     }
 }
 
-static inline void _vl_insert_WQ(WDataOutP owp, QData ld, int hbit, int lbit,
+static inline void _vl_insert_WQ(WDataOutP iowp, QData ld, int hbit, int lbit,
                                  int rbits = 0) VL_MT_SAFE {
     VlWide lwp;
     VL_SET_WQ(lwp, ld);
-    _vl_insert_WW(owp, lwp, hbit, lbit, rbits);
+    _vl_insert_WW(iowp, lwp, hbit, lbit, rbits);
 }
 
 // EMIT_RULE: VL_REPLICATE:  oclean=clean>width32, dirty<=width32; lclean=clean; rclean==clean;
@@ -1366,6 +1365,9 @@ static inline QData VL_REPLICATE_QII(int lbits, IData ld, IData rep) VL_PURE {
 static inline WDataOutP VL_REPLICATE_WII(int lbits, WDataOutP owp, IData ld,
                                          IData rep) VL_MT_SAFE {
     owp[0] = ld;
+    // Zeroing all words isn't strictly needed but allows compiler to know
+    // it does not need to preserve data in word(s) not being written
+    for (unsigned i = 1; i < VL_WORDS_I(static_cast(lbits) * rep); ++i) owp[i] = 0;
     for (unsigned i = 1; i < rep; ++i) {
         _vl_insert_WI(owp, ld, i * lbits + lbits - 1, i * lbits);
     }
@@ -1374,6 +1376,9 @@ static inline WDataOutP VL_REPLICATE_WII(int lbits, WDataOutP owp, IData ld,
 static inline WDataOutP VL_REPLICATE_WQI(int lbits, WDataOutP owp, QData ld,
                                          IData rep) VL_MT_SAFE {
     VL_SET_WQ(owp, ld);
+    // Zeroing all words isn't strictly needed but allows compiler to know
+    // it does not need to preserve data in word(s) not being written
+    for (unsigned i = 2; i < VL_WORDS_I(static_cast(lbits) * rep); ++i) owp[i] = 0;
     for (unsigned i = 1; i < rep; ++i) {
         _vl_insert_WQ(owp, ld, i * lbits + lbits - 1, i * lbits);
     }
@@ -1381,7 +1386,12 @@ static inline WDataOutP VL_REPLICATE_WQI(int lbits, WDataOutP owp, QData ld,
 }
 static inline WDataOutP VL_REPLICATE_WWI(int lbits, WDataOutP owp, WDataInP const lwp,
                                          IData rep) VL_MT_SAFE {
-    for (int i = 0; i < VL_WORDS_I(lbits); ++i) owp[i] = lwp[i];
+    for (unsigned i = 0; i < VL_WORDS_I(static_cast(lbits)); ++i) owp[i] = lwp[i];
+    // Zeroing all words isn't strictly needed but allows compiler to know
+    // it does not need to preserve data in word(s) not being written
+    for (unsigned i = VL_WORDS_I(static_cast(lbits));
+         i < VL_WORDS_I(static_cast(lbits * rep)); ++i)
+        owp[i] = 0;
     for (unsigned i = 1; i < rep; ++i) {
         _vl_insert_WW(owp, lwp, i * lbits + lbits - 1, i * lbits);
     }
@@ -1706,7 +1716,7 @@ static inline WDataOutP VL_SHIFTR_WWQ(int obits, int lbits, int rbits, WDataOutP
 }
 
 static inline IData VL_SHIFTR_IIW(int obits, int, int rbits, IData lhs,
-                                  WDataInP const rwp) VL_MT_SAFE {
+                                  WDataInP const rwp) VL_PURE {
     for (int i = 1; i < VL_WORDS_I(rbits); ++i) {
         if (VL_UNLIKELY(rwp[i])) {  // Huge shift 1>>32 or more
             return 0;
@@ -1715,7 +1725,7 @@ static inline IData VL_SHIFTR_IIW(int obits, int, int rbits, IData lhs,
     return VL_CLEAN_II(obits, obits, lhs >> rwp[0]);
 }
 static inline QData VL_SHIFTR_QQW(int obits, int, int rbits, QData lhs,
-                                  WDataInP const rwp) VL_MT_SAFE {
+                                  WDataInP const rwp) VL_PURE {
     for (int i = 1; i < VL_WORDS_I(rbits); ++i) {
         if (VL_UNLIKELY(rwp[i])) {  // Huge shift 1>>32 or more
             return 0;
@@ -1724,11 +1734,11 @@ static inline QData VL_SHIFTR_QQW(int obits, int, int rbits, QData lhs,
     // Above checks rwp[1]==0 so not needed in below shift
     return VL_CLEAN_QQ(obits, obits, lhs >> (static_cast(rwp[0])));
 }
-static inline IData VL_SHIFTR_IIQ(int obits, int, int, IData lhs, QData rhs) VL_MT_SAFE {
+static inline IData VL_SHIFTR_IIQ(int obits, int, int, IData lhs, QData rhs) VL_PURE {
     if (VL_UNLIKELY(rhs >= VL_IDATASIZE)) return 0;
     return VL_CLEAN_QQ(obits, obits, lhs >> rhs);
 }
-static inline QData VL_SHIFTR_QQQ(int obits, int, int, QData lhs, QData rhs) VL_MT_SAFE {
+static inline QData VL_SHIFTR_QQQ(int obits, int, int, QData lhs, QData rhs) VL_PURE {
     if (VL_UNLIKELY(rhs >= VL_QUADSIZE)) return 0;
     return VL_CLEAN_QQ(obits, obits, lhs >> rhs);
 }
@@ -1803,7 +1813,7 @@ static inline WDataOutP VL_SHIFTRS_WWQ(int obits, int lbits, int rbits, WDataOut
     return VL_SHIFTRS_WWW(obits, lbits, rbits, owp, lwp, rwp);
 }
 static inline IData VL_SHIFTRS_IIW(int obits, int lbits, int rbits, IData lhs,
-                                   WDataInP const rwp) VL_MT_SAFE {
+                                   WDataInP const rwp) VL_PURE {
     EData overshift = 0;  // Huge shift 1>>32 or more
     for (int i = 1; i < VL_WORDS_I(rbits); ++i) overshift |= rwp[i];
     if (VL_UNLIKELY(overshift || rwp[0] >= static_cast(obits))) {
@@ -1813,7 +1823,7 @@ static inline IData VL_SHIFTRS_IIW(int obits, int lbits, int rbits, IData lhs,
     return VL_SHIFTRS_III(obits, lbits, 32, lhs, rwp[0]);
 }
 static inline QData VL_SHIFTRS_QQW(int obits, int lbits, int rbits, QData lhs,
-                                   WDataInP const rwp) VL_MT_SAFE {
+                                   WDataInP const rwp) VL_PURE {
     EData overshift = 0;  // Huge shift 1>>32 or more
     for (int i = 1; i < VL_WORDS_I(rbits); ++i) overshift |= rwp[i];
     if (VL_UNLIKELY(overshift || rwp[0] >= static_cast(obits))) {
@@ -1822,8 +1832,7 @@ static inline QData VL_SHIFTRS_QQW(int obits, int lbits, int rbits, QData lhs,
     }
     return VL_SHIFTRS_QQI(obits, lbits, 32, lhs, rwp[0]);
 }
-static inline IData VL_SHIFTRS_IIQ(int obits, int lbits, int rbits, IData lhs,
-                                   QData rhs) VL_MT_SAFE {
+static inline IData VL_SHIFTRS_IIQ(int obits, int lbits, int rbits, IData lhs, QData rhs) VL_PURE {
     VlWide rwp;
     VL_SET_WQ(rwp, rhs);
     return VL_SHIFTRS_IIW(obits, lbits, rbits, lhs, rwp);
@@ -1985,17 +1994,17 @@ static inline void VL_ASSIGNSEL_QQ(int rbits, int obits, int lsb, QData& lhsr, Q
 }
 // static inline void VL_ASSIGNSEL_IIIW(int obits, int lsb, IData& lhsr, WDataInP const rwp)
 // VL_MT_SAFE { Illegal, as lhs width >= rhs width
-static inline void VL_ASSIGNSEL_WI(int rbits, int obits, int lsb, WDataOutP owp,
+static inline void VL_ASSIGNSEL_WI(int rbits, int obits, int lsb, WDataOutP iowp,
                                    IData rhs) VL_MT_SAFE {
-    _vl_insert_WI(owp, rhs, lsb + obits - 1, lsb, rbits);
+    _vl_insert_WI(iowp, rhs, lsb + obits - 1, lsb, rbits);
 }
-static inline void VL_ASSIGNSEL_WQ(int rbits, int obits, int lsb, WDataOutP owp,
+static inline void VL_ASSIGNSEL_WQ(int rbits, int obits, int lsb, WDataOutP iowp,
                                    QData rhs) VL_MT_SAFE {
-    _vl_insert_WQ(owp, rhs, lsb + obits - 1, lsb, rbits);
+    _vl_insert_WQ(iowp, rhs, lsb + obits - 1, lsb, rbits);
 }
-static inline void VL_ASSIGNSEL_WW(int rbits, int obits, int lsb, WDataOutP owp,
+static inline void VL_ASSIGNSEL_WW(int rbits, int obits, int lsb, WDataOutP iowp,
                                    WDataInP const rwp) VL_MT_SAFE {
-    _vl_insert_WW(owp, rwp, lsb + obits - 1, lsb, rbits);
+    _vl_insert_WW(iowp, rwp, lsb + obits - 1, lsb, rbits);
 }
 
 //======================================================================
@@ -2172,7 +2181,7 @@ extern IData VL_DIST_UNIFORM(IData& seedr, IData ustart, IData uend) VL_MT_SAFE;
 //======================================================================
 // Conversion functions
 
-extern std::string VL_CVT_PACK_STR_NW(int lwords, const WDataInP lwp) VL_MT_SAFE;
+extern std::string VL_CVT_PACK_STR_NW(int lwords, const WDataInP lwp) VL_PURE;
 inline std::string VL_CVT_PACK_STR_NQ(QData lhs) VL_PURE {
     VlWide lw;
     VL_SET_WQ(lw, lhs);
@@ -2198,7 +2207,7 @@ inline std::string VL_REPLICATEN_NNI(const std::string& lhs, IData rep) VL_PURE
     return VL_REPLICATEN_NNQ(lhs, rep);
 }
 
-inline IData VL_LEN_IN(const std::string& ld) { return ld.length(); }
+inline IData VL_LEN_IN(const std::string& ld) { return static_cast(ld.length()); }
 extern std::string VL_TOLOWER_NN(const std::string& ld) VL_PURE;
 extern std::string VL_TOUPPER_NN(const std::string& ld) VL_PURE;
 
diff --git a/include/verilated_heavy.h b/include/verilated_heavy.h
index e4acd8142..d6fc2d97c 100644
--- a/include/verilated_heavy.h
+++ b/include/verilated_heavy.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2010-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2010-2023 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.
diff --git a/include/verilated_imp.h b/include/verilated_imp.h
index 6a005dc85..e357ddcc8 100644
--- a/include/verilated_imp.h
+++ b/include/verilated_imp.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2009-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2009-2023 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.
diff --git a/include/verilated_intrinsics.h b/include/verilated_intrinsics.h
index 51e916223..c1e2fea11 100644
--- a/include/verilated_intrinsics.h
+++ b/include/verilated_intrinsics.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2003-2023 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.
diff --git a/include/verilated_probdist.cpp b/include/verilated_probdist.cpp
index d0b5f39ed..b367d5a82 100644
--- a/include/verilated_probdist.cpp
+++ b/include/verilated_probdist.cpp
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2003-2023 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.
diff --git a/include/verilated_profiler.cpp b/include/verilated_profiler.cpp
index 5aab5df71..db721bbcc 100644
--- a/include/verilated_profiler.cpp
+++ b/include/verilated_profiler.cpp
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2012-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2012-2023 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.
diff --git a/include/verilated_profiler.h b/include/verilated_profiler.h
index 5ca1271ff..b71194f44 100644
--- a/include/verilated_profiler.h
+++ b/include/verilated_profiler.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2012-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2012-2023 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.
diff --git a/include/verilated_save.cpp b/include/verilated_save.cpp
index a4dd64562..26387afc7 100644
--- a/include/verilated_save.cpp
+++ b/include/verilated_save.cpp
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2001-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2001-2023 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.
@@ -60,7 +60,7 @@ static const char* const VLTSAVE_TRAILER_STR = "vltsaved";
 //=============================================================================
 //=============================================================================
 //=============================================================================
-// Searalization
+// Serialization
 
 bool VerilatedDeserialize::readDiffers(const void* __restrict datap,
                                        size_t size) VL_MT_UNSAFE_ONE {
diff --git a/include/verilated_save.h b/include/verilated_save.h
index 5b3385b1e..212c28a67 100644
--- a/include/verilated_save.h
+++ b/include/verilated_save.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2000-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2000-2023 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.
diff --git a/include/verilated_sc.h b/include/verilated_sc.h
index 614382dd1..da6c479ba 100644
--- a/include/verilated_sc.h
+++ b/include/verilated_sc.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2009-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2009-2023 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.
diff --git a/include/verilated_std.sv b/include/verilated_std.sv
index 996bc951b..a5c560920 100644
--- a/include/verilated_std.sv
+++ b/include/verilated_std.sv
@@ -4,7 +4,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2022-2023 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
diff --git a/include/verilated_sym_props.h b/include/verilated_sym_props.h
index 03228467f..f3167126c 100644
--- a/include/verilated_sym_props.h
+++ b/include/verilated_sym_props.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2003-2023 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.
@@ -182,7 +182,7 @@ public:
     }
     // Total size in bytes (note DPI limited to 4GB)
     size_t totalSize() const;
-    // Adjust a data pointer to access a given array element, NuLL if something goes bad
+    // Adjust a data pointer to access a given array element, NULL if something goes bad
     void* datapAdjustIndex(void* datap, int dim, int indx) const;
 };
 
diff --git a/include/verilated_syms.h b/include/verilated_syms.h
index b2ca74849..85a73b21c 100644
--- a/include/verilated_syms.h
+++ b/include/verilated_syms.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2003-2023 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.
diff --git a/include/verilated_threads.cpp b/include/verilated_threads.cpp
index 40adba4bc..c6e327797 100644
--- a/include/verilated_threads.cpp
+++ b/include/verilated_threads.cpp
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2012-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2012-2023 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.
diff --git a/include/verilated_threads.h b/include/verilated_threads.h
index e4c2b9cc3..dfb949f2d 100644
--- a/include/verilated_threads.h
+++ b/include/verilated_threads.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2012-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2012-2023 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.
diff --git a/include/verilated_trace.h b/include/verilated_trace.h
index b9cf68c6c..48b7e3558 100644
--- a/include/verilated_trace.h
+++ b/include/verilated_trace.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2001-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2001-2023 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.
diff --git a/include/verilated_trace_defs.h b/include/verilated_trace_defs.h
index 0ff900ee7..ad3c62054 100644
--- a/include/verilated_trace_defs.h
+++ b/include/verilated_trace_defs.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2001-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2001-2023 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.
diff --git a/include/verilated_trace_imp.h b/include/verilated_trace_imp.h
index 2aba690b5..f4972d163 100644
--- a/include/verilated_trace_imp.h
+++ b/include/verilated_trace_imp.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2001-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2001-2023 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.
@@ -497,7 +497,7 @@ void VerilatedTrace::runCallbacks(const std::vectornumThreads() + 1;
         // Main thread executes all jobs with index % threads == 0
         std::vector mainThreadWorkerData;
-        // Enuque all the jobs
+        // Enqueue all the jobs
         for (unsigned i = 0; i < cbVec.size(); ++i) {
             const CallbackRecord& cbr = cbVec[i];
             // Always get the trace buffer on the main thread
@@ -793,7 +793,7 @@ static inline void cvtSDataToStr(char* dstp, SData value) {
 static inline void cvtIDataToStr(char* dstp, IData value) {
 #ifdef VL_HAVE_AVX2
     // Similar to cvtSDataToStr but the bottom 16-bits are processed in the
-    // top half of the YMM registerss
+    // top half of the YMM registers
     const __m256i a = _mm256_insert_epi32(_mm256_undefined_si256(), value, 0);
     const __m256i b = _mm256_permute4x64_epi64(a, 0);
     const __m256i s = _mm256_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
diff --git a/include/verilated_types.h b/include/verilated_types.h
index 5c852e54a..1442f7d1d 100644
--- a/include/verilated_types.h
+++ b/include/verilated_types.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2003-2023 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.
@@ -212,9 +212,9 @@ struct VlWide final {
 
     // OPERATOR METHODS
     // Default copy assignment operators are used.
-    operator WDataOutP() { return &m_storage[0]; }  // This also allows []
-    operator WDataInP() const { return &m_storage[0]; }  // This also allows []
-    bool operator!=(const VlWide& that) const {
+    operator WDataOutP() VL_PURE { return &m_storage[0]; }  // This also allows []
+    operator WDataInP() const VL_PURE { return &m_storage[0]; }  // This also allows []
+    bool operator!=(const VlWide& that) const VL_PURE {
         for (size_t i = 0; i < T_Words; ++i) {
             if (m_storage[i] != that.m_storage[i]) return true;
         }
@@ -273,6 +273,8 @@ public:
     VlQueue(VlQueue&&) = default;
     VlQueue& operator=(const VlQueue&) = default;
     VlQueue& operator=(VlQueue&&) = default;
+    bool operator==(const VlQueue& rhs) const { return m_deque == rhs.m_deque; }
+    bool operator!=(const VlQueue& rhs) const { return m_deque != rhs.m_deque; }
 
     // Standard copy constructor works. Verilog: assoca = assocb
     // Also must allow conversion from a different T_MaxSize queue
@@ -692,6 +694,8 @@ public:
     VlAssocArray(VlAssocArray&&) = default;
     VlAssocArray& operator=(const VlAssocArray&) = default;
     VlAssocArray& operator=(VlAssocArray&&) = default;
+    bool operator==(const VlAssocArray& rhs) const { return m_map == rhs.m_map; }
+    bool operator!=(const VlAssocArray& rhs) const { return m_map != rhs.m_map; }
 
     // METHODS
     T_Value& atDefault() { return m_defaultValue; }
@@ -1225,6 +1229,9 @@ public:
     T_Class* operator->() const { return m_objp; }
     // For 'if (ptr)...'
     operator bool() const { return m_objp; }
+    // In SV A == B iff both are handles to the same object (IEEE 1800-2017 8.4)
+    bool operator==(const VlClassRef& rhs) const { return m_objp == rhs.m_objp; };
+    bool operator!=(const VlClassRef& rhs) const { return m_objp != rhs.m_objp; };
 };
 
 template 
@@ -1238,6 +1245,42 @@ static inline bool VL_CAST_DYNAMIC(VlClassRef in, VlClassRef& outr) {
     }
 }
 
+//=============================================================================
+// VlSampleQueue stores samples for input clockvars in clocking blocks. At a clocking event,
+// samples from this queue should be written to the correct input clockvar.
+
+template 
+class VlSampleQueue final {
+    // TYPES
+    // Type representing a single value sample at a point in time
+    struct VlSample {
+        uint64_t m_timestamp;  // Timestamp at which the value was sampled
+        T_Sampled m_value;  // The sampled value
+    };
+
+    // MEMBERS
+    std::deque m_queue;  // Queue of samples with timestamps
+
+public:
+    // METHODS
+    // Push a new sample with the given timestamp to the end of the queue
+    void push(uint64_t time, const T_Sampled& value) { m_queue.push_back({time, value}); }
+    // Get the latest sample with its timestamp less than or equal to the given skew
+    void pop(uint64_t time, uint64_t skew, T_Sampled& value) {
+        if (time < skew) return;
+        // Find the last element not greater than (time - skew). Do a binary search, as the queue
+        // should be ordered.
+        auto it = std::lower_bound(m_queue.rbegin(), m_queue.rend(), VlSample{time - skew, {}},
+                                   [](const VlSample& sample, const VlSample& skewed) {
+                                       return sample.m_timestamp > skewed.m_timestamp;
+                                   });
+        if (it != m_queue.rend()) {
+            value = it->m_value;
+            m_queue.erase(m_queue.begin(), it.base());
+        }
+    }
+};
+
 //======================================================================
 
 #define VL_NEW(Class, ...) \
diff --git a/include/verilated_vcd_c.cpp b/include/verilated_vcd_c.cpp
index e65b0380f..f1d93a183 100644
--- a/include/verilated_vcd_c.cpp
+++ b/include/verilated_vcd_c.cpp
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2001-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2001-2023 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.
@@ -527,7 +527,7 @@ void VerilatedVcd::declare(uint32_t code, const char* name, const char* wirep, b
                 std::strlen(buf));  // Code (overwrite separator if isBit)
     entryp[length + !isBit] = '\n';  // Replace '\0' with line termination '\n'
     // Set length of suffix (used to increment write pointer)
-    entryp[VL_TRACE_SUFFIX_ENTRY_SIZE - 1] = !isBit + length + 1;
+    entryp[VL_TRACE_SUFFIX_ENTRY_SIZE - 1] = static_cast(length + !isBit + 1);
     decl += " ";
     decl += basename;
     if (array) {
diff --git a/include/verilated_vcd_c.h b/include/verilated_vcd_c.h
index 233f86192..9ffceaa87 100644
--- a/include/verilated_vcd_c.h
+++ b/include/verilated_vcd_c.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2001-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2001-2023 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.
diff --git a/include/verilated_vcd_sc.cpp b/include/verilated_vcd_sc.cpp
index dcccc975b..fa262cb0c 100644
--- a/include/verilated_vcd_sc.cpp
+++ b/include/verilated_vcd_sc.cpp
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2001-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2001-2023 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.
diff --git a/include/verilated_vcd_sc.h b/include/verilated_vcd_sc.h
index 2905a37cf..4ef558fb4 100644
--- a/include/verilated_vcd_sc.h
+++ b/include/verilated_vcd_sc.h
@@ -1,7 +1,7 @@
 // -*- mode: C++; c-file-style: "cc-mode" -*-
 //=============================================================================
 //
-// Copyright 2001-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2001-2023 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.
diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp
index ffabf253f..4c255ed79 100644
--- a/include/verilated_vpi.cpp
+++ b/include/verilated_vpi.cpp
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2009-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2009-2023 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.
@@ -126,34 +126,18 @@ public:
     virtual PLI_INT32 dovpi_remove_cb() { return 0; }
 };
 
-class VerilatedVpioTimedCb final : public VerilatedVpio {
-    // A handle to a timed callback created with vpi_register_cb
-    // User can call vpi_remove_cb or vpi_release_handle on it
-    const uint64_t m_id;  // Unique id/sequence number to find schedule's event
-    const QData m_time;
-
-public:
-    VerilatedVpioTimedCb(uint64_t id, QData time)
-        : m_id{id}
-        , m_time{time} {}
-    ~VerilatedVpioTimedCb() override = default;
-    static VerilatedVpioTimedCb* castp(vpiHandle h) {
-        return dynamic_cast(reinterpret_cast(h));
-    }
-    uint32_t type() const override { return vpiCallback; }
-    PLI_INT32 dovpi_remove_cb() override;
-};
-
 class VerilatedVpioReasonCb final : public VerilatedVpio {
-    // A handle to a non-timed callback created with vpi_register_cb
+    // A handle to a timed or non-timed callback created with vpi_register_cb
     // User can call vpi_remove_cb or vpi_release_handle on it
     const uint64_t m_id;  // Unique id/sequence number to find schedule's event
+    const QData m_time;  // Scheduled time, or 0 = not timed
     const PLI_INT32 m_reason;  // VPI callback reason code
 
 public:
     // cppcheck-suppress uninitVar  // m_value
-    VerilatedVpioReasonCb(uint64_t id, PLI_INT32 reason)
+    VerilatedVpioReasonCb(uint64_t id, QData time, PLI_INT32 reason)
         : m_id{id}
+        , m_time{time}
         , m_reason{reason} {}
     ~VerilatedVpioReasonCb() override = default;
     static VerilatedVpioReasonCb* castp(vpiHandle h) {
@@ -474,7 +458,7 @@ using VerilatedPliCb = PLI_INT32 (*)(struct t_cb_data*);
 
 class VerilatedVpiCbHolder final {
     // Holds information needed to call a callback
-    uint64_t m_id;
+    uint64_t m_id;  // Unique id/sequence number to find schedule's event, 0 = invalid
     s_cb_data m_cbData;
     s_vpi_value m_value;
     VerilatedVpioVar m_varo;  // If a cbValueChange callback, the object we will return
@@ -515,13 +499,15 @@ struct VerilatedVpiTimedCbsCmp {
 class VerilatedVpiError;
 
 class VerilatedVpiImp final {
-    enum { CB_ENUM_MAX_VALUE = cbAtEndOfSimTime + 1 };  // Maxium callback reason
+    enum { CB_ENUM_MAX_VALUE = cbAtEndOfSimTime + 1 };  // Maximum callback reason
     using VpioCbList = std::list;
-    using VpioTimedCbs = std::map, VerilatedVpiCbHolder>;
+    using VpioFutureCbs = std::map, VerilatedVpiCbHolder>;
 
     // All only medium-speed, so use singleton function
-    VpioCbList m_cbObjLists[CB_ENUM_MAX_VALUE];  // Callbacks for each supported reason
-    VpioTimedCbs m_timedCbs;  // Time based callbacks
+    // Callbacks that are past or at current timestamp
+    std::array m_cbCurrentLists;
+    VpioFutureCbs m_futureCbs;  // Time based callbacks for future timestamps
+    VpioFutureCbs m_nextCbs;  // cbNextSimTime callbacks
     VerilatedVpiError* m_errorInfop = nullptr;  // Container for vpi error info
     VerilatedAssertOneThread m_assertOne;  // Assert only called from single thread
     uint64_t m_nextCallbackId = 1;  // Id to identify callback
@@ -535,7 +521,7 @@ public:
     static void assertOneCheck() { s().m_assertOne.check(); }
     static uint64_t nextCallbackId() { return ++s().m_nextCallbackId; }
 
-    static void cbReasonAdd(uint64_t id, const s_cb_data* cb_data_p) {
+    static void cbCurrentAdd(uint64_t id, const s_cb_data* cb_data_p) {
         // The passed cb_data_p was property of the user, so need to recreate
         if (VL_UNCOVERABLE(cb_data_p->reason >= CB_ENUM_MAX_VALUE)) {
             VL_FATAL_MT(__FILE__, __LINE__, "", "vpi bb reason too large");
@@ -544,82 +530,109 @@ public:
                                     cb_data_p->reason, id, cb_data_p->obj););
         VerilatedVpioVar* varop = nullptr;
         if (cb_data_p->reason == cbValueChange) varop = VerilatedVpioVar::castp(cb_data_p->obj);
-        s().m_cbObjLists[cb_data_p->reason].emplace_back(id, cb_data_p, varop);
+        s().m_cbCurrentLists[cb_data_p->reason].emplace_back(id, cb_data_p, varop);
     }
-    static void cbTimedAdd(uint64_t id, const s_cb_data* cb_data_p, QData time) {
+    static void cbFutureAdd(uint64_t id, const s_cb_data* cb_data_p, QData time) {
         // The passed cb_data_p was property of the user, so need to recreate
-        VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_register_cb reason=%d id=%" PRId64
-                                    " delay=%" PRIu64 "\n",
-                                    cb_data_p->reason, id, time););
-        s().m_timedCbs.emplace(std::piecewise_construct,
-                               std::forward_as_tuple(std::make_pair(time, id)),
-                               std::forward_as_tuple(id, cb_data_p, nullptr));
+        VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_register_cb reason=%d id=%" PRId64 " time=%" PRIu64
+                                    " obj=%p\n",
+                                    cb_data_p->reason, id, time, cb_data_p->obj););
+        s().m_futureCbs.emplace(std::piecewise_construct,
+                                std::forward_as_tuple(std::make_pair(time, id)),
+                                std::forward_as_tuple(id, cb_data_p, nullptr));
     }
-    static void cbReasonRemove(uint64_t id, uint32_t reason) {
+    static void cbNextAdd(uint64_t id, const s_cb_data* cb_data_p, QData time) {
+        // The passed cb_data_p was property of the user, so need to recreate
+        VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_register_cb reason=%d(NEXT) id=%" PRId64
+                                    " time=%" PRIu64 " obj=%p\n",
+                                    cb_data_p->reason, id, time, cb_data_p->obj););
+        s().m_nextCbs.emplace(std::piecewise_construct,
+                              std::forward_as_tuple(std::make_pair(time, id)),
+                              std::forward_as_tuple(id, cb_data_p, nullptr));
+    }
+    static void cbReasonRemove(uint64_t id, uint32_t reason, QData time) {
         // Id might no longer exist, if already removed due to call after event, or teardown
-        VpioCbList& cbObjList = s().m_cbObjLists[reason];
         // We do not remove it now as we may be iterating the list,
         // instead set to nullptr and will cleanup later
-        for (auto& ir : cbObjList) {
-            if (ir.id() == id) ir.invalidate();
+        // Remove from cbCurrent queue
+        for (auto& ir : s().m_cbCurrentLists[reason]) {
+            if (ir.id() == id) {
+                ir.invalidate();
+                return;  // Once found, it won't also be in m_futureCbs
+            }
+        }
+        {  // Remove from cbFuture queue
+            const auto it = s().m_futureCbs.find(std::make_pair(time, id));
+            if (it != s().m_futureCbs.end()) {
+                it->second.invalidate();
+                return;
+            }
+        }
+        {  // Remove from cbNext
+            const auto it = s().m_nextCbs.find(std::make_pair(time, id));
+            if (it != s().m_nextCbs.end()) {
+                it->second.invalidate();
+                return;
+            }
         }
     }
-    static void cbTimedRemove(uint64_t id, QData time) {
-        // Id might no longer exist, if already removed due to call after event, or teardown
-        const auto it = s().m_timedCbs.find(std::make_pair(time, id));
-        if (VL_LIKELY(it != s().m_timedCbs.end())) it->second.invalidate();
-    }
-    static void callTimedCbs() VL_MT_UNSAFE_ONE {
-        assertOneCheck();
+    static void moveFutureCbs() VL_MT_UNSAFE_ONE {
+        // For any events past current time, move from cbFuture queue to cbCurrent queue
+        if (s().m_futureCbs.empty() && s().m_nextCbs.empty()) return;
+        // VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: moveFutureCbs\n"); dumpCbs(); );
         const QData time = VL_TIME_Q();
-        for (auto it = s().m_timedCbs.begin(); it != s().m_timedCbs.end();) {
-            if (VL_UNLIKELY(it->first.first <= time)) {
-                VerilatedVpiCbHolder& ho = it->second;
-                const auto last_it = it;
-                ++it;
-                if (VL_UNLIKELY(!ho.invalid())) {
-                    VL_DEBUG_IF_PLI(
-                        VL_DBG_MSGF("- vpi: timed_callback id=%" PRId64 "\n", ho.id()););
-                    ho.invalidate();  // Timed callbacks are one-shot
-                    (ho.cb_rtnp())(ho.cb_datap());
-                }
-                s().m_timedCbs.erase(last_it);
-            } else {
-                ++it;
+        for (auto it = s().m_futureCbs.begin();  //
+             VL_UNLIKELY(it != s().m_futureCbs.end() && it->first.first <= time);) {
+            VerilatedVpiCbHolder& hor = it->second;
+            const auto last_it = it;
+            ++it;
+            if (VL_UNLIKELY(!hor.invalid())) {
+                VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: moveFutureCbs id=%" PRId64 "\n", hor.id()););
+                s().m_cbCurrentLists[hor.cb_datap()->reason].emplace_back(hor);
             }
+            s().m_futureCbs.erase(last_it);
+        }
+        for (auto it = s().m_nextCbs.begin();  //
+             VL_UNLIKELY(it != s().m_nextCbs.end() && it->first.first < time);) {
+            VerilatedVpiCbHolder& hor = it->second;
+            const auto last_it = it;
+            ++it;
+            if (VL_UNLIKELY(!hor.invalid())) {
+                VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: moveFutureCbs id=%" PRId64 "\n", hor.id()););
+                s().m_cbCurrentLists[hor.cb_datap()->reason].emplace_back(hor);
+            }
+            s().m_nextCbs.erase(last_it);
         }
     }
     static QData cbNextDeadline() {
-        const auto it = s().m_timedCbs.cbegin();
-        if (VL_LIKELY(it != s().m_timedCbs.cend())) return it->first.first;
+        const auto it = s().m_futureCbs.cbegin();
+        if (VL_LIKELY(it != s().m_futureCbs.cend())) return it->first.first;
         return ~0ULL;  // maxquad
     }
     static bool callCbs(const uint32_t reason) VL_MT_UNSAFE_ONE {
-        VpioCbList& cbObjList = s().m_cbObjLists[reason];
+        VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: callCbs reason=%u\n", reason););
+        assertOneCheck();
+        moveFutureCbs();
+        if (s().m_cbCurrentLists[reason].empty()) return false;
+        // Iterate on old list, making new list empty, to prevent looping over newly added elements
+        VpioCbList cbObjList;
+        std::swap(s().m_cbCurrentLists[reason], cbObjList);
         bool called = false;
-        if (cbObjList.empty()) return called;
-        const auto last = std::prev(cbObjList.end());  // prevent looping over newly added elements
-        for (auto it = cbObjList.begin(); true;) {
+        for (VerilatedVpiCbHolder& ihor : cbObjList) {
             // cbReasonRemove sets to nullptr, so we know on removal the old end() will still exist
-            const bool was_last = it == last;
-            if (VL_UNLIKELY(it->invalid())) {  // Deleted earlier, cleanup
-                it = cbObjList.erase(it);
-                if (was_last) break;
-                continue;
+            if (VL_LIKELY(!ihor.invalid())) {  // Not deleted earlier
+                VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: reason_callback reason=%d id=%" PRId64 "\n",
+                                            reason, ihor.id()););
+                ihor.invalidate();  // Timed callbacks are one-shot
+                (ihor.cb_rtnp())(ihor.cb_datap());
+                called = true;
             }
-            VerilatedVpiCbHolder& ho = *it;
-            VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: reason_callback reason=%d id=%" PRId64 "\n",
-                                        reason, ho.id()););
-            (ho.cb_rtnp())(ho.cb_datap());
-            called = true;
-            if (was_last) break;
-            ++it;
         }
         return called;
     }
     static bool callValueCbs() VL_MT_UNSAFE_ONE {
         assertOneCheck();
-        VpioCbList& cbObjList = s().m_cbObjLists[cbValueChange];
+        VpioCbList& cbObjList = s().m_cbCurrentLists[cbValueChange];
         bool called = false;
         std::unordered_set update;  // set of objects to update after callbacks
         if (cbObjList.empty()) return called;
@@ -658,7 +671,7 @@ public:
         }
         return called;
     }
-
+    static void dumpCbs() VL_MT_UNSAFE_ONE;
     static VerilatedVpiError* error_info() VL_MT_UNSAFE_ONE;  // getter for vpi error info
 };
 
@@ -742,23 +755,21 @@ public:
 //======================================================================
 // VerilatedVpi implementation
 
-void VerilatedVpi::callTimedCbs() VL_MT_UNSAFE_ONE { VerilatedVpiImp::callTimedCbs(); }
-
-bool VerilatedVpi::callValueCbs() VL_MT_UNSAFE_ONE { return VerilatedVpiImp::callValueCbs(); }
-
 bool VerilatedVpi::callCbs(uint32_t reason) VL_MT_UNSAFE_ONE {
     return VerilatedVpiImp::callCbs(reason);
 }
 
+// Historical, before we had multiple kinds of timed callbacks
+void VerilatedVpi::callTimedCbs() VL_MT_UNSAFE_ONE { VerilatedVpiImp::callCbs(cbAfterDelay); }
+
+bool VerilatedVpi::callValueCbs() VL_MT_UNSAFE_ONE { return VerilatedVpiImp::callValueCbs(); }
+
 QData VerilatedVpi::cbNextDeadline() VL_MT_UNSAFE_ONE { return VerilatedVpiImp::cbNextDeadline(); }
 
-PLI_INT32 VerilatedVpioTimedCb::dovpi_remove_cb() {
-    VerilatedVpiImp::cbTimedRemove(m_id, m_time);
-    delete this;  // IEEE 37.2.2 a vpi_remove_cb does a vpi_release_handle
-    return 1;
-}
+void VerilatedVpi::dumpCbs() VL_MT_UNSAFE_ONE { VerilatedVpiImp::dumpCbs(); }
+
 PLI_INT32 VerilatedVpioReasonCb::dovpi_remove_cb() {
-    VerilatedVpiImp::cbReasonRemove(m_id, m_reason);
+    VerilatedVpiImp::cbReasonRemove(m_id, m_reason, m_time);
     delete this;  // IEEE 37.2.2 a vpi_remove_cb does a vpi_release_handle
     return 1;
 }
@@ -766,6 +777,42 @@ PLI_INT32 VerilatedVpioReasonCb::dovpi_remove_cb() {
 //======================================================================
 // VerilatedVpiImp implementation
 
+void VerilatedVpiImp::dumpCbs() VL_MT_UNSAFE_ONE {
+    assertOneCheck();
+    VL_DBG_MSGF("- vpi: dumpCbs\n");
+    for (uint32_t reason = 0; reason < CB_ENUM_MAX_VALUE; ++reason) {
+        VpioCbList& cbObjList = s().m_cbCurrentLists[reason];
+        for (auto& ho : cbObjList) {
+            if (VL_UNLIKELY(!ho.invalid())) {
+                VL_DBG_MSGF("- vpi:   reason=%d=%s  id=%" PRId64 "\n", reason,
+                            VerilatedVpiError::strFromVpiCallbackReason(reason), ho.id());
+            }
+        }
+    }
+    for (auto& ifuture : s().m_nextCbs) {
+        const QData time = ifuture.first.first;
+        const uint64_t id = ifuture.first.second;
+        VerilatedVpiCbHolder& ho = ifuture.second;
+        if (VL_UNLIKELY(!ho.invalid())) {
+            VL_DBG_MSGF("- vpi:   time=%" PRId64 "(NEXT) reason=%d=%s  id=%" PRId64 "\n", time,
+                        ho.cb_datap()->reason,
+                        VerilatedVpiError::strFromVpiCallbackReason(ho.cb_datap()->reason),
+                        ho.id());
+        }
+    }
+    for (auto& ifuture : s().m_futureCbs) {
+        const QData time = ifuture.first.first;
+        const uint64_t id = ifuture.first.second;
+        VerilatedVpiCbHolder& ho = ifuture.second;
+        if (VL_UNLIKELY(!ho.invalid())) {
+            VL_DBG_MSGF("- vpi:   time=%" PRId64 " reason=%d=%s  id=%" PRId64 "\n", time,
+                        ho.cb_datap()->reason,
+                        VerilatedVpiError::strFromVpiCallbackReason(ho.cb_datap()->reason),
+                        ho.id());
+        }
+    }
+}
+
 VerilatedVpiError* VerilatedVpiImp::error_info() VL_MT_UNSAFE_ONE {
     VerilatedVpiImp::assertOneCheck();
     if (VL_UNLIKELY(!s().m_errorInfop)) s().m_errorInfop = new VerilatedVpiError;
@@ -1306,34 +1353,54 @@ vpiHandle vpi_register_cb(p_cb_data cb_data_p) {
         VL_VPI_WARNING_(__FILE__, __LINE__, "%s : callback data pointer is null", __func__);
         return nullptr;
     }
-    switch (cb_data_p->reason) {
-    case cbAfterDelay: {
-        QData time = 0;
-        if (cb_data_p->time) time = VL_SET_QII(cb_data_p->time->high, cb_data_p->time->low);
-        const QData abstime = VL_TIME_Q() + time;
+    const PLI_INT32 reason = cb_data_p->reason;
+    switch (reason) {
+    case cbAfterDelay:  // FALLTHRU // One-shot; time relative
+    case cbAtEndOfSimTime:  // FALLTHRU // One-shot; time absolute; supported via vlt_main.cpp
+    case cbAtStartOfSimTime:  // FALLTHRU // One-shot; time absolute; supported via vlt_main.cpp
+    case cbReadOnlySynch:  // FALLTHRU // One-shot; time relative; supported via vlt_main.cpp
+    case cbReadWriteSynch: {  // One-shot; time relative; supported via vlt_main.cpp
+        const bool abs = reason == cbAtStartOfSimTime || reason == cbAtEndOfSimTime;
+        const QData time = VL_TIME_Q();
+        QData abstime = 0;
+        if (cb_data_p->time) {
+            if (abs) {
+                abstime = VL_SET_QII(cb_data_p->time->high, cb_data_p->time->low);
+            } else {
+                abstime = time + VL_SET_QII(cb_data_p->time->high, cb_data_p->time->low);
+            }
+        }
         const uint64_t id = VerilatedVpiImp::nextCallbackId();
-        VerilatedVpioTimedCb* const vop = new VerilatedVpioTimedCb{id, abstime};
-        VerilatedVpiImp::cbTimedAdd(id, cb_data_p, abstime);
+        VerilatedVpioReasonCb* const vop = new VerilatedVpioReasonCb{id, abstime, reason};
+        if (abstime <= time) {
+            VerilatedVpiImp::cbCurrentAdd(id, cb_data_p);
+        } else {
+            VerilatedVpiImp::cbFutureAdd(id, cb_data_p, abstime);
+        }
         return vop->castVpiHandle();
     }
-    case cbReadWriteSynch:  // FALLTHRU // Supported via vlt_main.cpp
-    case cbReadOnlySynch:  // FALLTHRU // Supported via vlt_main.cpp
-    case cbNextSimTime:  // FALLTHRU // Supported via vlt_main.cpp
-    case cbStartOfSimulation:  // FALLTHRU // Supported via vlt_main.cpp
-    case cbEndOfSimulation:  // FALLTHRU // Supported via vlt_main.cpp
-    case cbValueChange:  // FALLTHRU // Supported via vlt_main.cpp
-    case cbPLIError:  // FALLTHRU // NOP, but need to return handle, so make object
+    case cbNextSimTime: {  // One-shot; time always next; supported via vlt_main.cpp
+        const QData time = VL_TIME_Q();
+        const uint64_t id = VerilatedVpiImp::nextCallbackId();
+        VerilatedVpioReasonCb* const vop = new VerilatedVpioReasonCb{id, 0, reason};
+        VerilatedVpiImp::cbNextAdd(id, cb_data_p, time);
+        return vop->castVpiHandle();
+    }
+    case cbEndOfSimulation:  // FALLTHRU // One-shot; time ignored; supported via vlt_main.cpp
     case cbEnterInteractive:  // FALLTHRU // NOP, but need to return handle, so make object
     case cbExitInteractive:  // FALLTHRU // NOP, but need to return handle, so make object
-    case cbInteractiveScopeChange: {  // FALLTHRU // NOP, but need to return handle, so make object
+    case cbInteractiveScopeChange:  // FALLTHRU // NOP, but need to return handle, so make object
+    case cbPLIError:  // FALLTHRU // NOP, but need to return handle, so make object
+    case cbStartOfSimulation:  // FALLTHRU // One-shot; time ignored; supported via vlt_main.cpp
+    case cbValueChange: {  // Multi-shot; supported via vlt_main.cpp
         const uint64_t id = VerilatedVpiImp::nextCallbackId();
-        VerilatedVpioReasonCb* const vop = new VerilatedVpioReasonCb{id, cb_data_p->reason};
-        VerilatedVpiImp::cbReasonAdd(id, cb_data_p);
+        VerilatedVpioReasonCb* const vop = new VerilatedVpioReasonCb{id, 0, reason};
+        VerilatedVpiImp::cbCurrentAdd(id, cb_data_p);
         return vop->castVpiHandle();
     }
     default:
         VL_VPI_WARNING_(__FILE__, __LINE__, "%s: Unsupported callback type %s", __func__,
-                        VerilatedVpiError::strFromVpiCallbackReason(cb_data_p->reason));
+                        VerilatedVpiError::strFromVpiCallbackReason(reason));
         return nullptr;
     }
 }
@@ -1583,7 +1650,7 @@ PLI_INT32 vpi_get(PLI_INT32 property, vpiHandle object) {
         return vop->type();
     }
     case vpiDirection: {
-        // By forthought, the directions already are vpi enumerated
+        // By forethought, the directions already are vpi enumerated
         const VerilatedVpioVarBase* const vop = VerilatedVpioVarBase::castp(object);
         if (VL_UNLIKELY(!vop)) return 0;
         return vop->varp()->vldir();
@@ -1751,13 +1818,13 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
         int i;
         if (bits > t_outStrSz) {
             // limit maximum size of output to size of buffer to prevent overrun.
-            bits = t_outStrSz;
             VL_VPI_WARNING_(
                 __FILE__, __LINE__,
                 "%s: Truncating string value of %s for %s"
                 " as buffer size (%d, VL_VALUE_STRING_MAX_WORDS=%d) is less than required (%d)",
                 __func__, VerilatedVpiError::strFromVpiVal(valuep->format), fullname, t_outStrSz,
                 VL_VALUE_STRING_MAX_WORDS, bits);
+            bits = t_outStrSz;
         }
         for (i = 0; i < bits; ++i) {
             const char val = (datap[i >> 3] >> (i & 7)) & 1;
diff --git a/include/verilated_vpi.h b/include/verilated_vpi.h
index 12cb0088c..0d9679eb7 100644
--- a/include/verilated_vpi.h
+++ b/include/verilated_vpi.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2009-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2009-2023 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.
@@ -52,6 +52,8 @@ public:
     /// Returns time of the next registered VPI callback, or
     /// ~(0ULL) if none are registered
     static QData cbNextDeadline() VL_MT_UNSAFE_ONE;
+    /// Debug dump of callbacks
+    static void dumpCbs() VL_MT_UNSAFE_ONE;
 
     // Self test, for internal use only
     static void selfTest() VL_MT_UNSAFE_ONE;
diff --git a/include/verilatedos.h b/include/verilatedos.h
index 9906e876f..0e30164a3 100644
--- a/include/verilatedos.h
+++ b/include/verilatedos.h
@@ -3,7 +3,7 @@
 //
 // Code available from: https://verilator.org
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2003-2023 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.
@@ -54,19 +54,20 @@
 # define VL_ATTR_PURE __attribute__((pure))
 # define VL_ATTR_UNUSED __attribute__((unused))
 # if !defined(_WIN32) && !defined(__MINGW32__)
+// All VL_ATTR_WEAK symbols must be marked with the macOS -U linker flag in verilated.mk.in
 #  define VL_ATTR_WEAK __attribute__((weak))
 # endif
 # if defined(__clang__)
-#  define VL_ACQUIRE(...) __attribute__((acquire_capability(__VA_ARGS__)))
-#  define VL_ACQUIRE_SHARED(...) __attribute__((acquire_shared_capability(__VA_ARGS__)))
-#  define VL_RELEASE(...) __attribute__((release_capability(__VA_ARGS__)))
-#  define VL_RELEASE_SHARED(...) __attribute__((release_shared_capability(__VA_ARGS__)))
+#  define VL_ACQUIRE(...) __attribute__((annotate("ACQUIRE"))) __attribute__((acquire_capability(__VA_ARGS__)))
+#  define VL_ACQUIRE_SHARED(...) __attribute__((annotate("ACQUIRE_SHARED"))) __attribute__((acquire_shared_capability(__VA_ARGS__)))
+#  define VL_RELEASE(...) __attribute__((annotate("RELEASE"))) __attribute__((release_capability(__VA_ARGS__)))
+#  define VL_RELEASE_SHARED(...) __attribute__((annotate("RELEASE_SHARED"))) __attribute__((release_shared_capability(__VA_ARGS__)))
 #  define VL_TRY_ACQUIRE(...) __attribute__((try_acquire_capability(__VA_ARGS__)))
 #  define VL_TRY_ACQUIRE_SHARED(...) __attribute__((try_acquire_shared_capability(__VA_ARGS__)))
 #  define VL_CAPABILITY(x) __attribute__((capability(x)))
-#  define VL_REQUIRES(x) __attribute__((requires_capability(x)))
-#  define VL_GUARDED_BY(x) __attribute__((guarded_by(x)))
-#  define VL_EXCLUDES(x) __attribute__((locks_excluded(x)))
+#  define VL_REQUIRES(x) __attribute__((annotate("REQUIRES"))) __attribute__((requires_capability(x)))
+#  define VL_GUARDED_BY(x) __attribute__((annotate("GUARDED_BY"))) __attribute__((guarded_by(x)))
+#  define VL_EXCLUDES(x) __attribute__((annotate("EXCLUDES"))) __attribute__((locks_excluded(x)))
 #  define VL_SCOPED_CAPABILITY __attribute__((scoped_lockable))
 # endif
 # define VL_LIKELY(x) __builtin_expect(!!(x), 1)  // Prefer over C++20 [[likely]]
@@ -425,7 +426,11 @@ using ssize_t = uint32_t;  ///< signed size_t; returned from read()
 // Verilated function size macros
 
 #define VL_MULS_MAX_WORDS 16  ///< Max size in words of MULS operation
-#define VL_VALUE_STRING_MAX_WORDS 64  ///< Max size in words of String conversion operation
+
+#ifndef VL_VALUE_STRING_MAX_WORDS
+    #define VL_VALUE_STRING_MAX_WORDS 64  ///< Max size in words of String conversion operation
+#endif
+
 #define VL_VALUE_STRING_MAX_CHARS (VL_VALUE_STRING_MAX_WORDS * VL_EDATASIZE / VL_BYTESIZE)
 
 //=========================================================================
@@ -510,13 +515,24 @@ using ssize_t = uint32_t;  ///< signed size_t; returned from read()
 # define VL_CPU_RELAX() asm volatile("rep; nop" ::: "memory")
 #elif defined(__ia64__)
 # define VL_CPU_RELAX() asm volatile("hint @pause" ::: "memory")
+#elif defined(__armel__) || defined(__ARMEL__)  // Arm, but broken, must be before __arm__
+# define VL_CPU_RELAX() asm volatile("nop" ::: "memory");
 #elif defined(__aarch64__) || defined(__arm__)
 # define VL_CPU_RELAX() asm volatile("yield" ::: "memory")
+#elif defined(__loongarch__)  // LoongArch does not currently have yield/pause
+# define VL_CPU_RELAX() asm volatile("nop" ::: "memory")
+#elif defined(__mips64el__) || defined(__mips__) || defined(__mips64__) || defined(__mips64)
+# define VL_CPU_RELAX() asm volatile("pause" ::: "memory")
 #elif defined(__powerpc64__)
 # define VL_CPU_RELAX() asm volatile("or 1, 1, 1; or 2, 2, 2;" ::: "memory")
-#elif defined(__loongarch__) || defined(__riscv)
-// LoongArch does not currently have a yield/pause instruction
+#elif defined(__riscv)  // RiscV does not currently have yield/pause, but one is proposed
 # define VL_CPU_RELAX() asm volatile("nop" ::: "memory")
+#elif defined(__s390x__)
+# define VL_CPU_RELAX() asm volatile("lr 0,0" ::: "memory")
+#elif defined(__sparc__)
+# define VL_CPU_RELAX() asm volatile("rd %%ccr, %%g0" ::: "memory")
+#elif defined(VL_IGNORE_UNKNOWN_ARCH)
+# define VL_CPU_RELAX()
 #else
 # error "Missing VL_CPU_RELAX() definition."
 #endif
diff --git a/nodist/clang_check_attributes b/nodist/clang_check_attributes
new file mode 100755
index 000000000..825e50520
--- /dev/null
+++ b/nodist/clang_check_attributes
@@ -0,0 +1,895 @@
+#!/usr/bin/env python3
+# pylint: disable=C0114,C0115,C0116,C0209,C0302,R0902,R0911,R0912,R0914,R0915,E1101
+#
+# Copyright 2022-2023 by Wilson Snyder. Verilator is free software; you
+# can redistribute it and/or modify it under the terms of either the GNU Lesser
+# General Public License Version 3 or the Apache License 2.0.
+# SPDX-License-Identifier: LGPL-3.0-only OR Apache-2.0
+
+import argparse
+import os
+import sys
+import shlex
+from typing import Callable, Iterable, Optional, Union
+import dataclasses
+from dataclasses import dataclass
+import enum
+from enum import Enum
+import multiprocessing
+import tempfile
+
+import clang.cindex
+from clang.cindex import CursorKind, Index, TranslationUnitSaveError, TranslationUnitLoadError
+
+
+def fully_qualified_name(node):
+    if node is None:
+        return []
+    if node.kind == CursorKind.TRANSLATION_UNIT:
+        return []
+    res = fully_qualified_name(node.semantic_parent)
+    if res:
+        return res + ([node.displayname] if node.displayname else [])
+    return [node.displayname] if node.displayname else []
+
+
+@dataclass
+class VlAnnotations:
+    mt_start: bool = False
+    mt_safe: bool = False
+    mt_safe_postinit: bool = False
+    mt_unsafe: bool = False
+    mt_unsafe_one: bool = False
+    pure: bool = False
+    guarded: bool = False
+    requires: bool = False
+    excludes: bool = False
+    acquire: bool = False
+    release: bool = False
+
+    def is_mt_safe_context(self):
+        return (not (self.mt_unsafe or self.mt_unsafe_one)
+                and (self.mt_safe or self.mt_start))
+
+    def is_pure_context(self):
+        return self.pure
+
+    def is_mt_unsafe_call(self):
+        return self.mt_unsafe or self.mt_unsafe_one
+
+    def is_mt_safe_call(self):
+        return (not self.is_mt_unsafe_call()
+                and (self.mt_safe or self.mt_safe_postinit or self.pure
+                     or self.requires or self.excludes or self.acquire
+                     or self.release))
+
+    def is_pure_call(self):
+        return self.pure
+
+    def __or__(self, other: "VlAnnotations"):
+        result = VlAnnotations()
+        for key, value in dataclasses.asdict(self).items():
+            setattr(result, key, value | getattr(other, key))
+        return result
+
+    def is_empty(self):
+        for value in dataclasses.asdict(self).values():
+            if value:
+                return False
+        return True
+
+    def __str__(self):
+        result = []
+        for field, value in dataclasses.asdict(self).items():
+            if value:
+                result.append(field)
+        return ", ".join(result)
+
+    @staticmethod
+    def from_nodes_list(nodes: Iterable):
+        result = VlAnnotations()
+        for node in nodes:
+            if node.kind == CursorKind.ANNOTATE_ATTR:
+                if node.displayname == "MT_START":
+                    result.mt_start = True
+                elif node.displayname == "MT_SAFE":
+                    result.mt_safe = True
+                elif node.displayname == "MT_SAFE_POSTINIT":
+                    result.mt_safe_postinit = True
+                elif node.displayname == "MT_UNSAFE":
+                    result.mt_unsafe = True
+                elif node.displayname == "MT_UNSAFE_ONE":
+                    result.mt_unsafe_one = True
+                elif node.displayname == "PURE":
+                    result.pure = True
+                elif node.displayname in ["ACQUIRE", "ACQUIRE_SHARED"]:
+                    result.acquire = True
+                elif node.displayname in ["RELEASE", "RELEASE_SHARED"]:
+                    result.release = True
+                elif node.displayname == "REQUIRES":
+                    result.requires = True
+                elif node.displayname in ["EXCLUDES", "MT_SAFE_EXCLUDES"]:
+                    result.excludes = True
+                elif node.displayname == "GUARDED_BY":
+                    result.guarded = True
+            # Attributes are always at the beginning
+            elif not node.kind.is_attribute():
+                break
+        return result
+
+
+class FunctionType(Enum):
+    UNKNOWN = enum.auto()
+    FUNCTION = enum.auto()
+    METHOD = enum.auto()
+    STATIC_METHOD = enum.auto()
+    CONSTRUCTOR = enum.auto()
+
+    @staticmethod
+    def from_node(node: clang.cindex.Cursor):
+        if node is None:
+            return FunctionType.UNKNOWN
+        if node.kind == CursorKind.FUNCTION_DECL:
+            return FunctionType.FUNCTION
+        if node.kind == CursorKind.CXX_METHOD and node.is_static_method():
+            return FunctionType.STATIC_METHOD
+        if node.kind == CursorKind.CXX_METHOD:
+            return FunctionType.METHOD
+        if node.kind == CursorKind.CONSTRUCTOR:
+            return FunctionType.CONSTRUCTOR
+        return FunctionType.UNKNOWN
+
+
+@dataclass(eq=False)
+class FunctionInfo:
+    name_parts: list[str]
+    usr: str
+    file: str
+    line: int
+    annotations: VlAnnotations
+    ftype: FunctionType
+
+    _hash: Optional[int] = dataclasses.field(default=None,
+                                             init=False,
+                                             repr=False)
+
+    @property
+    def name(self):
+        return "::".join(self.name_parts)
+
+    def __str__(self):
+        return f"[{self.name}@{self.file}:{self.line}]"
+
+    def __hash__(self):
+        if not self._hash:
+            self._hash = hash(f"{self.usr}:{self.file}:{self.line}")
+        return self._hash
+
+    def __eq__(self, other):
+        return (self.usr == other.usr and self.file == other.file
+                and self.line == other.line)
+
+    def copy(self, /, **changes):
+        return dataclasses.replace(self, **changes)
+
+    @staticmethod
+    def from_node(node: clang.cindex.Cursor,
+                  refd: Optional[clang.cindex.Cursor] = None,
+                  annotations: Optional[VlAnnotations] = None):
+        file = os.path.abspath(node.location.file.name)
+        line = node.location.line
+        if annotations is None:
+            annotations = VlAnnotations.from_nodes_list(node.get_children())
+        if refd is None:
+            refd = node.referenced
+        if refd is not None:
+            refd = refd.canonical
+        assert refd is not None
+        name_parts = fully_qualified_name(refd)
+        usr = refd.get_usr()
+        ftype = FunctionType.from_node(refd)
+
+        return FunctionInfo(name_parts, usr, file, line, annotations, ftype)
+
+
+class DiagnosticKind(Enum):
+    ANNOTATIONS_DEF_DECL_MISMATCH = enum.auto()
+    NON_PURE_CALL_IN_PURE_CTX = enum.auto()
+    NON_MT_SAFE_CALL_IN_MT_SAFE_CTX = enum.auto()
+
+    def __lt__(self, other):
+        return self.value < other.value
+
+
+@dataclass
+class Diagnostic:
+    target: FunctionInfo
+    source: FunctionInfo
+    source_ctx: FunctionInfo
+    kind: DiagnosticKind
+
+    _hash: Optional[int] = dataclasses.field(default=None,
+                                             init=False,
+                                             repr=False)
+
+    def __hash__(self):
+        if not self._hash:
+            self._hash = hash(
+                hash(self.target) ^ hash(self.source_ctx) ^ hash(self.kind))
+        return self._hash
+
+
+class CallAnnotationsValidator:
+
+    def __init__(self, diagnostic_cb: Callable[[Diagnostic], None],
+                 is_ignored_top_level: Callable[[clang.cindex.Cursor], bool],
+                 is_ignored_def: Callable[
+                     [clang.cindex.Cursor, clang.cindex.Cursor], bool],
+                 is_ignored_call: Callable[[clang.cindex.Cursor], bool]):
+        self._diagnostic_cb = diagnostic_cb
+        self._is_ignored_top_level = is_ignored_top_level
+        self._is_ignored_call = is_ignored_call
+        self._is_ignored_def = is_ignored_def
+
+        self._index = Index.create()
+
+        self._processed_headers: set[str] = set()
+
+        # Current context
+        self._call_location: Optional[FunctionInfo] = None
+        self._caller: Optional[FunctionInfo] = None
+        self._level: int = 0
+
+    def compile_and_analyze_file(self, source_file: str,
+                                 compiler_args: list[str],
+                                 build_dir: Optional[str]):
+        filename = os.path.abspath(source_file)
+        initial_cwd = "."
+
+        if build_dir:
+            initial_cwd = os.getcwd()
+            os.chdir(build_dir)
+        translation_unit = self._index.parse(filename, compiler_args)
+        has_errors = False
+        for diag in translation_unit.diagnostics:
+            if diag.severity > clang.cindex.Diagnostic.Error:
+                has_errors = True
+        if translation_unit and not has_errors:
+            self.process_translation_unit(translation_unit)
+        else:
+            print(f"%Error: parsing failed: {filename}", file=sys.stderr)
+        if build_dir:
+            os.chdir(initial_cwd)
+
+    def emit_diagnostic(self, target: Union[FunctionInfo, clang.cindex.Cursor],
+                        kind: DiagnosticKind):
+        assert self._caller is not None
+        assert self._call_location is not None
+        source = self._caller
+        source_ctx = self._call_location
+        if isinstance(target, FunctionInfo):
+            self._diagnostic_cb(Diagnostic(target, source, source_ctx, kind))
+        else:
+            self._diagnostic_cb(
+                Diagnostic(FunctionInfo.from_node(target), source, source_ctx,
+                           kind))
+
+    def iterate_children(self, children: Iterable[clang.cindex.Cursor],
+                         handler: Callable[[clang.cindex.Cursor], None]):
+        if children:
+            self._level += 1
+            for child in children:
+                handler(child)
+            self._level -= 1
+
+    @staticmethod
+    def get_referenced_node_info(
+        node: clang.cindex.Cursor
+    ) -> tuple[bool, Optional[clang.cindex.Cursor], VlAnnotations,
+               Iterable[clang.cindex.Cursor]]:
+        if not node.spelling and not node.displayname:
+            return (False, None, VlAnnotations(), [])
+
+        refd = node.referenced
+        if refd is None:
+            raise ValueError("The node does not specify referenced node.")
+
+        refd = refd.canonical
+        children = list(refd.get_children())
+
+        annotations = VlAnnotations.from_nodes_list(children)
+        return (True, refd, annotations, children)
+
+    # Call handling
+
+    def process_method_call(self, node: clang.cindex.Cursor,
+                            refd: clang.cindex.Cursor,
+                            annotations: VlAnnotations):
+        assert self._call_location
+        ctx = self._call_location.annotations
+
+        # MT-safe context
+        if ctx.is_mt_safe_context():
+            is_mt_safe = False
+
+            if annotations.is_mt_safe_call():
+                is_mt_safe = True
+            elif not annotations.is_mt_unsafe_call():
+                # Check whether the object the method is called on is mt-safe
+                def find_object_ref(node):
+                    try:
+                        node = next(node.get_children())
+                        if node.kind == CursorKind.DECL_REF_EXPR:
+                            # Operator on an argument or local object
+                            return node
+                        if node.kind != CursorKind.MEMBER_REF_EXPR:
+                            return None
+                        if node.referenced and node.referenced.kind == CursorKind.FIELD_DECL:
+                            # Operator on a member object
+                            return node
+                        node = next(node.get_children())
+                        if node.kind == CursorKind.UNEXPOSED_EXPR:
+                            node = next(node.get_children())
+                        return node
+                    except StopIteration:
+                        return None
+
+                refn = find_object_ref(node)
+                # class/struct member
+                if refn and refn.kind == CursorKind.MEMBER_REF_EXPR and refn.referenced:
+                    refn = refn.referenced
+                    refna = VlAnnotations.from_nodes_list(refn.get_children())
+                    if refna.guarded:
+                        is_mt_safe = True
+                # variable
+                elif refn and refn.kind == CursorKind.DECL_REF_EXPR and refn.referenced:
+                    # This is probably a local or an argument. Assume it's safe.
+                    is_mt_safe = True
+
+            if not is_mt_safe:
+                self.emit_diagnostic(
+                    FunctionInfo.from_node(refd, refd, annotations),
+                    DiagnosticKind.NON_MT_SAFE_CALL_IN_MT_SAFE_CTX)
+
+        if ctx.is_pure_context():
+            if not annotations.is_pure_call():
+                self.emit_diagnostic(
+                    FunctionInfo.from_node(refd, refd, annotations),
+                    DiagnosticKind.NON_PURE_CALL_IN_PURE_CTX)
+
+    def process_function_call(self, refd: clang.cindex.Cursor,
+                              annotations: VlAnnotations):
+        assert self._call_location
+        ctx = self._call_location.annotations
+
+        # MT-safe context
+        if ctx.is_mt_safe_context():
+            if not annotations.is_mt_safe_call():
+                self.emit_diagnostic(
+                    FunctionInfo.from_node(refd, refd, annotations),
+                    DiagnosticKind.NON_MT_SAFE_CALL_IN_MT_SAFE_CTX)
+        # pure context
+        if ctx.is_pure_context():
+            if not annotations.is_pure_call():
+                self.emit_diagnostic(
+                    FunctionInfo.from_node(refd, refd, annotations),
+                    DiagnosticKind.NON_PURE_CALL_IN_PURE_CTX)
+
+    def process_constructor_call(self, refd: clang.cindex.Cursor,
+                                 annotations: VlAnnotations):
+        assert self._call_location
+        ctx = self._call_location.annotations
+
+        # Constructors are always OK in MT-safe context.
+
+        # pure context
+        if ctx.is_pure_context():
+            if not annotations.is_pure_call(
+            ) and not refd.is_default_constructor():
+                self.emit_diagnostic(
+                    FunctionInfo.from_node(refd, refd, annotations),
+                    DiagnosticKind.NON_PURE_CALL_IN_PURE_CTX)
+
+    def dispatch_call_node(self, node: clang.cindex.Cursor):
+        [supported, refd, annotations, _] = self.get_referenced_node_info(node)
+
+        if not supported:
+            self.iterate_children(node.get_children(),
+                                  self.dispatch_node_inside_definition)
+            return
+
+        assert refd is not None
+        if self._is_ignored_call(refd):
+            return
+
+        assert self._call_location is not None
+        node_file = os.path.abspath(node.location.file.name)
+        self._call_location = self._call_location.copy(file=node_file,
+                                                       line=node.location.line)
+
+        # Standalone functions and static class methods
+        if (refd.kind == CursorKind.FUNCTION_DECL
+                or refd.kind == CursorKind.CXX_METHOD
+                and refd.is_static_method()):
+            self.process_function_call(refd, annotations)
+            return
+        # Function pointer
+        if refd.kind in [
+                CursorKind.VAR_DECL, CursorKind.FIELD_DECL,
+                CursorKind.PARM_DECL
+        ]:
+            self.process_function_call(refd, annotations)
+            return
+        # Non-static class methods
+        if refd.kind == CursorKind.CXX_METHOD:
+            self.process_method_call(node, refd, annotations)
+            return
+        # Conversion method (e.g. `operator int()`)
+        if refd.kind == CursorKind.CONVERSION_FUNCTION:
+            self.process_method_call(node, refd, annotations)
+            return
+        # Constructors
+        if refd.kind == CursorKind.CONSTRUCTOR:
+            self.process_constructor_call(refd, annotations)
+            return
+
+        # Ignore other callables
+        print(f"{refd.location.file.name}:{refd.location.line}: "
+              f"{refd.displayname}    {refd.kind}\n"
+              f"    from: {node.location.file.name}:{node.location.line}")
+
+    # Definition handling
+
+    def dispatch_node_inside_definition(self, node: clang.cindex.Cursor):
+        if node.kind == CursorKind.CALL_EXPR:
+            self.dispatch_call_node(node)
+            return None
+
+        return self.iterate_children(node.get_children(),
+                                     self.dispatch_node_inside_definition)
+
+    def process_function_definition(self, node: clang.cindex.Cursor):
+        [supported, refd, annotations, _] = self.get_referenced_node_info(node)
+
+        if refd and self._is_ignored_def(node, refd):
+            return None
+
+        node_children = list(node.get_children())
+
+        if not supported:
+            return self.iterate_children(node_children, self.dispatch_node)
+
+        assert refd is not None
+
+        prev_caller = self._caller
+        prev_call_location = self._call_location
+
+        def_annotations = VlAnnotations.from_nodes_list(node_children)
+
+        if not (def_annotations.is_empty() or def_annotations == annotations):
+            # Use definition's annotations for the diagnostic
+            # source (i.e. the definition)
+            self._caller = FunctionInfo.from_node(node, refd, def_annotations)
+            self._call_location = self._caller
+
+            self.emit_diagnostic(
+                FunctionInfo.from_node(refd, refd, annotations),
+                DiagnosticKind.ANNOTATIONS_DEF_DECL_MISMATCH)
+
+        # Use concatenation of definition and declaration annotations
+        # for callees validation.
+        self._caller = FunctionInfo.from_node(node, refd,
+                                              def_annotations | annotations)
+        self._call_location = self._caller
+
+        self.iterate_children(node_children,
+                              self.dispatch_node_inside_definition)
+
+        self._call_location = prev_call_location
+        self._caller = prev_caller
+
+        return None
+
+    # Nodes not located inside definition
+
+    def dispatch_node(self, node: clang.cindex.Cursor):
+        if node.is_definition() and node.kind in [
+                CursorKind.CXX_METHOD, CursorKind.FUNCTION_DECL,
+                CursorKind.CONSTRUCTOR, CursorKind.CONVERSION_FUNCTION
+        ]:
+            return self.process_function_definition(node)
+        if node.is_definition() and node.kind in [
+                CursorKind.NAMESPACE, CursorKind.STRUCT_DECL,
+                CursorKind.UNION_DECL, CursorKind.CLASS_DECL
+        ]:
+            return self.iterate_children(node.get_children(),
+                                         self.dispatch_node)
+
+        return self.iterate_children(node.get_children(), self.dispatch_node)
+
+    def process_translation_unit(
+            self, translation_unit: clang.cindex.TranslationUnit):
+        self._level += 1
+        for child in translation_unit.cursor.get_children():
+            if self._is_ignored_top_level(child):
+                continue
+            if self._processed_headers:
+                filename = os.path.abspath(child.location.file.name)
+                if filename in self._processed_headers:
+                    continue
+            self.dispatch_node(child)
+        self._level -= 1
+
+        self._processed_headers.update([
+            os.path.abspath(str(hdr.source))
+            for hdr in translation_unit.get_includes()
+        ])
+
+
+@dataclass
+class CompileCommand:
+    refid: int
+    filename: str
+    args: list[str]
+    directory: str = dataclasses.field(default_factory=os.getcwd)
+
+
+def get_filter_funcs(verilator_root: str):
+    verilator_root = os.path.abspath(verilator_root) + "/"
+
+    def is_ignored_top_level(node: clang.cindex.Cursor) -> bool:
+        # Anything defined in a header outside Verilator root
+        if not node.location.file:
+            return True
+        filename = os.path.abspath(node.location.file.name)
+        return not filename.startswith(verilator_root)
+
+    def is_ignored_def(node: clang.cindex.Cursor,
+                       refd: clang.cindex.Cursor) -> bool:
+        # __*
+        if str(refd.spelling).startswith("__"):
+            return True
+
+        # Anything defined in a header outside Verilator root
+        if not node.location.file:
+            return True
+        filename = os.path.abspath(node.location.file.name)
+        if not filename.startswith(verilator_root):
+            return True
+
+        return False
+
+    def is_ignored_call(refd: clang.cindex.Cursor) -> bool:
+        # __*
+        if str(refd.spelling).startswith("__"):
+            return True
+
+        # std::*
+        fqn = fully_qualified_name(refd)
+        if fqn and fqn[0] == "std":
+            return True
+
+        # Anything declared in a header outside Verilator root
+        if not refd.location.file:
+            return True
+        filename = os.path.abspath(refd.location.file.name)
+        if not filename.startswith(verilator_root):
+            return True
+
+        return False
+
+    return (is_ignored_top_level, is_ignored_def, is_ignored_call)
+
+
+def precompile_header(compile_command: CompileCommand, tmp_dir: str) -> str:
+    try:
+        initial_cwd = os.getcwd()
+        os.chdir(compile_command.directory)
+
+        index = Index.create()
+        translation_unit = index.parse(compile_command.filename,
+                                       compile_command.args)
+        for diag in translation_unit.diagnostics:
+            if diag.severity > clang.cindex.Diagnostic.Error:
+                pch_file = None
+                break
+        else:
+            pch_file = os.path.join(
+                tmp_dir,
+                f"{compile_command.refid:02}_{os.path.basename(compile_command.filename)}.pch"
+            )
+            translation_unit.save(pch_file)
+
+        os.chdir(initial_cwd)
+
+        if pch_file:
+            return pch_file
+
+    except (TranslationUnitSaveError, TranslationUnitLoadError, OSError):
+        pass
+
+    print(
+        f"%Warning: Precompiling failed, skipping: {compile_command.filename}")
+    return ""
+
+
+# Compile and analyze inputs in a single process.
+def run_analysis(ccl: Iterable[CompileCommand], pccl: Iterable[CompileCommand],
+                 diagnostic_cb: Callable[[Diagnostic],
+                                         None], verilator_root: str):
+    (is_ignored_top_level, is_ignored_def,
+     is_ignored_call) = get_filter_funcs(verilator_root)
+
+    prefix = "verilator_clang_check_attributes_"
+    with tempfile.TemporaryDirectory(prefix=prefix) as tmp_dir:
+        extra_args = []
+        for pcc in pccl:
+            pch_file = precompile_header(pcc, tmp_dir)
+            if pch_file:
+                extra_args += ["-include-pch", pch_file]
+
+        cav = CallAnnotationsValidator(diagnostic_cb, is_ignored_top_level,
+                                       is_ignored_def, is_ignored_call)
+        for compile_command in ccl:
+            cav.compile_and_analyze_file(compile_command.filename,
+                                         compile_command.args + extra_args,
+                                         compile_command.directory)
+
+
+class ParallelAnalysisProcess:
+    cav: Optional[CallAnnotationsValidator] = None
+    diags: set[Diagnostic] = dataclasses.field(default_factory=set)
+    tmp_dir: str = ""
+
+    @staticmethod
+    def init_data(verilator_root: str, tmp_dir: str):
+        (is_ignored_top_level, is_ignored_def,
+         is_ignored_call) = get_filter_funcs(verilator_root)
+
+        ParallelAnalysisProcess.cav = CallAnnotationsValidator(
+            ParallelAnalysisProcess._diagnostic_handler, is_ignored_top_level,
+            is_ignored_def, is_ignored_call)
+        ParallelAnalysisProcess.tmp_dir = tmp_dir
+
+    @staticmethod
+    def _diagnostic_handler(diag: Diagnostic):
+        ParallelAnalysisProcess.diags.add(diag)
+
+    @staticmethod
+    def analyze_cpp_file(compile_command: CompileCommand) -> set[Diagnostic]:
+        ParallelAnalysisProcess.diags = set()
+        assert ParallelAnalysisProcess.cav is not None
+        ParallelAnalysisProcess.cav.compile_and_analyze_file(
+            compile_command.filename, compile_command.args,
+            compile_command.directory)
+        return ParallelAnalysisProcess.diags
+
+    @staticmethod
+    def precompile_header(compile_command: CompileCommand) -> str:
+        return precompile_header(compile_command,
+                                 ParallelAnalysisProcess.tmp_dir)
+
+
+# Compile and analyze inputs in multiple processes.
+def run_parallel_analysis(ccl: Iterable[CompileCommand],
+                          pccl: Iterable[CompileCommand],
+                          diagnostic_cb: Callable[[Diagnostic], None],
+                          jobs_count: int, verilator_root: str):
+    prefix = "verilator_clang_check_attributes_"
+    with tempfile.TemporaryDirectory(prefix=prefix) as tmp_dir:
+        with multiprocessing.Pool(
+                processes=jobs_count,
+                initializer=ParallelAnalysisProcess.init_data,
+                initargs=[verilator_root, tmp_dir]) as pool:
+            extra_args = []
+            for pch_file in pool.imap_unordered(
+                    ParallelAnalysisProcess.precompile_header, pccl):
+                if pch_file:
+                    extra_args += ["-include-pch", pch_file]
+
+            if extra_args:
+                for compile_command in ccl:
+                    compile_command.args = compile_command.args + extra_args
+
+            for diags in pool.imap_unordered(
+                    ParallelAnalysisProcess.analyze_cpp_file, ccl, 1):
+                for diag in diags:
+                    diagnostic_cb(diag)
+
+
+class TopDownSummaryPrinter():
+
+    @dataclass
+    class FunctionCallees:
+        info: FunctionInfo
+        calees: set[FunctionInfo]
+        mismatch: Optional[FunctionInfo] = None
+        non_mt_safe_call_in_mt_safe: Optional[FunctionInfo] = None
+        non_pure_call_in_pure: Optional[FunctionInfo] = None
+
+    def __init__(self):
+        self._is_first_group = True
+
+        self._funcs: dict[str, TopDownSummaryPrinter.FunctionCallees] = {}
+        self._unsafe_in_safe: set[str] = set()
+
+    def begin_group(self, label):
+        if not self._is_first_group:
+            print()
+
+        print(f"%Error: {label}")
+
+        self._is_first_group = False
+
+    def handle_diagnostic(self, diag: Diagnostic):
+        usr = diag.source.usr
+        func = self._funcs.get(usr, None)
+        if func is None:
+            func = TopDownSummaryPrinter.FunctionCallees(diag.source, set())
+            self._funcs[usr] = func
+        if diag.kind == DiagnosticKind.ANNOTATIONS_DEF_DECL_MISMATCH:
+            func.mismatch = diag.target
+        else:
+            func.calees.add(diag.target)
+            self._unsafe_in_safe.add(diag.target.usr)
+            if diag.kind == DiagnosticKind.NON_MT_SAFE_CALL_IN_MT_SAFE_CTX:
+                func.non_mt_safe_call_in_mt_safe = diag.target
+            elif diag.kind == DiagnosticKind.NON_PURE_CALL_IN_PURE_CTX:
+                func.non_pure_call_in_pure = diag.target
+
+    def print_summary(self, root_dir: str):
+        row_groups: dict[str, list[list[str]]] = {}
+        column_widths = [0, 0]
+        for func in sorted(self._funcs.values(),
+                           key=lambda func:
+                           (func.info.file, func.info.line, func.info.usr)):
+            func_info = func.info
+            relfile = os.path.relpath(func_info.file, root_dir)
+
+            row_group = []
+            name = f"\"{func_info.name}\" "
+            if func.mismatch:
+                name += "declaration does not match definition"
+            elif func.non_mt_safe_call_in_mt_safe:
+                name += "is mtsafe but calls non-mtsafe function(s)"
+            elif func.non_pure_call_in_pure:
+                name += "is pure but calls non-pure function(s)"
+            else:
+                name += "for unknown reason (please add description)"
+
+            if func.mismatch:
+                mrelfile = os.path.relpath(func.mismatch.file, root_dir)
+                row_group.append([
+                    f"{mrelfile}:{func.mismatch.line}:",
+                    f"[{func.mismatch.annotations}]",
+                    func.mismatch.name + " [declaration]"
+                ])
+
+            row_group.append([
+                f"{relfile}:{func_info.line}:", f"[{func_info.annotations}]",
+                func_info.name
+            ])
+
+            for callee in sorted(func.calees,
+                                 key=lambda func:
+                                 (func.file, func.line, func.usr)):
+                crelfile = os.path.relpath(callee.file, root_dir)
+                row_group.append([
+                    f"{crelfile}:{callee.line}:", f"[{callee.annotations}]",
+                    "  " + callee.name
+                ])
+
+            row_groups[name] = row_group
+
+            for row in row_group:
+                for row_id, value in enumerate(row[0:-1]):
+                    column_widths[row_id] = max(column_widths[row_id],
+                                                len(value))
+
+        for label, rows in sorted(row_groups.items(), key=lambda kv: kv[0]):
+            self.begin_group(label)
+            for row in rows:
+                print(f"{row[0]:<{column_widths[0]}}  "
+                      f"{row[1]:<{column_widths[1]}}    "
+                      f"{row[2]}")
+        print(
+            f"Number of functions reported unsafe: {len(self._unsafe_in_safe)}"
+        )
+
+
+def main():
+    default_verilator_root = os.path.abspath(
+        os.path.join(os.path.dirname(__file__), ".."))
+
+    parser = argparse.ArgumentParser(
+        allow_abbrev=False,
+        formatter_class=argparse.RawDescriptionHelpFormatter,
+        description="""Check function annotations for correctness""",
+        epilog=
+        """Copyright 2022-2023 by Wilson Snyder. Verilator is free software;
+    you can redistribute it and/or modify it under the terms of either the GNU
+    Lesser General Public License Version 3 or the Apache License 2.0.
+    SPDX-License-Identifier: LGPL-3.0-only OR Apache-2.0""")
+
+    parser.add_argument("--verilator-root",
+                        type=str,
+                        default=default_verilator_root,
+                        help="Path to Verilator sources root directory.")
+    parser.add_argument("--jobs",
+                        "-j",
+                        type=int,
+                        default=0,
+                        help="Number of parallel jobs to use.")
+    parser.add_argument("--cxxflags",
+                        type=str,
+                        default=None,
+                        help="Flags passed to clang++.")
+    parser.add_argument(
+        "--compilation-root",
+        type=str,
+        default=os.getcwd(),
+        help="Directory used as CWD when compiling source files.")
+    parser.add_argument(
+        "-c",
+        "--precompile",
+        action="append",
+        help="Header file to be precompiled and cached at the start.")
+    parser.add_argument("file",
+                        type=str,
+                        nargs="+",
+                        help="Source file to analyze.")
+
+    cmdline = parser.parse_args()
+
+    if cmdline.jobs == 0:
+        cmdline.jobs = max(1, len(os.sched_getaffinity(0)))
+
+    if not cmdline.compilation_root:
+        cmdline.compilation_root = cmdline.verilator_root
+
+    verilator_root = os.path.abspath(cmdline.verilator_root)
+    compilation_root = os.path.abspath(cmdline.compilation_root)
+
+    default_cxx_flags = [
+        f"-I{verilator_root}/src",
+        f"-I{verilator_root}/include",
+        f"-I{verilator_root}/src/obj_opt",
+        "-fcoroutines-ts",
+    ]
+    if cmdline.cxxflags is not None:
+        cxxflags = shlex.split(cmdline.cxxflags)
+    else:
+        cxxflags = default_cxx_flags
+
+    precompile_commands_list = []
+
+    if cmdline.precompile:
+        hdr_cxxflags = ['-xc++-header'] + cxxflags
+        for refid, file in enumerate(cmdline.precompile):
+            filename = os.path.abspath(file)
+            compile_command = CompileCommand(refid, filename, hdr_cxxflags,
+                                             compilation_root)
+            precompile_commands_list.append(compile_command)
+
+    compile_commands_list = []
+    for refid, file in enumerate(cmdline.file):
+        filename = os.path.abspath(file)
+        compile_command = CompileCommand(refid, filename, cxxflags,
+                                         compilation_root)
+        compile_commands_list.append(compile_command)
+
+    summary_printer = TopDownSummaryPrinter()
+
+    if cmdline.jobs == 1:
+        run_analysis(compile_commands_list, precompile_commands_list,
+                     summary_printer.handle_diagnostic, verilator_root)
+    else:
+        run_parallel_analysis(compile_commands_list, precompile_commands_list,
+                              summary_printer.handle_diagnostic, cmdline.jobs,
+                              verilator_root)
+
+    summary_printer.print_summary(verilator_root)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/nodist/code_coverage b/nodist/code_coverage
index 5b6bcc53f..2fe0d13ac 100755
--- a/nodist/code_coverage
+++ b/nodist/code_coverage
@@ -348,7 +348,7 @@ files. Run as:
   cd $VERILATOR_ROOT
   nodist/code_coverage""",
     epilog=
-    """Copyright 2019-2022 by Wilson Snyder. This program is free software; you
+    """Copyright 2019-2023 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.
diff --git a/nodist/code_coverage.dat b/nodist/code_coverage.dat
index 5197f226f..d655d2179 100644
--- a/nodist/code_coverage.dat
+++ b/nodist/code_coverage.dat
@@ -1,7 +1,7 @@
 # -*- Python -*-
 # DESCRIPTION: Verilator: Internal C++ code lcov control file
 #
-# Copyright 2019-2022 by Wilson Snyder. This program is free software; you
+# Copyright 2019-2023 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.
diff --git a/nodist/dot_importer b/nodist/dot_importer
index cedf26696..970665d07 100755
--- a/nodist/dot_importer
+++ b/nodist/dot_importer
@@ -87,7 +87,7 @@ parser = argparse.ArgumentParser(
 This x.cpp file is then manually included in V3GraphTest.cpp to verify
 various xsub-algorithms.""",
     epilog=
-    """Copyright 2005-2022 by Wilson Snyder. This program is free software; you
+    """Copyright 2005-2023 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.
diff --git a/nodist/fuzzer/all b/nodist/fuzzer/all
index 8382a7245..ce0be68ce 100755
--- a/nodist/fuzzer/all
+++ b/nodist/fuzzer/all
@@ -10,7 +10,7 @@
 ######################################################################
 
 # Run all steps needed to configure and start fuzzer
-# Note that this assumes the system is a Debian-like Linux distrubution
+# Note that this assumes the system is a Debian-like Linux distribution
 
 set -e
 
diff --git a/nodist/install_test b/nodist/install_test
index 0b1c66052..423400c45 100755
--- a/nodist/install_test
+++ b/nodist/install_test
@@ -118,7 +118,7 @@ parser = argparse.ArgumentParser(
 Verilator kit.  It isn't part of the normal "make test" due to the number
 of builds required.""",
     epilog=
-    """Copyright 2009-2022 by Wilson Snyder. This program is free software; you
+    """Copyright 2009-2023 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.
diff --git a/nodist/leakchecking.txt b/nodist/leakchecking.txt
deleted file mode 100644
index 6155e210c..000000000
--- a/nodist/leakchecking.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-export GLIBCPP_FORCE_NEW=1
-compile with -DVL_LEAK_CHECKS
-valgrind --tool=memcheck --leak-check=yes $VERILATOR_ROOT/verilator_bin_dbg -MMD --bin $VERILATOR_ROOT/verilator_bin_dbg --cc -f $VERILATOR_ROOT/test_c/../test_v/input.vc top.v --no-skip-identical 2>&1 | tee ~/d/aa
-valgrind --tool=memcheck --leak-check=yes $VERILATOR_ROOT/verilator_bin_dbg -MMD --bin $VERILATOR_ROOT/verilator_bin_dbg --cc $VERILATOR_ROOT/test_regress/t/t_case_huge.v --no-skip-identical -I$VERILATOR_ROOT/test_regress/t 2>&1 | tee ~/d/aa
diff --git a/src/.gdbinit b/src/.gdbinit
index 9ad13ac14..b6c6c40a3 100644
--- a/src/.gdbinit
+++ b/src/.gdbinit
@@ -1,6 +1,6 @@
 # DESCRIPTION: Verilator: GDB startup file with useful defines
 #
-# Copyright 2012-2022 by Wilson Snyder. This program is free software; you
+# Copyright 2012-2023 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.
@@ -28,7 +28,7 @@ document dtf
 end
 
 define watchedit
-   watch AstNode::s_editCntGbl==$arg0
+   watch *(AstNode::s_editCntGbl)==$arg0
 end
 document watchedit
   Verilator: Create watch on where an edit number is made
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644
index 000000000..54d979b8a
--- /dev/null
+++ b/src/CMakeLists.txt
@@ -0,0 +1,498 @@
+#*****************************************************************************
+#
+# DESCRIPTION: Script for build tool cmake on both unix and windows
+#
+#*****************************************************************************
+#
+# Copyright 2003-2023 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
+#
+#****************************************************************************/
+
+#
+# Utilities
+macro (addBuildType sourceConfig newConfig)
+    get_cmake_property(variableNames VARIABLES)
+    foreach (variableName ${variableNames})
+        if (variableName MATCHES "^CMAKE_.*_${sourceConfig}(|_.*)$")
+            string(REPLACE _${sourceConfig} _${newConfig} newVariableName ${variableName})
+            set(${newVariableName} ${${variableName}})
+            mark_as_advanced(${newVariableName})
+            message(DEBUG "   Propagating ${variableName} to ${newVariableName} = ${${newVariableName}}")
+        endif()
+    endforeach()
+endmacro()
+
+#
+# Sources and headers for the verilator binary
+
+set(HEADERS
+    V3Active.h
+    V3ActiveTop.h
+    V3Assert.h
+    V3AssertPre.h
+    V3Ast.h
+    V3AstConstOnly.h
+    V3AstInlines.h
+    V3AstNodeDType.h
+    V3AstNodeExpr.h
+    V3AstNodeOther.h
+    V3AstUserAllocator.h
+    V3Begin.h
+    V3Branch.h
+    V3Broken.h
+    V3Case.h
+    V3Cast.h
+    V3CCtors.h
+    V3Cdc.h
+    V3Class.h
+    V3Clean.h
+    V3Clock.h
+    V3Combine.h
+    V3Common.h
+    V3Config.h
+    V3Const.h
+    V3Coverage.h
+    V3CoverageJoin.h
+    V3CUse.h
+    V3Dead.h
+    V3Delayed.h
+    V3Depth.h
+    V3DepthBlock.h
+    V3Descope.h
+    V3Dfg.h
+    V3DfgOptimizer.h
+    V3DfgPasses.h
+    V3DfgPeephole.h
+    V3DfgVertices.h
+    V3DupFinder.h
+    V3EmitC.h
+    V3EmitCBase.h
+    V3EmitCConstInit.h
+    V3EmitCFunc.h
+    V3EmitCMain.h
+    V3EmitCMake.h
+    V3EmitMk.h
+    V3EmitV.h
+    V3EmitXml.h
+    V3Error.h
+    V3Expand.h
+    V3File.h
+    V3FileLine.h
+    V3Force.h
+    V3FunctionTraits.h
+    V3Gate.h
+    V3Global.h
+    V3Graph.h
+    V3GraphAlg.h
+    V3GraphPathChecker.h
+    V3GraphStream.h
+    V3Hash.h
+    V3Hasher.h
+    V3HierBlock.h
+    V3Inline.h
+    V3Inst.h
+    V3InstrCount.h
+    V3LangCode.h
+    V3LanguageWords.h
+    V3Life.h
+    V3LifePost.h
+    V3LinkCells.h
+    V3LinkDot.h
+    V3LinkInc.h
+    V3LinkJump.h
+    V3LinkLevel.h
+    V3LinkLValue.h
+    V3LinkParse.h
+    V3LinkResolve.h
+    V3List.h
+    V3Localize.h
+    V3MergeCond.h
+    V3Name.h
+    V3Number.h
+    V3OptionParser.h
+    V3Options.h
+    V3Order.h
+    V3OrderGraph.h
+    V3OrderMoveGraph.h
+    V3Os.h
+    V3PairingHeap.h
+    V3Param.h
+    V3Parse.h
+    V3ParseImp.h
+    V3ParseSym.h
+    V3Partition.h
+    V3PartitionGraph.h
+    V3PreLex.h
+    V3Premit.h
+    V3PreProc.h
+    V3PreShell.h
+    V3ProtectLib.h
+    V3Randomize.h
+    V3Reloop.h
+    V3Sched.h
+    V3Scope.h
+    V3Scoreboard.h
+    V3SenExprBuilder.h
+    V3SenTree.h
+    V3Simulate.h
+    V3Slice.h
+    V3Split.h
+    V3SplitAs.h
+    V3SplitVar.h
+    V3Stats.h
+    V3StdFuture.h
+    V3String.h
+    V3Subst.h
+    V3SymTable.h
+    V3Table.h
+    V3Task.h
+    V3Timing.h
+    V3Trace.h
+    V3TraceDecl.h
+    V3Tristate.h
+    V3TSP.h
+    V3Undriven.h
+    V3UniqueNames.h
+    V3Unknown.h
+    V3Unroll.h
+    V3VariableOrder.h
+    V3Waiver.h
+    V3Width.h
+    V3WidthCommit.h
+    VlcBucket.h
+    VlcOptions.h
+    VlcPoint.h
+    VlcSource.h
+    VlcTest.h
+    VlcTop.h
+)
+
+set(COMMON_SOURCES
+    Verilator.cpp
+    V3Active.cpp
+    V3ActiveTop.cpp
+    V3Assert.cpp
+    V3AssertPre.cpp
+    V3Ast.cpp
+    V3AstNodes.cpp
+    V3Begin.cpp
+    V3Branch.cpp
+    V3Broken.cpp
+    V3CCtors.cpp
+    V3CUse.cpp
+    V3Case.cpp
+    V3Cast.cpp
+    V3Cdc.cpp
+    V3Class.cpp
+    V3Clean.cpp
+    V3Clock.cpp
+    V3Combine.cpp
+    V3Common.cpp
+    V3Config.cpp
+    V3Const__gen.cpp
+    V3Coverage.cpp
+    V3CoverageJoin.cpp
+    V3Dead.cpp
+    V3Delayed.cpp
+    V3Depth.cpp
+    V3DepthBlock.cpp
+    V3Descope.cpp
+    V3Dfg.cpp
+    V3DfgAstToDfg.cpp
+    V3DfgDecomposition.cpp
+    V3DfgDfgToAst.cpp
+    V3DfgOptimizer.cpp
+    V3DfgPasses.cpp
+    V3DfgPeephole.cpp
+    V3DupFinder.cpp
+    V3Timing.cpp
+    V3EmitCBase.cpp
+    V3EmitCConstPool.cpp
+    V3EmitCFunc.cpp
+    V3EmitCHeaders.cpp
+    V3EmitCImp.cpp
+    V3EmitCInlines.cpp
+    V3EmitCMain.cpp
+    V3EmitCMake.cpp
+    V3EmitCModel.cpp
+    V3EmitCSyms.cpp
+    V3EmitMk.cpp
+    V3EmitV.cpp
+    V3EmitXml.cpp
+    V3Error.cpp
+    V3Expand.cpp
+    V3File.cpp
+    V3FileLine.cpp
+    V3Force.cpp
+    V3Gate.cpp
+    V3Global.cpp
+    V3Graph.cpp
+    V3GraphAcyc.cpp
+    V3GraphAlg.cpp
+    V3GraphPathChecker.cpp
+    V3GraphTest.cpp
+    V3Hash.cpp
+    V3Hasher.cpp
+    V3HierBlock.cpp
+    V3Inline.cpp
+    V3Inst.cpp
+    V3InstrCount.cpp
+    V3Life.cpp
+    V3LifePost.cpp
+    V3LinkCells.cpp
+    V3LinkDot.cpp
+    V3LinkInc.cpp
+    V3LinkJump.cpp
+    V3LinkLevel.cpp
+    V3LinkLValue.cpp
+    V3LinkParse.cpp
+    V3LinkResolve.cpp
+    V3Localize.cpp
+    V3MergeCond.cpp
+    V3Name.cpp
+    V3Number.cpp
+    V3OptionParser.cpp
+    V3Options.cpp
+    V3Order.cpp
+    V3Os.cpp
+    V3Param.cpp
+    V3Partition.cpp
+    V3PreShell.cpp
+    V3Premit.cpp
+    V3ProtectLib.cpp
+    V3Randomize.cpp
+    V3Reloop.cpp
+    V3Sched.cpp
+    V3SchedAcyclic.cpp
+    V3SchedPartition.cpp
+    V3SchedReplicate.cpp
+    V3SchedTiming.cpp
+    V3Scope.cpp
+    V3Scoreboard.cpp
+    V3Slice.cpp
+    V3Split.cpp
+    V3SplitAs.cpp
+    V3SplitVar.cpp
+    V3Stats.cpp
+    V3StatsReport.cpp
+    V3String.cpp
+    V3Subst.cpp
+    V3Table.cpp
+    V3Task.cpp
+    V3Trace.cpp
+    V3TraceDecl.cpp
+    V3Tristate.cpp
+    V3TSP.cpp
+    V3Undriven.cpp
+    V3Unknown.cpp
+    V3Unroll.cpp
+    V3VariableOrder.cpp
+    V3Waiver.cpp
+    V3Width.cpp
+    V3WidthSel.cpp
+    V3ParseImp.cpp
+    V3ParseGrammar.cpp
+    V3ParseLex.cpp
+    V3PreProc.cpp
+)
+
+SET(COVERAGE_SOURCES
+    VlcMain.cpp
+)
+
+# Note about tests:
+# VlcMain.cpp #includes the following files:
+#  V3Error.cpp, V3String.cpp, V3Os.cpp and VlcTop.cpp
+# V3Number_test.cpp #includes the following files:
+#  V3FileLine.cpp
+
+#
+# Generated sources and headers for the verilator binary
+
+set(srcdir ${CMAKE_CURRENT_SOURCE_DIR})
+
+file(TO_NATIVE_PATH ${srcdir}/astgen ASTGEN)
+file(TO_NATIVE_PATH ${srcdir}/bisonpre BISONPRE)
+file(TO_NATIVE_PATH ${srcdir}/flexfix FLEXFIX)
+file(TO_NATIVE_PATH ${srcdir}/../bin/verilator_includer VERILATOR_INCLUDER)
+file(TO_NATIVE_PATH ${srcdir}/vlcovgen VLCOVGEN)
+file(TO_NATIVE_PATH ${srcdir}/config_rev CONFIG_REV)
+
+configure_file(config_build.h.in config_build.h @ONLY)
+
+add_custom_command(
+    OUTPUT V3Ast__gen_forward_class_decls.h V3Dfg__gen_forward_class_decls.h
+    DEPENDS ./V3Ast.h ${ASTGEN}
+    COMMAND ${PYTHON3} ARGS
+    ${ASTGEN} -I "${srcdir}" --astdef V3AstNodeDType.h --astdef V3AstNodeExpr.h --astdef V3AstNodeOther.h --dfgdef V3DfgVertices.h --classes
+)
+list(APPEND GENERATED_FILES V3Ast__gen_forward_class_decls.h V3Dfg__gen_forward_class_decls.h)
+# Output used directly by the `verilator` target
+
+set(verilog_y "${srcdir}/verilog.y" )
+set(BISON_V3ParseBison_OUTPUT_HEADER "${CMAKE_CURRENT_BINARY_DIR}/V3ParseBison.h")
+set(BISON_V3ParseBison_OUTPUT_SOURCE "${CMAKE_CURRENT_BINARY_DIR}/V3ParseBison.c")
+add_custom_command(
+    OUTPUT V3ParseBison.c V3ParseBison.h
+    MAIN_DEPENDENCY ./verilog.y
+    DEPENDS ${BISONPRE}
+    COMMAND ${PYTHON3} ARGS
+        ${BISONPRE} --yacc "${BISON_EXECUTABLE}" -d -v
+            -o "${BISON_V3ParseBison_OUTPUT_SOURCE}" "${verilog_y}"
+)
+list(APPEND GENERATED_FILES V3ParseBison.c V3ParseBison.h)
+# Output used directly by the `verilator` target
+
+set(verilog_l "${srcdir}/verilog.l")
+set(FLEX_V3Lexer_pregen_OUTPUTS "${CMAKE_CURRENT_BINARY_DIR}/V3Lexer_pregen.yy.cpp")
+add_custom_command(
+    OUTPUT V3Lexer_pregen.yy.cpp
+    MAIN_DEPENDENCY ./verilog.l
+    DEPENDS ${BISON_V3ParseBison_OUTPUT_HEADER} ${HEADERS}
+    COMMAND ${FLEX_EXECUTABLE} ARGS
+        ${LFLAGS} -o "${FLEX_V3Lexer_pregen_OUTPUTS}" "${verilog_l}"
+)
+# Output used by another command
+
+set(FLEX_V3Lexer_OUTPUTS ${CMAKE_CURRENT_BINARY_DIR}/V3Lexer.yy.cpp)
+add_custom_command(
+    OUTPUT V3Lexer.yy.cpp
+    MAIN_DEPENDENCY ${FLEX_V3Lexer_pregen_OUTPUTS}
+    DEPENDS ${FLEXFIX}
+    COMMAND ${PYTHON3} ARGS
+        ${FLEXFIX} V3Lexer < "$" > "$"
+)
+add_custom_target(V3Lexer_yy_cpp${CMAKE_BUILD_TYPE} DEPENDS ${FLEX_V3Lexer_OUTPUTS})
+# Output included by another source file
+
+set(FLEX_V3PreLex_pregen_OUTPUTS ${CMAKE_CURRENT_BINARY_DIR}/V3PreLex_pregen.yy.cpp)
+add_custom_command(
+    OUTPUT V3PreLex_pregen.yy.cpp
+    MAIN_DEPENDENCY ./V3PreLex.l
+    DEPENDS ${HEADERS}
+    COMMAND ${FLEX_EXECUTABLE} ARGS
+        ${LFLAGS} -o "${FLEX_V3PreLex_pregen_OUTPUTS}" "${srcdir}/V3PreLex.l"
+)
+# Output used by another command
+
+set(FLEX_V3PreLex_OUTPUTS ${CMAKE_CURRENT_BINARY_DIR}/V3PreLex.yy.cpp)
+add_custom_command(
+    OUTPUT V3PreLex.yy.cpp
+    MAIN_DEPENDENCY ${FLEX_V3PreLex_pregen_OUTPUTS}
+    DEPENDS ${FLEXFIX}
+    COMMAND ${PYTHON3} ARGS
+        ${FLEXFIX} V3PreLex < "$" > "$"
+)
+add_custom_target(V3PreLex_yy_cpp${CMAKE_BUILD_TYPE} DEPENDS ${FLEX_V3PreLex_OUTPUTS})
+# Output included by another source file
+
+set(gitHead ${srcdir}/../.git/logs/HEAD)
+if (NOT EXISTS ${githead})
+    set(gitHead "")
+endif()
+add_custom_command(
+    OUTPUT config_rev.h
+    MAIN_DEPENDENCY ${gitHead}
+    DEPENDS ${CONFIG_REV}
+    COMMAND ${PYTHON3} ARGS
+        ${CONFIG_REV} "${srcdir}" > "$"
+)
+list(APPEND GENERATED_FILES config_rev.h)
+# Output used directly by the `verilator` target
+
+set(ASTGENERATED_NAMES
+    V3Const
+)
+
+foreach(astgen_name ${ASTGENERATED_NAMES})
+    add_custom_command(
+        OUTPUT ${astgen_name}__gen.cpp
+        MAIN_DEPENDENCY ${astgen_name}.cpp
+        DEPENDS ${ASTGEN} V3Ast.h
+        COMMAND ${PYTHON3} ARGS
+            ${ASTGEN} -I"${srcdir}" --astdef V3AstNodeDType.h --astdef V3AstNodeExpr.h --astdef V3AstNodeOther.h --dfgdef V3DfgVertices.h ${astgen_name}.cpp
+    )
+    list(APPEND GENERATED_FILES ${astgen_name}__gen.cpp)
+endforeach()
+
+#
+# Set up the Coverage build type
+
+addBuildType(DEBUG COVERAGE)
+
+# This regenerates include/verilated_cov_key.h in the source tree.
+# It is a custom_target, not custom_command, because vlcovgen.d is
+# a phony target (it doesn't exist as a file).
+add_custom_target(
+    vlcovgen.d${CMAKE_BUILD_TYPE}
+    DEPENDS ../include/verilated_cov_key.h ${VLCOVGEN}
+    COMMENT "Updating include/verilated_cov_key.h"
+    COMMAND ${PYTHON3}
+        ${VLCOVGEN} --srcdir ${srcdir}
+)
+
+#
+# Set up the verilator binary target
+
+set(verilator verilator${CMAKE_BUILD_TYPE})
+
+add_executable(${verilator}
+    $<$>:${COMMON_SOURCES}>
+    $<$>:${GENERATED_FILES}>
+    $<$:${COVERAGE_SOURCES} config_rev.h>
+)
+
+set_target_properties(${verilator} PROPERTIES
+    OUTPUT_NAME_RELEASE   verilator_bin
+    OUTPUT_NAME_DEBUG     verilator_bin_dbg
+    OUTPUT_NAME_COVERAGE  verilator_coverage_bin_dbg
+    #UNITY_BUILD $,FALSE,${CMAKE_UNITY_BUILD}>
+    MSVC_RUNTIME_LIBRARY  MultiThreaded$,,DebugDLL>
+    #JOB_POOL_LINK         one_job      # Linking takes lots of resources
+    INTERPROCEDURAL_OPTIMIZATION_RELEASE  TRUE
+)
+
+add_dependencies(${verilator}
+    V3Lexer_yy_cpp${CMAKE_BUILD_TYPE}
+    V3PreLex_yy_cpp${CMAKE_BUILD_TYPE}
+)
+
+# verilated_cov_key.h is only regenerated in a single-configuration environment.
+# This limitation can be lifted when `add_dependencies` will support generator
+# expressions. See https://gitlab.kitware.com/cmake/cmake/issues/19467
+if (CMAKE_BUILD_TYPE STREQUAL Coverage)
+    add_dependencies(${verilator} vlcovgen.d${CMAKE_BUILD_TYPE})
+endif()
+
+if (NOT MSVC)
+    target_compile_features(${verilator} PRIVATE cxx_std_11)
+endif()
+
+target_compile_definitions(${verilator} PRIVATE
+    YYDEBUG # Required to get nice error messages
+    $<$:VL_DEBUG>
+    $<$:_GLIBCXX_DEBUG>
+)
+
+target_include_directories(${verilator}
+    PRIVATE
+    ../include
+    ${WIN_FLEX_BISON}
+    ${CMAKE_CURRENT_BINARY_DIR}
+    ${CMAKE_CURRENT_BINARY_DIR}/../include
+    ${CMAKE_CURRENT_SOURCE_DIR}
+)
+
+if (WIN32)
+    target_compile_definitions(${verilator} PRIVATE
+        YY_NO_UNISTD_H
+    )
+    target_include_directories(${verilator} PRIVATE ../platform/win32)
+    target_link_libraries(${verilator} PRIVATE bcrypt psapi)
+endif()
+
+install(TARGETS ${verilator})
diff --git a/src/Makefile.in b/src/Makefile.in
index ffd2eaf72..15d34ebd6 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -7,7 +7,7 @@
 #
 #*****************************************************************************
 #
-# Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+# Copyright 2003-2023 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.
diff --git a/src/Makefile_obj.in b/src/Makefile_obj.in
index a0f995f8f..dd177da20 100644
--- a/src/Makefile_obj.in
+++ b/src/Makefile_obj.in
@@ -7,7 +7,7 @@
 #
 #*****************************************************************************
 #
-# Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+# Copyright 2003-2023 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.
@@ -40,7 +40,6 @@ CXX = @CXX@
 LINK = @CXX@
 LEX = @LEX@
 LFLAGS = -d
-PERL = @PERL@
 PYTHON3 = @PYTHON3@
 YACC = @YACC@
 OBJCACHE ?= @OBJCACHE@
@@ -326,6 +325,8 @@ V3Number_test: V3Number_test.o
 %__gen.cpp:	%.cpp $(ASTGEN) $(AST_DEFS) $(DFG_DEFS)
 	$(PYTHON3) $(ASTGEN) $(ASTGENFLAGS) $*.cpp
 
+.SECONDARY:
+
 %.o:	%.cpp
 	$(OBJCACHE) ${CXX} ${CXXFLAGS} ${CPPFLAGSWALL} -c $< -o $@
 %.o:	%.c
@@ -385,7 +386,7 @@ HEADER_CC_H := $(filter-out $(NON_STANDALONE_HEADERS), $(notdir $(wildcard $(src
 header_cc: $(addsuffix __header_cc.o, $(basename $(HEADER_CC_H)))
 
 %__header_cc.cpp: %.h
-	$(PERL) $(srcdir)/../bin/verilator_includer $^ > $@
+	$(PYTHON3) $(srcdir)/../bin/verilator_includer $^ > $@
 
 .SUFFIXES:
 
diff --git a/src/V3Active.cpp b/src/V3Active.cpp
index 7cfa896ae..68ef3dbf1 100644
--- a/src/V3Active.cpp
+++ b/src/V3Active.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -86,7 +86,7 @@ protected:
     }
 
     // Recursively traverse the graph to determine whether every control 'BLOCK' has an assignment
-    // to the output we are currently analysing (the output whose 'user() is set), if so return
+    // to the output we are currently analyzing (the output whose 'user() is set), if so return
     // true. Where a BLOCK contains a BRANCH, both the if and else sides of the branch must return
     // true for the BRANCH to evaluate to true. A BLOCK however needs only a single one of its
     // siblings to evaluate true in order to evaluate true itself. On output vertex only evaluates
@@ -243,16 +243,21 @@ public:
     // METHODS
     AstScope* scopep() { return m_scopep; }
 
-    // Make a new AstActive sensitive to the given special sensitivity class and return it
-    template 
-    AstActive* makeSpecialActive(FileLine* const fl) {
-        AstSenTree* const senTreep = new AstSenTree{fl, new AstSenItem{fl, SenItemKind{}}};
+    // Make a new AstActive sensitive to the given sentree and return it
+    AstActive* makeActive(FileLine* const fl, AstSenTree* const senTreep) {
         auto* const activep = new AstActive{fl, "", senTreep};
         activep->sensesStorep(activep->sensesp());
         addActive(activep);
         return activep;
     }
 
+    // Make a new AstActive sensitive to the given special sensitivity class and return it
+    template 
+    AstActive* makeSpecialActive(FileLine* const fl) {
+        AstSenTree* const senTreep = new AstSenTree{fl, new AstSenItem{fl, SenItemKind{}}};
+        return makeActive(fl, senTreep);
+    }
+
     // Return an AstActive sensitive to the given special sensitivity class (possibly pre-created)
     template 
     AstActive* getSpecialActive(FileLine* fl) {
@@ -542,6 +547,22 @@ private:
         AstActive* const activep = m_namer.makeSpecialActive(nodep->fileline());
         activep->addStmtsp(nodep->unlinkFrBack());
     }
+    void visit(AstAlwaysObserved* nodep) override {
+        UASSERT_OBJ(nodep->sensesp(), nodep, "Should have a sentree");
+        AstSenTree* const sensesp = nodep->sensesp();
+        sensesp->unlinkFrBack();
+        // Make a new active for it, needs to be the only item under the active for V3Sched
+        AstActive* const activep = m_namer.makeActive(nodep->fileline(), sensesp);
+        activep->addStmtsp(nodep->unlinkFrBack());
+    }
+    void visit(AstAlwaysReactive* nodep) override {
+        UASSERT_OBJ(nodep->sensesp(), nodep, "Should have a sentree");
+        AstSenTree* const sensesp = nodep->sensesp();
+        sensesp->unlinkFrBack();
+        // Make a new active for it, needs to be the only item under the active for V3Sched
+        AstActive* const activep = m_namer.makeActive(nodep->fileline(), sensesp);
+        activep->addStmtsp(nodep->unlinkFrBack());
+    }
     void visit(AstAlwaysPublic* nodep) override {
         visitAlways(nodep, nodep->sensesp(), VAlwaysKwd::ALWAYS);
     }
diff --git a/src/V3Active.h b/src/V3Active.h
index 84ee4cdb9..81684c6f1 100644
--- a/src/V3Active.h
+++ b/src/V3Active.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3ActiveTop.cpp b/src/V3ActiveTop.cpp
index 47f183122..29d9df091 100644
--- a/src/V3ActiveTop.cpp
+++ b/src/V3ActiveTop.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3ActiveTop.h b/src/V3ActiveTop.h
index 5a7f018db..ac9361c7d 100644
--- a/src/V3ActiveTop.h
+++ b/src/V3ActiveTop.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp
index cf2de9ad0..7b33bc841 100644
--- a/src/V3Assert.cpp
+++ b/src/V3Assert.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2005-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2005-2023 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.
@@ -368,6 +368,7 @@ private:
             inp = new AstVarRef{nodep->fileline(), invarp, VAccess::READ};
         }
         nodep->replaceWith(inp);
+        VL_DO_DANGLING(pushDeletep(nodep), nodep);
     }
 
     //========== Move $sampled down to read-only variables
diff --git a/src/V3Assert.h b/src/V3Assert.h
index d20b9b436..0715dd405 100644
--- a/src/V3Assert.h
+++ b/src/V3Assert.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2005-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2005-2023 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.
diff --git a/src/V3AssertPre.cpp b/src/V3AssertPre.cpp
index 8e84e2986..b27a36c1b 100644
--- a/src/V3AssertPre.cpp
+++ b/src/V3AssertPre.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2005-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2005-2023 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.
@@ -16,6 +16,7 @@
 //  Pre steps:
 //      Attach clocks to each assertion
 //      Substitute property references by property body (IEEE Std 1800-2012, section 16.12.1).
+//      Transform clocking blocks into imperative logic
 //*************************************************************************
 
 #include "config_build.h"
@@ -24,8 +25,10 @@
 #include "V3AssertPre.h"
 
 #include "V3Ast.h"
+#include "V3Const.h"
 #include "V3Global.h"
 #include "V3Task.h"
+#include "V3UniqueNames.h"
 
 VL_DEFINE_DEBUG_FUNCTIONS;
 
@@ -37,16 +40,26 @@ class AssertPreVisitor final : public VNVisitor {
     // Eventually inlines calls to sequences, properties, etc.
     // We're not parsing the tree, or anything more complicated.
 private:
-    // NODE STATE/TYPES
+    // NODE STATE
+    const VNUser1InUse m_inuser1;
     // STATE
+    // Current context:
+    AstNetlist* const m_netlistp = nullptr;  // Current netlist
+    AstNodeModule* m_modp = nullptr;  // Current module
+    AstClocking* m_clockingp = nullptr;  // Current clocking block
     // Reset each module:
-    AstSenItem* m_seniDefaultp = nullptr;  // Default sensitivity (from AstDefClock)
+    AstClocking* m_defaultClockingp = nullptr;  // Default clocking for the current module
     // Reset each assertion:
     AstSenItem* m_senip = nullptr;  // Last sensitivity
     // Reset each always:
     AstSenItem* m_seniAlwaysp = nullptr;  // Last sensitivity in always
     // Reset each assertion:
     AstNodeExpr* m_disablep = nullptr;  // Last disable
+    // Other:
+    V3UniqueNames m_cycleDlyNames{"__VcycleDly"};  // Cycle delay counter name generator
+    bool m_inAssign = false;  // True if in an AssignNode
+    bool m_inAssignDlyLhs = false;  // True if in AssignDly's LHS
+    bool m_inSynchDrive = false;  // True if in synchronous drive
 
     // METHODS
 
@@ -55,7 +68,7 @@ private:
         // Return nullptr for always
         AstSenTree* newp = nullptr;
         AstSenItem* senip = m_senip;
-        if (!senip) senip = m_seniDefaultp;
+        if (!senip && m_defaultClockingp) senip = m_defaultClockingp->sensesp();
         if (!senip) senip = m_seniAlwaysp;
         if (!senip) {
             nodep->v3warn(E_UNSUPPORTED, "Unsupported: Unclocked assertion");
@@ -139,17 +152,199 @@ private:
 
     // VISITORS
     //========== Statements
-    void visit(AstClocking* nodep) override {
+    void visit(AstClocking* const nodep) override {
+        VL_RESTORER(m_clockingp);
+        m_clockingp = nodep;
         UINFO(8, "   CLOCKING" << nodep << endl);
-        // Store the new default clock, reset on new module
-        m_seniDefaultp = nodep->sensesp();
-        // Trash it, keeping children
-        if (nodep->bodysp()) {
-            nodep->replaceWith(nodep->bodysp()->unlinkFrBack());
-        } else {
-            nodep->unlinkFrBack();
+        iterateChildren(nodep);
+    }
+    void visit(AstClockingItem* const nodep) override {
+        FileLine* const flp = nodep->fileline();
+        V3Const::constifyEdit(nodep->skewp());
+        if (!VN_IS(nodep->skewp(), Const)) {
+            nodep->skewp()->v3error("Skew must be constant (IEEE 1800-2017 14.4)");
+            VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
+            return;
+        }
+        AstConst* const skewp = VN_AS(nodep->skewp(), Const);
+        if (skewp->num().isNegative()) skewp->v3error("Skew cannot be negative");
+        AstNodeExpr* const exprp = nodep->exprp();
+        // Get a ref to the sampled/driven variable
+        AstVar* const varp = nodep->varp()->unlinkFrBack();
+        m_clockingp->addVarsp(varp);
+        varp->user1p(nodep);
+        if (nodep->direction() == VDirection::OUTPUT) {
+            AstVarRef* const skewedRefp = new AstVarRef{flp, varp, VAccess::READ};
+            skewedRefp->user1(true);
+            AstAssign* const assignp = new AstAssign{flp, exprp->cloneTree(false), skewedRefp};
+            if (skewp->isZero()) {
+                // Drive the var in Re-NBA (IEEE 1800-2017 14.16)
+                m_clockingp->addNextHere(new AstAlwaysReactive{
+                    flp, new AstSenTree{flp, m_clockingp->sensesp()->cloneTree(false)}, assignp});
+            } else if (skewp->fileline()->timingOn()) {
+                // Create a fork so that this AlwaysObserved can be retriggered before the
+                // assignment happens. Also then it can be combo, avoiding the need for creating
+                // new triggers.
+                AstFork* const forkp = new AstFork{flp, "", assignp};
+                forkp->joinType(VJoinType::JOIN_NONE);
+                // Use Observed for this to make sure we do not miss the event
+                m_clockingp->addNextHere(new AstAlwaysObserved{
+                    flp, new AstSenTree{flp, m_clockingp->sensesp()->cloneTree(false)}, forkp});
+                if (v3Global.opt.timing().isSetTrue()) {
+                    assignp->timingControlp(new AstDelay{flp, skewp->unlinkFrBack(), false});
+                } else if (v3Global.opt.timing().isSetFalse()) {
+                    nodep->v3warn(E_NOTIMING,
+                                  "Clocking output skew greater than #0 requires --timing");
+                } else {
+                    nodep->v3warn(E_NEEDTIMINGOPT,
+                                  "Use --timing or --no-timing to specify how "
+                                  "clocking output skew greater than #0 should be handled");
+                }
+            }
+        } else if (nodep->direction() == VDirection::INPUT) {
+            // Ref to the clockvar
+            AstVarRef* const refp = new AstVarRef{flp, varp, VAccess::WRITE};
+            refp->user1(true);
+            if (skewp->num().is1Step()) {
+                // Assign the sampled expression to the clockvar (IEEE 1800-2017 14.13)
+                AstSampled* const sampledp = new AstSampled{flp, exprp->cloneTree(false)};
+                sampledp->dtypeFrom(exprp);
+                m_clockingp->addNextHere(new AstAssignW{flp, refp, sampledp});
+            } else if (skewp->isZero()) {
+                // #0 means the var has to be sampled in Observed (IEEE 1800-2017 14.13)
+                AstAssign* const assignp = new AstAssign{flp, refp, exprp->cloneTree(false)};
+                m_clockingp->addNextHere(new AstAlwaysObserved{
+                    flp, new AstSenTree{flp, m_clockingp->sensesp()->cloneTree(false)}, assignp});
+            } else {
+                // Create a queue where we'll store sampled values with timestamps
+                AstSampleQueueDType* const queueDtp
+                    = new AstSampleQueueDType{flp, exprp->dtypep()};
+                m_netlistp->typeTablep()->addTypesp(queueDtp);
+                AstVar* const queueVarp = new AstVar{
+                    flp, VVarType::MODULETEMP,
+                    "__Vqueue__" + m_clockingp->name() + "__DOT__" + varp->name(), queueDtp};
+                m_clockingp->addNextHere(queueVarp);
+                // Create a process like this:
+                //     always queue.push();
+                AstCMethodHard* const pushp = new AstCMethodHard{
+                    flp, new AstVarRef{flp, queueVarp, VAccess::WRITE}, "push",
+                    new AstTime(nodep->fileline(), m_modp->timeunit())};
+                pushp->addPinsp(exprp->cloneTree(false));
+                pushp->dtypeSetVoid();
+                m_clockingp->addNextHere(
+                    new AstAlways{flp, VAlwaysKwd::ALWAYS, nullptr, pushp->makeStmt()});
+                // Create a process like this:
+                //     always @ queue.pop(, /*out*/});
+                AstCMethodHard* const popp = new AstCMethodHard{
+                    flp, new AstVarRef{flp, queueVarp, VAccess::READWRITE}, "pop",
+                    new AstTime(nodep->fileline(), m_modp->timeunit())};
+                popp->addPinsp(skewp->unlinkFrBack());
+                popp->addPinsp(refp);
+                popp->dtypeSetVoid();
+                m_clockingp->addNextHere(
+                    new AstAlways{flp, VAlwaysKwd::ALWAYS,
+                                  new AstSenTree{flp, m_clockingp->sensesp()->cloneTree(false)},
+                                  popp->makeStmt()});
+            }
+        } else {
+            nodep->v3fatal("Invalid direction");
+        }
+        pushDeletep(nodep->unlinkFrBack());
+    }
+    void visit(AstDelay* nodep) override {
+        // Only cycle delays are relevant in this stage; also only process once
+        if (!nodep->isCycleDelay()) {
+            if (m_inSynchDrive) {
+                nodep->v3error("Only cycle delays can be used in synchronous drives"
+                               " (IEEE 1800-2017 14.16)");
+            }
+            return;
+        }
+        if (m_inAssign && !m_inSynchDrive) {
+            nodep->v3error("Cycle delays not allowed as intra-assignment delays"
+                           " (IEEE 1800-2017 14.11)");
+            VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
+            return;
+        }
+        if (nodep->stmtsp()) nodep->addNextHere(nodep->stmtsp()->unlinkFrBackWithNext());
+        FileLine* const flp = nodep->fileline();
+        AstNodeExpr* valuep = V3Const::constifyEdit(nodep->lhsp()->unlinkFrBack());
+        AstConst* const constp = VN_CAST(valuep, Const);
+        if (constp->isZero()) {
+            nodep->v3warn(E_UNSUPPORTED, "Unsupported: ##0 delays");
+            VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
+            return;
+        }
+        if (!m_defaultClockingp) {
+            nodep->v3error("Usage of cycle delays requires default clocking"
+                           " (IEEE 1800-2017 14.11)");
+            VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
+            return;
+        }
+        AstEventControl* const controlp = new AstEventControl{
+            nodep->fileline(),
+            new AstSenTree{flp, m_defaultClockingp->sensesp()->cloneTree(false)}, nullptr};
+        const std::string delayName = m_cycleDlyNames.get(nodep);
+        AstVar* const cntVarp = new AstVar{flp, VVarType::BLOCKTEMP, delayName + "__counter",
+                                           nodep->findBasicDType(VBasicDTypeKwd::UINT32)};
+        AstBegin* const beginp = new AstBegin{flp, delayName + "__block", cntVarp, false, true};
+        beginp->addStmtsp(new AstAssign{flp, new AstVarRef{flp, cntVarp, VAccess::WRITE}, valuep});
+        beginp->addStmtsp(new AstWhile{
+            nodep->fileline(),
+            new AstGt{flp, new AstVarRef{flp, cntVarp, VAccess::READ}, new AstConst{flp, 0}},
+            controlp,
+            new AstAssign{flp, new AstVarRef{flp, cntVarp, VAccess::WRITE},
+                          new AstSub{flp, new AstVarRef{flp, cntVarp, VAccess::READ},
+                                     new AstConst{flp, 1}}}});
+        nodep->replaceWith(beginp);
+        VL_DO_DANGLING(nodep->deleteTree(), nodep);
+    }
+    void visit(AstSenTree* nodep) override {
+        if (m_inSynchDrive) {
+            nodep->v3error("Event controls cannot be used in "
+                           "synchronous drives (IEEE 1800-2017 14.16)");
+        }
+    }
+    void visit(AstNodeVarRef* nodep) override {
+        if (AstClockingItem* const itemp = VN_CAST(nodep->varp()->user1p(), ClockingItem)) {
+            if (nodep->access().isReadOrRW() && !nodep->user1()
+                && itemp->direction() == VDirection::OUTPUT) {
+                nodep->v3error("Cannot read from output clockvar (IEEE 1800-2017 14.3)");
+            }
+            if (nodep->access().isWriteOrRW()) {
+                if (itemp->direction() == VDirection::OUTPUT) {
+                    if (!m_inAssignDlyLhs) {
+                        nodep->v3error("Only non-blocking assignments can write "
+                                       "to clockvars (IEEE 1800-2017 14.16)");
+                    }
+                    if (m_inAssign) m_inSynchDrive = true;
+                } else if (!nodep->user1() && itemp->direction() == VDirection::INPUT) {
+                    nodep->v3error("Cannot write to input clockvar (IEEE 1800-2017 14.3)");
+                }
+            }
+        }
+    }
+    void visit(AstNodeAssign* nodep) override {
+        if (nodep->user1()) return;
+        VL_RESTORER(m_inAssign);
+        VL_RESTORER(m_inSynchDrive);
+        m_inAssign = true;
+        m_inSynchDrive = false;
+        {
+            VL_RESTORER(m_inAssignDlyLhs);
+            m_inAssignDlyLhs = VN_IS(nodep, AssignDly);
+            iterate(nodep->lhsp());
+        }
+        iterate(nodep->rhsp());
+        if (nodep->timingControlp()) {
+            iterate(nodep->timingControlp());
+        } else if (m_inSynchDrive) {
+            AstAssign* const assignp = new AstAssign{
+                nodep->fileline(), nodep->lhsp()->unlinkFrBack(), nodep->rhsp()->unlinkFrBack()};
+            assignp->user1(true);
+            nodep->replaceWith(assignp);
+            VL_DO_DANGLING(nodep->deleteTree(), nodep);
         }
-        VL_DO_DANGLING(pushDeletep(nodep), nodep);
     }
     void visit(AstAlways* nodep) override {
         iterateAndNextNull(nodep->sensesp());
@@ -255,9 +450,20 @@ private:
         VL_DO_DANGLING(pushDeletep(nodep), nodep);
     }
     void visit(AstNodeModule* nodep) override {
+        VL_RESTORER(m_defaultClockingp);
+        VL_RESTORER(m_modp);
+        m_defaultClockingp = nullptr;
+        nodep->foreach([&](AstClocking* const clockingp) {
+            if (clockingp->isDefault()) {
+                if (m_defaultClockingp) {
+                    clockingp->v3error("Only one default clocking block allowed per module"
+                                       " (IEEE 1800-2017 14.12)");
+                }
+                m_defaultClockingp = clockingp;
+            }
+        });
+        m_modp = nodep;
         iterateChildren(nodep);
-        // Reset defaults
-        m_seniDefaultp = nullptr;
     }
     void visit(AstProperty* nodep) override {
         // The body will be visited when will be substituted in place of property reference
@@ -268,7 +474,8 @@ private:
 
 public:
     // CONSTRUCTORS
-    explicit AssertPreVisitor(AstNetlist* nodep) {
+    explicit AssertPreVisitor(AstNetlist* nodep)
+        : m_netlistp{nodep} {
         clearAssertInfo();
         // Process
         iterate(nodep);
diff --git a/src/V3AssertPre.h b/src/V3AssertPre.h
index 30efc1f2d..9cc61528d 100644
--- a/src/V3AssertPre.h
+++ b/src/V3AssertPre.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2005-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2005-2023 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.
diff --git a/src/V3Ast.cpp b/src/V3Ast.cpp
index 14fd978df..b77b329e4 100644
--- a/src/V3Ast.cpp
+++ b/src/V3Ast.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Ast.h b/src/V3Ast.h
index e303c989c..f437f1ef9 100644
--- a/src/V3Ast.h
+++ b/src/V3Ast.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -2207,7 +2207,7 @@ AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp);
 // Inline method implementations
 AstNode* AstNode::addNext(AstNode* newp) { return addNext(this, newp); }
 
-// Specialisations of privateTypeTest
+// Specializations of privateTypeTest
 #include "V3Ast__gen_type_tests.h"  // From ./astgen
 
 // Specializations of AstNode::mayBeUnder
diff --git a/src/V3AstConstOnly.h b/src/V3AstConstOnly.h
index 223143a68..f785a3239 100644
--- a/src/V3AstConstOnly.h
+++ b/src/V3AstConstOnly.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3AstInlines.h b/src/V3AstInlines.h
index 745fee3f3..79023761b 100644
--- a/src/V3AstInlines.h
+++ b/src/V3AstInlines.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -19,7 +19,7 @@
 
 #ifndef VERILATOR_V3AST_H_
 #error "Use V3Ast.h as the include"
-#include "V3Ast.h"  // This helps code analysis tools pick up symbols in V3Ast.h and relaed
+#include "V3Ast.h"  // This helps code analysis tools pick up symbols in V3Ast.h and related
 #endif
 
 //######################################################################
diff --git a/src/V3AstNodeDType.h b/src/V3AstNodeDType.h
index d06961356..a50a88006 100644
--- a/src/V3AstNodeDType.h
+++ b/src/V3AstNodeDType.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -219,7 +219,7 @@ public:
     int uniqueNum() const { return m_uniqueNum; }
     const char* broken() const override;
     void dump(std::ostream& str) const override;
-    bool isCompound() const override { return false; }  // Because don't support unpacked
+    bool isCompound() const override { return !packed(); }
     // For basicp() we reuse the size to indicate a "fake" basic type of same size
     AstBasicDType* basicp() const override {
         return (isFourstate()
@@ -241,6 +241,7 @@ public:
     string name() const override { return m_name; }
     void name(const string& flag) override { m_name = flag; }
     bool packed() const VL_MT_SAFE { return m_packed; }
+    void packed(bool flag) { m_packed = flag; }
     // packed() but as don't support unpacked, presently all structs
     static bool packedUnsup() { return true; }
     void isFourstate(bool flag) { m_isFourstate = flag; }
@@ -1121,6 +1122,50 @@ public:
         return false;
     }
 };
+class AstSampleQueueDType final : public AstNodeDType {
+    // @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width
+    AstNodeDType* m_refDTypep = nullptr;  // Elements of this type (after widthing)
+public:
+    AstSampleQueueDType(FileLine* fl, AstNodeDType* dtp)
+        : ASTGEN_SUPER_SampleQueueDType(fl) {
+        refDTypep(dtp);
+        dtypep(dtp);
+    }
+    ASTGEN_MEMBERS_AstSampleQueueDType;
+    const char* broken() const override {
+        BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
+                     || (!m_refDTypep && childDTypep())));
+        return nullptr;
+    }
+    void cloneRelink() override {
+        if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep();
+    }
+    bool same(const AstNode* samep) const override {
+        const AstNodeArrayDType* const asamep = static_cast(samep);
+        if (!asamep->subDTypep()) return false;
+        return (subDTypep() == asamep->subDTypep());
+    }
+    bool similarDType(const AstNodeDType* samep) const override {
+        const AstSampleQueueDType* const asamep = static_cast(samep);
+        return type() == samep->type() && asamep->subDTypep()
+               && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp());
+    }
+    void dumpSmall(std::ostream& str) const override;
+    AstNodeDType* getChildDTypep() const override { return childDTypep(); }
+    // op1 = Range of variable
+    AstNodeDType* subDTypep() const override { return m_refDTypep ? m_refDTypep : childDTypep(); }
+    void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
+    AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
+    void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
+    // METHODS
+    AstBasicDType* basicp() const override { return subDTypep()->basicp(); }
+    AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; }
+    AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
+    AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
+    int widthAlignBytes() const override { return sizeof(std::map); }
+    int widthTotalBytes() const override { return sizeof(std::map); }
+    bool isCompound() const override { return true; }
+};
 class AstUnsizedArrayDType final : public AstNodeDType {
     // Unsized/open-range Array data type, ie "some_dtype var_name []"
     // @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width
@@ -1274,12 +1319,15 @@ public:
 
 // === AstNodeUOrStructDType ===
 class AstStructDType final : public AstNodeUOrStructDType {
+    AstNodeModule* m_classOrPackagep = nullptr;  // Package hierarchy
 public:
     // VSigning below is mispurposed to indicate if packed or not
     AstStructDType(FileLine* fl, VSigning numericUnpack)
         : ASTGEN_SUPER_StructDType(fl, numericUnpack) {}
     ASTGEN_MEMBERS_AstStructDType;
     string verilogKwd() const override { return "struct"; }
+    AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
+    void classOrPackagep(AstNodeModule* classpackagep) { m_classOrPackagep = classpackagep; }
 };
 class AstUnionDType final : public AstNodeUOrStructDType {
 public:
diff --git a/src/V3AstNodeExpr.h b/src/V3AstNodeExpr.h
index 185ac1484..243029f39 100644
--- a/src/V3AstNodeExpr.h
+++ b/src/V3AstNodeExpr.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2003-2023 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
@@ -936,6 +936,13 @@ public:
         dtypeSetBit();  // Events 1 bit, objects 64 bits, so autoExtend=1 and use bit here
         initWithNumber();
     }
+    class OneStep {};
+    AstConst(FileLine* fl, OneStep)
+        : ASTGEN_SUPER_Const(fl)
+        , m_num(V3Number::OneStep{}, this) {
+        dtypeSetLogicSized(64, VSigning::UNSIGNED);
+        initWithNumber();
+    }
     ASTGEN_MEMBERS_AstConst;
     string name() const override { return num().ascii(); }  // * = Value
     const V3Number& num() const VL_MT_SAFE { return m_num; }  // * = Value
@@ -1778,6 +1785,31 @@ public:
     bool cleanOut() const override { return true; }
     bool same(const AstNode* /*samep*/) const override { return true; }
 };
+class AstStructSel final : public AstNodeExpr {
+    // Unpacked struct member access
+    // Parents: math|stmt
+    // Children: varref, math
+    // @astgen op1 := fromp : AstNodeExpr
+private:
+    string m_name;  // Name of the member
+public:
+    AstStructSel(FileLine* fl, AstNodeExpr* fromp, const string& name)
+        : ASTGEN_SUPER_StructSel(fl)
+        , m_name{name} {
+        this->fromp(fromp);
+        dtypep(nullptr);  // V3Width will resolve
+    }
+    ASTGEN_MEMBERS_AstStructSel;
+    string name() const override { return m_name; }
+    string emitVerilog() override { V3ERROR_NA_RETURN(""); }
+    string emitC() override { V3ERROR_NA_RETURN(""); }
+    bool cleanOut() const override { return false; }
+    bool same(const AstNode* samep) const override {
+        const AstStructSel* const sp = static_cast(samep);
+        return m_name == sp->m_name;
+    }
+    int instrCount() const override { return widthInstrs(); }
+};
 class AstSysIgnore final : public AstNodeExpr {
     // @astgen op1 := exprsp : List[AstNode] // Expressions to output (???)
 public:
diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h
index e407dbf4a..c71ccb688 100644
--- a/src/V3AstNodeOther.h
+++ b/src/V3AstNodeOther.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -814,17 +814,50 @@ public:
     AstClass* classp() const;  // Class being extended (after link)
 };
 class AstClocking final : public AstNode {
-    // Set default clock region
     // Parents:  MODULE
-    // @astgen op1 := sensesp : List[AstSenItem]
-    // @astgen op2 := bodysp : List[AstNode]
+    // Children: SENITEM, CLOCKING ITEMs, VARs
+    // @astgen op1 := sensesp : AstSenItem
+    // @astgen op2 := itemsp : List[AstClockingItem]
+    // @astgen op3 := varsp : List[AstVar]
+    // @astgen op4 := eventp : Optional[AstVar]
+    std::string m_name;  // Clocking block name
+    const bool m_isDefault = false;  // True if default clocking
+
 public:
-    AstClocking(FileLine* fl, AstSenItem* sensesp, AstNode* bodysp)
-        : ASTGEN_SUPER_Clocking(fl) {
-        this->addSensesp(sensesp);
-        this->addBodysp(bodysp);
+    AstClocking(FileLine* fl, const std::string& name, AstSenItem* sensesp,
+                AstClockingItem* itemsp, bool isDefault)
+        : ASTGEN_SUPER_Clocking(fl)
+        , m_isDefault{isDefault} {
+        m_name = name;
+        this->sensesp(sensesp);
+        addItemsp(itemsp);
     }
     ASTGEN_MEMBERS_AstClocking;
+    std::string name() const override { return m_name; }
+    bool isDefault() const { return m_isDefault; }
+};
+class AstClockingItem final : public AstNode {
+    // Parents:  CLOCKING
+    // Children: EXPRs, ASSIGNs, VARs
+    // @astgen op1 := skewp : Optional[AstNodeExpr]
+    // @astgen op2 := exprp : Optional[AstNodeExpr]
+    // @astgen op3 := assignp : Optional[AstAssign]
+    // @astgen op4 := varp : Optional[AstVar]
+    VDirection m_direction;
+
+public:
+    AstClockingItem(FileLine* fl, VDirection direction, AstNodeExpr* skewp, AstNode* clockingDeclp)
+        : ASTGEN_SUPER_ClockingItem(fl) {
+        m_direction = direction;
+        this->skewp(skewp);
+        if (AstAssign* const assignp = VN_CAST(clockingDeclp, Assign)) {
+            this->assignp(assignp);
+        } else {
+            exprp(VN_AS(clockingDeclp, NodeExpr));
+        }
+    }
+    ASTGEN_MEMBERS_AstClockingItem;
+    VDirection direction() const { return m_direction; }
 };
 class AstConstPool final : public AstNode {
     // Container for const static data
@@ -2182,6 +2215,17 @@ public:
     void dump(std::ostream& str) const override;
     VAlwaysKwd keyword() const { return m_keyword; }
 };
+class AstAlwaysObserved final : public AstNodeProcedure {
+    // Like always but Observed scheduling region
+    // @astgen op1 := sensesp : Optional[AstSenTree] // Sensitivity list, removed in V3Active
+
+public:
+    AstAlwaysObserved(FileLine* fl, AstSenTree* sensesp, AstNode* bodysp)
+        : ASTGEN_SUPER_AlwaysObserved(fl, bodysp) {
+        this->sensesp(sensesp);
+    }
+    ASTGEN_MEMBERS_AstAlwaysObserved;
+};
 class AstAlwaysPost final : public AstNodeProcedure {
     // Like always but post assignments for memory assignment IFs
     // @astgen op1 := sensesp : Optional[AstSenTree] // Sensitivity list iff clocked
@@ -2200,6 +2244,17 @@ public:
         : ASTGEN_SUPER_AlwaysPostponed(fl, stmtsp) {}
     ASTGEN_MEMBERS_AstAlwaysPostponed;
 };
+class AstAlwaysReactive final : public AstNodeProcedure {
+    // Like always but Reactive scheduling region
+    // @astgen op1 := sensesp : Optional[AstSenTree] // Sensitivity list, removed in V3Active
+
+public:
+    AstAlwaysReactive(FileLine* fl, AstSenTree* sensesp, AstNode* bodysp)
+        : ASTGEN_SUPER_AlwaysReactive(fl, bodysp) {
+        this->sensesp(sensesp);
+    }
+    ASTGEN_MEMBERS_AstAlwaysReactive;
+};
 class AstFinal final : public AstNodeProcedure {
 public:
     AstFinal(FileLine* fl, AstNode* stmtsp)
@@ -2496,13 +2551,18 @@ class AstDelay final : public AstNodeStmt {
     // Delay statement
     // @astgen op1 := lhsp : AstNodeExpr // Delay value
     // @astgen op2 := stmtsp : List[AstNode] // Statements under delay
+    const bool m_isCycle;  // True if it is a cycle delay
+
 public:
-    AstDelay(FileLine* fl, AstNodeExpr* lhsp)
-        : ASTGEN_SUPER_Delay(fl) {
+    AstDelay(FileLine* fl, AstNodeExpr* lhsp, bool isCycle)
+        : ASTGEN_SUPER_Delay(fl)
+        , m_isCycle{isCycle} {
         this->lhsp(lhsp);
     }
     ASTGEN_MEMBERS_AstDelay;
+    void dump(std::ostream& str) const override;
     bool isTimingControl() const override { return true; }
+    bool isCycleDelay() const { return m_isCycle; }
     bool same(const AstNode* /*samep*/) const override { return true; }
 };
 class AstDisable final : public AstNodeStmt {
diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp
index 6d833054e..7c69d1007 100644
--- a/src/V3AstNodes.cpp
+++ b/src/V3AstNodes.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -724,6 +724,9 @@ AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool compound) const {
         // + 1 below as VlQueue uses 0 to mean unlimited, 1 to mean size() max is 1
         if (adtypep->boundp()) info.m_type += ", " + cvtToStr(adtypep->boundConst() + 1);
         info.m_type += ">";
+    } else if (const auto* const adtypep = VN_CAST(dtypep, SampleQueueDType)) {
+        const CTypeRecursed sub = adtypep->subDTypep()->cTypeRecurse(true);
+        info.m_type = "VlSampleQueue<" + sub.m_type + ">";
     } else if (const auto* const adtypep = VN_CAST(dtypep, ClassRefDType)) {
         info.m_type = "VlClassRef<" + EmitCBaseVisitor::prefixNameProtect(adtypep) + ">";
     } else if (const auto* const adtypep = VN_CAST(dtypep, IfaceRefDType)) {
@@ -734,6 +737,9 @@ AstNodeDType::CTypeRecursed AstNodeDType::cTypeRecurse(bool compound) const {
         info.m_type = "VlUnpacked<" + sub.m_type;
         info.m_type += ", " + cvtToStr(adtypep->declRange().elements());
         info.m_type += ">";
+    } else if (VN_IS(dtypep, StructDType) && !VN_AS(dtypep, StructDType)->packed()) {
+        const auto* const sdtypep = VN_AS(dtypep, StructDType);
+        info.m_type = EmitCBaseVisitor::prefixNameProtect(sdtypep);
     } else if (const AstBasicDType* const bdtypep = dtypep->basicp()) {
         // We don't print msb()/lsb() as multidim packed would require recursion,
         // and may confuse users as C++ data is stored always with bit 0 used
@@ -1152,7 +1158,7 @@ static bool sameInit(const AstInitArray* ap, const AstInitArray* bp) {
         // Compare initializer arrays by value. Note this is only called when they hash the same,
         // so they likely run at most once per call to 'AstConstPool::findTable'.
         // This assumes that the defaults are used in the same way.
-        // TODO when buinding the AstInitArray, remove any values matching the default
+        // TODO when building the AstInitArray, remove any values matching the default
         const auto& amapr = ap->map();
         const auto& bmapr = bp->map();
         const auto ait = amapr.cbegin();
@@ -1999,6 +2005,10 @@ bool AstWildcardArrayDType::similarDType(const AstNodeDType* samep) const {
     return type() == samep->type() && asamep->subDTypep()
            && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp());
 }
+void AstSampleQueueDType::dumpSmall(std::ostream& str) const {
+    this->AstNodeDType::dumpSmall(str);
+    str << "[*]";
+}
 void AstUnsizedArrayDType::dumpSmall(std::ostream& str) const {
     this->AstNodeDType::dumpSmall(str);
     str << "[]";
@@ -2082,6 +2092,7 @@ void AstVar::dump(std::ostream& str) const {
     if (isSigPublic()) str << " [P]";
     if (isLatched()) str << " [LATCHED]";
     if (isUsedLoopIdx()) str << " [LOOP]";
+    if (noReset()) str << " [!RST]";
     if (attrIsolateAssign()) str << " [aISO]";
     if (attrFileDescr()) str << " [aFD]";
     if (isFuncReturn()) {
@@ -2320,3 +2331,8 @@ AstAlways* AstAssignW::convertToAlways() {
     replaceWith(newp);  // User expected to then deleteTree();
     return newp;
 }
+
+void AstDelay::dump(std::ostream& str) const {
+    this->AstNodeStmt::dump(str);
+    if (isCycleDelay()) str << " [CYCLE]";
+}
diff --git a/src/V3AstUserAllocator.h b/src/V3AstUserAllocator.h
index 1a7f55a46..c3b0d1dc2 100644
--- a/src/V3AstUserAllocator.h
+++ b/src/V3AstUserAllocator.h
@@ -7,7 +7,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp
index 9af5384a6..636b029e1 100644
--- a/src/V3Begin.cpp
+++ b/src/V3Begin.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -70,7 +70,7 @@ private:
     string m_namedScope;  // Name of begin blocks above us
     string m_unnamedScope;  // Name of begin blocks, including unnamed blocks
     int m_ifDepth = 0;  // Current if depth
-    bool m_underFork = false;  // True if the current statement is directly under a fork
+    bool m_keepBegins = false;  // True if begins should not be inlined
 
     // METHODS
 
@@ -123,11 +123,18 @@ private:
 
     // VISITORS
     void visit(AstFork* nodep) override {
-        VL_RESTORER(m_underFork);
-        m_underFork = true;
+        // Keep this begin to group its statements together
+        VL_RESTORER(m_keepBegins);
+        m_keepBegins = true;
         dotNames(nodep, "__FORK__");
         nodep->name("");
     }
+    void visit(AstNodeAssign* nodep) override {
+        // Keep begin under assignment (in nodep->timingControlp())
+        VL_RESTORER(m_keepBegins);
+        m_keepBegins = true;
+        iterateChildren(nodep);
+    }
     void visit(AstNodeModule* nodep) override {
         VL_RESTORER(m_modp);
         {
@@ -178,15 +185,14 @@ private:
         VL_RESTORER(m_unnamedScope);
         {
             {
-                VL_RESTORER(m_underFork);
-                m_underFork = false;
+                VL_RESTORER(m_keepBegins);
+                m_keepBegins = false;
                 dotNames(nodep, "__BEGIN__");
             }
             UASSERT_OBJ(!nodep->genforp(), nodep, "GENFORs should have been expanded earlier");
 
             // Cleanup
-            if (m_underFork) {
-                // If we're under a fork, keep this begin to group its statements together
+            if (m_keepBegins) {
                 nodep->name("");
                 return;
             }
@@ -263,8 +269,8 @@ private:
     }
     // VISITORS - LINT CHECK
     void visit(AstIf* nodep) override {  // not AstNodeIf; other types not covered
-        VL_RESTORER(m_underFork);
-        m_underFork = false;
+        VL_RESTORER(m_keepBegins);
+        m_keepBegins = false;
         // Check IFDEPTH warning - could be in other transform files if desire
         VL_RESTORER(m_ifDepth);
         if (m_ifDepth == -1 || v3Global.opt.ifDepth() < 1) {  // Turned off
@@ -279,8 +285,8 @@ private:
         iterateChildren(nodep);
     }
     void visit(AstNode* nodep) override {
-        VL_RESTORER(m_underFork);
-        m_underFork = false;
+        VL_RESTORER(m_keepBegins);
+        m_keepBegins = false;
         iterateChildren(nodep);
     }
 
diff --git a/src/V3Begin.h b/src/V3Begin.h
index 491821e3d..b62f6ce34 100644
--- a/src/V3Begin.h
+++ b/src/V3Begin.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Branch.cpp b/src/V3Branch.cpp
index 0cf4acda9..003b0cb24 100644
--- a/src/V3Branch.cpp
+++ b/src/V3Branch.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Branch.h b/src/V3Branch.h
index 8ad39daa4..a86d9fae1 100644
--- a/src/V3Branch.h
+++ b/src/V3Branch.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp
index 2ff17e9f6..aa02b4dd3 100644
--- a/src/V3Broken.cpp
+++ b/src/V3Broken.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -106,10 +106,11 @@ public:
                     // may be varp() and other cross links that are bad.
                     // When get this message, find what forgot to delete the
                     // node by running GDB, where for node "" use:
-                    //    watch AstNode::s_editCntGbl==####
+                    //    watch *(AstNode::s_editCntGbl)==####
                     //    run
                     //    bt
-                    std::cerr << "%Error: LeakedNode" << (withBack ? "with back pointer: " : ": ");
+                    std::cerr << "%Error: LeakedNode"
+                              << (withBack ? " with back pointer: " : ": ");
                     nodep->AstNode::dump(std::cerr);
                     std::cerr << endl;
                     V3Error::incErrors();
diff --git a/src/V3Broken.h b/src/V3Broken.h
index b6d6b2419..6f4822642 100644
--- a/src/V3Broken.h
+++ b/src/V3Broken.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3CCtors.cpp b/src/V3CCtors.cpp
index 3f9bce6ed..76453af5f 100644
--- a/src/V3CCtors.cpp
+++ b/src/V3CCtors.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -130,6 +130,80 @@ private:
 
 //######################################################################
 
+// Link state, as a visitor of each AstNode
+
+class CCtorsVisitor final : public VNVisitor {
+private:
+    // NODE STATE
+
+    // STATE
+    AstNodeModule* m_modp = nullptr;  // Current module
+    AstCFunc* m_cfuncp = nullptr;  // Current function
+    V3CCtorsBuilder* m_varResetp = nullptr;  // Builder of _ctor_var_reset
+
+    // VISITs
+    void visit(AstNodeModule* nodep) override {
+        VL_RESTORER(m_modp);
+        VL_RESTORER(m_varResetp);
+        m_modp = nodep;
+        V3CCtorsBuilder var_reset{nodep, "_ctor_var_reset",
+                                  VN_IS(nodep, Class) ? VCtorType::CLASS : VCtorType::MODULE};
+        m_varResetp = &var_reset;
+        iterateChildren(nodep);
+
+        if (v3Global.opt.coverage()) {
+            V3CCtorsBuilder configure_coverage{nodep, "_configure_coverage", VCtorType::COVERAGE};
+            for (AstNode* np = nodep->stmtsp(); np; np = np->nextp()) {
+                if (AstCoverDecl* const coverp = VN_CAST(np, CoverDecl)) {
+                    np = coverp->backp();
+                    configure_coverage.add(coverp->unlinkFrBack());
+                }
+            }
+        }
+        if (AstClass* const classp = VN_CAST(nodep, Class)) {
+            AstCFunc* const funcp = new AstCFunc{classp->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);
+            classp->addStmtsp(funcp);
+        }
+    }
+
+    void visit(AstCFunc* nodep) override {
+        VL_RESTORER(m_varResetp);
+        VL_RESTORER(m_cfuncp);
+        m_varResetp = nullptr;
+        m_cfuncp = nodep;
+        iterateChildren(nodep);
+    }
+    void visit(AstVar* nodep) override {
+        if (!nodep->isIfaceParent() && !nodep->isIfaceRef() && !nodep->noReset()
+            && !nodep->isParam() && !nodep->isStatementTemp()
+            && !(nodep->basicp()
+                 && (nodep->basicp()->isEvent() || nodep->basicp()->isTriggerVec()))) {
+            if (m_varResetp) {
+                const auto vrefp = new AstVarRef{nodep->fileline(), nodep, VAccess::WRITE};
+                m_varResetp->add(new AstCReset{nodep->fileline(), vrefp});
+            } else if (m_cfuncp) {
+                const auto vrefp = new AstVarRef{nodep->fileline(), nodep, VAccess::WRITE};
+                nodep->addNextHere(new AstCReset{nodep->fileline(), vrefp});
+            }
+        }
+    }
+
+    void visit(AstConstPool*) override {}
+    void visit(AstNode* nodep) override { iterateChildren(nodep); }
+
+public:
+    // CONSTRUCTORS
+    CCtorsVisitor(AstNode* nodep) { iterate(nodep); }
+    ~CCtorsVisitor() override = default;
+};
+
+//######################################################################
+
 void V3CCtors::evalAsserts() {
     AstNodeModule* const modp = v3Global.rootp()->modulesp();  // Top module wrapper
     AstCFunc* const funcp
@@ -178,42 +252,6 @@ void V3CCtors::evalAsserts() {
 void V3CCtors::cctorsAll() {
     UINFO(2, __FUNCTION__ << ": " << endl);
     evalAsserts();
-    for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp;
-         modp = VN_AS(modp->nextp(), NodeModule)) {
-        // Process each module in turn
-        {
-            V3CCtorsBuilder var_reset{modp, "_ctor_var_reset",
-                                      VN_IS(modp, Class) ? VCtorType::CLASS : VCtorType::MODULE};
-
-            for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
-                if (AstVar* const varp = VN_CAST(np, Var)) {
-                    if (!varp->isIfaceParent() && !varp->isIfaceRef() && !varp->noReset()
-                        && !varp->isParam()
-                        && !(varp->basicp()
-                             && (varp->basicp()->isEvent() || varp->basicp()->isTriggerVec()))) {
-                        const auto vrefp = new AstVarRef{varp->fileline(), varp, VAccess::WRITE};
-                        var_reset.add(new AstCReset{varp->fileline(), vrefp});
-                    }
-                }
-            }
-        }
-        if (v3Global.opt.coverage()) {
-            V3CCtorsBuilder configure_coverage{modp, "_configure_coverage", VCtorType::COVERAGE};
-            for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
-                if (AstCoverDecl* const coverp = VN_CAST(np, CoverDecl)) {
-                    np = coverp->backp();
-                    configure_coverage.add(coverp->unlinkFrBack());
-                }
-            }
-        }
-        if (const AstClass* const classp = VN_CAST(modp, Class)) {
-            AstCFunc* const 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->addStmtsp(funcp);
-        }
-    }
+    { CCtorsVisitor{v3Global.rootp()}; }
+    V3Global::dumpCheckGlobalTree("cctors", 0, dumpTree() >= 3);
 }
diff --git a/src/V3CCtors.h b/src/V3CCtors.h
index 41ad3e49c..4a244dca2 100644
--- a/src/V3CCtors.h
+++ b/src/V3CCtors.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3CUse.cpp b/src/V3CUse.cpp
index 11eb84957..85a03b697 100644
--- a/src/V3CUse.cpp
+++ b/src/V3CUse.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -73,6 +73,13 @@ class CUseVisitor final : public VNVisitor {
         if (nodep->user1SetOnce()) return;  // Process once
         if (nodep->virtRefDTypep()) iterate(nodep->virtRefDTypep());
         if (nodep->virtRefDType2p()) iterate(nodep->virtRefDType2p());
+
+        // Add a CUse for every struct that requires a declaration
+        AstStructDType* const stypep = VN_CAST(nodep->skipRefp(), StructDType);
+        if (stypep && stypep->classOrPackagep()) {
+            addNewUse(nodep, VUseType::INT_INCLUDE, stypep->classOrPackagep()->name());
+            iterateChildren(stypep);
+        }
     }
     void visit(AstNode* nodep) override {
         if (nodep->user1SetOnce()) return;  // Process once
diff --git a/src/V3CUse.h b/src/V3CUse.h
index 88e1e0425..1ab67c8f0 100644
--- a/src/V3CUse.h
+++ b/src/V3CUse.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Case.cpp b/src/V3Case.cpp
index dc378d51f..8a3857c17 100644
--- a/src/V3Case.cpp
+++ b/src/V3Case.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -274,7 +274,9 @@ private:
         // Convert valueItem from AstCaseItem* to the expression
         // Not done earlier, as we may now have a nullptr because it's just a ";" NOP branch
         for (uint32_t i = 0; i < numCases; ++i) {
-            m_valueItem[i] = VN_AS(m_valueItem[i], CaseItem)->stmtsp();
+            if (AstCaseItem* const itemp = VN_AS(m_valueItem[i], CaseItem)) {
+                m_valueItem[i] = itemp->stmtsp();
+            }
         }
         return true;  // All is fine
     }
diff --git a/src/V3Case.h b/src/V3Case.h
index c52a90246..0fa9fb11f 100644
--- a/src/V3Case.h
+++ b/src/V3Case.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Cast.cpp b/src/V3Cast.cpp
index b27e22669..4f253beed 100644
--- a/src/V3Cast.cpp
+++ b/src/V3Cast.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2004-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2004-2023 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.
@@ -159,7 +159,7 @@ private:
         const AstNode* const backp = nodep->backp();
         if (nodep->access().isReadOnly() && VN_IS(backp, NodeExpr) && !VN_IS(backp, CCast)
             && !VN_IS(backp, NodeCCall) && !VN_IS(backp, CMethodHard) && !VN_IS(backp, SFormatF)
-            && !VN_IS(backp, ArraySel) && !VN_IS(backp, RedXor)
+            && !VN_IS(backp, ArraySel) && !VN_IS(backp, StructSel) && !VN_IS(backp, RedXor)
             && (nodep->varp()->basicp() && !nodep->varp()->basicp()->isTriggerVec()
                 && !nodep->varp()->basicp()->isForkSync())
             && backp->width() && castSize(nodep) != castSize(nodep->varp())) {
diff --git a/src/V3Cast.h b/src/V3Cast.h
index 716fba353..1f359dc9c 100644
--- a/src/V3Cast.h
+++ b/src/V3Cast.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2004-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2004-2023 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.
diff --git a/src/V3Cdc.cpp b/src/V3Cdc.cpp
index a13e79554..0875bde87 100644
--- a/src/V3Cdc.cpp
+++ b/src/V3Cdc.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Cdc.h b/src/V3Cdc.h
index 31d26d879..d065cbd25 100644
--- a/src/V3Cdc.h
+++ b/src/V3Cdc.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Class.cpp b/src/V3Class.cpp
index c717e0b6f..f5e65b2a0 100644
--- a/src/V3Class.cpp
+++ b/src/V3Class.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -41,6 +41,7 @@ private:
 
     // MEMBERS
     string m_prefix;  // String prefix to add to name based on hier
+    AstNodeModule* m_modp = nullptr;  // Current module
     AstNodeModule* m_classPackagep = nullptr;  // Package moving into
     const AstScope* m_classScopep = nullptr;  // Package moving scopes into
     AstScope* m_packageScopep = nullptr;  // Class package scope
@@ -92,7 +93,9 @@ private:
         VL_RESTORER(m_classPackagep);
         VL_RESTORER(m_classScopep);
         VL_RESTORER(m_packageScopep);
+        VL_RESTORER(m_modp);
         {
+            m_modp = nodep;
             m_classPackagep = packagep;
             m_classScopep = classScopep;
             m_packageScopep = scopep;
@@ -104,7 +107,9 @@ private:
     void visit(AstNodeModule* nodep) override {
         // Visit for NodeModules that are not AstClass (AstClass is-a AstNodeModule)
         VL_RESTORER(m_prefix);
+        VL_RESTORER(m_modp);
         {
+            m_modp = nodep;
             m_prefix = nodep->name() + "__03a__03a";  // ::
             iterateChildren(nodep);
         }
@@ -166,6 +171,30 @@ private:
         }
     }
 
+    void setStructModulep(AstStructDType* const dtypep) {
+        // Give it a pointer to its package and a final name
+        dtypep->classOrPackagep(m_modp);
+        dtypep->name(dtypep->name() + "__struct" + cvtToStr(dtypep->uniqueNum()));
+
+        for (const AstMemberDType* itemp = dtypep->membersp(); itemp;
+             itemp = VN_AS(itemp->nextp(), MemberDType)) {
+            AstStructDType* const subp = VN_CAST(itemp->skipRefp(), StructDType);
+            // Recurse only into anonymous unpacked structs inside this definition,
+            // other unpacked structs will be reached from another typedefs
+            if (subp && !subp->packed() && subp->name().empty()) { setStructModulep(subp); }
+        }
+    }
+    void visit(AstTypedef* nodep) override {
+        if (nodep->user1SetOnce()) return;
+        iterateChildren(nodep);
+
+        AstStructDType* const dtypep = VN_CAST(nodep->dtypep(), StructDType);
+        if (dtypep && !dtypep->packed()) {
+            dtypep->name(nodep->name());
+            setStructModulep(dtypep);
+        }
+    }
+
     void visit(AstNodeExpr* nodep) override {}  // Short circuit
     void visit(AstNodeStmt* nodep) override {}  // Short circuit
     void visit(AstNode* nodep) override { iterateChildren(nodep); }
diff --git a/src/V3Class.h b/src/V3Class.h
index 6eed73f71..bde611ead 100644
--- a/src/V3Class.h
+++ b/src/V3Class.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Clean.cpp b/src/V3Clean.cpp
index c7190e401..bcd392abd 100644
--- a/src/V3Clean.cpp
+++ b/src/V3Clean.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -97,7 +97,9 @@ private:
                 || VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType)
                 || VN_IS(nodep->dtypep()->skipRefp(), VoidDType)) {
             } else {
-                setCppWidth(nodep);
+                const AstStructDType* const dtypep
+                    = VN_CAST(nodep->dtypep()->skipRefp(), StructDType);
+                if (!dtypep || dtypep->packed()) { setCppWidth(nodep); }
             }
         }
     }
diff --git a/src/V3Clean.h b/src/V3Clean.h
index ee3405c03..451004d00 100644
--- a/src/V3Clean.h
+++ b/src/V3Clean.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Clock.cpp b/src/V3Clock.cpp
index 7d2d39103..f2a537555 100644
--- a/src/V3Clock.cpp
+++ b/src/V3Clock.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Clock.h b/src/V3Clock.h
index d000abc77..c809b9113 100644
--- a/src/V3Clock.h
+++ b/src/V3Clock.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Combine.cpp b/src/V3Combine.cpp
index ee19f0eef..44e9b2954 100644
--- a/src/V3Combine.cpp
+++ b/src/V3Combine.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Combine.h b/src/V3Combine.h
index 88ac94e19..2ea3ef581 100644
--- a/src/V3Combine.h
+++ b/src/V3Combine.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Common.cpp b/src/V3Common.cpp
index a421c49f5..5e589d4d7 100644
--- a/src/V3Common.cpp
+++ b/src/V3Common.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -61,6 +61,37 @@ static void makeVlToString(AstIface* nodep) {
     funcp->addStmtsp(new AstCReturn{nodep->fileline(), exprp});
     nodep->addStmtsp(funcp);
 }
+static void makeVlToString(AstStructDType* nodep) {
+    AstNodeModule* const modp = nodep->classOrPackagep();
+    AstCFunc* const funcp
+        = new AstCFunc{nodep->fileline(), "VL_TO_STRING", nullptr, "std::string"};
+    funcp->argTypes("const " + EmitCBaseVisitor::prefixNameProtect(nodep) + "& obj");
+    funcp->isMethod(false);
+    funcp->isConst(false);
+    funcp->isStatic(false);
+    funcp->protect(false);
+    funcp->addStmtsp(new AstCStmt{nodep->fileline(), "std::string out;\n"});
+    for (const AstMemberDType* itemp = nodep->membersp(); itemp;
+         itemp = VN_AS(itemp->nextp(), MemberDType)) {
+        std::string stmt = "out += \"";
+        if (itemp == nodep->membersp()) {
+            stmt += "'{";
+        } else {
+            stmt += ", ";
+        }
+        stmt += itemp->nameProtect() + ":\" + ";
+        if (VN_IS(itemp->dtypep()->skipRefp(), BasicDType) && itemp->isWide()) {
+            stmt += "VL_TO_STRING_W";
+        } else {
+            stmt += "VL_TO_STRING";
+        }
+        stmt += "(obj." + itemp->nameProtect() + ");\n";
+        funcp->addStmtsp(new AstCStmt{nodep->fileline(), stmt});
+    }
+    funcp->addStmtsp(new AstCStmt{nodep->fileline(), "out += \"}\";\n"});
+    funcp->addStmtsp(new AstCStmt{nodep->fileline(), "return out;\n"});
+    modp->addStmtsp(funcp);
+}
 static void makeToString(AstClass* nodep) {
     AstCFunc* const funcp = new AstCFunc{nodep->fileline(), "to_string", nullptr, "std::string"};
     funcp->isConst(true);
@@ -135,5 +166,11 @@ void V3Common::commonAll() {
             makeVlToString(ifacep);
         }
     }
+    for (AstNode* nodep = v3Global.rootp()->typeTablep()->typesp(); nodep;
+         nodep = nodep->nextp()) {
+        if (AstStructDType* const dtypep = VN_CAST(nodep, StructDType)) {
+            if (!dtypep->packed()) makeVlToString(dtypep);
+        }
+    }
     V3Global::dumpCheckGlobalTree("common", 0, dumpTree() >= 3);
 }
diff --git a/src/V3Common.h b/src/V3Common.h
index 54f9f92bc..f71e7ba2e 100644
--- a/src/V3Common.h
+++ b/src/V3Common.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Config.cpp b/src/V3Config.cpp
index 0b3d277be..f5018d8cc 100644
--- a/src/V3Config.cpp
+++ b/src/V3Config.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2010-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2010-2023 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.
diff --git a/src/V3Config.h b/src/V3Config.h
index effe2da08..eff00b846 100644
--- a/src/V3Config.h
+++ b/src/V3Config.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2010-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2010-2023 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.
diff --git a/src/V3Const.cpp b/src/V3Const.cpp
index 4c2640d7f..c2f9b3d60 100644
--- a/src/V3Const.cpp
+++ b/src/V3Const.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -560,9 +560,13 @@ class ConstBitOpTreeVisitor final : public VNVisitor {
                     if (leafInfo.lsb() <= leafInfo.msb()) {
                         m_bitPolarities.emplace_back(leafInfo, isXorTree() || leafInfo.polarity(),
                                                      leafInfo.lsb());
-                    } else if (isAndTree() && leafInfo.polarity()) {
-                        // If there is a constant 0 term in an And tree, we must include it. Fudge
-                        // this by adding a bit with both polarities, which will simplify to zero
+                    } else if ((isAndTree() && leafInfo.polarity())
+                               || (isOrTree() && !leafInfo.polarity())) {
+                        // If there is a constant 0 term in an And tree or 1 term in an Or tree, we
+                        // must include it. Fudge this by adding a bit with both polarities, which
+                        // will simplify to zero or one respectively.
+                        // Note that Xor tree does not need this kind of care, polarity of Xor tree
+                        // is already cared when visitin AstNot. Taking xor with 1'b0 is nop.
                         m_bitPolarities.emplace_back(leafInfo, true, 0);
                         m_bitPolarities.emplace_back(leafInfo, false, 0);
                     }
@@ -1377,7 +1381,7 @@ private:
         // Pure checks - if this node and all nodes under it are free of
         // side effects can do this optimization
         // Eventually we'll recurse through tree when unknown, memoizing results so far,
-        // but for now can disable en-mass until V3Purify takes effect.
+        // but for now can disable en masse until V3Purify takes effect.
         return m_doShort || VN_IS(nodep, VarRef) || VN_IS(nodep, Const);
     }
     bool isTreePureRecurse(AstNode* nodep) {
@@ -2719,7 +2723,7 @@ private:
             if (nodep->isClocked()) {  // A constant can never get a pos/negedge
                 if (onlySenItemInSenTree(nodep)) {
                     if (nodep->edgeType() == VEdgeType::ET_CHANGED) {
-                        // TODO: This really is dodgy, as strictgly compliant simulators will not
+                        // TODO: This really is dodgy, as strictly compliant simulators will not
                         //       execute this block, but but t_func_check relies on it
                         nodep->replaceWith(
                             new AstSenItem{nodep->fileline(), AstSenItem::Initial{}});
@@ -3186,7 +3190,12 @@ private:
 
     void visit(AstStmtExpr* nodep) override {
         iterateChildren(nodep);
-        if (!nodep->exprp()) VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
+        if (!nodep->exprp()) {
+            VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
+            return;
+        }
+        // TODO if there's an ExprStmt underneath just keep lower statements
+        // (No current test case needs this)
     }
 
     // Simplify
diff --git a/src/V3Const.h b/src/V3Const.h
index 8cabc60d6..c171a5afe 100644
--- a/src/V3Const.h
+++ b/src/V3Const.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Coverage.cpp b/src/V3Coverage.cpp
index 173b87725..88e61becf 100644
--- a/src/V3Coverage.cpp
+++ b/src/V3Coverage.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -354,18 +354,34 @@ private:
                 newent.cleanup();
             }
         } else if (const AstStructDType* const adtypep = VN_CAST(dtypep, StructDType)) {
-            // For now it's packed, so similar to array
-            for (AstMemberDType* itemp = adtypep->membersp(); itemp;
-                 itemp = VN_AS(itemp->nextp(), MemberDType)) {
-                AstNodeDType* const subtypep = itemp->subDTypep()->skipRefp();
-                const int index_code = itemp->lsb();
-                ToggleEnt newent{above.m_comment + std::string{"."} + itemp->name(),
-                                 new AstSel{varp->fileline(), above.m_varRefp->cloneTree(true),
-                                            index_code, subtypep->width()},
-                                 new AstSel{varp->fileline(), above.m_chgRefp->cloneTree(true),
-                                            index_code, subtypep->width()}};
-                toggleVarRecurse(subtypep, depth + 1, newent, varp, chgVarp);
-                newent.cleanup();
+            if (adtypep->packed()) {
+                for (AstMemberDType* itemp = adtypep->membersp(); itemp;
+                     itemp = VN_AS(itemp->nextp(), MemberDType)) {
+                    AstNodeDType* const subtypep = itemp->subDTypep()->skipRefp();
+                    const int index_code = itemp->lsb();
+                    ToggleEnt newent{above.m_comment + std::string{"."} + itemp->name(),
+                                     new AstSel{varp->fileline(), above.m_varRefp->cloneTree(true),
+                                                index_code, subtypep->width()},
+                                     new AstSel{varp->fileline(), above.m_chgRefp->cloneTree(true),
+                                                index_code, subtypep->width()}};
+                    toggleVarRecurse(subtypep, depth + 1, newent, varp, chgVarp);
+                    newent.cleanup();
+                }
+            } else {
+                for (AstMemberDType* itemp = adtypep->membersp(); itemp;
+                     itemp = VN_AS(itemp->nextp(), MemberDType)) {
+                    AstNodeDType* const subtypep = itemp->subDTypep()->skipRefp();
+                    AstNodeExpr* const varRefp = new AstStructSel{
+                        varp->fileline(), above.m_varRefp->cloneTree(true), itemp->name()};
+                    AstNodeExpr* const chgRefp = new AstStructSel{
+                        varp->fileline(), above.m_varRefp->cloneTree(true), itemp->name()};
+                    varRefp->dtypep(subtypep);
+                    chgRefp->dtypep(subtypep);
+                    ToggleEnt newent{above.m_comment + std::string{"."} + itemp->name(), varRefp,
+                                     chgRefp};
+                    toggleVarRecurse(subtypep, depth + 1, newent, varp, chgVarp);
+                    newent.cleanup();
+                }
             }
         } else if (const AstUnionDType* const adtypep = VN_CAST(dtypep, UnionDType)) {
             // Arbitrarily handle only the first member of the union
diff --git a/src/V3Coverage.h b/src/V3Coverage.h
index efacd3f33..3a29fd7cb 100644
--- a/src/V3Coverage.h
+++ b/src/V3Coverage.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3CoverageJoin.cpp b/src/V3CoverageJoin.cpp
index 8e1b6cc6d..8b087f09f 100644
--- a/src/V3CoverageJoin.cpp
+++ b/src/V3CoverageJoin.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3CoverageJoin.h b/src/V3CoverageJoin.h
index fb786c2c8..3f1a88345 100644
--- a/src/V3CoverageJoin.h
+++ b/src/V3CoverageJoin.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp
index 32dedc071..2b45be47f 100644
--- a/src/V3Dead.cpp
+++ b/src/V3Dead.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -72,6 +72,7 @@ private:
     std::vector m_scopesp;
     std::vector m_cellsp;
     std::vector m_classesp;
+    std::vector m_typedefsp;
 
     AssignMap m_assignMap;  // List of all simple assignments for each variable
     const bool m_elimUserVars;  // Allow removal of user's vars
@@ -234,6 +235,11 @@ private:
         if (nodep->fromp()->dtypep()) nodep->fromp()->dtypep()->user1Inc();  // classref
         checkAll(nodep);
     }
+    void visit(AstStructSel* nodep) override {
+        iterateChildren(nodep);
+        if (nodep->fromp()->dtypep()) nodep->fromp()->dtypep()->user1Inc();  // structdtype
+        checkAll(nodep);
+    }
     void visit(AstModport* nodep) override {
         iterateChildren(nodep);
         if (m_elimCells) {
@@ -253,11 +259,8 @@ private:
     }
     void visit(AstTypedef* nodep) override {
         iterateChildren(nodep);
-        if (m_elimCells && !nodep->attrPublic()) {
-            VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
-            return;
-        }
-        checkAll(nodep);
+        m_typedefsp.push_back(nodep);
+
         // Don't let packages with only public variables disappear
         // 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();
@@ -299,6 +302,11 @@ private:
     }
 
     //-----
+    void visit(AstClockingItem* nodep) override {
+        // Prevent V3Dead from deleting clockvars that are seemingly dead before V3AssertPre. Later
+        // the vars will be moved to the containing module so if they are actually dead they will
+        // still get deleted.
+    }
     void visit(AstNode* nodep) override {
         if (nodep->isOutputter()) m_sideEffect = true;
         iterateChildren(nodep);
@@ -306,6 +314,22 @@ private:
     }
 
     // METHODS
+    void deadCheckTypedefs() {
+        for (AstTypedef* typedefp : m_typedefsp) {
+            if (shouldDeleteTypedef(typedefp)) {
+                VL_DO_DANGLING(pushDeletep(typedefp->unlinkFrBack()), typedefp);
+                continue;
+            }
+            checkAll(typedefp);
+        }
+    }
+    bool shouldDeleteTypedef(AstTypedef* typedefp) {
+        if (auto* structp = VN_CAST(typedefp->subDTypep(), StructDType)) {
+            if (structp->user1() && !structp->packed()) return false;
+        }
+        return m_elimCells && !typedefp->attrPublic();
+    }
+
     void deadCheckMod() {
         // Kill any unused modules
         // V3LinkCells has a graph that is capable of this too, but we need to do it
@@ -490,6 +514,7 @@ public:
             vscp->varp()->user1Inc();
         }
 
+        deadCheckTypedefs();
         deadCheckVar();
         // We only eliminate scopes when in a flattened structure
         // Otherwise we have no easy way to know if a scope is used
diff --git a/src/V3Dead.h b/src/V3Dead.h
index 01486c6fc..c94508137 100644
--- a/src/V3Dead.h
+++ b/src/V3Dead.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Delayed.cpp b/src/V3Delayed.cpp
index 62835fe89..2c30c392e 100644
--- a/src/V3Delayed.cpp
+++ b/src/V3Delayed.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Delayed.h b/src/V3Delayed.h
index 96d6f9e2e..dd36bda69 100644
--- a/src/V3Delayed.h
+++ b/src/V3Delayed.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Depth.cpp b/src/V3Depth.cpp
index a7f2a4288..2ca383362 100644
--- a/src/V3Depth.cpp
+++ b/src/V3Depth.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Depth.h b/src/V3Depth.h
index 372636d54..a35aaf56a 100644
--- a/src/V3Depth.h
+++ b/src/V3Depth.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3DepthBlock.cpp b/src/V3DepthBlock.cpp
index b45e5f208..f4e4ec5eb 100644
--- a/src/V3DepthBlock.cpp
+++ b/src/V3DepthBlock.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3DepthBlock.h b/src/V3DepthBlock.h
index 099c43f7b..0282d0487 100644
--- a/src/V3DepthBlock.h
+++ b/src/V3DepthBlock.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Descope.cpp b/src/V3Descope.cpp
index be9020dd8..fded54459 100644
--- a/src/V3Descope.cpp
+++ b/src/V3Descope.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Descope.h b/src/V3Descope.h
index c7175ff73..b8f77b8db 100644
--- a/src/V3Descope.h
+++ b/src/V3Descope.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Dfg.cpp b/src/V3Dfg.cpp
index 9f08a3b12..c3caf86c8 100644
--- a/src/V3Dfg.cpp
+++ b/src/V3Dfg.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Dfg.h b/src/V3Dfg.h
index 5d86805f8..ff6908d43 100644
--- a/src/V3Dfg.h
+++ b/src/V3Dfg.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -125,7 +125,7 @@ class DfgGraph final {
 
     // Variables and constants make up a significant proportion of vertices (40-50% was observed
     // in large designs), and they can often be treated specially in algorithms, which in turn
-    // enables significant verilation performance gains, so we keep these in separate lists for
+    // enables significant Verilation performance gains, so we keep these in separate lists for
     // direct access.
     V3List m_varVertices;  // The variable vertices in the graph
     V3List m_constVertices;  // The constant vertices in the graph
@@ -559,7 +559,7 @@ public:
     virtual const string srcName(size_t idx) const = 0;
 };
 
-// Specialisations of privateTypeTest
+// Specializations of privateTypeTest
 #include "V3Dfg__gen_type_tests.h"  // From ./astgen
 
 //------------------------------------------------------------------------------
diff --git a/src/V3DfgAstToDfg.cpp b/src/V3DfgAstToDfg.cpp
index a47f7262c..1afaaddff 100644
--- a/src/V3DfgAstToDfg.cpp
+++ b/src/V3DfgAstToDfg.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -277,9 +277,10 @@ class AstToDfgVisitor final : public VNVisitor {
                    std::vector& drivers) const {
         if (DfgConcat* const concatp = vtxp->cast()) {
             DfgVertex* const rhsp = concatp->rhsp();
+            auto const rhs_width = rhsp->width();
             addDriver(rhsp->fileline(), lsb, rhsp, drivers);
             DfgVertex* const lhsp = concatp->lhsp();
-            addDriver(lhsp->fileline(), lsb + rhsp->width(), lhsp, drivers);
+            addDriver(lhsp->fileline(), lsb + rhs_width, lhsp, drivers);
             concatp->unlinkDelete(*m_dfgp);
         } else {
             drivers.emplace_back(flp, lsb, vtxp);
diff --git a/src/V3DfgDecomposition.cpp b/src/V3DfgDecomposition.cpp
index b81edf12f..9dc61a07d 100644
--- a/src/V3DfgDecomposition.cpp
+++ b/src/V3DfgDecomposition.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -291,7 +291,7 @@ class ExtractCyclicComponents final {
         // Assign vertex to the target component
         vtxState.component = targetComponent;
 
-        // Visit all neighbours. We stop at variable boundaries,
+        // Visit all neighbors. We stop at variable boundaries,
         // which is where we will split the graphs
         vtx.forEachSource([=](DfgVertex& other) {
             if (other.is()) return;
diff --git a/src/V3DfgDfgToAst.cpp b/src/V3DfgDfgToAst.cpp
index cd32b3fcb..3932162be 100644
--- a/src/V3DfgDfgToAst.cpp
+++ b/src/V3DfgDfgToAst.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -276,7 +276,7 @@ class DfgToAstVisitor final : DfgVisitor {
             // Whole variable is driven. Just assign from the canonical variable.
             addResultEquation(dfgVarp->driverFileLine(0), wRef(), rRef());
         } else {
-            // Variable is driven partially. Asign from parts of the canonical var.
+            // Variable is driven partially. Assign from parts of the canonical var.
             dfgVarp->forEachSourceEdge([&](const DfgEdge& edge, size_t idx) {
                 UASSERT_OBJ(edge.sourcep(), dfgVarp, "Should have removed undriven sources");
                 // Create select LValue
@@ -292,7 +292,7 @@ class DfgToAstVisitor final : DfgVisitor {
     }
 
     void convertArrayDiver(const DfgVarArray* dfgVarp) {
-        // Variable is driven partially. Asign from parts of the canonical var.
+        // Variable is driven partially. Assign from parts of the canonical var.
         dfgVarp->forEachSourceEdge([&](const DfgEdge& edge, size_t idx) {
             UASSERT_OBJ(edge.sourcep(), dfgVarp, "Should have removed undriven sources");
             // Render the rhs expression
diff --git a/src/V3DfgOptimizer.cpp b/src/V3DfgOptimizer.cpp
index 958d73202..d3b361bf6 100644
--- a/src/V3DfgOptimizer.cpp
+++ b/src/V3DfgOptimizer.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3DfgOptimizer.h b/src/V3DfgOptimizer.h
index 5377dcd23..16b4b34cb 100644
--- a/src/V3DfgOptimizer.h
+++ b/src/V3DfgOptimizer.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3DfgPasses.cpp b/src/V3DfgPasses.cpp
index 0b6f43758..edeb007dd 100644
--- a/src/V3DfgPasses.cpp
+++ b/src/V3DfgPasses.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3DfgPasses.h b/src/V3DfgPasses.h
index 7d8ed5913..fabe4f92d 100644
--- a/src/V3DfgPasses.h
+++ b/src/V3DfgPasses.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3DfgPeephole.cpp b/src/V3DfgPeephole.cpp
index c62875526..72d1f19b0 100644
--- a/src/V3DfgPeephole.cpp
+++ b/src/V3DfgPeephole.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -1400,26 +1400,17 @@ class V3DfgPeephole final : public DfgVisitor {
     }
 
     void visit(DfgShiftL* vtxp) override {
-        UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched width");
-
         if (foldBinary(vtxp)) return;
-
         optimizeShiftRHS(vtxp);
     }
 
     void visit(DfgShiftR* vtxp) override {
-        UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched width");
-
         if (foldBinary(vtxp)) return;
-
         optimizeShiftRHS(vtxp);
     }
 
     void visit(DfgShiftRS* vtxp) override {
-        UASSERT_OBJ(vtxp->dtypep() == vtxp->lhsp()->dtypep(), vtxp, "Mismatched width");
-
         if (foldBinary(vtxp)) return;
-
         optimizeShiftRHS(vtxp);
     }
 
diff --git a/src/V3DfgPeephole.h b/src/V3DfgPeephole.h
index 6323fbe13..a20cadf6a 100644
--- a/src/V3DfgPeephole.h
+++ b/src/V3DfgPeephole.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3DfgVertices.h b/src/V3DfgVertices.h
index a440f9b8d..a576d5767 100644
--- a/src/V3DfgVertices.h
+++ b/src/V3DfgVertices.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3DupFinder.cpp b/src/V3DupFinder.cpp
index 70647a1d1..49fcf2808 100644
--- a/src/V3DupFinder.cpp
+++ b/src/V3DupFinder.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3DupFinder.h b/src/V3DupFinder.h
index 9bc8df81b..37118aebc 100644
--- a/src/V3DupFinder.h
+++ b/src/V3DupFinder.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2005-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2005-2023 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.
diff --git a/src/V3EmitC.h b/src/V3EmitC.h
index cafec665a..696eb3df6 100644
--- a/src/V3EmitC.h
+++ b/src/V3EmitC.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3EmitCBase.cpp b/src/V3EmitCBase.cpp
index 1a426e1bb..884950da2 100644
--- a/src/V3EmitCBase.cpp
+++ b/src/V3EmitCBase.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3EmitCBase.h b/src/V3EmitCBase.h
index 8f7a97dd8..39ff0e70e 100644
--- a/src/V3EmitCBase.h
+++ b/src/V3EmitCBase.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -97,6 +97,7 @@ public:
         return v3Global.opt.compLimitMembers() != 0  // Enabled
                && !varp->isStatic()  // Not a static variable
                && !varp->isSc()  // Aggregates can't be anon
+               && !VN_IS(varp->dtypep()->skipRefp(), SampleQueueDType)  // Aggregates can't be anon
                && (varp->basicp() && !varp->basicp()->isOpaque());  // Aggregates can't be anon
     }
 
diff --git a/src/V3EmitCConstInit.h b/src/V3EmitCConstInit.h
index adc317b36..9113348e5 100644
--- a/src/V3EmitCConstInit.h
+++ b/src/V3EmitCConstInit.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3EmitCConstPool.cpp b/src/V3EmitCConstPool.cpp
index 00c3d9459..6ba5c33bc 100644
--- a/src/V3EmitCConstPool.cpp
+++ b/src/V3EmitCConstPool.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3EmitCFunc.cpp b/src/V3EmitCFunc.cpp
index 214d8d9b1..0184a8b88 100644
--- a/src/V3EmitCFunc.cpp
+++ b/src/V3EmitCFunc.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -578,8 +578,9 @@ void EmitCFunc::emitSetVarConstant(const string& assignString, AstConst* constp)
 
 void EmitCFunc::emitVarReset(AstVar* varp) {
     AstNodeDType* const dtypep = varp->dtypep()->skipRefp();
-    const string varNameProtected
-        = VN_IS(m_modp, Class) ? varp->nameProtect() : "vlSelf->" + varp->nameProtect();
+    const string varNameProtected = (VN_IS(m_modp, Class) || varp->isFuncLocal())
+                                        ? varp->nameProtect()
+                                        : "vlSelf->" + varp->nameProtect();
     if (varp->isIO() && m_modp->isTop() && optSystemC()) {
         // System C top I/O doesn't need loading, as the lower level subinst code does it.}
     } else if (varp->isParam()) {
@@ -660,6 +661,8 @@ string EmitCFunc::emitVarResetRecurse(const AstVar* varp, const string& varNameP
         const string cvtarray = (adtypep->subDTypep()->isWide() ? ".data()" : "");
         return emitVarResetRecurse(varp, varNameProtected, adtypep->subDTypep(), depth + 1,
                                    suffix + ".atDefault()" + cvtarray);
+    } else if (VN_IS(dtypep, SampleQueueDType)) {
+        return "";
     } else if (const AstUnpackArrayDType* const adtypep = VN_CAST(dtypep, UnpackArrayDType)) {
         UASSERT_OBJ(adtypep->hi() >= adtypep->lo(), varp,
                     "Should have swapped msb & lsb earlier.");
@@ -670,6 +673,17 @@ string EmitCFunc::emitVarResetRecurse(const AstVar* varp, const string& varNameP
                                                  depth + 1, suffix + "[" + ivar + "]");
         const string post = "}\n";
         return below.empty() ? "" : pre + below + post;
+    } else if (VN_IS(dtypep, StructDType) && !VN_AS(dtypep, StructDType)->packed()) {
+        const auto* const sdtypep = VN_AS(dtypep, StructDType);
+        string literal;
+        for (const AstMemberDType* itemp = sdtypep->membersp(); itemp;
+             itemp = VN_AS(itemp->nextp(), MemberDType)) {
+            const std::string line
+                = emitVarResetRecurse(varp, varNameProtected + suffix + "." + itemp->nameProtect(),
+                                      itemp->dtypep(), depth + 1, "");
+            if (!line.empty()) literal += line;
+        }
+        return literal;
     } else if (basicp && basicp->keyword() == VBasicDTypeKwd::STRING) {
         // String's constructor deals with it
         return "";
@@ -684,9 +698,11 @@ string EmitCFunc::emitVarResetRecurse(const AstVar* varp, const string& varNameP
     } else if (basicp) {
         const bool zeroit
             = (varp->attrFileDescr()  // Zero so we don't do file IO if never $fopen
+               || varp->isFuncLocal()  // Randomization too slow
                || (basicp && basicp->isZeroInit())
                || (v3Global.opt.underlineZero() && !varp->name().empty() && varp->name()[0] == '_')
                || (v3Global.opt.xInitial() == "fast" || v3Global.opt.xInitial() == "0"));
+        const bool slow = !varp->isFuncLocal() && !varp->isClassMember();
         splitSizeInc(1);
         if (dtypep->isWide()) {  // Handle unpacked; not basicp->isWide
             string out;
@@ -698,7 +714,7 @@ string EmitCFunc::emitVarResetRecurse(const AstVar* varp, const string& varNameP
                     out += cvtToStr(constp->num().edataWord(w)) + "U;\n";
                 }
             } else {
-                out += zeroit ? "VL_ZERO_RESET_W(" : "VL_RAND_RESET_W(";
+                out += zeroit ? (slow ? "VL_ZERO_RESET_W(" : "VL_ZERO_W(") : "VL_RAND_RESET_W(";
                 out += cvtToStr(dtypep->widthMin());
                 out += ", " + varNameProtected + suffix + ");\n";
             }
diff --git a/src/V3EmitCFunc.h b/src/V3EmitCFunc.h
index e19a42995..7f1078505 100644
--- a/src/V3EmitCFunc.h
+++ b/src/V3EmitCFunc.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -358,7 +358,7 @@ public:
             // Wide functions assign into the array directly, don't need separate assign statement
             m_wideTempRefp = VN_AS(nodep->lhsp(), VarRef);
             paren = false;
-        } else if (nodep->isWide()) {
+        } else if (nodep->isWide() && !VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType)) {
             putbs("VL_ASSIGN_W(");
             puts(cvtToStr(nodep->widthMin()) + ",");
             iterateAndNextNull(nodep->lhsp());
@@ -1066,6 +1066,11 @@ public:
         putbs("->");
         puts(nodep->varp()->nameProtect());
     }
+    void visit(AstStructSel* nodep) override {
+        iterateAndNextNull(nodep->fromp());
+        putbs(".");
+        puts(nodep->nameProtect());
+    }
     void visit(AstNullCheck* nodep) override {
         puts("VL_NULL_CHECK(");
         iterateAndNextNull(nodep->lhsp());
diff --git a/src/V3EmitCHeaders.cpp b/src/V3EmitCHeaders.cpp
index a20c622ab..744e13baf 100644
--- a/src/V3EmitCHeaders.cpp
+++ b/src/V3EmitCHeaders.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -147,7 +147,7 @@ class EmitCHeader final : public EmitCConstInit {
         if (!VN_IS(modp, Class)) {  // Classes use CFuncs with isConstructor/isDestructor
             const string& name = prefixNameProtect(modp);
             putsDecoration("\n// CONSTRUCTORS\n");
-            puts(name + "(" + symClassName() + "* symsp, const char* name);\n");
+            puts(name + "(" + symClassName() + "* symsp, const char* v__name);\n");
             puts("~" + name + "();\n");
             puts("VL_UNCOPYABLE(" + name + ");\n");
         }
@@ -208,6 +208,44 @@ class EmitCHeader final : public EmitCConstInit {
             }
         }
     }
+    void emitStructDecl(const AstNodeModule* modp, AstStructDType* sdtypep,
+                        std::set& emitted) {
+        if (emitted.count(sdtypep) > 0) return;
+        emitted.insert(sdtypep);
+        for (const AstMemberDType* itemp = sdtypep->membersp(); itemp;
+             itemp = VN_AS(itemp->nextp(), MemberDType)) {
+            AstStructDType* subp = VN_CAST(itemp->skipRefp(), StructDType);
+            if (subp && !subp->packed()) {
+                // Recurse if it belongs to the current module
+                if (subp->classOrPackagep() == modp) {
+                    emitStructDecl(modp, subp, emitted);
+                    puts("\n");
+                }
+            }
+        }
+        puts("struct " + EmitCBaseVisitor::prefixNameProtect(sdtypep) + " {\n");
+        for (const AstMemberDType* itemp = sdtypep->membersp(); itemp;
+             itemp = VN_AS(itemp->nextp(), MemberDType)) {
+            puts(itemp->dtypep()->cType(itemp->nameProtect(), false, false));
+            puts(";\n");
+        }
+        puts("};\n");
+    }
+    void emitStructs(const AstNodeModule* modp) {
+        bool first = true;
+        // Track structs that've been emitted already
+        std::set emitted;
+        for (const AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
+            const AstTypedef* const tdefp = VN_CAST(nodep, Typedef);
+            if (!tdefp) continue;
+            AstStructDType* const sdtypep
+                = VN_CAST(tdefp->dtypep()->skipRefToEnump(), StructDType);
+            if (!sdtypep) continue;
+            if (sdtypep->packed()) continue;
+            decorateFirst(first, "\n// UNPACKED STRUCT TYPES\n");
+            emitStructDecl(modp, sdtypep, emitted);
+        }
+    }
     void emitFuncDecls(const AstNodeModule* modp, bool inClassBody) {
         std::vector funcsp;
 
@@ -252,6 +290,8 @@ class EmitCHeader final : public EmitCConstInit {
         // From `systemc_header
         emitTextSection(modp, VNType::atScHdr);
 
+        emitStructs(modp);
+
         // Open class body {{{
         puts("\nclass ");
         puts(prefixNameProtect(modp));
diff --git a/src/V3EmitCImp.cpp b/src/V3EmitCImp.cpp
index bcdeb9618..16e24ac64 100644
--- a/src/V3EmitCImp.cpp
+++ b/src/V3EmitCImp.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -50,6 +50,11 @@ class EmitCGatherDependencies final : VNVisitor {
         if (const AstClassRefDType* const dtypep = VN_CAST(nodep, ClassRefDType)) {
             m_dependencies.insert(
                 EmitCBaseVisitor::prefixNameProtect(dtypep->classp()->classOrPackagep()));
+        } else if (const AstStructDType* const dtypep = VN_CAST(nodep, StructDType)) {
+            if (!dtypep->packed()) {
+                m_dependencies.insert(
+                    EmitCBaseVisitor::prefixNameProtect(dtypep->classOrPackagep()));
+            }
         }
     }
     void addSelfDependency(const string& selfPointer, AstNode* nodep) {
@@ -92,6 +97,10 @@ class EmitCGatherDependencies final : VNVisitor {
         addDTypeDependency(nodep->fromp()->dtypep());
         iterateChildrenConst(nodep);
     }
+    void visit(AstStructSel* nodep) override {
+        addDTypeDependency(nodep->fromp()->dtypep());
+        iterateChildrenConst(nodep);
+    }
     void visit(AstNodeVarRef* nodep) override {
         addSelfDependency(nodep->selfPointer(), nodep->varp());
         iterateChildrenConst(nodep);
@@ -241,8 +250,8 @@ class EmitCImp final : EmitCFunc {
                          "(" + modName + "* vlSelf);");
         puts("\n");
 
-        puts(modName + "::" + modName + "(" + symClassName() + "* symsp, const char* name)\n");
-        puts("    : VerilatedModule{name}\n");
+        puts(modName + "::" + modName + "(" + symClassName() + "* symsp, const char* v__name)\n");
+        puts("    : VerilatedModule{v__name}\n");
 
         ofp()->indentInc();
         for (const AstNode* nodep = modp->stmtsp(); nodep; nodep = nodep->nextp()) {
diff --git a/src/V3EmitCInlines.cpp b/src/V3EmitCInlines.cpp
index 58cae781a..338b956ec 100644
--- a/src/V3EmitCInlines.cpp
+++ b/src/V3EmitCInlines.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3EmitCMain.cpp b/src/V3EmitCMain.cpp
index 992720031..352e15603 100644
--- a/src/V3EmitCMain.cpp
+++ b/src/V3EmitCMain.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3EmitCMain.h b/src/V3EmitCMain.h
index c61826b9b..cf4d04f9f 100644
--- a/src/V3EmitCMain.h
+++ b/src/V3EmitCMain.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3EmitCMake.cpp b/src/V3EmitCMake.cpp
index ca3a3d3ef..071808934 100644
--- a/src/V3EmitCMake.cpp
+++ b/src/V3EmitCMake.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2004-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2004-2023 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.
diff --git a/src/V3EmitCMake.h b/src/V3EmitCMake.h
index 9c17c0563..1f2a11246 100644
--- a/src/V3EmitCMake.h
+++ b/src/V3EmitCMake.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3EmitCModel.cpp b/src/V3EmitCModel.cpp
index 32cceae3a..94567f1a8 100644
--- a/src/V3EmitCModel.cpp
+++ b/src/V3EmitCModel.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3EmitCSyms.cpp b/src/V3EmitCSyms.cpp
index 86692e6d4..8b3e75d84 100644
--- a/src/V3EmitCSyms.cpp
+++ b/src/V3EmitCSyms.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3EmitMk.cpp b/src/V3EmitMk.cpp
index 2964f0bc3..86f325c2f 100644
--- a/src/V3EmitMk.cpp
+++ b/src/V3EmitMk.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2004-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2004-2023 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.
@@ -317,7 +317,7 @@ class EmitMkHierVerilation final {
     void emit(V3OutMkFile& of) const {
         of.puts("# Hierarchical Verilation -*- Makefile -*-\n");
         of.puts("# DESCR"
-                "IPTION: Verilator output: Makefile for hierarchical verilatrion\n");
+                "IPTION: Verilator output: Makefile for hierarchical Verilation\n");
         of.puts("#\n");
         of.puts("# The main makefile " + v3Global.opt.prefix() + ".mk calls this makefile\n");
         of.puts("\n");
diff --git a/src/V3EmitMk.h b/src/V3EmitMk.h
index 6b8d6b5fd..a23748fb0 100644
--- a/src/V3EmitMk.h
+++ b/src/V3EmitMk.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3EmitV.cpp b/src/V3EmitV.cpp
index 5561ee89e..f55c3c074 100644
--- a/src/V3EmitV.cpp
+++ b/src/V3EmitV.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2004-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2004-2023 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.
diff --git a/src/V3EmitV.h b/src/V3EmitV.h
index 6e74823ae..8af3061df 100644
--- a/src/V3EmitV.h
+++ b/src/V3EmitV.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3EmitXml.cpp b/src/V3EmitXml.cpp
index c3ac43da1..ef8071a20 100644
--- a/src/V3EmitXml.cpp
+++ b/src/V3EmitXml.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2004-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2004-2023 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.
diff --git a/src/V3EmitXml.h b/src/V3EmitXml.h
index a8a45db59..399f3f743 100644
--- a/src/V3EmitXml.h
+++ b/src/V3EmitXml.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Error.cpp b/src/V3Error.cpp
index 798c280c0..0a3515219 100644
--- a/src/V3Error.cpp
+++ b/src/V3Error.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Error.h b/src/V3Error.h
index 63fb4828d..1dc8e2487 100644
--- a/src/V3Error.h
+++ b/src/V3Error.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -96,6 +96,7 @@ public:
         IGNOREDRETURN,  // Ignoring return value (function as task)
         IMPERFECTSCH,   // Imperfect schedule (disabled by default). Historical, never issued.
         IMPLICIT,       // Implicit wire
+        IMPLICITSTATIC, // Implicit static function
         IMPORTSTAR,     // Import::* in $unit
         IMPURE,         // Impure function not being inlined
         INCABSPATH,     // Include has absolute path
@@ -180,7 +181,7 @@ public:
             "DECLFILENAME", "DEFPARAM", "DEPRECATED",
             "ENCAPSULATED", "ENDLABEL", "ENUMVALUE", "EOFNEWLINE", "GENCLK", "HIERBLOCK",
             "IFDEPTH", "IGNOREDRETURN",
-            "IMPERFECTSCH", "IMPLICIT", "IMPORTSTAR", "IMPURE",
+            "IMPERFECTSCH", "IMPLICIT", "IMPLICITSTATIC", "IMPORTSTAR", "IMPURE",
             "INCABSPATH", "INFINITELOOP", "INITIALDLY", "INSECURE",
             "LATCH", "LITENDIAN", "MINTYPMAXDLY", "MODDUP",
             "MULTIDRIVEN", "MULTITOP","NOLATCH", "NULLPORT", "PINCONNECTEMPTY",
@@ -220,9 +221,9 @@ public:
     bool lintError() const VL_MT_SAFE {
         return (m_e == ALWCOMBORDER || m_e == BSSPACE || m_e == CASEINCOMPLETE
                 || m_e == CASEOVERLAP || m_e == CASEWITHX || m_e == CASEX || m_e == CASTCONST
-                || m_e == CMPCONST || m_e == COLONPLUS || m_e == IMPLICIT || m_e == LATCH
-                || m_e == LITENDIAN || m_e == PINMISSING || m_e == REALCVT || m_e == UNSIGNED
-                || m_e == WIDTH);
+                || m_e == CMPCONST || m_e == COLONPLUS || m_e == IMPLICIT || m_e == IMPLICITSTATIC
+                || m_e == LATCH || m_e == LITENDIAN || m_e == PINMISSING || m_e == REALCVT
+                || m_e == UNSIGNED || m_e == WIDTH);
     }
     // Warnings that are style only
     bool styleError() const VL_MT_SAFE {
@@ -431,11 +432,12 @@ inline void v3errorEndFatal(std::ostringstream& sstr) {
     return value
 
 // Helper macros for VL_DEFINE_DEBUG_FUNCTIONS
-#define VL_DEFINE_DEBUG(name) \
-    VL_ATTR_UNUSED static int debug##name() { \
+// Takes an optional "name" (as __VA_ARGS__)
+#define VL_DEFINE_DEBUG(...) \
+    VL_ATTR_UNUSED static int debug##__VA_ARGS__() { \
         static int level = -1; \
         if (VL_UNLIKELY(level < 0)) { \
-            std::string tag{VL_STRINGIFY(name)}; \
+            std::string tag{VL_STRINGIFY(__VA_ARGS__)}; \
             tag[0] = std::tolower(tag[0]); \
             const unsigned debugTag = v3Global.opt.debugLevel(tag); \
             const unsigned debugSrc = v3Global.opt.debugSrcLevel(__FILE__); \
@@ -447,11 +449,12 @@ inline void v3errorEndFatal(std::ostringstream& sstr) {
     } \
     static_assert(true, "")
 
-#define VL_DEFINE_DUMP(name) \
-    VL_ATTR_UNUSED static int dump##name() { \
+// Takes an optional "name" (as __VA_ARGS__)
+#define VL_DEFINE_DUMP(...) \
+    VL_ATTR_UNUSED static int dump##__VA_ARGS__() { \
         static int level = -1; \
         if (VL_UNLIKELY(level < 0)) { \
-            std::string tag{VL_STRINGIFY(name)}; \
+            std::string tag{VL_STRINGIFY(__VA_ARGS__)}; \
             tag[0] = std::tolower(tag[0]); \
             const unsigned dumpTag = v3Global.opt.dumpLevel(tag); \
             const unsigned dumpSrc = v3Global.opt.dumpSrcLevel(__FILE__); \
diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp
index 5efbb7592..a34660a7d 100644
--- a/src/V3Expand.cpp
+++ b/src/V3Expand.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2004-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2004-2023 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.
@@ -341,6 +341,18 @@ private:
             VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
         }
     }
+    bool expandWide(AstNodeAssign* nodep, AstExtend* rhsp) {
+        UINFO(8, "    Wordize ASSIGN(EXTEND) " << nodep << endl);
+        if (!doExpand(nodep)) return false;
+        AstNodeExpr* const rlhsp = rhsp->lhsp();
+        for (int w = 0; w < rlhsp->widthWords(); ++w) {
+            addWordAssign(nodep, w, newAstWordSelClone(rlhsp, w));
+        }
+        for (int w = rlhsp->widthWords(); w < nodep->widthWords(); ++w) {
+            addWordAssign(nodep, w, new AstConst{nodep->fileline(), AstConst::SizedEData{}, 0});
+        }
+        return true;
+    }
 
     void visit(AstSel* nodep) override {
         if (nodep->user1SetOnce()) return;  // Process once
@@ -836,6 +848,10 @@ private:
     }
     void visit(AstNodeAssign* nodep) override {
         if (nodep->user1SetOnce()) return;  // Process once
+        if (VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType)) {
+            return;  // Skip for UnpackArrayDType
+        }
+
         VL_RESTORER(m_stmtp);
         m_stmtp = nodep;
         iterateChildren(nodep);
@@ -854,6 +870,8 @@ private:
                 did = expandWide(nodep, rhsp);
             } else if (AstConcat* const rhsp = VN_CAST(nodep->rhsp(), Concat)) {
                 did = expandWide(nodep, rhsp);
+            } else if (AstExtend* const rhsp = VN_CAST(nodep->rhsp(), Extend)) {
+                did = expandWide(nodep, rhsp);
             } else if (AstReplicate* const rhsp = VN_CAST(nodep->rhsp(), Replicate)) {
                 did = expandWide(nodep, rhsp);
             } else if (AstAnd* const rhsp = VN_CAST(nodep->rhsp(), And)) {
diff --git a/src/V3Expand.h b/src/V3Expand.h
index 39f2f2f23..01938f7a9 100644
--- a/src/V3Expand.h
+++ b/src/V3Expand.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3File.cpp b/src/V3File.cpp
index d2b24cf9a..af4fa9162 100644
--- a/src/V3File.cpp
+++ b/src/V3File.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3File.h b/src/V3File.h
index ba2b5c6d1..fcee430f8 100644
--- a/src/V3File.h
+++ b/src/V3File.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -126,7 +126,7 @@ private:
     bool m_inStringLiteral = false;
     int m_indentLevel = 0;  // Current {} indentation
     std::stack m_parenVec;  // Stack of columns where last ( was
-    int m_bracketLevel = 0;  // Intenting = { block, indicates number of {'s seen.
+    int m_bracketLevel = 0;  // Indenting = { block, indicates number of {'s seen.
 
     int endLevels(const char* strg);
     void putcNoTracking(char chr);
diff --git a/src/V3FileLine.cpp b/src/V3FileLine.cpp
index 4ded807ee..026bd2823 100644
--- a/src/V3FileLine.cpp
+++ b/src/V3FileLine.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3FileLine.h b/src/V3FileLine.h
index 4453f0db6..2da4cc73d 100644
--- a/src/V3FileLine.h
+++ b/src/V3FileLine.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Force.cpp b/src/V3Force.cpp
index 84cdc972b..46a1166f7 100644
--- a/src/V3Force.cpp
+++ b/src/V3Force.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Force.h b/src/V3Force.h
index 6c1e87188..0318f80e3 100644
--- a/src/V3Force.h
+++ b/src/V3Force.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3FunctionTraits.h b/src/V3FunctionTraits.h
index 6f8a854e0..5f4e133a1 100644
--- a/src/V3FunctionTraits.h
+++ b/src/V3FunctionTraits.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp
index fe8fae672..3b450856f 100644
--- a/src/V3Gate.cpp
+++ b/src/V3Gate.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -510,6 +510,7 @@ private:
     void visit(AstCFunc* nodep) override {
         iterateNewStmt(nodep, "User C Function", "User C Function");
     }
+    void visit(AstClocking* nodep) override { iterateNewStmt(nodep, nullptr, nullptr); }
     void visit(AstSenItem* nodep) override {
         m_inSenItem = true;
         if (m_logicVertexp) {  // Already under logic; presumably a SenGate
@@ -592,7 +593,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
         if (!logicVertexp->reducible()) continue;
         AstNode* const logicp = logicVertexp->nodep();
 
-        // Commit pendingg optimizations to driving logic, as we will re-analyse
+        // Commit pending optimizations to driving logic, as we will re-analyze
         commitElimVar(logicp);
 
         // Can we eliminate?
diff --git a/src/V3Gate.h b/src/V3Gate.h
index f7950c51d..f4a03d3f0 100644
--- a/src/V3Gate.h
+++ b/src/V3Gate.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Global.cpp b/src/V3Global.cpp
index c75b51785..89fac8f91 100644
--- a/src/V3Global.cpp
+++ b/src/V3Global.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2004-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2004-2023 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.
@@ -35,14 +35,11 @@ void V3Global::boot() {
     m_rootp = new AstNetlist;
 }
 
-void V3Global::clear() {
-#ifdef VL_LEAK_CHECK
-    if (m_rootp) VL_DO_CLEAR(m_rootp->deleteTree(), m_rootp = nullptr);
-#endif
-}
-
 void V3Global::shutdown() {
     VL_DO_CLEAR(delete m_hierPlanp, m_hierPlanp = nullptr);  // delete nullptr is safe
+#ifdef VL_LEAK_CHECKS
+    if (m_rootp) VL_DO_CLEAR(m_rootp->deleteTree(), m_rootp = nullptr);
+#endif
 }
 
 void V3Global::checkTree() const { rootp()->checkTree(); }
diff --git a/src/V3Global.h b/src/V3Global.h
index 7807d6f2b..228440e3a 100644
--- a/src/V3Global.h
+++ b/src/V3Global.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -93,7 +93,7 @@ class V3Global final {
     // Globals
     AstNetlist* m_rootp = nullptr;  // Root of entire netlist,
     // created by makeInitNetlist(} so static constructors run first
-    V3HierBlockPlan* m_hierPlanp = nullptr;  // Hierarchical verilation plan,
+    V3HierBlockPlan* m_hierPlanp = nullptr;  // Hierarchical Verilation plan,
     // nullptr unless hier_block, set via hierPlanp(V3HierBlockPlan*}
     VWidthMinUsage m_widthMinUsage
         = VWidthMinUsage::LINT_WIDTH;  // What AstNode::widthMin() is used for
@@ -126,7 +126,6 @@ public:
     // CONSTRUCTORS
     V3Global() {}
     void boot();
-    void clear();
     void shutdown();  // Release allocated resources
     // ACCESSORS (general)
     AstNetlist* rootp() const VL_MT_SAFE { return m_rootp; }
diff --git a/src/V3Graph.cpp b/src/V3Graph.cpp
index 751b2ab36..202cd4587 100644
--- a/src/V3Graph.cpp
+++ b/src/V3Graph.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Graph.h b/src/V3Graph.h
index 8589a003c..132221767 100644
--- a/src/V3Graph.h
+++ b/src/V3Graph.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3GraphAcyc.cpp b/src/V3GraphAcyc.cpp
index 5a6b4bff2..c31485d26 100644
--- a/src/V3GraphAcyc.cpp
+++ b/src/V3GraphAcyc.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3GraphAlg.cpp b/src/V3GraphAlg.cpp
index c8af95e3f..67a2f12b0 100644
--- a/src/V3GraphAlg.cpp
+++ b/src/V3GraphAlg.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3GraphAlg.h b/src/V3GraphAlg.h
index 6441b2cca..e93f37949 100644
--- a/src/V3GraphAlg.h
+++ b/src/V3GraphAlg.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3GraphPathChecker.cpp b/src/V3GraphPathChecker.cpp
index 6f40a9aa7..f609652b0 100644
--- a/src/V3GraphPathChecker.cpp
+++ b/src/V3GraphPathChecker.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3GraphPathChecker.h b/src/V3GraphPathChecker.h
index b919c7869..620736ff1 100644
--- a/src/V3GraphPathChecker.h
+++ b/src/V3GraphPathChecker.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3GraphStream.h b/src/V3GraphStream.h
index 2c1a50545..a2cdbd888 100644
--- a/src/V3GraphStream.h
+++ b/src/V3GraphStream.h
@@ -7,7 +7,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3GraphTest.cpp b/src/V3GraphTest.cpp
index 540a5d85a..cb48888a6 100644
--- a/src/V3GraphTest.cpp
+++ b/src/V3GraphTest.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Hash.cpp b/src/V3Hash.cpp
index 916e703a5..5fd2d2751 100644
--- a/src/V3Hash.cpp
+++ b/src/V3Hash.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Hash.h b/src/V3Hash.h
index 8bf377cd6..7cdfb8749 100644
--- a/src/V3Hash.h
+++ b/src/V3Hash.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Hasher.cpp b/src/V3Hasher.cpp
index 2b72c0bc5..0dfdee7b3 100644
--- a/src/V3Hasher.cpp
+++ b/src/V3Hasher.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -300,7 +300,7 @@ private:
     }
 
     //------------------------------------------------------------
-    // AstNode direct descendents
+    // AstNode direct descendants
     void visit(AstNodeRange* nodep) override {
         m_hash += hashNodeAndIterate(nodep, HASH_DTYPE, HASH_CHILDREN, [=]() {});
     }
diff --git a/src/V3Hasher.h b/src/V3Hasher.h
index 823a1a074..6c24cfe0d 100644
--- a/src/V3Hasher.h
+++ b/src/V3Hasher.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2005-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2005-2023 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.
diff --git a/src/V3HierBlock.cpp b/src/V3HierBlock.cpp
index e1f258ccd..8c234cac2 100644
--- a/src/V3HierBlock.cpp
+++ b/src/V3HierBlock.cpp
@@ -1,12 +1,12 @@
 // -*- mode: C++; c-file-style: "cc-mode" -*-
 //*************************************************************************
-// DESCRIPTION: Verilator: Hierarchical verilation for large designs
+// DESCRIPTION: Verilator: Hierarchical Verilation for large designs
 //
 // Code available from: https://verilator.org
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -338,7 +338,7 @@ void V3HierBlockPlan::createPlan(AstNetlist* nodep) {
     if (modp->hierBlock()) {
         modp->v3warn(HIERBLOCK,
                      "Top module illegally marked hierarchical block, ignoring marking\n"
-                         + V3Error::warnMore()
+                         + modp->warnMore()
                          + "... Suggest remove verilator hier_block on this module");
         modp->hierBlock(false);
     }
diff --git a/src/V3HierBlock.h b/src/V3HierBlock.h
index 28df43ff7..02842a62d 100644
--- a/src/V3HierBlock.h
+++ b/src/V3HierBlock.h
@@ -6,15 +6,11 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder.  This program is free software; you can
-// redistribute it and/or modify it under the terms of either the GNU
+// Copyright 2003-2023 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.
+// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
 //
 //*************************************************************************
 
diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp
index cfb3f0f41..b2774b60e 100644
--- a/src/V3Inline.cpp
+++ b/src/V3Inline.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Inline.h b/src/V3Inline.h
index 0fe1126d5..dc5264ad1 100644
--- a/src/V3Inline.h
+++ b/src/V3Inline.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Inst.cpp b/src/V3Inst.cpp
index 3fedd9803..533fccd0e 100644
--- a/src/V3Inst.cpp
+++ b/src/V3Inst.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Inst.h b/src/V3Inst.h
index 0e55b8ce1..6cfce8f77 100644
--- a/src/V3Inst.h
+++ b/src/V3Inst.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3InstrCount.cpp b/src/V3InstrCount.cpp
index b72e352e6..96d19aa90 100644
--- a/src/V3InstrCount.cpp
+++ b/src/V3InstrCount.cpp
@@ -7,7 +7,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3InstrCount.h b/src/V3InstrCount.h
index bee916109..279885616 100644
--- a/src/V3InstrCount.h
+++ b/src/V3InstrCount.h
@@ -7,7 +7,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3LangCode.h b/src/V3LangCode.h
index 949767489..3835825d9 100644
--- a/src/V3LangCode.h
+++ b/src/V3LangCode.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3LanguageWords.h b/src/V3LanguageWords.h
index 41aaf998d..2717b90d6 100644
--- a/src/V3LanguageWords.h
+++ b/src/V3LanguageWords.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2005-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2005-2023 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.
diff --git a/src/V3Life.cpp b/src/V3Life.cpp
index 4bbfb904b..7ba66e97b 100644
--- a/src/V3Life.cpp
+++ b/src/V3Life.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Life.h b/src/V3Life.h
index 7186c3a99..fa4291519 100644
--- a/src/V3Life.h
+++ b/src/V3Life.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3LifePost.cpp b/src/V3LifePost.cpp
index 780026a4f..b3bd4234c 100644
--- a/src/V3LifePost.cpp
+++ b/src/V3LifePost.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3LifePost.h b/src/V3LifePost.h
index 174b0b57b..ddf92c555 100644
--- a/src/V3LifePost.h
+++ b/src/V3LifePost.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3LinkCells.cpp b/src/V3LinkCells.cpp
index e9cc52c1d..f6db23721 100644
--- a/src/V3LinkCells.cpp
+++ b/src/V3LinkCells.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -82,7 +82,7 @@ void LinkCellsGraph::loopsMessageCb(V3GraphVertex* vertexp) {
                                  "Unsupported: Recursive multiple modules (module instantiates "
                                  "something leading back to itself): "
                                      << vvertexp->modp()->prettyNameQ() << '\n'
-                                     << V3Error::warnMore()
+                                     << vvertexp->modp()->warnMore()
                                      << "... note: self-recursion (module instantiating itself "
                                         "directly) is supported.");
         V3Error::abortIfErrors();
diff --git a/src/V3LinkCells.h b/src/V3LinkCells.h
index 8e40b7fbc..eab1a73fe 100644
--- a/src/V3LinkCells.h
+++ b/src/V3LinkCells.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp
index bf6a6c5ad..c87fd5198 100644
--- a/src/V3LinkDot.cpp
+++ b/src/V3LinkDot.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -740,6 +740,7 @@ class LinkDotFindVisitor final : public VNVisitor {
     // STATE
     LinkDotState* const m_statep;  // State to pass between visitors, including symbol table
     AstNodeModule* m_classOrPackagep = nullptr;  // Current package
+    AstClocking* m_clockingp = nullptr;  // Current clocking block
     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
@@ -913,7 +914,7 @@ class LinkDotFindVisitor final : public VNVisitor {
     void visit(AstClass* nodep) override {
         UASSERT_OBJ(m_curSymp, nodep, "Class not under module/package/$unit");
         UINFO(8, "   " << nodep << endl);
-        // Remove classes that have void params, as they were only used for the parametrization
+        // Remove classes that have void params, as they were only used for the parameterization
         // step and will not be instantiated
         if (m_statep->removeVoidParamedClasses()) {
             for (auto* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
@@ -1028,8 +1029,13 @@ class LinkDotFindVisitor final : public VNVisitor {
             // are common.
             for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
                 if (VN_IS(stmtp, Var) || VN_IS(stmtp, Foreach)) {
-                    ++m_modBlockNum;
-                    nodep->name("unnamedblk" + cvtToStr(m_modBlockNum));
+                    std::string name;
+                    do {
+                        ++m_modBlockNum;
+                        name = "unnamedblk" + cvtToStr(m_modBlockNum);
+                        // Increment again if earlier pass of V3LinkDot claimed this name
+                    } while (m_curSymp->findIdFlat(name));
+                    nodep->name(name);
                     break;
                 }
             }
@@ -1123,6 +1129,49 @@ class LinkDotFindVisitor final : public VNVisitor {
             m_ftaskp = nullptr;
         }
     }
+    void visit(AstClocking* nodep) override {
+        VL_RESTORER(m_clockingp);
+        m_clockingp = nodep;
+        iterate(nodep->sensesp());
+        iterateAndNextNull(nodep->itemsp());
+        // If the block has no name, one cannot reference the clockvars
+        if (nodep->name().empty()) return;
+        VL_RESTORER(m_curSymp);
+        m_curSymp = m_statep->insertBlock(m_curSymp, nodep->name(), nodep, m_classOrPackagep);
+        m_curSymp->fallbackp(nullptr);
+        iterateAndNextNull(nodep->itemsp());
+    }
+    void visit(AstClockingItem* nodep) override {
+        if (nodep->varp()) {
+            if (m_curSymp->nodep() == m_clockingp) iterate(nodep->varp());
+            return;
+        }
+        std::string varname;
+        AstNodeDType* dtypep;
+        if (AstAssign* const assignp = nodep->assignp()) {
+            AstNodeExpr* const rhsp = assignp->rhsp()->unlinkFrBack();
+            dtypep = new AstRefDType{nodep->fileline(), AstRefDType::FlagTypeOfExpr{},
+                                     rhsp->cloneTree(false)};
+            nodep->exprp(rhsp);
+            varname = assignp->lhsp()->name();
+            VL_DO_DANGLING(assignp->unlinkFrBack()->deleteTree(), assignp);
+        } else {
+            AstNodeExpr* const refp = nodep->exprp();
+            const VSymEnt* foundp = m_curSymp->findIdFallback(refp->name());
+            if (!foundp || !foundp->nodep()) {
+                refp->v3error("Corresponding variable " << refp->prettyNameQ()
+                                                        << " does not exist");
+                VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
+                return;
+            }
+            varname = refp->name();
+            dtypep = VN_AS(foundp->nodep(), Var)->childDTypep()->cloneTree(false);
+        }
+        AstVar* const newvarp = new AstVar{nodep->fileline(), VVarType::MODULETEMP, varname,
+                                           VFlagChildDType{}, dtypep};
+        nodep->varp(newvarp);
+        iterate(nodep->exprp());
+    }
     void visit(AstVar* nodep) override {
         // Var: Remember its name for later resolution
         UASSERT_OBJ(m_curSymp && m_modSymp, nodep, "Var not under module?");
@@ -1150,6 +1199,10 @@ class LinkDotFindVisitor final : public VNVisitor {
                                              << cvtToHex(foundp->parentp()) << endl);
                 if (foundp->parentp() == m_curSymp  // Only when on same level
                     && !foundp->imported()) {  // and not from package
+                    if (VN_IS(m_curSymp->nodep(), Clocking)) {
+                        nodep->v3error("Multiple clockvars with the same name not allowed");
+                        return;
+                    }
                     const bool nansiBad
                         = ((findvarp->isDeclTyped() && nodep->isDeclTyped())
                            || (findvarp->isIO() && nodep->isIO()));  // e.g. !(output && output)
@@ -1946,6 +1999,7 @@ private:
     AstNodeModule* m_modp = nullptr;  // Current module
     AstNodeFTask* m_ftaskp = nullptr;  // Current function/task
     int m_modportNum = 0;  // Uniqueify modport numbers
+    bool m_inSens = false;  // True if in senitem
 
     struct DotStates {
         DotPosition m_dotPos;  // Scope part of dotted resolution
@@ -2062,9 +2116,27 @@ private:
             refp->user5p(nodep);
         }
     }
+    VSymEnt* getCreateClockingEventSymEnt(AstClocking* clockingp) {
+        if (!clockingp->eventp()) {
+            AstVar* const eventp = new AstVar{
+                clockingp->fileline(), VVarType::MODULETEMP, clockingp->name(), VFlagChildDType{},
+                new AstBasicDType{clockingp->fileline(), VBasicDTypeKwd::EVENT}};
+            clockingp->eventp(eventp);
+            // Trigger the clocking event in Observed (IEEE 1800-2017 14.13)
+            clockingp->addNextHere(new AstAlwaysObserved{
+                clockingp->fileline(),
+                new AstSenTree{clockingp->fileline(), clockingp->sensesp()->cloneTree(false)},
+                new AstFireEvent{clockingp->fileline(),
+                                 new AstVarRef{clockingp->fileline(), eventp, VAccess::WRITE},
+                                 false}});
+            v3Global.setHasEvents();
+            eventp->user1p(new VSymEnt{m_statep->symsp(), eventp});
+        }
+        return reinterpret_cast(clockingp->eventp()->user1p());
+    }
 
     bool isParamedClassRef(const AstNode* nodep) {
-        // Is this a parametrized reference to a class, or a reference to class parameter
+        // Is this a parameterized reference to a class, or a reference to class parameter
         if (const auto* classRefp = VN_CAST(nodep, ClassOrPackageRef)) {
             if (classRefp->paramsp()) return true;
             const auto* classp = classRefp->classOrPackageNodep();
@@ -2267,7 +2339,7 @@ private:
                 // if (debug() >= 9) nodep->dumpTree("-  dot-lho: ");
             }
             if (m_statep->forPrimary() && isParamedClassRef(nodep->lhsp())) {
-                // Dots of paramed classes will be linked after deparametrization
+                // Dots of paramed classes will be linked after deparameterization
                 m_ds.m_dotPos = DP_NONE;
                 return;
             }
@@ -2311,6 +2383,11 @@ private:
             m_ds.m_dotp = lastStates.m_dotp;
         }
     }
+    void visit(AstSenItem* nodep) override {
+        VL_RESTORER(m_inSens);
+        m_inSens = true;
+        iterateChildren(nodep);
+    }
     void visit(AstParseRef* nodep) override {
         if (nodep->user3SetOnce()) return;
         UINFO(9, "   linkPARSEREF " << m_ds.ascii() << "  n=" << nodep << endl);
@@ -2333,7 +2410,7 @@ private:
         }
         if (nodep->name() == "this") {
             iterateChildren(nodep);
-            if (m_statep->forPrimary()) return;  // The class might be parametrized somewhere
+            if (m_statep->forPrimary()) return;  // The class might be parameterized somewhere
             const VSymEnt* classSymp = getThisClassSymp();
             if (!classSymp) {
                 nodep->v3error("'this' used outside class (IEEE 1800-2017 8.11)");
@@ -2417,6 +2494,12 @@ private:
             }
             // What fell out?
             bool ok = false;
+            // Special case: waiting on clocking event
+            if (m_inSens && foundp && m_ds.m_dotPos != DP_SCOPE) {
+                if (AstClocking* const clockingp = VN_CAST(foundp->nodep(), Clocking)) {
+                    foundp = getCreateClockingEventSymEnt(clockingp);
+                }
+            }
             if (!foundp) {
             } else if (VN_IS(foundp->nodep(), Cell) || VN_IS(foundp->nodep(), Begin)
                        || VN_IS(foundp->nodep(), Netlist)  // for $root
@@ -2582,6 +2665,15 @@ private:
                     m_ds.m_dotPos = DP_MEMBER;
                     m_ds.m_dotText = "";
                 }
+            } else if (VN_IS(foundp->nodep(), Clocking)) {
+                m_ds.m_dotSymp = foundp;
+                ok = m_ds.m_dotPos == DP_SCOPE;
+            } else if (VN_IS(foundp->nodep(), Property)) {
+                AstFuncRef* const propRefp
+                    = new AstFuncRef{nodep->fileline(), nodep->name(), nullptr};
+                nodep->replaceWith(propRefp);
+                VL_DO_DANGLING(pushDeletep(nodep), nodep);
+                ok = m_ds.m_dotPos == DP_NONE;
             }
             //
             if (!ok) {
@@ -3076,8 +3168,9 @@ private:
                     if (cextp->childDTypep() || cextp->dtypep()) continue;  // Already converted
                     AstClassOrPackageRef* const cpackagerefp
                         = VN_CAST(cextp->classOrPkgsp(), ClassOrPackageRef);
-                    if (!cpackagerefp) {
-                        cextp->v3error("Attempting to extend using a non-class ");
+                    if (VL_UNCOVERABLE(!cpackagerefp)) {
+                        // Linking the extend gives an error before this is hit
+                        cextp->v3error("Attempting to extend using non-class");  // LCOV_EXCL_LINE
                     } else {
                         VSymEnt* const foundp = m_curSymp->findIdFallback(cpackagerefp->name());
                         bool ok = false;
diff --git a/src/V3LinkDot.h b/src/V3LinkDot.h
index 428f18904..14af04e82 100644
--- a/src/V3LinkDot.h
+++ b/src/V3LinkDot.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3LinkInc.cpp b/src/V3LinkInc.cpp
index c08b58f6a..fdd8dd70d 100644
--- a/src/V3LinkInc.cpp
+++ b/src/V3LinkInc.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -15,7 +15,7 @@
 //*************************************************************************
 // V3LinkInc's Transformations:
 //
-//      prepost_stmt_visit
+//      prepost_expr_visit
 //        PREADD/PRESUB
 //          Create a temporary __VIncrementX variable, assign the value of
 //          the current variable value to it, substitute the current
@@ -27,7 +27,7 @@
 //          Create a temporary __VIncrementX variable, assign the value of
 //          of the current variable (after the operation) to it. Substitute
 //          The original variable with the temporary one in the statement.
-//      prepost_non_stmt_visit
+//      prepost_stmt_visit
 //        PREADD/PRESUB/POSTADD/POSTSUB
 //          Increment/decrement the current variable by the given value.
 //          The order (pre/post) doesn't matter outside statements thus
@@ -193,36 +193,33 @@ private:
     void prepost_visit(AstNodeTriop* nodep) {
         // Check if we are underneath a statement
         if (!m_insStmtp) {
-            prepost_non_stmt_visit(nodep);
-        } else {
             prepost_stmt_visit(nodep);
+        } else {
+            prepost_expr_visit(nodep);
         }
     }
-    void prepost_non_stmt_visit(AstNodeTriop* nodep) {
+    void prepost_stmt_visit(AstNodeTriop* nodep) {
         iterateChildren(nodep);
 
         AstConst* const constp = VN_AS(nodep->lhsp(), Const);
         UASSERT_OBJ(nodep, constp, "Expecting CONST");
         AstConst* const newconstp = constp->cloneTree(true);
 
-        AstNodeExpr* const storetop = nodep->thsp();
-        AstNodeExpr* const valuep = nodep->rhsp();
-
-        storetop->unlinkFrBack();
-        valuep->unlinkFrBack();
+        AstNodeExpr* const storeTop = nodep->thsp()->unlinkFrBack();
+        AstNodeExpr* const valuep = nodep->rhsp()->unlinkFrBack();
 
         AstAssign* assignp;
         if (VN_IS(nodep, PreSub) || VN_IS(nodep, PostSub)) {
-            assignp = new AstAssign{nodep->fileline(), storetop,
+            assignp = new AstAssign{nodep->fileline(), storeTop,
                                     new AstSub{nodep->fileline(), valuep, newconstp}};
         } else {
-            assignp = new AstAssign{nodep->fileline(), storetop,
+            assignp = new AstAssign{nodep->fileline(), storeTop,
                                     new AstAdd{nodep->fileline(), valuep, newconstp}};
         }
         nodep->replaceWith(assignp);
         VL_DO_DANGLING(nodep->deleteTree(), nodep);
     }
-    void prepost_stmt_visit(AstNodeTriop* nodep) {
+    void prepost_expr_visit(AstNodeTriop* nodep) {
         iterateChildren(nodep);
 
         const AstNodeVarRef* varrefp = nullptr;
diff --git a/src/V3LinkInc.h b/src/V3LinkInc.h
index 835bddd51..1b5a6ff55 100644
--- a/src/V3LinkInc.h
+++ b/src/V3LinkInc.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3LinkJump.cpp b/src/V3LinkJump.cpp
index d028cb11f..14c1eddac 100644
--- a/src/V3LinkJump.cpp
+++ b/src/V3LinkJump.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3LinkJump.h b/src/V3LinkJump.h
index e2cc25ac7..598cd98bc 100644
--- a/src/V3LinkJump.h
+++ b/src/V3LinkJump.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3LinkLValue.cpp b/src/V3LinkLValue.cpp
index 692339ed3..5672089fc 100644
--- a/src/V3LinkLValue.cpp
+++ b/src/V3LinkLValue.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -193,6 +193,7 @@ private:
         {
             m_setRefLvalue = VAccess::WRITE;
             iterateAndNextNull(nodep->filep());
+            iterateAndNextNull(nodep->rhsp());
         }
     }
     void visit(AstSScanF* nodep) override {
@@ -203,8 +204,7 @@ private:
         }
     }
     void visit(AstSysIgnore* nodep) override {
-        // Can't know if lvalue or not; presume so as stricter
-        VL_RESTORER(m_setRefLvalue);
+        // Can't know if lvalue or not; presume not
         iterateChildren(nodep);
     }
     void visit(AstRand* nodep) override {
diff --git a/src/V3LinkLValue.h b/src/V3LinkLValue.h
index d9e4d78d9..16656936d 100644
--- a/src/V3LinkLValue.h
+++ b/src/V3LinkLValue.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3LinkLevel.cpp b/src/V3LinkLevel.cpp
index c3780e434..cfa121649 100644
--- a/src/V3LinkLevel.cpp
+++ b/src/V3LinkLevel.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -132,7 +132,7 @@ void V3LinkLevel::timescaling(const ModVec& mods) {
                                              VTimescale{VTimescale::TS_DEFAULT});
     }
 
-    // Classes under package have timescale propaged in V3LinkParse
+    // Classes under package have timescale propagated in V3LinkParse
 }
 
 //######################################################################
diff --git a/src/V3LinkLevel.h b/src/V3LinkLevel.h
index 6a9ecdd11..c1b1c6354 100644
--- a/src/V3LinkLevel.h
+++ b/src/V3LinkLevel.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3LinkParse.cpp b/src/V3LinkParse.cpp
index ea67c2aea..8aa45b271 100644
--- a/src/V3LinkParse.cpp
+++ b/src/V3LinkParse.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -60,6 +60,8 @@ private:
     AstNodeModule* m_modp = nullptr;  // Current module
     AstNodeFTask* m_ftaskp = nullptr;  // Current task
     AstNodeDType* m_dtypep = nullptr;  // Current data type
+    AstNodeExpr* m_defaultInSkewp = nullptr;  // Current default input skew
+    AstNodeExpr* m_defaultOutSkewp = nullptr;  // Current default output skew
     int m_genblkAbove = 0;  // Begin block number of if/case/for above
     int m_genblkNum = 0;  // Begin block number, 0=none seen
     VLifetime m_lifetime = VLifetime::STATIC;  // Propagating lifetime
@@ -121,6 +123,13 @@ private:
                 && (VN_IS(nodep->stmtsp(), GenIf))  // Begin has if underneath
                 && !nodep->stmtsp()->nextp());  // Has only one item
     }
+    bool hasStaticDeclAssignments(AstNodeFTask* nodep) {
+        for (const AstNode* itemp = nodep->stmtsp(); itemp; itemp = itemp->nextp()) {
+            const AstVar* const varp = VN_CAST(itemp, Var);
+            if (varp && varp->valuep() && !varp->lifetime().isAutomatic()) return true;
+        }
+        return false;
+    }
 
     // VISITs
     void visit(AstNodeFTask* nodep) override {
@@ -131,10 +140,26 @@ private:
             VL_RESTORER(m_lifetime);
             {
                 m_ftaskp = nodep;
-                m_lifetime = nodep->lifetime();
-                if (m_lifetime.isNone()) {
-                    // Automatic always until we support static
-                    m_lifetime = VLifetime::AUTOMATIC;
+                if (!nodep->lifetime().isNone()) {
+                    m_lifetime = nodep->lifetime();
+                } else {
+                    const AstClassOrPackageRef* const classPkgRefp
+                        = VN_AS(nodep->classOrPackagep(), ClassOrPackageRef);
+                    if (classPkgRefp && VN_IS(classPkgRefp->classOrPackageNodep(), Class)) {
+                        // Class methods are automatic by default
+                        m_lifetime = VLifetime::AUTOMATIC;
+                    } else if (nodep->dpiImport()) {
+                        // DPI-imported function don't have lifetime specifiers
+                        m_lifetime = VLifetime::NONE;
+                    }
+                    if (m_lifetime.isStatic() && hasStaticDeclAssignments(nodep)) {
+                        nodep->v3warn(
+                            IMPLICITSTATIC,
+                            "Function/task's lifetime implicitly set to static\n"
+                                << nodep->warnMore()
+                                << "... Suggest use 'function automatic' or 'function static'");
+                    }
+                    nodep->lifetime(m_lifetime);
                 }
                 iterateChildren(nodep);
             }
@@ -632,6 +657,66 @@ private:
             nodep->classOrPackagep(m_stdPackagep);
         }
     }
+    void visit(AstClocking* nodep) override {
+        VL_RESTORER(m_defaultInSkewp);
+        VL_RESTORER(m_defaultOutSkewp);
+        // Find default input and output skews
+        AstClockingItem* nextItemp = nodep->itemsp();
+        for (AstClockingItem* itemp = nextItemp; itemp; itemp = nextItemp) {
+            nextItemp = VN_AS(itemp->nextp(), ClockingItem);
+            if (itemp->exprp() || itemp->assignp()) continue;
+            if (itemp->skewp()) {
+                if (itemp->direction() == VDirection::INPUT) {
+                    // Disallow default redefinition; note some simulators allow this
+                    if (m_defaultInSkewp) {
+                        itemp->skewp()->v3error("Multiple default input skews not allowed");
+                    }
+                    m_defaultInSkewp = itemp->skewp();
+                } else if (itemp->direction() == VDirection::OUTPUT) {
+                    if (AstConst* const constp = VN_CAST(itemp->skewp(), Const)) {
+                        if (constp->num().is1Step()) {
+                            itemp->skewp()->v3error("1step not allowed as output skew");
+                        }
+                    }
+                    // Disallow default redefinition; note some simulators allow this
+                    if (m_defaultOutSkewp) {
+                        itemp->skewp()->v3error("Multiple default output skews not allowed");
+                    }
+                    m_defaultOutSkewp = itemp->skewp();
+                } else {
+                    itemp->v3fatalSrc("Incorrect direction");
+                }
+            }
+            pushDeletep(itemp->unlinkFrBack());
+        }
+        iterateChildren(nodep);
+    }
+    void visit(AstClockingItem* nodep) override {
+        if (nodep->direction() == VDirection::OUTPUT) {
+            if (!nodep->skewp()) {
+                if (m_defaultOutSkewp) {
+                    nodep->skewp(m_defaultOutSkewp->cloneTree(false));
+                } else {
+                    // Default is 0 (IEEE 1800-2017 14.3)
+                    nodep->skewp(new AstConst{nodep->fileline(), 0});
+                }
+            } else if (AstConst* const constp = VN_CAST(nodep->skewp(), Const)) {
+                if (constp->num().is1Step()) {
+                    nodep->skewp()->v3error("1step not allowed as output skew");
+                }
+            }
+        } else if (nodep->direction() == VDirection::INPUT) {
+            if (!nodep->skewp()) {
+                if (m_defaultInSkewp) {
+                    nodep->skewp(m_defaultInSkewp->cloneTree(false));
+                } else {
+                    // Default is 1step (IEEE 1800-2017 14.3)
+                    nodep->skewp(new AstConst{nodep->fileline(), AstConst::OneStep{}});
+                }
+            }
+        }
+        iterateChildren(nodep);
+    }
 
     void visit(AstNode* nodep) override {
         // Default: Just iterate
diff --git a/src/V3LinkParse.h b/src/V3LinkParse.h
index f428fb935..df57d97d2 100644
--- a/src/V3LinkParse.h
+++ b/src/V3LinkParse.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp
index 06d1bc27e..6eb2a3897 100644
--- a/src/V3LinkResolve.cpp
+++ b/src/V3LinkResolve.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -59,7 +59,7 @@ private:
 
     // VISITs
     // TODO: Most of these visitors are here for historical reasons.
-    // TODO: ExpectDecriptor can move to data type resolution, and the rest
+    // TODO: ExpectDescriptor can move to data type resolution, and the rest
     // TODO: could move to V3LinkParse to get them out of the way of elaboration
     void visit(AstNodeModule* nodep) override {
         // Module: Create sim table for entire module and iterate
diff --git a/src/V3LinkResolve.h b/src/V3LinkResolve.h
index 606886385..929c36452 100644
--- a/src/V3LinkResolve.h
+++ b/src/V3LinkResolve.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3List.h b/src/V3List.h
index c32794cc2..6b4472008 100644
--- a/src/V3List.h
+++ b/src/V3List.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Localize.cpp b/src/V3Localize.cpp
index 4a30bcc7b..1cf60339d 100644
--- a/src/V3Localize.cpp
+++ b/src/V3Localize.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -108,6 +108,7 @@ private:
                 AstVar* const newVarp
                     = new AstVar{oldVarp->fileline(), oldVarp->varType(), newName, oldVarp};
                 newVarp->funcLocal(true);
+                newVarp->noReset(oldVarp->noReset());
                 funcp->addInitsp(newVarp);
 
                 // Fix up all the references within this function
diff --git a/src/V3Localize.h b/src/V3Localize.h
index 1dce59c59..65d369214 100644
--- a/src/V3Localize.h
+++ b/src/V3Localize.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3MergeCond.cpp b/src/V3MergeCond.cpp
index 51f4e1679..c7fe8ec75 100644
--- a/src/V3MergeCond.cpp
+++ b/src/V3MergeCond.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -138,7 +138,7 @@ bool areDisjoint(const std::set& a, const std::set
 struct StmtProperties {
     AstNodeExpr* m_condp = nullptr;  // The condition expression, if a conditional node
     std::set m_rdVars;  // Variables read by this statement
-    std::set m_wrVars;  // Variables writen by this statement
+    std::set m_wrVars;  // Variables written by this statement
     bool m_isFence = false;  // Nothing should move across this statement, nor should it be merged
     AstNodeStmt* m_prevWithSameCondp = nullptr;  // Previous node in same list, with same condition
     bool writesConditionVar() const {
diff --git a/src/V3MergeCond.h b/src/V3MergeCond.h
index 7772705dc..07d41e538 100644
--- a/src/V3MergeCond.h
+++ b/src/V3MergeCond.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Name.cpp b/src/V3Name.cpp
index 8cb27838d..68a282140 100644
--- a/src/V3Name.cpp
+++ b/src/V3Name.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Name.h b/src/V3Name.h
index 5f7a4b01a..f51fdac0b 100644
--- a/src/V3Name.h
+++ b/src/V3Name.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Number.cpp b/src/V3Number.cpp
index 49081321a..30d58e482 100644
--- a/src/V3Number.cpp
+++ b/src/V3Number.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -494,6 +494,10 @@ V3Number& V3Number::setMask(int nbits) {
 string V3Number::ascii(bool prefixed, bool cleanVerilog) const {
     std::ostringstream out;
 
+    if (is1Step()) {
+        out << "1step";
+        return out.str();
+    }
     if (isDouble()) {
         out.precision(17);
         if (VL_UNCOVERABLE(width() != 64)) {
diff --git a/src/V3Number.h b/src/V3Number.h
index ea4fd2cae..b58806705 100644
--- a/src/V3Number.h
+++ b/src/V3Number.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -97,6 +97,7 @@ private:
 public:
     bool m_sized : 1;  // True if the user specified the width, else we track it.
     bool m_signed : 1;  // True if signed value
+    bool m_is1Step : 1;  // True if 1step
     bool m_isNull : 1;  // True if "null" versus normal 0
     bool m_fromString : 1;  // True if from string literal
     bool m_autoExtend : 1;  // True if SystemVerilog extend-to-any-width
@@ -107,6 +108,7 @@ public:
         : m_type{V3NumberDataType::UNINITIALIZED}
         , m_sized{false}
         , m_signed{false}
+        , m_is1Step{false}
         , m_isNull{false}
         , m_fromString{false}
         , m_autoExtend{false} {}
@@ -118,6 +120,7 @@ public:
         , m_type{other.m_type}
         , m_sized{other.m_sized}
         , m_signed{other.m_signed}
+        , m_is1Step{other.m_is1Step}
         , m_isNull{other.m_isNull}
         , m_fromString{other.m_fromString}
         , m_autoExtend{other.m_autoExtend} {
@@ -145,6 +148,7 @@ public:
         m_type = other.m_type;
         m_sized = other.m_sized;
         m_signed = other.m_signed;
+        m_is1Step = other.m_is1Step;
         m_isNull = other.m_isNull;
         m_fromString = other.m_fromString;
         m_autoExtend = other.m_autoExtend;
@@ -156,6 +160,7 @@ public:
         , m_type{other.m_type}
         , m_sized{other.m_sized}
         , m_signed{other.m_signed}
+        , m_is1Step{other.m_is1Step}
         , m_isNull{other.m_isNull}
         , m_fromString{other.m_fromString}
         , m_autoExtend{other.m_autoExtend} {
@@ -184,6 +189,7 @@ public:
         m_type = other.m_type;
         m_sized = other.m_sized;
         m_signed = other.m_signed;
+        m_is1Step = other.m_is1Step;
         m_isNull = other.m_isNull;
         m_fromString = other.m_fromString;
         m_autoExtend = other.m_autoExtend;
@@ -489,6 +495,11 @@ public:
         setString(value);
         m_data.m_fromString = true;
     }
+    class OneStep {};
+    V3Number(OneStep, AstNode* nodep) {
+        init(nodep, 64);
+        m_data.m_is1Step = true;
+    }
     class Null {};
     V3Number(Null, AstNode* nodep) {
         init(nodep);
@@ -601,6 +612,7 @@ public:
                || m_data.type() == V3NumberDataType::DOUBLE;
     }
     bool isNegative() const VL_MT_SAFE { return !isString() && bitIs1(width() - 1); }
+    bool is1Step() const VL_MT_SAFE { return m_data.m_is1Step; }
     bool isNull() const VL_MT_SAFE { return m_data.m_isNull; }
     bool isFourState() const VL_MT_SAFE;
     bool hasZ() const {
diff --git a/src/V3Number_test.cpp b/src/V3Number_test.cpp
index a0352e35a..fd0887d8b 100644
--- a/src/V3Number_test.cpp
+++ b/src/V3Number_test.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3OptionParser.cpp b/src/V3OptionParser.cpp
index 7c26d1a86..8d9f41b2c 100644
--- a/src/V3OptionParser.cpp
+++ b/src/V3OptionParser.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3OptionParser.h b/src/V3OptionParser.h
index d087e71e5..264d209ee 100644
--- a/src/V3OptionParser.h
+++ b/src/V3OptionParser.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Options.cpp b/src/V3Options.cpp
index 3d920dfca..2785a939b 100644
--- a/src/V3Options.cpp
+++ b/src/V3Options.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -803,18 +803,17 @@ void V3Options::notify() {
             // We always call protect() on names, we don't check if public or not
             // Hence any external references wouldn't be able to find the refed public object.
             cmdfl->v3warn(E_UNSUPPORTED, "Unsupported: Using --protect-ids with --public\n"  //
-                                             + V3Error::warnMore()
-                                             + "... Suggest remove --public.");
+                                             + cmdfl->warnMore() + "... Suggest remove --public.");
         }
         if (trace()) {
             cmdfl->v3warn(INSECURE,
                           "Using --protect-ids with --trace may expose private design details\n"
-                              + V3Error::warnMore() + "... Suggest remove --trace.");
+                              + cmdfl->warnMore() + "... Suggest remove --trace.");
         }
         if (vpi()) {
             cmdfl->v3warn(INSECURE,
                           "Using --protect-ids with --vpi may expose private design details\n"
-                              + V3Error::warnMore() + "... Suggest remove --vpi.");
+                              + cmdfl->warnMore() + "... Suggest remove --vpi.");
         }
     }
 
@@ -1406,7 +1405,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
         m_statsVars = flag;
         m_stats |= flag;
     });
-    DECL_OPTION("-structs-unpacked", OnOff, &m_structsPacked);
+    DECL_OPTION("-structs-packed", OnOff, &m_structsPacked);
     DECL_OPTION("-sv", CbCall, [this]() { m_defaultLanguage = V3LangCode::L1800_2017; });
 
     DECL_OPTION("-threads-coarsen", OnOff, &m_threadsCoarsen).undocumented();  // Debug
@@ -1822,7 +1821,7 @@ void V3Options::showVersion(bool verbose) {
     if (!verbose) return;
 
     cout << endl;
-    cout << "Copyright 2003-2022 by Wilson Snyder.  Verilator is free software; you can\n";
+    cout << "Copyright 2003-2023 by Wilson Snyder.  Verilator is free software; you can\n";
     cout << "redistribute it and/or modify the Verilator internals under the terms of\n";
     cout << "either the GNU Lesser General Public License Version 3 or the Perl Artistic\n";
     cout << "License Version 2.0.\n";
diff --git a/src/V3Options.h b/src/V3Options.h
index 4d3a14280..27e4f5036 100644
--- a/src/V3Options.h
+++ b/src/V3Options.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -249,7 +249,7 @@ private:
     bool m_ignc = false;            // main switch: --ignc
     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_main = false;            // main switch: --main
     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
@@ -267,7 +267,7 @@ private:
     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_structsPacked = false;   // 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
@@ -281,7 +281,7 @@ private:
     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_verilate = true;         // main switch: --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
@@ -638,7 +638,7 @@ public:
     bool hierTop() const VL_MT_SAFE { 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.
+    // Returns makeDir() unless top module of hierarchical Verilation.
     string hierTopDataDir() const VL_MT_SAFE {
         return hierTop() ? (makeDir() + '/' + prefix() + "__hier.dir") : makeDir();
     }
diff --git a/src/V3Order.cpp b/src/V3Order.cpp
index 037b16230..a81a8afe0 100644
--- a/src/V3Order.cpp
+++ b/src/V3Order.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -217,7 +217,7 @@ class OrderBuildVisitor final : public VNVisitor {
 
         m_inClocked = senTreep->hasClocked();
 
-        // Note: We don't need to analyse the sensitivity list, as currently all sensitivity
+        // Note: We don't need to analyze the sensitivity list, as currently all sensitivity
         // lists simply reference an entry in a trigger vector, which are all set external to
         // the code being ordered.
 
@@ -385,6 +385,12 @@ class OrderBuildVisitor final : public VNVisitor {
         iterateLogic(nodep);
         m_inPost = false;
     }
+    void visit(AstAlwaysObserved* nodep) override {  //
+        iterateLogic(nodep);
+    }
+    void visit(AstAlwaysReactive* nodep) override {  //
+        iterateLogic(nodep);
+    }
     void visit(AstFinal* nodep) override {  // LCOV_EXCL_START
         nodep->v3fatalSrc("AstFinal should not need ordering");
     }  // LCOV_EXCL_STOP
diff --git a/src/V3Order.h b/src/V3Order.h
index 6beac4031..be2612371 100644
--- a/src/V3Order.h
+++ b/src/V3Order.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3OrderGraph.h b/src/V3OrderGraph.h
index a8093944d..5cc0ea85b 100644
--- a/src/V3OrderGraph.h
+++ b/src/V3OrderGraph.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3OrderMoveGraph.h b/src/V3OrderMoveGraph.h
index bfcdb239a..c0187a68f 100644
--- a/src/V3OrderMoveGraph.h
+++ b/src/V3OrderMoveGraph.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Os.cpp b/src/V3Os.cpp
index 5e9bbb194..01dcfe8d3 100644
--- a/src/V3Os.cpp
+++ b/src/V3Os.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Os.h b/src/V3Os.h
index 7daf580e6..6b73aa3b5 100644
--- a/src/V3Os.h
+++ b/src/V3Os.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3PairingHeap.h b/src/V3PairingHeap.h
index d7dc489d4..494b6da99 100644
--- a/src/V3PairingHeap.h
+++ b/src/V3PairingHeap.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -27,7 +27,7 @@
 //
 // While this is written as a generic data structure, it's interface and
 // implementation is finely tuned for it's use by V3Parm_tition, and is critical
-// to verilaton performance, so be very careful changing anything or adding any
+// to Verilation performance, so be very careful changing anything or adding any
 // new operations that would impact either memory usage, or performance of the
 // existing operations. This data structure is fully deterministic, meaning
 // the order in which elements with equal keys are retrieved only depends on
diff --git a/src/V3Param.cpp b/src/V3Param.cpp
index 421586b3e..f5abe2e29 100644
--- a/src/V3Param.cpp
+++ b/src/V3Param.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -79,7 +79,7 @@ class ParameterizedHierBlocks final {
 
     // MEMBERS
     // key:Original module name, value:HiearchyBlockOption*
-    // If a module is parameterized, the module is uniquiefied to overridden parameters.
+    // If a module is parameterized, the module is uniquified to overridden parameters.
     // This is why HierBlockOptsByOrigName is multimap.
     HierBlockOptsByOrigName m_hierBlockOptsByOrigName;
     // key:mangled module name, value:AstNodeModule*
@@ -330,6 +330,7 @@ class ParamProcessor final {
             key += " ";
             key += paramValueKey(dtypep->subDTypep());
         } else if (const AstBasicDType* const dtypep = VN_CAST(nodep, BasicDType)) {
+            if (dtypep->isSigned()) { key += " signed"; }
             if (dtypep->isRanged()) {
                 key += "[" + cvtToStr(dtypep->left()) + ":" + cvtToStr(dtypep->right()) + "]";
             }
@@ -442,7 +443,7 @@ class ParamProcessor final {
             }
         }
     }
-    // Check if parameter setting during instantiation is simple enough for hierarchical verilation
+    // 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.
@@ -453,7 +454,7 @@ class ParamProcessor final {
             }
             if (!supported) {
                 pinp->v3error(AstNode::prettyNameQ(modp->origName())
-                              << " has hier_block metacomment, hierarchical verilation"
+                              << " has hier_block metacomment, hierarchical Verilation"
                               << " supports only integer/floating point/string parameters");
             }
         } else {
@@ -542,12 +543,27 @@ class ParamProcessor final {
             hash.insert(V3Os::trueRandom(64));
         }
     }
+    void replaceRefsRecurse(AstNode* const nodep, const AstClass* const oldClassp,
+                            AstClass* const newClassp) {
+        if (AstClassRefDType* const classRefp = VN_CAST(nodep, ClassRefDType)) {
+            if (classRefp->classp() == oldClassp) classRefp->classp(newClassp);
+        }
+        if (nodep->op1p()) replaceRefsRecurse(nodep->op1p(), oldClassp, newClassp);
+        if (nodep->op2p()) replaceRefsRecurse(nodep->op2p(), oldClassp, newClassp);
+        if (nodep->op3p()) replaceRefsRecurse(nodep->op3p(), oldClassp, newClassp);
+        if (nodep->op4p()) replaceRefsRecurse(nodep->op4p(), oldClassp, newClassp);
+        if (nodep->nextp()) replaceRefsRecurse(nodep->nextp(), oldClassp, newClassp);
+    }
     void deepCloneModule(AstNodeModule* srcModp, AstNode* cellp, AstPin* paramsp,
                          const string& newname, const IfaceRefRefs& ifaceRefRefs) {
         // Deep clone of new module
         // Note all module internal variables will be re-linked to the new modules by clone
         // However links outside the module (like on the upper cells) will not.
         AstNodeModule* const newmodp = srcModp->cloneTree(false);
+        if (VN_IS(srcModp, Class)) {
+            replaceRefsRecurse(newmodp->stmtsp(), VN_AS(newmodp, Class), VN_AS(srcModp, Class));
+        }
+
         newmodp->name(newname);
         newmodp->user5(false);  // We need to re-recurse this module once changed
         newmodp->recursive(false);
@@ -561,9 +577,9 @@ class ParamProcessor final {
                            << v3Global.opt.moduleRecursionDepth());
             return;
         }
-        // Keep tree sorted by level. Note: Different parametrizations of the same recursive module
-        // end up with the same level, which we will need to fix up at the end, as we do not know
-        // up front how recursive modules are expanded, and a later expansion might re-use an
+        // Keep tree sorted by level. Note: Different parameterizations of the same recursive
+        // module end up with the same level, which we will need to fix up at the end, as we do not
+        // know up front how recursive modules are expanded, and a later expansion might re-use an
         // earlier expansion (see t_recursive_module_bug_2).
         AstNode* insertp = srcModp;
         while (VN_IS(insertp->nextp(), NodeModule)
@@ -861,7 +877,7 @@ public:
         } else if (auto* classRefp = VN_CAST(nodep, ClassOrPackageRef)) {
             classRefDeparam(classRefp, srcModpr);
         } else {
-            nodep->v3fatalSrc("Expected module parametrization");
+            nodep->v3fatalSrc("Expected module parameterization");
         }
 
         UINFO(8, "     Done with " << nodep << endl);
@@ -942,7 +958,7 @@ class ParamVisitor final : public VNVisitor {
                 } else if (const auto* classRefp = VN_CAST(cellp, ClassRefDType)) {
                     srcModp = classRefp->classp();
                 } else {
-                    cellp->v3fatalSrc("Expected module parametrization");
+                    cellp->v3fatalSrc("Expected module parameterization");
                 }
                 UASSERT_OBJ(srcModp, cellp, "Unlinked class ref");
 
diff --git a/src/V3Param.h b/src/V3Param.h
index 4154aa96f..bf4fbe16d 100644
--- a/src/V3Param.h
+++ b/src/V3Param.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Parse.h b/src/V3Parse.h
index b285030e8..ed034d36b 100644
--- a/src/V3Parse.h
+++ b/src/V3Parse.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3ParseGrammar.cpp b/src/V3ParseGrammar.cpp
index 278dd2a2b..d59129982 100644
--- a/src/V3ParseGrammar.cpp
+++ b/src/V3ParseGrammar.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -138,13 +138,16 @@ AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep, AstNodeRange* nra
                                                  rangep};
             } else if (VN_IS(nrangep, UnsizedRange)) {
                 arrayp = new AstUnsizedArrayDType{nrangep->fileline(), VFlagChildDType{}, arrayp};
+                VL_DO_DANGLING(nrangep->deleteTree(), nrangep);
             } else if (VN_IS(nrangep, BracketRange)) {
                 const AstBracketRange* const arangep = VN_AS(nrangep, BracketRange);
                 AstNode* const keyp = arangep->elementsp()->unlinkFrBack();
                 arrayp = new AstBracketArrayDType{nrangep->fileline(), VFlagChildDType{}, arrayp,
                                                   keyp};
+                VL_DO_DANGLING(nrangep->deleteTree(), nrangep);
             } else if (VN_IS(nrangep, WildcardRange)) {
                 arrayp = new AstWildcardArrayDType{nrangep->fileline(), VFlagChildDType{}, arrayp};
+                VL_DO_DANGLING(nrangep->deleteTree(), nrangep);
             } else {
                 UASSERT_OBJ(0, nrangep, "Expected range or unsized range");
             }
diff --git a/src/V3ParseImp.cpp b/src/V3ParseImp.cpp
index 640dfa9f5..a9fb2bb92 100644
--- a/src/V3ParseImp.cpp
+++ b/src/V3ParseImp.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h
index 7a5eeefbe..14db28acc 100644
--- a/src/V3ParseImp.h
+++ b/src/V3ParseImp.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2009-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2009-2023 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.
diff --git a/src/V3ParseLex.cpp b/src/V3ParseLex.cpp
index 5c4472de0..43ae1fb53 100644
--- a/src/V3ParseLex.cpp
+++ b/src/V3ParseLex.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3ParseSym.h b/src/V3ParseSym.h
index 4eae7b6a2..422e86c35 100644
--- a/src/V3ParseSym.h
+++ b/src/V3ParseSym.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2009-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2009-2023 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.
diff --git a/src/V3Partition.cpp b/src/V3Partition.cpp
index 87a631ea0..82b41ca32 100644
--- a/src/V3Partition.cpp
+++ b/src/V3Partition.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -1119,7 +1119,7 @@ public:
 // of a rescore, in case its score has fallen and we need to move it up
 // toward the front of the scoreboard.
 //
-// Wait, whaaat? Shouldn't the scores only increase as we merge nodes? Well
+// Wait, what? Shouldn't the scores only increase as we merge nodes? Well
 // that's almost true. But there is one exception.
 //
 // Suppose we have A->B, B->C, and A->C.
@@ -1652,12 +1652,12 @@ private:
         // Need at least 2 edges
         if (!mtaskp->beginp(way) || !mtaskp->beginp(way)->nextp(way)) return;
 
-        std::array neighbours;
+        std::array neighbors;
 
         // This is a hot method, so we want so sort as efficiently as possible. We pre-load
         // all data (critical path cost and id) required for determining ordering into an aligned
         // structure. There is not enough space next to these to keep a whole pointer within 16
-        // bytes, so we store an index into the neighbours buffer instead. We can then compare
+        // bytes, so we store an index into the neighbors buffer instead. We can then compare
         // and swap these sorting records very efficiently. With this the standard library sorting
         // functions are efficient enough and using more optimized methods (e.g.: sorting networks)
         // has no measurable benefit.
@@ -1666,7 +1666,7 @@ private:
             uint32_t m_cp;
             uint8_t m_idx;
             static_assert(PART_SIBLING_EDGE_LIMIT <= std::numeric_limits::max(),
-                          "m_idx must fit all indices into 'neighbours'");
+                          "m_idx must fit all indices into 'neighbors'");
             bool operator<(const SortingRecord& that) const {
                 return m_cp < that.m_cp || (m_cp == that.m_cp && m_id < that.m_id);
             }
@@ -1680,7 +1680,7 @@ private:
         for (V3GraphEdge *edgep = mtaskp->beginp(way), *nextp; edgep; edgep = nextp) {
             nextp = edgep->nextp(way);  // Fetch next first as likely cache miss
             LogicMTask* const otherp = static_cast(edgep->furtherp(way));
-            neighbours[n] = otherp;
+            neighbors[n] = otherp;
             sortRecs[n].m_id = otherp->id();
             sortRecs[n].m_cp = otherp->critPathCost(way) + otherp->cost();
             sortRecs[n].m_idx = n;
@@ -1697,13 +1697,13 @@ private:
             const size_t end = n & ~static_cast(1);  // Round down to even, (we want pairs)
             std::sort(sortRecs.begin(), sortRecs.begin() + n);
             for (size_t i = 0; i < end; i += 2) {
-                makeSiblingMC(neighbours[sortRecs[i].m_idx], neighbours[sortRecs[i + 1].m_idx]);
+                makeSiblingMC(neighbors[sortRecs[i].m_idx], neighbors[sortRecs[i + 1].m_idx]);
             }
         } else {
             constexpr size_t end = 2 * MAX_NONEXHAUSTIVE_PAIRS;
             std::partial_sort(sortRecs.begin(), sortRecs.begin() + end, sortRecs.begin() + n);
             for (size_t i = 0; i < end; i += 2) {
-                makeSiblingMC(neighbours[sortRecs[i].m_idx], neighbours[sortRecs[i + 1].m_idx]);
+                makeSiblingMC(neighbors[sortRecs[i].m_idx], neighbors[sortRecs[i + 1].m_idx]);
             }
         }
     }
@@ -1907,7 +1907,7 @@ private:
 //
 // ABOUT UNORDERED WRITE-READ PAIRS
 //
-//   If we don't put unordered write-read pairs into some order at verilation
+//   If we don't put unordered write-read pairs into some order at Verilation
 //   time, we risk a runtime race.
 //
 //   How do such unordered writer/reader pairs happen? Here's a partial list
@@ -1971,13 +1971,9 @@ private:
                 tasksByRank[writerMtaskp->rank()].insert(writerMtaskp);
             }
         }
-        // Find all reader tasks for this variable, group by rank.
-        for (V3GraphEdge* edgep = varVtxp->outBeginp(); edgep; edgep = edgep->outNextp()) {
-            if (const auto* const logicVtxp = dynamic_cast(edgep->fromp())) {
-                LogicMTask* const readerMtaskp = static_cast(logicVtxp->userp());
-                tasksByRank[readerMtaskp->rank()].insert(readerMtaskp);
-            }
-        }
+        // Not: Find all reader tasks for this variable, group by rank.
+        // There was "broken" code here to find readers, but fixing it to
+        // work properly harmed performance on some tests, see #3360.
     }
     void mergeSameRankTasks(const TasksByRank& tasksByRank) {
         LogicMTask* lastRecipientp = nullptr;
diff --git a/src/V3Partition.h b/src/V3Partition.h
index 72a9ed43f..cfa68c515 100644
--- a/src/V3Partition.h
+++ b/src/V3Partition.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3PartitionGraph.h b/src/V3PartitionGraph.h
index 6f8e8c72d..fc16c81c6 100644
--- a/src/V3PartitionGraph.h
+++ b/src/V3PartitionGraph.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3PreLex.h b/src/V3PreLex.h
index 721075495..b6718d264 100644
--- a/src/V3PreLex.h
+++ b/src/V3PreLex.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2000-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2000-2023 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.
@@ -92,6 +92,7 @@ class V3PreProcImp;
 # define yytext V3PreLextext
 # define yyerror V3PreLexerror
 # define yyerrorf V3PreLexerrorf
+# define yylex_destroy V3PreLexlex_destroy
 #endif
 
 #ifndef yyourleng
@@ -117,6 +118,7 @@ extern void yyourtext(const char* textp, size_t size);  // Must call with static
 YY_BUFFER_STATE yy_create_buffer(FILE* file, int size);
 void yy_switch_to_buffer(YY_BUFFER_STATE new_buffer);
 void yy_delete_buffer(YY_BUFFER_STATE b);
+int yylex_destroy();
 
 //======================================================================
 
@@ -190,6 +192,7 @@ public:  // Used only by V3PreLex.cpp and V3PreProc.cpp
             m_streampStack.pop();
         }
         VL_DO_CLEAR(yy_delete_buffer(m_bufferState), m_bufferState = nullptr);
+        yylex_destroy();
     }
 
     // Called by V3PreLex.l from lexer
diff --git a/src/V3PreLex.l b/src/V3PreLex.l
index e423341f2..3168f7025 100644
--- a/src/V3PreLex.l
+++ b/src/V3PreLex.l
@@ -5,7 +5,7 @@
  *
  **************************************************************************
  *
- * Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+ * Copyright 2003-2023 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.
diff --git a/src/V3PreProc.cpp b/src/V3PreProc.cpp
index 15817b78f..32384386a 100644
--- a/src/V3PreProc.cpp
+++ b/src/V3PreProc.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2000-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2000-2023 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.
@@ -803,7 +803,7 @@ void V3PreProcImp::openFile(FileLine*, VInFilter* filterp, const string& filenam
     m_lexp->scanNewFile(flsp);
     addLineComment(1);  // Enter
 
-    // Filter all DOS CR's en-mass.  This avoids bugs with lexing CRs in the wrong places.
+    // Filter all DOS CR's en masse.  This avoids bugs with lexing CRs in the wrong places.
     // This will also strip them from strings, but strings aren't supposed
     // to be multi-line without a "\"
     int eof_newline = 0;  // Number of characters following last newline
diff --git a/src/V3PreProc.h b/src/V3PreProc.h
index a14562a32..72126141e 100644
--- a/src/V3PreProc.h
+++ b/src/V3PreProc.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2000-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2000-2023 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.
diff --git a/src/V3PreShell.cpp b/src/V3PreShell.cpp
index 9236283ca..087b25a75 100644
--- a/src/V3PreShell.cpp
+++ b/src/V3PreShell.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2004-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2004-2023 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.
@@ -78,6 +78,10 @@ protected:
         }
     }
 
+    void shutdown() {
+        if (s_preprocp) VL_DO_DANGLING(delete s_preprocp, s_preprocp);
+    }
+
     bool preproc(FileLine* fl, const string& modname, VInFilter* filterp, V3ParseImp* parsep,
                  const string& errmsg) {  // "" for no error
         // Preprocess the given module, putting output in vppFilename
@@ -153,6 +157,7 @@ VInFilter* V3PreShellImp::s_filterp = nullptr;
 // V3PreShell
 
 void V3PreShell::boot() { V3PreShellImp::s_preImp.boot(); }
+void V3PreShell::shutdown() { V3PreShellImp::s_preImp.shutdown(); }
 bool V3PreShell::preproc(FileLine* fl, const string& modname, VInFilter* filterp,
                          V3ParseImp* parsep, const string& errmsg) {
     return V3PreShellImp::s_preImp.preproc(fl, modname, filterp, parsep, errmsg);
diff --git a/src/V3PreShell.h b/src/V3PreShell.h
index 9c7b73499..eb6a426cd 100644
--- a/src/V3PreShell.h
+++ b/src/V3PreShell.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2004-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2004-2023 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.
@@ -33,6 +33,7 @@ class V3PreShell final {
     // Static class for calling preprocessor
 public:
     static void boot();
+    static void shutdown();
     static bool preproc(FileLine* fl, const string& modname, VInFilter* filterp,
                         V3ParseImp* parsep, const string& errmsg);
     static void preprocInclude(FileLine* fl, const string& modname);
diff --git a/src/V3Premit.cpp b/src/V3Premit.cpp
index 58c756b17..540d1526d 100644
--- a/src/V3Premit.cpp
+++ b/src/V3Premit.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Premit.h b/src/V3Premit.h
index fe13743ed..59f09a188 100644
--- a/src/V3Premit.h
+++ b/src/V3Premit.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3ProtectLib.cpp b/src/V3ProtectLib.cpp
index 27a088878..3a993714a 100644
--- a/src/V3ProtectLib.cpp
+++ b/src/V3ProtectLib.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -151,7 +151,7 @@ private:
 
         // Timescale
         if (v3Global.opt.hierChild() && v3Global.rootp()->timescaleSpecified()) {
-            // Emit timescale for hierarchical verilation if input HDL specifies timespec
+            // Emit timescale for hierarchical Verilation if input HDL specifies timespec
             txtp->addText(fl, std::string{"timeunit "} + modp->timeunit().ascii() + ";\n");
             txtp->addText(fl, std::string{"timeprecision "}
                                   + +v3Global.rootp()->timeprecision().ascii() + ";\n");
diff --git a/src/V3ProtectLib.h b/src/V3ProtectLib.h
index 6055311b2..a3db9ea8c 100644
--- a/src/V3ProtectLib.h
+++ b/src/V3ProtectLib.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp
index 493b2db67..9dfb2a536 100644
--- a/src/V3Randomize.cpp
+++ b/src/V3Randomize.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Randomize.h b/src/V3Randomize.h
index 29ea2b6b7..ff56f9a86 100644
--- a/src/V3Randomize.h
+++ b/src/V3Randomize.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Reloop.cpp b/src/V3Reloop.cpp
index bed943f75..5f605ebcf 100644
--- a/src/V3Reloop.cpp
+++ b/src/V3Reloop.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Reloop.h b/src/V3Reloop.h
index c94cc30e9..da9228510 100644
--- a/src/V3Reloop.h
+++ b/src/V3Reloop.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Sched.cpp b/src/V3Sched.cpp
index 885e5d4a0..601b82c7b 100644
--- a/src/V3Sched.cpp
+++ b/src/V3Sched.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -192,7 +192,13 @@ LogicClasses gatherLogicClasses(AstNetlist* netlistp) {
                 }
             } else {
                 UASSERT_OBJ(senTreep->hasClocked(), activep, "What else could it be?");
-                result.m_clocked.emplace_back(scopep, activep);
+                if (VN_IS(activep->stmtsp(), AlwaysObserved)) {
+                    result.m_observed.emplace_back(scopep, activep);
+                } else if (VN_IS(activep->stmtsp(), AlwaysReactive)) {
+                    result.m_reactive.emplace_back(scopep, activep);
+                } else {
+                    result.m_clocked.emplace_back(scopep, activep);
+                }
             }
         });
 
@@ -332,6 +338,20 @@ struct TriggerKit {
     }
 };
 
+//============================================================================
+// EvalKit groups items that have to be passed to createEval() for a given eval region
+
+struct EvalKit {
+    // The TRIGGERVEC AstVarScope representing the region's trigger flags
+    AstVarScope* const m_vscp = nullptr;
+    // The AstCFunc that computes the region's active triggers
+    AstCFunc* const m_triggerComputep = nullptr;
+    // The AstCFunc that dumps the region's active triggers
+    AstCFunc* const m_dumpp = nullptr;
+    // The AstCFunc that evaluates the region's logic
+    AstCFunc* const m_funcp = nullptr;
+};
+
 // Create an AstSenTree that is sensitive to the given trigger index. Must not exist yet!
 AstSenTree* createTriggerSenTree(AstNetlist* netlistp, AstVarScope* const vscp, uint32_t index) {
     AstTopScope* const topScopep = netlistp->topScopep();
@@ -534,6 +554,7 @@ AstNodeStmt* buildLoop(AstNetlist* netlistp, const string& name,
     FileLine* const flp = scopeTopp->fileline();
     // Create the loop condition variable
     AstVarScope* const condp = scopeTopp->createTemp("__V" + name + "Continue", 1);
+    condp->varp()->noReset(true);
     // Initialize the loop condition variable to true
     AstNodeStmt* const resp = setVar(condp, 1);
     // Add the loop
@@ -558,6 +579,7 @@ std::pair makeEvalLoop(AstNetlist* netlistp, const s
     FileLine* const flp = scopeTopp->fileline();
 
     AstVarScope* const counterp = scopeTopp->createTemp("__V" + tag + "IterCount", 32);
+    counterp->varp()->noReset(true);
 
     AstNodeStmt* nodep = setVar(counterp, 0);
     nodep->addNext(buildLoop(netlistp, tag, [&](AstVarScope* continuep, AstWhile* loopp) {
@@ -765,15 +787,45 @@ AstNode* createInputCombLoop(AstNetlist* netlistp, AstCFunc* const initFuncp,
 }
 
 //============================================================================
-// Bold together parts to create the top level _eval function
+// Helpers for 'createEval'
+
+AstStmtExpr* createTriggerClearCall(FileLine* const flp, AstVarScope* const vscp) {  // Trigger
+    AstVarRef* const refp = new AstVarRef{flp, vscp, VAccess::WRITE};
+    AstCMethodHard* const callp = new AstCMethodHard{flp, refp, "clear"};
+    callp->dtypeSetVoid();
+    return callp->makeStmt();
+}
+
+AstStmtExpr* createTriggerSetCall(FileLine* const flp, AstVarScope* const toVscp,
+                                  AstVarScope* const fromVscp) {
+    AstVarRef* const lhsp = new AstVarRef{flp, toVscp, VAccess::WRITE};
+    AstVarRef* const argp = new AstVarRef{flp, fromVscp, VAccess::READ};
+    AstCMethodHard* const callp = new AstCMethodHard{flp, lhsp, "set", argp};
+    callp->dtypeSetVoid();
+    return callp->makeStmt();
+}
+
+AstStmtExpr* createTriggerAndNotCall(FileLine* const flp, AstVarScope* const lhsVscp,
+                                     AstVarScope* const aVscp, AstVarScope* const bVscp) {
+    AstVarRef* const lhsp = new AstVarRef{flp, lhsVscp, VAccess::WRITE};
+    AstVarRef* const opap = new AstVarRef{flp, aVscp, VAccess::READ};
+    AstVarRef* const opbp = new AstVarRef{flp, bVscp, VAccess::READ};
+    opap->addNext(opbp);
+    AstCMethodHard* const callp = new AstCMethodHard{flp, lhsp, "andNot", opap};
+    callp->dtypeSetVoid();
+    return callp->makeStmt();
+}
+
+//============================================================================
+// Bolt together parts to create the top level _eval function
 
 void createEval(AstNetlist* netlistp,  //
                 AstNode* icoLoop,  //
-                const TriggerKit& actTrig,  //
+                const EvalKit& actKit,  //
                 AstVarScope* preTrigsp,  //
-                AstVarScope* nbaTrigsp,  //
-                AstCFunc* actFuncp,  //
-                AstCFunc* nbaFuncp,  //
+                const EvalKit& nbaKit,  //
+                const EvalKit& obsKit,  //
+                const EvalKit& reactKit,  //
                 AstCFunc* postponedFuncp,  //
                 TimingKit& timingKit  //
 ) {
@@ -785,31 +837,16 @@ void createEval(AstNetlist* netlistp,  //
     // Start with the ico loop, if any
     if (icoLoop) funcp->addStmtsp(icoLoop);
 
-    // Create the NBA trigger dumping function, which is the same as act trigger
-    // dumping function, but referencing the nba trigger vector.
-    AstCFunc* const nbaDumpp = actTrig.m_dumpp->cloneTree(false);
-    actTrig.m_dumpp->addNextHere(nbaDumpp);
-    nbaDumpp->name("_dump_triggers__nba");
-    nbaDumpp->foreach([&](AstVarRef* refp) {
-        UASSERT_OBJ(refp->access().isReadOnly(), refp, "Should only read state");
-        if (refp->varScopep() == actTrig.m_vscp) {
-            refp->replaceWith(new AstVarRef{refp->fileline(), nbaTrigsp, VAccess::READ});
-        }
-    });
-    nbaDumpp->foreach([&](AstText* textp) {  //
-        textp->text(VString::replaceWord(textp->text(), "act", "nba"));
-    });
-
     // Create the active eval loop
     AstNodeStmt* const activeEvalLoopp
         = makeEvalLoop(
-              netlistp, "act", "Active", actTrig.m_vscp, actTrig.m_dumpp,
+              netlistp, "act", "Active", actKit.m_vscp, actKit.m_dumpp,
               [&]() {  // Trigger
                   AstNodeStmt* resultp = nullptr;
 
                   // Compute the current triggers
                   {
-                      AstCCall* const trigsp = new AstCCall{flp, actTrig.m_funcp};
+                      AstCCall* const trigsp = new AstCCall{flp, actKit.m_triggerComputep};
                       trigsp->dtypeSetVoid();
                       resultp = AstNode::addNext(resultp, trigsp->makeStmt());
                   }
@@ -822,38 +859,21 @@ void createEval(AstNetlist* netlistp,  //
                   return resultp;
               },
               [&]() {  // Body
-                  AstNodeStmt* resultp = nullptr;
-
                   // Compute the pre triggers
-                  {
-                      AstVarRef* const lhsp = new AstVarRef{flp, preTrigsp, VAccess::WRITE};
-                      AstVarRef* const opap = new AstVarRef{flp, actTrig.m_vscp, VAccess::READ};
-                      AstVarRef* const opbp = new AstVarRef{flp, nbaTrigsp, VAccess::READ};
-                      opap->addNext(opbp);
-                      AstCMethodHard* const callp = new AstCMethodHard{flp, lhsp, "andNot", opap};
-                      callp->dtypeSetVoid();
-                      resultp = AstNode::addNext(resultp, callp->makeStmt());
-                  }
-
+                  AstNodeStmt* resultp
+                      = createTriggerAndNotCall(flp, preTrigsp, actKit.m_vscp, nbaKit.m_vscp);
                   // Latch the active trigger flags under the NBA trigger flags
-                  {
-                      AstVarRef* const lhsp = new AstVarRef{flp, nbaTrigsp, VAccess::WRITE};
-                      AstVarRef* const argp = new AstVarRef{flp, actTrig.m_vscp, VAccess::READ};
-                      AstCMethodHard* const callp = new AstCMethodHard{flp, lhsp, "set", argp};
-                      callp->dtypeSetVoid();
-                      resultp = AstNode::addNext(resultp, callp->makeStmt());
-                  }
-
+                  resultp = AstNode::addNext(
+                      resultp, createTriggerSetCall(flp, nbaKit.m_vscp, actKit.m_vscp));
                   // Resume triggered timing schedulers
                   if (AstCCall* const resumep = timingKit.createResume(netlistp)) {
                       resultp = AstNode::addNext(resultp, resumep->makeStmt());
                   }
-
                   // Invoke body function
                   {
-                      AstCCall* const callp = new AstCCall{flp, actFuncp};
+                      AstCCall* const callp = new AstCCall{flp, actKit.m_funcp};
                       callp->dtypeSetVoid();
-                      return AstNode::addNext(resultp, callp->makeStmt());
+                      resultp = AstNode::addNext(resultp, callp->makeStmt());
                   }
 
                   return resultp;
@@ -861,32 +881,75 @@ void createEval(AstNetlist* netlistp,  //
               .second;
 
     // Create the NBA eval loop. This uses the Active eval loop in the trigger section.
-    AstNodeStmt* const nbaEvalLoopp
+    AstNodeStmt* topEvalLoopp
         = makeEvalLoop(
-              netlistp, "nba", "NBA", nbaTrigsp, nbaDumpp,
+              netlistp, "nba", "NBA", nbaKit.m_vscp, nbaKit.m_dumpp,
               [&]() {  // Trigger
-                  AstNodeStmt* resultp = nullptr;
-
                   // Reset NBA triggers
-                  {
-                      AstVarRef* const refp = new AstVarRef{flp, nbaTrigsp, VAccess::WRITE};
-                      AstCMethodHard* const callp = new AstCMethodHard{flp, refp, "clear"};
-                      callp->dtypeSetVoid();
-                      resultp = AstNode::addNext(resultp, callp->makeStmt());
-                  }
-
+                  AstNodeStmt* resultp = createTriggerClearCall(flp, nbaKit.m_vscp);
                   // Run the Active eval loop
-                  return AstNode::addNext(resultp, activeEvalLoopp);
+                  resultp = AstNode::addNext(resultp, activeEvalLoopp);
+                  return resultp;
               },
               [&]() {  // Body
-                  AstCCall* const callp = new AstCCall{flp, nbaFuncp};
+                  AstCCall* const callp = new AstCCall{flp, nbaKit.m_funcp};
                   callp->dtypeSetVoid();
-                  return callp->makeStmt();
+                  AstNodeStmt* resultp = callp->makeStmt();
+                  // Latch the NBA trigger flags under the following region's trigger flags
+                  AstVarScope* const nextVscp = obsKit.m_vscp ? obsKit.m_vscp : reactKit.m_vscp;
+                  if (nextVscp) {
+                      resultp = AstNode::addNext(
+                          resultp, createTriggerSetCall(flp, nextVscp, nbaKit.m_vscp));
+                  }
+                  return resultp;
               })
               .second;
 
-    // Add the NBA eval loop
-    funcp->addStmtsp(nbaEvalLoopp);
+    if (obsKit.m_funcp) {
+        // Create the Observed eval loop. This uses the NBA eval loop in the trigger section.
+        topEvalLoopp
+            = makeEvalLoop(
+                  netlistp, "obs", "Observed", obsKit.m_vscp, obsKit.m_dumpp,
+                  [&]() {  // Trigger
+                      // Reset Observed triggers
+                      AstNodeStmt* resultp = createTriggerClearCall(flp, obsKit.m_vscp);
+                      // Run the NBA eval loop
+                      resultp = AstNode::addNext(resultp, topEvalLoopp);
+                      return resultp;
+                  },
+                  [&]() {  // Body
+                      AstCCall* const callp = new AstCCall{flp, obsKit.m_funcp};
+                      callp->dtypeSetVoid();
+                      AstNodeStmt* resultp = callp->makeStmt();
+                      // Latch the Observed trigger flags under the Reactive trigger flags
+                      if (reactKit.m_vscp) {
+                          resultp = AstNode::addNext(
+                              resultp, createTriggerSetCall(flp, reactKit.m_vscp, obsKit.m_vscp));
+                      }
+                      return resultp;
+                  })
+                  .second;
+    }
+
+    if (reactKit.m_funcp) {
+        // Create the Reactive eval loop. This uses the previous eval loop in the trigger section.
+        topEvalLoopp = makeEvalLoop(
+                           netlistp, "react", "Reactive", reactKit.m_vscp, reactKit.m_dumpp,
+                           [&]() {  // Trigger
+                               // Reset Reactive triggers
+                               AstNodeStmt* resultp = createTriggerClearCall(flp, reactKit.m_vscp);
+                               // Run the previous eval loop
+                               resultp = AstNode::addNext(resultp, topEvalLoopp);
+                               return resultp;
+                           },
+                           [&]() {  // Body
+                               auto* const callp = new AstCCall{flp, reactKit.m_funcp};
+                               callp->dtypeSetVoid();
+                               return callp->makeStmt();
+                           })
+                           .second;
+    }
+    funcp->addStmtsp(topEvalLoopp);
 
     // Add the Postponed eval call
     if (postponedFuncp) {
@@ -989,6 +1052,8 @@ void schedule(AstNetlist* netlistp) {
     const auto& senTreeps = getSenTreesUsedBy({&logicRegions.m_pre,  //
                                                &logicRegions.m_act,  //
                                                &logicRegions.m_nba,  //
+                                               &logicClasses.m_observed,  //
+                                               &logicClasses.m_reactive,  //
                                                &timingKit.m_lbs});
     const TriggerKit& actTrig
         = createTriggers(netlistp, initp, senExprBuilder, senTreeps, "act", extraTriggers);
@@ -1002,13 +1067,11 @@ void schedule(AstNetlist* netlistp) {
 
     AstVarScope* const actTrigVscp = actTrig.m_vscp;
     AstVarScope* const preTrigVscp = scopeTopp->createTempLike("__VpreTriggered", actTrigVscp);
-    AstVarScope* const nbaTrigVscp = scopeTopp->createTempLike("__VnbaTriggered", actTrigVscp);
 
     const auto cloneMapWithNewTriggerReferences
         = [=](std::unordered_map map, AstVarScope* vscp) {
               // Copy map
               auto newMap{map};
-              VNDeleter deleter;
               // Replace references in each mapped value with a reference to the given vscp
               for (auto& pair : newMap) {
                   pair.second = pair.second->cloneTree(false);
@@ -1016,7 +1079,7 @@ void schedule(AstNetlist* netlistp) {
                       UASSERT_OBJ(refp->varScopep() == actTrigVscp, refp, "Unexpected reference");
                       UASSERT_OBJ(refp->access() == VAccess::READ, refp, "Should be read ref");
                       refp->replaceWith(new AstVarRef{refp->fileline(), vscp, VAccess::READ});
-                      deleter.pushDeletep(refp);
+                      VL_DO_DANGLING(refp->deleteTree(), refp);
                   });
                   topScopep->addSenTreesp(pair.second);
               }
@@ -1025,7 +1088,6 @@ void schedule(AstNetlist* netlistp) {
 
     const auto& actTrigMap = actTrig.m_map;
     const auto preTrigMap = cloneMapWithNewTriggerReferences(actTrigMap, preTrigVscp);
-    const auto nbaTrigMap = cloneMapWithNewTriggerReferences(actTrigMap, nbaTrigVscp);
     if (v3Global.opt.stats()) V3Stats::statsStage("sched-create-triggers");
 
     // Note: Experiments so far show that running the Act (or Ico) regions on
@@ -1061,37 +1123,79 @@ void schedule(AstNetlist* netlistp) {
     splitCheck(actFuncp);
     if (v3Global.opt.stats()) V3Stats::statsStage("sched-create-act");
 
-    // Step 10: Create the 'nba' region evaluation function
+    const EvalKit& actKit = {actTrig.m_vscp, actTrig.m_funcp, actTrig.m_dumpp, actFuncp};
 
-    // Remap sensitivities of the input logic to the triggers
-    remapSensitivities(logicRegions.m_nba, nbaTrigMap);
-    remapSensitivities(logicReplicas.m_nba, nbaTrigMap);
-    const auto& nbaTimingDomains = timingKit.remapDomains(nbaTrigMap);
+    // Orders a region's logic and creates the region eval function
+    const auto order = [&](const std::string& name,
+                           const std::vector& logic) -> EvalKit {
+        AstVarScope* const trigVscp
+            = scopeTopp->createTempLike("__V" + name + "Triggered", actTrigVscp);
+        const auto trigMap = cloneMapWithNewTriggerReferences(actTrigMap, trigVscp);
+        // Remap sensitivities of the input logic to the triggers
+        for (LogicByScope* lbs : logic) remapSensitivities(*lbs, trigMap);
 
-    // Create the inverse map from trigger ref AstSenTree to original AstSenTree
-    std::unordered_map trigToSenNba;
-    invertAndMergeSenTreeMap(trigToSenNba, nbaTrigMap);
+        // Create the inverse map from trigger ref AstSenTree to original AstSenTree
+        std::unordered_map trigToSen;
+        invertAndMergeSenTreeMap(trigToSen, trigMap);
 
-    AstSenTree* const dpiExportTriggeredNba
-        = createTriggerSenTree(netlistp, nbaTrigVscp, dpiExportTriggerIndex);
+        AstSenTree* const dpiExportTriggered
+            = createTriggerSenTree(netlistp, trigVscp, dpiExportTriggerIndex);
 
-    AstCFunc* const nbaFuncp = V3Order::order(
-        netlistp, {&logicRegions.m_nba, &logicReplicas.m_nba}, trigToSenNba, "nba",
-        v3Global.opt.mtasks(), false, [&](const AstVarScope* vscp, std::vector& out) {
-            auto it = nbaTimingDomains.find(vscp);
-            if (it != nbaTimingDomains.end()) out = it->second;
-            if (vscp->varp()->isWrittenByDpi()) out.push_back(dpiExportTriggeredNba);
+        const auto& timingDomains = timingKit.remapDomains(trigMap);
+        AstCFunc* const funcp = V3Order::order(
+            netlistp, logic, trigToSen, name, name == "nba" && v3Global.opt.mtasks(), false,
+            [&](const AstVarScope* vscp, std::vector& out) {
+                auto it = timingDomains.find(vscp);
+                if (it != timingDomains.end()) out = it->second;
+                if (vscp->varp()->isWrittenByDpi()) out.push_back(dpiExportTriggered);
+            });
+
+        // Create the trigger dumping function, which is the same as act trigger
+        // dumping function, but referencing this region's trigger vector.
+        AstCFunc* const dumpp = actTrig.m_dumpp->cloneTree(false);
+        actTrig.m_dumpp->addNextHere(dumpp);
+        dumpp->name("_dump_triggers__" + name);
+        dumpp->foreach([&](AstVarRef* refp) {
+            UASSERT_OBJ(refp->access().isReadOnly(), refp, "Should only read state");
+            if (refp->varScopep() == actTrig.m_vscp) {
+                refp->replaceWith(new AstVarRef{refp->fileline(), trigVscp, VAccess::READ});
+                VL_DO_DANGLING(refp->deleteTree(), refp);
+            }
         });
-    splitCheck(nbaFuncp);
-    netlistp->evalNbap(nbaFuncp);  // Remember for V3LifePost
+        dumpp->foreach([&](AstText* textp) {  //
+            textp->text(VString::replaceWord(textp->text(), "act", name));
+        });
+
+        return {trigVscp, nullptr, dumpp, funcp};
+    };
+
+    // Step 10: Create the 'nba' region evaluation function
+    const EvalKit& nbaKit = order("nba", {&logicRegions.m_nba, &logicReplicas.m_nba});
+    splitCheck(nbaKit.m_funcp);
+    netlistp->evalNbap(nbaKit.m_funcp);  // Remember for V3LifePost
     if (v3Global.opt.stats()) V3Stats::statsStage("sched-create-nba");
 
-    // Step 11: Create the 'postponed' region evaluation function
+    // Orders a region's logic and creates the region eval function (only if there is any logic in
+    // the region)
+    const auto orderIfNonEmpty = [&](const std::string& name, LogicByScope& lbs) -> EvalKit {
+        if (lbs.empty()) return {};
+        const auto& kit = order(name, {&lbs});
+        if (v3Global.opt.stats()) V3Stats::statsStage("sched-create-" + name);
+        return kit;
+    };
+
+    // Step 11: Create the 'obs' region evaluation function
+    const EvalKit& obsKit = orderIfNonEmpty("obs", logicClasses.m_observed);
+
+    // Step 12: Create the 're' region evaluation function
+    const EvalKit& reactKit = orderIfNonEmpty("react", logicClasses.m_reactive);
+
+    // Step 13: Create the 'postponed' region evaluation function
     auto* const postponedFuncp = createPostponed(netlistp, logicClasses);
 
-    // Step 12: Bolt it all together to create the '_eval' function
-    createEval(netlistp, icoLoopp, actTrig, preTrigVscp, nbaTrigVscp, actFuncp, nbaFuncp,
-               postponedFuncp, timingKit);
+    // Step 14: Bolt it all together to create the '_eval' function
+    createEval(netlistp, icoLoopp, actKit, preTrigVscp, nbaKit, obsKit, reactKit, postponedFuncp,
+               timingKit);
 
     transformForks(netlistp);
 
diff --git a/src/V3Sched.h b/src/V3Sched.h
index 3132706e8..ffd12dcad 100644
--- a/src/V3Sched.h
+++ b/src/V3Sched.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -82,6 +82,8 @@ struct LogicClasses final {
     LogicByScope m_clocked;  // Clocked (or sequential) logic (logic with explicit sensitivities)
     LogicByScope m_hybrid;  // Hybrid logic (combinational logic with some explicit sensitivities)
     LogicByScope m_postponed;  // Postponed logic ($strobe)
+    LogicByScope m_observed;  // Observed logic (contains AstAlwaysObserved)
+    LogicByScope m_reactive;  // Reactive logic (contains AstAlwaysReactive)
 
     LogicClasses() = default;
     VL_UNCOPYABLE(LogicClasses);
diff --git a/src/V3SchedAcyclic.cpp b/src/V3SchedAcyclic.cpp
index 89c783fb8..4d196a068 100644
--- a/src/V3SchedAcyclic.cpp
+++ b/src/V3SchedAcyclic.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3SchedPartition.cpp b/src/V3SchedPartition.cpp
index b356afde1..0234dab01 100644
--- a/src/V3SchedPartition.cpp
+++ b/src/V3SchedPartition.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -258,7 +258,7 @@ class SchedGraphBuilder final : public VNVisitor {
 
     // Default - Any other AstActive content not handled above will hit this
     void visit(AstNode* nodep) override {  //
-        nodep->v3fatalSrc("Should behandled above");
+        nodep->v3fatalSrc("Should be handled above");
     }
     // LCOV_EXCL_STOP
 
@@ -361,7 +361,7 @@ LogicRegions partition(LogicByScope& clockedLogic, LogicByScope& combinationalLo
     // Partition the Pre logic
     {
         const VNUser1InUse user1InUse;  // AstVarScope::user1() -> bool: read in Active region
-        const VNUser2InUse user2InUse;  // AstVarScope::user2() -> bool: writen in Active region
+        const VNUser2InUse user2InUse;  // AstVarScope::user2() -> bool: written in Active region
 
         const auto markVars = [](AstNode* nodep) {
             nodep->foreach([](const AstNodeVarRef* vrefp) {
diff --git a/src/V3SchedReplicate.cpp b/src/V3SchedReplicate.cpp
index 7c3d3fb3c..0564bb60d 100644
--- a/src/V3SchedReplicate.cpp
+++ b/src/V3SchedReplicate.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3SchedTiming.cpp b/src/V3SchedTiming.cpp
index 897877253..212163164 100644
--- a/src/V3SchedTiming.cpp
+++ b/src/V3SchedTiming.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Scope.cpp b/src/V3Scope.cpp
index ffc8127e7..e10bc172b 100644
--- a/src/V3Scope.cpp
+++ b/src/V3Scope.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -58,6 +58,7 @@ private:
     // STATE, for passing down one level of hierarchy (may need save/restore)
     AstCell* m_aboveCellp = nullptr;  // Cell that instantiates this module
     AstScope* m_aboveScopep = nullptr;  // Scope that instantiates this scope
+    AstClocking* m_clockingp = nullptr;  // Current clocking block
 
     std::unordered_map m_packageScopes;  // Scopes for each package
     VarScopeMap m_varScopes;  // Varscopes created for each scope and var
@@ -247,6 +248,15 @@ private:
         // We iterate under the *clone*
         iterateChildren(clonep);
     }
+    void visit(AstClocking* nodep) override {
+        VL_RESTORER(m_clockingp);
+        m_clockingp = nodep;
+        UINFO(4, "    CLOCKING " << nodep << endl);
+        iterateChildren(nodep);
+        if (nodep->varsp()) m_scopep->modp()->addStmtsp(nodep->varsp()->unlinkFrBackWithNext());
+        if (nodep->eventp()) m_scopep->modp()->addStmtsp(nodep->eventp()->unlinkFrBack());
+        VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
+    }
     void visit(AstNodeFTask* nodep) override {
         // Add to list of blocks under this scope
         UINFO(4, "    FTASK " << nodep << endl);
@@ -265,7 +275,9 @@ private:
     }
     void visit(AstVar* nodep) override {
         // Make new scope variable
-        if (!nodep->user1p()) {
+        if (m_clockingp) {
+            nodep->name(VString::dot(m_clockingp->name(), "__DOT__", nodep->name()));
+        } else if (!nodep->user1p()) {
             AstScope* scopep = m_scopep;
             if (AstIfaceRefDType* const ifacerefp = VN_CAST(nodep->dtypep(), IfaceRefDType)) {
                 // Attach every non-virtual interface variable its inner scope
diff --git a/src/V3Scope.h b/src/V3Scope.h
index 391810df2..3a6e6b2c6 100644
--- a/src/V3Scope.h
+++ b/src/V3Scope.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Scoreboard.cpp b/src/V3Scoreboard.cpp
index b46aee6fb..761ba9f94 100644
--- a/src/V3Scoreboard.cpp
+++ b/src/V3Scoreboard.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Scoreboard.h b/src/V3Scoreboard.h
index 4bf915431..796183ef6 100644
--- a/src/V3Scoreboard.h
+++ b/src/V3Scoreboard.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3SenExprBuilder.h b/src/V3SenExprBuilder.h
index fe7c30f08..7188b22fd 100644
--- a/src/V3SenExprBuilder.h
+++ b/src/V3SenExprBuilder.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3SenTree.h b/src/V3SenTree.h
index eea4128f3..81b5e6ef5 100644
--- a/src/V3SenTree.h
+++ b/src/V3SenTree.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Simulate.h b/src/V3Simulate.h
index 24113394f..0fda5bec2 100644
--- a/src/V3Simulate.h
+++ b/src/V3Simulate.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp
index 59a08ee8c..8bee2d842 100644
--- a/src/V3Slice.cpp
+++ b/src/V3Slice.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Slice.h b/src/V3Slice.h
index 4c65f5e8c..002c31443 100644
--- a/src/V3Slice.h
+++ b/src/V3Slice.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Split.cpp b/src/V3Split.cpp
index 380801070..db8a8da73 100644
--- a/src/V3Split.cpp
+++ b/src/V3Split.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Split.h b/src/V3Split.h
index 4fd6960eb..e0978405d 100644
--- a/src/V3Split.h
+++ b/src/V3Split.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3SplitAs.cpp b/src/V3SplitAs.cpp
index 564e023df..b8c82f80d 100644
--- a/src/V3SplitAs.cpp
+++ b/src/V3SplitAs.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3SplitAs.h b/src/V3SplitAs.h
index b959c709e..7d692813d 100644
--- a/src/V3SplitAs.h
+++ b/src/V3SplitAs.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3SplitVar.cpp b/src/V3SplitVar.cpp
index da1b95c87..43af5a4a2 100644
--- a/src/V3SplitVar.cpp
+++ b/src/V3SplitVar.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -27,7 +27,7 @@
 // What this pass does looks as below.
 //
 //     // Original
-//     logic [1:0] unpcked_array_var[0:1] /*verilator split_var*/;
+//     logic [1:0] unpacked_array_var[0:1] /*verilator split_var*/;
 //     always_comb begin
 //        unpacked_array_var[1][0] =  unpacked_array_var[0][0]; // UNOPTFLAT warning
 //        unpacked_array_var[1][1] = ~unpacked_array_var[0][1]; // UNOPTFLAT warning
@@ -45,8 +45,8 @@
 // is initially converted to
 //
 //     // Intermediate
-//     logic [1:0] unpcked_array_var0 /*verilator split_var*/;
-//     logic [1:0] unpcked_array_var1 /*verilator split_var*/;
+//     logic [1:0] unpacked_array_var0 /*verilator split_var*/;
+//     logic [1:0] unpacked_array_var1 /*verilator split_var*/;
 //     always_comb begin
 //        unpacked_array_var1[0] =  unpacked_array_var0[0];
 //        unpacked_array_var1[1] = ~unpacked_array_var0[1];
@@ -228,7 +228,7 @@ struct SplitVarImpl {
 };  // SplitVarImpl
 
 //######################################################################
-// Utilities required in wharious placs
+// Utilities required in various placs
 
 static void warnNoSplit(const AstVar* varp, const AstNode* wherep, const char* reasonp) {
     wherep->v3warn(SPLITVAR, varp->prettyNameQ()
diff --git a/src/V3SplitVar.h b/src/V3SplitVar.h
index 1e0f494f4..2d2c525a5 100644
--- a/src/V3SplitVar.h
+++ b/src/V3SplitVar.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Stats.cpp b/src/V3Stats.cpp
index bda08d003..df38e83ac 100644
--- a/src/V3Stats.cpp
+++ b/src/V3Stats.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2005-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2005-2023 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.
diff --git a/src/V3Stats.h b/src/V3Stats.h
index 6676797a1..fb56fbfe8 100644
--- a/src/V3Stats.h
+++ b/src/V3Stats.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2005-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2005-2023 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.
diff --git a/src/V3StatsReport.cpp b/src/V3StatsReport.cpp
index daab941dd..72123b2df 100644
--- a/src/V3StatsReport.cpp
+++ b/src/V3StatsReport.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2005-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2005-2023 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.
@@ -215,6 +215,7 @@ void V3Stats::statsStage(const string& name) {
     const double wallTimeDelta = wallTime - lastWallTime;
     lastWallTime = wallTime;
     V3Stats::addStatPerf("Stage, Elapsed time (sec), " + digitName, wallTimeDelta);
+    V3Stats::addStatPerf("Stage, Elapsed time (sec), TOTAL", wallTimeDelta);
 
     const double memory = V3Os::memUsageBytes() / 1024.0 / 1024.0;
     V3Stats::addStatPerf("Stage, Memory (MB), " + digitName, memory);
diff --git a/src/V3StdFuture.h b/src/V3StdFuture.h
index ea630b7fd..09f21dbd4 100644
--- a/src/V3StdFuture.h
+++ b/src/V3StdFuture.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3String.cpp b/src/V3String.cpp
index 232673006..3db19a40c 100644
--- a/src/V3String.cpp
+++ b/src/V3String.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3String.h b/src/V3String.h
index bad040651..d65c9db55 100644
--- a/src/V3String.h
+++ b/src/V3String.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Subst.cpp b/src/V3Subst.cpp
index 56c74181b..05dec8dba 100644
--- a/src/V3Subst.cpp
+++ b/src/V3Subst.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2004-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2004-2023 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.
diff --git a/src/V3Subst.h b/src/V3Subst.h
index 7dbc2d335..de7e09381 100644
--- a/src/V3Subst.h
+++ b/src/V3Subst.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3SymTable.h b/src/V3SymTable.h
index 714574096..d81b0f276 100644
--- a/src/V3SymTable.h
+++ b/src/V3SymTable.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3TSP.cpp b/src/V3TSP.cpp
index 6690fb2ba..2ee4a27ca 100644
--- a/src/V3TSP.cpp
+++ b/src/V3TSP.cpp
@@ -1,6 +1,6 @@
 // -*- mode: C++; c-file-style: "cc-mode" -*-
 //*************************************************************************
-// DESCRIPTION: Verilator: Implementation of Christofides' algorithm to
+// DESCRIPTION: Verilator: Implementation of Christofides algorithm to
 //              approximate the solution to the traveling salesman problem.
 //
 // ISSUES: This isn't exactly Christofides algorithm; see the TODO
@@ -11,7 +11,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -264,7 +264,7 @@ public:
             vtxp->user(VertexState::UNMATCHED_ODD);
         }
 
-        // TODO: The true Chrisofides algorithm calls for minimum-weight
+        // TODO: The true Christofides algorithm calls for minimum-weight
         // perfect matching. Instead, we have a simple greedy algorithm
         // which might get close to the minimum, maybe, with luck?
         //
diff --git a/src/V3TSP.h b/src/V3TSP.h
index 8df9a2f2f..ea698c62a 100644
--- a/src/V3TSP.h
+++ b/src/V3TSP.h
@@ -1,13 +1,13 @@
 // -*- mode: C++; c-file-style: "cc-mode" -*-
 //*************************************************************************
-// DESCRIPTION: Verilator: Implementation of Christofides' algorithm to
+// DESCRIPTION: Verilator: Implementation of Christofides algorithm to
 //              approximate the solution to the traveling salesman problem.
 //
 // Code available from: https://verilator.org
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Table.cpp b/src/V3Table.cpp
index 5680d80af..56b754b04 100644
--- a/src/V3Table.cpp
+++ b/src/V3Table.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Table.h b/src/V3Table.h
index 3051a690e..08eaf62b7 100644
--- a/src/V3Table.h
+++ b/src/V3Table.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Task.cpp b/src/V3Task.cpp
index 84cf450d3..500d8e6dc 100644
--- a/src/V3Task.cpp
+++ b/src/V3Task.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -1094,7 +1094,7 @@ private:
                     if (bdtypep->isDpiBitVec() && portp->width() > 32) {
                         portp->v3error("DPI function may not return a > 32 bits wide type "
                                        "other than basic types.\n"
-                                       + V3Error::warnMore()
+                                       + portp->warnMore()
                                        + "... Suggest make it an output argument instead?");
                     }
                     if (bdtypep->isDpiLogicVec()) {
@@ -1106,7 +1106,7 @@ private:
                 if (portp->isWide()) {
                     nodep->v3warn(E_UNSUPPORTED,
                                   "Unsupported: Public functions with return > 64 bits wide.\n"
-                                      + V3Error::warnMore()
+                                      + nodep->warnMore()
                                       + "... Suggest make it an output argument instead?");
                 }
             }
diff --git a/src/V3Task.h b/src/V3Task.h
index a2ae41769..1a1a5ef8e 100644
--- a/src/V3Task.h
+++ b/src/V3Task.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Timing.cpp b/src/V3Timing.cpp
index 195714a2b..5b3ae150d 100644
--- a/src/V3Timing.cpp
+++ b/src/V3Timing.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -155,8 +155,8 @@ private:
     }
     // Transform an assignment with an intra timing control into a timing control with the
     // assignment under it
-    AstNodeStmt* factorOutTimingControl(AstNodeAssign* nodep) const {
-        AstNodeStmt* stmtp = nodep;
+    AstNode* factorOutTimingControl(AstNodeAssign* nodep) const {
+        AstNode* stmtp = nodep;
         AstDelay* delayp = getLhsNetDelay(nodep);
         FileLine* const flp = nodep->fileline();
         AstNode* const controlp = nodep->timingControlp();
@@ -182,6 +182,11 @@ private:
             stmtp->replaceWith(eventControlp);
             eventControlp->addStmtsp(stmtp);
             stmtp = eventControlp;
+        } else if (auto* const beginp = VN_CAST(controlp, Begin)) {
+            // Begin from V3AssertPre
+            stmtp->replaceWith(beginp);
+            beginp->addStmtsp(stmtp);
+            stmtp = beginp;
         }
         return stmtp == nodep ? nullptr : stmtp;
     }
@@ -495,6 +500,8 @@ private:
         m_procp->user2(true);
     }
     void visit(AstDelay* nodep) override {
+        UASSERT_OBJ(!nodep->isCycleDelay(), nodep,
+                    "Cycle delays should have been handled in V3AssertPre");
         FileLine* const flp = nodep->fileline();
         AstNodeExpr* valuep = V3Const::constifyEdit(nodep->lhsp()->unlinkFrBack());
         auto* const constp = VN_CAST(valuep, Const);
diff --git a/src/V3Timing.h b/src/V3Timing.h
index 2114f1bbb..784b5cddf 100644
--- a/src/V3Timing.h
+++ b/src/V3Timing.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Trace.cpp b/src/V3Trace.cpp
index 618a1dd0a..32dbd8471 100644
--- a/src/V3Trace.cpp
+++ b/src/V3Trace.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -400,7 +400,7 @@ private:
                     cost *= declp->arrayRange().ranged() ? declp->arrayRange().elements() : 1;
                     // Note: Experiments factoring in the size of declp->valuep()
                     // showed no benefit in tracing speed, even for large trees,
-                    // so we will leve those out for now.
+                    // so we will leave those out for now.
                     complexity += cost;
                 }
             }
diff --git a/src/V3Trace.h b/src/V3Trace.h
index db130e69c..4e89805e3 100644
--- a/src/V3Trace.h
+++ b/src/V3Trace.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp
index 449abf60f..8c6f73e25 100644
--- a/src/V3TraceDecl.cpp
+++ b/src/V3TraceDecl.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -421,7 +421,28 @@ private:
                 // a much faster way to trace
                 addTraceDecl(VNumRange{}, nodep->width());
             } else if (!nodep->packed()) {
-                addIgnore("Unsupported: Unpacked struct/union");
+                if (VN_IS(nodep, UnionDType)) {
+                    addIgnore("Unsupported: Unpacked union");
+                } else {
+                    FileLine* const flp = nodep->fileline();
+                    VL_RESTORER(m_traName);
+                    string prefix{m_traName};
+                    prefix += getScopeChar(VLT_TRACE_SCOPE_STRUCT);
+                    addToSubFunc(new AstTracePushNamePrefix{flp, prefix + ' '});
+                    for (const AstMemberDType* itemp = nodep->membersp(); itemp;
+                         itemp = VN_AS(itemp->nextp(), MemberDType)) {
+                        AstNodeDType* const subtypep = itemp->subDTypep()->skipRefToEnump();
+                        m_traName = itemp->prettyName();
+                        VL_RESTORER(m_traValuep);
+                        m_traValuep = m_traValuep->cloneTree(false);
+                        m_traName = itemp->prettyName();
+                        m_traValuep = new AstStructSel{flp, m_traValuep, itemp->name()};
+                        m_traValuep->dtypep(subtypep);
+                        iterate(subtypep);
+                        VL_DO_CLEAR(m_traValuep->deleteTree(), m_traValuep = nullptr);
+                    }
+                    addToSubFunc(new AstTracePopNamePrefix{flp, 1});
+                }
             } else {
                 FileLine* const flp = nodep->fileline();
                 const bool isStruct = VN_IS(nodep, StructDType);  // Otherwise union
diff --git a/src/V3TraceDecl.h b/src/V3TraceDecl.h
index 2f2c7cb3b..0922e842f 100644
--- a/src/V3TraceDecl.h
+++ b/src/V3TraceDecl.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp
index 24cbb7da5..9837dbb92 100644
--- a/src/V3Tristate.cpp
+++ b/src/V3Tristate.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -65,7 +65,7 @@
 //
 // It is possible to statically resolve all drivers when the strongest assignment has RHS marked as
 // non-tristate. If the RHS is equal to z, that assignment has to be skipped. Since the value may
-// be not known at verilation time, cases with tristates on RHS can't be handled statically.
+// be not known at Verilation time, cases with tristates on RHS can't be handled statically.
 //
 // Static resolution is split into 2 parts.
 // First part can be done before tristate propagation. It is about removing assignments that are
diff --git a/src/V3Tristate.h b/src/V3Tristate.h
index c820a1f2a..2b8a22c64 100644
--- a/src/V3Tristate.h
+++ b/src/V3Tristate.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Undriven.cpp b/src/V3Undriven.cpp
index 68abc5ee0..5a70dd3d6 100644
--- a/src/V3Undriven.cpp
+++ b/src/V3Undriven.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2004-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2004-2023 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.
diff --git a/src/V3Undriven.h b/src/V3Undriven.h
index 059581f3b..a93e7fc1a 100644
--- a/src/V3Undriven.h
+++ b/src/V3Undriven.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3UniqueNames.h b/src/V3UniqueNames.h
index 1fe8439e9..7c4aa4af2 100644
--- a/src/V3UniqueNames.h
+++ b/src/V3UniqueNames.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2005-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2005-2023 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.
diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp
index ccd394846..258c98506 100644
--- a/src/V3Unknown.cpp
+++ b/src/V3Unknown.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Unknown.h b/src/V3Unknown.h
index 792eed1ea..24af14faa 100644
--- a/src/V3Unknown.h
+++ b/src/V3Unknown.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Unroll.cpp b/src/V3Unroll.cpp
index 23e4b3974..5e94255a3 100644
--- a/src/V3Unroll.cpp
+++ b/src/V3Unroll.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Unroll.h b/src/V3Unroll.h
index 6cdece617..4abf47241 100644
--- a/src/V3Unroll.h
+++ b/src/V3Unroll.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3VariableOrder.cpp b/src/V3VariableOrder.cpp
index b360aaca0..bdff566ba 100644
--- a/src/V3VariableOrder.cpp
+++ b/src/V3VariableOrder.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3VariableOrder.h b/src/V3VariableOrder.h
index e83b65af0..5dc7b274e 100644
--- a/src/V3VariableOrder.h
+++ b/src/V3VariableOrder.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Waiver.cpp b/src/V3Waiver.cpp
index 41a07c1ff..606aa0b46 100644
--- a/src/V3Waiver.cpp
+++ b/src/V3Waiver.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2020-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2020-2023 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.
diff --git a/src/V3Waiver.h b/src/V3Waiver.h
index ba714c6c9..10f711d1c 100644
--- a/src/V3Waiver.h
+++ b/src/V3Waiver.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3Width.cpp b/src/V3Width.cpp
index a420d2a04..32899dce3 100644
--- a/src/V3Width.cpp
+++ b/src/V3Width.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -222,6 +222,7 @@ private:
     const AstWith* m_withp = nullptr;  // Current 'with' statement
     const AstFunc* m_funcp = nullptr;  // Current function
     const AstAttrOf* m_attrp = nullptr;  // Current attribute
+    AstNodeModule* m_modp = nullptr;  // Current module
     const bool m_paramsOnly;  // Computing parameter value; limit operation
     const bool m_doGenerate;  // Do errors later inside generate statement
     int m_dtTables = 0;  // Number of created data type tables
@@ -2255,7 +2256,7 @@ private:
     }
     void visit(AstEnumItemRef* nodep) override {
         if (!nodep->itemp()->didWidth()) {
-            // We need to do the whole enum en-mass
+            // We need to do the whole enum en masse
             AstNode* enump = nodep->itemp();
             UASSERT_OBJ(enump, nodep, "EnumItemRef not linked");
             for (; enump; enump = enump->backp()) {
@@ -2478,34 +2479,42 @@ private:
         UINFO(5, "   NODECLASS " << nodep << endl);
         // if (debug() >= 9) nodep->dumpTree("-  class-in: ");
         if (!nodep->packed()) {
-            nodep->v3warn(UNPACKED, "Unsupported: Unpacked struct/union");
-            if (!v3Global.opt.structsPacked()) {
-                nodep->v3warn(UNPACKED, "Unsupported: --no-structs-packed");
+            if (VN_IS(nodep, UnionDType)) {
+                nodep->v3warn(UNPACKED, "Unsupported: Unpacked union");
+            } else if (v3Global.opt.structsPacked()) {
+                nodep->packed(true);
             }
         }
         userIterateChildren(nodep, nullptr);  // First size all members
         nodep->repairMemberCache();
-        // Determine bit assignments and width
         nodep->dtypep(nodep);
-        int lsb = 0;
-        int width = 0;
         nodep->isFourstate(false);
-        // MSB is first, so go backwards
-        AstMemberDType* itemp;
-        for (itemp = nodep->membersp(); itemp && itemp->nextp();
-             itemp = VN_AS(itemp->nextp(), MemberDType)) {}
-        for (AstMemberDType* backip; itemp; itemp = backip) {
-            if (itemp->isFourstate()) nodep->isFourstate(true);
-            backip = VN_CAST(itemp->backp(), MemberDType);
-            itemp->lsb(lsb);
-            if (VN_IS(nodep, UnionDType)) {
-                width = std::max(width, itemp->width());
-            } else {
-                lsb += itemp->width();
-                width += itemp->width();
+        // Determine bit assignments and width
+        if (VN_IS(nodep, UnionDType) || nodep->packed()) {
+            int lsb = 0;
+            int width = 0;
+            // MSB is first, so go backwards
+            AstMemberDType* itemp;
+            for (itemp = nodep->membersp(); itemp && itemp->nextp();
+                 itemp = VN_AS(itemp->nextp(), MemberDType)) {}
+            for (AstMemberDType* backip; itemp; itemp = backip) {
+                if (itemp->skipRefp()->isCompound())
+                    itemp->v3error(
+                        "Unpacked data type in packed struct/union (IEEE 1800-2017 7.2.1)");
+                if (itemp->isFourstate()) nodep->isFourstate(true);
+                backip = VN_CAST(itemp->backp(), MemberDType);
+                itemp->lsb(lsb);
+                if (VN_IS(nodep, UnionDType)) {
+                    width = std::max(width, itemp->width());
+                } else {
+                    lsb += itemp->width();
+                    width += itemp->width();
+                }
             }
+            nodep->widthForce(width, width);  // Signing stays as-is, as parsed from declaration
+        } else {
+            nodep->widthForce(1, 1);
         }
-        nodep->widthForce(width, width);  // Signing stays as-is, as parsed from declaration
         // if (debug() >= 9) nodep->dumpTree("-  class-out: ");
     }
     void visit(AstClass* nodep) override {
@@ -2526,6 +2535,11 @@ private:
         // though causes problems with t_class_forward.v, so for now avoided
         // userIterateChildren(nodep->classp(), nullptr);
     }
+    void visit(AstNodeModule* nodep) override {
+        VL_RESTORER(m_modp);
+        m_modp = nodep;
+        userIterateChildren(nodep, nullptr);
+    }
     void visit(AstClassOrPackageRef* nodep) override {
         if (nodep->didWidthAndSet()) return;
         userIterateChildren(nodep, nullptr);
@@ -2550,6 +2564,9 @@ private:
         nodep->dtypep(nodep);  // The member itself, not subDtype
         nodep->widthFromSub(nodep->subDTypep());
     }
+    void visit(AstStructSel* nodep) override {
+        userIterateChildren(nodep, WidthVP{SELF, BOTH}.p());
+    }
     void visit(AstMemberSel* nodep) override {
         UINFO(5, "   MEMBERSEL " << nodep << endl);
         if (debug() >= 9) nodep->dumpTree("-  mbs-in: ");
@@ -2564,6 +2581,7 @@ private:
         } else if (AstClassRefDType* const adtypep = VN_CAST(fromDtp, ClassRefDType)) {
             if (AstNode* const foundp = memberSelClass(nodep, adtypep)) {
                 if (AstVar* const varp = VN_CAST(foundp, Var)) {
+                    if (!varp->didWidth()) userIterate(varp, nullptr);
                     nodep->dtypep(foundp->dtypep());
                     nodep->varp(varp);
                     return;
@@ -2668,7 +2686,7 @@ private:
                 nodep->dtypep(memberp);
                 UINFO(9, "   MEMBERSEL(attr) -> " << nodep << endl);
                 UINFO(9, "           dt-> " << nodep->dtypep() << endl);
-            } else {
+            } else if (adtypep->packed()) {
                 AstSel* const newp = new AstSel{nodep->fileline(), nodep->fromp()->unlinkFrBack(),
                                                 memberp->lsb(), memberp->width()};
                 // Must skip over the member to find the union; as the member may disappear later
@@ -2680,6 +2698,18 @@ private:
                 VL_DO_DANGLING(pushDeletep(nodep), nodep);
                 // Should be able to treat it as a normal-ish nodesel - maybe.
                 // The lhsp() will be strange until this stage; create the number here?
+            } else {
+                AstStructSel* const newp = new AstStructSel{
+                    nodep->fileline(), nodep->fromp()->unlinkFrBack(), nodep->name()};
+                // Must skip over the member to find the union; as the member may disappear later
+                newp->dtypep(memberp->subDTypep()->skipRefToEnump());
+                newp->didWidth(true);  // Don't replace dtype with basic type
+                UINFO(9, "   MEMBERSEL -> " << newp << endl);
+                UINFO(9, "           dt-> " << newp->dtypep() << endl);
+                nodep->replaceWith(newp);
+                VL_DO_DANGLING(pushDeletep(nodep), nodep);
+                // Should be able to treat it as a normal-ish nodesel - maybe.
+                // The lhsp() will be strange until this stage; create the number here?
             }
             return true;
         }
@@ -3597,6 +3627,10 @@ private:
                 // Either made explicitly or V3LinkDot made implicitly
                 classp->v3fatalSrc("Can't find class's new");
             }
+            if (classp->isVirtual()) {
+                nodep->v3error(
+                    "Illegal to call 'new' using an abstract virtual class (IEEE 1800-2017 8.21)");
+            }
         } else {  // super.new case
             // in this case class and taskp() should be properly linked in V3LinkDot.cpp during
             // "super" reference resolution
@@ -3605,10 +3639,6 @@ private:
             UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked taskp()");
             nodep->dtypeFrom(nodep->taskp());
         }
-        if (classp->isVirtual()) {
-            nodep->v3error(
-                "Illegal to call 'new' using an abstract virtual class (IEEE 1800-2017 8.21)");
-        }
         userIterate(nodep->taskp(), nullptr);
         processFTaskRefArgs(nodep);
     }
@@ -3703,13 +3733,14 @@ private:
                 }
             }
             AstPatMember* defaultp = nullptr;
-            for (AstPatMember* patp = VN_AS(nodep->itemsp(), PatMember); patp;
-                 patp = VN_AS(patp->nextp(), PatMember)) {
+            for (AstPatMember* patp = VN_AS(nodep->itemsp(), PatMember); patp;) {
+                AstPatMember* const nextp = VN_AS(patp->nextp(), PatMember);
                 if (patp->isDefault()) {
                     if (defaultp) nodep->v3error("Multiple '{ default: } clauses");
                     defaultp = patp;
                     patp->unlinkFrBack();
                 }
+                patp = nextp;
             }
             while (const AstConstDType* const vdtypep = VN_CAST(dtypep, ConstDType)) {
                 dtypep = vdtypep->subDTypep()->skipRefp();
@@ -4561,7 +4592,10 @@ private:
                                || VN_IS(dtypep, WildcardArrayDType)  //
                                || VN_IS(dtypep, ClassRefDType)  //
                                || VN_IS(dtypep, DynArrayDType)  //
-                               || VN_IS(dtypep, QueueDType)) {
+                               || VN_IS(dtypep, UnpackArrayDType)  //
+                               || VN_IS(dtypep, QueueDType)
+                               || (VN_IS(dtypep, StructDType)
+                                   && !VN_AS(dtypep, StructDType)->packed())) {
                         added = true;
                         newFormat += "%@";
                         VNRelinker handle;
@@ -5343,6 +5377,12 @@ private:
             }
         }
     }
+    void visit(AstClockingItem* nodep) override {
+        nodep->exprp()->foreach([nodep](AstVarRef* const refp) {
+            refp->access(nodep->direction().isWritable() ? VAccess::WRITE : VAccess::READ);
+        });
+        userIterateChildren(nodep, WidthVP{SELF, PRELIM}.p());
+    }
     void visit(AstWait* nodep) override {
         if (VN_IS(m_ftaskp, Func)) {
             nodep->v3error("Wait statements are not legal in functions. Suggest use a task "
@@ -7170,7 +7210,7 @@ AstNode* V3Width::widthParamsEdit(AstNode* nodep) {
 //! later to do the width check.
 //! @return  Pointer to the edited node.
 AstNode* V3Width::widthGenerateParamsEdit(
-    AstNode* nodep) {  //!< [in] AST whose parameters widths are to be analysed.
+    AstNode* nodep) {  //!< [in] AST whose parameters widths are to be analyzed.
     UINFO(4, __FUNCTION__ << ": " << nodep << endl);
     // We should do it in bottom-up module order, but it works in any order.
     WidthVisitor visitor{true, true};
diff --git a/src/V3Width.h b/src/V3Width.h
index 6a0261d9e..857ca1dc1 100644
--- a/src/V3Width.h
+++ b/src/V3Width.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3WidthCommit.h b/src/V3WidthCommit.h
index f9b2e191b..785db8add 100644
--- a/src/V3WidthCommit.h
+++ b/src/V3WidthCommit.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp
index 98437443b..20b2741b7 100644
--- a/src/V3WidthSel.cpp
+++ b/src/V3WidthSel.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/Verilator.cpp b/src/Verilator.cpp
index aad4863cd..76956b5e8 100644
--- a/src/Verilator.cpp
+++ b/src/Verilator.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -159,7 +159,7 @@ static void process() {
     V3Dead::deadifyModules(v3Global.rootp());
     v3Global.checkTree();
 
-    // Create a hierarchical verilation plan
+    // 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.
@@ -672,9 +672,6 @@ static void verilate(const string& argString) {
 
     // Final writing shouldn't throw warnings, but...
     V3Error::abortIfWarnings();
-    // Cleanup memory for valgrind leak analysis
-    v3Global.clear();
-    FileLine::deleteAllRemaining();
 }
 
 static string buildMakeCmd(const string& makefile, const string& target) {
@@ -763,7 +760,9 @@ int main(int argc, char** argv) {
     }
 
     // Explicitly release resources
+    V3PreShell::shutdown();
     v3Global.shutdown();
+    FileLine::deleteAllRemaining();
 
     UINFO(1, "Done, Exiting...\n");
 }
diff --git a/src/VlcBucket.h b/src/VlcBucket.h
index 0160ae1b2..5fa253af0 100644
--- a/src/VlcBucket.h
+++ b/src/VlcBucket.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/VlcMain.cpp b/src/VlcMain.cpp
index a2f93f043..78291e3e6 100644
--- a/src/VlcMain.cpp
+++ b/src/VlcMain.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -34,7 +34,7 @@ static int debug() { return V3Error::debugDefault(); }
 #include "V3OptionParser.cpp"
 #include "V3Os.cpp"
 #include "VlcTop.cpp"
-// clanf-format on
+// clang-format on
 
 #include "VlcOptions.h"
 #include "VlcTop.h"
@@ -102,7 +102,7 @@ void VlcOptions::showVersion(bool verbose) {
     if (!verbose) return;
 
     cout << endl;
-    cout << "Copyright 2003-2022 by Wilson Snyder.  Verilator is free software; you can\n";
+    cout << "Copyright 2003-2023 by Wilson Snyder.  Verilator is free software; you can\n";
     cout << "redistribute it and/or modify the Verilator internals under the terms of\n";
     cout << "either the GNU Lesser General Public License Version 3 or the Perl Artistic\n";
     cout << "License Version 2.0.\n";
diff --git a/src/VlcOptions.h b/src/VlcOptions.h
index 6f4bd3a0f..c105594d4 100644
--- a/src/VlcOptions.h
+++ b/src/VlcOptions.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/VlcPoint.h b/src/VlcPoint.h
index 1b59b39f2..bb954bf36 100644
--- a/src/VlcPoint.h
+++ b/src/VlcPoint.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/VlcSource.h b/src/VlcSource.h
index fc40ae241..5c4eedf04 100644
--- a/src/VlcSource.h
+++ b/src/VlcSource.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/VlcTest.h b/src/VlcTest.h
index 0ceb7d340..3f960b9fb 100644
--- a/src/VlcTest.h
+++ b/src/VlcTest.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/VlcTop.cpp b/src/VlcTop.cpp
index fe94464ea..db5a9fa03 100644
--- a/src/VlcTop.cpp
+++ b/src/VlcTop.cpp
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/VlcTop.h b/src/VlcTop.h
index 2f453b5ff..3f05bf343 100644
--- a/src/VlcTop.h
+++ b/src/VlcTop.h
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/astgen b/src/astgen
index fe85a30cc..95d609df7 100755
--- a/src/astgen
+++ b/src/astgen
@@ -1222,7 +1222,7 @@ parser = argparse.ArgumentParser(
     formatter_class=argparse.RawDescriptionHelpFormatter,
     description="""Generate V3Ast headers to reduce C++ code duplication.""",
     epilog=
-    """Copyright 2002-2022 by Wilson Snyder. This program is free software; you
+    """Copyright 2002-2023 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.
diff --git a/src/bisonpre b/src/bisonpre
index 368f1c81b..507ca1668 100755
--- a/src/bisonpre
+++ b/src/bisonpre
@@ -508,7 +508,7 @@ BISON GRAMMAR EXTENSIONS
     If the bison version is >= the specified version, include the given
     command.
 
-Copyright 2002-2022 by Wilson Snyder. This program is free software; you
+Copyright 2002-2023 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.
diff --git a/src/config_build.h.in b/src/config_build.h.in
index 32a0da56f..34cb81c45 100644
--- a/src/config_build.h.in
+++ b/src/config_build.h.in
@@ -8,7 +8,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
diff --git a/src/config_rev b/src/config_rev
index 754ab29d2..420140ec7 100755
--- a/src/config_rev
+++ b/src/config_rev
@@ -2,7 +2,7 @@
 # pylint: disable=C0103,C0114
 ######################################################################
 #
-# Copyright 2005-2022 by Wilson Snyder. This program is free software; you
+# Copyright 2005-2023 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.
diff --git a/src/cppcheck_filtered b/src/cppcheck_filtered
index 78156e1e9..d023910ce 100755
--- a/src/cppcheck_filtered
+++ b/src/cppcheck_filtered
@@ -183,7 +183,7 @@ filters out unnecessary warnings related to Verilator. Run as:
     cd $VERILATOR_ROOT
     make -k cppcheck""",
     epilog=
-    """Copyright 2014-2022 by Wilson Snyder. This program is free software; you
+    """Copyright 2014-2023 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.
diff --git a/src/flexfix b/src/flexfix
index 9ade34b8f..ee017dc43 100755
--- a/src/flexfix
+++ b/src/flexfix
@@ -2,7 +2,7 @@
 # pylint: disable=C0114,C0301
 ######################################################################
 #
-# Copyright 2002-2022 by Wilson Snyder. This program is free software; you
+# Copyright 2002-2023 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.
diff --git a/src/verilog.l b/src/verilog.l
index b4b42635c..bff9bd3b1 100644
--- a/src/verilog.l
+++ b/src/verilog.l
@@ -6,7 +6,7 @@
  *
  **************************************************************************
  *
- * Copyright 2003-2022 by Wilson Snyder.  Verilator is free software; you
+ * Copyright 2003-2023 by Wilson Snyder.  Verilator is free software; you
  * can redistribute it and/or modify it under the terms of either the
  * GNU Lesser General Public License Version 3 or the Perl Artistic License
  * Version 2.0.
@@ -637,6 +637,7 @@ vnum    {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
 
 {
   /*     Generic unsupported warnings */
+   "1step"              { FL; return ya1STEP; }
    "above"              { ERROR_RSVD_WORD("AMS"); }
    "abs"                { ERROR_RSVD_WORD("AMS"); }
    "absdelay"           { ERROR_RSVD_WORD("AMS"); }
@@ -929,8 +930,7 @@ vnum    {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
                           return yaTIMENUM;
                         }
   1step                 {
-                          FL; yylval.cdouble = 0;  // Unsupported
-                          return yaTIMENUM;
+                          return ya1STEP;
                         }
 }
 
diff --git a/src/verilog.y b/src/verilog.y
index 311e68a4c..bdbd218af 100644
--- a/src/verilog.y
+++ b/src/verilog.y
@@ -6,7 +6,7 @@
 //
 //*************************************************************************
 //
-// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+// Copyright 2003-2023 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.
@@ -95,7 +95,11 @@ public:
     bool m_pinAnsi = false;  // In ANSI port list
     bool m_tracingParse = true;  // Tracing disable for parser
     bool m_insideProperty = false;  // Is inside property declaration
-    bool m_typedPropertyPort = false;  // True if typed property port occured on port lists
+    bool m_typedPropertyPort = false;  // True if typed property port occurred on port lists
+    bool m_modportImpExpActive
+        = false;  // Standalone ID is a tf_identifier instead of port_identifier
+    bool m_modportImpExpLastIsExport
+        = false;  // Last import_export statement in modportPortsDecl is an export
 
     int m_pinNum = -1;  // Pin number currently parsing
     std::stack m_pinStack;  // Queue of pin numbers being parsed
@@ -243,6 +247,19 @@ public:
             fileline->v3error("Unsupported DPI type '" << str << "': Use 'DPI-C'");
         }
     }
+    // Given a list of clocking declarations, put them in clocking items
+    AstClockingItem* makeClockingItemList(FileLine* flp, const VDirection direction,
+                                          AstNodeExpr* skewp, AstNode* const clockingDeclps) {
+        AstClockingItem* itemsp = nullptr;
+        for (AstNode *nodep = clockingDeclps, *nextp; nodep; nodep = nextp) {
+            nextp = nodep->nextp();
+            if (nextp) nextp->unlinkFrBackWithNext();
+            if (itemsp && skewp) skewp = skewp->cloneTree(false);
+            AstClockingItem* itemp = new AstClockingItem{flp, direction, skewp, nodep};
+            itemsp = itemsp ? itemsp->addNext(itemp) : itemp;
+        }
+        return itemsp;
+    }
 };
 
 const VBasicDTypeKwd LOGIC = VBasicDTypeKwd::LOGIC;  // Shorthand "LOGIC"
@@ -330,7 +347,7 @@ static void ERRSVKWD(FileLine* fileline, const string& tokname) {
     fileline->v3error(
         std::string{"Unexpected '"} + tokname + "': '" + tokname
         + "' is a SystemVerilog keyword misused as an identifier."
-        + (!toldonce++ ? "\n" + V3Error::warnMore()
+        + (!toldonce++ ? "\n" + fileline->warnMore()
                              + "... Suggest modify the Verilog-2001 code to avoid SV keywords,"
                              + " or use `begin_keywords or --language."
                        : ""));
@@ -494,6 +511,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
 // for example yP_ for punctuation based operators.
 // Double underscores "yX__Y" means token X followed by Y,
 // and "yX__ETC" means X folled by everything but Y(s).
+%token              ya1STEP         "1step"
 //UNSUP %token      yACCEPT_ON      "accept_on"
 %token              yALIAS          "alias"
 %token              yALWAYS         "always"
@@ -1546,7 +1564,7 @@ portSig:
 // Interface headers
 
 interface_declaration:          // IEEE: interface_declaration + interface_nonansi_header + interface_ansi_header:
-        //                      // timeunits_delcarationE is instead in interface_item
+        //                      // timeunits_declarationE is instead in interface_item
                 intFront importsAndParametersE portsStarE ';'
                         interface_itemListE yENDINTERFACE endLabelE
                         { if ($2) $1->addStmtsp($2);
@@ -1634,7 +1652,7 @@ anonymous_program_item:  // ==IEEE: anonymous_program_item
         ;
 
 program_declaration:            // IEEE: program_declaration + program_nonansi_header + program_ansi_header:
-        //                      // timeunits_delcarationE is instead in program_item
+        //                      // timeunits_declarationE is instead in program_item
                 pgmFront parameter_port_listE portsStarE ';'
         /*cont*/    program_itemListE yENDPROGRAM endLabelE
                         { $1->modTrace(GRAMMARP->allTracingOn($1->fileline()));  // Stash for implicit wires, etc
@@ -1730,30 +1748,40 @@ modportPortsDeclList:
 // We track the type as with the V2k series of defines, then create as each ID is seen.
 modportPortsDecl:
         //                      // IEEE: modport_simple_ports_declaration
-                port_direction modportSimplePort        { $$ = new AstModportVarRef{$2, *$2, GRAMMARP->m_varIO}; }
+                port_direction modportSimplePortOrTFPort { $$ = new AstModportVarRef{$2, *$2, GRAMMARP->m_varIO};
+                                                           GRAMMARP->m_modportImpExpActive = false;}
         //                      // IEEE: modport_clocking_declaration
         |       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 id/*tf_identifier*/              { $$ = new AstModportFTaskRef{$2, *$2, false};
+                                                           GRAMMARP->m_modportImpExpActive = true;
+                                                           GRAMMARP->m_modportImpExpLastIsExport = false; }
+        |       yEXPORT id/*tf_identifier*/              { $$ = new AstModportFTaskRef{$2, *$2, true};
+                                                           GRAMMARP->m_modportImpExpActive = true;
+                                                           GRAMMARP->m_modportImpExpLastIsExport = true; }
         |       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}; }
+        |       modportSimplePortOrTFPort                { $$ = GRAMMARP->m_modportImpExpActive ?
+                                                                static_cast(
+                                                                  new AstModportFTaskRef(
+                                                                    $1, *$1, GRAMMARP->m_modportImpExpLastIsExport) ) :
+                                                                static_cast(
+                                                                  new AstModportVarRef(
+                                                                    $1, *$1, GRAMMARP->m_varIO) ); }
         ;
 
-modportSimplePort:        // IEEE: modport_simple_port or modport_tf_port, depending what keyword was earlier
+modportSimplePortOrTFPort:// IEEE: modport_simple_port or modport_tf_port, depending what keyword was earlier
                 id                                      { $$ = $1; }
         //UNSUP '.' idAny '(' ')'                       { }
         //UNSUP '.' idAny '(' expr ')'                  { }
         ;
-
 //************************************************
 // Variable Declarations
 
@@ -2091,7 +2119,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 = nullptr; }
+        /*cont*/    list_of_member_decl_assignments ';'
+                        { $$ = $4; DEL(GRAMMARP->m_memDTypep); GRAMMARP->m_memDTypep = nullptr; }
         |       vlTag                                   { $$ = nullptr; }
         ;
 
@@ -2104,10 +2133,8 @@ member_decl_assignment:   // Derived from IEEE: variable_decl_assi
         //                      // At present we allow only packed structures/unions.
         //                      // So this is different from variable_decl_assignment
                 id variable_dimensionListE
-                        { if ($2) $2->v3warn(UNPACKED, "Unsupported: Unpacked array in packed struct/union"
-                                                       " (struct/union converted to unpacked)");
-                          $$ = new AstMemberDType{$1, *$1, VFlagChildDType{},
-                                                  AstNodeDType::cloneTreeNull(GRAMMARP->m_memDTypep, true)};
+                        { $$ = new AstMemberDType{$1, *$1, VFlagChildDType{},
+                                                  GRAMMARP->createArray(AstNodeDType::cloneTreeNull(GRAMMARP->m_memDTypep, true), $2, false)};
                           PARSEP->tagNodep($$);
                           }
         |       id variable_dimensionListE '=' variable_declExpr
@@ -2830,13 +2857,13 @@ delay_controlE:
 
 delay_control:   //== IEEE: delay_control
                 '#' delay_value
-                        { $$ = new AstDelay{$1, $2}; }
+                        { $$ = new AstDelay{$1, $2, false}; }
         |       '#' '(' minTypMax ')'
-                        { $$ = new AstDelay{$1, $3}; }
+                        { $$ = new AstDelay{$1, $3, false}; }
         |       '#' '(' minTypMax ',' minTypMax ')'
-                        { $$ = new AstDelay{$1, $3}; RISEFALLDLYUNSUP($3); DEL($5); }
+                        { $$ = new AstDelay{$1, $3, false}; RISEFALLDLYUNSUP($3); DEL($5); }
         |       '#' '(' minTypMax ',' minTypMax ',' minTypMax ')'
-                        { $$ = new AstDelay{$1, $3}; RISEFALLDLYUNSUP($3); DEL($5); DEL($7); }
+                        { $$ = new AstDelay{$1, $3, false}; RISEFALLDLYUNSUP($3); DEL($5); DEL($7); }
         ;
 
 delay_value:         // ==IEEE:delay_value
@@ -3322,6 +3349,10 @@ statement_item:          // IEEE: statement_item
         //                      // IEEE: nonblocking_assignment
         |       fexprLvalue yP_LTE delay_or_event_controlE expr ';'
                         { $$ = new AstAssignDly{$2, $1, $4, $3}; }
+        //                      // IEEE: clocking_drive ';'
+        |       fexprLvalue yP_LTE cycle_delay expr ';'
+                        { $$ = new AstAssignDly{$2, $1, $4, $3}; }
+        //UNSUP cycle_delay fexprLvalue yP_LTE ';'      { UNSUP }
         |       yASSIGN idClassSel '=' delay_or_event_controlE expr ';'
                         { $$ = new AstAssign{$1, $2, $5, $4}; }
         |       yDEASSIGN variable_lvalue ';'
@@ -3442,8 +3473,14 @@ statement_item:          // IEEE: statement_item
                                                           if ($2 && $2->nextp()) nextp = $2->nextp()->unlinkFrBackWithNext();
                                                           $$ = new AstEventControl{FILELINE_OR_CRE($1), $1, $2};
                                                           addNextNull($$, nextp); }
-        //UNSUP cycle_delay stmtBlock                   { UNSUP }
-        //
+        |       cycle_delay stmtBlock
+                        { AstNode* nextp = nullptr;
+                          if ($2) {
+                              if ($2->nextp()) nextp = $2->nextp()->unlinkFrBackWithNext();
+                              $1->addStmtsp($2);
+                          }
+                          $$ = $1;
+                          addNextNull($$, nextp); }
         |       seq_block                               { $$ = $1; }
         //
         //                      // IEEE: wait_statement
@@ -3454,13 +3491,6 @@ statement_item:          // IEEE: statement_item
         //                      // IEEE: procedural_assertion_statement
         |       procedural_assertion_statement          { $$ = $1; }
         //
-        //                      // IEEE: clocking_drive ';'
-        //                      // Pattern w/o cycle_delay handled by nonblocking_assign above
-        //                      // clockvar_expression made to fexprLvalue to prevent reduce conflict
-        //                      // Note LTE in this context is highest precedence, so first on left wins
-        //UNSUP cycle_delay fexprLvalue yP_LTE ';'      { UNSUP }
-        //UNSUP fexprLvalue yP_LTE cycle_delay expr ';' { UNSUP }
-        //
         //UNSUP randsequence_statement                  { $$ = $1; }
         //
         //                      // IEEE: randcase_statement
@@ -4014,7 +4044,7 @@ system_f_call:           // IEEE: system_tf_call (as func)
         |       system_f_call_or_t                      { $$ = $1; }
         ;
 
-systemDpiArgsE:           // IEEE: part of system_if_call for aruments of $dpi call
+systemDpiArgsE:           // IEEE: part of system_if_call for arguments of $dpi call
                 parenE                                  { $$ = nullptr; }
         |       '(' exprList ')'                        { $$ = GRAMMARP->argWrapList($2); }
         ;
@@ -5405,87 +5435,92 @@ endLabelE:
 //************************************************
 // Clocking
 
-clocking_declaration:            // IEEE: clocking_declaration  (INCOMPLETE)
-        //UNSUP: vvv remove this -- vastly simplified grammar:
-                yDEFAULT yCLOCKING '@' '(' senitemEdge ')' ';' yENDCLOCKING
-                        { $$ = new AstClocking{$2, $5, nullptr}; }
-        //UNSUP: ^^^ remove this -- vastly simplified grammar:
-        //UNSUP clockingFront clocking_event ';'
-        //UNSUP  clocking_itemListE yENDCLOCKING endLabelE { SYMP->popScope($$); }
+clocking_declaration:            // IEEE: clocking_declaration
+                yCLOCKING idAny clocking_event ';' clocking_itemListE yENDCLOCKING endLabelE
+                        { $$ = new AstClocking{$2, *$2, $3, $5, false}; }
+        |       yDEFAULT yCLOCKING clocking_event ';' clocking_itemListE yENDCLOCKING endLabelE
+                        { $$ = new AstClocking{$2, "", $3, $5, true}; }
+        |       yDEFAULT yCLOCKING idAny clocking_event ';' clocking_itemListE yENDCLOCKING endLabelE
+                        { $$ = new AstClocking{$3, *$3, $4, $6, true}; }
+        |       yGLOBAL__CLOCKING yCLOCKING clocking_event ';' clocking_itemListE yENDCLOCKING endLabelE
+                        { $$ = nullptr;
+                          BBUNSUP($2, "Unsupported: global clocking"); }
+        |       yGLOBAL__CLOCKING yCLOCKING idAny clocking_event ';' clocking_itemListE yENDCLOCKING endLabelE
+                        { $$ = nullptr;
+                          BBUNSUP($3, "Unsupported: global clocking"); }
         ;
 
-//UNSUPclockingFront:  // IEEE: part of class_declaration
-//UNSUP         yCLOCKING                               { PARSEP->symPushNewAnon(VAstType::CLOCKING); }
-//UNSUP |       yCLOCKING idAny/*clocking_identifier*/  { SYMP->pushNew($$); }
-//UNSUP |       yDEFAULT yCLOCKING                      { PARSEP->symPushNewAnon(VAstType::CLOCKING); }
-//UNSUP |       yDEFAULT yCLOCKING idAny/*clocking_identifier*/ { SYMP->pushNew($$); }
-//UNSUP |       yGLOBAL__CLOCKING yCLOCKING                     { PARSEP->symPushNewAnon(VAstType::CLOCKING); }
-//UNSUP |       yGLOBAL__CLOCKING yCLOCKING idAny/*clocking_identifier*/        { SYMP->pushNew($$); }
-//UNSUP ;
+clocking_event:       // IEEE: clocking_event
+                '@' id
+                        { $$ = new AstSenItem{$2, VEdgeType::ET_CHANGED, new AstParseRef{$2, VParseRefExp::PX_TEXT, *$2, nullptr, nullptr}}; }
+        |       '@' '(' event_expression ')'            { $$ = $3; }
+        ;
 
-//UNSUPclocking_event:  // ==IEEE: clocking_event
-//UNSUP         '@' id                                  { }
-//UNSUP |       '@' '(' event_expression ')'            { }
-//UNSUP ;
+clocking_itemListE:
+                /* empty */                             { $$ = nullptr; }
+        |       clocking_itemList                       { $$ = $1; }
+        ;
 
-//UNSUPclocking_itemListE:
-//UNSUP         /* empty */                             { $$ = nullptr; }
-//UNSUP |       clocking_itemList                       { $$ = $1; }
-//UNSUP ;
+clocking_itemList:  // IEEE: [ clocking_item ]
+                clocking_item                           { $$ = $1; }
+        |       clocking_itemList clocking_item         { if ($1) $$ = addNextNull($1, $2); }
+        ;
 
-//UNSUPclocking_itemList:  // IEEE: [ clocking_item ]
-//UNSUP         clocking_item                           { $$ = $1; }
-//UNSUP |       clocking_itemList clocking_item         { $$ = addNextNull($1, $2); }
-//UNSUP ;
+clocking_item:   // IEEE: clocking_item
+                yDEFAULT yINPUT clocking_skew ';'       { $$ = new AstClockingItem{$1, VDirection::INPUT, $3, nullptr}; }
+        |       yDEFAULT yOUTPUT clocking_skew ';'      { $$ = new AstClockingItem{$1, VDirection::OUTPUT, $3, nullptr}; }
+        |       yDEFAULT yINPUT clocking_skew yOUTPUT clocking_skew ';'
+                        { $$ = new AstClockingItem{$1, VDirection::INPUT, $3, nullptr};
+                          $$->addNext(new AstClockingItem{$4, VDirection::OUTPUT, $5, nullptr}); }
+        |       yINPUT clocking_skewE list_of_clocking_decl_assign ';'
+                        { $$ = GRAMMARP->makeClockingItemList($1, VDirection::INPUT, $2, $3); }
+        |       yOUTPUT clocking_skewE list_of_clocking_decl_assign ';'
+                        { $$ = GRAMMARP->makeClockingItemList($1, VDirection::OUTPUT, $2, $3); }
+        |       yINPUT clocking_skewE yOUTPUT clocking_skewE list_of_clocking_decl_assign ';'
+                        { $$ = nullptr;
+                          BBUNSUP($5, "Unsupported: Mixed input/output clocking items"); }
+        |       yINOUT list_of_clocking_decl_assign ';'
+                        { $$ = nullptr;
+                          BBUNSUP($1, "Unsupported: 'inout' clocking items"); }
+        |       assertion_item_declaration
+                        { $$ = nullptr;
+                          BBUNSUP($1, "Unsupported: assertion items in clocking blocks"); }
+        ;
 
-//UNSUPclocking_item:  // ==IEEE: clocking_item
-//UNSUP         yDEFAULT default_skew ';'               { }
-//UNSUP |       clocking_direction list_of_clocking_decl_assign ';'     { }
-//UNSUP |       assertion_item_declaration              { }
-//UNSUP ;
+list_of_clocking_decl_assign:  // IEEE: list_of_clocking_decl_assign
+                clocking_decl_assign                    { $$ = $1; }
+        |       list_of_clocking_decl_assign ',' clocking_decl_assign
+                        { $$ = addNextNull($1, $3); }
+        ;
 
-//UNSUPdefault_skew:  // ==IEEE: default_skew
-//UNSUP         yINPUT clocking_skew                    { }
-//UNSUP |       yOUTPUT clocking_skew                   { }
-//UNSUP |       yINPUT clocking_skew yOUTPUT clocking_skew      { }
-//UNSUP ;
+clocking_decl_assign:    // IEEE: clocking_decl_assign
+                idAny/*new-signal_identifier*/ exprEqE
+                        { AstParseRef* const refp = new AstParseRef{$1, VParseRefExp::PX_TEXT, *$1, nullptr, nullptr};
+                          $$ = refp;
+                          if ($2) $$ = new AstAssign{$2, refp, $2}; }
+        ;
 
-//UNSUPclocking_direction:  // ==IEEE: clocking_direction
-//UNSUP         yINPUT clocking_skewE                   { }
-//UNSUP |       yOUTPUT clocking_skewE                  { }
-//UNSUP |       yINPUT clocking_skewE yOUTPUT clocking_skewE    { }
-//UNSUP |       yINOUT                                  { }
-//UNSUP ;
+clocking_skewE:          // IEEE: [clocking_skew]
+                /* empty */                             { $$ = nullptr; }
+        |       clocking_skew                           { $$ = $1; }
+        ;
 
-//UNSUPlist_of_clocking_decl_assign:  // ==IEEE: list_of_clocking_decl_assign
-//UNSUP         clocking_decl_assign                    { $$ = $1; }
-//UNSUP |       list_of_clocking_decl_assign ',' clocking_decl_assign   { }
-//UNSUP ;
+clocking_skew:           // IEEE: clocking_skew
+                delay_control                           { $$ = $1->lhsp()->unlinkFrBack(); $1->deleteTree(); }
+        |      '#' ya1STEP                              { $$ = new AstConst{$1, AstConst::OneStep{}}; }
+        |      yPOSEDGE delay_controlE                  { $$ = nullptr;
+                                                          BBUNSUP($1, "Unsupported: clocking event edge override"); }
+        |      yNEGEDGE delay_controlE                  { $$ = nullptr;
+                                                          BBUNSUP($1, "Unsupported: clocking event edge override"); }
+        |      yEDGE delay_controlE                     { $$ = nullptr;
+                                                          BBUNSUP($1, "Unsupported: clocking event edge override"); }
+        ;
 
-//UNSUPclocking_decl_assign:  // ==IEEE: clocking_decl_assign
-//UNSUP         idAny/*new-signal_identifier*/ exprEqE  { $$ = $1; }
-//UNSUP ;
-
-//UNSUPclocking_skewE:  // IEEE: [clocking_skew]
-//UNSUP         /* empty */                             { $$ = nullptr; }
-//UNSUP |       clocking_skew                           { $$ = $1; }
-//UNSUP ;
-
-//UNSUPclocking_skew:  // ==IEEE: clocking_skew
-//UNSUP         yPOSEDGE                                { }
-//UNSUP |       yPOSEDGE delay_control                  { }
-//UNSUP |       yNEGEDGE                                { }
-//UNSUP |       yNEGEDGE delay_control                  { }
-//UNSUP |       yEDGE                                   { NEED_S09($1, "edge"); }
-//UNSUP |       yEDGE delay_control                     { NEED_S09($1, "edge"); }
-//UNSUP |       delay_control                           { $$ = $1; }
-//UNSUP ;
-
-//UNSUPcycle_delay:  // ==IEEE: cycle_delay
-//UNSUP         yP_POUNDPOUND yaINTNUM                  { }
-//UNSUP |       yP_POUNDPOUND id                        { }
-//UNSUP |       yP_POUNDPOUND '(' expr ')'              { }
-//UNSUP ;
+cycle_delay:  // IEEE: cycle_delay
+               yP_POUNDPOUND yaINTNUM                   { $$ = new AstDelay{$1, new AstConst{$2, *$2}, true}; }
+        |      yP_POUNDPOUND id                         { $$ = new AstDelay{$1, new AstParseRef{$2, VParseRefExp::PX_TEXT, *$2, nullptr, nullptr}, true}; }
+        |      yP_POUNDPOUND '(' expr ')'               { $$ = new AstDelay{$1, $3, true}; }
+        ;
 
 //************************************************
 // Asserts
diff --git a/src/vlcovgen b/src/vlcovgen
index e440dca43..9465d6929 100755
--- a/src/vlcovgen
+++ b/src/vlcovgen
@@ -83,7 +83,7 @@ parser = argparse.ArgumentParser(
     description=
     """Generate verilated_cov headers to reduce C++ code duplication.""",
     epilog=
-    """Copyright 2002-2022 by Wilson Snyder. This program is free software; you
+    """Copyright 2002-2023 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.
diff --git a/test_regress/CMakeLists.txt b/test_regress/CMakeLists.txt
index 8a7119cf0..fc83ccee5 100644
--- a/test_regress/CMakeLists.txt
+++ b/test_regress/CMakeLists.txt
@@ -4,7 +4,7 @@
 #
 # This CMake file is meant to be consumed by regression tests.
 #
-# Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+# Copyright 2003-2023 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.
diff --git a/test_regress/Makefile b/test_regress/Makefile
index fcc0a934a..b148f7bdc 100644
--- a/test_regress/Makefile
+++ b/test_regress/Makefile
@@ -5,7 +5,7 @@
 # This calls the object directory makefile.  That allows the objects to
 # be placed in the "current directory" which simplifies the Makefile.
 #
-# Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+# Copyright 2003-2023 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.
diff --git a/test_regress/Makefile_obj b/test_regress/Makefile_obj
index b600939fa..237ab1224 100644
--- a/test_regress/Makefile_obj
+++ b/test_regress/Makefile_obj
@@ -5,7 +5,7 @@
 #
 # This is executed in the object directory, and called by ../Makefile
 #
-# Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+# Copyright 2003-2023 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.
@@ -41,7 +41,7 @@ CPPFLAGS += $(CPPFLAGS_ADD)
 
 ifeq ($(CFG_WITH_LONGTESTS),yes)
   ifeq ($(DRIVER_STD),newest)
-    CPPFLAGS += $(CFG_CXXFLAGS_STD_NEWEST)
+    CPPFLAGS += $(CFG_CXXFLAGS_STD)
   endif
 endif
 
diff --git a/test_regress/driver.pl b/test_regress/driver.pl
index a2a7899a1..a0c616a1f 100755
--- a/test_regress/driver.pl
+++ b/test_regress/driver.pl
@@ -2664,425 +2664,19 @@ driver.pl - Run regression tests
 
 =head1 SYNOPSIS
 
-  driver.pl
+  make test    # In Verilator directory
+  ./driver.pl  # Or, to run directly
 
 =head1 DESCRIPTION
 
 driver.pl invokes Verilator or another simulator on each test file.
-
-The driver reports the number of tests which pass, fail, or skipped (some
-resource required by the test is not available, such as SystemC).
-
-There are hundreds of tests, and for faster completion you may want to run
-the regression tests with OBJCACHE enabled and in parallel on a machine
-with many cores.  See the -j option and OBJCACHE environment variable.
-
-=head1 TEST CONFIGURATION
-
-The test configuration script (e.g. C) controls
-how the test will run by driver.pl. In general it includes a call to the
-C subroutine to compile the test with Verilator (or an alternative
-simulator), followed by a call to the C subroutine to run the
-test. Compile-only tests omit the call to C.
-
-If those complete, the script calls C to increment the count of
-successful tests and then returns 1 as its result.
-
-Both C and C take an optional argument hash table to
-control their behavior. For example:
-
-  compile(
-     verilator_flags2 => ["--lint-only"],
-     fails => 1,
-  );
-
-indicates that when compiling this test, the C<--lint-only> flag should be
-passed and that the test is expected to fail.
-
-The full list of arguments can be found by looking at the C
-source code. Some commonly used arguments are:
-
-=over 4
-
-=item all_run_flags
-
-A list of flags to be passed when running the simulator (Verilated model or
-one of the other simulators).
-
-=item check_finished
-
-Set to 1 to indicate successful completion of the test is indicated by the
-string C<*-* All Finished *-*> being printed on standard output. This is
-the normal way for successful tests to finish.
-
-=item expect
-
-A quoted list of strings or regular expression to be matched in the
-output. See  for more detail on how this argument
-should be used.
-
-=item fails
-
-Set to 1 to indicate this step (C or C or C) is
-expected to fail.  Tests that are expected to fail generally have _bad in
-their filename.
-
-=item make_main
-
-Set to 0 to disable the automatic creation of a C++ test wrapper (for
-example when a hand-written test wrapper is provided using C<--exe>).
-
-=item make_top_shell
-
-Set to 0 to disable the automatic creation of a top level shell to run the
-executable (for example when a hand-written test wrapper is provided using
-C<--exe>).
-
-=item ms_flags
-
-=item ms_flags2
-
-=item ms_run_flags
-
-The equivalent of C, C and C, but only
-for use with the ModelSim simulator.
-
-=item nc_flags
-
-=item nc_flags2
-
-=item nc_run_flags
-
-The equivalent of C, C and C, but only
-for use with the Cadence NC simulator.
-
-=item iv_flags
-
-=item iv_flags2
-
-=item iv_run_flags
-
-The equivalent of C, C and C, but only
-for use with the Icarus Verilog simulator.
-
-=item v_flags
-
-A list of standard Verilog simulator flags to be passed to the simulator
-compiler (Verilator or one of the other simulators).  This list is create
-by the driver and rarely changed, use v_flags2 instead.
-
-=item v_flags2
-
-A list of standard Verilog simulator flags to be passed to the simulator
-compiler (Verilator or one of the other simulators). Unlike v_flags, these
-options may be overridden in some simulation files.
-
-Similar sets of flags exist for atsim, GHDL, Cadence NC, Modelsim and
-Synopsys VCS.
-
-=item vcs_flags
-
-=item vcs_flags2
-
-=item vcs_run_flags
-
-The equivalent of C, C and C, but only
-for use with the Synopsys VCS simulator.
-
-=item verilator_flags
-
-=item verilator_flags2
-
-The equivalent of C and C, but only for use with
-Verilator.  If a flag is a standard flag (+incdir for example) v_flags2
-should be used instead.
-
-=item benchmarksim
-
-Output the number of model evaluations and execution time of a test to
-I/I_benchmarksim.csv. Multiple invocations
-of the same test file will append to to the same .csv file.
-
-=item xsim_flags
-
-=item xsim_flags2
-
-=item xsim_run_flags
-
-The equivalent of C, C and C, but only
-for use with the Xilinx XSim simulator.
-
-=back
-
-=head2 HINTS ON WRITING TESTS
-
-There is generally no need for the test to create its own main program or
-top level shell as the driver creates one automatically, however some tests
-require their own C++ or SystemC test harness. This is commonly given the
-same name as the test, but with .cpp as suffix
-(C). This can be specified as follows:
-
-  compile(
-      make_top_shell   => 0,
-      make_main        => 0,
-      verilator_flags2 => ["--exe $Self->{t_dir}/$Self->{name}.cpp"], );
-
-Tests should be self-checking, rather than producing lots of output. If a
-test succeeds it should print C<*-* All Finished *-*> to standard output
-and terminate (in Verilog C<$finish>), if not it should just stop (in
-Verilog C<$stop>) as that signals an error.
-
-If termination should be triggered from the C++ wrapper, the following code
-can be used:
-
-  vl_fatal(__FILE__, __LINE__, "dut", "");
-  exit(1);
-
-This can be particularly useful if checking that the Verilator model has
-not unexpectedly terminated.
-
-  if (contextp->gotFinish()) {
-      vl_fatal(__FILE__, __LINE__, "dut", "");
-      exit(1);
-  }
-
-Where it might be useful for a test to produce output, it should qualify
-this with C. For example in Verilog:
-
-  `ifdef TEST_VERBOSE
-        $write("Conditional generate if MASK [%1d] = %d\n", g, MASK[g]);
-  `endif
-
-Or in a hand-written C++ wrapper:
-
-  #ifdef TEST_VERBOSE
-      cout << "Read  a     = " << a << endl;
-  #endif
-
-The C specifies a filename that should be used to check
-the output results. This should not generally be used to decide if a test
-has succeeded. However, in the case of tests that are designed to fail at
-compile time, it is the only option. For example:
-
-  compile(
-      fails => 1,
-      expect_filename => $Self->{golden_filename},
-      );
-
-Note expect_filename strips some debugging information from the logfile
-when comparing.
-
-The C argument specifies a regular expression which must match the
-output.
-
-=head1 DRIVER ARGUMENTS
-
-=over 4
-
-=item --benchmark []
-
-Show execution times of each step.  If an optional number is given,
-specifies the number of simulation cycles (for tests that support it).
-
-=item --debug
-
-Same as C: Use the debug version of Verilator which
-enables additional assertions, debugging messages, and structure dump
-files.
-
-=item --debugi(-) 
-
-Same as C: Set Verilator internal debugging level
-globally to the specified debug level (1-10) or set the specified source
-file to the specified level. Higher levels produce more detailed messages
-(plain C<--debug> is equivalent to C<--debugi 4>).
-
-=item --dump-tree
-
-Same as C: Enable Verilator writing .tree debug
-files with dumping level 3, which dumps the standard critical stages.  For
-details on the format see the Verilator Internals manual.
-
-=item --gdb
-
-Same as C: Run Verilator under the debugger.
-
-=item --gdbbt
-
-Same as C: Run Verilator under the debugger, only to
-print backtrace information.  Requires --debug.
-
-=item --gdbsim
-
-Run Verilator generated executable under the debugger.
-
-=item --golden
-
-Update golden files, equivalent to setting HARNESS_UPDATE_GOLDEN=1.
-
-=item --hashset I/I
-
-Split tests based on a hash of the test names into I and run only
-tests in set number I (0..I-1).
-
-=item --help
-
-Displays this message and program version and exits.
-
-=item --j #
-
-Run number of parallel tests, or 0 to determine the count based on the
-number of cores installed.  Requires Perl's Parallel::Forker package.
-
-=item --quiet
-
-Suppress all output except for failures and progress messages every 15
-seconds.  Intended for use only in automated regressions.  See also
-C<--rerun>, and C<--verbose> which is not the opposite of C<--quiet>.
-
-=item --rerun
-
-Rerun all tests that failed in this run. Reruns force the flags
-C<--no-quiet --j 1>.
-
-=item --rr
-
-Same as C: Run Verilator and record with rr.
-
-=item --rrsim
-
-Run Verilator generated executable and record with rr.
-
-=item --sanitize
-
-Enable address sanitizer to compile Verilated C++ code.
-This may detect misuses of memory, such as out-of-bound accesses, use-after-free,
-and memory leaks.
-
-=item --site
-
-Run site specific tests also.
-
-=item --stop
-
-Stop on the first error.
-
-=item --trace
-
-Set the simulator specific flags to request waveform tracing.
-
-=item --verbose
-
-Compile and run the test in verbose mode. This means C will
-be defined for the test (Verilog and any C++/SystemC wrapper).
-
-=back
-
-=head1 SCENARIO ARGUMENTS
-
-The following options control which simulator is used, and which tests are
-run.  Multiple flags may be used to run multiple simulators/scenarios
-simultaneously.
-
-=over 4
-
-=item --atsim
-
-Run ATSIM simulator tests.
-
-=item --dist
-
-Run simulator-agnostic distribution tests.
-
-=item --ghdl
-
-Run GHDL simulator tests.
-
-=item --iv
-
-Run Icarus Verilog simulator tests.
-
-=item --ms
-
-Run ModelSim simulator tests.
-
-=item --nc
-
-Run Cadence NC-Verilog simulator tests.
-
-=item --vcs
-
-Run Synopsys VCS simulator tests.
-
-=item --vlt
-
-Run Verilator tests in single-threaded mode.  Default unless another scenario flag is provided.
-
-=item --vltmt
-
-Run Verilator tests in multithreaded mode.
-
-=item --xsim
-
-Run Xilinx XSim simulator tests.
-
-=back
-
-=head1 ENVIRONMENT
-
-=over 4
-
-=item SYSTEMC
-
-Root directory name of SystemC kit.  Only used if SYSTEMC_INCLUDE not set.
-
-=item SYSTEMC_INCLUDE
-
-Directory name with systemc.h in it.
-
-=item VERILATOR_GHDL
-
-Command to use to invoke GHDL.
-
-=item VERILATOR_IVERILOG
-
-Command to use to invoke Icarus Verilog.
-
-=item VERILATOR_MAKE
-
-Command to use to rebuild Verilator and run single test.  Defaults to "make &&".
-
-=item VERILATOR_MODELSIM
-
-Command to use to invoke ModelSim.
-
-=item VERILATOR_NCVERILOG
-
-Command to use to invoke ncverilog.
-
-=item VERILATOR_TESTS_SITE
-
-Used with --site, a colon-separated list of directories with tests to be added to testlist.
-
-=item VERILATOR_VCS
-
-Command to use to invoke VCS.
-
-=item VERILATOR_XELAB
-
-Command to use to invoke XSim xelab
-
-=item VERILATOR_XVLOG
-
-Command to use to invoke XSim xvlog
-
-=back
+See docs/internals.rst in the distribution for more information.
 
 =head1 DISTRIBUTION
 
 The latest version is available from L.
 
-Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+Copyright 2003-2023 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.
diff --git a/test_regress/t/TestCheck.h b/test_regress/t/TestCheck.h
index 2f8cf2283..c9b054b6c 100644
--- a/test_regress/t/TestCheck.h
+++ b/test_regress/t/TestCheck.h
@@ -1,7 +1,7 @@
 // -*- mode: C++; c-file-style: "cc-mode" -*-
 //*************************************************************************
 //
-// Copyright 2013-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2013-2023 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.
diff --git a/test_regress/t/TestSimulator.h b/test_regress/t/TestSimulator.h
index c25304f6e..5c49404f4 100644
--- a/test_regress/t/TestSimulator.h
+++ b/test_regress/t/TestSimulator.h
@@ -1,7 +1,7 @@
 // -*- mode: C++; c-file-style: "cc-mode" -*-
 //*************************************************************************
 //
-// Copyright 2013-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2013-2023 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.
@@ -11,6 +11,7 @@
 
 #include "vpi_user.h"
 
+#include 
 #include 
 
 class TestSimulator {
diff --git a/test_regress/t/TestVpi.h b/test_regress/t/TestVpi.h
index 40734b7c6..01db39ced 100644
--- a/test_regress/t/TestVpi.h
+++ b/test_regress/t/TestVpi.h
@@ -1,7 +1,7 @@
 // -*- mode: C++; c-file-style: "cc-mode" -*-
 //*************************************************************************
 //
-// Copyright 2013-2022 by Wilson Snyder. This program is free software; you can
+// Copyright 2013-2023 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.
diff --git a/test_regress/t/bootstrap.pl b/test_regress/t/bootstrap.pl
index 9672e2299..dd290d26e 100755
--- a/test_regress/t/bootstrap.pl
+++ b/test_regress/t/bootstrap.pl
@@ -1,7 +1,7 @@
 #!/usr/bin/env perl
 # DESCRIPTION: Verilator: Verilog Test driver bootstrapper
 #
-# Copyright 2008 by Wilson Snyder. This program is free software; you
+# Copyright 2008-2023 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.
diff --git a/test_regress/t/t_EXAMPLE.pl b/test_regress/t/t_EXAMPLE.pl
index 1aa73f80a..859050d63 100755
--- a/test_regress/t/t_EXAMPLE.pl
+++ b/test_regress/t/t_EXAMPLE.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Wilson Snyder. This program is free software; you
+# Copyright 2023 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.
diff --git a/test_regress/t/t_EXAMPLE.v b/test_regress/t/t_EXAMPLE.v
index 236e0f85d..ad11f43cd 100644
--- a/test_regress/t/t_EXAMPLE.v
+++ b/test_regress/t/t_EXAMPLE.v
@@ -13,7 +13,7 @@
 // please note it here, otherwise:**
 //
 // This file ONLY is placed under the Creative Commons Public Domain, for
-// any use, without warranty, 2022 by Wilson Snyder.
+// any use, without warranty, 2023 by Wilson Snyder.
 // SPDX-License-Identifier: CC0-1.0
 
 module t(/*AUTOARG*/
diff --git a/test_regress/t/t_a5_attributes_include.pl b/test_regress/t/t_a5_attributes_include.pl
new file mode 100755
index 000000000..6c69c95e3
--- /dev/null
+++ b/test_regress/t/t_a5_attributes_include.pl
@@ -0,0 +1,44 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 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(dist => 1);
+rerunnable(0);
+if ($ENV{VERILATOR_TEST_NO_ATTRIBUTES}) {
+    skip("Skipping due to VERILATOR_TEST_NO_ATTRIBUTES");
+} else {
+    check();
+}
+sub check {
+    my $root = "..";
+    # some of the files are only used in Verilation
+    # and are only in "include" folder
+    my @srcfiles = glob("$root/include/*.cpp");
+    my $srcfiles_str = join(" ", @srcfiles);
+    my $clang_args = "-I$root/include/ -I$root/include/vltstd/ -fcoroutines-ts";
+
+    sub run_clang_check {
+        {
+            my $cmd = qq{python3 -c "from clang.cindex import Index; index = Index.create(); print(\\"Clang imported\\")";};
+            print "\t$cmd\n" if $::Debug;
+            my $out = `$cmd`;
+            if (!$out || $out !~ /Clang imported/) { skip("No libclang installed\n"); return 1; }
+        }
+        run(logfile => $Self->{run_log_filename},
+            tee => 1,
+            cmd => ["python3", "$root/nodist/clang_check_attributes --verilator-root=$root --cxxflags='$clang_args' $srcfiles_str"]);
+
+        file_grep($Self->{run_log_filename}, "Number of functions reported unsafe: 0");
+    }
+
+    run_clang_check();
+}
+
+ok(1);
+1;
diff --git a/test_regress/t/t_a5_attributes_src.pl b/test_regress/t/t_a5_attributes_src.pl
new file mode 100755
index 000000000..8c2447820
--- /dev/null
+++ b/test_regress/t/t_a5_attributes_src.pl
@@ -0,0 +1,46 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 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(dist => 1);
+rerunnable(0);
+if ($ENV{VERILATOR_TEST_NO_ATTRIBUTES}) {
+    skip("Skipping due to VERILATOR_TEST_NO_ATTRIBUTES");
+} else {
+    check();
+}
+sub check {
+    my $root = "..";
+    # some of the files are only used in Verilation
+    # and are only in "include" folder
+    my @srcfiles = grep { !/\/(V3Const|Vlc\w*|\w*_test|\w*_sc|\w*.yy).cpp$/ }
+                   glob("$root/src/*.cpp $root/src/obj_opt/V3Const__gen.cpp");
+    my $srcfiles_str = join(" ", @srcfiles);
+    my $precompile_args = "-c $root/src/V3Ast.h";
+    my $clang_args = "-I$root/src/ -I$root/include/ -I$root/src/obj_opt/ -fcoroutines-ts";
+
+    sub run_clang_check {
+        {
+            my $cmd = qq{python3 -c "from clang.cindex import Index; index = Index.create(); print(\\"Clang imported\\")";};
+            print "\t$cmd\n" if $::Debug;
+            my $out = `$cmd`;
+            if (!$out || $out !~ /Clang imported/) { skip("No libclang installed\n"); return 1; }
+        }
+        run(logfile => $Self->{run_log_filename},
+            tee => 1,
+            cmd => ["python3", "$root/nodist/clang_check_attributes --verilator-root=$root --cxxflags='$clang_args' $precompile_args $srcfiles_str"]);
+
+        file_grep($Self->{run_log_filename}, "Number of functions reported unsafe: 24");
+    }
+
+    run_clang_check();
+}
+
+ok(1);
+1;
diff --git a/test_regress/t/t_array_index_increment.pl b/test_regress/t/t_array_index_increment.pl
index 89a4e77d9..beaa2ca59 100755
--- a/test_regress/t/t_array_index_increment.pl
+++ b/test_regress/t/t_array_index_increment.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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);
 
diff --git a/test_regress/t/t_array_index_increment.v b/test_regress/t/t_array_index_increment.v
index 67732b596..8d89223fa 100644
--- a/test_regress/t/t_array_index_increment.v
+++ b/test_regress/t/t_array_index_increment.v
@@ -1,3 +1,9 @@
+// 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 (/*AUTOARG*/
    // Inputs
    clk
diff --git a/test_regress/t/t_array_pattern_bad2.out b/test_regress/t/t_array_pattern_bad2.out
new file mode 100644
index 000000000..bc5533253
--- /dev/null
+++ b/test_regress/t/t_array_pattern_bad2.out
@@ -0,0 +1,5 @@
+%Error: t/t_array_pattern_bad2.v:22:16: Multiple '{ default: } clauses
+                                      : ... In instance t
+   22 |       myinfo = '{default: '0,
+      |                ^~
+%Error: Exiting due to
diff --git a/test_regress/t/t_struct_unpacked_bad.pl b/test_regress/t/t_array_pattern_bad2.pl
similarity index 94%
rename from test_regress/t/t_struct_unpacked_bad.pl
rename to test_regress/t/t_array_pattern_bad2.pl
index 59ba0d6c6..a60503a1f 100755
--- a/test_regress/t/t_struct_unpacked_bad.pl
+++ b/test_regress/t/t_array_pattern_bad2.pl
@@ -11,7 +11,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 scenarios(linter => 1);
 
 lint(
-    fails => $Self->{vlt_all},
+    fails => 1,
     expect_filename => $Self->{golden_filename},
     );
 
diff --git a/test_regress/t/t_array_pattern_bad2.v b/test_regress/t/t_array_pattern_bad2.v
new file mode 100644
index 000000000..5401630bc
--- /dev/null
+++ b/test_regress/t/t_array_pattern_bad2.v
@@ -0,0 +1,25 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2018 by Wilson Snyder.
+// SPDX-License-Identifier: CC0-1.0
+
+// bug1364
+
+module t (/*AUTOARG*/
+   // Inputs
+   clk, res
+   );
+   input clk;
+   input res;
+
+    typedef struct packed {
+        logic [3:0] port_num;
+    } info_t;
+
+    info_t myinfo;
+    always_comb
+      myinfo = '{default: '0,
+                 default: '1};  // Bad
+
+endmodule
diff --git a/test_regress/t/t_array_query_with.pl b/test_regress/t/t_array_query_with.pl
index c505d6263..a86f4c404 100755
--- a/test_regress/t/t_array_query_with.pl
+++ b/test_regress/t/t_array_query_with.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_array_query_with.v b/test_regress/t/t_array_query_with.v
index 423670b00..bb4fa6137 100644
--- a/test_regress/t/t_array_query_with.v
+++ b/test_regress/t/t_array_query_with.v
@@ -19,19 +19,19 @@ module t (/*AUTOARG*/
       return found.size() == 1;
    endfunction
 
-   function bit test_find_index;
+   function static bit test_find_index;
       int    q[$] = {1, 2, 3, 4};
       int    found[$] = q.find_index(x) with (x <= 2);
       return found.size() == 2;
    endfunction
 
-   function bit test_find_first_index;
+   function static bit test_find_first_index;
       int    q[] = {1, 2, 3, 4, 5, 6};
       int    first_even_idx[$] = q.find_first_index(x) with (x % 2 == 0);
       return first_even_idx[0] == 1;
    endfunction
 
-   function bit test_sort;
+   function automatic bit test_sort;
       int    q[] = {-5, 2, -3, 0, 4};
       q.sort(x) with (x >= 0 ? x : -x);
       return q[1] == 2;
diff --git a/test_regress/t/t_assert_clock_event_unsup.pl b/test_regress/t/t_assert_clock_event_unsup.pl
index f201521f0..d188a4276 100755
--- a/test_regress/t/t_assert_clock_event_unsup.pl
+++ b/test_regress/t/t_assert_clock_event_unsup.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
@@ -11,8 +11,8 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 scenarios(vlt => 1);
 
 compile(
-    expect_filename=>$Self->{golden_filename},
-    verilator_flags2=> ['--assert'],
+    expect_filename => $Self->{golden_filename},
+    verilator_flags2 => ['--assert'],
     fails => 1,
     );
 
diff --git a/test_regress/t/t_assert_disable_bad.pl b/test_regress/t/t_assert_disable_bad.pl
index f201521f0..efe818bd1 100755
--- a/test_regress/t/t_assert_disable_bad.pl
+++ b/test_regress/t/t_assert_disable_bad.pl
@@ -11,8 +11,8 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 scenarios(vlt => 1);
 
 compile(
-    expect_filename=>$Self->{golden_filename},
-    verilator_flags2=> ['--assert'],
+    expect_filename => $Self->{golden_filename},
+    verilator_flags2 => ['--assert'],
     fails => 1,
     );
 
diff --git a/test_regress/t/t_assert_named_property.pl b/test_regress/t/t_assert_named_property.pl
index c505d6263..a86f4c404 100755
--- a/test_regress/t/t_assert_named_property.pl
+++ b/test_regress/t/t_assert_named_property.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_assert_named_property.v b/test_regress/t/t_assert_named_property.v
index 63e4f6a33..43a41582f 100644
--- a/test_regress/t/t_assert_named_property.v
+++ b/test_regress/t/t_assert_named_property.v
@@ -54,8 +54,16 @@ module t (/*AUTOARG*/
         // Assertion should fail
         expected_fails += 1;
      end
+
+   logic out = 1;
+
+    property prop_a;
+        @(posedge clk) disable iff (cyc <= 10) out;
+    endproperty
+
    assert property(disable iff (cyc < 5) check_if_gt_5(cyc + 1));
    assert property(@(posedge clk) pass_assertion(cyc));
+   assert property (prop_a) else $error($sformatf("property check failed :assert: (False)"));
 
    always @(posedge clk) begin
       if (expected_fails == 2) begin
diff --git a/test_regress/t/t_assert_past.pl b/test_regress/t/t_assert_past.pl
index c505d6263..a86f4c404 100755
--- a/test_regress/t/t_assert_past.pl
+++ b/test_regress/t/t_assert_past.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_assert_property_untyped.pl b/test_regress/t/t_assert_property_untyped.pl
index c505d6263..a86f4c404 100755
--- a/test_regress/t/t_assert_property_untyped.pl
+++ b/test_regress/t/t_assert_property_untyped.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_assert_property_untyped_unsup.pl b/test_regress/t/t_assert_property_untyped_unsup.pl
index f201521f0..d188a4276 100755
--- a/test_regress/t/t_assert_property_untyped_unsup.pl
+++ b/test_regress/t/t_assert_property_untyped_unsup.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
@@ -11,8 +11,8 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 scenarios(vlt => 1);
 
 compile(
-    expect_filename=>$Self->{golden_filename},
-    verilator_flags2=> ['--assert'],
+    expect_filename => $Self->{golden_filename},
+    verilator_flags2 => ['--assert'],
     fails => 1,
     );
 
diff --git a/test_regress/t/t_assert_recursive_property_unsup.pl b/test_regress/t/t_assert_recursive_property_unsup.pl
index f201521f0..15b4f4a73 100755
--- a/test_regress/t/t_assert_recursive_property_unsup.pl
+++ b/test_regress/t/t_assert_recursive_property_unsup.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_assert_sampled.pl b/test_regress/t/t_assert_sampled.pl
index c505d6263..a86f4c404 100755
--- a/test_regress/t/t_assert_sampled.pl
+++ b/test_regress/t/t_assert_sampled.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_assoc2.v b/test_regress/t/t_assoc2.v
index 5b94ca3b9..7ceff9c25 100644
--- a/test_regress/t/t_assoc2.v
+++ b/test_regress/t/t_assoc2.v
@@ -21,7 +21,7 @@ module t (/*AUTOARG*/
    // associative array of an associative array
    logic [31:0] a [logic [31:0]][logic [63:0]];
 
-   task disp();
+   task static disp();
       int i = 60;
       imap[i++] = 600;
       imap[i++] = 601;
diff --git a/test_regress/t/t_assoc_compare.pl b/test_regress/t/t_assoc_compare.pl
new file mode 100755
index 000000000..9a15dd2cc
--- /dev/null
+++ b/test_regress/t/t_assoc_compare.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 2019 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_assoc_compare.v b/test_regress/t/t_assoc_compare.v
new file mode 100644
index 000000000..1311b7cab
--- /dev/null
+++ b/test_regress/t/t_assoc_compare.v
@@ -0,0 +1,67 @@
+// DESCRIPTION: Verilator: Check == and != operations performed on associative arrays
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2023 by Ilya Barkov.
+// SPDX-License-Identifier: CC0-1.0
+
+`define stop $stop
+`define check_comp(lhs, rhs, op, exp) if ((exp) != ((lhs) op (rhs))) begin $write("%%Error: %s:%0d: op comparison shall return 'b%x\n", `__FILE__, `__LINE__, (exp)); `stop; end
+// Two checks because == and != may not be derived from each other
+`define check_eq(lhs, rhs) `check_comp(lhs, rhs, ==, 1'b1) `check_comp(lhs, rhs, !=, 1'b0)
+`define check_ne(lhs, rhs) `check_comp(lhs, rhs, ==, 1'b0) `check_comp(lhs, rhs, !=, 1'b1)
+
+class Cls;
+   int i;
+endclass
+
+module t;
+   initial begin
+      begin // simple case
+         int assoc1[int];
+         int assoc2[int];
+         // Empty are equal
+         `check_eq(assoc1, assoc2)
+         // Make different
+         assoc1[10] = 15;
+         assoc2[-1] = 365;
+         `check_ne(assoc1, assoc2)
+         // Make same
+         assoc1[-1] = 365;
+         assoc2[10] = 15;
+         `check_eq(assoc1, assoc2)
+         // Don't actually change
+         assoc1[-1] = 365;
+         `check_eq(assoc1, assoc2)
+         // Compare different sizes
+         assoc1[3] = 0;
+         `check_ne(assoc1, assoc2)
+      end
+      begin // check that a class as key is fine
+         int assoc1[Cls];
+         int assoc2[Cls];
+         Cls a = new;
+         Cls b = new;
+         int t;
+         assoc1[a] = 0;
+         `check_ne(assoc1, assoc2)
+         assoc2[a] = 0;
+         `check_eq(assoc1, assoc2)
+         assoc2.delete(a);
+         assoc2[b] = 0;
+         `check_ne(assoc1, assoc2)
+      end
+      begin // check that a class as value is fine
+         Cls assoc1[int];
+         Cls assoc2[int];
+         Cls a = new;
+         Cls b = new;
+         assoc1[1] = a;
+         assoc2[1] = b;
+         `check_ne(assoc1, assoc2)
+         assoc2[1] = a;
+         `check_eq(assoc1, assoc2)
+      end
+      $write("*-* All Finished *-*\n");
+      $finish;
+   end
+endmodule
diff --git a/test_regress/t/t_bigmem_bad.pl b/test_regress/t/t_bigmem_bad.pl
index 8e592a491..66a4e492d 100755
--- a/test_regress/t/t_bigmem_bad.pl
+++ b/test_regress/t/t_bigmem_bad.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2021 by filamoon. This program is free software; you can
+# Copyright 2021 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.
diff --git a/test_regress/t/t_bitsel_wire_array_bad.pl b/test_regress/t/t_bitsel_wire_array_bad.pl
index 2d59ce73a..af94708c0 100755
--- a/test_regress/t/t_bitsel_wire_array_bad.pl
+++ b/test_regress/t/t_bitsel_wire_array_bad.pl
@@ -10,7 +10,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 
 scenarios(linter => 1);
 
-# Comple time only test
+# Compile time only test
 
 lint(
     fails => 1,
diff --git a/test_regress/t/t_case_enum_emptyish.pl b/test_regress/t/t_case_enum_emptyish.pl
new file mode 100755
index 000000000..7d49cd2cd
--- /dev/null
+++ b/test_regress/t/t_case_enum_emptyish.pl
@@ -0,0 +1,22 @@
+#!/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(
+    verilator_flags2 => ["--compiler msvc"],  # We have deep expressions we want to test
+    );
+
+execute(
+    check_finished => 1,
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_case_enum_emptyish.v b/test_regress/t/t_case_enum_emptyish.v
new file mode 100644
index 000000000..0dbeb259a
--- /dev/null
+++ b/test_regress/t/t_case_enum_emptyish.v
@@ -0,0 +1,29 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2023 by Wilson Snyder.
+// SPDX-License-Identifier: CC0-1.0
+
+module t (/*AUTOARG*/);
+
+   enum logic [2:0] {
+          e0,
+          e1,
+          e2,
+	  e3
+        } EN;
+
+   initial begin
+
+      unique case (EN)
+        e0 :;
+        e1 :;
+        e2 :;
+        e3 :;
+      endcase
+
+      $write("*-* All Finished *-*\n");
+      $finish;
+   end
+
+endmodule
diff --git a/test_regress/t/t_case_incrdecr.v b/test_regress/t/t_case_incrdecr.v
index 4b3e6e2fc..fe415616e 100644
--- a/test_regress/t/t_case_incrdecr.v
+++ b/test_regress/t/t_case_incrdecr.v
@@ -1,3 +1,9 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2022 by Wilson Snyder.
+// SPDX-License-Identifier: CC0-1.0
+
 module t
   (/*AUTOARG*/
    // Inputs
diff --git a/test_regress/t/t_class_assign_bad.pl b/test_regress/t/t_class_assign_bad.pl
index b59a5c675..430290c0a 100755
--- a/test_regress/t/t_class_assign_bad.pl
+++ b/test_regress/t/t_class_assign_bad.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_class_compare.pl b/test_regress/t/t_class_compare.pl
new file mode 100755
index 000000000..9a15dd2cc
--- /dev/null
+++ b/test_regress/t/t_class_compare.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 2019 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_compare.v b/test_regress/t/t_class_compare.v
new file mode 100644
index 000000000..ee4826725
--- /dev/null
+++ b/test_regress/t/t_class_compare.v
@@ -0,0 +1,27 @@
+// DESCRIPTION: Verilator: Check == and != operations performed on class objects
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2023 by Ilya Barkov.
+// SPDX-License-Identifier: CC0-1.0
+
+`define stop $stop
+`define check_comp(lhs, rhs, op, exp) if ((exp) != ((lhs) op (rhs))) begin $write("%%Error: %s:%0d: op comparison shall return 'b%x\n", `__FILE__, `__LINE__, (exp)); `stop; end
+// Two checks because == and != may not be derived from each other
+`define check_eq(lhs, rhs) `check_comp(lhs, rhs, ==, 1'b1) `check_comp(lhs, rhs, !=, 1'b0)
+`define check_ne(lhs, rhs) `check_comp(lhs, rhs, ==, 1'b0) `check_comp(lhs, rhs, !=, 1'b1)
+
+class Cls;
+   int i;
+endclass
+
+module t;
+   initial begin
+      Cls a = new;
+      Cls b = new;
+      `check_ne(a, b)
+      a = b;
+      `check_eq(a, b)
+      $write("*-* All Finished *-*\n");
+      $finish;
+   end
+endmodule
diff --git a/test_regress/t/t_class_fwd_cc.pl b/test_regress/t/t_class_fwd_cc.pl
index 7314796b8..aca1cb3c1 100755
--- a/test_regress/t/t_class_fwd_cc.pl
+++ b/test_regress/t/t_class_fwd_cc.pl
@@ -2,6 +2,10 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
+# Copyright 2023 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);
diff --git a/test_regress/t/t_class_member_sens.pl b/test_regress/t/t_class_member_sens.pl
index cf6d969a8..cff05f43a 100755
--- a/test_regress/t/t_class_member_sens.pl
+++ b/test_regress/t/t_class_member_sens.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_class_membersel_int.pl b/test_regress/t/t_class_membersel_int.pl
new file mode 100755
index 000000000..859050d63
--- /dev/null
+++ b/test_regress/t/t_class_membersel_int.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 2023 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_membersel_int.v b/test_regress/t/t_class_membersel_int.v
new file mode 100644
index 000000000..a0367f11d
--- /dev/null
+++ b/test_regress/t/t_class_membersel_int.v
@@ -0,0 +1,24 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2023 by Wilson Snyder.
+// SPDX-License-Identifier: CC0-1.0
+
+class Cls;
+   int t;
+endclass
+
+module Sub;
+   Cls c;
+   initial begin
+      int i;
+      c = new;
+      i = c.t;
+      $write("*-* All Finished *-*\n");
+      $finish;
+   end
+endmodule
+
+module t;
+   Sub foo;
+endmodule
diff --git a/test_regress/t/t_class_new_return.pl b/test_regress/t/t_class_new_return.pl
index bf4e4ce9f..1aa73f80a 100755
--- a/test_regress/t/t_class_new_return.pl
+++ b/test_regress/t/t_class_new_return.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
@@ -10,7 +10,8 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 
 scenarios(simulator => 1);
 
-compile();
+compile(
+    );
 
 execute(
     check_finished => 1,
diff --git a/test_regress/t/t_class_param.v b/test_regress/t/t_class_param.v
index 99740abb7..5dfa4ee20 100644
--- a/test_regress/t/t_class_param.v
+++ b/test_regress/t/t_class_param.v
@@ -45,6 +45,15 @@ endclass
 
 typedef Cls#(8) Cls8_t;
 
+class SelfRefClassTypeParam #(type T=logic);
+   typedef SelfRefClassTypeParam #(int) self_int_t;
+   T field;
+endclass
+
+class SelfRefClassIntParam #(int P=1);
+   typedef SelfRefClassIntParam #(10) self_int_t;
+endclass
+
 module t (/*AUTOARG*/);
 
    Cls c12;
@@ -52,12 +61,20 @@ module t (/*AUTOARG*/);
    Cls8_t c8;
    Wrap #(.P(16)) w16;
    Wrap2 #(.P(32)) w32;
+   SelfRefClassTypeParam src_logic;
+   SelfRefClassTypeParam::self_int_t src_int;
+   SelfRefClassIntParam src1;
+   SelfRefClassIntParam::self_int_t src10;
    initial begin
       c12 = new;
       c4 = new;
       c8 = new;
       w16 = new;
       w32 = new;
+      src_int = new;
+      src_logic = new;
+      src1 = new;
+      src10 = new;
       if (Cls#()::PBASE != 12) $stop;
       if (Cls#(4)::PBASE != 4) $stop;
       if (Cls8_t::PBASE != 8) $stop;
@@ -92,6 +109,11 @@ module t (/*AUTOARG*/);
       `checks($sformatf("%p", c12), "'{member:'haaa}");
       `checks($sformatf("%p", c4), "'{member:'ha}");
 
+      if ($bits(src_logic.field) != 1) $stop;
+      if ($bits(src_int.field) != 32) $stop;
+      if (src1.P != 1) $stop;
+      if (src10.P != 10) $stop;
+
       $write("*-* All Finished *-*\n");
       $finish;
    end
diff --git a/test_regress/t/t_class_param_bad2.pl b/test_regress/t/t_class_param_bad2.pl
index 19ba90d40..44783b1f6 100755
--- a/test_regress/t/t_class_param_bad2.pl
+++ b/test_regress/t/t_class_param_bad2.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_class_param_mod.v b/test_regress/t/t_class_param_mod.v
index a57ba7316..e117fa2ec 100644
--- a/test_regress/t/t_class_param_mod.v
+++ b/test_regress/t/t_class_param_mod.v
@@ -45,17 +45,34 @@ endclass
 
    typedef Cls#(8) Cls8_t;
 
+class SelfRefClassTypeParam #(type T=logic);
+   typedef SelfRefClassTypeParam #(int) self_int_t;
+   T field;
+endclass
+
+class SelfRefClassIntParam #(int P=1);
+   typedef SelfRefClassIntParam #(10) self_int_t;
+endclass
+
    Cls c12;
    Cls #(.PBASE(4)) c4;
    Cls8_t c8;
    Wrap #(.P(16)) w16;
    Wrap2 #(.P(32)) w32;
+   SelfRefClassTypeParam src_logic;
+   SelfRefClassTypeParam::self_int_t src_int;
+   SelfRefClassIntParam src1;
+   SelfRefClassIntParam::self_int_t src10;
    initial begin
       c12 = new;
       c4 = new;
       c8 = new;
       w16 = new;
       w32 = new;
+      src_int = new;
+      src_logic = new;
+      src1 = new;
+      src10 = new;
       if (Cls#()::PBASE != 12) $stop;
       if (Cls#(4)::PBASE != 4) $stop;
       if (Cls8_t::PBASE != 8) $stop;
@@ -90,6 +107,11 @@ endclass
       `checks($sformatf("%p", c12), "'{member:'haaa}");
       `checks($sformatf("%p", c4), "'{member:'ha}");
 
+      if ($bits(src_logic.field) != 1) $stop;
+      if ($bits(src_int.field) != 32) $stop;
+      if (src1.P != 1) $stop;
+      if (src10.P != 10) $stop;
+
       $write("*-* All Finished *-*\n");
       $finish;
    end
diff --git a/test_regress/t/t_class_virtual_chain_ctor.pl b/test_regress/t/t_class_virtual_chain_ctor.pl
new file mode 100755
index 000000000..5b8136393
--- /dev/null
+++ b/test_regress/t/t_class_virtual_chain_ctor.pl
@@ -0,0 +1,16 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2023 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();
+
+ok(1);
+1;
diff --git a/test_regress/t/t_class_virtual_chain_ctor.v b/test_regress/t/t_class_virtual_chain_ctor.v
new file mode 100644
index 000000000..53a1b4ec8
--- /dev/null
+++ b/test_regress/t/t_class_virtual_chain_ctor.v
@@ -0,0 +1,34 @@
+// DESCRIPTION: Verilator: Check that an abstract class' contstructor
+// can be called indirectly from a constructor of a derived class.
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2023 by Ilya Barkov
+// SPDX-License-Identifier: CC0-1.0
+
+// It's illegal to call
+//     VBase b = new;
+// see t_class_virtual_bad
+virtual class VBase;
+   function new(); endfunction
+endclass
+
+// Another constructor of an abstact class in the chain
+virtual class VChild1 extends VBase;
+   function new();
+      super.new();
+   endfunction
+endclass
+
+// It shall be perfectly fine to create an instance of a
+// non-abstract VChild2
+class VChild2 extends VChild1;
+   function new();
+      super.new();
+   endfunction
+endclass
+
+module t;
+   initial begin
+      VChild2 c = new;
+   end
+endmodule
diff --git a/test_regress/t/t_clk_2in.cpp b/test_regress/t/t_clk_2in.cpp
index fc5a0233f..a314d43a6 100644
--- a/test_regress/t/t_clk_2in.cpp
+++ b/test_regress/t/t_clk_2in.cpp
@@ -29,13 +29,14 @@ void clockit(int clk1, int clk0) {
 }
 
 int main(int argc, char* argv[]) {
+    Verilated::debug(0);
+    Verilated::commandArgs(argc, argv);
+
     topp = new VM_PREFIX;
     topp->check = 0;
     clockit(0, 0);
     main_time += 10;
 
-    Verilated::debug(0);
-
     for (int i = 0; i < 2; i++) {
         clockit(0, 0);
         clockit(0, 1);
diff --git a/test_regress/t/t_clk_gate_ext.v b/test_regress/t/t_clk_gate_ext.v
index 170ce63e6..5f50801bf 100644
--- a/test_regress/t/t_clk_gate_ext.v
+++ b/test_regress/t/t_clk_gate_ext.v
@@ -1,3 +1,9 @@
+// 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(/*AUTOARG*/
    // Inputs
    clk
diff --git a/test_regress/t/t_clk_inp_init.pl b/test_regress/t/t_clk_inp_init.pl
index a55bf1710..7a546294f 100755
--- a/test_regress/t/t_clk_inp_init.pl
+++ b/test_regress/t/t_clk_inp_init.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2018 by Argon Design. This program is free software; you
+# Copyright 2018 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.
diff --git a/test_regress/t/t_clocking_bad1.out b/test_regress/t/t_clocking_bad1.out
new file mode 100644
index 000000000..214ae7a0d
--- /dev/null
+++ b/test_regress/t/t_clocking_bad1.out
@@ -0,0 +1,5 @@
+%Error: t/t_clocking_bad1.v:16:12: Only one default clocking block allowed per module (IEEE 1800-2017 14.12)
+                                 : ... In instance t
+   16 |    default clocking @(posedge clk);
+      |            ^~~~~~~~
+%Error: Exiting due to
diff --git a/test_regress/t/t_clocking_bad1.pl b/test_regress/t/t_clocking_bad1.pl
new file mode 100755
index 000000000..8ab3c0995
--- /dev/null
+++ b/test_regress/t/t_clocking_bad1.pl
@@ -0,0 +1,20 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 by Antmicro Ltd. 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(
+    verilator_flags2 => ["--timing"],
+    fails => 1,
+    expect_filename => $Self->{golden_filename},
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_clocking_bad1.v b/test_regress/t/t_clocking_bad1.v
new file mode 100644
index 000000000..306b502f6
--- /dev/null
+++ b/test_regress/t/t_clocking_bad1.v
@@ -0,0 +1,18 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2022 by Antmicro Ltd.
+// SPDX-License-Identifier: CC0-1.0
+
+module t(/*AUTOARG*/
+   // Inputs
+   clk
+   );
+   input clk;
+
+   default clocking @(posedge clk);
+   endclocking
+
+   default clocking @(posedge clk);
+   endclocking
+endmodule
diff --git a/test_regress/t/t_clocking_bad2.out b/test_regress/t/t_clocking_bad2.out
new file mode 100644
index 000000000..5d32295d1
--- /dev/null
+++ b/test_regress/t/t_clocking_bad2.out
@@ -0,0 +1,16 @@
+%Error: t/t_clocking_bad2.v:15:32: 1step not allowed as output skew
+   15 |        default input #1 output #1step;
+      |                                ^
+%Error: t/t_clocking_bad2.v:16:23: Multiple default input skews not allowed
+   16 |        default input #2 output #2;
+      |                       ^
+%Error: t/t_clocking_bad2.v:16:33: Multiple default output skews not allowed
+   16 |        default input #2 output #2;
+      |                                 ^
+%Error: t/t_clocking_bad2.v:17:15: 1step not allowed as output skew
+   17 |        output #1step out;
+      |               ^
+%Error: t/t_clocking_bad2.v:18:8: Multiple clockvars with the same name not allowed
+   18 |        output out;
+      |        ^~~~~~
+%Error: Exiting due to
diff --git a/test_regress/t/t_clocking_bad2.pl b/test_regress/t/t_clocking_bad2.pl
new file mode 100755
index 000000000..8ab3c0995
--- /dev/null
+++ b/test_regress/t/t_clocking_bad2.pl
@@ -0,0 +1,20 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 by Antmicro Ltd. 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(
+    verilator_flags2 => ["--timing"],
+    fails => 1,
+    expect_filename => $Self->{golden_filename},
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_clocking_bad2.v b/test_regress/t/t_clocking_bad2.v
new file mode 100644
index 000000000..7d5581415
--- /dev/null
+++ b/test_regress/t/t_clocking_bad2.v
@@ -0,0 +1,20 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2022 by Antmicro Ltd.
+// SPDX-License-Identifier: CC0-1.0
+
+module t(/*AUTOARG*/
+   // Inputs
+   clk
+   );
+   input clk;
+
+   logic in, out;
+   clocking cb @(posedge clk);
+       default input #1 output #1step;
+       default input #2 output #2;
+       output #1step out;
+       output out;
+   endclocking
+endmodule
diff --git a/test_regress/t/t_clocking_bad3.out b/test_regress/t/t_clocking_bad3.out
new file mode 100644
index 000000000..8202621e3
--- /dev/null
+++ b/test_regress/t/t_clocking_bad3.out
@@ -0,0 +1,13 @@
+%Error: t/t_clocking_bad3.v:14:14: Corresponding variable 'in' does not exist
+   14 |        input in;
+      |              ^~
+%Error: t/t_clocking_bad3.v:15:15: Corresponding variable 'out' does not exist
+   15 |        output out;
+      |               ^~~
+%Error: t/t_clocking_bad3.v:18:13: Duplicate declaration of CLOCKING 'cb': 'cb'
+   18 |    clocking cb @(posedge clk);
+      |             ^~
+        t/t_clocking_bad3.v:13:13: ... Location of original declaration
+   13 |    clocking cb @(posedge clk);
+      |             ^~
+%Error: Exiting due to
diff --git a/test_regress/t/t_clocking_bad3.pl b/test_regress/t/t_clocking_bad3.pl
new file mode 100755
index 000000000..8ab3c0995
--- /dev/null
+++ b/test_regress/t/t_clocking_bad3.pl
@@ -0,0 +1,20 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 by Antmicro Ltd. 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(
+    verilator_flags2 => ["--timing"],
+    fails => 1,
+    expect_filename => $Self->{golden_filename},
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_clocking_bad3.v b/test_regress/t/t_clocking_bad3.v
new file mode 100644
index 000000000..a7949e4a0
--- /dev/null
+++ b/test_regress/t/t_clocking_bad3.v
@@ -0,0 +1,20 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2022 by Antmicro Ltd.
+// SPDX-License-Identifier: CC0-1.0
+
+module t(/*AUTOARG*/
+   // Inputs
+   clk
+   );
+   input clk;
+
+   clocking cb @(posedge clk);
+       input in;
+       output out;
+   endclocking
+
+   clocking cb @(posedge clk);
+   endclocking
+endmodule
diff --git a/test_regress/t/t_clocking_bad4.out b/test_regress/t/t_clocking_bad4.out
new file mode 100644
index 000000000..b5702e561
--- /dev/null
+++ b/test_regress/t/t_clocking_bad4.out
@@ -0,0 +1,45 @@
+%Error: t/t_clocking_bad4.v:23:15: Skew must be constant (IEEE 1800-2017 14.4)
+                                 : ... In instance t
+   23 |        input #cyc in;
+      |               ^~~
+%Error: t/t_clocking_bad4.v:24:16: Skew cannot be negative
+                                 : ... In instance t
+   24 |        input #(-1) out;
+      |                ^
+%Error: t/t_clocking_bad4.v:31:11: Usage of cycle delays requires default clocking (IEEE 1800-2017 14.11)
+                                 : ... In instance t
+   31 |    always ##1;
+      |           ^~
+%Error: t/t_clocking_bad4.v:32:15: Only non-blocking assignments can write to clockvars (IEEE 1800-2017 14.16)
+                                 : ... In instance t
+   32 |    always cb1.out = clk;
+      |               ^~~
+%Error: t/t_clocking_bad4.v:33:15: Only non-blocking assignments can write to clockvars (IEEE 1800-2017 14.16)
+                                 : ... In instance t
+   33 |    assign cb1.out = clk;
+      |               ^~~
+%Error: t/t_clocking_bad4.v:34:21: Only non-blocking assignments can write to clockvars (IEEE 1800-2017 14.16)
+                                 : ... In instance t
+   34 |    always write(cb1.out);
+      |                     ^~~
+%Error: t/t_clocking_bad4.v:35:22: Event controls cannot be used in synchronous drives (IEEE 1800-2017 14.16)
+                                 : ... In instance t
+   35 |    always cb1.out <= @(posedge clk) 1;
+      |                      ^
+%Error: t/t_clocking_bad4.v:36:22: Only cycle delays can be used in synchronous drives (IEEE 1800-2017 14.16)
+                                 : ... In instance t
+   36 |    always cb1.out <= #1 1;
+      |                      ^
+%Error: t/t_clocking_bad4.v:37:18: Cycle delays not allowed as intra-assignment delays (IEEE 1800-2017 14.11)
+                                 : ... In instance t
+   37 |    always out <= ##1 1;
+      |                  ^~
+%Error: t/t_clocking_bad4.v:40:12: Cannot write to input clockvar (IEEE 1800-2017 14.3)
+                                 : ... In instance t
+   40 |        cb1.in = 1;
+      |            ^~
+%Error: t/t_clocking_bad4.v:41:21: Cannot read from output clockvar (IEEE 1800-2017 14.3)
+                                 : ... In instance t
+   41 |        $display(cb1.out);
+      |                     ^~~
+%Error: Exiting due to
diff --git a/test_regress/t/t_clocking_bad4.pl b/test_regress/t/t_clocking_bad4.pl
new file mode 100755
index 000000000..8ab3c0995
--- /dev/null
+++ b/test_regress/t/t_clocking_bad4.pl
@@ -0,0 +1,20 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 by Antmicro Ltd. 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(
+    verilator_flags2 => ["--timing"],
+    fails => 1,
+    expect_filename => $Self->{golden_filename},
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_clocking_bad4.v b/test_regress/t/t_clocking_bad4.v
new file mode 100644
index 000000000..58707a1af
--- /dev/null
+++ b/test_regress/t/t_clocking_bad4.v
@@ -0,0 +1,43 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2022 by Antmicro Ltd.
+// SPDX-License-Identifier: CC0-1.0
+
+module t(/*AUTOARG*/
+   // Inputs
+   clk
+   );
+   input clk;
+
+   logic in, out;
+   clocking cb1 @(posedge clk);
+       input in;
+       output out;
+   endclocking
+
+   int cyc = 0;
+   always @(posedge clk) cyc <= cyc + 1;
+
+   clocking cb2 @(negedge clk);
+       input #cyc in;
+       input #(-1) out;
+   endclocking
+
+   task write(output x);
+       x = 1;
+   endtask
+
+   always ##1;
+   always cb1.out = clk;
+   assign cb1.out = clk;
+   always write(cb1.out);
+   always cb1.out <= @(posedge clk) 1;
+   always cb1.out <= #1 1;
+   always out <= ##1 1;
+
+   always @(posedge clk) begin
+       cb1.in = 1;
+       $display(cb1.out);
+   end
+endmodule
diff --git a/test_regress/t/t_clocking_concat.pl b/test_regress/t/t_clocking_concat.pl
new file mode 100755
index 000000000..1aa73f80a
--- /dev/null
+++ b/test_regress/t/t_clocking_concat.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 2022 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_clocking_concat.v b/test_regress/t/t_clocking_concat.v
new file mode 100644
index 000000000..027264dad
--- /dev/null
+++ b/test_regress/t/t_clocking_concat.v
@@ -0,0 +1,37 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2022 by Antmicro Ltd.
+// SPDX-License-Identifier: CC0-1.0
+
+module t (/*AUTOARG*/
+   // Inputs
+   clk
+   );
+   input clk;
+
+   logic[3:0] D1, D2, Q1, Q2;
+   always @(posedge clk) begin
+       {Q1, Q2} <= {D1, D2};
+   end
+
+   always @(posedge clk) $display("[%0t] posedge clk", $time);
+
+   clocking cb @(posedge clk);
+      input #0 Q = {Q1, Q2};
+      output #0 D = {D1, D2};
+   endclocking
+
+   initial $monitor("[%0t] --> D=%x\t\tQ=%x\t\tcb.Q=%x", $time, {D1,D2}, {Q1,Q2}, cb.Q);
+
+   int cyc = 0;
+   always @ (posedge clk) begin
+       cyc <= cyc + 1;
+       if (cyc > 1 && cb.Q != {D1 - 4'd1, D2 - 4'd1}) $stop;
+       cb.D <= {D1 + 4'd1, D2 + 4'd1};
+       if (cyc==10) begin
+          $write("*-* All Finished *-*\n");
+          $finish;
+       end
+   end
+endmodule
diff --git a/test_regress/t/t_clocking_notiming.out b/test_regress/t/t_clocking_notiming.out
new file mode 100644
index 000000000..4a304c9d9
--- /dev/null
+++ b/test_regress/t/t_clocking_notiming.out
@@ -0,0 +1,6 @@
+%Error-NOTIMING: t/t_clocking_notiming.v:11:8: Clocking output skew greater than #0 requires --timing
+                                             : ... In instance t
+   11 |        output #1 out;
+      |        ^~~~~~
+                 ... For error description see https://verilator.org/warn/NOTIMING?v=latest
+%Error: Exiting due to
diff --git a/test_regress/t/t_clocking_notiming.pl b/test_regress/t/t_clocking_notiming.pl
new file mode 100755
index 000000000..5a683788e
--- /dev/null
+++ b/test_regress/t/t_clocking_notiming.pl
@@ -0,0 +1,20 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 by Antmicro Ltd. 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(
+    verilator_flags2 => ["--no-timing"],
+    fails => 1,
+    expect_filename => $Self->{golden_filename},
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_clocking_notiming.v b/test_regress/t/t_clocking_notiming.v
new file mode 100644
index 000000000..1c718fda8
--- /dev/null
+++ b/test_regress/t/t_clocking_notiming.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, 2022 by Antmicro Ltd.
+// SPDX-License-Identifier: CC0-1.0
+
+module t;
+   logic clk;
+   logic out;
+   clocking cb @(posedge clk);
+       output #1 out;
+   endclocking
+endmodule
diff --git a/test_regress/t/t_clocking_sched.out b/test_regress/t/t_clocking_sched.out
new file mode 100644
index 000000000..8ae143c29
--- /dev/null
+++ b/test_regress/t/t_clocking_sched.out
@@ -0,0 +1,55 @@
+0 | posedge
+0 | cb.y=0
+0 | b=0
+0 | x<=0
+0 | y=0
+0 | c<=0
+0 | c<=1
+0 | cb.a=1
+0 | cb.b=1
+0 | posedge
+0 | x<=1
+0 | y=1
+0 | c<=0
+0 | cb.a=0
+0 | cb.b=1
+0 | cb.y=1
+0 | b=1
+0 | x<=0
+0 | y=0
+0 | 0 1 0 0 0 0
+20 | posedge
+20 | c<=1
+20 | cb.a=1
+20 | cb.b=1
+20 | cb.y=0
+20 | b=0
+20 | posedge
+20 | x<=1
+20 | y=1
+20 | c<=0
+20 | cb.a=0
+20 | cb.b=1
+20 | cb.y=1
+20 | b=1
+20 | x<=0
+20 | y=0
+20 | 0 1 0 0 0 0
+30 | posedge
+30 | c<=1
+30 | cb.a=1
+30 | cb.b=1
+30 | cb.y=0
+30 | b=0
+30 | posedge
+30 | x<=1
+30 | y=1
+30 | c<=0
+30 | cb.a=0
+30 | cb.b=1
+30 | cb.y=1
+30 | b=1
+30 | x<=0
+30 | y=0
+30 | 0 1 0 0 0 0
+*-* All Finished *-*
diff --git a/test_regress/t/t_clocking_sched.pl b/test_regress/t/t_clocking_sched.pl
new file mode 100755
index 000000000..f071267de
--- /dev/null
+++ b/test_regress/t/t_clocking_sched.pl
@@ -0,0 +1,22 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 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);
+
+compile(
+    );
+
+execute(
+    check_finished => 1,
+    expect_filename => $Self->{golden_filename}
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_clocking_sched.v b/test_regress/t/t_clocking_sched.v
new file mode 100644
index 000000000..44007f266
--- /dev/null
+++ b/test_regress/t/t_clocking_sched.v
@@ -0,0 +1,74 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2022 by Antmicro Ltd.
+// SPDX-License-Identifier: CC0-1.0
+
+module t (/*AUTOARG*/
+  // Inputs
+  clk
+  );
+  input clk;
+  int cyc = 0;
+
+  always @(negedge clk) begin  // negedge so there is nothing after $finish
+     cyc <= cyc + 1;
+     if (cyc == 2) begin
+        $write("*-* All Finished *-*\n");
+        $finish;
+     end
+  end
+
+  logic genclk = 0, a = 0, b = 1, c = 0, x = 0, y, z = 0;
+  always @(edge clk) genclk = clk;
+  always @(posedge genclk) $display("%0t | posedge", $time);
+
+  // Clocking block
+  clocking cb @(posedge genclk);
+    input #0 a, y;
+    input #1step b;
+    output #0 x;
+`ifdef VERILATOR_TIMING
+    output #2 z;
+`endif
+  endclocking
+
+  // Print after Observed
+  always @(posedge genclk) a = ~a;
+  always @cb $display("%0t | cb.a=%b", $time, cb.a);
+  always @cb $display("%0t | cb.b=%b", $time, cb.b);
+  always @cb.y $display("%0t | cb.y=%b", $time, cb.y);
+
+  // Retrigger everything after Observed
+  always @cb.a b = x;
+  always @b begin
+    $display("%0t | b=%b", $time, b);
+    if (b == 0) genclk = ~genclk;
+  end
+
+  // Do an NBA
+  always @(posedge genclk) c <= ~c;
+  always @c begin
+    $display("%0t | c<=%b", $time, c);
+  end
+
+  // Print after Re-NBA
+  always @(posedge genclk) cb.x <= ~x;
+  always @x $display("%0t | x<=%b", $time, x);
+
+  // Retrigger everything after Re-NBA
+  always @x y = x;
+  always @y begin
+    $display("%0t | y=%b", $time, y);
+    if (y == 1) genclk = ~genclk;
+  end
+
+`ifdef VERILATOR_TIMING
+  // Print after delay and Re-NBA
+  always @(posedge genclk) cb.z <= ~z;
+  always @z $display("%0t | z<=%b", $time, z);
+`endif
+
+  // Print in Postponed
+  always @(posedge genclk) $strobe("%0t | %b %b %b %b %b %b", $time, a, b, c, x, y, z);
+endmodule;
diff --git a/test_regress/t/t_clocking_sched_timing.out b/test_regress/t/t_clocking_sched_timing.out
new file mode 100644
index 000000000..f0fee8b8e
--- /dev/null
+++ b/test_regress/t/t_clocking_sched_timing.out
@@ -0,0 +1,58 @@
+0 | posedge
+0 | cb.y=0
+0 | b=0
+0 | z<=0
+0 | x<=0
+0 | y=0
+0 | c<=0
+0 | c<=1
+0 | cb.a=1
+0 | cb.b=1
+0 | posedge
+0 | x<=1
+0 | y=1
+0 | c<=0
+0 | cb.a=0
+0 | cb.b=1
+0 | cb.y=1
+0 | b=1
+0 | x<=0
+0 | y=0
+0 | 0 1 0 0 0 0
+2 | z<=1
+3 | posedge
+3 | c<=1
+3 | cb.a=1
+3 | cb.b=1
+3 | cb.y=0
+3 | b=0
+3 | posedge
+3 | x<=1
+3 | y=1
+3 | c<=0
+3 | cb.a=0
+3 | cb.b=1
+3 | cb.y=1
+3 | b=1
+3 | x<=0
+3 | y=0
+3 | 0 1 0 0 0 1
+5 | posedge
+5 | z<=0
+5 | c<=1
+5 | cb.a=1
+5 | cb.b=1
+5 | cb.y=0
+5 | b=0
+5 | posedge
+5 | x<=1
+5 | y=1
+5 | c<=0
+5 | cb.a=0
+5 | cb.b=1
+5 | cb.y=1
+5 | b=1
+5 | x<=0
+5 | y=0
+5 | 0 1 0 0 0 0
+*-* All Finished *-*
diff --git a/test_regress/t/t_clocking_sched_timing.pl b/test_regress/t/t_clocking_sched_timing.pl
new file mode 100755
index 000000000..7fe0b1dee
--- /dev/null
+++ b/test_regress/t/t_clocking_sched_timing.pl
@@ -0,0 +1,31 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 by Antmicro Ltd. 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);
+
+if (!$Self->have_coroutines) {
+    skip("No coroutine support");
+}
+else {
+    top_filename("t/t_clocking_sched.v");
+
+    compile(
+        timing_loop => 1,
+        verilator_flags2 => ["--timing"],
+        );
+
+    execute(
+        check_finished => 1,
+        expect_filename => $Self->{golden_filename}
+        );
+}
+
+ok(1);
+1;
diff --git a/test_regress/t/t_clocking_timing.v b/test_regress/t/t_clocking_timing.v
new file mode 100644
index 000000000..f918f5665
--- /dev/null
+++ b/test_regress/t/t_clocking_timing.v
@@ -0,0 +1,90 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2022 by Antmicro Ltd.
+// SPDX-License-Identifier: CC0-1.0
+
+`timescale 10ns/1ns
+
+`ifdef TEST_VERBOSE
+ `define WRITE_VERBOSE(args) $write args
+`else
+ `define WRITE_VERBOSE(args)
+`endif
+
+`ifndef TEST_WIDTH
+`define TEST_WIDTH 4
+`endif
+`ifndef TEST_BITS
+`define TEST_BITS 4*`TEST_WIDTH
+`endif
+
+`ifndef TEST_CLK_PERIOD
+`define TEST_CLK_PERIOD 10
+`endif
+`ifndef TEST_INPUT_SKEW
+`define TEST_INPUT_SKEW 2
+`endif
+`ifndef TEST_OUTPUT_SKEW
+`define TEST_OUTPUT_SKEW 6
+`endif
+`ifndef TEST_CYCLE_DELAY
+`define TEST_CYCLE_DELAY 4
+`endif
+
+module t;
+   typedef logic[`TEST_BITS-1:0] sig_t;
+   sig_t D, Q;
+   always @(posedge clk) Q <= D;
+
+   logic clk = 0;
+   always #(`TEST_CLK_PERIOD/2) clk = ~clk;
+
+   always @(posedge clk) `WRITE_VERBOSE(("[%0t] posedge clk\n", $time));
+
+   default clocking cb @(posedge clk);
+      default input #`TEST_INPUT_SKEW output #`TEST_OUTPUT_SKEW;
+      input Q;
+      output D;
+   endclocking
+
+`ifdef TEST_VERBOSE
+   initial $monitor("[%0t] --> D=%x\t\tQ=%x\t\tcb.Q=%x", $time, D, Q, cb.Q);
+`endif
+
+   always
+      begin
+         sig_t val = '0;
+         cb.D <= val;
+         for (int i = 0; i < 5; i++) begin ##(`TEST_CYCLE_DELAY+`TEST_OUTPUT_SKEW/`TEST_CLK_PERIOD+1)
+            val = {`TEST_WIDTH{(`TEST_BITS/`TEST_WIDTH)'('ha + i)}};
+            `WRITE_VERBOSE(("[%0t] cb.D <= ##%0d %x\n", $time, `TEST_CYCLE_DELAY, val));
+            cb.D <= ##(`TEST_CYCLE_DELAY) val;
+            fork
+                #(`TEST_CYCLE_DELAY*`TEST_CLK_PERIOD+`TEST_OUTPUT_SKEW-0.1) begin
+                    if (D == val) begin
+                        `WRITE_VERBOSE(("[%0t] D == %x == %x\n", $time, D, val));
+                        $stop;
+                    end
+                    if (cb.Q != D) begin
+                        `WRITE_VERBOSE(("[%0t] cb.Q == %x != %x\n", $time, cb.Q, D));
+                        $stop;
+                    end
+                end
+                #(`TEST_CYCLE_DELAY*`TEST_CLK_PERIOD+`TEST_OUTPUT_SKEW+0.1) begin
+                    if (D != val) begin
+                        `WRITE_VERBOSE(("[%0t] D == %x != %x\n", $time, D, val));
+                        $stop;
+                    end
+                    if (cb.Q == D) begin
+                        `WRITE_VERBOSE(("[%0t] cb.Q == %x == %x\n", $time, cb.Q, D));
+                        $stop;
+                    end
+                end
+            join_none
+         end
+         ##4
+         $write("*-* All Finished *-*\n");
+         $finish;
+      end
+endmodule
diff --git a/test_regress/t/t_clocking_timing1.pl b/test_regress/t/t_clocking_timing1.pl
new file mode 100755
index 000000000..ca8f6fa4e
--- /dev/null
+++ b/test_regress/t/t_clocking_timing1.pl
@@ -0,0 +1,30 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 by Antmicro Ltd. 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);
+
+if (!$Self->have_coroutines) {
+    skip("No coroutine support");
+}
+else {
+    top_filename("t/t_clocking_timing.v");
+
+    compile(
+        verilator_flags2 => ["--exe --main --timing"],
+        make_main => 0,
+        );
+
+    execute(
+        check_finished => 1,
+        );
+}
+
+ok(1);
+1;
diff --git a/test_regress/t/t_clocking_timing2.pl b/test_regress/t/t_clocking_timing2.pl
new file mode 100755
index 000000000..6dff6484b
--- /dev/null
+++ b/test_regress/t/t_clocking_timing2.pl
@@ -0,0 +1,30 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 by Antmicro Ltd. 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);
+
+if (!$Self->have_coroutines) {
+    skip("No coroutine support");
+}
+else {
+    top_filename("t/t_clocking_timing.v");
+
+    compile(
+        verilator_flags2 => ["--exe --main --timing -DTEST_INPUT_SKEW=12 -DTEST_OUTPUT_SKEW=16"],
+        make_main => 0,
+        );
+
+    execute(
+        check_finished => 1,
+        );
+}
+
+ok(1);
+1;
diff --git a/test_regress/t/t_clocking_unsup1.out b/test_regress/t/t_clocking_unsup1.out
new file mode 100644
index 000000000..1dce09ae4
--- /dev/null
+++ b/test_regress/t/t_clocking_unsup1.out
@@ -0,0 +1,23 @@
+%Error-UNSUPPORTED: t/t_clocking_unsup1.v:14:26: Unsupported: Mixed input/output clocking items
+   14 |        input #1 output #1step x;
+      |                          ^
+                    ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
+%Error-UNSUPPORTED: t/t_clocking_unsup1.v:15:8: Unsupported: 'inout' clocking items
+   15 |        inout y;
+      |        ^~~~~
+%Error-UNSUPPORTED: t/t_clocking_unsup1.v:16:15: Unsupported: clocking event edge override
+   16 |        output posedge #1 a;
+      |               ^~~~~~~
+%Error-UNSUPPORTED: t/t_clocking_unsup1.v:17:15: Unsupported: clocking event edge override
+   17 |        output negedge #1 b;
+      |               ^~~~~~~
+%Error-UNSUPPORTED: t/t_clocking_unsup1.v:18:15: Unsupported: clocking event edge override
+   18 |        output edge #1 b;
+      |               ^~~~
+%Error-UNSUPPORTED: t/t_clocking_unsup1.v:13:20: Unsupported: global clocking
+   13 |    global clocking cb @(posedge clk);
+      |                    ^~
+%Error-UNSUPPORTED: t/t_clocking_unsup1.v:21:11: Unsupported: global clocking
+   21 |    global clocking @(posedge clk);
+      |           ^~~~~~~~
+%Error: Exiting due to
diff --git a/test_regress/t/t_clocking_unsup1.pl b/test_regress/t/t_clocking_unsup1.pl
new file mode 100755
index 000000000..8ab3c0995
--- /dev/null
+++ b/test_regress/t/t_clocking_unsup1.pl
@@ -0,0 +1,20 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 by Antmicro Ltd. 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(
+    verilator_flags2 => ["--timing"],
+    fails => 1,
+    expect_filename => $Self->{golden_filename},
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_clocking_unsup1.v b/test_regress/t/t_clocking_unsup1.v
new file mode 100644
index 000000000..0eac13dc7
--- /dev/null
+++ b/test_regress/t/t_clocking_unsup1.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, 2022 by Antmicro Ltd.
+// SPDX-License-Identifier: CC0-1.0
+
+module t(/*AUTOARG*/
+   // Inputs
+   clk
+   );
+   input clk;
+
+   global clocking cb @(posedge clk);
+       input #1 output #1step x;
+       inout y;
+       output posedge #1 a;
+       output negedge #1 b;
+       output edge #1 b;
+   endclocking
+
+   global clocking @(posedge clk);
+   endclocking
+endmodule
diff --git a/test_regress/t/t_clocking_unsup2.out b/test_regress/t/t_clocking_unsup2.out
new file mode 100644
index 000000000..644d2e206
--- /dev/null
+++ b/test_regress/t/t_clocking_unsup2.out
@@ -0,0 +1,6 @@
+%Error-UNSUPPORTED: t/t_clocking_unsup2.v:16:11: Unsupported: ##0 delays
+                                               : ... In instance t
+   16 |    always ##0;
+      |           ^~
+                    ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
+%Error: Exiting due to
diff --git a/test_regress/t/t_clocking_unsup2.pl b/test_regress/t/t_clocking_unsup2.pl
new file mode 100755
index 000000000..8ab3c0995
--- /dev/null
+++ b/test_regress/t/t_clocking_unsup2.pl
@@ -0,0 +1,20 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 by Antmicro Ltd. 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(
+    verilator_flags2 => ["--timing"],
+    fails => 1,
+    expect_filename => $Self->{golden_filename},
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_clocking_unsup2.v b/test_regress/t/t_clocking_unsup2.v
new file mode 100644
index 000000000..17babaa15
--- /dev/null
+++ b/test_regress/t/t_clocking_unsup2.v
@@ -0,0 +1,17 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2022 by Antmicro Ltd.
+// SPDX-License-Identifier: CC0-1.0
+
+module t(/*AUTOARG*/
+   // Inputs
+   clk
+   );
+   input clk;
+
+   default clocking @(posedge clk);
+   endclocking
+
+   always ##0;
+endmodule
diff --git a/test_regress/t/t_comb_input_0.cpp b/test_regress/t/t_comb_input_0.cpp
index 926562092..068210940 100644
--- a/test_regress/t/t_comb_input_0.cpp
+++ b/test_regress/t/t_comb_input_0.cpp
@@ -18,8 +18,8 @@
 
 int main(int argc, char** argv) {
     const std::unique_ptr contextp{new VerilatedContext};
-    contextp->commandArgs(argc, argv);
     contextp->debug(0);
+    contextp->commandArgs(argc, argv);
     srand48(5);
 
     const std::unique_ptr topp{new Vt_comb_input_0};
diff --git a/test_regress/t/t_comb_input_1.cpp b/test_regress/t/t_comb_input_1.cpp
index 0277f3ca1..b97948dad 100644
--- a/test_regress/t/t_comb_input_1.cpp
+++ b/test_regress/t/t_comb_input_1.cpp
@@ -18,8 +18,8 @@
 
 int main(int argc, char** argv) {
     const std::unique_ptr contextp{new VerilatedContext};
-    contextp->commandArgs(argc, argv);
     contextp->debug(0);
+    contextp->commandArgs(argc, argv);
     srand48(5);
 
     const std::unique_ptr topp{new Vt_comb_input_1};
diff --git a/test_regress/t/t_comb_input_2.cpp b/test_regress/t/t_comb_input_2.cpp
index 527cfae3d..9d2aad472 100644
--- a/test_regress/t/t_comb_input_2.cpp
+++ b/test_regress/t/t_comb_input_2.cpp
@@ -18,8 +18,8 @@
 
 int main(int argc, char** argv) {
     const std::unique_ptr contextp{new VerilatedContext};
-    contextp->commandArgs(argc, argv);
     contextp->debug(0);
+    contextp->commandArgs(argc, argv);
     srand48(5);
 
     const std::unique_ptr topp{new Vt_comb_input_2};
diff --git a/test_regress/t/t_const_opt.cpp b/test_regress/t/t_const_opt.cpp
index 116148dfb..fde57c973 100644
--- a/test_regress/t/t_const_opt.cpp
+++ b/test_regress/t/t_const_opt.cpp
@@ -1,7 +1,7 @@
 // -*- mode: C++; c-file-style: "cc-mode" -*-
 //*************************************************************************
 //
-// Copyright 2021 by Yutetsu TAKATSUKASA. This program is free software; you can
+// Copyright 2023 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.
@@ -9,5 +9,5 @@
 //
 //*************************************************************************
 
-// This function is used to introduce dependency and disturb optimization
-extern "C" int fake_dependency() { return 0; }
+// Fake dependency to avoid optimization
+extern "C" int c_fake_dependency() { return 0; }
diff --git a/test_regress/t/t_const_opt.pl b/test_regress/t/t_const_opt.pl
index 1ee302ca7..bf8d4b3a3 100755
--- a/test_regress/t/t_const_opt.pl
+++ b/test_regress/t/t_const_opt.pl
@@ -20,7 +20,7 @@ execute(
     );
 
 if ($Self->{vlt}) {
-    file_grep($Self->{stats}, qr/Optimizations, Const bit op reduction\s+(\d+)/i, 15);
+    file_grep($Self->{stats}, qr/Optimizations, Const bit op reduction\s+(\d+)/i, 16);
 }
 ok(1);
 1;
diff --git a/test_regress/t/t_const_opt.v b/test_regress/t/t_const_opt.v
index 8ebb397b3..dcdc1419e 100644
--- a/test_regress/t/t_const_opt.v
+++ b/test_regress/t/t_const_opt.v
@@ -7,7 +7,7 @@
 // This function always returns 0, so safe to take bitwise OR with any value.
 // Calling this function stops constant folding as Verialtor does not know
 // what this function returns.
-import "DPI-C" context function int fake_dependency();
+import "DPI-C" context function int c_fake_dependency();
 
 module t(/*AUTOARG*/
    // Inputs
@@ -62,7 +62,7 @@ module t(/*AUTOARG*/
          $write("[%0t] cyc==%0d crc=%x sum=%x\n", $time, cyc, crc, sum);
          if (crc !== 64'hc77bb9b3784ea091) $stop;
          // What checksum will we end up with (above print should match)
-`define EXPECTED_SUM 64'h94c0495e8e279723
+`define EXPECTED_SUM 64'he65eec57cf769267
 
          if (sum !== `EXPECTED_SUM) $stop;
          $write("*-* All Finished *-*\n");
@@ -91,10 +91,11 @@ module Test(/*AUTOARG*/
    wire  bug3399_out0;
    wire  bug3399_out1;
    logic bug3786_out;
+   logic bug3824_out;
 
    output logic o;
 
-   logic [12:0] tmp;
+   logic [13:0] tmp;
    assign o = ^tmp;
 
    always_ff @(posedge clk) begin
@@ -123,6 +124,7 @@ module Test(/*AUTOARG*/
       tmp[10]<= bug3399_out0;
       tmp[11]<= bug3399_out1;
       tmp[12]<= bug3786_out;
+      tmp[13]<= bug3824_out;
    end
 
    bug3182 i_bug3182(.in(d[4:0]), .out(bug3182_out));
@@ -132,6 +134,7 @@ module Test(/*AUTOARG*/
    bug3509 i_bug3509(.clk(clk), .in(d), .out(bug3509_out));
    bug3399 i_bug3399(.clk(clk), .in(d), .out0(bug3399_out0), .out1(bug3399_out1));
    bug3786 i_bug3786(.clk(clk), .in(d), .out(bug3786_out));
+   bug3824 i_bug3824(.clk(clk), .in(d), .out(bug3824_out));
 
 endmodule
 
@@ -143,7 +146,7 @@ module bug3182(in, out);
 
    /* verilator lint_off WIDTH */
    always @(in)
-      bit_source = fake_dependency() | in;
+      bit_source = c_fake_dependency() | in;
 
    wire [5:0] tmp = bit_source; // V3Gate should inline this
    wire out =  ~(tmp >> 5) & (bit_source == 5'd10);
@@ -200,7 +203,7 @@ module bug3445(input wire clk, input wire [31:0] in, output wire out);
       st[1] <= st[0];
       st[2] <= st[1];
       st[3] <= st[2];
-      zero <= fake_dependency() > 0;
+      zero <= c_fake_dependency() > 0;
    end
 
    logic result0, result1, result2, result3;
@@ -331,3 +334,33 @@ module bug3786(input wire clk, input wire [31:0] in, inout wire out);
 
    assign out = ^{d1, d0};
 endmodule
+
+// Bug3824
+// When a variable is shift-out, the term becomes 0.
+// Such behavior was not considered in Or-tree.
+module bug3824(input wire clk, input wire [31:0] in, output wire out);
+   logic [5:0] a;
+   always_ff @(posedge clk) a <= in[5:0];
+   logic [6:0] b;
+   assign b = {1'b0, a};
+
+   logic c_and;
+   assign c_and = (b[6]);  // c_and is always 1'b0
+   always_comb if (c_and != 1'b0) $stop;
+   logic d_and;
+   always_ff @(posedge clk) d_and <= (&a) & c_and;
+
+   logic c_or;
+   assign c_or = ~(b[6]);  // c_or is always 1'b1 as b[6] is 1'b0
+   always_comb if (c_or != 1'b1) $stop;
+   logic d_or;
+   always_ff @(posedge clk) d_or <= (|a) | c_or;
+
+   logic c_xor;
+   assign c_xor = ^(b[6]);  // c_xor is always 1'b0
+   always_comb if (c_xor != 1'b0) $stop;
+   logic d_xor;
+   always_ff @(posedge clk) d_xor <= (^a) ^ c_xor;
+
+  assign out = d_and ^ d_or ^ d_xor;
+endmodule
diff --git a/test_regress/t/t_const_opt_shortcut.cpp b/test_regress/t/t_const_opt_shortcut.cpp
index 9d2e9bb33..44a695a94 100644
--- a/test_regress/t/t_const_opt_shortcut.cpp
+++ b/test_regress/t/t_const_opt_shortcut.cpp
@@ -1,4 +1,9 @@
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2022 by Wilson Snyder.
+// SPDX-License-Identifier: CC0-1.0
+
 #include 
+
 extern "C" int import_func0() {
     static int c = 0;
     return ++c;
diff --git a/test_regress/t/t_const_slicesel.v b/test_regress/t/t_const_slicesel.v
index 244fa28ae..a4fec28f4 100644
--- a/test_regress/t/t_const_slicesel.v
+++ b/test_regress/t/t_const_slicesel.v
@@ -2,7 +2,7 @@
 //
 // This file ONLY is placed under the Creative Commons Public Domain, for
 // any use, without warranty, 2021 by Michael Lefebvre.
-
+// SPDX-License-Identifier: CC0-1.0
 
 module t(/*AUTOARG*/);
 
diff --git a/test_regress/t/t_const_slicesel_bad.v b/test_regress/t/t_const_slicesel_bad.v
index 15a7e0dc1..9d588a3ad 100644
--- a/test_regress/t/t_const_slicesel_bad.v
+++ b/test_regress/t/t_const_slicesel_bad.v
@@ -2,7 +2,7 @@
 //
 // This file ONLY is placed under the Creative Commons Public Domain, for
 // any use, without warranty, 2021 by Michael Lefebvre.
-
+// SPDX-License-Identifier: CC0-1.0
 
 module t(/*AUTOARG*/);
 
diff --git a/test_regress/t/t_continue_do_while_bad.pl b/test_regress/t/t_continue_do_while_bad.pl
index f201521f0..15b4f4a73 100755
--- a/test_regress/t/t_continue_do_while_bad.pl
+++ b/test_regress/t/t_continue_do_while_bad.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_convert2string.pl b/test_regress/t/t_convert2string.pl
index 89a4e77d9..beaa2ca59 100755
--- a/test_regress/t/t_convert2string.pl
+++ b/test_regress/t/t_convert2string.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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);
 
diff --git a/test_regress/t/t_convert2string.v b/test_regress/t/t_convert2string.v
index 990dfd2fc..9e85e81c9 100644
--- a/test_regress/t/t_convert2string.v
+++ b/test_regress/t/t_convert2string.v
@@ -2,6 +2,7 @@
 //
 // This file ONLY is placed into the Public Domain, for any use,
 // without warranty, 2020 by Peter Monsson.
+// SPDX-License-Identifier: Unlicense
 
 module t (/*AUTOARG*/
    // Inputs
diff --git a/test_regress/t/t_cover_toggle.out b/test_regress/t/t_cover_toggle.out
new file mode 100644
index 000000000..d9dd61b7d
--- /dev/null
+++ b/test_regress/t/t_cover_toggle.out
@@ -0,0 +1,162 @@
+	// verilator_coverage annotation
+	// DESCRIPTION: Verilator: Verilog Test module
+	//
+	// This file ONLY is placed under the Creative Commons Public Domain, for
+	// any use, without warranty, 2008 by Wilson Snyder.
+	// SPDX-License-Identifier: CC0-1.0
+	
+	module t (/*AUTOARG*/
+	   // Inputs
+	   clk,
+	   check_real,
+	   check_string
+	   );
+	
+ 000019	   input clk;
+	   input real check_real; // Check issue #2741
+	   input string check_string; // Check issue #2766
+	
+	   typedef struct packed {
+	      union packed {
+	         logic    ua;
+	         logic    ub;
+	      } u;
+	      logic b;
+	   } str_t;
+	
+%000002	   reg   toggle; initial toggle='0;
+	
+%000004	   str_t stoggle; initial stoggle='0;
+	
+	   const reg aconst = '0;
+	
+%000002	   reg [1:0][1:0] ptoggle; initial ptoggle=0;
+	
+	   integer cyc; initial cyc=1;
+ 000019	   wire [7:0] cyc_copy = cyc[7:0];
+%000002	   wire       toggle_up;
+	
+	   alpha a1 (/*AUTOINST*/
+	             // Outputs
+	             .toggle_up                 (toggle_up),
+	             // Inputs
+	             .clk                       (clk),
+	             .toggle                    (toggle),
+	             .cyc_copy                  (cyc_copy[7:0]));
+	   alpha a2 (/*AUTOINST*/
+	             // Outputs
+	             .toggle_up                 (toggle_up),
+	             // Inputs
+	             .clk                       (clk),
+	             .toggle                    (toggle),
+	             .cyc_copy                  (cyc_copy[7:0]));
+	
+	   beta  b1 (/*AUTOINST*/
+	             // Inputs
+	             .clk                       (clk),
+	             .toggle_up                 (toggle_up));
+	
+	   off   o1 (/*AUTOINST*/
+	             // Inputs
+	             .clk                       (clk),
+	             .toggle                    (toggle));
+	
+%000001	   reg [1:0]  memory[121:110];
+	
+	   wire [1023:0] largeish = {992'h0, cyc};
+	   // CHECK_COVER_MISSING(-1)
+	
+	   always @ (posedge clk) begin
+	      if (cyc!=0) begin
+	         cyc <= cyc + 1;
+	         memory[cyc + 'd100] <= memory[cyc + 'd100] + 2'b1;
+	         toggle <= '0;
+	         stoggle.u <= toggle;
+	         stoggle.b <= toggle;
+	         ptoggle[0][0] <= toggle;
+	         if (cyc==3) begin
+	            toggle <= '1;
+	         end
+	         if (cyc==4) begin
+	            toggle <= '0;
+	         end
+	         else if (cyc==10) begin
+	            $write("*-* All Finished *-*\n");
+	            $finish;
+	         end
+	      end
+	   end
+	
+	endmodule
+	
+	module alpha (/*AUTOARG*/
+	   // Outputs
+	   toggle_up,
+	   // Inputs
+	   clk, toggle, cyc_copy
+	   );
+	
+	   // t.a1 and t.a2 collapse to a count of 2
+	
+ 000038	   input clk;
+	
+%000004	   input toggle;
+	   // CHECK_COVER(-1,"top.t.a*",4)
+	   // 2 edges * (t.a1 and t.a2)
+	
+ 000038	   input [7:0] cyc_copy;
+	   // CHECK_COVER(-1,"top.t.a*","cyc_copy[0]",22)
+	   // CHECK_COVER(-2,"top.t.a*","cyc_copy[1]",10)
+	   // CHECK_COVER(-3,"top.t.a*","cyc_copy[2]",4)
+	   // CHECK_COVER(-4,"top.t.a*","cyc_copy[3]",2)
+	   // CHECK_COVER(-5,"top.t.a*","cyc_copy[4]",0)
+	   // CHECK_COVER(-6,"top.t.a*","cyc_copy[5]",0)
+	   // CHECK_COVER(-7,"top.t.a*","cyc_copy[6]",0)
+	   // CHECK_COVER(-8,"top.t.a*","cyc_copy[7]",0)
+	
+%000004	   reg         toggle_internal;
+	   // CHECK_COVER(-1,"top.t.a*",4)
+	   // 2 edges * (t.a1 and t.a2)
+	
+%000004	   output reg  toggle_up;
+	   // CHECK_COVER(-1,"top.t.a*",4)
+	   // 2 edges * (t.a1 and t.a2)
+	
+	   always @ (posedge clk) begin
+	      toggle_internal <= toggle;
+	      toggle_up       <= toggle;
+	   end
+	endmodule
+	
+	module beta (/*AUTOARG*/
+	   // Inputs
+	   clk, toggle_up
+	   );
+	
+ 000019	   input clk;
+	
+%000002	   input toggle_up;
+	   // CHECK_COVER(-1,"top.t.b1","toggle_up",2)
+	
+	   /* verilator public_module */
+	
+	   always @ (posedge clk) begin
+	      if (0 && toggle_up) begin end
+	   end
+	endmodule
+	
+	module off (/*AUTOARG*/
+	   // Inputs
+	   clk, toggle
+	   );
+	
+	   // verilator coverage_off
+	   input clk;
+	   // CHECK_COVER_MISSING(-1)
+	
+	   // verilator coverage_on
+%000002	   input toggle;
+	   // CHECK_COVER(-1,"top.t.o1","toggle",2)
+	
+	endmodule
+	
diff --git a/test_regress/t/t_cover_toggle.pl b/test_regress/t/t_cover_toggle.pl
index 64324cf9d..5564c29d5 100755
--- a/test_regress/t/t_cover_toggle.pl
+++ b/test_regress/t/t_cover_toggle.pl
@@ -26,5 +26,14 @@ file_grep_not("$Self->{obj_dir}/coverage.dat", "largeish");
 file_grep($Self->{stats}, qr/Coverage, Toggle points joined\s+(\d+)/i, 25)
     if $Self->{vlt_all};
 
+run(cmd => ["../bin/verilator_coverage",
+            "--annotate", "$Self->{obj_dir}/annotated",
+            "$Self->{obj_dir}/coverage.dat",
+            ],
+    verilator_run => 1,
+    );
+
+files_identical("$Self->{obj_dir}/annotated/$Self->{name}.v", $Self->{golden_filename});
+
 ok(1);
 1;
diff --git a/test_regress/t/t_debug_emitv.out b/test_regress/t/t_debug_emitv.out
index dc2725f00..7ef0ebebd 100644
--- a/test_regress/t/t_debug_emitv.out
+++ b/test_regress/t/t_debug_emitv.out
@@ -32,7 +32,7 @@ module Vt_debug_emitv_t;
     ???? // UNSIZEDARRAYDTYPE
 
     ???? // DYNARRAYDTYPE
-    signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed realstringIData [31:0] signed logic [31:0] signed int [31:0] logic [2:0] logic [0:0]  e_t;
+    signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed realstringIData [31:0] signed logic [31:0] signed int [31:0] bit [0:0] logic [0:0]  e_t;
     typedef struct packed 
     {
         ???? // REFDTYPE 'e_t'
@@ -56,7 +56,7 @@ module Vt_debug_emitv_t;
     ???? // UNSIZEDARRAYDTYPE
 
     ???? // DYNARRAYDTYPE
-    signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed realstringIData [31:0] signed logic [31:0] signed int [31:0] logic [2:0] logic [0:0]  ps_t;
+    signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed realstringIData [31:0] signed logic [31:0] signed int [31:0] bit [0:0] logic [0:0]  ps_t;
     typedef struct 
     {signed logic [2:0]  a}logicunion 
     {logic a}
@@ -77,7 +77,7 @@ module Vt_debug_emitv_t;
     ???? // UNSIZEDARRAYDTYPE
 
     ???? // DYNARRAYDTYPE
-    signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed realstringIData [31:0] signed logic [31:0] signed int [31:0] logic [2:0] logic [0:0]  us_t;
+    signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed realstringIData [31:0] signed logic [31:0] signed int [31:0] bit [0:0] logic [0:0]  us_t;
     typedef union 
     {logic a}
     ???? // REFDTYPE 'ps_t'
@@ -97,7 +97,7 @@ module Vt_debug_emitv_t;
     ???? // UNSIZEDARRAYDTYPE
 
     ???? // DYNARRAYDTYPE
-    signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed realstringIData [31:0] signed logic [31:0] signed int [31:0] logic [2:0] logic [0:0]  union_t;
+    signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed int [31:0] signed realstringIData [31:0] signed logic [31:0] signed int [31:0] bit [0:0] logic [0:0]  union_t;
     struct packed 
     {
         ???? // REFDTYPE 'e_t'
diff --git a/test_regress/t/t_dfg_3817.pl b/test_regress/t/t_dfg_3817.pl
new file mode 100755
index 000000000..31e4367f7
--- /dev/null
+++ b/test_regress/t/t_dfg_3817.pl
@@ -0,0 +1,16 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 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);
+
+compile();
+
+ok(1);
+1;
diff --git a/test_regress/t/t_dfg_3817.v b/test_regress/t/t_dfg_3817.v
new file mode 100644
index 000000000..043142ab7
--- /dev/null
+++ b/test_regress/t/t_dfg_3817.v
@@ -0,0 +1,15 @@
+// DESCRIPTION: Verilator: Verilog Test module for issue #3817
+// addDriver() was causing use-after-free and segfaulting during Verilation
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2022 by Jevin Sweval.
+// SPDX-License-Identifier: CC0-1.0
+
+module t (
+  output [2:0] c_b_a,
+  input a,
+  input b,
+  input c
+);
+  assign c_b_a = {c, {b, a}};
+endmodule
diff --git a/test_regress/t/t_dfg_3872.pl b/test_regress/t/t_dfg_3872.pl
new file mode 100755
index 000000000..31e4367f7
--- /dev/null
+++ b/test_regress/t/t_dfg_3872.pl
@@ -0,0 +1,16 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 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);
+
+compile();
+
+ok(1);
+1;
diff --git a/test_regress/t/t_dfg_3872.v b/test_regress/t/t_dfg_3872.v
new file mode 100644
index 000000000..2a7b0617a
--- /dev/null
+++ b/test_regress/t/t_dfg_3872.v
@@ -0,0 +1,12 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2023 by Geza Lore.
+// SPDX-License-Identifier: CC0-1.0
+
+module top(
+  input  wire [1:0] i,
+  output wire [3:0] o
+);
+  assign o = 4'd2 ** i;
+endmodule
diff --git a/test_regress/t/t_dfg_peephole.cpp b/test_regress/t/t_dfg_peephole.cpp
index 6a6bf3440..0664397e1 100644
--- a/test_regress/t/t_dfg_peephole.cpp
+++ b/test_regress/t/t_dfg_peephole.cpp
@@ -1,5 +1,5 @@
 //
-// DESCRIPTION: Verilator: DFG optimzier equivalence testing
+// DESCRIPTION: Verilator: DFG optimizer equivalence testing
 //
 // This file ONLY is placed under the Creative Commons Public Domain, for
 // any use, without warranty, 2022 by Geza Lore.
@@ -30,17 +30,20 @@ int main(int, char**) {
     uint64_t rand_a = 0x5aef0c8dd70a4497;
     uint64_t rand_b = 0xf0c0a8dd75ae4497;
     uint64_t srand_a = 0x00fa8dcc7ae4957;
+    uint64_t srand_b = 0x0fa8dc7ae3c9574;
 
     for (size_t n = 0; n < 200000; ++n) {
         // Update rngs
         rngUpdate(rand_a);
         rngUpdate(rand_b);
         rngUpdate(srand_a);
+        rngUpdate(srand_b);
 
         // Assign inputs
         ref.rand_a = opt.rand_a = rand_a;
         ref.rand_b = opt.rand_b = rand_b;
         ref.srand_a = opt.srand_a = srand_a;
+        ref.srand_b = opt.srand_b = srand_b;
 
         // Evaluate both models
         ref.eval();
diff --git a/test_regress/t/t_dfg_peephole.v b/test_regress/t/t_dfg_peephole.v
index de4f54229..7f0ea086e 100644
--- a/test_regress/t/t_dfg_peephole.v
+++ b/test_regress/t/t_dfg_peephole.v
@@ -8,7 +8,7 @@
 
 module t (
 `include "portlist.vh" // Boilerplate generated by t_dfg_peephole.pl
-          rand_a, rand_b, srand_a
+          rand_a, rand_b, srand_a, srand_b
           );
 
 `include "portdecl.vh" // Boilerplate generated by t_dfg_peephole.pl
@@ -16,9 +16,11 @@ module t (
    input rand_a;
    input rand_b;
    input srand_a;
+   input srand_b;
    wire logic        [63:0] rand_a;
    wire logic        [63:0] rand_b;
    wire logic signed [63:0] srand_a;
+   wire logic signed [63:0] srand_b;
 
    wire        logic randbit_a = rand_a[0];
    wire        logic [127:0] rand_ba = {rand_b, rand_a};
@@ -179,6 +181,15 @@ module t (
    `signal(RIGHT_LEANING_ASSOC, (((rand_a + rand_b) + rand_a) + rand_b));
    `signal(RIGHT_LEANING_CONCET, {{{rand_a, rand_b}, rand_a}, rand_b});
 
+   // Operators that should work wiht mismatched widths
+   `signal(MISMATCHED_ShiftL,const_a << 4'd2);
+   `signal(MISMATCHED_ShiftR,const_a >> 4'd2);
+   `signal(MISMATCHED_ShiftRS, const_a >> 4'd2);
+   `signal(MISMATCHED_PowUU, rand_a ** 4'd5);
+   `signal(MISMATCHED_PowSS, srand_a ** 4'sd5);
+   `signal(MISMATCHED_PowSU, srand_b ** 4'd5);
+   `signal(MISMATCHED_PowUS, rand_b ** 4'sd5);
+
    // Some selects need extra temporaries
    wire [63:0] sel_from_cond = rand_a[0] ? rand_a : const_a;
    wire [63:0] sel_from_shiftl = rand_a << 10;
diff --git a/test_regress/t/t_dist_attributes_bad.cpp b/test_regress/t/t_dist_attributes_bad.cpp
new file mode 100644
index 000000000..cc68d5111
--- /dev/null
+++ b/test_regress/t/t_dist_attributes_bad.cpp
@@ -0,0 +1,183 @@
+// -*- mode: C++; c-file-style: "cc-mode" -*-
+//
+//*************************************************************************
+//
+// Code available from: https://verilator.org
+//
+// Copyright 2022-2023 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
+//
+//*************************************************************************
+
+#include "verilatedos.h"
+
+#include "t_dist_attributes_bad.h"
+
+// Non-Static Functions, Annotated declaration, Unannotated definition.
+// (definitions)
+EMIT_ALL(SIG_UNANNOTATED, nsf_au, /**/, {})
+
+// Non-Static Functions, Unannotated declaration, Annotated definition.
+// (definitions)
+EMIT_ALL(SIG_ANNOTATED, nsf_ua, /**/, {})
+
+// Non-Static Functions, Annotated declaration, Annotated definition.
+// (definitions)
+EMIT_ALL(SIG_ANNOTATED, nsf_aa, /**/, {})
+
+// Non-Static Functions, Annotated declaration, Annotated definition.
+// Definitions have extra annotations.
+// (definitions)
+EMIT_ALL(SIG_ANNOTATED, nsf_ae, /**/, VL_PURE VL_MT_SAFE{})
+
+// Non-Static Functions, Annotated declaration, Annotated definition.
+// Declarations have extra annotations.
+// (definitions)
+EMIT_ALL(SIG_ANNOTATED, nsf_ea, /**/, {})
+
+// Non-Static Functions (call test).
+EMIT_ALL(VL_ATTR_UNUSED static SIG_ANNOTATED, nsf_test_caller_func, /**/, {
+    VerilatedMutex m;
+
+    EMIT_ALL(CALL, nsf_au, m, ;)
+    EMIT_ALL(CALL, nsf_ua, m, ;)
+    EMIT_ALL(CALL, nsf_aa, m, ;)
+    EMIT_ALL(CALL, nsf_ae, m, ;)
+    EMIT_ALL(CALL, nsf_ea, m, ;)
+})
+
+// Inline Functions in Header (call test).
+EMIT_ALL(VL_ATTR_UNUSED static SIG_ANNOTATED, ifh_test_caller_func, /**/, {
+    VerilatedMutex m;
+
+    EMIT_ALL(CALL, ifh, m, ;)
+})
+
+// Static Functions in Cpp file.
+EMIT_ALL(inline SIG_ANNOTATED, sfc, /**/, {})
+
+// Static Functions in Cpp file (call test).
+EMIT_ALL(VL_ATTR_UNUSED static SIG_ANNOTATED, sfc_test_caller_func, /**/, {
+    VerilatedMutex m;
+
+    EMIT_ALL(CALL, sfc, m, ;)
+})
+
+// Static Class Methods, Annotated declaration, Unannotated definition.
+// (definitions)
+EMIT_ALL(SIG_UNANNOTATED, TestClass::scm_au, /**/, {})
+
+// Static Class Methods, Unannotated declaration, Annotated definition.
+// (definitions)
+EMIT_ALL(SIG_ANNOTATED, TestClass::scm_ua, /**/, {})
+
+// Static Class Methods, Annotated declaration, Annotated definition.
+// (definitions)
+EMIT_ALL(SIG_ANNOTATED, TestClass::scm_aa, /**/, {})
+
+// Static Class Methods, Annotated declaration, Annotated definition.
+// Definitions have extra annotations.
+// (definitions)
+EMIT_ALL(SIG_ANNOTATED, TestClass::scm_ae, /**/, VL_PURE VL_MT_SAFE{})
+
+// Static Class Methods, Annotated declaration, Annotated definition.
+// Declarations have extra annotations.
+// (definitions)
+EMIT_ALL(SIG_ANNOTATED, TestClass::scm_ea, /**/, {})
+
+// Static Class Methods (call test).
+// (definition)
+EMIT_ALL(SIG_ANNOTATED, TestClass::scm_test_caller_smethod, /**/, {
+    VerilatedMutex m;
+
+    EMIT_ALL(CALL, TestClass::scm_au, m, ;)
+    EMIT_ALL(CALL, TestClass::scm_ua, m, ;)
+    EMIT_ALL(CALL, TestClass::scm_aa, m, ;)
+    EMIT_ALL(CALL, TestClass::scm_ae, m, ;)
+    EMIT_ALL(CALL, TestClass::scm_ea, m, ;)
+
+    TestClass tc;
+    EMIT_ALL(CALL, tc.scm_au, m, ;)
+    EMIT_ALL(CALL, tc.scm_ua, m, ;)
+    EMIT_ALL(CALL, tc.scm_aa, m, ;)
+    EMIT_ALL(CALL, tc.scm_ae, m, ;)
+    EMIT_ALL(CALL, tc.scm_ea, m, ;)
+
+    TestClass* tcp = &tc;
+    EMIT_ALL(CALL, tcp->scm_au, m, ;)
+    EMIT_ALL(CALL, tcp->scm_ua, m, ;)
+    EMIT_ALL(CALL, tcp->scm_aa, m, ;)
+    EMIT_ALL(CALL, tcp->scm_ae, m, ;)
+    EMIT_ALL(CALL, tcp->scm_ea, m, ;)
+})
+
+// Inline Static Class Methods (call test).
+// (definition)
+EMIT_ALL(SIG_ANNOTATED, TestClass::iscm_test_caller_smethod, /**/, {
+    VerilatedMutex m;
+
+    EMIT_ALL(CALL, TestClass::iscm, m, ;)
+
+    TestClass tc;
+    EMIT_ALL(CALL, tc.iscm, m, ;)
+
+    TestClass* tcp = &tc;
+    EMIT_ALL(CALL, tcp->iscm, m, ;)
+})
+
+// Class Methods, Annotated declaration, Unannotated definition.
+// (definitions)
+EMIT_ALL(SIG_UNANNOTATED, TestClass::cm_au, /**/, {})
+
+// Class Methods, Unannotated declaration, Annotated definition.
+// (definitions)
+EMIT_ALL(SIG_ANNOTATED, TestClass::cm_ua, /**/, {})
+
+// Class Methods, Annotated declaration, Annotated definition.
+// (definitions)
+EMIT_ALL(SIG_ANNOTATED, TestClass::cm_aa, /**/, {})
+
+// Class Methods, Annotated declaration, Annotated definition.
+// Definitions have extra annotations.
+// (definitions)
+EMIT_ALL(SIG_ANNOTATED, TestClass::cm_ae, /**/, VL_PURE VL_MT_SAFE{})
+
+// Class Methods, Annotated declaration, Annotated definition.
+// Declarations have extra annotations.
+// (definitions)
+EMIT_ALL(SIG_ANNOTATED, TestClass::cm_ea, /**/, {})
+
+// Class Methods (call test).
+// (definition)
+EMIT_ALL(SIG_ANNOTATED, TestClass::cm_test_caller_smethod, /**/, {
+    VerilatedMutex m;
+
+    TestClass tc;
+    EMIT_ALL(CALL, tc.cm_au, m, ;)
+    EMIT_ALL(CALL, tc.cm_ua, m, ;)
+    EMIT_ALL(CALL, tc.cm_aa, m, ;)
+    EMIT_ALL(CALL, tc.cm_ae, m, ;)
+    EMIT_ALL(CALL, tc.cm_ea, m, ;)
+
+    TestClass* tcp = &tc;
+    EMIT_ALL(CALL, tcp->cm_au, m, ;)
+    EMIT_ALL(CALL, tcp->cm_ua, m, ;)
+    EMIT_ALL(CALL, tcp->cm_aa, m, ;)
+    EMIT_ALL(CALL, tcp->cm_ae, m, ;)
+    EMIT_ALL(CALL, tcp->cm_ea, m, ;)
+})
+
+// Inline Class Methods (call test).
+// (definition)
+EMIT_ALL(SIG_ANNOTATED, TestClass::icm_test_caller_smethod, /**/, {
+    VerilatedMutex m;
+
+    TestClass tc;
+    EMIT_ALL(CALL, tc.icm, m, ;)
+
+    TestClass* tcp = &tc;
+    EMIT_ALL(CALL, tcp->icm, m, ;)
+})
diff --git a/test_regress/t/t_dist_attributes_bad.h b/test_regress/t/t_dist_attributes_bad.h
new file mode 100644
index 000000000..bd24cf77f
--- /dev/null
+++ b/test_regress/t/t_dist_attributes_bad.h
@@ -0,0 +1,276 @@
+// -*- mode: C++; c-file-style: "cc-mode" -*-
+//
+//*************************************************************************
+//
+// Code available from: https://verilator.org
+//
+// Copyright 2022-2023 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
+//
+//*************************************************************************
+
+#ifndef T_DIST_ATTRIBUTES_BAD_H_
+#define T_DIST_ATTRIBUTES_BAD_H_
+
+#include "verilatedos.h"
+
+#include "verilated.h"
+
+#include 
+
+#define NO_ANNOTATION
+
+#define CALL_0(prefix, annotation, aarg_type, aarg, val) prefix##_##annotation(val)
+
+#define CALL_1(prefix, annotation, aarg_type, aarg, val) prefix##_##annotation(val)
+
+#define SIG_ANNOTATED_0(prefix, annotation, aarg_type, aarg, val) \
+    void prefix##_##annotation(aarg_type aarg) annotation
+
+#define SIG_ANNOTATED_1(prefix, annotation, aarg_type, aarg, val) \
+    void prefix##_##annotation(aarg_type aarg) annotation(aarg)
+
+#define SIG_UNANNOTATED_0(prefix, annotation, aarg_type, aarg, val) \
+    void prefix##_##annotation(aarg_type aarg)
+
+#define SIG_UNANNOTATED_1(prefix, annotation, aarg_type, aarg, val) \
+    void prefix##_##annotation(aarg_type aarg)
+
+// clang-format off
+#define EMIT_ALL(before, sig_prefix, val, after) \
+    before##_0(sig_prefix, NO_ANNOTATION,       VerilatedMutex&, mtx, val) after \
+    before##_0(sig_prefix, VL_PURE,             VerilatedMutex&, mtx, val) after \
+    before##_0(sig_prefix, VL_MT_SAFE,          VerilatedMutex&, mtx, val) after \
+    before##_0(sig_prefix, VL_MT_SAFE_POSTINIT, VerilatedMutex&, mtx, val) after \
+    before##_0(sig_prefix, VL_MT_UNSAFE,        VerilatedMutex&, mtx, val) after \
+    before##_0(sig_prefix, VL_MT_UNSAFE_ONE,    VerilatedMutex&, mtx, val) after \
+    before##_0(sig_prefix, VL_MT_START,         VerilatedMutex&, mtx, val) after \
+    before##_1(sig_prefix, VL_ACQUIRE,          VerilatedMutex&, mtx, val) after \
+    before##_1(sig_prefix, VL_REQUIRES,         VerilatedMutex&, mtx, val) after \
+    before##_1(sig_prefix, VL_RELEASE,          VerilatedMutex&, mtx, val) after \
+    before##_1(sig_prefix, VL_ACQUIRE_SHARED,   VerilatedMutex&, mtx, val) after \
+    before##_1(sig_prefix, VL_RELEASE_SHARED,   VerilatedMutex&, mtx, val) after \
+    before##_1(sig_prefix, VL_EXCLUDES,         VerilatedMutex&, mtx, val) after \
+    before##_1(sig_prefix, VL_MT_SAFE_EXCLUDES, VerilatedMutex&, mtx, val) after
+// clang-format on
+
+// Non-Static Functions, Annotated declaration, Unannotated definition.
+// (declarations)
+EMIT_ALL(SIG_ANNOTATED, nsf_au, /**/, ;)
+
+// Non-Static Functions, Unannotated declaration, Annotated definition.
+// (declarations)
+EMIT_ALL(SIG_UNANNOTATED, nsf_ua, /**/, ;)
+
+// Non-Static Functions, Annotated declaration, Annotated definition.
+// (declarations)
+EMIT_ALL(SIG_ANNOTATED, nsf_aa, /**/, ;)
+
+// Non-Static Functions, Annotated declaration, Annotated definition.
+// Definitions have extra annotations.
+// (declarations)
+EMIT_ALL(SIG_ANNOTATED, nsf_ae, /**/, ;)
+
+// Non-Static Functions, Annotated declaration, Annotated definition.
+// Declarations have extra annotations.
+// (declarations)
+EMIT_ALL(SIG_ANNOTATED, nsf_ea, /**/, VL_PURE VL_MT_SAFE;)
+
+// Non-Static Functions (call test in header).
+EMIT_ALL(inline SIG_ANNOTATED, nsf_test_caller_func_hdr, /**/, {
+    VerilatedMutex m;
+
+    EMIT_ALL(CALL, nsf_au, m, ;)
+    EMIT_ALL(CALL, nsf_ua, m, ;)
+    EMIT_ALL(CALL, nsf_aa, m, ;)
+    EMIT_ALL(CALL, nsf_ae, m, ;)
+    EMIT_ALL(CALL, nsf_ea, m, ;)
+})
+
+// Inline Functions in Header.
+EMIT_ALL(inline SIG_ANNOTATED, ifh, /**/, {})
+
+// Inline Functions in Header (call test in header).
+EMIT_ALL(inline SIG_ANNOTATED, ifh_test_caller_func_hdr, /**/, {
+    VerilatedMutex m;
+
+    EMIT_ALL(CALL, ifh, m, ;)
+})
+
+struct GuardMe {
+    void safe_if_guarded_or_local() {}
+
+    operator int() const { return 4; }
+
+    GuardMe& operator+=(int) { return *this; }
+};
+
+class TestClass {
+    VerilatedMutex m_mtx;
+    GuardMe m_guardme VL_GUARDED_BY(m_mtx);
+
+    GuardMe m_guardme_unguarded;
+
+public:
+    // Static Class Methods, Annotated declaration, Unannotated definition.
+    // (declarations)
+    EMIT_ALL(static SIG_ANNOTATED, scm_au, /**/, ;)
+
+    // Static Class Methods, Unannotated declaration, Annotated definition.
+    // (declarations)
+    EMIT_ALL(static SIG_UNANNOTATED, scm_ua, /**/, ;)
+
+    // Static Class Methods, Annotated declaration, Annotated definition.
+    // (declarations)
+    EMIT_ALL(static SIG_ANNOTATED, scm_aa, /**/, ;)
+
+    // Static Class Methods, Annotated declaration, Annotated definition.
+    // Definitions have extra annotations.
+    // (declarations)
+    EMIT_ALL(static SIG_ANNOTATED, scm_ae, /**/, ;)
+
+    // Static Class Methods, Annotated declaration, Annotated definition.
+    // Declarations have extra annotations.
+    // (declarations)
+    EMIT_ALL(static SIG_ANNOTATED, scm_ea, /**/, VL_PURE VL_MT_SAFE;)
+
+    // Static Class Methods (call test in header).
+    EMIT_ALL(static SIG_ANNOTATED, scm_test_caller_smethod_hdr, /**/, {
+        VerilatedMutex m;
+
+        EMIT_ALL(CALL, TestClass::scm_au, m, ;)
+        EMIT_ALL(CALL, TestClass::scm_ua, m, ;)
+        EMIT_ALL(CALL, TestClass::scm_aa, m, ;)
+        EMIT_ALL(CALL, TestClass::scm_ae, m, ;)
+        EMIT_ALL(CALL, TestClass::scm_ea, m, ;)
+
+        TestClass tc;
+        EMIT_ALL(CALL, tc.scm_au, m, ;)
+        EMIT_ALL(CALL, tc.scm_ua, m, ;)
+        EMIT_ALL(CALL, tc.scm_aa, m, ;)
+        EMIT_ALL(CALL, tc.scm_ae, m, ;)
+        EMIT_ALL(CALL, tc.scm_ea, m, ;)
+
+        TestClass* tcp = &tc;
+        EMIT_ALL(CALL, tcp->scm_au, m, ;)
+        EMIT_ALL(CALL, tcp->scm_ua, m, ;)
+        EMIT_ALL(CALL, tcp->scm_aa, m, ;)
+        EMIT_ALL(CALL, tcp->scm_ae, m, ;)
+        EMIT_ALL(CALL, tcp->scm_ea, m, ;)
+    })
+
+    // Static Class Methods (call test).
+    // (declaration)
+    EMIT_ALL(static SIG_ANNOTATED, scm_test_caller_smethod, /**/, ;)
+
+    // Inline Static Class Methods.
+    EMIT_ALL(static SIG_ANNOTATED, iscm, /**/, {})
+
+    // Inline Static Class Methods (call test in header).
+    EMIT_ALL(static SIG_ANNOTATED, iscm_test_caller_smethod_hdr, /**/, {
+        VerilatedMutex m;
+
+        EMIT_ALL(CALL, TestClass::iscm, m, ;)
+
+        TestClass tc;
+        EMIT_ALL(CALL, tc.iscm, m, ;)
+
+        TestClass* tcp = &tc;
+        EMIT_ALL(CALL, tcp->iscm, m, ;)
+    })
+
+    // Inline Static Class Methods (call test).
+    // (declaration)
+    EMIT_ALL(static SIG_ANNOTATED, iscm_test_caller_smethod, /**/, ;)
+
+    // Class Methods, Annotated declaration, Unannotated definition.
+    // (declarations)
+    EMIT_ALL(SIG_ANNOTATED, cm_au, /**/, ;)
+
+    // Class Methods, Unannotated declaration, Annotated definition.
+    // (declarations)
+    EMIT_ALL(SIG_UNANNOTATED, cm_ua, /**/, ;)
+
+    // Class Methods, Annotated declaration, Annotated definition.
+    // (declarations)
+    EMIT_ALL(SIG_ANNOTATED, cm_aa, /**/, ;)
+
+    // Class Methods, Annotated declaration, Annotated definition.
+    // Definitions have extra annotations.
+    // (declarations)
+    EMIT_ALL(SIG_ANNOTATED, cm_ae, /**/, ;)
+
+    // Class Methods, Annotated declaration, Annotated definition.
+    // Declarations have extra annotations.
+    // (declarations)
+    EMIT_ALL(SIG_ANNOTATED, cm_ea, /**/, VL_PURE VL_MT_SAFE;)
+
+    // Class Methods (call test in header).
+    EMIT_ALL(SIG_ANNOTATED, cm_test_caller_smethod_hdr, /**/, {
+        VerilatedMutex m;
+
+        TestClass tc;
+        EMIT_ALL(CALL, tc.cm_au, m, ;)
+        EMIT_ALL(CALL, tc.cm_ua, m, ;)
+        EMIT_ALL(CALL, tc.cm_aa, m, ;)
+        EMIT_ALL(CALL, tc.cm_ae, m, ;)
+        EMIT_ALL(CALL, tc.cm_ea, m, ;)
+
+        TestClass* tcp = &tc;
+        EMIT_ALL(CALL, tcp->cm_au, m, ;)
+        EMIT_ALL(CALL, tcp->cm_ua, m, ;)
+        EMIT_ALL(CALL, tcp->cm_aa, m, ;)
+        EMIT_ALL(CALL, tcp->cm_ae, m, ;)
+        EMIT_ALL(CALL, tcp->cm_ea, m, ;)
+    })
+
+    // Class Methods (call test).
+    // (declaration)
+    EMIT_ALL(SIG_ANNOTATED, cm_test_caller_smethod, /**/, ;)
+
+    // Inline Class Methods.
+    EMIT_ALL(SIG_ANNOTATED, icm, /**/, {})
+
+    // Inline Class Methods (call test in header).
+    EMIT_ALL(SIG_ANNOTATED, icm_test_caller_smethod_hdr, /**/, {
+        VerilatedMutex m;
+
+        TestClass tc;
+        EMIT_ALL(CALL, tc.icm, m, ;)
+
+        TestClass* tcp = &tc;
+        EMIT_ALL(CALL, tcp->icm, m, ;)
+    })
+
+    // Inline Class Methods (call test).
+    // (declaration)
+    EMIT_ALL(SIG_ANNOTATED, icm_test_caller_smethod, /**/, ;)
+
+    void guarded_by_test_pass(GuardMe& guardme_arg) VL_MT_SAFE {
+        guardme_arg.safe_if_guarded_or_local();
+        int a = guardme_arg;
+        guardme_arg += 4;
+
+        m_mtx.lock();
+        m_guardme.safe_if_guarded_or_local();
+        int b = m_guardme;
+        m_guardme += 4;
+        m_mtx.unlock();
+
+        GuardMe guardme_local;
+        guardme_local.safe_if_guarded_or_local();
+        int c = guardme_local;
+        guardme_local += 4;
+    }
+
+    void guarded_by_test_fail() VL_MT_SAFE {
+        m_guardme_unguarded.safe_if_guarded_or_local();
+        int a = m_guardme_unguarded;
+        m_guardme_unguarded += 4;
+    }
+};
+
+#endif  // T_DIST_ATTRIBUTES_BAD_H_
diff --git a/test_regress/t/t_dist_attributes_bad.out b/test_regress/t/t_dist_attributes_bad.out
new file mode 100644
index 000000000..71a4bd01b
--- /dev/null
+++ b/test_regress/t/t_dist_attributes_bad.out
@@ -0,0 +1,1160 @@
+%Error: "TestClass::cm_ae_NO_ANNOTATION(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:204:    []                                   TestClass::cm_ae_NO_ANNOTATION(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:146:  [mt_safe, pure]                      TestClass::cm_ae_NO_ANNOTATION(VerilatedMutex &)
+
+%Error: "TestClass::cm_ae_VL_ACQUIRE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:204:    [acquire]                            TestClass::cm_ae_VL_ACQUIRE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:146:  [mt_safe, pure, acquire]             TestClass::cm_ae_VL_ACQUIRE(VerilatedMutex &)
+
+%Error: "TestClass::cm_ae_VL_ACQUIRE_SHARED(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:204:    [acquire]                            TestClass::cm_ae_VL_ACQUIRE_SHARED(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:146:  [mt_safe, pure, acquire]             TestClass::cm_ae_VL_ACQUIRE_SHARED(VerilatedMutex &)
+
+%Error: "TestClass::cm_ae_VL_EXCLUDES(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:204:    [excludes]                           TestClass::cm_ae_VL_EXCLUDES(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:146:  [mt_safe, pure, excludes]            TestClass::cm_ae_VL_EXCLUDES(VerilatedMutex &)
+
+%Error: "TestClass::cm_ae_VL_MT_SAFE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:204:    [mt_safe]                            TestClass::cm_ae_VL_MT_SAFE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:146:  [mt_safe, pure]                      TestClass::cm_ae_VL_MT_SAFE(VerilatedMutex &)
+
+%Error: "TestClass::cm_ae_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:204:    [excludes]                           TestClass::cm_ae_VL_MT_SAFE_EXCLUDES(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:146:  [mt_safe, pure, excludes]            TestClass::cm_ae_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+
+%Error: "TestClass::cm_ae_VL_MT_SAFE_POSTINIT(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:204:    [mt_safe_postinit]                   TestClass::cm_ae_VL_MT_SAFE_POSTINIT(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:146:  [mt_safe, mt_safe_postinit, pure]    TestClass::cm_ae_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+
+%Error: "TestClass::cm_ae_VL_MT_START(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:204:    [mt_start]                           TestClass::cm_ae_VL_MT_START(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:146:  [mt_start, mt_safe, pure]            TestClass::cm_ae_VL_MT_START(VerilatedMutex &)
+
+%Error: "TestClass::cm_ae_VL_MT_UNSAFE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:204:    [mt_unsafe]                          TestClass::cm_ae_VL_MT_UNSAFE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:146:  [mt_safe, mt_unsafe, pure]           TestClass::cm_ae_VL_MT_UNSAFE(VerilatedMutex &)
+
+%Error: "TestClass::cm_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:204:    [mt_unsafe_one]                      TestClass::cm_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:146:  [mt_safe, mt_unsafe_one, pure]       TestClass::cm_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::cm_ae_VL_PURE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:204:    [pure]                               TestClass::cm_ae_VL_PURE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:146:  [mt_safe, pure]                      TestClass::cm_ae_VL_PURE(VerilatedMutex &)
+
+%Error: "TestClass::cm_ae_VL_RELEASE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:204:    [release]                            TestClass::cm_ae_VL_RELEASE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:146:  [mt_safe, pure, release]             TestClass::cm_ae_VL_RELEASE(VerilatedMutex &)
+
+%Error: "TestClass::cm_ae_VL_RELEASE_SHARED(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:204:    [release]                            TestClass::cm_ae_VL_RELEASE_SHARED(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:146:  [mt_safe, pure, release]             TestClass::cm_ae_VL_RELEASE_SHARED(VerilatedMutex &)
+
+%Error: "TestClass::cm_ae_VL_REQUIRES(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:204:    [requires]                           TestClass::cm_ae_VL_REQUIRES(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:146:  [mt_safe, pure, requires]            TestClass::cm_ae_VL_REQUIRES(VerilatedMutex &)
+
+%Error: "TestClass::cm_test_caller_smethod_VL_MT_SAFE(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.cpp:155:  [mt_safe]                            TestClass::cm_test_caller_smethod_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [mt_unsafe]                            TestClass::cm_au_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [mt_unsafe_one]                        TestClass::cm_au_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [mt_unsafe]                            TestClass::cm_aa_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [mt_unsafe_one]                        TestClass::cm_aa_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [mt_unsafe]                            TestClass::cm_ae_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [mt_unsafe_one]                        TestClass::cm_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:209:    [mt_safe, mt_unsafe, pure]             TestClass::cm_ea_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:209:    [mt_safe, mt_unsafe_one, pure]         TestClass::cm_ea_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::cm_test_caller_smethod_VL_MT_START(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.cpp:155:  [mt_start]                           TestClass::cm_test_caller_smethod_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [mt_unsafe]                            TestClass::cm_au_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [mt_unsafe_one]                        TestClass::cm_au_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [mt_unsafe]                            TestClass::cm_aa_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [mt_unsafe_one]                        TestClass::cm_aa_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [mt_unsafe]                            TestClass::cm_ae_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [mt_unsafe_one]                        TestClass::cm_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:209:    [mt_safe, mt_unsafe, pure]             TestClass::cm_ea_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:209:    [mt_safe, mt_unsafe_one, pure]         TestClass::cm_ea_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::cm_test_caller_smethod_VL_PURE(VerilatedMutex &)" is pure but calls non-pure function(s)
+t/t_dist_attributes_bad.cpp:155:  [pure]                               TestClass::cm_test_caller_smethod_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    []                                     TestClass::cm_au_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [acquire]                              TestClass::cm_au_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [acquire]                              TestClass::cm_au_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [excludes]                             TestClass::cm_au_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [mt_safe]                              TestClass::cm_au_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [excludes]                             TestClass::cm_au_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [mt_safe_postinit]                     TestClass::cm_au_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [mt_start]                             TestClass::cm_au_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [mt_unsafe]                            TestClass::cm_au_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [mt_unsafe_one]                        TestClass::cm_au_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [release]                              TestClass::cm_au_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [release]                              TestClass::cm_au_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [requires]                             TestClass::cm_au_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    []                                     TestClass::cm_aa_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [acquire]                              TestClass::cm_aa_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [acquire]                              TestClass::cm_aa_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [excludes]                             TestClass::cm_aa_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [mt_safe]                              TestClass::cm_aa_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [excludes]                             TestClass::cm_aa_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [mt_safe_postinit]                     TestClass::cm_aa_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [mt_start]                             TestClass::cm_aa_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [mt_unsafe]                            TestClass::cm_aa_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [mt_unsafe_one]                        TestClass::cm_aa_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [release]                              TestClass::cm_aa_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [release]                              TestClass::cm_aa_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [requires]                             TestClass::cm_aa_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    []                                     TestClass::cm_ae_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [acquire]                              TestClass::cm_ae_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [acquire]                              TestClass::cm_ae_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [excludes]                             TestClass::cm_ae_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [mt_safe]                              TestClass::cm_ae_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [excludes]                             TestClass::cm_ae_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [mt_safe_postinit]                     TestClass::cm_ae_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [mt_start]                             TestClass::cm_ae_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [mt_unsafe]                            TestClass::cm_ae_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [mt_unsafe_one]                        TestClass::cm_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [release]                              TestClass::cm_ae_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [release]                              TestClass::cm_ae_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [requires]                             TestClass::cm_ae_VL_REQUIRES(VerilatedMutex &)
+
+%Error: "TestClass::cm_test_caller_smethod_hdr_VL_MT_SAFE(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.h:212:    [mt_safe]                            TestClass::cm_test_caller_smethod_hdr_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [mt_unsafe]                            TestClass::cm_au_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [mt_unsafe_one]                        TestClass::cm_au_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [mt_unsafe]                            TestClass::cm_aa_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [mt_unsafe_one]                        TestClass::cm_aa_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [mt_unsafe]                            TestClass::cm_ae_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [mt_unsafe_one]                        TestClass::cm_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:209:    [mt_safe, mt_unsafe, pure]             TestClass::cm_ea_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:209:    [mt_safe, mt_unsafe_one, pure]         TestClass::cm_ea_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::cm_test_caller_smethod_hdr_VL_MT_START(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.h:212:    [mt_start]                           TestClass::cm_test_caller_smethod_hdr_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [mt_unsafe]                            TestClass::cm_au_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [mt_unsafe_one]                        TestClass::cm_au_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [mt_unsafe]                            TestClass::cm_aa_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [mt_unsafe_one]                        TestClass::cm_aa_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [mt_unsafe]                            TestClass::cm_ae_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [mt_unsafe_one]                        TestClass::cm_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:209:    [mt_safe, mt_unsafe, pure]             TestClass::cm_ea_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:209:    [mt_safe, mt_unsafe_one, pure]         TestClass::cm_ea_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::cm_test_caller_smethod_hdr_VL_PURE(VerilatedMutex &)" is pure but calls non-pure function(s)
+t/t_dist_attributes_bad.h:212:    [pure]                               TestClass::cm_test_caller_smethod_hdr_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    []                                     TestClass::cm_au_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [acquire]                              TestClass::cm_au_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [acquire]                              TestClass::cm_au_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [excludes]                             TestClass::cm_au_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [mt_safe]                              TestClass::cm_au_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [excludes]                             TestClass::cm_au_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [mt_safe_postinit]                     TestClass::cm_au_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [mt_start]                             TestClass::cm_au_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [mt_unsafe]                            TestClass::cm_au_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [mt_unsafe_one]                        TestClass::cm_au_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [release]                              TestClass::cm_au_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [release]                              TestClass::cm_au_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:191:    [requires]                             TestClass::cm_au_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:195:    []                                     TestClass::cm_ua_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    []                                     TestClass::cm_aa_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [acquire]                              TestClass::cm_aa_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [acquire]                              TestClass::cm_aa_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [excludes]                             TestClass::cm_aa_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [mt_safe]                              TestClass::cm_aa_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [excludes]                             TestClass::cm_aa_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [mt_safe_postinit]                     TestClass::cm_aa_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [mt_start]                             TestClass::cm_aa_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [mt_unsafe]                            TestClass::cm_aa_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [mt_unsafe_one]                        TestClass::cm_aa_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [release]                              TestClass::cm_aa_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [release]                              TestClass::cm_aa_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:199:    [requires]                             TestClass::cm_aa_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    []                                     TestClass::cm_ae_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [acquire]                              TestClass::cm_ae_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [acquire]                              TestClass::cm_ae_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [excludes]                             TestClass::cm_ae_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [mt_safe]                              TestClass::cm_ae_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [excludes]                             TestClass::cm_ae_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [mt_safe_postinit]                     TestClass::cm_ae_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [mt_start]                             TestClass::cm_ae_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [mt_unsafe]                            TestClass::cm_ae_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [mt_unsafe_one]                        TestClass::cm_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [release]                              TestClass::cm_ae_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [release]                              TestClass::cm_ae_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:204:    [requires]                             TestClass::cm_ae_VL_REQUIRES(VerilatedMutex &)
+
+%Error: "TestClass::cm_ua_VL_ACQUIRE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:195:    []                                   TestClass::cm_ua_VL_ACQUIRE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:137:  [acquire]                            TestClass::cm_ua_VL_ACQUIRE(VerilatedMutex &)
+
+%Error: "TestClass::cm_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:195:    []                                   TestClass::cm_ua_VL_ACQUIRE_SHARED(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:137:  [acquire]                            TestClass::cm_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)
+
+%Error: "TestClass::cm_ua_VL_EXCLUDES(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:195:    []                                   TestClass::cm_ua_VL_EXCLUDES(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:137:  [excludes]                           TestClass::cm_ua_VL_EXCLUDES(VerilatedMutex &)
+
+%Error: "TestClass::cm_ua_VL_MT_SAFE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:195:    []                                   TestClass::cm_ua_VL_MT_SAFE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:137:  [mt_safe]                            TestClass::cm_ua_VL_MT_SAFE(VerilatedMutex &)
+
+%Error: "TestClass::cm_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:195:    []                                   TestClass::cm_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:137:  [excludes]                           TestClass::cm_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+
+%Error: "TestClass::cm_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:195:    []                                   TestClass::cm_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:137:  [mt_safe_postinit]                   TestClass::cm_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+
+%Error: "TestClass::cm_ua_VL_MT_START(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:195:    []                                   TestClass::cm_ua_VL_MT_START(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:137:  [mt_start]                           TestClass::cm_ua_VL_MT_START(VerilatedMutex &)
+
+%Error: "TestClass::cm_ua_VL_MT_UNSAFE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:195:    []                                   TestClass::cm_ua_VL_MT_UNSAFE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:137:  [mt_unsafe]                          TestClass::cm_ua_VL_MT_UNSAFE(VerilatedMutex &)
+
+%Error: "TestClass::cm_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:195:    []                                   TestClass::cm_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:137:  [mt_unsafe_one]                      TestClass::cm_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::cm_ua_VL_PURE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:195:    []                                   TestClass::cm_ua_VL_PURE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:137:  [pure]                               TestClass::cm_ua_VL_PURE(VerilatedMutex &)
+
+%Error: "TestClass::cm_ua_VL_RELEASE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:195:    []                                   TestClass::cm_ua_VL_RELEASE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:137:  [release]                            TestClass::cm_ua_VL_RELEASE(VerilatedMutex &)
+
+%Error: "TestClass::cm_ua_VL_RELEASE_SHARED(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:195:    []                                   TestClass::cm_ua_VL_RELEASE_SHARED(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:137:  [release]                            TestClass::cm_ua_VL_RELEASE_SHARED(VerilatedMutex &)
+
+%Error: "TestClass::cm_ua_VL_REQUIRES(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:195:    []                                   TestClass::cm_ua_VL_REQUIRES(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:137:  [requires]                           TestClass::cm_ua_VL_REQUIRES(VerilatedMutex &)
+
+%Error: "TestClass::guarded_by_test_fail()" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.h:269:    [mt_safe]                            TestClass::guarded_by_test_fail()
+t/t_dist_attributes_bad.h:104:    []                                     GuardMe::safe_if_guarded_or_local()
+t/t_dist_attributes_bad.h:106:    []                                     GuardMe::operator int()
+t/t_dist_attributes_bad.h:108:    []                                     GuardMe::operator+=(int)
+
+%Error: "TestClass::icm_test_caller_smethod_VL_MT_SAFE(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.cpp:175:  [mt_safe]                            TestClass::icm_test_caller_smethod_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [mt_unsafe]                            TestClass::icm_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [mt_unsafe_one]                        TestClass::icm_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::icm_test_caller_smethod_VL_MT_START(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.cpp:175:  [mt_start]                           TestClass::icm_test_caller_smethod_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [mt_unsafe]                            TestClass::icm_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [mt_unsafe_one]                        TestClass::icm_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::icm_test_caller_smethod_VL_PURE(VerilatedMutex &)" is pure but calls non-pure function(s)
+t/t_dist_attributes_bad.cpp:175:  [pure]                               TestClass::icm_test_caller_smethod_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    []                                     TestClass::icm_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [acquire]                              TestClass::icm_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [acquire]                              TestClass::icm_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [excludes]                             TestClass::icm_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [mt_safe]                              TestClass::icm_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [excludes]                             TestClass::icm_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [mt_safe_postinit]                     TestClass::icm_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [mt_start]                             TestClass::icm_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [mt_unsafe]                            TestClass::icm_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [mt_unsafe_one]                        TestClass::icm_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [release]                              TestClass::icm_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [release]                              TestClass::icm_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [requires]                             TestClass::icm_VL_REQUIRES(VerilatedMutex &)
+
+%Error: "TestClass::icm_test_caller_smethod_hdr_VL_MT_SAFE(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.h:238:    [mt_safe]                            TestClass::icm_test_caller_smethod_hdr_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [mt_unsafe]                            TestClass::icm_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [mt_unsafe_one]                        TestClass::icm_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::icm_test_caller_smethod_hdr_VL_MT_START(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.h:238:    [mt_start]                           TestClass::icm_test_caller_smethod_hdr_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [mt_unsafe]                            TestClass::icm_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [mt_unsafe_one]                        TestClass::icm_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::icm_test_caller_smethod_hdr_VL_PURE(VerilatedMutex &)" is pure but calls non-pure function(s)
+t/t_dist_attributes_bad.h:238:    [pure]                               TestClass::icm_test_caller_smethod_hdr_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    []                                     TestClass::icm_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [acquire]                              TestClass::icm_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [acquire]                              TestClass::icm_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [excludes]                             TestClass::icm_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [mt_safe]                              TestClass::icm_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [excludes]                             TestClass::icm_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [mt_safe_postinit]                     TestClass::icm_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [mt_start]                             TestClass::icm_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [mt_unsafe]                            TestClass::icm_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [mt_unsafe_one]                        TestClass::icm_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [release]                              TestClass::icm_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [release]                              TestClass::icm_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:235:    [requires]                             TestClass::icm_VL_REQUIRES(VerilatedMutex &)
+
+%Error: "TestClass::iscm_test_caller_smethod_VL_MT_SAFE(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.cpp:119:  [mt_safe]                            TestClass::iscm_test_caller_smethod_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    []                                     TestClass::iscm_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_start]                             TestClass::iscm_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_unsafe]                            TestClass::iscm_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_unsafe_one]                        TestClass::iscm_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::iscm_test_caller_smethod_VL_MT_START(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.cpp:119:  [mt_start]                           TestClass::iscm_test_caller_smethod_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    []                                     TestClass::iscm_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_start]                             TestClass::iscm_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_unsafe]                            TestClass::iscm_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_unsafe_one]                        TestClass::iscm_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::iscm_test_caller_smethod_VL_PURE(VerilatedMutex &)" is pure but calls non-pure function(s)
+t/t_dist_attributes_bad.cpp:119:  [pure]                               TestClass::iscm_test_caller_smethod_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    []                                     TestClass::iscm_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [acquire]                              TestClass::iscm_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [acquire]                              TestClass::iscm_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [excludes]                             TestClass::iscm_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_safe]                              TestClass::iscm_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [excludes]                             TestClass::iscm_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_safe_postinit]                     TestClass::iscm_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_start]                             TestClass::iscm_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_unsafe]                            TestClass::iscm_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_unsafe_one]                        TestClass::iscm_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [release]                              TestClass::iscm_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [release]                              TestClass::iscm_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [requires]                             TestClass::iscm_VL_REQUIRES(VerilatedMutex &)
+
+%Error: "TestClass::iscm_test_caller_smethod_hdr_VL_MT_SAFE(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.h:173:    [mt_safe]                            TestClass::iscm_test_caller_smethod_hdr_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    []                                     TestClass::iscm_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_start]                             TestClass::iscm_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_unsafe]                            TestClass::iscm_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_unsafe_one]                        TestClass::iscm_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::iscm_test_caller_smethod_hdr_VL_MT_START(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.h:173:    [mt_start]                           TestClass::iscm_test_caller_smethod_hdr_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    []                                     TestClass::iscm_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_start]                             TestClass::iscm_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_unsafe]                            TestClass::iscm_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_unsafe_one]                        TestClass::iscm_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::iscm_test_caller_smethod_hdr_VL_PURE(VerilatedMutex &)" is pure but calls non-pure function(s)
+t/t_dist_attributes_bad.h:173:    [pure]                               TestClass::iscm_test_caller_smethod_hdr_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    []                                     TestClass::iscm_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [acquire]                              TestClass::iscm_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [acquire]                              TestClass::iscm_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [excludes]                             TestClass::iscm_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_safe]                              TestClass::iscm_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [excludes]                             TestClass::iscm_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_safe_postinit]                     TestClass::iscm_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_start]                             TestClass::iscm_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_unsafe]                            TestClass::iscm_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [mt_unsafe_one]                        TestClass::iscm_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [release]                              TestClass::iscm_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [release]                              TestClass::iscm_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:170:    [requires]                             TestClass::iscm_VL_REQUIRES(VerilatedMutex &)
+
+%Error: "TestClass::scm_ae_NO_ANNOTATION(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:133:    []                                   TestClass::scm_ae_NO_ANNOTATION(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:84:   [mt_safe, pure]                      TestClass::scm_ae_NO_ANNOTATION(VerilatedMutex &)
+
+%Error: "TestClass::scm_ae_VL_ACQUIRE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:133:    [acquire]                            TestClass::scm_ae_VL_ACQUIRE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:84:   [mt_safe, pure, acquire]             TestClass::scm_ae_VL_ACQUIRE(VerilatedMutex &)
+
+%Error: "TestClass::scm_ae_VL_ACQUIRE_SHARED(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:133:    [acquire]                            TestClass::scm_ae_VL_ACQUIRE_SHARED(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:84:   [mt_safe, pure, acquire]             TestClass::scm_ae_VL_ACQUIRE_SHARED(VerilatedMutex &)
+
+%Error: "TestClass::scm_ae_VL_EXCLUDES(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:133:    [excludes]                           TestClass::scm_ae_VL_EXCLUDES(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:84:   [mt_safe, pure, excludes]            TestClass::scm_ae_VL_EXCLUDES(VerilatedMutex &)
+
+%Error: "TestClass::scm_ae_VL_MT_SAFE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:133:    [mt_safe]                            TestClass::scm_ae_VL_MT_SAFE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:84:   [mt_safe, pure]                      TestClass::scm_ae_VL_MT_SAFE(VerilatedMutex &)
+
+%Error: "TestClass::scm_ae_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:133:    [excludes]                           TestClass::scm_ae_VL_MT_SAFE_EXCLUDES(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:84:   [mt_safe, pure, excludes]            TestClass::scm_ae_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+
+%Error: "TestClass::scm_ae_VL_MT_SAFE_POSTINIT(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:133:    [mt_safe_postinit]                   TestClass::scm_ae_VL_MT_SAFE_POSTINIT(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:84:   [mt_safe, mt_safe_postinit, pure]    TestClass::scm_ae_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+
+%Error: "TestClass::scm_ae_VL_MT_START(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:133:    [mt_start]                           TestClass::scm_ae_VL_MT_START(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:84:   [mt_start, mt_safe, pure]            TestClass::scm_ae_VL_MT_START(VerilatedMutex &)
+
+%Error: "TestClass::scm_ae_VL_MT_UNSAFE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:133:    [mt_unsafe]                          TestClass::scm_ae_VL_MT_UNSAFE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:84:   [mt_safe, mt_unsafe, pure]           TestClass::scm_ae_VL_MT_UNSAFE(VerilatedMutex &)
+
+%Error: "TestClass::scm_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:133:    [mt_unsafe_one]                      TestClass::scm_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:84:   [mt_safe, mt_unsafe_one, pure]       TestClass::scm_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::scm_ae_VL_PURE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:133:    [pure]                               TestClass::scm_ae_VL_PURE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:84:   [mt_safe, pure]                      TestClass::scm_ae_VL_PURE(VerilatedMutex &)
+
+%Error: "TestClass::scm_ae_VL_RELEASE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:133:    [release]                            TestClass::scm_ae_VL_RELEASE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:84:   [mt_safe, pure, release]             TestClass::scm_ae_VL_RELEASE(VerilatedMutex &)
+
+%Error: "TestClass::scm_ae_VL_RELEASE_SHARED(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:133:    [release]                            TestClass::scm_ae_VL_RELEASE_SHARED(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:84:   [mt_safe, pure, release]             TestClass::scm_ae_VL_RELEASE_SHARED(VerilatedMutex &)
+
+%Error: "TestClass::scm_ae_VL_REQUIRES(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:133:    [requires]                           TestClass::scm_ae_VL_REQUIRES(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:84:   [mt_safe, pure, requires]            TestClass::scm_ae_VL_REQUIRES(VerilatedMutex &)
+
+%Error: "TestClass::scm_test_caller_smethod_VL_MT_SAFE(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.cpp:93:   [mt_safe]                            TestClass::scm_test_caller_smethod_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    []                                     TestClass::scm_au_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_start]                             TestClass::scm_au_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_unsafe]                            TestClass::scm_au_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_unsafe_one]                        TestClass::scm_au_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    []                                     TestClass::scm_aa_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_start]                             TestClass::scm_aa_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_unsafe]                            TestClass::scm_aa_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_unsafe_one]                        TestClass::scm_aa_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    []                                     TestClass::scm_ae_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_start]                             TestClass::scm_ae_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_unsafe]                            TestClass::scm_ae_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_unsafe_one]                        TestClass::scm_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:138:    [mt_safe, mt_unsafe, pure]             TestClass::scm_ea_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:138:    [mt_safe, mt_unsafe_one, pure]         TestClass::scm_ea_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::scm_test_caller_smethod_VL_MT_START(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.cpp:93:   [mt_start]                           TestClass::scm_test_caller_smethod_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    []                                     TestClass::scm_au_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_start]                             TestClass::scm_au_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_unsafe]                            TestClass::scm_au_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_unsafe_one]                        TestClass::scm_au_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    []                                     TestClass::scm_aa_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_start]                             TestClass::scm_aa_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_unsafe]                            TestClass::scm_aa_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_unsafe_one]                        TestClass::scm_aa_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    []                                     TestClass::scm_ae_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_start]                             TestClass::scm_ae_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_unsafe]                            TestClass::scm_ae_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_unsafe_one]                        TestClass::scm_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:138:    [mt_safe, mt_unsafe, pure]             TestClass::scm_ea_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:138:    [mt_safe, mt_unsafe_one, pure]         TestClass::scm_ea_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::scm_test_caller_smethod_VL_PURE(VerilatedMutex &)" is pure but calls non-pure function(s)
+t/t_dist_attributes_bad.cpp:93:   [pure]                               TestClass::scm_test_caller_smethod_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    []                                     TestClass::scm_au_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [acquire]                              TestClass::scm_au_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [acquire]                              TestClass::scm_au_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [excludes]                             TestClass::scm_au_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_safe]                              TestClass::scm_au_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [excludes]                             TestClass::scm_au_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_safe_postinit]                     TestClass::scm_au_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_start]                             TestClass::scm_au_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_unsafe]                            TestClass::scm_au_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_unsafe_one]                        TestClass::scm_au_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [release]                              TestClass::scm_au_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [release]                              TestClass::scm_au_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [requires]                             TestClass::scm_au_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    []                                     TestClass::scm_aa_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [acquire]                              TestClass::scm_aa_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [acquire]                              TestClass::scm_aa_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [excludes]                             TestClass::scm_aa_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_safe]                              TestClass::scm_aa_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [excludes]                             TestClass::scm_aa_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_safe_postinit]                     TestClass::scm_aa_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_start]                             TestClass::scm_aa_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_unsafe]                            TestClass::scm_aa_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_unsafe_one]                        TestClass::scm_aa_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [release]                              TestClass::scm_aa_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [release]                              TestClass::scm_aa_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [requires]                             TestClass::scm_aa_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    []                                     TestClass::scm_ae_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [acquire]                              TestClass::scm_ae_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [acquire]                              TestClass::scm_ae_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [excludes]                             TestClass::scm_ae_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_safe]                              TestClass::scm_ae_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [excludes]                             TestClass::scm_ae_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_safe_postinit]                     TestClass::scm_ae_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_start]                             TestClass::scm_ae_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_unsafe]                            TestClass::scm_ae_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_unsafe_one]                        TestClass::scm_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [release]                              TestClass::scm_ae_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [release]                              TestClass::scm_ae_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [requires]                             TestClass::scm_ae_VL_REQUIRES(VerilatedMutex &)
+
+%Error: "TestClass::scm_test_caller_smethod_hdr_VL_MT_SAFE(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.h:141:    [mt_safe]                            TestClass::scm_test_caller_smethod_hdr_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    []                                     TestClass::scm_au_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_start]                             TestClass::scm_au_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_unsafe]                            TestClass::scm_au_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_unsafe_one]                        TestClass::scm_au_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    []                                     TestClass::scm_aa_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_start]                             TestClass::scm_aa_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_unsafe]                            TestClass::scm_aa_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_unsafe_one]                        TestClass::scm_aa_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    []                                     TestClass::scm_ae_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_start]                             TestClass::scm_ae_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_unsafe]                            TestClass::scm_ae_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_unsafe_one]                        TestClass::scm_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:138:    [mt_safe, mt_unsafe, pure]             TestClass::scm_ea_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:138:    [mt_safe, mt_unsafe_one, pure]         TestClass::scm_ea_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::scm_test_caller_smethod_hdr_VL_MT_START(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.h:141:    [mt_start]                           TestClass::scm_test_caller_smethod_hdr_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    []                                     TestClass::scm_au_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_start]                             TestClass::scm_au_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_unsafe]                            TestClass::scm_au_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_unsafe_one]                        TestClass::scm_au_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    []                                     TestClass::scm_aa_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_start]                             TestClass::scm_aa_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_unsafe]                            TestClass::scm_aa_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_unsafe_one]                        TestClass::scm_aa_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    []                                     TestClass::scm_ae_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_start]                             TestClass::scm_ae_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_unsafe]                            TestClass::scm_ae_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_unsafe_one]                        TestClass::scm_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:138:    [mt_safe, mt_unsafe, pure]             TestClass::scm_ea_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:138:    [mt_safe, mt_unsafe_one, pure]         TestClass::scm_ea_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::scm_test_caller_smethod_hdr_VL_PURE(VerilatedMutex &)" is pure but calls non-pure function(s)
+t/t_dist_attributes_bad.h:141:    [pure]                               TestClass::scm_test_caller_smethod_hdr_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    []                                     TestClass::scm_au_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [acquire]                              TestClass::scm_au_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [acquire]                              TestClass::scm_au_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [excludes]                             TestClass::scm_au_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_safe]                              TestClass::scm_au_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [excludes]                             TestClass::scm_au_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_safe_postinit]                     TestClass::scm_au_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_start]                             TestClass::scm_au_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_unsafe]                            TestClass::scm_au_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [mt_unsafe_one]                        TestClass::scm_au_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [release]                              TestClass::scm_au_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [release]                              TestClass::scm_au_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:120:    [requires]                             TestClass::scm_au_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:124:    []                                     TestClass::scm_ua_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    []                                     TestClass::scm_aa_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [acquire]                              TestClass::scm_aa_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [acquire]                              TestClass::scm_aa_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [excludes]                             TestClass::scm_aa_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_safe]                              TestClass::scm_aa_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [excludes]                             TestClass::scm_aa_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_safe_postinit]                     TestClass::scm_aa_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_start]                             TestClass::scm_aa_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_unsafe]                            TestClass::scm_aa_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [mt_unsafe_one]                        TestClass::scm_aa_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [release]                              TestClass::scm_aa_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [release]                              TestClass::scm_aa_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:128:    [requires]                             TestClass::scm_aa_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    []                                     TestClass::scm_ae_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [acquire]                              TestClass::scm_ae_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [acquire]                              TestClass::scm_ae_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [excludes]                             TestClass::scm_ae_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_safe]                              TestClass::scm_ae_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [excludes]                             TestClass::scm_ae_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_safe_postinit]                     TestClass::scm_ae_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_start]                             TestClass::scm_ae_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_unsafe]                            TestClass::scm_ae_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [mt_unsafe_one]                        TestClass::scm_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [release]                              TestClass::scm_ae_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [release]                              TestClass::scm_ae_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:133:    [requires]                             TestClass::scm_ae_VL_REQUIRES(VerilatedMutex &)
+
+%Error: "TestClass::scm_ua_VL_ACQUIRE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:124:    []                                   TestClass::scm_ua_VL_ACQUIRE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:75:   [acquire]                            TestClass::scm_ua_VL_ACQUIRE(VerilatedMutex &)
+
+%Error: "TestClass::scm_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:124:    []                                   TestClass::scm_ua_VL_ACQUIRE_SHARED(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:75:   [acquire]                            TestClass::scm_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)
+
+%Error: "TestClass::scm_ua_VL_EXCLUDES(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:124:    []                                   TestClass::scm_ua_VL_EXCLUDES(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:75:   [excludes]                           TestClass::scm_ua_VL_EXCLUDES(VerilatedMutex &)
+
+%Error: "TestClass::scm_ua_VL_MT_SAFE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:124:    []                                   TestClass::scm_ua_VL_MT_SAFE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:75:   [mt_safe]                            TestClass::scm_ua_VL_MT_SAFE(VerilatedMutex &)
+
+%Error: "TestClass::scm_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:124:    []                                   TestClass::scm_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:75:   [excludes]                           TestClass::scm_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+
+%Error: "TestClass::scm_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:124:    []                                   TestClass::scm_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:75:   [mt_safe_postinit]                   TestClass::scm_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+
+%Error: "TestClass::scm_ua_VL_MT_START(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:124:    []                                   TestClass::scm_ua_VL_MT_START(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:75:   [mt_start]                           TestClass::scm_ua_VL_MT_START(VerilatedMutex &)
+
+%Error: "TestClass::scm_ua_VL_MT_UNSAFE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:124:    []                                   TestClass::scm_ua_VL_MT_UNSAFE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:75:   [mt_unsafe]                          TestClass::scm_ua_VL_MT_UNSAFE(VerilatedMutex &)
+
+%Error: "TestClass::scm_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:124:    []                                   TestClass::scm_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:75:   [mt_unsafe_one]                      TestClass::scm_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "TestClass::scm_ua_VL_PURE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:124:    []                                   TestClass::scm_ua_VL_PURE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:75:   [pure]                               TestClass::scm_ua_VL_PURE(VerilatedMutex &)
+
+%Error: "TestClass::scm_ua_VL_RELEASE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:124:    []                                   TestClass::scm_ua_VL_RELEASE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:75:   [release]                            TestClass::scm_ua_VL_RELEASE(VerilatedMutex &)
+
+%Error: "TestClass::scm_ua_VL_RELEASE_SHARED(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:124:    []                                   TestClass::scm_ua_VL_RELEASE_SHARED(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:75:   [release]                            TestClass::scm_ua_VL_RELEASE_SHARED(VerilatedMutex &)
+
+%Error: "TestClass::scm_ua_VL_REQUIRES(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:124:    []                                   TestClass::scm_ua_VL_REQUIRES(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:75:   [requires]                           TestClass::scm_ua_VL_REQUIRES(VerilatedMutex &)
+
+%Error: "ifh_test_caller_func_VL_MT_SAFE(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.cpp:53:   [mt_safe]                            ifh_test_caller_func_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     []                                     ifh_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_start]                             ifh_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_unsafe]                            ifh_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_unsafe_one]                        ifh_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "ifh_test_caller_func_VL_MT_START(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.cpp:53:   [mt_start]                           ifh_test_caller_func_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     []                                     ifh_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_start]                             ifh_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_unsafe]                            ifh_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_unsafe_one]                        ifh_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "ifh_test_caller_func_VL_PURE(VerilatedMutex &)" is pure but calls non-pure function(s)
+t/t_dist_attributes_bad.cpp:53:   [pure]                               ifh_test_caller_func_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     []                                     ifh_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [acquire]                              ifh_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [acquire]                              ifh_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [excludes]                             ifh_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_safe]                              ifh_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [excludes]                             ifh_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_safe_postinit]                     ifh_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_start]                             ifh_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_unsafe]                            ifh_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_unsafe_one]                        ifh_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [release]                              ifh_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [release]                              ifh_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [requires]                             ifh_VL_REQUIRES(VerilatedMutex &)
+
+%Error: "ifh_test_caller_func_hdr_VL_MT_SAFE(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.h:97:     [mt_safe]                            ifh_test_caller_func_hdr_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     []                                     ifh_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_start]                             ifh_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_unsafe]                            ifh_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_unsafe_one]                        ifh_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "ifh_test_caller_func_hdr_VL_MT_START(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.h:97:     [mt_start]                           ifh_test_caller_func_hdr_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     []                                     ifh_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_start]                             ifh_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_unsafe]                            ifh_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_unsafe_one]                        ifh_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "ifh_test_caller_func_hdr_VL_PURE(VerilatedMutex &)" is pure but calls non-pure function(s)
+t/t_dist_attributes_bad.h:97:     [pure]                               ifh_test_caller_func_hdr_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     []                                     ifh_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [acquire]                              ifh_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [acquire]                              ifh_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [excludes]                             ifh_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_safe]                              ifh_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [excludes]                             ifh_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_safe_postinit]                     ifh_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_start]                             ifh_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_unsafe]                            ifh_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [mt_unsafe_one]                        ifh_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [release]                              ifh_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [release]                              ifh_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:94:     [requires]                             ifh_VL_REQUIRES(VerilatedMutex &)
+
+%Error: "nsf_ae_NO_ANNOTATION(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:75:     []                                   nsf_ae_NO_ANNOTATION(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:34:   [mt_safe, pure]                      nsf_ae_NO_ANNOTATION(VerilatedMutex &)
+
+%Error: "nsf_ae_VL_ACQUIRE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:75:     [acquire]                            nsf_ae_VL_ACQUIRE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:34:   [mt_safe, pure, acquire]             nsf_ae_VL_ACQUIRE(VerilatedMutex &)
+
+%Error: "nsf_ae_VL_ACQUIRE_SHARED(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:75:     [acquire]                            nsf_ae_VL_ACQUIRE_SHARED(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:34:   [mt_safe, pure, acquire]             nsf_ae_VL_ACQUIRE_SHARED(VerilatedMutex &)
+
+%Error: "nsf_ae_VL_EXCLUDES(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:75:     [excludes]                           nsf_ae_VL_EXCLUDES(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:34:   [mt_safe, pure, excludes]            nsf_ae_VL_EXCLUDES(VerilatedMutex &)
+
+%Error: "nsf_ae_VL_MT_SAFE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:75:     [mt_safe]                            nsf_ae_VL_MT_SAFE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:34:   [mt_safe, pure]                      nsf_ae_VL_MT_SAFE(VerilatedMutex &)
+
+%Error: "nsf_ae_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:75:     [excludes]                           nsf_ae_VL_MT_SAFE_EXCLUDES(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:34:   [mt_safe, pure, excludes]            nsf_ae_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+
+%Error: "nsf_ae_VL_MT_SAFE_POSTINIT(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:75:     [mt_safe_postinit]                   nsf_ae_VL_MT_SAFE_POSTINIT(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:34:   [mt_safe, mt_safe_postinit, pure]    nsf_ae_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+
+%Error: "nsf_ae_VL_MT_START(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:75:     [mt_start]                           nsf_ae_VL_MT_START(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:34:   [mt_start, mt_safe, pure]            nsf_ae_VL_MT_START(VerilatedMutex &)
+
+%Error: "nsf_ae_VL_MT_UNSAFE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:75:     [mt_unsafe]                          nsf_ae_VL_MT_UNSAFE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:34:   [mt_safe, mt_unsafe, pure]           nsf_ae_VL_MT_UNSAFE(VerilatedMutex &)
+
+%Error: "nsf_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:75:     [mt_unsafe_one]                      nsf_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:34:   [mt_safe, mt_unsafe_one, pure]       nsf_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "nsf_ae_VL_PURE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:75:     [pure]                               nsf_ae_VL_PURE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:34:   [mt_safe, pure]                      nsf_ae_VL_PURE(VerilatedMutex &)
+
+%Error: "nsf_ae_VL_RELEASE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:75:     [release]                            nsf_ae_VL_RELEASE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:34:   [mt_safe, pure, release]             nsf_ae_VL_RELEASE(VerilatedMutex &)
+
+%Error: "nsf_ae_VL_RELEASE_SHARED(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:75:     [release]                            nsf_ae_VL_RELEASE_SHARED(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:34:   [mt_safe, pure, release]             nsf_ae_VL_RELEASE_SHARED(VerilatedMutex &)
+
+%Error: "nsf_ae_VL_REQUIRES(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:75:     [requires]                           nsf_ae_VL_REQUIRES(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:34:   [mt_safe, pure, requires]            nsf_ae_VL_REQUIRES(VerilatedMutex &)
+
+%Error: "nsf_test_caller_func_VL_MT_SAFE(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.cpp:42:   [mt_safe]                            nsf_test_caller_func_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     []                                     nsf_au_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_start]                             nsf_au_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_unsafe]                            nsf_au_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_unsafe_one]                        nsf_au_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     []                                     nsf_aa_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_start]                             nsf_aa_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_unsafe]                            nsf_aa_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_unsafe_one]                        nsf_aa_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     []                                     nsf_ae_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_start]                             nsf_ae_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_unsafe]                            nsf_ae_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_unsafe_one]                        nsf_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:80:     [mt_safe, mt_unsafe, pure]             nsf_ea_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:80:     [mt_safe, mt_unsafe_one, pure]         nsf_ea_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "nsf_test_caller_func_VL_MT_START(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.cpp:42:   [mt_start]                           nsf_test_caller_func_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     []                                     nsf_au_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_start]                             nsf_au_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_unsafe]                            nsf_au_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_unsafe_one]                        nsf_au_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     []                                     nsf_aa_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_start]                             nsf_aa_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_unsafe]                            nsf_aa_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_unsafe_one]                        nsf_aa_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     []                                     nsf_ae_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_start]                             nsf_ae_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_unsafe]                            nsf_ae_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_unsafe_one]                        nsf_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:80:     [mt_safe, mt_unsafe, pure]             nsf_ea_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:80:     [mt_safe, mt_unsafe_one, pure]         nsf_ea_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "nsf_test_caller_func_VL_PURE(VerilatedMutex &)" is pure but calls non-pure function(s)
+t/t_dist_attributes_bad.cpp:42:   [pure]                               nsf_test_caller_func_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     []                                     nsf_au_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [acquire]                              nsf_au_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [acquire]                              nsf_au_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [excludes]                             nsf_au_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_safe]                              nsf_au_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [excludes]                             nsf_au_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_safe_postinit]                     nsf_au_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_start]                             nsf_au_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_unsafe]                            nsf_au_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_unsafe_one]                        nsf_au_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [release]                              nsf_au_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [release]                              nsf_au_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [requires]                             nsf_au_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     []                                     nsf_aa_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [acquire]                              nsf_aa_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [acquire]                              nsf_aa_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [excludes]                             nsf_aa_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_safe]                              nsf_aa_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [excludes]                             nsf_aa_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_safe_postinit]                     nsf_aa_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_start]                             nsf_aa_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_unsafe]                            nsf_aa_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_unsafe_one]                        nsf_aa_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [release]                              nsf_aa_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [release]                              nsf_aa_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [requires]                             nsf_aa_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     []                                     nsf_ae_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [acquire]                              nsf_ae_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [acquire]                              nsf_ae_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [excludes]                             nsf_ae_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_safe]                              nsf_ae_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [excludes]                             nsf_ae_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_safe_postinit]                     nsf_ae_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_start]                             nsf_ae_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_unsafe]                            nsf_ae_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_unsafe_one]                        nsf_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [release]                              nsf_ae_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [release]                              nsf_ae_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [requires]                             nsf_ae_VL_REQUIRES(VerilatedMutex &)
+
+%Error: "nsf_test_caller_func_hdr_VL_MT_SAFE(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.h:83:     [mt_safe]                            nsf_test_caller_func_hdr_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     []                                     nsf_au_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_start]                             nsf_au_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_unsafe]                            nsf_au_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_unsafe_one]                        nsf_au_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     []                                     nsf_aa_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_start]                             nsf_aa_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_unsafe]                            nsf_aa_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_unsafe_one]                        nsf_aa_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     []                                     nsf_ae_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_start]                             nsf_ae_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_unsafe]                            nsf_ae_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_unsafe_one]                        nsf_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:80:     [mt_safe, mt_unsafe, pure]             nsf_ea_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:80:     [mt_safe, mt_unsafe_one, pure]         nsf_ea_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "nsf_test_caller_func_hdr_VL_MT_START(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.h:83:     [mt_start]                           nsf_test_caller_func_hdr_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     []                                     nsf_au_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_start]                             nsf_au_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_unsafe]                            nsf_au_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_unsafe_one]                        nsf_au_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     []                                     nsf_aa_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_start]                             nsf_aa_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_unsafe]                            nsf_aa_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_unsafe_one]                        nsf_aa_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     []                                     nsf_ae_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_start]                             nsf_ae_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_unsafe]                            nsf_ae_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_unsafe_one]                        nsf_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:80:     [mt_safe, mt_unsafe, pure]             nsf_ea_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:80:     [mt_safe, mt_unsafe_one, pure]         nsf_ea_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "nsf_test_caller_func_hdr_VL_PURE(VerilatedMutex &)" is pure but calls non-pure function(s)
+t/t_dist_attributes_bad.h:83:     [pure]                               nsf_test_caller_func_hdr_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     []                                     nsf_au_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [acquire]                              nsf_au_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [acquire]                              nsf_au_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [excludes]                             nsf_au_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_safe]                              nsf_au_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [excludes]                             nsf_au_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_safe_postinit]                     nsf_au_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_start]                             nsf_au_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_unsafe]                            nsf_au_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [mt_unsafe_one]                        nsf_au_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [release]                              nsf_au_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [release]                              nsf_au_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:62:     [requires]                             nsf_au_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:66:     []                                     nsf_ua_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     []                                     nsf_aa_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [acquire]                              nsf_aa_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [acquire]                              nsf_aa_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [excludes]                             nsf_aa_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_safe]                              nsf_aa_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [excludes]                             nsf_aa_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_safe_postinit]                     nsf_aa_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_start]                             nsf_aa_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_unsafe]                            nsf_aa_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [mt_unsafe_one]                        nsf_aa_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [release]                              nsf_aa_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [release]                              nsf_aa_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:70:     [requires]                             nsf_aa_VL_REQUIRES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     []                                     nsf_ae_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [acquire]                              nsf_ae_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [acquire]                              nsf_ae_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [excludes]                             nsf_ae_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_safe]                              nsf_ae_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [excludes]                             nsf_ae_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_safe_postinit]                     nsf_ae_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_start]                             nsf_ae_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_unsafe]                            nsf_ae_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [mt_unsafe_one]                        nsf_ae_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [release]                              nsf_ae_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [release]                              nsf_ae_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.h:75:     [requires]                             nsf_ae_VL_REQUIRES(VerilatedMutex &)
+
+%Error: "nsf_ua_VL_ACQUIRE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:66:     []                                   nsf_ua_VL_ACQUIRE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:25:   [acquire]                            nsf_ua_VL_ACQUIRE(VerilatedMutex &)
+
+%Error: "nsf_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:66:     []                                   nsf_ua_VL_ACQUIRE_SHARED(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:25:   [acquire]                            nsf_ua_VL_ACQUIRE_SHARED(VerilatedMutex &)
+
+%Error: "nsf_ua_VL_EXCLUDES(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:66:     []                                   nsf_ua_VL_EXCLUDES(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:25:   [excludes]                           nsf_ua_VL_EXCLUDES(VerilatedMutex &)
+
+%Error: "nsf_ua_VL_MT_SAFE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:66:     []                                   nsf_ua_VL_MT_SAFE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:25:   [mt_safe]                            nsf_ua_VL_MT_SAFE(VerilatedMutex &)
+
+%Error: "nsf_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:66:     []                                   nsf_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:25:   [excludes]                           nsf_ua_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+
+%Error: "nsf_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:66:     []                                   nsf_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:25:   [mt_safe_postinit]                   nsf_ua_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+
+%Error: "nsf_ua_VL_MT_START(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:66:     []                                   nsf_ua_VL_MT_START(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:25:   [mt_start]                           nsf_ua_VL_MT_START(VerilatedMutex &)
+
+%Error: "nsf_ua_VL_MT_UNSAFE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:66:     []                                   nsf_ua_VL_MT_UNSAFE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:25:   [mt_unsafe]                          nsf_ua_VL_MT_UNSAFE(VerilatedMutex &)
+
+%Error: "nsf_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:66:     []                                   nsf_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:25:   [mt_unsafe_one]                      nsf_ua_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "nsf_ua_VL_PURE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:66:     []                                   nsf_ua_VL_PURE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:25:   [pure]                               nsf_ua_VL_PURE(VerilatedMutex &)
+
+%Error: "nsf_ua_VL_RELEASE(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:66:     []                                   nsf_ua_VL_RELEASE(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:25:   [release]                            nsf_ua_VL_RELEASE(VerilatedMutex &)
+
+%Error: "nsf_ua_VL_RELEASE_SHARED(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:66:     []                                   nsf_ua_VL_RELEASE_SHARED(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:25:   [release]                            nsf_ua_VL_RELEASE_SHARED(VerilatedMutex &)
+
+%Error: "nsf_ua_VL_REQUIRES(VerilatedMutex &)" declaration does not match definition
+t/t_dist_attributes_bad.h:66:     []                                   nsf_ua_VL_REQUIRES(VerilatedMutex &) [declaration]
+t/t_dist_attributes_bad.cpp:25:   [requires]                           nsf_ua_VL_REQUIRES(VerilatedMutex &)
+
+%Error: "sfc_test_caller_func_VL_MT_SAFE(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.cpp:63:   [mt_safe]                            sfc_test_caller_func_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   []                                     sfc_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   [mt_start]                             sfc_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   [mt_unsafe]                            sfc_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   [mt_unsafe_one]                        sfc_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "sfc_test_caller_func_VL_MT_START(VerilatedMutex &)" is mtsafe but calls non-mtsafe function(s)
+t/t_dist_attributes_bad.cpp:63:   [mt_start]                           sfc_test_caller_func_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   []                                     sfc_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   [mt_start]                             sfc_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   [mt_unsafe]                            sfc_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   [mt_unsafe_one]                        sfc_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+
+%Error: "sfc_test_caller_func_VL_PURE(VerilatedMutex &)" is pure but calls non-pure function(s)
+t/t_dist_attributes_bad.cpp:63:   [pure]                               sfc_test_caller_func_VL_PURE(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   []                                     sfc_NO_ANNOTATION(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   [acquire]                              sfc_VL_ACQUIRE(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   [acquire]                              sfc_VL_ACQUIRE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   [excludes]                             sfc_VL_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   [mt_safe]                              sfc_VL_MT_SAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   [excludes]                             sfc_VL_MT_SAFE_EXCLUDES(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   [mt_safe_postinit]                     sfc_VL_MT_SAFE_POSTINIT(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   [mt_start]                             sfc_VL_MT_START(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   [mt_unsafe]                            sfc_VL_MT_UNSAFE(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   [mt_unsafe_one]                        sfc_VL_MT_UNSAFE_ONE(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   [release]                              sfc_VL_RELEASE(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   [release]                              sfc_VL_RELEASE_SHARED(VerilatedMutex &)
+t/t_dist_attributes_bad.cpp:60:   [requires]                             sfc_VL_REQUIRES(VerilatedMutex &)
+Number of functions reported unsafe: 220
diff --git a/test_regress/t/t_dist_attributes_bad.pl b/test_regress/t/t_dist_attributes_bad.pl
new file mode 100755
index 000000000..15a8060cf
--- /dev/null
+++ b/test_regress/t/t_dist_attributes_bad.pl
@@ -0,0 +1,44 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 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(dist => 1);
+if ($ENV{VERILATOR_TEST_NO_ATTRIBUTES}) {
+    skip("Skipping due to VERILATOR_TEST_NO_ATTRIBUTES");
+} else {
+    check();
+}
+sub check {
+    my $root = "..";
+    my @srcfiles = glob("$root/test_regress/t/t_dist_attributes_bad.cpp");
+    my $srcfiles_str = join(" ", @srcfiles);
+    my $clang_args = "-I$root/include";
+
+    sub run_clang_check {
+        {
+            my $cmd = qq{python3 -c "from clang.cindex import Index; index = Index.create(); print(\\"Clang imported\\")";};
+            print "\t$cmd\n" if $::Debug;
+            my $out = `$cmd`;
+            if (!$out || $out !~ /Clang imported/) { skip("No libclang installed\n"); return 1; }
+        }
+        run(logfile => $Self->{run_log_filename},
+            tee => 1,
+            # With `--verilator-root` set to the current directory
+            # (i.e. `test_regress`) the script will skip annotation issues in
+            # headers from the `../include` directory.
+            cmd => ["python3", "$root/nodist/clang_check_attributes --verilator-root=. --cxxflags='$clang_args' $srcfiles_str"]);
+
+        files_identical($Self->{run_log_filename}, $Self->{golden_filename});
+    }
+
+    run_clang_check();
+}
+
+ok(1);
+1;
diff --git a/test_regress/t/t_dist_copyright.pl b/test_regress/t/t_dist_copyright.pl
new file mode 100755
index 000000000..e69ddb798
--- /dev/null
+++ b/test_regress/t/t_dist_copyright.pl
@@ -0,0 +1,104 @@
+#!/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
+
+use IO::File;
+use POSIX qw(strftime);
+use strict;
+
+scenarios(dist => 1);
+
+our $Release_Ok_Re = qr!(^test_regress/t/|^examples/)!;
+our $Exempt_Author_Re = qr!(^ci/|^nodist/fastcov.py|^nodist/fuzzer|^test_regress/t/.*\.(v|cpp|h)$)!;
+our $Exempt_Files_Re = qr!(^\.|/\.|\.gitignore$|\.dat|\.gprof|\.mem|\.out$|\.png$|\.tree|\.vc$|\.vcd$|^\.)!;
+our @Exempt_Files_List = qw(
+    Artistic
+    CPPLINT.cfg
+    LICENSE
+    README.rst
+    ci/ci-win-compile.ps1
+    ci/ci-win-test.ps1
+    ci/coverage-upload.sh
+    docs/CONTRIBUTING.rst
+    docs/CONTRIBUTORS
+    docs/_static
+    docs/gen
+    docs/spelling.txt
+    docs/verilated.dox
+    include/gtkwave
+    include/vltstd
+    install-sh
+    src/mkinstalldirs
+    test_regress/t/t_altera_lpm.v
+    test_regress/t/t_flag_f__3.v
+    test_regress/t/t_fuzz_eof_bad.v
+    test_regress/t/t_incr_void.v
+    test_regress/t/t_timing_trace_fst.pl
+    test_regress/t/t_wrapper_context.pl
+    test_regress/t/t_wrapper_context_fst.pl
+    test_regress/t/t_wrapper_context_seq.pl
+    test_regress/t/t_wrapper_del_context_bad.pl
+    test_regress/t/tsub/t_flag_f_tsub.v
+    test_regress/t/tsub/t_flag_f_tsub_inc.v
+    verilator.pc.in
+    );
+
+my $root = "..";
+my $Debug;
+
+my $Exempt_Files_List_Re = '^(' . join('|', (map { quotemeta $_ } @Exempt_Files_List)) . ")";
+
+if (!-r "$root/.git") {
+    skip("Not in a git repository");
+} else {
+    my $files = `cd $root && git ls-files --exclude-standard`;
+    my $year = strftime("%Y", localtime);
+
+    $files =~ s/\s+/ /g;
+    foreach my $filename (split /\s+/, $files) {
+        next if $filename =~ /$Exempt_Files_Re/;
+        next if $filename =~ /$Exempt_Files_List_Re/;
+        my $fh = IO::File->new("<$root/$filename") or error("$! $filename");
+        my $spdx;
+        my $copyright;
+        my $release;
+        while (my $line = $fh->getline) {
+            if ($line =~ /SPDX-License-Identifier:/) {
+                $spdx = $line;
+            } elsif ($line =~ /Copyright 20[0-9][0-9]/) {
+                $copyright = $line;
+                if ($line !~ /Wilson Snyder|Geza Lore/
+                    && !($filename =~ /test_regress/ && $line =~ /Antmicro|Todd Strader/)) {
+                    my $yeardash = ($filename =~ m!test_regress/t!) ? $year : $year."-".$year;
+                    if ($filename !~ /$Exempt_Author_Re/) {
+                        warn "   ".$copyright;
+                        error("$filename: Please use standard 'Copyright $yeardash by Wilson Snyder'");
+                    }
+                }
+            } elsif ($line =~ m!Creative Commons Public Domain!
+                     || $line =~ m!freely copied and/or distributed!
+                     || $line =~ m!placed into the Public Domain!) {
+                $release = 1;
+            }
+        }
+        my $release_note;
+        if ($release && $filename !~ /$Release_Ok_Re/) {
+            $release_note = " (has copyright release, but not part of $Release_Ok_Re)";
+        }
+        if (!$copyright && (!$release || $release_note)) {
+            error("$filename: Please add standard 'Copyright $year ...', similar to in other files" . $release_note);
+        }
+        if (!$spdx) {
+            error("$filename: Please add standard 'SPDX-License_Identifier: ...', similar to in other files");
+        }
+    }
+}
+
+ok(1);
+1;
diff --git a/test_regress/t/t_dist_tabs.pl b/test_regress/t/t_dist_tabs.pl
index f1bb39258..1f4a6b734 100755
--- a/test_regress/t/t_dist_tabs.pl
+++ b/test_regress/t/t_dist_tabs.pl
@@ -12,7 +12,7 @@ scenarios(dist => 1);
 
 my $root = "..";
 
-my $Tabs_Exempt_Re = qr!(\.out$)|(/gtkwave)|(Makefile)|(\.mk$)|(nodist/fastcov.py)!;
+my $Tabs_Exempt_Re = qr!(\.out$)|(/gtkwave)|(Makefile)|(\.mk$)|(\.mk\.in$)|(nodist/fastcov.py)!;
 #my $Wide_Exempt_Re = qr!(\.l$)|(\.y$)!;
 my $Wide_Exempt_Re = qr!.*!;  # clang-tidy generally cleans up
 
@@ -94,7 +94,7 @@ sub _has_tabs {
     if ($filename =~ /\.out$/) {
         # Ignore golden files
     } elsif ($contents =~ /[\001\002\003\004\005\006]/) {
-        # Ignore binrary files
+        # Ignore binary files
     } elsif ($contents =~ /\t/) {
         return 1;
     }
diff --git a/test_regress/t/t_dist_untracked.pl b/test_regress/t/t_dist_untracked.pl
index 254e6aa3d..a8f155d03 100755
--- a/test_regress/t/t_dist_untracked.pl
+++ b/test_regress/t/t_dist_untracked.pl
@@ -49,7 +49,7 @@ sub _has_tabs {
     if ($filename =~ /\.out$/) {
         # Ignore golden files
     } elsif ($contents =~ /[\001\002\003\004\005\006]/) {
-        # Ignore binrary files
+        # Ignore binary files
     } elsif ($contents =~ /\t/) {
         return 1;
     }
diff --git a/test_regress/t/t_dist_warn_coverage.pl b/test_regress/t/t_dist_warn_coverage.pl
index 85ce9260f..258b74a8f 100755
--- a/test_regress/t/t_dist_warn_coverage.pl
+++ b/test_regress/t/t_dist_warn_coverage.pl
@@ -23,6 +23,7 @@ my %Suppressed;
 foreach my $s (
     ' exited with ',  # Is hit; driver.pl filters out
     'EOF in unterminated string',  # Instead get normal unterminated
+    'Enum names without values only allowed on numeric types',  # Hard to hit
     'Enum ranges must be integral, per spec',  # Hard to hit
     'Return with return value isn\'t underneath a function',  # Hard to hit, get other bad return messages
     'Select from non-array ',  # Instead get type does not have a bit range
@@ -32,8 +33,6 @@ foreach my $s (
     # Not yet analyzed
     ' is not an in/out/inout/param/interface: ',
     ' loading non-variable',
-    '$fopen mode should be <= 4 characters',
-    '\'foreach\' loop variable expects simple variable name',
     '--pipe-filter protocol error, unexpected: ',
     '/*verilator sformat*/ can only be applied to last argument of ',
     'Argument needed for string.',
@@ -44,7 +43,6 @@ foreach my $s (
     'Assignment pattern with no members',
     'Assignment pattern with too many elements',
     'Attempted parameter setting of non-parameter: Param ',
-    'Attempting to extend using a non-class ',
     'Can\'t find varpin scope of ',
     'Can\'t resolve module reference: \'',
     'Cannot mix DPI import, DPI export, class methods, and/or public ',
@@ -52,7 +50,6 @@ foreach my $s (
     'Circular logic when ordering code (non-cutable edge loop)',
     'Deferred assertions must use \'#0\' (IEEE 1800-2017 16.4)',
     'Define or directive not defined: `',
-    'Enum names without values only allowed on numeric types',
     'Exceeded limit of ',
     'Extern declaration\'s scope is not a defined class',
     'Format to $display-like function must have constant format string',
@@ -68,7 +65,6 @@ foreach my $s (
     'Modport item not found: ',
     'Modport not referenced as .',
     'Modport not referenced from underneath an interface: ',
-    'Multiple \'{ default: } clauses',
     'Non-interface used as an interface: ',
     'Not marked as function return var',
     'Parameter not found in sub-module: Param ',
@@ -89,7 +85,6 @@ foreach my $s (
     'Unknown `pragma',
     'Unknown built-in event method ',
     'Unsized numbers/parameters not allowed in streams.',
-    'Unsupported LHS tristate construct: ',
     'Unsupported RHS tristate construct: ',
     'Unsupported or syntax error: Unsized range in instance or other declaration',
     'Unsupported pullup/down (weak driver) construct.',
@@ -99,7 +94,6 @@ foreach my $s (
     'Unsupported/unknown built-in dynamic array method ',
     'Unsupported: $bits for queue',
     'Unsupported: $c can\'t generate wider than 64 bits',
-    'Unsupported: --no-structs-packed',
     'Unsupported: 4-state numbers in this context',
     'Unsupported: Concatenation to form ',
     'Unsupported: Non-variable on LHS of built-in method \'',
@@ -119,6 +113,7 @@ foreach my $s (
     'Unsupported: no_inline for tasks',
     'Unsupported: static cast to ',
     'Unsupported: super',
+    '\'foreach\' loop variable expects simple variable name',
     ) { $Suppressed{$s} = 1; }
 
 if (!-r "$root/.git") {
diff --git a/test_regress/t/t_dist_whitespace.pl b/test_regress/t/t_dist_whitespace.pl
index 1aaf1975f..3a09d63e7 100755
--- a/test_regress/t/t_dist_whitespace.pl
+++ b/test_regress/t/t_dist_whitespace.pl
@@ -33,8 +33,7 @@ foreach my $file (sort keys %files) {
     }
     if ($contents =~ /[ \t]\n/
         || $contents =~ m/\n\n+$/) {  # Regexp repeated below
-        my $eol_ws_exempt = ($file =~ /(\.txt|\.html)$/
-                             || $file =~ m!^README$!
+        my $eol_ws_exempt = ($file =~ /spelling.txt$/
                              || $file =~ m!/gtkwave/!);
         next if $eol_ws_exempt;
         if ($ENV{HARNESS_UPDATE_GOLDEN}) {
@@ -50,7 +49,7 @@ foreach my $file (sort keys %files) {
         my $line_no = 0;
         foreach my $line (@lines) {
             $line_no++;
-            # Trim trailing carriage-return (ascii 0xd) and form feed (0xc),
+            # Trim trailing carriage-return (ASCII 0x0d) and form feed (0x0c),
             # as we expect a few of those
             $line =~ s/[\x{d}\x{c}]//g;
             if ($line =~ /\s$/) {
@@ -62,6 +61,16 @@ foreach my $file (sort keys %files) {
             $warns{$file} = "Trailing newlines at EOF in $file";
         }
     }
+    # Unicode checker; should this be done in another file?
+    # No way to auto-fix.
+    # Files with \r are flagged elsewhere, right?
+    if ($contents =~ /[^[:alnum:][:punct:] \t\r\n]/) {
+        my $unicode_exempt = ($file =~ /Changes$/
+                              || $file =~ /CONTRIBUTORS$/
+                              || $file =~ /contributors.rst$/);
+        next if $unicode_exempt;
+        $warns{$file} = "Warning: non-ASCII contents in $file\n";
+    }
     ++$any;
 }
 $any > 50 or error("Too few source files found");
diff --git a/test_regress/t/t_dotfiles.pl b/test_regress/t/t_dotfiles.pl
index 9df77e2ca..c60055256 100755
--- a/test_regress/t/t_dotfiles.pl
+++ b/test_regress/t/t_dotfiles.pl
@@ -23,7 +23,7 @@ foreach my $dotname ("linkcells", "task_call", "gate_simp", "gate_opt",
         "ordermv_initial", "ordermv_hazards", "ordermv_contraction",
         "ordermv_transitive1", "orderg_done", "ordermv_transitive2", "schedule") {
     # Some files with identical prefix are generated multiple times during
-    # verilation. Ensure that at least one of each $dotname-prefixed file is generated.
+    # Verilation. Ensure that at least one of each $dotname-prefixed file is generated.
     @dotFiles = glob("$Self->{obj_dir}/*$dotname.dot");
     if (scalar @dotFiles == 0) {
         error("Found no dotfiles with pattern *$dotname.dot");
diff --git a/test_regress/t/t_dpi_accessors.cpp b/test_regress/t/t_dpi_accessors.cpp
index 3ccae802c..cf13572d4 100644
--- a/test_regress/t/t_dpi_accessors.cpp
+++ b/test_regress/t/t_dpi_accessors.cpp
@@ -172,7 +172,7 @@ int main() {
         logRegHex(dut->clk, "read mem32", 8, mem32, " (after clk)");
 
         // In this case, the value never changes. But we should check it is
-        // waht we expect (0x20).
+        // what we expect (0x20).
         checkResult(mem32 == 0x20, "Test of array element reading failed.");
     }
 
@@ -487,7 +487,7 @@ int main() {
         logRegHex(dut->clk, "read  mem32 [7:6,2:0]", 5, mem32_slice, " (after clk)");
 
         // We have already tested that array element writing works, so we just
-        // check that dhe slice of "mem32" after the clock is the
+        // check that the slice of "mem32" after the clock is the
         // concatenation of the top 2 and bottom 3 bits of "mem32"
         checkResult(mem32_slice == (((mem32 & 0xc0) >> 3) | (mem32 & 0x07)),
                     "Test of array element slice writing failed.");
diff --git a/test_regress/t/t_dpi_export_context2_bad.cpp b/test_regress/t/t_dpi_export_context2_bad.cpp
index ec2b10216..4c4eeb82a 100644
--- a/test_regress/t/t_dpi_export_context2_bad.cpp
+++ b/test_regress/t/t_dpi_export_context2_bad.cpp
@@ -22,9 +22,10 @@ double sc_time_stamp() { return main_time; }
 VM_PREFIX* topp = nullptr;
 
 int main(int argc, char* argv[]) {
-    topp = new VM_PREFIX;
-
     Verilated::debug(0);
+    Verilated::commandArgs(argc, argv);
+
+    topp = new VM_PREFIX;
 
     topp->eval();
     VL_DO_DANGLING(delete topp, topp);
diff --git a/test_regress/t/t_dpi_export_context_bad.cpp b/test_regress/t/t_dpi_export_context_bad.cpp
index 407c8b5b4..27a58730a 100644
--- a/test_regress/t/t_dpi_export_context_bad.cpp
+++ b/test_regress/t/t_dpi_export_context_bad.cpp
@@ -38,9 +38,10 @@ double sc_time_stamp() { return main_time; }
 VM_PREFIX* topp = nullptr;
 
 int main(int argc, char* argv[]) {
-    topp = new VM_PREFIX;
-
     Verilated::debug(0);
+    Verilated::commandArgs(argc, argv);
+
+    topp = new VM_PREFIX;
 
     topp->eval();
     dpix_task();  // Missing svSetScope
diff --git a/test_regress/t/t_dpi_export_scope_bad.cpp b/test_regress/t/t_dpi_export_scope_bad.cpp
index 0a19d5add..e6a04e849 100644
--- a/test_regress/t/t_dpi_export_scope_bad.cpp
+++ b/test_regress/t/t_dpi_export_scope_bad.cpp
@@ -28,9 +28,10 @@ double sc_time_stamp() { return main_time; }
 VM_PREFIX* topp = nullptr;
 
 int main(int argc, char* argv[]) {
-    topp = new VM_PREFIX;
-
     Verilated::debug(0);
+    Verilated::commandArgs(argc, argv);
+
+    topp = new VM_PREFIX;
 
     topp->eval();
 
diff --git a/test_regress/t/t_dpi_open_query.cpp b/test_regress/t/t_dpi_open_query.cpp
index 021e6ef53..53864a6bb 100644
--- a/test_regress/t/t_dpi_open_query.cpp
+++ b/test_regress/t/t_dpi_open_query.cpp
@@ -31,7 +31,7 @@
 
 // These are simple wrappers for the array querying functions themselves,
 // see IEEE 1800-2017 H.12.2. Sadly on the SV side these have different
-// signagures, and hence need to have different names here as well.
+// signatures, and hence need to have different names here as well.
 
 // 1 open dimension
 int cSvLeft1(const svOpenArrayHandle h, int d) { return svLeft(h, d); }
diff --git a/test_regress/t/t_dpi_result_type_bad.out b/test_regress/t/t_dpi_result_type_bad.out
index b95b58dc6..4c3e82ffe 100644
--- a/test_regress/t/t_dpi_result_type_bad.out
+++ b/test_regress/t/t_dpi_result_type_bad.out
@@ -1,65 +1,65 @@
 %Error: t/t_dpi_result_type_bad.v:79:40: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                       : ... Suggest make it an output argument instead?
    79 |    import "DPI-C" function bit [ 32:0] i_array_2_state_33();
       |                                        ^~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:80:40: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                       : ... Suggest make it an output argument instead?
    80 |    import "DPI-C" function bit [ 63:0] i_array_2_state_64();
       |                                        ^~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:81:40: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                       : ... Suggest make it an output argument instead?
    81 |    import "DPI-C" function bit [ 64:0] i_array_2_state_65();
       |                                        ^~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:82:40: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                       : ... Suggest make it an output argument instead?
    82 |    import "DPI-C" function bit [127:0] i_array_2_state_128();
       |                                        ^~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:85:48: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                       : ... Suggest make it an output argument instead?
    85 |    import "DPI-C" function array_2_state_33_t  i_array_2_state_33_t();
       |                                                ^~~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:86:48: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                       : ... Suggest make it an output argument instead?
    86 |    import "DPI-C" function array_2_state_64_t  i_array_2_state_64_t();
       |                                                ^~~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:87:48: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                       : ... Suggest make it an output argument instead?
    87 |    import "DPI-C" function array_2_state_65_t  i_array_2_state_65_t();
       |                                                ^~~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:88:48: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                       : ... Suggest make it an output argument instead?
    88 |    import "DPI-C" function array_2_state_128_t i_array_2_state_128_t();
       |                                                ^~~~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:91:47: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                       : ... Suggest make it an output argument instead?
    91 |    import "DPI-C" function struct_2_state_33  i_struct_2_state_33();
       |                                               ^~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:92:47: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                       : ... Suggest make it an output argument instead?
    92 |    import "DPI-C" function struct_2_state_64  i_struct_2_state_64();
       |                                               ^~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:93:47: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                       : ... Suggest make it an output argument instead?
    93 |    import "DPI-C" function struct_2_state_65  i_struct_2_state_65();
       |                                               ^~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:94:47: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                       : ... Suggest make it an output argument instead?
    94 |    import "DPI-C" function struct_2_state_128 i_struct_2_state_128();
       |                                               ^~~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:97:46: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                       : ... Suggest make it an output argument instead?
    97 |    import "DPI-C" function union_2_state_33  i_union_2_state_33();
       |                                              ^~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:98:46: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                       : ... Suggest make it an output argument instead?
    98 |    import "DPI-C" function union_2_state_64  i_union_2_state_64();
       |                                              ^~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:99:46: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                       : ... Suggest make it an output argument instead?
    99 |    import "DPI-C" function union_2_state_65  i_union_2_state_65();
       |                                              ^~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:100:46: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                        : ... Suggest make it an output argument instead?
   100 |    import "DPI-C" function union_2_state_128 i_union_2_state_128();
       |                                              ^~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:103:36: DPI function may not return a 4-state type other than a single 'logic' (IEEE 1800-2017 35.5.5)
@@ -198,67 +198,67 @@
   155 |    import "DPI-C" function union_4_state_128 i_union_4_state_128();
       |                                              ^~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:245:25: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                        : ... Suggest make it an output argument instead?
   245 |    function bit [ 32:0] e_array_2_state_33();  return 0; endfunction
       |                         ^~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:246:25: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                        : ... Suggest make it an output argument instead?
   246 |    function bit [ 63:0] e_array_2_state_64();  return 0; endfunction
       |                         ^~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:247:25: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                        : ... Suggest make it an output argument instead?
   247 |    function bit [ 64:0] e_array_2_state_65();  return 0; endfunction
       |                         ^~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:248:25: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                        : ... Suggest make it an output argument instead?
   248 |    function bit [127:0] e_array_2_state_128(); return 0; endfunction
       |                         ^~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:251:33: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                        : ... Suggest make it an output argument instead?
   251 |    function array_2_state_33_t  e_array_2_state_33_t();  return 0; endfunction
       |                                 ^~~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:252:33: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                        : ... Suggest make it an output argument instead?
   252 |    function array_2_state_64_t  e_array_2_state_64_t();  return 0; endfunction
       |                                 ^~~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:253:33: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                        : ... Suggest make it an output argument instead?
   253 |    function array_2_state_65_t  e_array_2_state_65_t();  return 0; endfunction
       |                                 ^~~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:254:33: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                        : ... Suggest make it an output argument instead?
   254 |    function array_2_state_128_t e_array_2_state_128_t(); return 0; endfunction
       |                                 ^~~~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:257:32: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                        : ... Suggest make it an output argument instead?
   257 |    function struct_2_state_33  e_struct_2_state_33();  return 0; endfunction
       |                                ^~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:258:32: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                        : ... Suggest make it an output argument instead?
   258 |    function struct_2_state_64  e_struct_2_state_64();  return 0; endfunction
       |                                ^~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:259:32: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                        : ... Suggest make it an output argument instead?
   259 |    function struct_2_state_65  e_struct_2_state_65();  return 0; endfunction
       |                                ^~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:260:32: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                        : ... Suggest make it an output argument instead?
   260 |    function struct_2_state_128 e_struct_2_state_128(); return 0; endfunction
       |                                ^~~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:263:31: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                        : ... Suggest make it an output argument instead?
   263 |    function union_2_state_33  e_union_2_state_33();  return 0; endfunction
       |                               ^~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:264:31: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                        : ... Suggest make it an output argument instead?
   264 |    function union_2_state_64  e_union_2_state_64();  return 0; endfunction
       |                               ^~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:265:31: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                        : ... Suggest make it an output argument instead?
   265 |    function union_2_state_65  e_union_2_state_65();  return 0; endfunction
       |                               ^~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:266:31: DPI function may not return a > 32 bits wide type other than basic types.
-        ... Suggest make it an output argument instead?
+                                        : ... Suggest make it an output argument instead?
   266 |    function union_2_state_128 e_union_2_state_128(); return 0; endfunction
       |                               ^~~~~~~~~~~~~~~~~~~
 %Error: t/t_dpi_result_type_bad.v:269:21: DPI function may not return a 4-state type other than a single 'logic' (IEEE 1800-2017 35.5.5)
diff --git a/test_regress/t/t_dpi_vams.cpp b/test_regress/t/t_dpi_vams.cpp
index 13ee8b82b..3eed4f0ed 100644
--- a/test_regress/t/t_dpi_vams.cpp
+++ b/test_regress/t/t_dpi_vams.cpp
@@ -40,9 +40,10 @@ double sc_time_stamp() { return main_time; }
 VM_PREFIX* topp = nullptr;
 
 int main(int argc, char* argv[]) {
-    topp = new VM_PREFIX;
-
     Verilated::debug(0);
+    Verilated::commandArgs(argc, argv);
+
+    topp = new VM_PREFIX;
 
     topp->in = 1.1;
     topp->eval();
diff --git a/test_regress/t/t_dpi_var.cpp b/test_regress/t/t_dpi_var.cpp
index d494db7f3..eac0571fe 100644
--- a/test_regress/t/t_dpi_var.cpp
+++ b/test_regress/t/t_dpi_var.cpp
@@ -114,8 +114,8 @@ int main(int argc, char** argv) {
     const std::unique_ptr contextp{new VerilatedContext};
 
     uint64_t sim_time = 1100;
-    contextp->commandArgs(argc, argv);
     contextp->debug(0);
+    contextp->commandArgs(argc, argv);
 
     const std::unique_ptr topp{new VM_PREFIX{contextp.get(),
                                                         // Note null name - we're flattening it out
diff --git a/test_regress/t/t_driver_random.pl b/test_regress/t/t_driver_random.pl
index 6627cfe33..482afba94 100755
--- a/test_regress/t/t_driver_random.pl
+++ b/test_regress/t/t_driver_random.pl
@@ -14,7 +14,8 @@ use Time::HiRes;
 scenarios(dist => 1);
 
 if (!$ENV{VERILATOR_TEST_RANDOM_FAILURE}) {
-    ok("Test is for harness checking only, setenv VERILATOR_TEST_RANDOM_FAILURE=1 ");
+    print("Test is for harness checking only, setenv VERILATOR_TEST_RANDOM_FAILURE=1\n");
+    ok(1);
 } else {
     # Randomly fail to test driver.pl
     my ($ign, $t) = Time::HiRes::gettimeofday();
diff --git a/test_regress/t/t_dynarray_param.v b/test_regress/t/t_dynarray_param.v
index 72098b871..e16635584 100644
--- a/test_regress/t/t_dynarray_param.v
+++ b/test_regress/t/t_dynarray_param.v
@@ -12,7 +12,7 @@ module t(/*AUTOARG*/);
    typedef int    calc_sums_t [3:0];
 
    localparam int SUMS_ARRAY [3:0] = calc_sums_array(SIZES, 4);
-   function calc_sums_t calc_sums_array(int s[3:0], int n);
+   function automatic calc_sums_t calc_sums_array(int s[3:0], int n);
       int sum = 0;
       for (int ii = 0; ii < n; ++ii) begin
          sum = sum + s[ii];
@@ -23,7 +23,7 @@ module t(/*AUTOARG*/);
 `ifndef VERILATOR
    localparam int SUMS_DYN [3:0] = calc_sums_dyn(SIZES, 4);
 `endif
-   function calc_sums_t calc_sums_dyn(int s[], int n);
+   function automatic calc_sums_t calc_sums_dyn(int s[], int n);
       int sum = 0;
       for (int ii = 0; ii < n; ++ii) begin
          sum = sum + s[ii];
diff --git a/test_regress/t/t_enum_public.cpp b/test_regress/t/t_enum_public.cpp
index 2ff06eea5..7bd7c99d5 100644
--- a/test_regress/t/t_enum_public.cpp
+++ b/test_regress/t/t_enum_public.cpp
@@ -15,9 +15,10 @@
 double sc_time_stamp() { return 0; }
 
 int main(int argc, char* argv[]) {
-    Vt_enum_public* topp = new Vt_enum_public;
-
     Verilated::debug(0);
+    Verilated::commandArgs(argc, argv);
+
+    Vt_enum_public* topp = new Vt_enum_public;
 
     // Make sure public tag worked
     if (Vt_enum_public_p3::ZERO == Vt_enum_public_p3::ONE) {}
diff --git a/test_regress/t/t_flag_csplit.pl b/test_regress/t/t_flag_csplit.pl
index c35017122..f4634a9e5 100755
--- a/test_regress/t/t_flag_csplit.pl
+++ b/test_regress/t/t_flag_csplit.pl
@@ -11,7 +11,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 scenarios(vlt_all => 1);
 
 while (1) {
-    # Thi rule requires GNU make > 4.1 (or so, known broken in 3.81)
+    # This rule requires GNU make > 4.1 (or so, known broken in 3.81)
     #%__Slow.o: %__Slow.cpp
     #        $(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_SLOW) -c -o $@ $<
     if (make_version() < 4.1) {
diff --git a/test_regress/t/t_flag_csplit_off.pl b/test_regress/t/t_flag_csplit_off.pl
index 8308d2a93..ae9edfc29 100755
--- a/test_regress/t/t_flag_csplit_off.pl
+++ b/test_regress/t/t_flag_csplit_off.pl
@@ -13,7 +13,7 @@ scenarios(vlt_all => 1);
 top_filename("t/t_flag_csplit.v");
 
 while (1) {
-    # Thi rule requires GNU make > 4.1 (or so, known broken in 3.81)
+    # This rule requires GNU make > 4.1 (or so, known broken in 3.81)
     #%__Slow.o: %__Slow.cpp
     #        $(OBJCACHE) $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(OPT_SLOW) -c -o $@ $<
     if (make_version() < 4.1) {
diff --git a/test_regress/t/t_flag_fi.cpp b/test_regress/t/t_flag_fi.cpp
index 176c434b7..e510f4cee 100644
--- a/test_regress/t/t_flag_fi.cpp
+++ b/test_regress/t/t_flag_fi.cpp
@@ -22,9 +22,10 @@ bool gotit = false;
 void myfunction() { gotit = true; }
 
 int main(int argc, char* argv[]) {
-    topp = new VM_PREFIX;
-
     Verilated::debug(0);
+    Verilated::commandArgs(argc, argv);
+
+    topp = new VM_PREFIX;
 
     topp->eval();
     if (!gotit) vl_fatal(__FILE__, __LINE__, "dut", "Never got call to myfunction");
diff --git a/test_regress/t/t_flag_parameter_hier.pl b/test_regress/t/t_flag_parameter_hier.pl
index c4d9c9bbd..655ecf51b 100755
--- a/test_regress/t/t_flag_parameter_hier.pl
+++ b/test_regress/t/t_flag_parameter_hier.pl
@@ -11,7 +11,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 scenarios(simulator => 1);
 
 compile(
-    # For Verilator, all PARAMs at all levels are overwridden
+    # For Verilator, all PARAMs at all levels are overridden
     # Error if parameter not found
     #verilator_flags2 => ['-GPARAM=10 -Gtop.t.x.HIER=20'],  # HIER would error
     verilator_flags2 => ['-GPARAM=10'],
diff --git a/test_regress/t/t_flag_structs_packed.pl b/test_regress/t/t_flag_structs_packed.pl
new file mode 100755
index 000000000..4f0a79a43
--- /dev/null
+++ b/test_regress/t/t_flag_structs_packed.pl
@@ -0,0 +1,22 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 by Antmicro Ltd. 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);
+
+compile(
+    verilator_flags2 => ['--structs-packed'],
+    );
+
+execute(
+    check_finished => 1,
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_struct_unpacked_bad.v b/test_regress/t/t_flag_structs_packed.v
similarity index 100%
rename from test_regress/t/t_struct_unpacked_bad.v
rename to test_regress/t/t_flag_structs_packed.v
diff --git a/test_regress/t/t_flag_structs_packed_bad.out b/test_regress/t/t_flag_structs_packed_bad.out
new file mode 100644
index 000000000..3ca15d47c
--- /dev/null
+++ b/test_regress/t/t_flag_structs_packed_bad.out
@@ -0,0 +1,5 @@
+%Error: t/t_flag_structs_packed.v:14:19: Unpacked data type in packed struct/union (IEEE 1800-2017 7.2.1)
+                                       : ... In instance x
+   14 |       notpacked_t b;
+      |                   ^
+%Error: Exiting due to
diff --git a/test_regress/t/t_flag_structs_packed_bad.pl b/test_regress/t/t_flag_structs_packed_bad.pl
new file mode 100755
index 000000000..2ac9f69e8
--- /dev/null
+++ b/test_regress/t/t_flag_structs_packed_bad.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
+
+top_filename("t/t_flag_structs_packed.v");
+
+scenarios(linter => 1);
+
+lint(
+    fails => $Self->{vlt_all},
+    expect_filename => $Self->{golden_filename},
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_flag_verilate.pl b/test_regress/t/t_flag_verilate.pl
index 649eac752..bf4061315 100755
--- a/test_regress/t/t_flag_verilate.pl
+++ b/test_regress/t/t_flag_verilate.pl
@@ -23,7 +23,7 @@ compile(  # Don't call cmake nor gmake from driver.pl. Nothing should be done he
                          '../' . $Self->{main_filename}]
     );
 
-# --no-verilate should skip verilation
+# --no-verilate should skip Verilation
 if ( -e $Self->{obj_dir} . '/Vt_flag_verilate.mk' ) {
     $Self->error('Vt_flag_verilate.mk is unexpectedly created');
 }
@@ -41,7 +41,7 @@ if ( ! -e $Self->{obj_dir} . '/Vt_flag_verilate.mk' ) {
     $Self->error('Vt_flag_verilate.mk does not exist');
 }
 
-# Just build, no verilation. .tree must not be saved even with --dump-tree option.
+# Just build, no Verilation. .tree must not be saved even with --dump-tree option.
 compile(  # Don't call cmake nor gmake from driver.pl. Just build here
     verilator_make_cmake => 0,
     verilator_make_gmake => 0,
diff --git a/test_regress/t/t_forceable_net.cpp b/test_regress/t/t_forceable_net.cpp
index 278020f0b..7830e52f0 100644
--- a/test_regress/t/t_forceable_net.cpp
+++ b/test_regress/t/t_forceable_net.cpp
@@ -18,8 +18,8 @@
 
 int main(int argc, char** argv) {
     const std::unique_ptr contextp{new VerilatedContext};
-    contextp->commandArgs(argc, argv);
     contextp->debug(0);
+    contextp->commandArgs(argc, argv);
     srand48(5);
 
     const std::unique_ptr topp{new VM_PREFIX{"top"}};
diff --git a/test_regress/t/t_forceable_var.cpp b/test_regress/t/t_forceable_var.cpp
index 9286d3606..f95b1c27c 100644
--- a/test_regress/t/t_forceable_var.cpp
+++ b/test_regress/t/t_forceable_var.cpp
@@ -18,8 +18,8 @@
 
 int main(int argc, char** argv) {
     const std::unique_ptr contextp{new VerilatedContext};
-    contextp->commandArgs(argc, argv);
     contextp->debug(0);
+    contextp->commandArgs(argc, argv);
     srand48(5);
 
     const std::unique_ptr topp{new VM_PREFIX{"top"}};
diff --git a/test_regress/t/t_foreach_blkname.pl b/test_regress/t/t_foreach_blkname.pl
new file mode 100755
index 000000000..13587bf85
--- /dev/null
+++ b/test_regress/t/t_foreach_blkname.pl
@@ -0,0 +1,17 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2023 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(
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_foreach_blkname.v b/test_regress/t/t_foreach_blkname.v
new file mode 100644
index 000000000..768e7697f
--- /dev/null
+++ b/test_regress/t/t_foreach_blkname.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, 2023 by Wilson Snyder
+// SPDX-License-Identifier: CC0-1.0
+
+module t;
+   function void func();
+      int a[2];
+      begin
+         int t;
+      end
+      foreach (a[i]) begin
+      end
+   endfunction
+endmodule
diff --git a/test_regress/t/t_func_bad.v b/test_regress/t/t_func_bad.v
index d16ecd5e2..835ab2b45 100644
--- a/test_regress/t/t_func_bad.v
+++ b/test_regress/t/t_func_bad.v
@@ -34,7 +34,7 @@ module t;
       hasout = 0;
    endfunction
 
-   function int f( int j = 1, int dup = 0 );
+   function automatic int f( int j = 1, int dup = 0 );
       return (j<<16) | dup;
    endfunction
 
diff --git a/test_regress/t/t_func_const.v b/test_regress/t/t_func_const.v
index 2955bf3d2..2d8487195 100644
--- a/test_regress/t/t_func_const.v
+++ b/test_regress/t/t_func_const.v
@@ -102,7 +102,7 @@ module t;
       endcase
    endfunction
 
-   function integer f_return(input [31:0] a);
+   function automatic integer f_return(input [31:0] a);
       integer out = 2;
       while (1) begin
          out = out+1;
diff --git a/test_regress/t/t_func_const2_bad.pl b/test_regress/t/t_func_const2_bad.pl
index ad607fff5..0fd907991 100755
--- a/test_regress/t/t_func_const2_bad.pl
+++ b/test_regress/t/t_func_const2_bad.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2017 by Todd Strader. This program is free software; you
+# Copyright 2017 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.
diff --git a/test_regress/t/t_func_const3_bad.pl b/test_regress/t/t_func_const3_bad.pl
index 475b114ec..5ece32e17 100755
--- a/test_regress/t/t_func_const3_bad.pl
+++ b/test_regress/t/t_func_const3_bad.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2017 by Todd Strader. This program is free software; you
+# Copyright 2017 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.
@@ -11,7 +11,6 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 scenarios(vlt => 1);
 
 lint(
-    v_flags2 => ["--lint-only"],
     fails => 1,
     expect_filename => $Self->{golden_filename},
     );
diff --git a/test_regress/t/t_func_const_packed_array_bad.pl b/test_regress/t/t_func_const_packed_array_bad.pl
index ad607fff5..0fd907991 100755
--- a/test_regress/t/t_func_const_packed_array_bad.pl
+++ b/test_regress/t/t_func_const_packed_array_bad.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2017 by Todd Strader. This program is free software; you
+# Copyright 2017 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.
diff --git a/test_regress/t/t_func_const_packed_struct_bad.pl b/test_regress/t/t_func_const_packed_struct_bad.pl
index ad607fff5..0fd907991 100755
--- a/test_regress/t/t_func_const_packed_struct_bad.pl
+++ b/test_regress/t/t_func_const_packed_struct_bad.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2017 by Todd Strader. This program is free software; you
+# Copyright 2017 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.
diff --git a/test_regress/t/t_func_const_packed_struct_bad2.pl b/test_regress/t/t_func_const_packed_struct_bad2.pl
index ad607fff5..0fd907991 100755
--- a/test_regress/t/t_func_const_packed_struct_bad2.pl
+++ b/test_regress/t/t_func_const_packed_struct_bad2.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2017 by Todd Strader. This program is free software; you
+# Copyright 2017 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.
diff --git a/test_regress/t/t_func_const_struct_bad.pl b/test_regress/t/t_func_const_struct_bad.pl
index ad607fff5..0fd907991 100755
--- a/test_regress/t/t_func_const_struct_bad.pl
+++ b/test_regress/t/t_func_const_struct_bad.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2017 by Todd Strader. This program is free software; you
+# Copyright 2017 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.
diff --git a/test_regress/t/t_func_default_warn.v b/test_regress/t/t_func_default_warn.v
index bf7ff2eff..fcc89134c 100644
--- a/test_regress/t/t_func_default_warn.v
+++ b/test_regress/t/t_func_default_warn.v
@@ -5,7 +5,7 @@
 // without warranty, 2015 by Todd Strader.
 // SPDX-License-Identifier: CC0-1.0
 
-function logic foo
+function automatic logic foo
   (
    // Intentionally provide a non-width'ed default value
    // This should warn, not error out
diff --git a/test_regress/t/t_func_named.v b/test_regress/t/t_func_named.v
index 2ecd570d7..353232dd2 100644
--- a/test_regress/t/t_func_named.v
+++ b/test_regress/t/t_func_named.v
@@ -6,7 +6,7 @@
 
 module t (/*AUTOARG*/);
 
-   function int f( int j = 1, int s = 0 );
+   function automatic int f( int j = 1, int s = 0 );
       return (j<<16) | s;
    endfunction
 
diff --git a/test_regress/t/t_func_no_lifetime_bad.out b/test_regress/t/t_func_no_lifetime_bad.out
new file mode 100644
index 000000000..ac2132066
--- /dev/null
+++ b/test_regress/t/t_func_no_lifetime_bad.out
@@ -0,0 +1,11 @@
+%Warning-IMPLICITSTATIC: t/t_func_no_lifetime_bad.v:7:14: Function/task's lifetime implicitly set to static
+                                                        : ... Suggest use 'function automatic' or 'function static'
+    7 | function int f_implicit_static();
+      |              ^~~~~~~~~~~~~~~~~
+                         ... For warning description see https://verilator.org/warn/IMPLICITSTATIC?v=latest
+                         ... Use "/* verilator lint_off IMPLICITSTATIC */" and lint_on around source to disable this message.
+%Warning-IMPLICITSTATIC: t/t_func_no_lifetime_bad.v:12:6: Function/task's lifetime implicitly set to static
+                                                        : ... Suggest use 'function automatic' or 'function static'
+   12 | task t_implicit_static();
+      |      ^~~~~~~~~~~~~~~~~
+%Error: Exiting due to
diff --git a/test_regress/t/t_func_no_lifetime_bad.pl b/test_regress/t/t_func_no_lifetime_bad.pl
new file mode 100755
index 000000000..bd07fc421
--- /dev/null
+++ b/test_regress/t/t_func_no_lifetime_bad.pl
@@ -0,0 +1,23 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2023 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(
+    fails => $Self->{vlt_all},
+    expect_filename => $Self->{golden_filename},
+    );
+
+execute(
+    check_finished => 1,
+    ) if !$Self->{vlt_all};
+
+ok(1);
+1;
diff --git a/test_regress/t/t_func_no_lifetime_bad.v b/test_regress/t/t_func_no_lifetime_bad.v
new file mode 100644
index 000000000..e77979cf3
--- /dev/null
+++ b/test_regress/t/t_func_no_lifetime_bad.v
@@ -0,0 +1,39 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2023 by Antmicro Ltd.
+// SPDX-License-Identifier: CC0-1.0
+
+function int f_implicit_static();
+   int cnt = 0;
+   return ++cnt;
+endfunction
+
+task t_implicit_static();
+   int cnt = 0;
+   $display("%d", ++cnt);
+endtask
+
+
+module t (/*AUTOARG*/
+   // Inputs
+   clk
+   );
+
+   // verilator lint_off IMPLICITSTATIC
+   function int f_implicit_but_lint_off();
+      int cnt = 0;
+      return ++cnt;
+   endfunction
+
+   input clk;
+
+   int   a, b;
+   initial begin
+      a = f_implicit_static();
+      t_implicit_static();
+      b = f_implicit_but_lint_off();
+      $stop;
+   end
+
+endmodule
diff --git a/test_regress/t/t_func_rand.cpp b/test_regress/t/t_func_rand.cpp
index d2be39ab9..fdfaba95e 100644
--- a/test_regress/t/t_func_rand.cpp
+++ b/test_regress/t/t_func_rand.cpp
@@ -13,9 +13,10 @@
 double sc_time_stamp() { return 0; }
 
 int main(int argc, char* argv[]) {
-    Vt_func_rand* topp = new Vt_func_rand;
-
     Verilated::debug(0);
+    Verilated::commandArgs(argc, argv);
+
+    Vt_func_rand* topp = new Vt_func_rand;
 
     printf("\nTesting\n");
     for (int i = 0; i < 10; i++) {
diff --git a/test_regress/t/t_func_sel.pl b/test_regress/t/t_func_sel.pl
new file mode 100755
index 000000000..1aa73f80a
--- /dev/null
+++ b/test_regress/t/t_func_sel.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 2022 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_func_sel.v b/test_regress/t/t_func_sel.v
new file mode 100644
index 000000000..53ab12b1f
--- /dev/null
+++ b/test_regress/t/t_func_sel.v
@@ -0,0 +1,63 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// The code as shown applies a random vector to the Test
+// module, then calculates a CRC on the Test module's outputs.
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2022 by Wilson Snyder.
+// SPDX-License-Identifier: CC0-1.0
+
+module t(/*AUTOARG*/
+   // Inputs
+   clk
+   );
+   input clk;
+   parameter W = 104;
+
+   integer cyc = 0;
+   reg [63:0] crc;
+   reg [127:0] sum;
+   wire [127:0] result;
+
+   wire [103:0] in;
+   reg [103:0]  out;
+
+   assign in = {crc[39:0], crc[63:0]};
+
+   always @(posedge clk) begin
+      out <= reverse(in);
+   end
+
+   assign result = {24'h0, out };
+
+   // Test loop
+   always @ (posedge clk) begin
+`ifdef TEST_VERBOSE
+      $write("[%0t] cyc==%0d crc=%x result=%x in=%x out=%x\n",
+             $time, cyc, crc, result, in, out);
+`endif
+      cyc <= cyc + 1;
+      crc <= {crc[62:0], crc[63] ^ crc[2] ^ crc[0]};
+      sum <= {sum[127:1], 1'b0} + result;
+
+      if (cyc < 10) begin
+         crc <= 1;
+         sum <= '0;
+      end
+      else if (cyc >= 90) begin
+         $display("SUM = %x_%x_%x_%x", sum[127:96],
+                  sum[95:64], sum[63:32], sum[31:0]);
+`define EXPECTED_SUM 128'h00002d36_42d1a346_8d1a5936_42d1a319
+         if (sum !== `EXPECTED_SUM) $stop;
+         $write("*-* All Finished *-*\n");
+         $finish;
+      end
+   end
+
+   function [W-1:0] reverse(input [W-1:0] val);
+      integer i;
+      // Bug workaround: reverse = '0;
+      for (i = 0; i < W; i = i + 1)
+        reverse[W-1-i] = val[i];
+   endfunction
+endmodule
diff --git a/test_regress/t/t_func_under.v b/test_regress/t/t_func_under.v
index f4d8f0155..dabe8f2b9 100644
--- a/test_regress/t/t_func_under.v
+++ b/test_regress/t/t_func_under.v
@@ -12,7 +12,7 @@ module t (/*AUTOARG*/
 
    reg [3:0] counter = 0;
    integer   l2;
-   function log2 (input [3:0] x);
+   function automatic log2 (input [3:0] x);
       integer log2 = (x < 2) ? 1 : (x < 4) ? 2 : (x < 8) ? 3 : 4;
    endfunction
    always @(posedge clk) begin
diff --git a/test_regress/t/t_gantt_two.cpp b/test_regress/t/t_gantt_two.cpp
index 04b412836..7b1375126 100644
--- a/test_regress/t/t_gantt_two.cpp
+++ b/test_regress/t/t_gantt_two.cpp
@@ -18,8 +18,8 @@ int main(int argc, char** argv) {
     const std::unique_ptr contextp{new VerilatedContext};
     // VL_USE_THREADS define is set in t_gantt_two.pl
     contextp->threads(TEST_USE_THREADS);
-    contextp->commandArgs(argc, argv);
     contextp->debug(0);
+    contextp->commandArgs(argc, argv);
 
     std::unique_ptr topap{new Vt_gantt_two{contextp.get(), "topa"}};
     std::unique_ptr topbp{new Vt_gantt_two{contextp.get(), "topb"}};
diff --git a/test_regress/t/t_generate_fatal_bad.pl b/test_regress/t/t_generate_fatal_bad.pl
index 0a88b22ae..27159da5b 100755
--- a/test_regress/t/t_generate_fatal_bad.pl
+++ b/test_regress/t/t_generate_fatal_bad.pl
@@ -2,7 +2,7 @@
 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
+# Copyright 2019 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.
diff --git a/test_regress/t/t_hier_block.pl b/test_regress/t/t_hier_block.pl
index 64e8f45ed..620a1c458 100755
--- a/test_regress/t/t_hier_block.pl
+++ b/test_regress/t/t_hier_block.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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
 
 # stats will be deleted but generation will be skipped if libs of hierarchical blocks exist.
 clean_objs();
@@ -14,7 +15,7 @@ scenarios(vlt_all => 1);
 
 # CI 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.
+# So use 6 threads here though it's not optimal in performance, but ok.
 
 compile(
     v_flags2 => ['t/t_hier_block.cpp'],
diff --git a/test_regress/t/t_hier_block.v b/test_regress/t/t_hier_block.v
index e7c67c615..aaf0016f3 100644
--- a/test_regress/t/t_hier_block.v
+++ b/test_regress/t/t_hier_block.v
@@ -2,6 +2,7 @@
 //
 // This file ONLY is placed into the Public Domain, for any use,
 // without warranty, 2020 by Yutetsu TAKATSUKASA
+// SPDX-License-Identifier: Unlicense
 
 `ifdef USE_VLT
 `define HIER_BLOCK
diff --git a/test_regress/t/t_hier_block0_bad.out b/test_regress/t/t_hier_block0_bad.out
index 6f145312f..c3a778047 100644
--- a/test_regress/t/t_hier_block0_bad.out
+++ b/test_regress/t/t_hier_block0_bad.out
@@ -1,12 +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
+%Error: t/t_hier_block0_bad.v:21: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));
+   21 |    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
+%Error: t/t_hier_block0_bad.v:23: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));
+   23 |    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: t/t_hier_block0_bad.v:27:42: Cannot access inside hierarchical block
+   27 |       $display("%d %d %d", count, i_sub0.ff, out1);
       |                                          ^~
 %Error: Exiting due to
diff --git a/test_regress/t/t_hier_block0_bad.pl b/test_regress/t/t_hier_block0_bad.pl
index 640769ddd..39bf8dbac 100755
--- a/test_regress/t/t_hier_block0_bad.pl
+++ b/test_regress/t/t_hier_block0_bad.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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);
 
diff --git a/test_regress/t/t_hier_block0_bad.v b/test_regress/t/t_hier_block0_bad.v
index bcb4ee144..45c0ca79c 100644
--- a/test_regress/t/t_hier_block0_bad.v
+++ b/test_regress/t/t_hier_block0_bad.v
@@ -2,6 +2,7 @@
 //
 // This file ONLY is placed into the Public Domain, for any use,
 // without warranty, 2020 by Yutetsu TAKATSUKASA
+// SPDX-License-Identifier: Unlicense
 
 `define HIER_BLOCK /*verilator hier_block*/
 
diff --git a/test_regress/t/t_hier_block1_bad.out b/test_regress/t/t_hier_block1_bad.out
index 84af5a79c..4e7234c0f 100644
--- a/test_regress/t/t_hier_block1_bad.out
+++ b/test_regress/t/t_hier_block1_bad.out
@@ -1,16 +1,16 @@
-%Warning-HIERBLOCK: t/t_hier_block1_bad.v:15:8: Top module illegally marked hierarchical block, ignoring marking
+%Warning-HIERBLOCK: t/t_hier_block1_bad.v:16:8: Top module illegally marked hierarchical block, ignoring marking
                                               : ... In instance t
-                    ... Suggest remove verilator hier_block on this module
-   15 | module t ( 
+                                              : ... Suggest remove verilator hier_block on this module
+   16 | module t ( 
       |        ^
                     ... For warning description see https://verilator.org/warn/HIERBLOCK?v=latest
                     ... 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
+%Error: t/t_hier_block1_bad.v:45: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*/ 
+   45 | 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
+%Error: t/t_hier_block1_bad.v:45: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*/ 
+   45 | 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
index 640769ddd..39bf8dbac 100755
--- a/test_regress/t/t_hier_block1_bad.pl
+++ b/test_regress/t/t_hier_block1_bad.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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);
 
diff --git a/test_regress/t/t_hier_block1_bad.v b/test_regress/t/t_hier_block1_bad.v
index c42918a47..8427b6c27 100644
--- a/test_regress/t/t_hier_block1_bad.v
+++ b/test_regress/t/t_hier_block1_bad.v
@@ -2,6 +2,7 @@
 //
 // This file ONLY is placed into the Public Domain, for any use,
 // without warranty, 2020 by Yutetsu TAKATSUKASA
+// SPDX-License-Identifier: Unlicense
 
 `define HIER_BLOCK /*verilator hier_block*/
 
diff --git a/test_regress/t/t_hier_block_cmake.pl b/test_regress/t/t_hier_block_cmake.pl
index 5c03ac6eb..8ccd098fa 100755
--- a/test_regress/t/t_hier_block_cmake.pl
+++ b/test_regress/t/t_hier_block_cmake.pl
@@ -6,8 +6,9 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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
 
-# If a test fails, broken .cmake may distrub the next run
+# If a test fails, broken .cmake may disturb the next run
 clean_objs();
 
 scenarios(simulator => 1);
diff --git a/test_regress/t/t_hier_block_cmake/CMakeLists.txt b/test_regress/t/t_hier_block_cmake/CMakeLists.txt
index 6e7c91bbe..645be0795 100644
--- a/test_regress/t/t_hier_block_cmake/CMakeLists.txt
+++ b/test_regress/t/t_hier_block_cmake/CMakeLists.txt
@@ -24,4 +24,3 @@ set(VERILATOR_OPTIONS "${VERILATOR_OPTIONS}" --hierarchical --stats --CFLAGS "-p
 
 verilate(t_hier_block_cmake VERILATOR_ARGS ${VERILATOR_OPTIONS} SOURCES
     ../t_hier_block.v )
-
diff --git a/test_regress/t/t_hier_block_libmod.pl b/test_regress/t/t_hier_block_libmod.pl
index 6fcdd000e..4f6d583d9 100755
--- a/test_regress/t/t_hier_block_libmod.pl
+++ b/test_regress/t/t_hier_block_libmod.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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_all => 1);
 
diff --git a/test_regress/t/t_hier_block_libmod.v b/test_regress/t/t_hier_block_libmod.v
index deaeb9fe2..91a96da98 100644
--- a/test_regress/t/t_hier_block_libmod.v
+++ b/test_regress/t/t_hier_block_libmod.v
@@ -2,6 +2,7 @@
 //
 // This file ONLY is placed into the Public Domain, for any use,
 // without warranty, 2020 by Yutetsu TAKATSUKASA
+// SPDX-License-Identifier: Unlicense
 
 module t;
    t_flag_relinc_sub i_t_flag_relinc_sub();
diff --git a/test_regress/t/t_hier_block_nohier.pl b/test_regress/t/t_hier_block_nohier.pl
index 97586ec08..9b5be406b 100755
--- a/test_regress/t/t_hier_block_nohier.pl
+++ b/test_regress/t/t_hier_block_nohier.pl
@@ -6,8 +6,9 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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 test makes sure that the intenral check of t_hier_block.v is correct.
+# This test makes sure that the internal 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.
@@ -18,7 +19,7 @@ top_filename("t/t_hier_block.v");
 
 # CI 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.
+# So use 6 threads here though it's not optimal in performance, but ok.
 compile(
     v_flags2 => ['t/t_hier_block.cpp'],
     verilator_flags2 => ['--stats',
diff --git a/test_regress/t/t_hier_block_prot_lib.pl b/test_regress/t/t_hier_block_prot_lib.pl
index c48b890ec..13cf91c7a 100755
--- a/test_regress/t/t_hier_block_prot_lib.pl
+++ b/test_regress/t/t_hier_block_prot_lib.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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
 
 top_filename("t/t_hier_block.v");
 
diff --git a/test_regress/t/t_hier_block_prot_lib_shared.pl b/test_regress/t/t_hier_block_prot_lib_shared.pl
index 0abe249aa..0e5239345 100755
--- a/test_regress/t/t_hier_block_prot_lib_shared.pl
+++ b/test_regress/t/t_hier_block_prot_lib_shared.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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
 
 top_filename("t/t_hier_block.v");
 
diff --git a/test_regress/t/t_hier_block_sc.pl b/test_regress/t/t_hier_block_sc.pl
index b2264712f..4a14b17d5 100755
--- a/test_regress/t/t_hier_block_sc.pl
+++ b/test_regress/t/t_hier_block_sc.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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
 
 # stats will be deleted but generation will be skipped if libs of hierarchical blocks exist.
 clean_objs();
@@ -14,7 +15,7 @@ top_filename("t/t_hier_block.v");
 
 # CI 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.
+# So use 6 threads here though it's not optimal in performance, but ok.
 scenarios(vlt_all => 1);
 
 compile(
diff --git a/test_regress/t/t_hier_block_sc_trace_fst.pl b/test_regress/t/t_hier_block_sc_trace_fst.pl
index 331f3fe87..8eb7a21c9 100755
--- a/test_regress/t/t_hier_block_sc_trace_fst.pl
+++ b/test_regress/t/t_hier_block_sc_trace_fst.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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
 
 # stats will be deleted but generation will be skipped if libs of hierarchical blocks exist.
 clean_objs();
@@ -14,7 +15,7 @@ top_filename("t/t_hier_block.v");
 
 # CI 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.
+# So use 6 threads here though it's not optimal in performance, but ok.
 scenarios(vlt_all => 1);
 
 compile(
diff --git a/test_regress/t/t_hier_block_sc_trace_vcd.pl b/test_regress/t/t_hier_block_sc_trace_vcd.pl
index 5f27738e6..52b2816a1 100755
--- a/test_regress/t/t_hier_block_sc_trace_vcd.pl
+++ b/test_regress/t/t_hier_block_sc_trace_vcd.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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
 
 # stats will be deleted but generation will be skipped if libs of hierarchical blocks exist.
 clean_objs();
@@ -14,7 +15,7 @@ top_filename("t/t_hier_block.v");
 
 # CI 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.
+# So use 6 threads here though it's not optimal in performance, but ok.
 scenarios(vlt_all => 1);
 
 compile(
diff --git a/test_regress/t/t_hier_block_trace_fst.pl b/test_regress/t/t_hier_block_trace_fst.pl
index d05251cfd..f5e8a33c1 100755
--- a/test_regress/t/t_hier_block_trace_fst.pl
+++ b/test_regress/t/t_hier_block_trace_fst.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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_all => 1);
 
@@ -13,7 +14,7 @@ top_filename("t/t_hier_block.v");
 
 # CI 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.
+# So use 6 threads here though it's not optimal in performance, but ok.
 
 compile(
     v_flags2 => ['t/t_hier_block.cpp'],
diff --git a/test_regress/t/t_hier_block_trace_vcd.pl b/test_regress/t/t_hier_block_trace_vcd.pl
index b53533adf..1dc8b71cf 100755
--- a/test_regress/t/t_hier_block_trace_vcd.pl
+++ b/test_regress/t/t_hier_block_trace_vcd.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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_all => 1);
 
@@ -13,7 +14,7 @@ top_filename("t/t_hier_block.v");
 
 # CI 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.
+# So use 6 threads here though it's not optimal in performance, but ok.
 
 compile(
     v_flags2 => ['t/t_hier_block.cpp'],
diff --git a/test_regress/t/t_hier_block_vlt.pl b/test_regress/t/t_hier_block_vlt.pl
index 63e0d466d..115e05367 100755
--- a/test_regress/t/t_hier_block_vlt.pl
+++ b/test_regress/t/t_hier_block_vlt.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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
 
 # stats will be deleted but generation will be skipped if libs of hierarchical blocks exist.
 clean_objs();
@@ -15,7 +16,7 @@ top_filename("t/t_hier_block.v");
 
 # CI 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.
+# So use 6 threads here though it's not optimal in performance, but ok.
 compile(
     v_flags2 => ['t/t_hier_block.cpp'],
     verilator_flags2 => ['--stats',
diff --git a/test_regress/t/t_hier_block_vlt.vlt b/test_regress/t/t_hier_block_vlt.vlt
index b8e6105c9..60a2d4c37 100644
--- a/test_regress/t/t_hier_block_vlt.vlt
+++ b/test_regress/t/t_hier_block_vlt.vlt
@@ -2,6 +2,7 @@
 //
 // This file ONLY is placed into the Public Domain, for any use,
 // without warranty, 2020 by Yutetsu TAKATSUKASA
+// SPDX-License-Identifier: Unlicense
 
 `verilator_config
 hier_block -module "sub?"
diff --git a/test_regress/t/t_hier_bynum.pl b/test_regress/t/t_hier_bynum.pl
index 2c0fb4904..4e314adef 100755
--- a/test_regress/t/t_hier_bynum.pl
+++ b/test_regress/t/t_hier_bynum.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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_all => 1);
 
diff --git a/test_regress/t/t_hier_bynum.v b/test_regress/t/t_hier_bynum.v
index fe76f1e8f..78307d98b 100644
--- a/test_regress/t/t_hier_bynum.v
+++ b/test_regress/t/t_hier_bynum.v
@@ -2,6 +2,7 @@
 //
 // This file ONLY is placed into the Public Domain, for any use,
 // without warranty, 2022 by Wilson Snyder.
+// SPDX-License-Identifier: Unlicense
 
 module flop (q, d, clk);
    // No AUTOARG; order of below is different from port order above
diff --git a/test_regress/t/t_if_swap.v b/test_regress/t/t_if_swap.v
index d1e771433..2dc1ef29d 100644
--- a/test_regress/t/t_if_swap.v
+++ b/test_regress/t/t_if_swap.v
@@ -1,3 +1,9 @@
+// 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
   (/*AUTOARG*/
    // Inputs
diff --git a/test_regress/t/t_increment_bad.out b/test_regress/t/t_increment_bad.out
index f10697bd0..026148082 100644
--- a/test_regress/t/t_increment_bad.out
+++ b/test_regress/t/t_increment_bad.out
@@ -1,26 +1,26 @@
-%Error-UNSUPPORTED: t/t_increment_bad.v:15:31: Unsupported: Incrementation in this context.
-   15 |       if (0 && test_string[pos++] != "e");
+%Error-UNSUPPORTED: t/t_increment_bad.v:21:31: Unsupported: Incrementation in this context.
+   21 |       if (0 && test_string[pos++] != "e");
       |                               ^~
                     ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
-%Error-UNSUPPORTED: t/t_increment_bad.v:16:19: Unsupported: Incrementation in this context.
-   16 |       if (1 || pos-- != 1);
+%Error-UNSUPPORTED: t/t_increment_bad.v:22:19: Unsupported: Incrementation in this context.
+   22 |       if (1 || pos-- != 1);
       |                   ^~
-%Error-UNSUPPORTED: t/t_increment_bad.v:18:17: Unsupported: Incrementation in this context.
-   18 |       if (a <-> --b);
+%Error-UNSUPPORTED: t/t_increment_bad.v:24:17: Unsupported: Incrementation in this context.
+   24 |       if (a <-> --b);
       |                 ^~
-%Error-UNSUPPORTED: t/t_increment_bad.v:19:16: Unsupported: Incrementation in this context.
-   19 |       if (0 -> ++b);
+%Error-UNSUPPORTED: t/t_increment_bad.v:25:16: Unsupported: Incrementation in this context.
+   25 |       if (0 -> ++b);
       |                ^~
-%Error-UNSUPPORTED: t/t_increment_bad.v:21:24: Unsupported: Incrementation in this context.
-   21 |       pos = (a > 0) ? a++ : --b;
+%Error-UNSUPPORTED: t/t_increment_bad.v:27:24: Unsupported: Incrementation in this context.
+   27 |       pos = (a > 0) ? a++ : --b;
       |                        ^~
-%Error-UNSUPPORTED: t/t_increment_bad.v:21:29: Unsupported: Incrementation in this context.
-   21 |       pos = (a > 0) ? a++ : --b;
+%Error-UNSUPPORTED: t/t_increment_bad.v:27:29: Unsupported: Incrementation in this context.
+   27 |       pos = (a > 0) ? a++ : --b;
       |                             ^~
-%Error-UNSUPPORTED: t/t_increment_bad.v:23:24: Unsupported: Incrementation in this context.
-   23 |       pos = array[0][0]++;
+%Error-UNSUPPORTED: t/t_increment_bad.v:29:24: Unsupported: Incrementation in this context.
+   29 |       pos = array[0][0]++;
       |                        ^~
-%Error-UNSUPPORTED: t/t_increment_bad.v:26:37: Unsupported: Incrementation in this context.
-   26 |    assert property (@(posedge clk) a++ >= 0);
+%Error-UNSUPPORTED: t/t_increment_bad.v:32:37: Unsupported: Incrementation in this context.
+   32 |    assert property (@(posedge clk) a++ >= 0);
       |                                     ^~
 %Error: Exiting due to
diff --git a/test_regress/t/t_increment_bad.pl b/test_regress/t/t_increment_bad.pl
index 385b304e3..23eda8f99 100755
--- a/test_regress/t/t_increment_bad.pl
+++ b/test_regress/t/t_increment_bad.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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);
 
diff --git a/test_regress/t/t_increment_bad.v b/test_regress/t/t_increment_bad.v
index 86755af51..11c031177 100644
--- a/test_regress/t/t_increment_bad.v
+++ b/test_regress/t/t_increment_bad.v
@@ -1,3 +1,9 @@
+// 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 (/*AUTOARG*/
    // Inputs
    clk
diff --git a/test_regress/t/t_initialstatic_circ.pl b/test_regress/t/t_initialstatic_circ.pl
index f5e338520..1aa73f80a 100755
--- a/test_regress/t/t_initialstatic_circ.pl
+++ b/test_regress/t/t_initialstatic_circ.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_inst_recurse_bad.out b/test_regress/t/t_inst_recurse_bad.out
index c9bbe810a..eb83d4b29 100644
--- a/test_regress/t/t_inst_recurse_bad.out
+++ b/test_regress/t/t_inst_recurse_bad.out
@@ -1,5 +1,5 @@
 %Error-UNSUPPORTED: t/t_inst_recurse_bad.v:18:8: Unsupported: Recursive multiple modules (module instantiates something leading back to itself): 'looped'
-                    ... note: self-recursion (module instantiating itself directly) is supported.
+                                               : ... note: self-recursion (module instantiating itself directly) is supported.
    18 | module looped ( );
       |        ^~~~~~
                     ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
diff --git a/test_regress/t/t_interface_modport_import_export_list.pl b/test_regress/t/t_interface_modport_import_export_list.pl
new file mode 100755
index 000000000..5412e6e24
--- /dev/null
+++ b/test_regress/t/t_interface_modport_import_export_list.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 2023 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(
+	fails=>0,
+);
+
+ok(1);
+1;
diff --git a/test_regress/t/t_interface_modport_import_export_list.v b/test_regress/t/t_interface_modport_import_export_list.v
new file mode 100644
index 000000000..ddefa9700
--- /dev/null
+++ b/test_regress/t/t_interface_modport_import_export_list.v
@@ -0,0 +1,54 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// Modport import export list test
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2023 by Goekce Aydos.
+// SPDX-License-Identifier: CC0-1.0
+
+interface intf;
+	logic l;
+	function void f1();
+	endfunction
+	function void f2();
+	endfunction
+	function void f3();
+	endfunction
+	function void f4();
+	endfunction
+
+	modport mpi (
+		import f1, f2,
+		input l,
+		import f3, f4
+	);
+	modport mpo (
+		output l,
+		import f1, f2, f3, f4
+	);
+endinterface
+
+module mo (intf.mpo intf0);
+	function void ef1();
+		intf0.f1();
+		intf0.f2();
+	endfunction
+	function void ef2();
+		intf0.f3();
+		intf0.f4();
+	endfunction
+
+initial begin
+	ef1();
+	ef2();
+end
+endmodule
+
+module mi (intf.mpi intf0);
+endmodule
+
+module t;
+	intf intf0();
+	mi mi(.*);
+	mo mo(.*);
+endmodule
diff --git a/test_regress/t/t_jumps_do_while.pl b/test_regress/t/t_jumps_do_while.pl
index c505d6263..a86f4c404 100755
--- a/test_regress/t/t_jumps_do_while.pl
+++ b/test_regress/t/t_jumps_do_while.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_jumps_do_while.v b/test_regress/t/t_jumps_do_while.v
index 217e46b3e..0f9705487 100644
--- a/test_regress/t/t_jumps_do_while.v
+++ b/test_regress/t/t_jumps_do_while.v
@@ -10,7 +10,7 @@ module t (/*AUTOARG*/
 
    input clk;
 
-   function bit test_1;
+   function automatic bit test_1;
       int iterations = 0;
       do begin
          iterations++;
@@ -20,7 +20,7 @@ module t (/*AUTOARG*/
       return iterations == 1;
    endfunction
 
-   function bit test_2;
+   function automatic bit test_2;
       int iterations = 0;
       do begin
          break;
@@ -37,7 +37,7 @@ module t (/*AUTOARG*/
       return 1'b1;
    endfunction
 
-   function bit test_4;
+   function automatic bit test_4;
       int incr = 0;
       do begin
          incr++;
@@ -48,7 +48,7 @@ module t (/*AUTOARG*/
       return incr == 1;
    endfunction
 
-   function bit test_5;
+   function automatic bit test_5;
       int incr = 0;
       do begin
          do
@@ -62,7 +62,7 @@ module t (/*AUTOARG*/
       return incr == 10;
    endfunction
 
-   function bit test_6;
+   function automatic bit test_6;
       int incr = 0;
       do begin
          do begin
@@ -78,7 +78,7 @@ module t (/*AUTOARG*/
       return incr == 10;
    endfunction
 
-   function bit test_7;
+   function automatic bit test_7;
       int incr = 0;
       do begin
          do begin
@@ -95,7 +95,7 @@ module t (/*AUTOARG*/
       return incr == 2;
    endfunction
 
-   function bit test_8;
+   function automatic bit test_8;
       int incr = 0;
       do begin
          incr++;
@@ -106,7 +106,7 @@ module t (/*AUTOARG*/
       return incr == 1;
    endfunction
 
-   function bit test_9;
+   function automatic bit test_9;
       int incr = 0;
       do begin
          incr++;
@@ -117,7 +117,7 @@ module t (/*AUTOARG*/
       return incr == 5;
    endfunction
 
-   function bit test_10;
+   function automatic bit test_10;
       do begin
          continue;
       end
@@ -125,7 +125,7 @@ module t (/*AUTOARG*/
       return 1'b1;
    endfunction
 
-   function bit test_11;
+   function automatic bit test_11;
       int incr = 0;
       do begin
          do
@@ -139,7 +139,7 @@ module t (/*AUTOARG*/
       return incr == 12;
    endfunction
 
-   function bit test_12;
+   function automatic bit test_12;
       int incr = 0;
       do begin
          do begin
diff --git a/test_regress/t/t_leak.cpp b/test_regress/t/t_leak.cpp
index decf48891..eb15c060f 100644
--- a/test_regress/t/t_leak.cpp
+++ b/test_regress/t/t_leak.cpp
@@ -48,11 +48,11 @@ long long get_memory_usage() {
 void make_and_destroy() {
 #ifdef VL_NO_LEGACY
     VerilatedContext* contextp = new VerilatedContext;
-    VM_PREFIX* topp = new VM_PREFIX{contextp};
     contextp->debug(0);
+    VM_PREFIX* topp = new VM_PREFIX{contextp};
 #else
-    VM_PREFIX* topp = new VM_PREFIX;
     Verilated::debug(0);
+    VM_PREFIX* topp = new VM_PREFIX;
 #endif
 
     topp->eval();
diff --git a/test_regress/t/t_lib_prot_exe_bad.pl b/test_regress/t/t_lib_prot_exe_bad.pl
index a89483bf5..9700f4120 100755
--- a/test_regress/t/t_lib_prot_exe_bad.pl
+++ b/test_regress/t/t_lib_prot_exe_bad.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Yinan Xu. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_lint_latch_1.v b/test_regress/t/t_lint_latch_1.v
index 95ae861c2..99987cfbc 100644
--- a/test_regress/t/t_lint_latch_1.v
+++ b/test_regress/t/t_lint_latch_1.v
@@ -2,6 +2,7 @@
 //
 // This file ONLY is placed into the Public Domain, for any use,
 // without warranty, 2020 by Julien Margetts.
+// SPDX-License-Identifier: Unlicense
 
 module t (/*AUTOARG*/ a, b, o);
    input  a;
diff --git a/test_regress/t/t_lint_latch_2.v b/test_regress/t/t_lint_latch_2.v
index d3c93d9d0..5ce9ec5e5 100644
--- a/test_regress/t/t_lint_latch_2.v
+++ b/test_regress/t/t_lint_latch_2.v
@@ -2,6 +2,7 @@
 //
 // This file ONLY is placed into the Public Domain, for any use,
 // without warranty, 2020 by Julien Margetts.
+// SPDX-License-Identifier: Unlicense
 
 module t (/*AUTOARG*/ i, o);
 
diff --git a/test_regress/t/t_lint_latch_3.v b/test_regress/t/t_lint_latch_3.v
index 6ba537f89..b38862ece 100644
--- a/test_regress/t/t_lint_latch_3.v
+++ b/test_regress/t/t_lint_latch_3.v
@@ -2,6 +2,7 @@
 //
 // This file ONLY is placed into the Public Domain, for any use,
 // without warranty, 2020 by Julien Margetts.
+// SPDX-License-Identifier: Unlicense
 
 module t (/*AUTOARG*/ out, out2, in );
 
diff --git a/test_regress/t/t_lint_latch_4.v b/test_regress/t/t_lint_latch_4.v
index 9f5504dc0..628af7315 100644
--- a/test_regress/t/t_lint_latch_4.v
+++ b/test_regress/t/t_lint_latch_4.v
@@ -2,6 +2,7 @@
 //
 // This file ONLY is placed into the Public Domain, for any use,
 // without warranty, 2021 by Julien Margetts (Originally provided by YanJiun)
+// SPDX-License-Identifier: Unlicense
 
 module test (
   input      [2:0] a,
diff --git a/test_regress/t/t_lint_latch_5.v b/test_regress/t/t_lint_latch_5.v
index dcca92df8..c8d5697e8 100644
--- a/test_regress/t/t_lint_latch_5.v
+++ b/test_regress/t/t_lint_latch_5.v
@@ -2,6 +2,7 @@
 //
 // This file ONLY is placed into the Public Domain, for any use,
 // without warranty, 2021 by Julien Margetts (Originally provided by Thomas Sailer)
+// SPDX-License-Identifier: Unlicense
 
 module test
   (input  logic [1:0] a,
diff --git a/test_regress/t/t_lint_latch_bad_2.out b/test_regress/t/t_lint_latch_bad_2.out
index 29e592071..8d2070747 100644
--- a/test_regress/t/t_lint_latch_bad_2.out
+++ b/test_regress/t/t_lint_latch_bad_2.out
@@ -1,6 +1,6 @@
-%Warning-LATCH: t/t_lint_latch_bad_2.v:11:4: Latch inferred for signal 'o' (not all control paths of combinational always assign a value)
+%Warning-LATCH: t/t_lint_latch_bad_2.v:12:4: Latch inferred for signal 'o' (not all control paths of combinational always assign a value)
                                            : ... Suggest use of always_latch for intentional latches
-   11 |    always_comb
+   12 |    always_comb
       |    ^~~~~~~~~~~
                 ... For warning description see https://verilator.org/warn/LATCH?v=latest
                 ... Use "/* verilator lint_off LATCH */" and lint_on around source to disable this message.
diff --git a/test_regress/t/t_lint_latch_bad_2.pl b/test_regress/t/t_lint_latch_bad_2.pl
index 34ebfdc61..70301e9b6 100755
--- a/test_regress/t/t_lint_latch_bad_2.pl
+++ b/test_regress/t/t_lint_latch_bad_2.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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);
 
diff --git a/test_regress/t/t_lint_latch_bad_2.v b/test_regress/t/t_lint_latch_bad_2.v
index e738dc23b..531995874 100644
--- a/test_regress/t/t_lint_latch_bad_2.v
+++ b/test_regress/t/t_lint_latch_bad_2.v
@@ -2,6 +2,7 @@
 //
 // This file ONLY is placed into the Public Domain, for any use,
 // without warranty, 2020 by Julien Margetts.
+// SPDX-License-Identifier: Unlicense
 
 module t (/*AUTOARG*/ a, b, o);
    input  a;
diff --git a/test_regress/t/t_lint_latch_bad_3.out b/test_regress/t/t_lint_latch_bad_3.out
index cb89d481a..93a9577b8 100644
--- a/test_regress/t/t_lint_latch_bad_3.out
+++ b/test_regress/t/t_lint_latch_bad_3.out
@@ -1,6 +1,6 @@
-%Warning-LATCH: t/t_lint_latch_bad_3.v:18:1: Latch inferred for signal 'o5' (not all control paths of combinational always assign a value)
+%Warning-LATCH: t/t_lint_latch_bad_3.v:19:1: Latch inferred for signal 'o5' (not all control paths of combinational always assign a value)
                                            : ... Suggest use of always_latch for intentional latches
-   18 | always_comb
+   19 | always_comb
       | ^~~~~~~~~~~
                 ... For warning description see https://verilator.org/warn/LATCH?v=latest
                 ... Use "/* verilator lint_off LATCH */" and lint_on around source to disable this message.
diff --git a/test_regress/t/t_lint_latch_bad_3.pl b/test_regress/t/t_lint_latch_bad_3.pl
index 34ebfdc61..70301e9b6 100755
--- a/test_regress/t/t_lint_latch_bad_3.pl
+++ b/test_regress/t/t_lint_latch_bad_3.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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);
 
diff --git a/test_regress/t/t_lint_latch_bad_3.v b/test_regress/t/t_lint_latch_bad_3.v
index 83a87b16d..4f1ba7c9c 100644
--- a/test_regress/t/t_lint_latch_bad_3.v
+++ b/test_regress/t/t_lint_latch_bad_3.v
@@ -2,6 +2,7 @@
 //
 // This file ONLY is placed into the Public Domain, for any use,
 // without warranty, 2020 by Julien Margetts.
+// SPDX-License-Identifier: Unlicense
 
 module t (/*AUTOARG*/ reset, a, b, c, en, o1, o2, o3, o4, o5);
    input  reset;
diff --git a/test_regress/t/t_lint_literal_bad.pl b/test_regress/t/t_lint_literal_bad.pl
index 506f62c09..5ece32e17 100755
--- a/test_regress/t/t_lint_literal_bad.pl
+++ b/test_regress/t/t_lint_literal_bad.pl
@@ -2,8 +2,8 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2017 by Todd Strader. This program is free software; you
-# can predistribute it and/or modify it under the terms of either the GNU
+# Copyright 2017 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
diff --git a/test_regress/t/t_lint_nolatch_bad.out b/test_regress/t/t_lint_nolatch_bad.out
index 8a229bd07..a7cc97b2b 100644
--- a/test_regress/t/t_lint_nolatch_bad.out
+++ b/test_regress/t/t_lint_nolatch_bad.out
@@ -1,5 +1,5 @@
-%Warning-NOLATCH: t/t_lint_nolatch_bad.v:11:4: No latches detected in always_latch block
-   11 |    always_latch
+%Warning-NOLATCH: t/t_lint_nolatch_bad.v:12:4: No latches detected in always_latch block
+   12 |    always_latch
       |    ^~~~~~~~~~~~
                   ... For warning description see https://verilator.org/warn/NOLATCH?v=latest
                   ... Use "/* verilator lint_off NOLATCH */" and lint_on around source to disable this message.
diff --git a/test_regress/t/t_lint_nolatch_bad.pl b/test_regress/t/t_lint_nolatch_bad.pl
index 0b13642c9..a8b75812f 100755
--- a/test_regress/t/t_lint_nolatch_bad.pl
+++ b/test_regress/t/t_lint_nolatch_bad.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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);
 
diff --git a/test_regress/t/t_lint_nolatch_bad.v b/test_regress/t/t_lint_nolatch_bad.v
index 5f88a38c3..0119646b1 100644
--- a/test_regress/t/t_lint_nolatch_bad.v
+++ b/test_regress/t/t_lint_nolatch_bad.v
@@ -2,6 +2,7 @@
 //
 // This file ONLY is placed into the Public Domain, for any use,
 // without warranty, 2020 by Julien Margetts.
+// SPDX-License-Identifier: Unlicense
 
 module t (/*AUTOARG*/ a, b, o);
    input  a;
diff --git a/test_regress/t/t_lint_pinnotfound.pl b/test_regress/t/t_lint_pinnotfound.pl
index 7314796b8..aca1cb3c1 100755
--- a/test_regress/t/t_lint_pinnotfound.pl
+++ b/test_regress/t/t_lint_pinnotfound.pl
@@ -2,6 +2,10 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
+# Copyright 2023 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);
diff --git a/test_regress/t/t_lint_pragma_protected.v b/test_regress/t/t_lint_pragma_protected.v
index dc8eb4cad..3852391fc 100644
--- a/test_regress/t/t_lint_pragma_protected.v
+++ b/test_regress/t/t_lint_pragma_protected.v
@@ -1,3 +1,9 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2021 by Wilson Snyder.
+// SPDX-License-Identifier: CC0-1.0
+
 // This part should pass OK
 
 module t_lint_pragma_protected;
diff --git a/test_regress/t/t_lint_pragma_protected_bad.out b/test_regress/t/t_lint_pragma_protected_bad.out
index bb729a9e2..a19cc9826 100644
--- a/test_regress/t/t_lint_pragma_protected_bad.out
+++ b/test_regress/t/t_lint_pragma_protected_bad.out
@@ -1,53 +1,53 @@
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:8:17: Unknown '`pragma protect' error
-    8 | `pragma protect encrypt_agent=123
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:14:17: Unknown '`pragma protect' error
+   14 | `pragma protect encrypt_agent=123
       |                 ^~~~~~~~~~~~~~~~~
                      ... For error description see https://verilator.org/warn/BADSTDPRAGMA?v=latest
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:10:17: Unknown '`pragma protect' error
-   10 | `pragma protect encrypt_agent_info
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:16:17: Unknown '`pragma protect' error
+   16 | `pragma protect encrypt_agent_info
       |                 ^~~~~~~~~~~~~~~~~~
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:23:1: BASE64 encoding length mismatch in `pragma protect key_bloock/data_block
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:27:17: multiple `pragma protected encoding sections
-   27 | `pragma protect encoding = (enctype = "BASE64", line_length = 76, bytes = 128)
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:29:1: BASE64 encoding length mismatch in `pragma protect key_bloock/data_block
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:33:17: multiple `pragma protected encoding sections
+   33 | `pragma protect encoding = (enctype = "BASE64", line_length = 76, bytes = 128)
       |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-%Warning-PROTECTED: t/t_lint_pragma_protected_bad.v:44:17: A '`pragma protected data_block' encrypted section was detected and will be skipped.
+%Warning-PROTECTED: t/t_lint_pragma_protected_bad.v:50:17: A '`pragma protected data_block' encrypted section was detected and will be skipped.
                     ... Use "/* verilator lint_off PROTECTED */" and lint_on around source to disable this message.
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:51:17: Illegal encoding type for `pragma protected encoding
-   51 | `pragma protect encoding = (enctype = "A-bad-not-BASE64", line_length = 1, bytes = 295)
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:57:17: Illegal encoding type for `pragma protected encoding
+   57 | `pragma protect encoding = (enctype = "A-bad-not-BASE64", line_length = 1, bytes = 295)
       |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-%Error-UNSUPPORTED: t/t_lint_pragma_protected_bad.v:51:17: Unsupported: only BASE64 is recognized for `pragma protected encoding
-   51 | `pragma protect encoding = (enctype = "A-bad-not-BASE64", line_length = 1, bytes = 295)
+%Error-UNSUPPORTED: t/t_lint_pragma_protected_bad.v:57:17: Unsupported: only BASE64 is recognized for `pragma protected encoding
+   57 | `pragma protect encoding = (enctype = "A-bad-not-BASE64", line_length = 1, bytes = 295)
       |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-%Warning-PROTECTED: t/t_lint_pragma_protected_bad.v:53:17: A '`pragma protected data_block' encrypted section was detected and will be skipped.
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:54:1: BASE64 encoding (too short) in `pragma protect key_bloock/data_block
-   54 | c2lvbiAzIG9mIHRoZSBHTlUgTGVzc2VyCkdlbmVyYWwgUHVibGljIExpY2Vuc2UsIGFuZCB0aGUg
+%Warning-PROTECTED: t/t_lint_pragma_protected_bad.v:59:17: A '`pragma protected data_block' encrypted section was detected and will be skipped.
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:60:1: BASE64 encoding (too short) in `pragma protect key_bloock/data_block
+   60 | c2lvbiAzIG9mIHRoZSBHTlUgTGVzc2VyCkdlbmVyYWwgUHVibGljIExpY2Vuc2UsIGFuZCB0aGUg
       | ^
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:55:1: BASE64 encoding (too short) in `pragma protect key_bloock/data_block
-   55 | IkdOVSBHUEwiIHJlZmVycyB0byB2ZXJzaW9uIDMgb2YgdGhlIEdOVQpHZW5lcmFsIFB1YmxpYyBM
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:61:1: BASE64 encoding (too short) in `pragma protect key_bloock/data_block
+   61 | IkdOVSBHUEwiIHJlZmVycyB0byB2ZXJzaW9uIDMgb2YgdGhlIEdOVQpHZW5lcmFsIFB1YmxpYyBM
       | ^
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:56:1: BASE64 encoding (too short) in `pragma protect key_bloock/data_block
-   56 | aWNlbnNlLgoKICAiVGhlIExpYnJhcnkiIHJlZmVycyB0byBhIGNvdmVyZWQgd29yayBnb3Zlcm5l
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:62:1: BASE64 encoding (too short) in `pragma protect key_bloock/data_block
+   62 | aWNlbnNlLgoKICAiVGhlIExpYnJhcnkiIHJlZmVycyB0byBhIGNvdmVyZWQgd29yayBnb3Zlcm5l
       | ^
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:57:1: BASE64 encoding (too short) in `pragma protect key_bloock/data_block
-   57 | ZCBieSB0aGlzIExpY2Vuc2UsCm90aGVyIHRoYW4gYW4gQXBwbGljYXRpb24gb3IgYSBDb21iaW5l
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:63:1: BASE64 encoding (too short) in `pragma protect key_bloock/data_block
+   63 | ZCBieSB0aGlzIExpY2Vuc2UsCm90aGVyIHRoYW4gYW4gQXBwbGljYXRpb24gb3IgYSBDb21iaW5l
       | ^
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:58:1: BASE64 encoding (too short) in `pragma protect key_bloock/data_block
-   58 | ZCBXb3JrIGFzIG==
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:64:1: BASE64 encoding (too short) in `pragma protect key_bloock/data_block
+   64 | ZCBXb3JrIGFzIG==
       | ^
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:59:1: BASE64 encoding (too short) in `pragma protect key_bloock/data_block
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:59:1: BASE64 encoding length mismatch in `pragma protect key_bloock/data_block
-%Warning-PROTECTED: t/t_lint_pragma_protected_bad.v:63:17: A '`pragma protected data_block' encrypted section was detected and will be skipped.
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:64:1: BASE64 line too long in `pragma protect key_bloock/data_block
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:64:1: BASE64 encoding length mismatch in `pragma protect key_bloock/data_block
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:66:17: multiple `pragma protected encoding sections
-   66 | `pragma protect encoding = (enctype = "BASE64", line_length = 1, bytes = 4)
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:65:1: BASE64 encoding (too short) in `pragma protect key_bloock/data_block
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:65:1: BASE64 encoding length mismatch in `pragma protect key_bloock/data_block
+%Warning-PROTECTED: t/t_lint_pragma_protected_bad.v:69:17: A '`pragma protected data_block' encrypted section was detected and will be skipped.
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:70:1: BASE64 line too long in `pragma protect key_bloock/data_block
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:70:1: BASE64 encoding length mismatch in `pragma protect key_bloock/data_block
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:72:17: multiple `pragma protected encoding sections
+   72 | `pragma protect encoding = (enctype = "BASE64", line_length = 1, bytes = 4)
       |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:66:17: line_length must be multiple of 4 for BASE64
-   66 | `pragma protect encoding = (enctype = "BASE64", line_length = 1, bytes = 4)
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:72:17: line_length must be multiple of 4 for BASE64
+   72 | `pragma protect encoding = (enctype = "BASE64", line_length = 1, bytes = 4)
       |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-%Warning-PROTECTED: t/t_lint_pragma_protected_bad.v:68:17: A '`pragma protected data_block' encrypted section was detected and will be skipped.
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:69:1: BASE64 line too long in `pragma protect key_bloock/data_block
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:69:1: BASE64 encoding length mismatch in `pragma protect key_bloock/data_block
-%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:77:1: `pragma is missing a pragma_expression.
-   77 | `pragma
+%Warning-PROTECTED: t/t_lint_pragma_protected_bad.v:74:17: A '`pragma protected data_block' encrypted section was detected and will be skipped.
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:75:1: BASE64 line too long in `pragma protect key_bloock/data_block
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:75:1: BASE64 encoding length mismatch in `pragma protect key_bloock/data_block
+%Error-BADSTDPRAGMA: t/t_lint_pragma_protected_bad.v:83:1: `pragma is missing a pragma_expression.
+   83 | `pragma
       | ^~~~~~~
 %Error: Exiting due to
diff --git a/test_regress/t/t_lint_pragma_protected_bad.v b/test_regress/t/t_lint_pragma_protected_bad.v
index 6d4f4e5e2..68e3c159d 100644
--- a/test_regress/t/t_lint_pragma_protected_bad.v
+++ b/test_regress/t/t_lint_pragma_protected_bad.v
@@ -1,3 +1,9 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2021 by Wilson Snyder.
+// SPDX-License-Identifier: CC0-1.0
+
 module t_lint_pragma_protected_err;
 
 // This part should see some failures
diff --git a/test_regress/t/t_math_imm2.cpp b/test_regress/t/t_math_imm2.cpp
index 54c1657e5..b4c8015a0 100644
--- a/test_regress/t/t_math_imm2.cpp
+++ b/test_regress/t/t_math_imm2.cpp
@@ -17,6 +17,7 @@ QData MaskVal(int lbit, int hbit) {
 
 int main(int argc, char* argv[]) {
     Verilated::debug(0);
+    Verilated::commandArgs(argc, argv);
 
     Vt_math_imm2* sim = new Vt_math_imm2;
     int lbit, hbit;
diff --git a/test_regress/t/t_math_signed_calc.pl b/test_regress/t/t_math_signed_calc.pl
index 700b77233..1aa73f80a 100755
--- a/test_regress/t/t_math_signed_calc.pl
+++ b/test_regress/t/t_math_signed_calc.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Raynard Qiao. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_mem_slot.cpp b/test_regress/t/t_mem_slot.cpp
index 5c32d9ec8..a65ae687d 100644
--- a/test_regress/t/t_mem_slot.cpp
+++ b/test_regress/t/t_mem_slot.cpp
@@ -45,11 +45,12 @@ unsigned int StepSim(Vt_mem_slot* sim, unsigned int slot, unsigned int bit, unsi
 }
 
 int main(int argc, char* argv[]) {
+    Verilated::debug(0);
+    Verilated::commandArgs(argc, argv);
+
     Vt_mem_slot* sim = new Vt_mem_slot;
     int slot, bit, i;
 
-    Verilated::debug(0);
-
     // clear all bits in the array
     for (slot = 0; slot < 3; slot++)
         for (bit = 0; bit < 2; bit++)  //
diff --git a/test_regress/t/t_multitop_sig.cpp b/test_regress/t/t_multitop_sig.cpp
index 0ce924bf8..29a01491b 100644
--- a/test_regress/t/t_multitop_sig.cpp
+++ b/test_regress/t/t_multitop_sig.cpp
@@ -20,9 +20,10 @@ double sc_time_stamp() { return 0; }
 int errors = 0;
 
 int main(int argc, char* argv[]) {
-    Vt_multitop_sig* topp = new Vt_multitop_sig{""};
-
     Verilated::debug(0);
+    Verilated::commandArgs(argc, argv);
+
+    Vt_multitop_sig* topp = new Vt_multitop_sig{""};
 
     {
         topp->a__02Ein = 0;
diff --git a/test_regress/t/t_crazy_sel.pl b/test_regress/t/t_name_collision.pl
similarity index 100%
rename from test_regress/t/t_crazy_sel.pl
rename to test_regress/t/t_name_collision.pl
diff --git a/test_regress/t/t_name_collision.v b/test_regress/t/t_name_collision.v
new file mode 100644
index 000000000..6639e9ed5
--- /dev/null
+++ b/test_regress/t/t_name_collision.v
@@ -0,0 +1,18 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2022 by Wilson Snyder.
+// SPDX-License-Identifier: CC0-1.0
+
+module HasNameParam
+  #(parameter name /*verilator public*/ = 0)
+   ();
+endmodule
+
+module t ();
+   HasNameParam a();
+   initial begin
+      $write("*-* All Finished *-*\n");
+      $finish;
+   end
+endmodule
diff --git a/test_regress/t/t_negated_property.pl b/test_regress/t/t_negated_property.pl
index c505d6263..a86f4c404 100755
--- a/test_regress/t/t_negated_property.pl
+++ b/test_regress/t/t_negated_property.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_order_quad.cpp b/test_regress/t/t_order_quad.cpp
index 95eddc4fa..cf6c247f3 100644
--- a/test_regress/t/t_order_quad.cpp
+++ b/test_regress/t/t_order_quad.cpp
@@ -27,9 +27,10 @@ void check(QData got, QData exp) {
 }
 
 int main(int argc, char* argv[]) {
-    topp = new VM_PREFIX;
-
     Verilated::debug(0);
+    Verilated::commandArgs(argc, argv);
+
+    topp = new VM_PREFIX;
 
     topp->a0 = 0;
     topp->eval();
diff --git a/test_regress/t/t_package_struct.out b/test_regress/t/t_package_struct.out
new file mode 100644
index 000000000..9bc7bd537
--- /dev/null
+++ b/test_regress/t/t_package_struct.out
@@ -0,0 +1,2 @@
+hello, world (0, 0)
+*-* All Finished *-*
diff --git a/test_regress/t/t_package_struct.pl b/test_regress/t/t_package_struct.pl
new file mode 100755
index 000000000..11eeb66fe
--- /dev/null
+++ b/test_regress/t/t_package_struct.pl
@@ -0,0 +1,22 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 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(
+    expect_filename => $Self->{golden_filename},
+    check_finished => 1,
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_package_struct.v b/test_regress/t/t_package_struct.v
new file mode 100644
index 000000000..445bfd541
--- /dev/null
+++ b/test_regress/t/t_package_struct.v
@@ -0,0 +1,25 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2022 by Antmicro Ltd.
+// SPDX-License-Identifier: CC0-1.0
+
+package pkg;
+   typedef struct {
+      string a, b;
+      struct {
+         bit a, b;
+      } has;
+   } strings;
+endpackage
+
+module t (/*AUTOARG*/);
+  initial begin
+     pkg::strings stct;
+     stct.a = "hello";
+     stct.b = "world";
+     $display("%s, %s (%1b, %1b)", stct.a, stct.b, stct.has.a, stct.has.b);
+     $write("*-* All Finished *-*\n");
+     $finish;
+  end
+endmodule
diff --git a/test_regress/t/t_param_array3.v b/test_regress/t/t_param_array3.v
index fb6926365..3d9d98fb1 100644
--- a/test_regress/t/t_param_array3.v
+++ b/test_regress/t/t_param_array3.v
@@ -8,7 +8,7 @@ module t;
    parameter int SIZES [3:0] = '{1,2,3,4};
    typedef int calc_sums_t [3:0];
 
-   function calc_sums_t calc_sums;
+   function static calc_sums_t calc_sums;
       int sum = 0;
       for (int i=0; i<4; i++) begin
          sum = sum + SIZES[i];
diff --git a/test_regress/t/t_param_func2.v b/test_regress/t/t_param_func2.v
index 432d2914d..1a4630d77 100644
--- a/test_regress/t/t_param_func2.v
+++ b/test_regress/t/t_param_func2.v
@@ -29,7 +29,7 @@ endmodule
 module sub;
    parameter WIDTH = 1;
 
-   function [WIDTH-1:0] orer;
+   function automatic [WIDTH-1:0] orer;
       input [WIDTH-1:0] in;
       // IEEE provices no way to override this parameter, basically it's a localparam
       parameter MASK_W = WIDTH - 2;
@@ -39,7 +39,7 @@ module sub;
       // verilator lint_on WIDTH
    endfunction
 
-   function [WIDTH-1:0] orer2;
+   function automatic [WIDTH-1:0] orer2;
       input [WIDTH-1:0] in;
       // Same param names as other function to check we disambiguate
       // IEEE provices no way to override this parameter, basically it's a localparam
diff --git a/test_regress/t/t_param_public.cpp b/test_regress/t/t_param_public.cpp
index 66bfd20cf..17cc1c0f6 100644
--- a/test_regress/t/t_param_public.cpp
+++ b/test_regress/t/t_param_public.cpp
@@ -15,9 +15,10 @@
 double sc_time_stamp() { return 0; }
 
 int main(int argc, char* argv[]) {
-    Vt_param_public* topp = new Vt_param_public;
-
     Verilated::debug(0);
+    Verilated::commandArgs(argc, argv);
+
+    Vt_param_public* topp = new Vt_param_public;
 
     // Make sure public tag worked
     if (static_cast(Vt_param_public_t::TOP_PARAM) != 30) {
diff --git a/test_regress/t/t_param_real2.pl b/test_regress/t/t_param_real2.pl
index 8d96a573a..1aa73f80a 100755
--- a/test_regress/t/t_param_real2.pl
+++ b/test_regress/t/t_param_real2.pl
@@ -2,8 +2,8 @@
 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 predistribute it and/or modify it under the terms of either the GNU
+# Copyright 2022 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
diff --git a/test_regress/t/t_param_type_cmp.pl b/test_regress/t/t_param_type_cmp.pl
new file mode 100755
index 000000000..b46d46042
--- /dev/null
+++ b/test_regress/t/t_param_type_cmp.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_param_type_cmp.v b/test_regress/t/t_param_type_cmp.v
new file mode 100644
index 000000000..9bbf2aecb
--- /dev/null
+++ b/test_regress/t/t_param_type_cmp.v
@@ -0,0 +1,48 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2004 by Wilson Snyder.
+// SPDX-License-Identifier: CC0-1.0
+
+module t ();
+
+   logic [2:0] a;
+   logic [2:0] b;
+
+   logic signed_out;
+   logic unsigned_out;
+
+   cmp #(.element_type(logic signed [2:0])) signed_cmp (.a(a), .b(b), .c(signed_out));
+   cmp #(.element_type(logic [2:0])) unsigned_cmp (.a(a), .b(b), .c(unsigned_out));
+
+   initial a = 3'b001;
+   initial b = 3'b111;
+
+   initial begin
+      if (signed_out !== 1'b0) begin
+         $display("%%Error: bad signed comparison %b < %b: got=%d exp=%d", a, b, signed_out, 1'b0);
+         $stop;
+      end
+      if (unsigned_out !== 1'b1) begin
+         $display("%%Error: bad unsigned comparison %b < %b: got=%d exp=%d", a, b, unsigned_out, 1'b1);
+         $stop;
+      end
+      $write("*-* All Finished *-*\n");
+      $finish;
+   end
+
+endmodule
+
+module cmp
+#(
+    parameter type element_type = logic
+)
+(
+   input element_type a,
+   input element_type b,
+   output logic c
+);
+
+   assign c = a < b;
+
+endmodule
diff --git a/test_regress/t/t_past_funcs.pl b/test_regress/t/t_past_funcs.pl
index c1a6773e9..e2cfde569 100755
--- a/test_regress/t/t_past_funcs.pl
+++ b/test_regress/t/t_past_funcs.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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);
 
diff --git a/test_regress/t/t_past_funcs.v b/test_regress/t/t_past_funcs.v
index 2ee24f4a5..2dce45368 100644
--- a/test_regress/t/t_past_funcs.v
+++ b/test_regress/t/t_past_funcs.v
@@ -2,6 +2,7 @@
 //
 // This file ONLY is placed into the Public Domain, for any use,
 // without warranty, 2020 by Peter Monsson.
+// SPDX-License-Identifier: Unlicense
 
 module t (/*AUTOARG*/
    // Inputs
@@ -94,12 +95,9 @@ module Test2 (/*AUTOARG*/
    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_strobe.pl b/test_regress/t/t_past_strobe.pl
index 4bbe254e3..a2660234f 100755
--- a/test_regress/t/t_past_strobe.pl
+++ b/test_regress/t/t_past_strobe.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_pgo_threads.pl b/test_regress/t/t_pgo_threads.pl
index 974bbe3c4..e132892fd 100755
--- a/test_regress/t/t_pgo_threads.pl
+++ b/test_regress/t/t_pgo_threads.pl
@@ -29,7 +29,7 @@ execute(
 file_grep("$Self->{obj_dir}/profile.vlt", qr/profile_data/i);
 
 compile(
-    # Intentinally no --prof-pgo here to make sure profile data can be read in
+    # Intentionally no --prof-pgo here to make sure profile data can be read in
     # without it (that is: --prof-pgo has no effect on profile_data hash names)
     v_flags2 => [" $Self->{obj_dir}/profile.vlt"],
     threads => 2
diff --git a/test_regress/t/t_pkg_using_dollar_unit_items.pl b/test_regress/t/t_pkg_using_dollar_unit_items.pl
index bf4e4ce9f..7b483d32e 100755
--- a/test_regress/t/t_pkg_using_dollar_unit_items.pl
+++ b/test_regress/t/t_pkg_using_dollar_unit_items.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_preproc_str_undef.v b/test_regress/t/t_preproc_str_undef.v
index f02544542..1ab629a7f 100644
--- a/test_regress/t/t_preproc_str_undef.v
+++ b/test_regress/t/t_preproc_str_undef.v
@@ -1,3 +1,9 @@
+// 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
+
 `define PREFIX_        my_prefix_
 `define SUFFIX          my_suffix
 `define PREFIX_SUFFIX   my_prefix_suffix
diff --git a/test_regress/t/t_process_redecl.pl b/test_regress/t/t_process_redecl.pl
index f697727ea..10266d6f8 100755
--- a/test_regress/t/t_process_redecl.pl
+++ b/test_regress/t/t_process_redecl.pl
@@ -6,6 +6,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 # 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);
 
diff --git a/test_regress/t/t_prof.pl b/test_regress/t/t_prof.pl
index bfa4cb19c..8601d6715 100755
--- a/test_regress/t/t_prof.pl
+++ b/test_regress/t/t_prof.pl
@@ -10,7 +10,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 
 scenarios(vlt_all => 1);
 
-# TODO below might no longer be requried as configure checks for -pg
+# TODO below might no longer be required as configure checks for -pg
 if ($ENV{VERILATOR_TEST_NO_GPROF}) {
     skip("Skipping due to VERILATOR_TEST_NO_GPROF");
 } else {
diff --git a/test_regress/t/t_protect_ids.v b/test_regress/t/t_protect_ids.v
index ef6bb188a..dcc0fc41d 100644
--- a/test_regress/t/t_protect_ids.v
+++ b/test_regress/t/t_protect_ids.v
@@ -25,10 +25,16 @@ module secret_sub
 
    // verilator no_inline_module
 
-   integer secret_cyc;
-   real    secret_cyc_r;
-   integer secret_o;
-   real    secret_r;
+   typedef struct {
+      integer secret_field;
+      integer secret_field_r;
+   } secret_st;
+
+   integer   secret_cyc;
+   real      secret_cyc_r;
+   integer   secret_o;
+   real      secret_r;
+   secret_st secret_pair;
 
    export "DPI-C" task dpix_a_task;
    task dpix_a_task(input int i, output int o);  o = i + 1; endtask
@@ -40,6 +46,8 @@ module secret_sub
 
    // Test loop
    always @ (posedge clk) begin
+      secret_pair.secret_field += 1;
+      secret_pair.secret_field_r += 2;
       secret_cyc_r = $itor(secret_cyc)/10.0 - 5.0;
       secret_cyc <= dpii_a_func(secret_cyc);
       secret_r += 1.0 + $cos(secret_cyc_r);
diff --git a/test_regress/t/t_pub_unpacked_port.pl b/test_regress/t/t_pub_unpacked_port.pl
index 4aa53aa05..55bd57e5c 100755
--- a/test_regress/t/t_pub_unpacked_port.pl
+++ b/test_regress/t/t_pub_unpacked_port.pl
@@ -2,17 +2,17 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Todd Strader. This program is free software; you
+# Copyright 2022 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,
-    );
+scenarios(vlt => 1);
 
 compile();
+
 execute();
+
 ok(1);
 1;
diff --git a/test_regress/t/t_public_clk.cpp b/test_regress/t/t_public_clk.cpp
index ebed647f7..7d27a83c8 100644
--- a/test_regress/t/t_public_clk.cpp
+++ b/test_regress/t/t_public_clk.cpp
@@ -16,8 +16,8 @@ std::unique_ptr topp;
 int main(int argc, char** argv) {
     vluint64_t sim_time = 1100;
     const std::unique_ptr contextp{new VerilatedContext};
-    contextp->commandArgs(argc, argv);
     contextp->debug(0);
+    contextp->commandArgs(argc, argv);
     srand48(5);
     topp.reset(new Vt_public_clk("top"));
 
diff --git a/test_regress/t/t_public_seq.cpp b/test_regress/t/t_public_seq.cpp
index f69b3ab8d..3299aba0c 100644
--- a/test_regress/t/t_public_seq.cpp
+++ b/test_regress/t/t_public_seq.cpp
@@ -16,8 +16,8 @@ std::unique_ptr topp;
 int main(int argc, char** argv) {
     vluint64_t sim_time = 1100;
     const std::unique_ptr contextp{new VerilatedContext};
-    contextp->commandArgs(argc, argv);
     contextp->debug(0);
+    contextp->commandArgs(argc, argv);
     srand48(5);
     topp.reset(new Vt_public_seq("top"));
 
diff --git a/test_regress/t/t_queue_compare.pl b/test_regress/t/t_queue_compare.pl
new file mode 100755
index 000000000..9a15dd2cc
--- /dev/null
+++ b/test_regress/t/t_queue_compare.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 2019 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_compare.v b/test_regress/t/t_queue_compare.v
new file mode 100644
index 000000000..2ae40e991
--- /dev/null
+++ b/test_regress/t/t_queue_compare.v
@@ -0,0 +1,61 @@
+// DESCRIPTION: Verilator: Check == and != operations performed on queues
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2023 by Ilya Barkov.
+// SPDX-License-Identifier: CC0-1.0
+
+`define stop $stop
+`define check_comp(lhs, rhs, op, exp) if ((exp) != ((lhs) op (rhs))) begin $write("%%Error: %s:%0d: op comparison shall return 'b%x\n", `__FILE__, `__LINE__, (exp)); `stop; end
+// Two checks because == and != may not be derived from each other
+`define check_eq(lhs, rhs) `check_comp(lhs, rhs, ==, 1'b1) `check_comp(lhs, rhs, !=, 1'b0)
+`define check_ne(lhs, rhs) `check_comp(lhs, rhs, ==, 1'b0) `check_comp(lhs, rhs, !=, 1'b1)
+
+class Cls;
+   int i;
+endclass
+
+module t;
+   initial begin
+      begin // integers
+         int q1[$];
+         bit[31:0] q2[$];
+         q1.push_back(1);
+         q2.push_back(1);
+         q1.push_back(-2);
+         q2.push_back(-2);
+         `check_eq(q1, q2)
+
+         q2.push_back(3);
+         `check_ne(q1, q2)
+      end
+      begin // strings
+         string q1[$];
+         string q2[$];
+         q1.push_back("one");
+         q2.push_back("one");
+         q1.push_back("two");
+         q2.push_back("two");
+         `check_eq(q1, q2)
+
+         q2.push_back("three");
+         `check_ne(q1, q2)
+      end
+
+      begin // classes
+         Cls a = new;
+         Cls b = new;
+         Cls q1[$];
+         Cls q2[$];
+         q1.push_back(a);
+         q2.push_back(b);
+         `check_ne(q1, q2)
+
+         q1.push_back(b);
+         q2.push_front(a);
+         `check_eq(q1, q2)
+      end
+
+      $write("*-* All Finished *-*\n");
+      $finish;
+   end
+endmodule
diff --git a/test_regress/t/t_queue_method3_bad.pl b/test_regress/t/t_queue_method3_bad.pl
index fbdf9000e..a083f46f5 100755
--- a/test_regress/t/t_queue_method3_bad.pl
+++ b/test_regress/t/t_queue_method3_bad.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_real_param.pl b/test_regress/t/t_real_param.pl
index ec4c9a6e4..1aa73f80a 100755
--- a/test_regress/t/t_real_param.pl
+++ b/test_regress/t/t_real_param.pl
@@ -2,7 +2,7 @@
 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
+# Copyright 2022 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.
diff --git a/test_regress/t/t_recursive_module_bug_2.v b/test_regress/t/t_recursive_module_bug_2.v
index fd47d945b..13ab908cf 100644
--- a/test_regress/t/t_recursive_module_bug_2.v
+++ b/test_regress/t/t_recursive_module_bug_2.v
@@ -4,6 +4,7 @@
 // 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
 
 module a #(parameter N) ();
    generate if (N > 1) begin
diff --git a/test_regress/t/t_runflag_bad.pl b/test_regress/t/t_runflag_bad.pl
index fd3637bc3..0eeef974c 100755
--- a/test_regress/t/t_runflag_bad.pl
+++ b/test_regress/t/t_runflag_bad.pl
@@ -16,31 +16,31 @@ compile(
 execute(
     all_run_flags => ["+verilator+bad+flag+testing"],
     fails => 1,
-    expect_filename => $Self->{golden_filename} . "-a",
+    expect_filename => "t/" . $Self->{name} . "_a.out",
     );
 
 execute(
     all_run_flags => ["+verilator+rand+reset+-1"],
     fails => 1,
-    expect_filename => $Self->{golden_filename} . "-b"
+    expect_filename => "t/" . $Self->{name} . "_b.out",
     );
 
 execute(
     all_run_flags => ["+verilator+rand+reset+3"],
     fails => 1,
-    expect_filename => $Self->{golden_filename} . "-c"
+    expect_filename => "t/" . $Self->{name} . "_c.out",
     );
 
 execute(
     all_run_flags => ["+verilator+prof+threads+window+0"],
     fails => 1,
-    expect_filename => $Self->{golden_filename} . "-d"
+    expect_filename => "t/" . $Self->{name} . "_d.out",
     );
 
 execute(
     all_run_flags => ["+verilator+prof+threads+window+1000000000000000000000000"],
     fails => 1,
-    expect_filename => $Self->{golden_filename} . "-e"
+    expect_filename => "t/" . $Self->{name} . "_e.out",
     );
 
 ok(1);
diff --git a/test_regress/t/t_runflag_bad.out-a b/test_regress/t/t_runflag_bad_a.out
similarity index 100%
rename from test_regress/t/t_runflag_bad.out-a
rename to test_regress/t/t_runflag_bad_a.out
diff --git a/test_regress/t/t_runflag_bad.out-b b/test_regress/t/t_runflag_bad_b.out
similarity index 100%
rename from test_regress/t/t_runflag_bad.out-b
rename to test_regress/t/t_runflag_bad_b.out
diff --git a/test_regress/t/t_runflag_bad.out-c b/test_regress/t/t_runflag_bad_c.out
similarity index 100%
rename from test_regress/t/t_runflag_bad.out-c
rename to test_regress/t/t_runflag_bad_c.out
diff --git a/test_regress/t/t_runflag_bad.out-d b/test_regress/t/t_runflag_bad_d.out
similarity index 100%
rename from test_regress/t/t_runflag_bad.out-d
rename to test_regress/t/t_runflag_bad_d.out
diff --git a/test_regress/t/t_runflag_bad.out-e b/test_regress/t/t_runflag_bad_e.out
similarity index 100%
rename from test_regress/t/t_runflag_bad.out-e
rename to test_regress/t/t_runflag_bad_e.out
diff --git a/test_regress/t/t_sampled_expr.pl b/test_regress/t/t_sampled_expr.pl
index c505d6263..a86f4c404 100755
--- a/test_regress/t/t_sampled_expr.pl
+++ b/test_regress/t/t_sampled_expr.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_savable_open_bad2.cpp b/test_regress/t/t_savable_open_bad2.cpp
index c3a278118..8086da829 100644
--- a/test_regress/t/t_savable_open_bad2.cpp
+++ b/test_regress/t/t_savable_open_bad2.cpp
@@ -23,9 +23,10 @@ int errors = 0;
 double sc_time_stamp() { return main_time; }
 
 int main(int argc, char* argv[]) {
-    // No need to make a model:  topp = new VM_PREFIX;
-
     Verilated::debug(0);
+    Verilated::commandArgs(argc, argv);
+
+    // No need to make a model:  topp = new VM_PREFIX;
     {
         VerilatedSave os;
         os.open("/No/such_file_as_this");
diff --git a/test_regress/t/t_sc_names.pl b/test_regress/t/t_sc_names.pl
index 2dc3e81c8..c234cca69 100755
--- a/test_regress/t/t_sc_names.pl
+++ b/test_regress/t/t_sc_names.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2020 by Edgar E. Iglesias. This program is free software; you
+# 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.
@@ -14,11 +14,9 @@ if (!$Self->have_sc) {
     skip("No SystemC installed");
 }
 else {
-    top_filename("t/t_sc_names.v");
-
     compile(
         make_main => 0,
-        verilator_flags2 => ["-sc --exe $Self->{t_dir}/t_sc_names.cpp"],
+        verilator_flags2 => ["-sc --exe $Self->{t_dir}/$Self->{name}.cpp"],
         );
 
     execute(
diff --git a/test_regress/t/t_scheduling_0.pl b/test_regress/t/t_scheduling_0.pl
index 07078dca2..1aa73f80a 100755
--- a/test_regress/t/t_scheduling_0.pl
+++ b/test_regress/t/t_scheduling_0.pl
@@ -2,8 +2,8 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Geza Lore. This program is free software; you can
-# redistribute it and/or modify it under the terms of either the GNU
+# Copyright 2022 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
diff --git a/test_regress/t/t_scheduling_1.pl b/test_regress/t/t_scheduling_1.pl
index 07078dca2..1aa73f80a 100755
--- a/test_regress/t/t_scheduling_1.pl
+++ b/test_regress/t/t_scheduling_1.pl
@@ -2,8 +2,8 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Geza Lore. This program is free software; you can
-# redistribute it and/or modify it under the terms of either the GNU
+# Copyright 2022 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
diff --git a/test_regress/t/t_scheduling_2.pl b/test_regress/t/t_scheduling_2.pl
index 07078dca2..1aa73f80a 100755
--- a/test_regress/t/t_scheduling_2.pl
+++ b/test_regress/t/t_scheduling_2.pl
@@ -2,8 +2,8 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Geza Lore. This program is free software; you can
-# redistribute it and/or modify it under the terms of either the GNU
+# Copyright 2022 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
diff --git a/test_regress/t/t_scheduling_3.pl b/test_regress/t/t_scheduling_3.pl
index 07078dca2..1aa73f80a 100755
--- a/test_regress/t/t_scheduling_3.pl
+++ b/test_regress/t/t_scheduling_3.pl
@@ -2,8 +2,8 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Geza Lore. This program is free software; you can
-# redistribute it and/or modify it under the terms of either the GNU
+# Copyright 2022 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
diff --git a/test_regress/t/t_scheduling_4.pl b/test_regress/t/t_scheduling_4.pl
index 07078dca2..1aa73f80a 100755
--- a/test_regress/t/t_scheduling_4.pl
+++ b/test_regress/t/t_scheduling_4.pl
@@ -2,8 +2,8 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Geza Lore. This program is free software; you can
-# redistribute it and/or modify it under the terms of either the GNU
+# Copyright 2022 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
diff --git a/test_regress/t/t_select_crazy.pl b/test_regress/t/t_select_crazy.pl
new file mode 100755
index 000000000..b46d46042
--- /dev/null
+++ b/test_regress/t/t_select_crazy.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_crazy_sel.v b/test_regress/t/t_select_crazy.v
similarity index 100%
rename from test_regress/t/t_crazy_sel.v
rename to test_regress/t/t_select_crazy.v
diff --git a/test_regress/t/t_split_var_0.pl b/test_regress/t/t_split_var_0.pl
index 321950306..6f0d325a3 100755
--- a/test_regress/t/t_split_var_0.pl
+++ b/test_regress/t/t_split_var_0.pl
@@ -12,7 +12,7 @@ scenarios(simulator => 1);
 
 # CI 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.
+# So use 6 threads here though it's not optimal in performance, but ok.
 compile(
     verilator_flags2 => ['--stats', "$Self->{t_dir}/t_split_var_0.vlt"],
     threads => $Self->{vltmt} ? 6 : 1
diff --git a/test_regress/t/t_split_var_2_trace.pl b/test_regress/t/t_split_var_2_trace.pl
index 9395d8cc5..6016b60f4 100755
--- a/test_regress/t/t_split_var_2_trace.pl
+++ b/test_regress/t/t_split_var_2_trace.pl
@@ -13,7 +13,7 @@ top_filename("t/t_split_var_0.v");
 
 # CI 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.
+# So use 6 threads here though it's not optimal in performance, but ok.
 compile(
     verilator_flags2 => ['--cc --trace --stats +define+TEST_ATTRIBUTES'],
     threads => $Self->{vltmt} ? 6 : 1
diff --git a/test_regress/t/t_std_pkg_bad.pl b/test_regress/t/t_std_pkg_bad.pl
index 19ba90d40..44783b1f6 100755
--- a/test_regress/t/t_std_pkg_bad.pl
+++ b/test_regress/t/t_std_pkg_bad.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_stream_integer_type.v b/test_regress/t/t_stream_integer_type.v
index 2b606829f..bb7c94533 100644
--- a/test_regress/t/t_stream_integer_type.v
+++ b/test_regress/t/t_stream_integer_type.v
@@ -236,7 +236,7 @@ module t (/*AUTOARG*/
       end
    endfunction : print_data_error
 
-   function void print_all_data (string name = "");
+   function static void print_all_data (string name = "");
       foreach (byte_in[i]) $display(" %s byte_in[%0d]=%0h, byte_out=%0h ", name, i, byte_in[i], byte_out[i]);
       $display(" %s packed_data_32=%0h, packed_data_32_ref=%0h", name, packed_data_32, packed_data_32_ref);
 
diff --git a/test_regress/t/t_strength_2_uneq_assign.pl b/test_regress/t/t_strength_2_uneq_assign.pl
index 19ba90d40..44783b1f6 100755
--- a/test_regress/t/t_strength_2_uneq_assign.pl
+++ b/test_regress/t/t_strength_2_uneq_assign.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_strength_assignments_constants.pl b/test_regress/t/t_strength_assignments_constants.pl
index f5e338520..1aa73f80a 100755
--- a/test_regress/t/t_strength_assignments_constants.pl
+++ b/test_regress/t/t_strength_assignments_constants.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_strength_bufif1.pl b/test_regress/t/t_strength_bufif1.pl
index 35c0dfe5b..52f7cc53a 100755
--- a/test_regress/t/t_strength_bufif1.pl
+++ b/test_regress/t/t_strength_bufif1.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_strength_equal_strength.pl b/test_regress/t/t_strength_equal_strength.pl
index f5e338520..1aa73f80a 100755
--- a/test_regress/t/t_strength_equal_strength.pl
+++ b/test_regress/t/t_strength_equal_strength.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_strength_strong1_strong1_bad.pl b/test_regress/t/t_strength_strong1_strong1_bad.pl
index 19ba90d40..44783b1f6 100755
--- a/test_regress/t/t_strength_strong1_strong1_bad.pl
+++ b/test_regress/t/t_strength_strong1_strong1_bad.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_strength_strongest_constant.pl b/test_regress/t/t_strength_strongest_constant.pl
index f5e338520..1aa73f80a 100755
--- a/test_regress/t/t_strength_strongest_constant.pl
+++ b/test_regress/t/t_strength_strongest_constant.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_strength_strongest_non_tristate.pl b/test_regress/t/t_strength_strongest_non_tristate.pl
index f5e338520..1aa73f80a 100755
--- a/test_regress/t/t_strength_strongest_non_tristate.pl
+++ b/test_regress/t/t_strength_strongest_non_tristate.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_struct_assign.out b/test_regress/t/t_struct_assign.out
new file mode 100644
index 000000000..d897b7de2
--- /dev/null
+++ b/test_regress/t/t_struct_assign.out
@@ -0,0 +1,3 @@
+(          3,           4) (          3,           4)
+%p='{fst:'h3, snd:'h4}
+*-* All Finished *-*
diff --git a/test_regress/t/t_struct_assign.pl b/test_regress/t/t_struct_assign.pl
new file mode 100755
index 000000000..11eeb66fe
--- /dev/null
+++ b/test_regress/t/t_struct_assign.pl
@@ -0,0 +1,22 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 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(
+    expect_filename => $Self->{golden_filename},
+    check_finished => 1,
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_struct_assign.v b/test_regress/t/t_struct_assign.v
new file mode 100644
index 000000000..c0dc33341
--- /dev/null
+++ b/test_regress/t/t_struct_assign.v
@@ -0,0 +1,27 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2022 by Antmicro Ltd.
+// SPDX-License-Identifier: CC0-1.0
+
+module t (/*AUTOARG*/);
+   typedef struct {
+      int fst, snd;
+   } pair_t;
+
+   pair_t a, b;
+
+   initial begin
+      a.fst = 1;
+      a.snd = 2;
+      b.fst = 3;
+      b.snd = 4;
+
+      a = b;
+
+      $display("(%d, %d) (%d, %d)", a.fst, a.snd, b.fst, b.snd);
+      $display("%%p=%p", a);
+      $write("*-* All Finished *-*\n");
+      $finish;
+   end
+endmodule
diff --git a/test_regress/t/t_struct_unpacked.v b/test_regress/t/t_struct_unpacked.v
index 7014a9b08..29a1e69b9 100644
--- a/test_regress/t/t_struct_unpacked.v
+++ b/test_regress/t/t_struct_unpacked.v
@@ -5,22 +5,24 @@
 // SPDX-License-Identifier: CC0-1.0
 
 module x;
-
-   // verilator lint_off UNPACKED
    typedef struct {
-      int         a;
-   } notpacked_t;
-   // verilator lint_on UNPACKED
+      int a, b;
+      logic [3:0] c;
+   } embedded_t;
 
-   typedef struct packed {
-      notpacked_t b;
-   } ispacked_t;
+   typedef struct {
+      embedded_t b;
+      embedded_t tab [3:0];
+   } notembedded_t;
 
-   ispacked_t p;
+   notembedded_t p;
+   embedded_t t [1:0];
 
    initial begin
-      p.b = 1;
-      if (p.b != 1) $stop;
+      t[1].a = 2;
+      p.b.a = 1;
+      if (t[1].a != 2) $stop;
+      if (p.b.a != 1) $stop;
       $write("*-* All Finished *-*\n");
       $finish;
    end
diff --git a/test_regress/t/t_struct_unpacked2.out b/test_regress/t/t_struct_unpacked2.out
deleted file mode 100644
index d31ee7fcd..000000000
--- a/test_regress/t/t_struct_unpacked2.out
+++ /dev/null
@@ -1,10 +0,0 @@
-%Warning-UNPACKED: t/t_struct_unpacked2.v:10:13: Unsupported: Unpacked array in packed struct/union (struct/union converted to unpacked)
-   10 |       int b [2];
-      |             ^
-                   ... For warning description see https://verilator.org/warn/UNPACKED?v=latest
-                   ... Use "/* verilator lint_off UNPACKED */" and lint_on around source to disable this message.
-%Warning-UNPACKED: t/t_struct_unpacked2.v:9:12: Unsupported: Unpacked struct/union
-                                              : ... In instance x
-    9 |    typedef struct {
-      |            ^~~~~~
-%Error: Exiting due to
diff --git a/test_regress/t/t_struct_unused.pl b/test_regress/t/t_struct_unused.pl
new file mode 100755
index 000000000..efbd21e12
--- /dev/null
+++ b/test_regress/t/t_struct_unused.pl
@@ -0,0 +1,33 @@
+#!/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_all => 1);
+
+# Use --debug-protect to assist debug
+
+compile(
+    );
+
+execute(
+    check_finished => 1,
+    );
+
+if ($Self->{vlt_all}) {
+    # Check for unused structs in any outputs
+    my $any;
+    foreach my $filename (glob $Self->{obj_dir} . "/*.[ch]*") {
+        file_grep_not($filename, qr/useless/i);
+        $any = 1;
+    }
+    $any or $Self->error("No outputs found");
+}
+
+ok(1);
+1;
diff --git a/test_regress/t/t_struct_unused.v b/test_regress/t/t_struct_unused.v
new file mode 100644
index 000000000..07181488a
--- /dev/null
+++ b/test_regress/t/t_struct_unused.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, 2022 by Antmicro Ltd.
+// SPDX-License-Identifier: CC0-1.0
+
+module x;
+   typedef struct {
+      int fst, snd;
+   } uselessA_t;
+
+   typedef struct {
+      bit [3:0] n;
+      uselessA_t b;
+   } uselessB_t;
+
+   uselessA_t useless;
+
+   initial begin
+      $write("*-* All Finished *-*\n");
+      $finish;
+   end
+endmodule
diff --git a/test_regress/t/t_structu_dataType_assignment.pl b/test_regress/t/t_structu_dataType_assignment.pl
index 2cb5eeaff..45d42e7f6 100755
--- a/test_regress/t/t_structu_dataType_assignment.pl
+++ b/test_regress/t/t_structu_dataType_assignment.pl
@@ -11,6 +11,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 scenarios(simulator => 1);
 
 compile(
+    verilator_flags2 => ['--structs-packed'],
     );
 
 execute(
diff --git a/test_regress/t/t_structu_dataType_assignment.v b/test_regress/t/t_structu_dataType_assignment.v
index 209dc34b6..5839b375a 100644
--- a/test_regress/t/t_structu_dataType_assignment.v
+++ b/test_regress/t/t_structu_dataType_assignment.v
@@ -38,9 +38,9 @@ module top();
     int A;
     struct {
       int B, C;
-      struct{
+      struct {
         int D, E;
-        struct{
+        struct {
           int F;
           shortint G;
         } FG1;
diff --git a/test_regress/t/t_structu_dataType_assignment_bad.pl b/test_regress/t/t_structu_dataType_assignment_bad.pl
index bec0388e9..b9230bc2a 100755
--- a/test_regress/t/t_structu_dataType_assignment_bad.pl
+++ b/test_regress/t/t_structu_dataType_assignment_bad.pl
@@ -12,6 +12,7 @@ scenarios(simulator => 1);
 
 
 compile(
+    verilator_flags2 => ['--structs-packed'],
     fails => 1,
     expect_filename => $Self->{golden_filename},
     );
diff --git a/test_regress/t/t_sys_fopen_bad.out b/test_regress/t/t_sys_fopen_bad.out
new file mode 100644
index 000000000..b788b2245
--- /dev/null
+++ b/test_regress/t/t_sys_fopen_bad.out
@@ -0,0 +1,4 @@
+%Error: t/t_sys_fopen_bad.v:14:34: $fopen mode should be <= 4 characters
+   14 |       file = $fopen("/dev/null", "somereallywidebad");
+      |                                  ^~~~~~~~~~~~~~~~~~~
+%Error: Exiting due to
diff --git a/test_regress/t/t_sys_fopen_bad.pl b/test_regress/t/t_sys_fopen_bad.pl
new file mode 100755
index 000000000..a5846c699
--- /dev/null
+++ b/test_regress/t/t_sys_fopen_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 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(
+    fails => 1,
+    expect_filename => $Self->{golden_filename},
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_sys_fopen_bad.v b/test_regress/t/t_sys_fopen_bad.v
new file mode 100644
index 000000000..9d633d4fe
--- /dev/null
+++ b/test_regress/t/t_sys_fopen_bad.v
@@ -0,0 +1,17 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// Copyright 2022 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
+
+module t ();
+
+   integer file;
+
+   initial begin
+      file = $fopen("/dev/null", "somereallywidebad");
+   end
+
+endmodule
diff --git a/test_regress/t/t_timescale_parse.cpp b/test_regress/t/t_timescale_parse.cpp
index 128a1b2e8..0b4da3371 100644
--- a/test_regress/t/t_timescale_parse.cpp
+++ b/test_regress/t/t_timescale_parse.cpp
@@ -1,7 +1,8 @@
 // -*- mode: C++; c-file-style: "cc-mode" -*-
 //
-// This file ONLY is placed into the Public Domain, for any use,
-// without warranty, 2019 by Wilson Snyder
+// 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
 
 #include "Vt_timescale_parse.h"
 
diff --git a/test_regress/t/t_timing_unset3.out b/test_regress/t/t_timing_unset3.out
new file mode 100644
index 000000000..3d91db2b4
--- /dev/null
+++ b/test_regress/t/t_timing_unset3.out
@@ -0,0 +1,6 @@
+%Error-NEEDTIMINGOPT: t/t_clocking_notiming.v:11:8: Use --timing or --no-timing to specify how clocking output skew greater than #0 should be handled
+                                                  : ... In instance t
+   11 |        output #1 out;
+      |        ^~~~~~
+                      ... For error description see https://verilator.org/warn/NEEDTIMINGOPT?v=latest
+%Error: Exiting due to
diff --git a/test_regress/t/t_timing_unset3.pl b/test_regress/t/t_timing_unset3.pl
new file mode 100755
index 000000000..8c206a0f0
--- /dev/null
+++ b/test_regress/t/t_timing_unset3.pl
@@ -0,0 +1,22 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2022 by Antmicro Ltd. 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);
+
+top_filename("t/t_clocking_notiming.v");
+
+compile(
+    # --timing/--no-timing not specified
+    fails => 1,
+    expect_filename => $Self->{golden_filename},
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_trace_cat.cpp b/test_regress/t/t_trace_cat.cpp
index bc5cc83bc..488eb4187 100644
--- a/test_regress/t/t_trace_cat.cpp
+++ b/test_regress/t/t_trace_cat.cpp
@@ -23,10 +23,11 @@ const char* trace_name() {
 }
 
 int main(int argc, char** argv) {
-    std::unique_ptr top{new VM_PREFIX("top")};
-
     Verilated::debug(0);
     Verilated::traceEverOn(true);
+    Verilated::commandArgs(argc, argv);
+
+    std::unique_ptr top{new VM_PREFIX("top")};
 
     std::unique_ptr tfp{new VerilatedVcdC};
     top->trace(tfp.get(), 99);
diff --git a/test_regress/t/t_trace_cat_fst.cpp b/test_regress/t/t_trace_cat_fst.cpp
index d541834a1..af8e3cdf3 100644
--- a/test_regress/t/t_trace_cat_fst.cpp
+++ b/test_regress/t/t_trace_cat_fst.cpp
@@ -23,10 +23,11 @@ const char* trace_name() {
 }
 
 int main(int argc, char** argv) {
-    std::unique_ptr top{new VM_PREFIX("top")};
-
     Verilated::debug(0);
     Verilated::traceEverOn(true);
+    Verilated::commandArgs(argc, argv);
+
+    std::unique_ptr top{new VM_PREFIX("top")};
 
     std::unique_ptr tfp{new VerilatedFstC};
     top->trace(tfp.get(), 99);
diff --git a/test_regress/t/t_trace_dumpvars_dyn.cpp b/test_regress/t/t_trace_dumpvars_dyn.cpp
index 57f8c50ca..f143e04ba 100644
--- a/test_regress/t/t_trace_dumpvars_dyn.cpp
+++ b/test_regress/t/t_trace_dumpvars_dyn.cpp
@@ -20,10 +20,11 @@ double sc_time_stamp() { return (double)main_time; }
 const unsigned long long dt_2 = 3;
 
 int main(int argc, char** argv) {
-    std::unique_ptr top{new VM_PREFIX("top")};
-
     Verilated::debug(0);
     Verilated::traceEverOn(true);
+    Verilated::commandArgs(argc, argv);
+
+    std::unique_ptr top{new VM_PREFIX("top")};
 
 #if defined(T_TRACE_DUMPVARS_DYN_VCD_0) || defined(T_TRACE_DUMPVARS_DYN_VCD_1)
     std::unique_ptr tfp{new VerilatedVcdC};
diff --git a/test_regress/t/t_trace_open_wrong_order_bad.pl b/test_regress/t/t_trace_open_wrong_order_bad.pl
index a7c8b6c51..12e11bbab 100755
--- a/test_regress/t/t_trace_open_wrong_order_bad.pl
+++ b/test_regress/t/t_trace_open_wrong_order_bad.pl
@@ -2,28 +2,24 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Yu-Sheng Lin. This program is free software; you
+# Copyright 2023 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);
+scenarios(vlt => 1);
 
-if ($Self->{vlt_all}) {
-    compile(
-        verilator_flags2 => ["--cc --trace --exe $Self->{t_dir}/$Self->{name}.cpp"],
-        make_top_shell => 0,
-        make_main => 0,
-        );
-} else {
-    compile(
-        );
-}
+compile(
+    verilator_flags2 => ["--cc --trace --exe $Self->{t_dir}/$Self->{name}.cpp"],
+    make_top_shell => 0,
+    make_main => 0,
+    );
 
 execute(
     fails => 1
     );
+
 file_grep($Self->{run_log_filename}, qr/::trace\(\)' shall not be called after 'VerilatedVcdC::open\(\)'/i);
 
 ok(1);
diff --git a/test_regress/t/t_trace_public_func.cpp b/test_regress/t/t_trace_public_func.cpp
index cd65cf622..6cd30c21f 100644
--- a/test_regress/t/t_trace_public_func.cpp
+++ b/test_regress/t/t_trace_public_func.cpp
@@ -28,10 +28,11 @@ double sc_time_stamp() { return (double)main_time; }
 const unsigned long long dt_2 = 3;
 
 int main(int argc, char** argv) {
-    std::unique_ptr top{new VM_PREFIX("top")};
-
     Verilated::debug(0);
     Verilated::traceEverOn(true);
+    Verilated::commandArgs(argc, argv);
+
+    std::unique_ptr top{new VM_PREFIX("top")};
 
     std::unique_ptr tfp{new VerilatedVcdC};
     top->trace(tfp.get(), 99);
diff --git a/test_regress/t/t_trace_public_sig.cpp b/test_regress/t/t_trace_public_sig.cpp
index 7295bd20c..c694a85cc 100644
--- a/test_regress/t/t_trace_public_sig.cpp
+++ b/test_regress/t/t_trace_public_sig.cpp
@@ -26,10 +26,11 @@ double sc_time_stamp() { return (double)main_time; }
 const unsigned long long dt_2 = 3;
 
 int main(int argc, char** argv) {
-    VM_PREFIX* top = new VM_PREFIX{"top"};
-
     Verilated::debug(0);
     Verilated::traceEverOn(true);
+    Verilated::commandArgs(argc, argv);
+
+    VM_PREFIX* top = new VM_PREFIX{"top"};
 
     VerilatedVcdC* tfp = new VerilatedVcdC;
     top->trace(tfp, 99);
diff --git a/test_regress/t/t_trace_rollover.cpp b/test_regress/t/t_trace_rollover.cpp
index b9f72042b..b07466a29 100644
--- a/test_regress/t/t_trace_rollover.cpp
+++ b/test_regress/t/t_trace_rollover.cpp
@@ -17,10 +17,11 @@ unsigned long long main_time = 0;
 double sc_time_stamp() { return (double)main_time; }
 
 int main(int argc, char** argv) {
-    std::unique_ptr top{new VM_PREFIX("top")};
-
     Verilated::debug(0);
     Verilated::traceEverOn(true);
+    Verilated::commandArgs(argc, argv);
+
+    std::unique_ptr top{new VM_PREFIX("top")};
 
     std::unique_ptr tfp{new VerilatedVcdC};
     top->trace(tfp.get(), 99);
diff --git a/test_regress/t/t_trace_string.v b/test_regress/t/t_trace_string.v
index cb48d4770..065a7c2f9 100644
--- a/test_regress/t/t_trace_string.v
+++ b/test_regress/t/t_trace_string.v
@@ -22,7 +22,7 @@ module t (/*AUTOARG*/
    localparam string REGX [0:31] = '{"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0/fp", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
                                       "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"};
 
-   function string regx (logic [5-1:0] r, bit abi=1'b0);
+   function automatic string regx (logic [5-1:0] r, bit abi=1'b0);
       regx = abi ? REGX[r] : $sformatf("x%0d", r);
    endfunction: regx
 
diff --git a/test_regress/t/t_trace_two_cc.cpp b/test_regress/t/t_trace_two_cc.cpp
index 9b4378a40..92d9d33f9 100644
--- a/test_regress/t/t_trace_two_cc.cpp
+++ b/test_regress/t/t_trace_two_cc.cpp
@@ -30,8 +30,8 @@ int main(int argc, char** argv) {
     const std::unique_ptr contextp{new VerilatedContext};
 
     uint64_t sim_time = 1100;
-    contextp->commandArgs(argc, argv);
     contextp->debug(0);
+    contextp->commandArgs(argc, argv);
     contextp->traceEverOn(true);
     srand48(5);
     ap = new VM_PREFIX{contextp.get(), "topa"};
diff --git a/test_regress/t/t_trace_two_sc.cpp b/test_regress/t/t_trace_two_sc.cpp
index 99f111fe4..c1ba67b28 100644
--- a/test_regress/t/t_trace_two_sc.cpp
+++ b/test_regress/t/t_trace_two_sc.cpp
@@ -28,11 +28,12 @@ VM_PREFIX* ap;
 Vt_trace_two_b* bp;
 
 int sc_main(int argc, char** argv) {
+    Verilated::debug(0);
+    Verilated::traceEverOn(true);
+    Verilated::commandArgs(argc, argv);
+
     sc_signal clk;
     sc_time sim_time(1100, SC_NS);
-    Verilated::commandArgs(argc, argv);
-    Verilated::traceEverOn(true);
-    Verilated::debug(0);
     srand48(5);
     ap = new VM_PREFIX{"topa"};
     bp = new Vt_trace_two_b{"topb"};
diff --git a/test_regress/t/t_tri_cond_eqcase_with_1.pl b/test_regress/t/t_tri_cond_eqcase_with_1.pl
index f5e338520..1aa73f80a 100755
--- a/test_regress/t/t_tri_cond_eqcase_with_1.pl
+++ b/test_regress/t/t_tri_cond_eqcase_with_1.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_tri_eqcase_input.pl b/test_regress/t/t_tri_eqcase_input.pl
index f5e338520..1aa73f80a 100755
--- a/test_regress/t/t_tri_eqcase_input.pl
+++ b/test_regress/t/t_tri_eqcase_input.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_tri_gate.cpp b/test_regress/t/t_tri_gate.cpp
index 3981e94b7..5996914aa 100644
--- a/test_regress/t/t_tri_gate.cpp
+++ b/test_regress/t/t_tri_gate.cpp
@@ -33,12 +33,11 @@ bool check() {
 }
 
 int main() {
-    bool pass = true;
-
     Verilated::debug(0);
     tb = new VM_PREFIX{"tb"};
 
     // loop through every possibility and check the result
+    bool pass = true;
     for (tb->SEL = 0; tb->SEL < 2; tb->SEL++) {
         for (tb->A = 0; tb->A < 4; tb->A++) {
             tb->eval();
diff --git a/test_regress/t/t_tri_ifbegin.pl b/test_regress/t/t_tri_ifbegin.pl
index 980a2d197..dd4fed003 100755
--- a/test_regress/t/t_tri_ifbegin.pl
+++ b/test_regress/t/t_tri_ifbegin.pl
@@ -13,7 +13,7 @@ scenarios(simulator => 1);
 compile(
     );
 
-# No exeecution
+# No execution
 
 ok(1);
 1;
diff --git a/test_regress/t/t_tri_pullup.cpp b/test_regress/t/t_tri_pullup.cpp
index 29aa72a9e..84fc351d1 100644
--- a/test_regress/t/t_tri_pullup.cpp
+++ b/test_regress/t/t_tri_pullup.cpp
@@ -44,12 +44,12 @@ bool check() {
 }
 
 int main() {
-    bool pass = true;
-
     Verilated::debug(0);
+
     tb = new Vt_tri_pullup{"tb"};
 
     // loop through every possibility and check the result
+    bool pass = true;
     for (tb->OE = 0; tb->OE < 2; tb->OE++) {
         for (tb->A = 0; tb->A < 2; tb->A++) {
             tb->eval();
diff --git a/test_regress/t/t_tri_select.cpp b/test_regress/t/t_tri_select.cpp
index a4c6ee54a..ff31b307d 100644
--- a/test_regress/t/t_tri_select.cpp
+++ b/test_regress/t/t_tri_select.cpp
@@ -42,12 +42,12 @@ bool check() {
 }
 
 int main() {
-    bool pass = true;
-
     Verilated::debug(0);
+
     tb = new Vt_tri_select{"tb"};
 
     // loop through every possibility and check the result
+    bool pass = true;
     for (tb->OE1 = 0; tb->OE1 < 2; tb->OE1++) {
         for (tb->OE2 = 0; tb->OE2 < 2; tb->OE2++) {
             for (tb->A1 = 0; tb->A1 < 4; tb->A1++) {
diff --git a/test_regress/t/t_tri_select_eqcase.pl b/test_regress/t/t_tri_select_eqcase.pl
index f5e338520..1aa73f80a 100755
--- a/test_regress/t/t_tri_select_eqcase.pl
+++ b/test_regress/t/t_tri_select_eqcase.pl
@@ -2,7 +2,7 @@
 if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
 # DESCRIPTION: Verilator: Verilog Test driver/expect definition
 #
-# Copyright 2022 by Antmicro Ltd. This program is free software; you
+# Copyright 2022 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.
diff --git a/test_regress/t/t_type_param.pl b/test_regress/t/t_type_param.pl
index ec4c9a6e4..1aa73f80a 100755
--- a/test_regress/t/t_type_param.pl
+++ b/test_regress/t/t_type_param.pl
@@ -2,7 +2,7 @@
 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
+# Copyright 2022 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.
diff --git a/test_regress/t/t_struct_unpacked_bad.out b/test_regress/t/t_union_unpacked_bad.out
similarity index 52%
rename from test_regress/t/t_struct_unpacked_bad.out
rename to test_regress/t/t_union_unpacked_bad.out
index 6b83b545a..783f81c13 100644
--- a/test_regress/t/t_struct_unpacked_bad.out
+++ b/test_regress/t/t_union_unpacked_bad.out
@@ -1,7 +1,7 @@
-%Warning-UNPACKED: t/t_struct_unpacked_bad.v:9:12: Unsupported: Unpacked struct/union
-                                                 : ... In instance x
-    9 |    typedef struct {
-      |            ^~~~~~
+%Warning-UNPACKED: t/t_union_unpacked_bad.v:9:12: Unsupported: Unpacked union
+                                                : ... In instance x
+    9 |    typedef union {
+      |            ^~~~~
                    ... For warning description see https://verilator.org/warn/UNPACKED?v=latest
                    ... Use "/* verilator lint_off UNPACKED */" and lint_on around source to disable this message.
 %Error: Exiting due to
diff --git a/test_regress/t/t_struct_unpacked2.pl b/test_regress/t/t_union_unpacked_bad.pl
similarity index 100%
rename from test_regress/t/t_struct_unpacked2.pl
rename to test_regress/t/t_union_unpacked_bad.pl
diff --git a/test_regress/t/t_struct_unpacked2.v b/test_regress/t/t_union_unpacked_bad.v
similarity index 72%
rename from test_regress/t/t_struct_unpacked2.v
rename to test_regress/t/t_union_unpacked_bad.v
index e7c6ff9ff..d93b5ec5b 100644
--- a/test_regress/t/t_struct_unpacked2.v
+++ b/test_regress/t/t_union_unpacked_bad.v
@@ -6,15 +6,15 @@
 
 module x;
 
-   typedef struct {
-      int b [2];
-   } notpacked_t;
+   typedef union {
+      int         a;
+   } union_t;
 
-   notpacked_t n;
+   union_t b;
 
    initial begin
-      n.b[0] = 1;
-      if (n.b[0] != 1) $stop;
+      b = 1;
+      if (b != 1) $stop;
       $write("*-* All Finished *-*\n");
       $finish;
    end
diff --git a/test_regress/t/t_unopt_combo.vlt b/test_regress/t/t_unopt_combo.vlt
index 21286681d..5231aa4e6 100644
--- a/test_regress/t/t_unopt_combo.vlt
+++ b/test_regress/t/t_unopt_combo.vlt
@@ -1,3 +1,9 @@
+// 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
+
 `verilator_config
 
 lint_off -rule UNOPTFLAT -file "*t_unopt_combo.v" -match "Signal unoptimizable: Circular combinational logic: *"
diff --git a/test_regress/t/t_unpack_array_direct_assignment.pl b/test_regress/t/t_unpack_array_direct_assignment.pl
new file mode 100755
index 000000000..29a73f42a
--- /dev/null
+++ b/test_regress/t/t_unpack_array_direct_assignment.pl
@@ -0,0 +1,24 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2023 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);
+
+top_filename("t/t_unpack_array_no_expand.v");
+
+compile(
+    verilator_flags2 => ['-fno-expand'],
+    );
+
+execute(
+    check_finished => 1,
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_unpack_array_no_expand.pl b/test_regress/t/t_unpack_array_no_expand.pl
new file mode 100755
index 000000000..859050d63
--- /dev/null
+++ b/test_regress/t/t_unpack_array_no_expand.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 2023 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_unpack_array_no_expand.v b/test_regress/t/t_unpack_array_no_expand.v
new file mode 100644
index 000000000..04e83813d
--- /dev/null
+++ b/test_regress/t/t_unpack_array_no_expand.v
@@ -0,0 +1,42 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2023 by Wilson Snyder.
+// SPDX-License-Identifier: CC0-1.0
+
+module t
+  (
+   output logic [255:0] data_out
+   );
+   localparam int       NUM_STAGES = 3;
+
+   /* verilator lint_off ALWCOMBORDER */
+   /* verilator lint_off UNOPTFLAT */
+
+`define INPUT 256'hbabecafe
+
+   logic [255:0]        stage_data [NUM_STAGES+1];
+
+   genvar               stage;
+   generate
+      always_comb begin
+         stage_data[0] = `INPUT;
+      end
+      for (stage = 0; stage < NUM_STAGES; ++stage) begin : stage_gen
+         always_comb begin
+            stage_data[stage+1] = stage_data[stage];
+         end
+      end
+   endgenerate
+
+   /* verilator lint_on UNOPTFLAT */
+   /* verilator lint_on ALWCOMBORDER */
+
+   always_comb begin
+      data_out = stage_data[NUM_STAGES];
+      if (data_out !== `INPUT) $stop;
+      $write("*-* All Finished *-*\n");
+      $finish;
+   end
+
+endmodule
diff --git a/test_regress/t/t_unpacked_array_p_fmt.out b/test_regress/t/t_unpacked_array_p_fmt.out
new file mode 100644
index 000000000..6872828ed
--- /dev/null
+++ b/test_regress/t/t_unpacked_array_p_fmt.out
@@ -0,0 +1,3 @@
+%p='{'h0, 'h1, 'h1, 'h0, 'h1, 'h0, 'h0, 'h1, 'h1, 'h0, 'h0, 'h1, 'h0, 'h1, 'h1, 'h0} 
+%p='{'{'h0, 'h1, 'h1, 'h0} , '{'h1, 'h0, 'h0, 'h1} , '{'h1, 'h0, 'h0, 'h1} , '{'h0, 'h1, 'h1, 'h0} } 
+*-* All Finished *-*
diff --git a/test_regress/t/t_unpacked_array_p_fmt.pl b/test_regress/t/t_unpacked_array_p_fmt.pl
new file mode 100755
index 000000000..6e4e9e231
--- /dev/null
+++ b/test_regress/t/t_unpacked_array_p_fmt.pl
@@ -0,0 +1,22 @@
+#!/usr/bin/env perl
+if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
+# DESCRIPTION: Verilator: Verilog Test driver/expect definition
+#
+# Copyright 2023 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(
+    expect_filename => $Self->{golden_filename},
+    check_finished => 1,
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_unpacked_array_p_fmt.v b/test_regress/t/t_unpacked_array_p_fmt.v
new file mode 100644
index 000000000..64ee8a33a
--- /dev/null
+++ b/test_regress/t/t_unpacked_array_p_fmt.v
@@ -0,0 +1,22 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed into the Public Domain, for any use,
+// without warranty, 2023 by Antmicro Ltd.
+// SPDX-License-Identifier: CC0-1.0
+
+module t (/*AUTOARG*/);
+   reg arr [15:0];
+   reg mat [3:0] [3:0];
+
+   initial begin
+      for (int i = 0; i < 16; i++) begin
+         arr[i] = ^i;
+         mat[i/4][i%4] = ^i;
+      end
+
+      $display("%%p=%p", arr);
+      $display("%%p=%p", mat);
+      $write("*-* All Finished *-*\n");
+      $finish;
+   end
+endmodule
diff --git a/test_regress/t/t_unpacked_slice_range.v b/test_regress/t/t_unpacked_slice_range.v
index 58c1bc6a1..c1e46fa27 100644
--- a/test_regress/t/t_unpacked_slice_range.v
+++ b/test_regress/t/t_unpacked_slice_range.v
@@ -2,6 +2,7 @@
 //
 // This file ONLY is placed into the Public Domain, for any use,
 // without warranty, 2020 by Yutetsu TAKATSUKASA
+// SPDX-License-Identifier: Unlicense
 
 module t (
    clk
diff --git a/test_regress/t/t_unpacked_str_init2.v b/test_regress/t/t_unpacked_str_init2.v
index 9481aafb8..3d31cb54d 100644
--- a/test_regress/t/t_unpacked_str_init2.v
+++ b/test_regress/t/t_unpacked_str_init2.v
@@ -14,12 +14,12 @@ module t (/*AUTOARG*/);
                                       "s3", "s4", "s5", "s6", "s7", "s8", "s9",
                                       "s10", "s11", "t3", "t4", "t5", "t6"};
 
-   function string reg_x (logic [4:0] r, bit abi=1'b0);
+   function automatic string reg_x (logic [4:0] r, bit abi=1'b0);
       reg_x = abi ? REG_X[r] : $sformatf("x%0d", r);
    endfunction
 
    // the issue is triggered by a second function containing a case statement
-   function string f2 (logic [4:0] r, bit abi=0);
+   function automatic string f2 (logic [4:0] r, bit abi=0);
       case (r)
         5'd0:    f2 = $sformatf("nop");
         5'd1:    f2 = $sformatf("reg %s", reg_x(r[4:0], abi));
diff --git a/test_regress/t/t_var_bad_sv.out b/test_regress/t/t_var_bad_sv.out
index 7a5ff2358..9309d1ec0 100644
--- a/test_regress/t/t_var_bad_sv.out
+++ b/test_regress/t/t_var_bad_sv.out
@@ -1,5 +1,5 @@
 %Error: t/t_var_bad_sv.v:8:8: Unexpected 'do': 'do' is a SystemVerilog keyword misused as an identifier.
-        ... Suggest modify the Verilog-2001 code to avoid SV keywords, or use `begin_keywords or --language.
+                            : ... Suggest modify the Verilog-2001 code to avoid SV keywords, or use `begin_keywords or --language.
     8 |    reg do;
       |        ^~
 %Error: t/t_var_bad_sv.v:9:14: Unexpected 'do': 'do' is a SystemVerilog keyword misused as an identifier.
diff --git a/test_regress/t/t_var_overwidth_bad.cpp b/test_regress/t/t_var_overwidth_bad.cpp
index e0f45a1b0..5a4158ca8 100644
--- a/test_regress/t/t_var_overwidth_bad.cpp
+++ b/test_regress/t/t_var_overwidth_bad.cpp
@@ -21,6 +21,7 @@ double sc_time_stamp() { return main_time; }
 
 int main(int argc, char** argv) {
     Verilated::debug(0);
+    Verilated::commandArgs(argc, argv);
 
     VM_PREFIX* topp = new VM_PREFIX{""};  // Note null name - we're flattening it out
 
diff --git a/test_regress/t/t_var_sc_bv.cpp b/test_regress/t/t_var_sc_bv.cpp
index d8324bf2f..24e4ab7d7 100644
--- a/test_regress/t/t_var_sc_bv.cpp
+++ b/test_regress/t/t_var_sc_bv.cpp
@@ -14,7 +14,7 @@ double sc_time_stamp() { return 0; }
 void compare_signals(const sc_signal>& ls, const sc_signal>& rs) {
     if (ls.read() != rs.read()) {
         pass &= false;
-        VL_PRINTF("%%Error: Data missmatch in signals %s and %s\n", ls.name(), rs.name());
+        VL_PRINTF("%%Error: Data mismatch in signals %s and %s\n", ls.name(), rs.name());
     }
 }
 
diff --git a/test_regress/t/t_var_static.pl b/test_regress/t/t_var_static.pl
index 8d48ddb75..dc589151c 100755
--- a/test_regress/t/t_var_static.pl
+++ b/test_regress/t/t_var_static.pl
@@ -11,6 +11,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di
 scenarios(simulator => 1);
 
 compile(
+    verilator_flags2 => ['-Wno-IMPLICITSTATIC'],
     fails => $Self->{vlt_all},  # Verilator unsupported, bug546
     expect_filename => $Self->{golden_filename},
     );
diff --git a/test_regress/t/t_var_static_param.out b/test_regress/t/t_var_static_param.out
index ac3c941a9..2a08df190 100644
--- a/test_regress/t/t_var_static_param.out
+++ b/test_regress/t/t_var_static_param.out
@@ -1,6 +1,6 @@
-%Error-UNSUPPORTED: t/t_var_static_param.v:32:18: Unsupported: 'static' function/task variables
+%Error-UNSUPPORTED: t/t_var_static_param.v:33:18: Unsupported: 'static' function/task variables
                                                 : ... In instance t.subb
-   32 |       static int st = 2; st += P; return st;
+   33 |       static int st = 2; st += P; return st;
       |                  ^~
                     ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
 %Error: Exiting due to
diff --git a/test_regress/t/t_var_static_param.v b/test_regress/t/t_var_static_param.v
index 89f381d98..83972619f 100644
--- a/test_regress/t/t_var_static_param.v
+++ b/test_regress/t/t_var_static_param.v
@@ -27,6 +27,7 @@ endmodule
 
 module sub;
    parameter P = 1;
+   // verilator lint_off IMPLICITSTATIC
    function int f_no_st ();
       // This static is unique within each parameterized module
       static int st = 2; st += P; return st;
diff --git a/test_regress/t/t_vlt_syntax_bad.v b/test_regress/t/t_vlt_syntax_bad.v
index 6370f0978..0f1777e05 100644
--- a/test_regress/t/t_vlt_syntax_bad.v
+++ b/test_regress/t/t_vlt_syntax_bad.v
@@ -1,2 +1,8 @@
+// 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;
 endmodule
diff --git a/test_regress/t/t_vpi_cb_iter.cpp b/test_regress/t/t_vpi_cb_iter.cpp
index 295b95e4d..d7b4d932e 100644
--- a/test_regress/t/t_vpi_cb_iter.cpp
+++ b/test_regress/t/t_vpi_cb_iter.cpp
@@ -147,8 +147,8 @@ int main(int argc, char** argv) {
     const std::unique_ptr contextp{new VerilatedContext};
 
     uint64_t sim_time = 100;
-    contextp->commandArgs(argc, argv);
     contextp->debug(0);
+    contextp->commandArgs(argc, argv);
 
     const std::unique_ptr topp{new VM_PREFIX{contextp.get(),
                                                         // Note null name - we're flattening it out
diff --git a/test_regress/t/t_vpi_get.cpp b/test_regress/t/t_vpi_get.cpp
index 6d28d1d76..132d2f39d 100644
--- a/test_regress/t/t_vpi_get.cpp
+++ b/test_regress/t/t_vpi_get.cpp
@@ -243,8 +243,8 @@ int main(int argc, char** argv) {
     const std::unique_ptr contextp{new VerilatedContext};
 
     uint64_t sim_time = 1100;
-    contextp->commandArgs(argc, argv);
     contextp->debug(0);
+    contextp->commandArgs(argc, argv);
 
     const std::unique_ptr topp{new VM_PREFIX{contextp.get(),
                                                         // Note null name - we're flattening it out
diff --git a/test_regress/t/t_vpi_memory.cpp b/test_regress/t/t_vpi_memory.cpp
index 63562b2f2..09ff0af06 100644
--- a/test_regress/t/t_vpi_memory.cpp
+++ b/test_regress/t/t_vpi_memory.cpp
@@ -254,8 +254,8 @@ int main(int argc, char** argv) {
     const std::unique_ptr contextp{new VerilatedContext};
 
     uint64_t sim_time = 1100;
-    contextp->commandArgs(argc, argv);
     contextp->debug(0);
+    contextp->commandArgs(argc, argv);
     // we're going to be checking for these errors do don't crash out
     contextp->fatalOnVpiError(0);
 
diff --git a/test_regress/t/t_vpi_module.cpp b/test_regress/t/t_vpi_module.cpp
index 14ba4236f..650c7f55f 100644
--- a/test_regress/t/t_vpi_module.cpp
+++ b/test_regress/t/t_vpi_module.cpp
@@ -175,8 +175,8 @@ int main(int argc, char** argv) {
     const std::unique_ptr contextp{new VerilatedContext};
 
     uint64_t sim_time = 1100;
-    contextp->commandArgs(argc, argv);
     contextp->debug(0);
+    contextp->commandArgs(argc, argv);
     // we're going to be checking for these errors do don't crash out
     contextp->fatalOnVpiError(0);
 
diff --git a/test_regress/t/t_vpi_onetime_cbs.cpp b/test_regress/t/t_vpi_onetime_cbs.cpp
new file mode 100644
index 000000000..c7632f8a9
--- /dev/null
+++ b/test_regress/t/t_vpi_onetime_cbs.cpp
@@ -0,0 +1,342 @@
+// -*- mode: C++; c-file-style: "cc-mode" -*-
+//*************************************************************************
+//
+// Copyright 2021 by Wilson Snyder and Marlon James. 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
+//
+//*************************************************************************
+
+// Setup multiple one-time callbacks with different time delays.
+// Ensure they are not called before the delay has elapsed.
+
+#ifdef IS_VPI
+
+#include "vpi_user.h"
+
+#include 
+
+#else
+
+#include "verilated.h"
+#include "verilated_vpi.h"
+
+#include "Vt_vpi_onetime_cbs.h"
+
+#endif
+
+#include "TestSimulator.h"
+#include "TestVpi.h"
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+typedef struct {
+    PLI_UINT32 count;
+    PLI_UINT32* exp_times;
+    PLI_UINT32 number_of_exp_times;
+} cb_stats;
+
+static cb_stats CallbackStats[cbAtEndOfSimTime + 1];
+
+bool got_error = false;
+
+static vpiHandle ValueHandle, ToggleHandle, ClockHandle;
+
+#ifdef TEST_VERBOSE
+bool verbose = true;
+#else
+bool verbose = false;
+#endif
+
+#define CHECK_RESULT_NZ(got) \
+    if (!(got)) { \
+        printf("%%Error: %s:%d: GOT = NULL  EXP = !NULL\n", __FILE__, __LINE__); \
+        got_error = true; \
+        return __LINE__; \
+    }
+
+// Use cout to avoid issues with %d/%lx etc
+#define CHECK_RESULT(got, exp) \
+    if ((got) != (exp)) { \
+        std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << ": GOT = " << (got) \
+                  << "   EXP = " << (exp) << std::endl; \
+        got_error = true; \
+        return __LINE__; \
+    }
+
+#define STRINGIFY_CB_CASE(_cb) \
+    case _cb: return #_cb
+
+static const char* cb_reason_to_string(int cb_name) {
+    switch (cb_name) {
+        STRINGIFY_CB_CASE(cbAtStartOfSimTime);
+        STRINGIFY_CB_CASE(cbReadWriteSynch);
+        STRINGIFY_CB_CASE(cbReadOnlySynch);
+        STRINGIFY_CB_CASE(cbNextSimTime);
+        STRINGIFY_CB_CASE(cbStartOfSimulation);
+        STRINGIFY_CB_CASE(cbEndOfSimulation);
+        STRINGIFY_CB_CASE(cbAtEndOfSimTime);
+    default: return "Unsupported callback";
+    }
+}
+
+#undef STRINGIFY_CB_CASE
+
+bool cb_time_is_delay(int cb_name) {
+    // For some callbacks, time is interpreted as a delay from current time
+    // instead of an absolute time
+    if (cb_name == cbReadOnlySynch || cb_name == cbReadWriteSynch) { return true; }
+    return false;
+}
+
+// forward declaration
+static PLI_INT32 TheCallback(s_cb_data* data);
+
+static PLI_INT32 AtEndOfSimTimeCallback(s_cb_data* data) {
+    s_vpi_time t;
+
+    cb_stats* stats = &CallbackStats[data->reason];
+
+    t.type = vpiSimTime;
+    vpi_get_time(0, &t);
+
+    if (verbose) vpi_printf(const_cast("- [@%d] AtEndOfSimTime Callback\n"), t.low);
+
+    CHECK_RESULT(t.low, stats->exp_times[stats->count]);
+    stats->count += 1;
+
+    s_cb_data cb_data;
+    s_vpi_time time = {vpiSimTime, 0, 417, 0};  // non-zero time to check that it's ignored
+    cb_data.time = &time;
+    cb_data.reason = cbNextSimTime;
+    cb_data.cb_rtn = TheCallback;
+    vpiHandle Handle = vpi_register_cb(&cb_data);
+    CHECK_RESULT_NZ(Handle);
+
+    return 0;
+}
+
+static PLI_INT32 TheCallback(s_cb_data* data) {
+    s_vpi_time t;
+
+    cb_stats* stats = &CallbackStats[data->reason];
+
+    t.type = vpiSimTime;
+    vpi_get_time(0, &t);
+
+    if (verbose) {
+        vpi_printf(const_cast("- [@%d] %s Callback\n"), t.low,
+                   cb_reason_to_string(data->reason));
+    }
+
+    CHECK_RESULT(t.low, stats->exp_times[stats->count]);
+    stats->count += 1;
+
+    if (stats->count >= stats->number_of_exp_times) return 0;
+
+    s_cb_data cb_data;
+    PLI_UINT32 next_time;
+
+    if (data->reason == cbNextSimTime) {
+        // if a cbNextSimTime calback is scheduled from
+        // another cbNextSimTime callback, it will
+        // be called in the same timestep, so we need
+        // to delay registering
+        next_time = t.low;
+        cb_data.reason = cbAtEndOfSimTime;
+        cb_data.cb_rtn = AtEndOfSimTimeCallback;
+    } else {
+        next_time = stats->exp_times[stats->count];
+        if (cb_time_is_delay(data->reason)) { next_time -= t.low; }
+        cb_data.reason = data->reason;
+        cb_data.cb_rtn = TheCallback;
+    }
+
+    if (verbose) {
+        vpi_printf(const_cast("- [@%d] Registering %s Callback with time = %d\n"), t.low,
+                   cb_reason_to_string(cb_data.reason), next_time);
+    }
+
+    s_vpi_time time = {vpiSimTime, 0, next_time, 0};
+    cb_data.time = &time;
+    vpiHandle Handle = vpi_register_cb(&cb_data);
+    CHECK_RESULT_NZ(Handle);
+
+    return 0;
+}
+
+static PLI_INT32 StartOfSimulationCallback(s_cb_data* data) {
+    s_cb_data cb_data;
+    s_vpi_time timerec = {vpiSimTime, 0, 0, 0};
+
+    s_vpi_time t;
+    t.type = vpiSimTime;
+    vpi_get_time(0, &t);
+
+    if (verbose) vpi_printf(const_cast("- [@%d] cbStartOfSimulation Callback\n"), t.low);
+
+    CHECK_RESULT(t.low, CallbackStats[data->reason].exp_times[0]);
+    CallbackStats[data->reason].count += 1;
+
+    cb_data.time = &timerec;
+    cb_data.value = 0;
+    cb_data.user_data = 0;
+    cb_data.obj = 0;
+    cb_data.cb_rtn = TheCallback;
+
+    CallbackStats[cbAtStartOfSimTime].exp_times = new PLI_UINT32[3]{5, 15, 20};
+    CallbackStats[cbAtStartOfSimTime].number_of_exp_times = 3;
+    timerec.low = 5;
+    cb_data.reason = cbAtStartOfSimTime;
+    vpiHandle ASOSHandle = vpi_register_cb(&cb_data);
+    CHECK_RESULT_NZ(ASOSHandle);
+
+    CallbackStats[cbReadWriteSynch].exp_times = new PLI_UINT32[3]{6, 16, 21};
+    CallbackStats[cbReadWriteSynch].number_of_exp_times = 3;
+    timerec.low = 6;
+    cb_data.reason = cbReadWriteSynch;
+    vpiHandle RWHandle = vpi_register_cb(&cb_data);
+    CHECK_RESULT_NZ(RWHandle);
+
+    CallbackStats[cbReadOnlySynch].exp_times = new PLI_UINT32[3]{7, 17, 22};
+    CallbackStats[cbReadOnlySynch].number_of_exp_times = 3;
+    timerec.low = 7;
+    cb_data.reason = cbReadOnlySynch;
+    vpiHandle ROHandle = vpi_register_cb(&cb_data);
+    CHECK_RESULT_NZ(ROHandle);
+
+    CallbackStats[cbNextSimTime].exp_times = new PLI_UINT32[9]{5, 6, 7, 15, 16, 17, 20, 21, 22};
+    CallbackStats[cbNextSimTime].number_of_exp_times = 9;
+    timerec.low = 8;
+    cb_data.reason = cbNextSimTime;
+    vpiHandle NSTHandle = vpi_register_cb(&cb_data);
+    CHECK_RESULT_NZ(NSTHandle);
+
+    CallbackStats[cbAtEndOfSimTime].exp_times = new PLI_UINT32[8]{5, 6, 7, 15, 16, 17, 20, 21};
+    CallbackStats[cbAtEndOfSimTime].number_of_exp_times = 8;
+
+    return (0);
+}
+
+static int EndOfSimulationCallback(p_cb_data cb_data) {
+    s_vpi_time t;
+    t.type = vpiSimTime;
+    vpi_get_time(0, &t);
+
+    (void)cb_data;  // Unused
+
+    if (verbose) vpi_printf(const_cast("- [@%d] cbEndOfSimulation Callback\n"), t.low);
+
+    CHECK_RESULT(t.low, CallbackStats[cbEndOfSimulation].exp_times[0]);
+    CallbackStats[cbEndOfSimulation].count += 1;
+
+    CHECK_RESULT(CallbackStats[cbStartOfSimulation].count, 1);
+    CHECK_RESULT(CallbackStats[cbAtStartOfSimTime].count, 3);
+    CHECK_RESULT(CallbackStats[cbNextSimTime].count, 9);
+    CHECK_RESULT(CallbackStats[cbReadWriteSynch].count, 3);
+    CHECK_RESULT(CallbackStats[cbReadOnlySynch].count, 3);
+    CHECK_RESULT(CallbackStats[cbAtEndOfSimTime].count, 8);
+    CHECK_RESULT(CallbackStats[cbEndOfSimulation].count, 1);
+
+    if (!got_error) { printf("*-* All Finished *-*\n"); }
+    return 0;
+}
+
+// cver entry
+static void VPIRegister(void) {
+    // Clear stats
+    for (int cb = 1; cb <= cbAtEndOfSimTime; cb++) { CallbackStats[cb].count = 0; }
+    CallbackStats[cbStartOfSimulation].exp_times = new PLI_UINT32(0);
+    CallbackStats[cbEndOfSimulation].exp_times = new PLI_UINT32(22);
+    s_cb_data cb_data;
+    s_vpi_time timerec = {vpiSuppressTime, 0, 0, 0};
+
+    cb_data.time = &timerec;
+    cb_data.value = 0;
+    cb_data.user_data = 0;
+    cb_data.obj = 0;
+    cb_data.reason = cbStartOfSimulation;
+    cb_data.cb_rtn = StartOfSimulationCallback;
+
+    vpi_register_cb(&cb_data);
+
+    cb_data.reason = cbEndOfSimulation;
+    cb_data.cb_rtn = EndOfSimulationCallback;
+    vpi_register_cb(&cb_data);
+}
+
+#ifdef IS_VPI
+
+// icarus entry
+void (*vlog_startup_routines[])(void) = {VPIRegister, 0};
+
+#else
+
+int main(int argc, char** argv, char** env) {
+    double sim_time = 100;
+    const std::unique_ptr contextp{new VerilatedContext};
+
+    bool cbs_called;
+    contextp->commandArgs(argc, argv);
+    // contextp->debug(9);
+
+    const std::unique_ptr topp{new VM_PREFIX{contextp.get(),
+                                                        // Note null name - we're flattening it out
+                                                        ""}};
+
+    topp->clk = 1;
+
+    // StartOfSimulationCallback(nullptr);
+    VPIRegister();
+
+    VerilatedVpi::callCbs(cbStartOfSimulation);
+
+    topp->clk = 0;
+    topp->eval();
+
+    while (contextp->time() < sim_time && !contextp->gotFinish()) {
+        VerilatedVpi::callTimedCbs();
+        VerilatedVpi::callCbs(cbNextSimTime);
+        VerilatedVpi::callCbs(cbAtStartOfSimTime);
+
+        topp->eval();
+
+        VerilatedVpi::callValueCbs();
+        VerilatedVpi::callCbs(cbReadWriteSynch);
+        VerilatedVpi::callCbs(cbReadOnlySynch);
+        VerilatedVpi::callCbs(cbAtEndOfSimTime);
+
+        const uint64_t next_time = VerilatedVpi::cbNextDeadline();
+        if (next_time != -1) contextp->time(next_time);
+        if (verbose)
+            vpi_printf(const_cast("- [@%" PRId64 "] time change\n"), contextp->time());
+        if (next_time == -1 && !contextp->gotFinish()) {
+            if (got_error) {
+                vl_stop(__FILE__, __LINE__, "TOP-cpp");
+            } else {
+                VerilatedVpi::callCbs(cbEndOfSimulation);
+                contextp->gotFinish(true);
+            }
+        }
+
+        // Count updates on rising edge, so cycle through falling edge as well
+        topp->clk = !topp->clk;
+        topp->eval();
+        topp->clk = !topp->clk;
+    }
+
+    if (!contextp->gotFinish()) {
+        vl_fatal(__FILE__, __LINE__, "main", "%Error: Timeout; never got a $finish");
+    }
+    topp->final();
+
+    exit(0L);
+}
+
+#endif
diff --git a/test_regress/t/t_vpi_onetime_cbs.pl b/test_regress/t/t_vpi_onetime_cbs.pl
new file mode 100755
index 000000000..b4c84aee4
--- /dev/null
+++ b/test_regress/t/t_vpi_onetime_cbs.pl
@@ -0,0 +1,30 @@
+#!/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 and Marlon James. 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);
+
+$Self->{sanitize} = 0;  # Test neads cleanup to reclaim all callbacks
+
+compile(
+    make_top_shell => 0,
+    make_main => 0,
+    make_pli => 1,
+    verilator_flags2 => ["--exe --vpi $Self->{t_dir}/$Self->{name}.cpp"],
+    iv_flags2 => ["-g2005-sv -D USE_VPI_NOT_DPI -DIVERILOG"],
+    v_flags2 => ["+define+USE_VPI_NOT_DPI"],
+    );
+
+execute(
+    check_finished => 1,
+    use_libvpi => 1,
+    );
+
+ok(1);
+1;
diff --git a/test_regress/t/t_vpi_cbs_called.v b/test_regress/t/t_vpi_onetime_cbs.v
similarity index 100%
rename from test_regress/t/t_vpi_cbs_called.v
rename to test_regress/t/t_vpi_onetime_cbs.v
diff --git a/test_regress/t/t_vpi_param.cpp b/test_regress/t/t_vpi_param.cpp
index 46b7cad4c..12feae1fd 100644
--- a/test_regress/t/t_vpi_param.cpp
+++ b/test_regress/t/t_vpi_param.cpp
@@ -243,8 +243,8 @@ int main(int argc, char** argv) {
     const std::unique_ptr contextp{new VerilatedContext};
 
     uint64_t sim_time = 1100;
-    contextp->commandArgs(argc, argv);
     contextp->debug(0);
+    contextp->commandArgs(argc, argv);
     // we're going to be checking for these errors do don't crash out
     contextp->fatalOnVpiError(0);
 
diff --git a/test_regress/t/t_vpi_cbs_called.cpp b/test_regress/t/t_vpi_repetitive_cbs.cpp
similarity index 76%
rename from test_regress/t/t_vpi_cbs_called.cpp
rename to test_regress/t/t_vpi_repetitive_cbs.cpp
index 16dac6df9..84a82fa2c 100644
--- a/test_regress/t/t_vpi_cbs_called.cpp
+++ b/test_regress/t/t_vpi_repetitive_cbs.cpp
@@ -9,11 +9,19 @@
 //
 //*************************************************************************
 
+#ifdef IS_VPI
+
+#include "vpi_user.h"
+
+#include 
+
+#else
+
 #include "verilated.h"
 #include "verilated_vpi.h"
 
-#include "Vt_vpi_cbs_called.h"
-#include "vpi_user.h"
+#include "Vt_vpi_repetitive_cbs.h"
+#endif
 
 #include 
 #include 
@@ -25,8 +33,7 @@
 #include "TestSimulator.h"
 #include "TestVpi.h"
 
-const std::vector cbs_to_test{cbReadWriteSynch,    cbReadOnlySynch,   cbNextSimTime,
-                                   cbStartOfSimulation, cbEndOfSimulation, cbValueChange};
+const std::vector cbs_to_test{cbValueChange};
 
 enum CallbackState { PRE_REGISTER, ACTIVE, ACTIVE_AGAIN, REM_REREG_ACTIVE, POST_REMOVE };
 const std::vector cb_states{PRE_REGISTER, ACTIVE, ACTIVE_AGAIN, REM_REREG_ACTIVE,
@@ -46,17 +53,29 @@ std::vector::const_iterator state_iter;
 
 bool got_error = false;
 
+#ifdef IS_VPI
+vpiHandle clk_h;
+#endif
+
 #ifdef TEST_VERBOSE
 bool verbose = true;
 #else
 bool verbose = false;
 #endif
 
+#ifdef IS_VPI
+#define END_TEST \
+    vpi_control(vpiStop); \
+    return 0;
+#else
+#define END_TEST return __LINE__;
+#endif
+
 #define CHECK_RESULT_NZ(got) \
     if (!(got)) { \
         printf("%%Error: %s:%d: GOT = NULL  EXP = !NULL\n", __FILE__, __LINE__); \
         got_error = true; \
-        return __LINE__; \
+        END_TEST \
     }
 
 // Use cout to avoid issues with %d/%lx etc
@@ -65,7 +84,7 @@ bool verbose = false;
         std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << ": GOT = " << (got) \
                   << "   EXP = " << (exp) << std::endl; \
         got_error = true; \
-        return __LINE__; \
+        END_TEST \
     }
 
 #define STRINGIFY_CB_CASE(_cb) \
@@ -73,11 +92,6 @@ bool verbose = false;
 
 static const char* cb_reason_to_string(int cb_name) {
     switch (cb_name) {
-        STRINGIFY_CB_CASE(cbReadWriteSynch);
-        STRINGIFY_CB_CASE(cbReadOnlySynch);
-        STRINGIFY_CB_CASE(cbNextSimTime);
-        STRINGIFY_CB_CASE(cbStartOfSimulation);
-        STRINGIFY_CB_CASE(cbEndOfSimulation);
         STRINGIFY_CB_CASE(cbValueChange);
     default: return "Unsupported callback";
     }
@@ -86,6 +100,7 @@ static const char* cb_reason_to_string(int cb_name) {
 #undef STRINGIFY_CB_CASE
 
 static int the_callback(p_cb_data cb_data) {
+    vpi_printf(const_cast("     The callback\n"));
     callback_counts[cb_data->reason] = callback_counts[cb_data->reason] + 1;
     return 0;
 }
@@ -98,7 +113,12 @@ static int register_cb(const int next_state) {
     cb_data_testcase.cb_rtn = the_callback;
     cb_data_testcase.reason = cb;
 
+#ifdef IS_VPI
+    TestVpiHandle count_h = vpi_handle_by_name(const_cast("t.count"),
+                                               0);  // Needed in this scope as is in cb_data
+#else
     TestVpiHandle count_h = VPI_HANDLE("count");  // Needed in this scope as is in cb_data
+#endif
     CHECK_RESULT_NZ(count_h);
     if (cb == cbValueChange) {
         v.format = vpiSuppressVal;
@@ -170,9 +190,11 @@ static int test_callbacks(p_cb_data cb_data) {
     auto exp_count = callback_expected_counts[cb];
     CHECK_RESULT(count, exp_count);
 
+#if !defined(IS_VPI)
     bool called = callbacks_called[cb];
     bool exp_called = callbacks_expected_called[cb];
     CHECK_RESULT(called, exp_called);
+#endif
 
     // Update expected values based on state of callback in next time through main loop
     reset_expected();
@@ -213,7 +235,7 @@ static int test_callbacks(p_cb_data cb_data) {
         cb_data_n.reason = cbAfterDelay;
         t1.type = vpiSimTime;
         t1.high = 0;
-        t1.low = 1;
+        t1.low = 10;
         cb_data_n.time = &t1;
         cb_data_n.cb_rtn = test_callbacks;
         TestVpiHandle vh_test_cb = vpi_register_cb(&cb_data_n);
@@ -223,7 +245,34 @@ static int test_callbacks(p_cb_data cb_data) {
     return ret;
 }
 
-static int register_test_callback() {
+#ifdef IS_VPI
+static int toggle_clock(p_cb_data data) {
+    s_vpi_value val;
+    s_vpi_time time = {vpiSimTime, 0, 0, 0};
+
+    val.format = vpiIntVal;
+    vpi_get_value(clk_h, &val);
+    val.value.integer = !val.value.integer;
+    vpi_put_value(clk_h, &val, &time, vpiInertialDelay);
+
+    s_vpi_time cur_time = {vpiSimTime, 0, 0, 0};
+    vpi_get_time(0, &cur_time);
+
+    if (cur_time.low < 100 && !got_error) {
+        t_cb_data cb_data;
+        bzero(&cb_data, sizeof(cb_data));
+        time.low = 5;
+        cb_data.reason = cbAfterDelay;
+        cb_data.time = &time;
+        cb_data.cb_rtn = toggle_clock;
+        vpi_register_cb(&cb_data);
+    }
+
+    return 0;
+}
+#endif
+
+static int register_test_callback(p_cb_data data) {
     t_cb_data cb_data;
     bzero(&cb_data, sizeof(cb_data));
     s_vpi_time t1;
@@ -233,7 +282,7 @@ static int register_test_callback() {
     cb_data.reason = cbAfterDelay;
     t1.type = vpiSimTime;
     t1.high = 0;
-    t1.low = 1;
+    t1.low = 10;
     cb_data.time = &t1;
     cb_data.cb_rtn = test_callbacks;
     TestVpiHandle vh_test_cb = vpi_register_cb(&cb_data);
@@ -242,9 +291,49 @@ static int register_test_callback() {
     cb_iter = cbs_to_test.cbegin();
     state_iter = cb_states.cbegin();
 
+#ifdef IS_VPI
+    t1.low = 1;
+    cb_data.cb_rtn = toggle_clock;
+    TestVpiHandle vh_toggle_cb = vpi_register_cb(&cb_data);
+    CHECK_RESULT_NZ(vh_toggle_cb);
+
+    clk_h = vpi_handle_by_name(const_cast("t.clk"), 0);
+    CHECK_RESULT_NZ(clk_h);
+#endif
+
     return 0;
 }
 
+#ifdef IS_VPI
+
+static int end_of_sim_cb(p_cb_data cb_data) {
+    if (!got_error) { fprintf(stdout, "*-* All Finished *-*\n"); }
+    return 0;
+}
+
+// cver entry
+void vpi_compat_bootstrap(void) {
+    t_cb_data cb_data;
+    bzero(&cb_data, sizeof(cb_data));
+    {
+        vpi_printf(const_cast("register start-of-sim callback\n"));
+        cb_data.reason = cbStartOfSimulation;
+        cb_data.time = 0;
+        cb_data.cb_rtn = register_test_callback;
+        vpi_register_cb(&cb_data);
+    }
+    {
+        cb_data.reason = cbEndOfSimulation;
+        cb_data.time = 0;
+        cb_data.cb_rtn = end_of_sim_cb;
+        vpi_register_cb(&cb_data);
+    }
+}
+// icarus entry
+void (*vlog_startup_routines[])() = {vpi_compat_bootstrap, 0};
+
+#else
+
 int main(int argc, char** argv) {
     const std::unique_ptr contextp{new VerilatedContext};
 
@@ -258,7 +347,7 @@ int main(int argc, char** argv) {
 
     if (verbose) VL_PRINTF("-- { Sim Time %" PRId64 " } --\n", contextp->time());
 
-    register_test_callback();
+    register_test_callback(nullptr);
 
     topp->eval();
     topp->clk = 0;
@@ -274,17 +363,22 @@ int main(int argc, char** argv) {
 
         for (const auto& i : cbs_to_test) {
             if (verbose) {
-                VL_PRINTF("     Calling %s (%d) callbacks\t", cb_reason_to_string(i), i);
+                VL_PRINTF("     Calling %s (%d) callbacks\n     >>>>\n", cb_reason_to_string(i),
+                          i);
             }
             if (i == cbValueChange) {
                 cbs_called = VerilatedVpi::callValueCbs();
             } else {
                 cbs_called = VerilatedVpi::callCbs(i);
             }
-            if (verbose) VL_PRINTF(" - any callbacks called? %s\n", cbs_called ? "YES" : "NO");
+            if (verbose)
+                VL_PRINTF("     <<<<\n     Any callbacks called? %s\n", cbs_called ? "YES" : "NO");
             callbacks_called[i] = cbs_called;
         }
 
+        // Always calling this so we can get code coverage on the Verilator debug routine
+        VerilatedVpi::dumpCbs();
+
         VerilatedVpi::callTimedCbs();
 
         int64_t next_time = VerilatedVpi::cbNextDeadline();
@@ -314,3 +408,5 @@ int main(int argc, char** argv) {
 
     return 0;
 }
+
+#endif
diff --git a/test_regress/t/t_vpi_cbs_called.pl b/test_regress/t/t_vpi_repetitive_cbs.pl
similarity index 79%
rename from test_regress/t/t_vpi_cbs_called.pl
rename to test_regress/t/t_vpi_repetitive_cbs.pl
index 0d8f23641..8dab7fd6d 100755
--- a/test_regress/t/t_vpi_cbs_called.pl
+++ b/test_regress/t/t_vpi_repetitive_cbs.pl
@@ -8,16 +8,20 @@ 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);
 
 compile(
     make_top_shell => 0,
     make_main => 0,
+    make_pli => 1,
     verilator_flags2 => ["--exe --vpi $Self->{t_dir}/$Self->{name}.cpp"],
+    iv_flags2 => ["-g2005-sv -D USE_VPI_NOT_DPI -DIVERILOG"],
+    v_flags2 => ["+define+USE_VPI_NOT_DPI"],
     );
 
 execute(
     check_finished => 1,
+    use_libvpi => 1,
     );
 
 ok(1);
diff --git a/test_regress/t/t_vpi_repetitive_cbs.v b/test_regress/t/t_vpi_repetitive_cbs.v
new file mode 100644
index 000000000..3568bf9d7
--- /dev/null
+++ b/test_regress/t/t_vpi_repetitive_cbs.v
@@ -0,0 +1,24 @@
+// DESCRIPTION: Verilator: Verilog Test module
+//
+// This file ONLY is placed under the Creative Commons Public Domain, for
+// any use, without warranty, 2020 Wilson Snyder and Marlon James.
+// SPDX-License-Identifier: CC0-1.0
+
+
+module t (/*AUTOARG*/
+   // Inputs
+   input clk
+   );
+
+   reg [31:0]     count    /*verilator public_flat_rd */;
+
+   // Test loop
+   initial begin
+      count = 0;
+   end
+
+   always @(posedge clk) begin
+      count <= count + 2;
+   end
+
+endmodule : t
diff --git a/test_regress/t/t_vpi_time_cb.cpp b/test_regress/t/t_vpi_time_cb.cpp
index d41fddc30..b26a1fb1f 100644
--- a/test_regress/t/t_vpi_time_cb.cpp
+++ b/test_regress/t/t_vpi_time_cb.cpp
@@ -28,8 +28,8 @@ int main(int argc, char** argv) {
     const std::unique_ptr contextp{new VerilatedContext};
 
     uint64_t sim_time = 1100;
-    contextp->commandArgs(argc, argv);
     contextp->debug(0);
+    contextp->commandArgs(argc, argv);
 
     const std::unique_ptr topp{new VM_PREFIX{contextp.get(),
                                                         // Note null name - we're flattening it out
diff --git a/test_regress/t/t_vpi_unimpl.cpp b/test_regress/t/t_vpi_unimpl.cpp
index f3797f9eb..da925d42b 100644
--- a/test_regress/t/t_vpi_unimpl.cpp
+++ b/test_regress/t/t_vpi_unimpl.cpp
@@ -188,7 +188,7 @@ int main(int argc, char** argv) {
 
     uint64_t sim_time = 1100;
     contextp->commandArgs(argc, argv);
-    contextp->debug(0);
+    // contextp->debug(9);
     // we're going to be checking for these errors do don't crash out
     contextp->fatalOnVpiError(0);
 
diff --git a/test_regress/t/t_vpi_var.cpp b/test_regress/t/t_vpi_var.cpp
index a75095d5c..5f28eb0d5 100644
--- a/test_regress/t/t_vpi_var.cpp
+++ b/test_regress/t/t_vpi_var.cpp
@@ -521,7 +521,7 @@ int _mon_check_putget_str(p_cb_data cb_data) {
             int words = (i + 31) >> 5;
             TEST_MSG("========== %d ==========\n", i);
             if (callback_count_strs) {
-                // check persistance
+                // check persistence
                 if (data[i].type) {
                     v.format = data[i].type;
                 } else {
@@ -697,8 +697,8 @@ int main(int argc, char** argv) {
     const std::unique_ptr contextp{new VerilatedContext};
 
     uint64_t sim_time = 1100;
-    contextp->commandArgs(argc, argv);
     contextp->debug(0);
+    contextp->commandArgs(argc, argv);
 
     const std::unique_ptr topp{new VM_PREFIX{contextp.get(),
                                                         // Note null name - we're flattening it out
diff --git a/test_regress/t/t_vpi_zero_time_cb.cpp b/test_regress/t/t_vpi_zero_time_cb.cpp
index b5c74feb5..e94e11164 100644
--- a/test_regress/t/t_vpi_zero_time_cb.cpp
+++ b/test_regress/t/t_vpi_zero_time_cb.cpp
@@ -109,8 +109,8 @@ int main(int argc, char** argv) {
     const std::unique_ptr contextp{new VerilatedContext};
 
     uint64_t sim_time = 1100;
-    contextp->commandArgs(argc, argv);
     contextp->debug(0);
+    contextp->commandArgs(argc, argv);
 
     const std::unique_ptr topp{new VM_PREFIX{contextp.get(),
                                                         // Note null name - we're flattening it out
diff --git a/test_regress/t/t_waiveroutput_allgood.vlt b/test_regress/t/t_waiveroutput_allgood.vlt
index 2f6af4e29..54c5798f2 100644
--- a/test_regress/t/t_waiveroutput_allgood.vlt
+++ b/test_regress/t/t_waiveroutput_allgood.vlt
@@ -1,12 +1,11 @@
-// DESCRIPTION: Verilator output: Waivers generated with --waiver-output
+// 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
 
 `verilator_config
 
-// Below you find suggested waivers. You have three options:
-//   1. Fix the reason for the linter warning
-//   2. Keep the waiver permanently if you are sure this is okay
-//   3. Keep the waiver temporarily to suppress the output
-
 lint_off -rule WIDTH -file "*t/t_waiveroutput.v" -match "Operator ASSIGN expects 1 bits on the Assign RHS, but Assign RHS's CONST '2'h3' generates 2 bits."
 
 lint_off -rule UNUSED -file "*t/t_waiveroutput.v" -match "Signal is not used: 'width_warn'"
diff --git a/test_regress/t/t_xml_debugcheck.out b/test_regress/t/t_xml_debugcheck.out
index dbadeec0d..ff409ca14 100644
--- a/test_regress/t/t_xml_debugcheck.out
+++ b/test_regress/t/t_xml_debugcheck.out
@@ -54,7 +54,13 @@
       
       
         
+        
+          
+        
         
+        
+          
+        
         
         
           
@@ -679,7 +685,13 @@
       
       
         
+        
+          
+        
         
+        
+          
+        
         
         
         
@@ -1678,12 +1690,6 @@
         
           
         
-        
-          
-        
-        
-          
-        
       
       
     
diff --git a/verilator-config-version.cmake.in b/verilator-config-version.cmake.in
index d878347c7..7cf05f411 100644
--- a/verilator-config-version.cmake.in
+++ b/verilator-config-version.cmake.in
@@ -7,7 +7,7 @@
 #
 #     find_package(verilate 4.0)
 #
-# Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+# Copyright 2003-2023 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.
diff --git a/verilator-config.cmake.in b/verilator-config.cmake.in
index 8c19a2711..6b2338662 100644
--- a/verilator-config.cmake.in
+++ b/verilator-config.cmake.in
@@ -11,7 +11,7 @@
 #     add_executable(simulator )
 #     verilate(simulator SOURCES )
 #
-# Copyright 2003-2022 by Wilson Snyder. This program is free software; you
+# Copyright 2003-2023 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.