diff --git a/CMakeLists.txt b/CMakeLists.txt index 59ae991b5..911751a8a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ # #***************************************************************************** # -# Copyright 2003-2024 by Wilson Snyder. This program is free software; you +# Copyright 2003-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/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,11 +16,16 @@ cmake_minimum_required(VERSION 3.15) cmake_policy(SET CMP0091 NEW) # Use MSVC_RUNTIME_LIBRARY to select the runtime project( Verilator - VERSION 5.030 + VERSION 5.032 HOMEPAGE_URL https://verilator.org LANGUAGES CXX ) +# Set default build type to Release if not specified +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE) +endif() + option( DEBUG_AND_RELEASE_AND_COVERAGE "Builds both the debug and release binaries, overriding CMAKE_BUILD_TYPE. Not supported under MSBuild." @@ -173,6 +178,7 @@ install( PATTERN "include/verilated_config.h" PATTERN "include/*.[chv]" PATTERN "include/*.cpp" + PATTERN "include/*.vlt" PATTERN "include/*.sv" PATTERN "include/gtkwave/*.[chv]*" PATTERN "include/vltstd/*.[chv]*" diff --git a/Changes b/Changes index ad9894665..d2121e117 100644 --- a/Changes +++ b/Changes @@ -8,6 +8,61 @@ The changes in each Verilator version are described below. The contributors that suggested a given feature are shown in []. Thanks! +Verilator 5.032 2025-01-01 +========================== + +**Minor:** + +* Support queue's assignment `push_back/push_front('{})` (#5585) (#5586). [Yilou Wang] +* Support basic constrained random for multi-dimensional dynamic array and queue (#5591). [Yilou Wang] +* Support vpiDefName (#3906) (#5572). [Krzysztof Starecki] +* Support parameter names in pattern initialization (#5593) (#5596). [Greg Davill] +* Support randomize size constraints with restrictions (#5582 partial) (#5611). [Ryszard Rozak, Antmicro Ltd.] +* Support associative array basic constrained randomization (#5658) (#5670). [Yilou Wang] +* Support `default disable iff` and `$inferred_disable` (#4016). [Srinivasan Venkataramanan] +* Support `extern constraint` and `pure constraint`. +* Add `--no-std-waiver` and default reading of standard lint waivers file (#5607). +* Add `--no-std-package` as subset-alias of `--no-std` (#5607). +* Add `lint_off --contents` in configuration files (#5606). +* Add `--waiver-multiline` for context-sensitive `--waiver-output` (#5608). +* Add `--fno-inline-funcs` to disable function inlining. +* Add `--fno-slice` to disable array assignment slicing (#5644). +* Add error on illegal enum base type (#3010). [Iztok Jeras] +* Add error on `wait` with missing `.triggered` (#4457). +* Add error when improperly storing to parameter (#5147). [Gökçe Aydos] +* Add error on illegal `--prefix` etc. values (#5507). [Fabian Keßler] +* Add error on `--savable --timing` (#5690). [Narcis Rodas] +* Add coverage point hierarchy to coverage reports (#5575) (#5576). [Andrew Nolte] +* Add warning on global constraints (#5625). [Ryszard Rozak, Antmicro Ltd.] +* Add default CMAKE_BUILD_TYPE (#5691) (#5692). [Anthony Moore] +* Add error on `solve before` or soft constraints of `randc` variable. +* Improve concatenation performance (#5598) (#5599) (#5602). [Geza Lore] +* Improve optimization of duplicate wide expressions (#5637). [Bartłomiej Chmiel, Antmicro Ltd.] +* Fix dotted reference in delay value (#2410). +* Fix `function fork...join_none` regression with unknown type (#4449). +* Fix public_module requiring a wire to become public (#4916). [Andrew Nolte] +* Fix --hierarchical on projects with dot-f dependency lists (#5199) (#5669). [Bartłomiej Chmiel, Antmicro Ltd.] +* Fix can't locate scope error in interface task delayed assignment (#5462) (#5568). [Zhou Shen] +* Fix BLKANDNBLK for for VARXREFs (#5569). [Todd Strader] +* Fix VPI error instead of fatal for vpi_get_value() on large signals (#5571). [Todd Strader] +* Fix --output-groups leftover files issue (#5574). [Todd Strader] +* Fix slow unsized number parsing (#5577). [Geza Lore] +* Fix negative assignment pattern keys (#5580). [Iztok Jeras] +* Fix duplicate scope identifiers decoding (#5584). [Bartłomiej Chmiel, Antmicro Ltd.] +* Fix `rand` dynamic arrays with null handles (#5594). [Ryszard Rozak, Antmicro Ltd.] +* Fix NBAs to unpacked arrays of unpacked structs (#5603). [Geza Lore] +* Fix array of struct member overwrites on member update (#5605) (#5618) (#5628). [sumpster] +* Fix interface and struct pattern collision (#5639) (#5640). [Todd Strader] +* Fix mis-aliasing of instances with mailbox parameter types (#5632 partial). +* Fix error on duplicated declaration of gen block (#5663). [Ryszard Rozak, Antmicro Ltd.] +* Fix wildcard equality and inside operators for non-fourstate expressions (#5673). [Ryszard Rozak, Antmicro Ltd.] +* Fix `randomize..with` of parameterized classes (#5676). [Ryszard Rozak, Antmicro Ltd.] +* Fix interface bracketed array parameter access (#5677) (#5678). [Todd Strader] +* Fix width extension of operands of `inside` operator (#5685). [Ryszard Rozak, Antmicro Ltd.] +* Fix VPI + SYMRSVDWORD intersection (#5686). [Todd Strader] +* Fix verilator_gantt for hierarchically Verilated models (#5700). [Bartłomiej Chmiel, Antmicro Ltd.] + + Verilator 5.030 2024-10-27 ========================== @@ -103,6 +158,9 @@ Verilator 5.030 2024-10-27 * Fix build on gcc when using the Spack wrapper (#5555). [Eric Müller] * Fix enum name method (#5563). [Todd Strader] * Fix `$countbits` in assert with non-tristates (#5566). [Shou-Li Hsu] +* Fix missing VlProcess handle in coroutines with splits (#5623) (#5650). [Bartłomiej Chmiel, Antmicro Ltd.] +* Fix imported array assignment literals (#5642) (#5648). [Todd Strader] +* Fix foreach mixed array (#5655) (#5656). [Yilou Wang] Verilator 5.028 2024-08-21 @@ -4872,7 +4930,7 @@ Verilator 0.0 1994-07-08 Copyright ========= -Copyright 2001-2024 by Wilson Snyder. This program is free software; you +Copyright 2001-2025 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it 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 025294225..ea0310369 100644 --- a/Makefile.in +++ b/Makefile.in @@ -7,7 +7,7 @@ # #***************************************************************************** # -# Copyright 2003-2024 by Wilson Snyder. This program is free software; you +# Copyright 2003-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/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,6 +249,7 @@ VL_INST_INC_BLDDIR_FILES = \ # Files under srcdir, instead of build time VL_INST_INC_SRCDIR_FILES = \ include/*.[chv]* \ + include/*.vlt \ include/*.sv \ include/gtkwave/*.[chv]* \ include/vltstd/*.[chv]* \ @@ -451,13 +452,13 @@ analyzer-include: scan-build $(MAKE) -k examples format: - $(MAKE) -j 4 clang-format yapf format-exec + $(MAKE) -j 4 format-c format-py format-exec CLANGFORMAT = clang-format-14 CLANGFORMAT_FLAGS = -i CLANGFORMAT_FILES = $(CHECK_CPP) $(CHECK_H) $(CHECK_YL) test_regress/t/*.c* test_regress/t/*.h -clang-format: +format-c clang-format: @$(CLANGFORMAT) --version | egrep 14.0 > /dev/null \ || echo "*** You are not using clang-format-14, indents may differ from master's ***" $(CLANGFORMAT) $(CLANGFORMAT_FLAGS) $(CLANGFORMAT_FILES) @@ -517,7 +518,7 @@ PY_TEST_FILES = \ YAPF = yapf3 YAPF_FLAGS = -i --parallel -yapf: +format-py yapf: $(YAPF) $(YAPF_FLAGS) $(PY_FILES) GERSEMI = gersemi diff --git a/README.rst b/README.rst index 1a8f34017..e62b6317d 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,7 @@ .. Github doesn't render images unless absolute URL .. Do not know of a conditional tag, "only: github" nor "github display" works -|badge1| |badge2| |badge3| |badge4| |badge5| |badge6| |badge7| |badge8| +|badge1| |badge2| |badge3| |badge4| |badge5| |badge6| |badge7| .. |badge1| image:: https://img.shields.io/badge/Website-Verilator.org-181717.svg :target: https://verilator.org @@ -15,9 +15,7 @@ :target: https://hub.docker.com/r/verilator/verilator .. |badge6| image:: https://api.codacy.com/project/badge/Grade/fa78caa433c84a4ab9049c43e9debc6f :target: https://www.codacy.com/gh/verilator/verilator -.. |badge7| image:: https://codecov.io/gh/verilator/verilator/branch/master/graph/badge.svg - :target: https://codecov.io/gh/verilator/verilator -.. |badge8| image:: https://github.com/verilator/verilator/workflows/build/badge.svg +.. |badge7| image:: https://github.com/verilator/verilator/workflows/build/badge.svg :target: https://github.com/verilator/verilator/actions?query=workflow%3Abuild @@ -143,7 +141,7 @@ Related Projects Open License ============ -Verilator is Copyright 2003-2024 by Wilson Snyder. (Report bugs to +Verilator is Copyright 2003-2025 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/redirect b/bin/redirect index 0e7becf25..ddd8c1a4d 100644 --- a/bin/redirect +++ b/bin/redirect @@ -1,7 +1,7 @@ #!/usr/bin/env perl ###################################################################### # -# Copyright 2003-2024 by Wilson Snyder. This program is free software; you +# Copyright 2003-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it 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 b/bin/verilator index 1ca6d3b8c..6f8f5ae35 100755 --- a/bin/verilator +++ b/bin/verilator @@ -1,7 +1,7 @@ #!/usr/bin/env perl ###################################################################### # -# Copyright 2003-2024 by Wilson Snyder. This program is free software; you +# Copyright 2003-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. @@ -448,7 +448,9 @@ detailed descriptions of these arguments. --no-skip-identical Disable skipping identical output --stats Create statistics file --stats-vars Provide statistics on variables - --no-std Prevent parsing standard library + --no-std Prevent loading standard files + --no-std-package Prevent parsing standard package + --no-std-waiver Prevent parsing standard lint waivers --no-stop-fail Do not call $stop when assertion fails --structs-packed Convert all unpacked structures to packed structures -sv Enable SystemVerilog parsing @@ -487,7 +489,8 @@ detailed descriptions of these arguments. +verilog2001ext+ Synonym for +1364-2001ext+ --version Show program version and exits --vpi Enable VPI compiles - --waiver-output Create a waiver file based on the linter warnings + --waiver-multiline Create multiline --match for waivers + --waiver-output Create a waiver file based on linter warnings -Wall Enable all style warnings -Werror- Convert warnings to errors -Wfuture- Disable unknown message warnings @@ -540,7 +543,7 @@ description of these arguments. The latest version is available from L. -Copyright 2003-2024 by Wilson Snyder. This program is free software; you can +Copyright 2003-2025 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 92355a898..2c39d4f30 100755 --- a/bin/verilator_ccache_report +++ b/bin/verilator_ccache_report @@ -16,7 +16,7 @@ parser = argparse.ArgumentParser( For documentation see https://verilator.org/guide/latest/exe_verilator_ccache_report.html""", - epilog="""Copyright 2002-2024 by Wilson Snyder. This program is free software; you + epilog="""Copyright 2002-2025 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it 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 887d7b1f0..e7f1f6be2 100755 --- a/bin/verilator_coverage +++ b/bin/verilator_coverage @@ -1,7 +1,7 @@ #!/usr/bin/env perl ###################################################################### # -# Copyright 2003-2024 by Wilson Snyder. This program is free software; you +# Copyright 2003-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. @@ -188,7 +188,7 @@ L. The latest version is available from L. -Copyright 2003-2024 by Wilson Snyder. This program is free software; you +Copyright 2003-2025 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 1b77e3832..b4385509b 100755 --- a/bin/verilator_difftree +++ b/bin/verilator_difftree @@ -108,7 +108,7 @@ parser = argparse.ArgumentParser( 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.""", - epilog="""Copyright 2005-2024 by Wilson Snyder. This program is free software; you + epilog="""Copyright 2005-2025 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it 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 40450d299..2f5fb5ec1 100755 --- a/bin/verilator_gantt +++ b/bin/verilator_gantt @@ -36,7 +36,7 @@ def read_data(filename): re_proc_cpu = re.compile(r'VLPROFPROC processor\s*:\s*(\d+)\s*$') re_proc_dat = re.compile(r'VLPROFPROC ([a-z_ ]+)\s*:\s*(.*)$') cpu = None - thread = None + thread = 0 execGraphStart = None global LongestVcdStrValueLength @@ -54,11 +54,11 @@ def read_data(filename): if kind == "SECTION_PUSH": LongestVcdStrValueLength = max(LongestVcdStrValueLength, len(payload)) SectionStack.append(payload) - Sections.append((tick, tuple(SectionStack))) + Sections[thread].append((tick, tuple(SectionStack))) elif kind == "SECTION_POP": assert SectionStack, "SECTION_POP without SECTION_PUSH" SectionStack.pop() - Sections.append((tick, tuple(SectionStack))) + Sections[thread].append((tick, tuple(SectionStack))) elif kind == "MTASK_BEGIN": mtask, predict_start, ecpu = re_payload_mtaskBegin.match(payload).groups() mtask = int(mtask) @@ -97,6 +97,7 @@ def read_data(filename): print("-Unknown execution trace record: %s" % line) elif re_thread.match(line): thread = int(re_thread.match(line).group(1)) + Sections.append([]) elif re.match(r'^VLPROF(THREAD|VERSION)', line): pass elif re_arg1.match(line): @@ -307,23 +308,27 @@ def report_cpus(): def report_sections(): - if not Sections: - return - print("\nSection profile:") + for thread, section in enumerate(Sections): + if section: + print(f"\nSection profile for thread {thread}:") + report_section(section) + +def report_section(section): totalTime = collections.defaultdict(lambda: 0) selfTime = collections.defaultdict(lambda: 0) sectionTree = [0, {}, 1] # [selfTime, childTrees, numberOfTimesEntered] prevTime = 0 prevStack = () - for time, stack in Sections: + for time, stack in section: if len(stack) > len(prevStack): scope = sectionTree for item in stack: scope = scope[1].setdefault(item, [0, {}, 0]) scope[2] += 1 dt = time - prevTime + assert dt >= 0 scope = sectionTree for item in prevStack: scope = scope[1].setdefault(item, [0, {}, 0]) @@ -457,12 +462,13 @@ def write_vcd(filename): addValue(pcode, time, value) # Section graph - if Sections: - scode = getCode(LongestVcdStrValueLength * 8, "section", "trace") - dcode = getCode(32, "section", "depth") - for time, stack in Sections: - addValue(scode, time, stack[-1] if stack else None) - addValue(dcode, time, len(stack)) + for thread, section in enumerate(Sections): + if section: + scode = getCode(LongestVcdStrValueLength * 8, "section", f"t{thread}_trace") + dcode = getCode(32, "section", f"t{thread}_depth") + for time, stack in section: + addValue(scode, time, stack[-1] if stack else None) + addValue(dcode, time, len(stack)) # Create output file fh.write("$version Generated by verilator_gantt $end\n") @@ -523,7 +529,7 @@ Verilator_gantt creates a visual representation to help analyze Verilator For documentation see https://verilator.org/guide/latest/exe_verilator_gantt.html""", - epilog="""Copyright 2018-2024 by Wilson Snyder. This program is free software; you + epilog="""Copyright 2018-2025 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it 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 e704723d6..c41755823 100755 --- a/bin/verilator_includer +++ b/bin/verilator_includer @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # pylint: disable=C0114,C0209 # -# Copyright 2003-2024 by Wilson Snyder. This program is free software; you +# Copyright 2003-2025 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_profcfunc b/bin/verilator_profcfunc index 51ed57a58..434fe2823 100755 --- a/bin/verilator_profcfunc +++ b/bin/verilator_profcfunc @@ -173,7 +173,7 @@ in each Verilog block. For documentation see https://verilator.org/guide/latest/exe_verilator_profcfunc.html""", - epilog="""Copyright 2002-2024 by Wilson Snyder. This program is free software; you + epilog="""Copyright 2002-2025 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it 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/docker/buildenv/README.rst b/ci/docker/buildenv/README.rst index 2f04bb732..64d82509b 100644 --- a/ci/docker/buildenv/README.rst +++ b/ci/docker/buildenv/README.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 77cb1adf6..86bad6cdb 100644 --- a/ci/docker/run/README.rst +++ b/ci/docker/run/README.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 bd2ee7f52..36e324e1c 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,7 +1,7 @@ --- # DESCRIPTION: codecov.io config # -# Copyright 2020-2024 by Wilson Snyder. This program is free software; you +# Copyright 2020-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it 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 6d01254b4..a7e1b8976 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ # DESCRIPTION: Process this file with autoconf to produce a configure script. # -# Copyright 2003-2024 by Wilson Snyder. Verilator is free software; you +# Copyright 2003-2025 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.030 2024-10-27], +AC_INIT([Verilator],[5.032 2025-01-01], [https://verilator.org], [verilator],[https://verilator.org]) @@ -176,8 +176,10 @@ AC_PROG_CXX AC_PROG_INSTALL AC_LANG_PUSH(C++) -cxx_version=$($CXX --version | head -1) -AC_MSG_RESULT([compiler is $CXX --version = $cxx_version]) +CFG_CXX_VERSION=`$CXX --version | head -1` +AC_MSG_RESULT([compiler $CXX --version = $CFG_CXX_VERSION]) +AC_SUBST(CFG_CXX_VERSION) + AC_MSG_CHECKING([that C++ compiler can compile simple program]) AC_RUN_IFELSE( [AC_LANG_SOURCE([int main() { return 0; }])], diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index dae6f4082..fa06407a2 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -20,6 +20,7 @@ Andrei Kostovski Andrew Miloradovsky Andrew Nolte Anthony Donlon +Anthony Moore Arkadiusz Kozdra Arthur Rosa Aylon Chaim Porat @@ -65,6 +66,7 @@ Gijs Burghoorn Glen Gibb Gökçe Aydos Graham Rushton +Greg Davill Guokai Chen Gus Smith Gustav Svensk @@ -126,6 +128,7 @@ Krzysztof Bieganski Krzysztof Boronski Krzysztof Boroński Krzysztof Obłonczek +Krzysztof Starecki Kuba Ober Larry Doolittle Liam Braun @@ -194,9 +197,11 @@ Srinivasan Venkataramanan Stefan Wallentowitz Stephen Henry Steven Hugg +sumpster Szymon Gizler Sören Tempel Teng Huang +Tom Manner Tim Hutt Tim Snyder Tobias Rosenkranz diff --git a/docs/Makefile b/docs/Makefile index 78e39fae8..71b3092eb 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -5,7 +5,7 @@ # # Code available from: https://verilator.org # -# Copyright 2003-2024 by Wilson Snyder. This program is free software; you +# Copyright 2003-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it 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 75a7585bf..99caea230 100755 --- a/docs/bin/vl_sphinx_extract +++ b/docs/bin/vl_sphinx_extract @@ -37,7 +37,7 @@ parser = argparse.ArgumentParser( allow_abbrev=False, formatter_class=argparse.RawDescriptionHelpFormatter, description="""Read a file and extract documentation data.""", - epilog=""" Copyright 2021-2024 by Wilson Snyder. This package is free software; + epilog=""" Copyright 2021-2025 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 d0e607a48..185a0a55d 100755 --- a/docs/bin/vl_sphinx_fix +++ b/docs/bin/vl_sphinx_fix @@ -53,7 +53,7 @@ parser = argparse.ArgumentParser( allow_abbrev=False, formatter_class=argparse.RawDescriptionHelpFormatter, description="""Post-process Sphinx HTML.""", - epilog=""" Copyright 2021-2024 by Wilson Snyder. This package is free software; + epilog=""" Copyright 2021-2025 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 c9f86a5c1..7454f5162 100644 --- a/docs/guide/changes.rst +++ b/docs/guide/changes.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 a01718c9e..328a4e900 100644 --- a/docs/guide/conf.py +++ b/docs/guide/conf.py @@ -1,7 +1,7 @@ # pylint: disable=C0103,C0114,C0116,C0301,E0402,W0622 # # Configuration file for Verilator's Sphinx documentation builder. -# Copyright 2003-2024 by Wilson Snyder. +# Copyright 2003-2025 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 724c2938b..c0f08175d 100644 --- a/docs/guide/connecting.rst +++ b/docs/guide/connecting.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 056a3e375..051b69869 100644 --- a/docs/guide/contributing.rst +++ b/docs/guide/contributing.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 ff223257a..504ca4698 100644 --- a/docs/guide/contributors.rst +++ b/docs/guide/contributors.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 ************************ @@ -34,130 +34,140 @@ MicroTune Inc., picoChip Designs Ltd., Sun Microsystems Inc., Nauticus Networks Inc., SiCortex Inc, Shunyao CAD, and Western Digital Inc. The contributors of major functionality are: Jeremy Bennett, Krzysztof -Bieganski, Byron Bradley, Lane Brooks, John Coiner, Duane Galbi, Geza Lore, -Todd Strader, Yutetsu Takatsukasa, Stefan Wallentowitz, Paul Wasson, Jie -Xu, and Wilson Snyder. +Bieganski, Byron Bradley, Lane Brooks, John Coiner, Duane Galbi, Arkadiusz +Kozdra, Geza Lore, Todd Strader, Yutetsu Takatsukasa, Stefan Wallentowitz, +Paul Wasson, Jie Xu, and Wilson Snyder. Some of the people who have provided ideas, and feedback for Verilator include: David Addison, Tariq B. Ahmad, Nikana Anastasiadis, John David Anglin, Frederic Antonin, Hans Van Antwerpen, Vasu Arasanipalai, Jens Arm, Rohan -Arshid, Gökçe Aydos, Adam Bagley, Sharad Bagri, Robert Balas, Marco -Balboni, Matthew Ballance, Andrew Bardsley, Ilya Barkov, Matthew Barr, -Geoff Barrett, Kaleb Barrett, Daniel Bates, Julius Baxter, Michael Berman, -Jean Berniolles, Victor Besyakov, Narayan Bhagavatula, Moinak -Bhattacharyya, Kritik Bhimani, David Biancolin, David Binderman, Piotr -Binkowski, Johan Björk, David Black, Tymoteusz Blazejczyk, Scott Bleiweiss, -David van der Bokke, Daniel Bone, Guy Bonneau, Krzysztof Boroński, Gregg -Bouchard, Christopher Boumenot, Nick Bowler, Bryan Brady, Maarten De -Braekeleer, Charlie Brej, J Briquet, John Brownlee, KC Buckenmaier, Jeff -Bush, Lawrence Butcher, Tony Bybell, Iru Cai, Ted Campbell, Anthony Campos, -Chris Candler, Lauren Carlson, Gregory Carver, Donal Casey, Sebastien Van -Cauwenberghe, Alex Chadwick, Greg Chadwick, Marcel Chang, Aliaksei -Chapyzhenka, Chih-Mao Chen, Guokai Chen, Terry Chen, Yi-Chung Chen, Yurii -Cherkasov, Hennadii Chernyshchyk, Enzo Chi, Robert A. Clark, Ryan Clarke, -Allan Cochrane, Keith Colbert, Quentin Corradi, Nassim Corteggiani, +Arshid, Valentin Atepalikhin, Philip Axer, Gökçe Aydos, Chris Bachhuber, +Filip Badáň, Adam Bagley, Sharad Bagri, James Bailey, Robert Balas, Marco +Balboni, Matthew Ballance, Ricardo Barbedo, Andrew Bardsley, Ilya Barkov, +Matthew Barr, Geoff Barrett, Kaleb Barrett, Daniel Bates, Julius Baxter, +Michael Berman, Jean Berniolles, Victor Besyakov, Narayan Bhagavatula, +Moinak Bhattacharyya, Kritik Bhimani, David Biancolin, Krzysztof Bieganski, +Michael Bikovitsky, David Binderman, Piotr Binkowski, Johan Björk, David +Black, Tymoteusz Blazejczyk, Scott Bleiweiss, David van der Bokke, Daniel +Bone, Guy Bonneau, Krzysztof Boroński, Gregg Bouchard, Christopher +Boumenot, Paul Bowen-Huggett, Nick Bowler, Bryan Brady, Maarten De +Braekeleer, Liam Braun, Charlie Brej, J Briquet, John Brownlee, KC +Buckenmaier, Gijs Burghoorn, Jeff Bush, Lawrence Butcher, Tony Bybell, Iru +Cai, Ted Campbell, Anthony Campos, Chris Candler, Lauren Carlson, Gregory +Carver, Donal Casey, Sebastien Van Cauwenberghe, Alex Chadwick, Greg +Chadwick, Marcel Chang, Aliaksei Chapyzhenka, Chih-Mao Chen, Guokai Chen, +Kefa Chen, Terry Chen, Yangyu Chen, Yi-Chung Chen, Yurii Cherkasov, +Hennadii Chernyshchyk, Enzo Chi, Bartłomiej Chmiel, Robert A. Clark, Ryan +Clarke, Allan Cochrane, Keith Colbert, Quentin Corradi, Nassim Corteggiani, Gianfranco Costamagna, February Cozzocrea, Sean Cross, George Cuan, Michal Czyz, Joe DErrico, Jim Dai, Lukasz Dalek, Laurens van Dam, Gunter -Dannoritzer, Ashutosh Das, Julian Daube, Bernard Deadman, Peter Debacker, -John Demme, Mike Denio, John Deroo, Philip Derrick, Aadi Desai, John -Dickol, Ruben Diez, Danny Ding, Jacko Dirks, Ivan Djordjevic, Brad Dobbie, -Paul Donahue, Jonathon Donaldson, Anthony Donlon, Caleb Donovick, Larry -Doolittle, Leendert van Doorn, Sebastian Dressler, Jonathan Drolet, Maciej -Dudek, Alex Duller, Jeff Dutton, Tomas Dzetkulic, Usuario Eda, Charles -Eddleston, Chandan Egbert, Joe Eiler, Ahmed El-Mahmoudy, Trevor Elbourne, -Mats Engstrom, Robert Farrell, Julien Faucher, Olivier Faure, Eugen Fekete, -Fabrizio Ferrandi, Udi Finkelstein, Brian Flachs, Bill Flynn, Andrea -Foletto, Alex Forencich, Aurelien Francillon, Bob Fredieu, Manuel -Freiberger, Mostafa Gamal, Vito Gamberini, Mostafa Garnal, Benjamin -Gartner, Christian Gelinek, Richard E George, Peter Gerst, Glen Gibb, -Michael Gielda, Barbara Gigerl, Nimrod Gileadi, Shankar Giri, Dan -Gisselquist, Petr Gladkikh, Sam Gladstone, Mariusz Glebocki, Embedded Go, -Andrew Goessling, Amir Gonnen, Chitlesh Goorah, Tomasz Gorochowik, Kai -Gossner, Tarik Graba, Sergi Granell, Al Grant, Nathan Graybeal, Alexander -Grobman, Qian Gu, Xuan Guo, Prabhat Gupta, Driss Hafdi, Neil Hamilton, -James Hanlon, Tang Haojin, Øyvind Harboe, Jannis Harder, David Harris, -Junji Hashimoto, Thomas Hawkins, Mitch Hayenga, Harald Heckmann, Robert -Henry, Stephen Henry, Sebastian Hesselbarth, David Hewson, Jamey Hicks, -Joel Holdsworth, Andrew Holme, Peter Holmes, Hiroki Honda, Alex Hornung, +Dannoritzer, Ashutosh Das, Julian Daube, Greg Davill, Bernard Deadman, +Peter Debacker, Josse Van Delm, John Demme, Mike Denio, John Deroo, Philip +Derrick, Aadi Desai, John Dickol, Ruben Diez, Danny Ding, Jacko Dirks, Ivan +Djordjevic, Brad Dobbie, Paul Donahue, Jonathon Donaldson, Anthony Donlon, +Caleb Donovick, Larry Doolittle, Leendert van Doorn, Sebastian Dressler, +Jonathan Drolet, Justin Yao Du, Maciej Dudek, Alex Duller, Jeff Dutton, +Tomas Dzetkulic, Usuario Eda, Charles Eddleston, Chandan Egbert, Joe Eiler, +Ahmed El-Mahmoudy, Trevor Elbourne, Mats Engstrom, Robert Farrell, Julien +Faucher, Olivier Faure, Eugene Feinberg, Eugen Fekete, Fabrizio Ferrandi, +Udi Finkelstein, Brian Flachs, Bill Flynn, Andrea Foletto, Alex Forencich, +Aurelien Francillon, Bob Fredieu, Manuel Freiberger, Mostafa Gamal, Vito +Gamberini, Mostafa Garnal, Benjamin Gartner, Christian Gelinek, Richard E +George, Peter Gerst, Glen Gibb, Michael Gielda, Barbara Gigerl, Nimrod +Gileadi, Shankar Giri, Dan Gisselquist, Szymon Gizler, Petr Gladkikh, Sam +Gladstone, Mariusz Glebocki, Embedded Go, Andrew Goessling, Amir Gonnen, +Chitlesh Goorah, Tomasz Gorochowik, Kai Gossner, Tarik Graba, Sergi +Granell, Al Grant, Nathan Graybeal, Alexander Grobman, Qian Gu, Xuan Guo, +Prabhat Gupta, Deniz Güzel, Driss Hafdi, Abdul Hameed, Neil Hamilton, James +Hanlon, Tang Haojin, Øyvind Harboe, Jannis Harder, David Harris, Junji +Hashimoto, Thomas Hawkins, Mitch Hayenga, Harald Heckmann, Robert Henry, +Stephen Henry, Sebastian Hesselbarth, David Hewson, Jamey Hicks, Joel +Holdsworth, Andrew Holme, Peter Holmes, Hiroki Honda, Alex Hornung, Pierre-Henri Horrein, David Horton, Peter Horvath, Jae Hossell, Kuoping -Hsu, Teng Huang, Steven Hugg, Huanghuang Zhou, Alan Hunter, James -Hutchinson, Tim Hutt, Ehab Ibrahim, Edgar E. Iglesias, Shahid Ikram, Jamie -Iles, Vighnesh Iyer, Ben Jackson, Daniel Jacques, Shareef Jalloq, Marlon +Hsu, Shou-Li Hsu, Teng Huang, Steven Hugg, Alan Hunter, James Hutchinson, +Tim Hutt, Ehab Ibrahim, Edgar E. Iglesias, Shahid Ikram, Jamie Iles, Fuad +Ismail, Vighnesh Iyer, Ben Jackson, Daniel Jacques, Shareef Jalloq, Marlon James, Krzysztof Jankowski, Eyck Jentzsch, HyungKi Jeong, Iztok Jeras, -Alexandre Joannou, James Johnson, Christophe Joly, Justin Jones, -William D. Jones, Larry Darryl Lee Jr., Franck Jullien, James Jung, -Yoshitomo Kaneda, Mike Kagen, Arthur Kahlich, Kaalia Kahn, Guy-Armand -Kamendje, Vasu Kandadi, Kanad Kanhere, Patricio Kaplan, Pieter Kapsenberg, -Rafal Kapuscik, Ralf Karge, Per Karlsson, Dan Katz, Sol Katzman, Ian -Kennedy, Ami Keren, Michael Killough, Sun Kim, Jonathan Kimmitt, Olof -Kindgren, Kevin Kiningham, Cameron Kirk, Dan Kirkham, Aleksander Kiryk, -Sobhan Klnv, Gernot Koch, Jack Koenig, Soon Koh, Nathan Kohagen, Steve -Kolecki, Brett Koonce, Will Korteland, Andrei Kostovski, Wojciech Koszek, -Varun Koyyalagunta, Arkadiusz Kozdra, Markus Krause, David Kravitz, Adam -Krolnik, Roland Kruse, Mahesh Kumashikar, Andreas Kuster, Sergey Kvachonok, -Charles Eric LaForest, Kevin Laeufer, Ed Lander, Steve Lang, Pierre -Laroche, Stephane Laurent, Walter Lavino, Christian Leber, David Ledger, -Alex Lee, Larry Lee, Yoda Lee, Michaël Lefebvre, Dag Lem, Igor Lesik, John -Li, Kay Li, Zixi Li, Davide Libenzi, Nandor Licker, Eivind Liland, Ícaro -Lima, Kevin Lin, Yu-Sheng Lin, Charlie Lind, Andrew Ling, Jiuyang Liu, Joey -Liu, Paul Liu, Derek Lockhart, Jake Longo, Arthur Low, Jose Loyola, Stefan -Ludwig, Dan Lussier, Konstantin Lübeck, Fred Ma, Liwei Ma, Duraid Madina, -Oleh Maksymenko, Affe Mao, Julien Margetts, Chick Markley, Alexis Marquet, -Mark Marshall, Alfonso Martinez, Unai Martinez-Corral, Adrien Le Masle, -Yves Mathieu, Vladimir Matveyenko, Patrick Maupin, Stan Mayer, Conor -McCullough, Jason McMullan, Elliot Mednick, Yuan Mei, Andy Meier, +Pawel Jewstafjew, Alexandre Joannou, James Johnson, Christophe Joly, Justin +Jones, William D. Jones, Abe Jordan, Larry Darryl Lee Jr., Franck Jullien, +James Jung, Mike Kagen, Arthur Kahlich, Kaalia Kahn, Guy-Armand Kamendje, +Vasu Kandadi, Yoshitomo Kaneda, Kanad Kanhere, Patricio Kaplan, Pieter +Kapsenberg, Rafal Kapuscik, Ralf Karge, Per Karlsson, Dan Katz, Sol +Katzman, Ian Kennedy, Ami Keren, Fabian Keßler, Michael Killough, Sun Kim, +Jonathan Kimmitt, Olof Kindgren, Kevin Kiningham, Cameron Kirk, Dan +Kirkham, Aleksander Kiryk, Sobhan Klnv, Gernot Koch, Jack Koenig, Soon Koh, +Nathan Kohagen, Steve Kolecki, Brett Koonce, Will Korteland, Andrei +Kostovski, Wojciech Koszek, Varun Koyyalagunta, Arkadiusz Kozdra, Markus +Krause, David Kravitz, Adam Krolnik, Roland Kruse, Mahesh Kumashikar, +Andreas Kuster, Sergey Kvachonok, Charles Eric LaForest, Kevin Laeufer, Ed +Lander, Steve Lang, Pierre Laroche, Stephane Laurent, Walter Lavino, +Christian Leber, David Ledger, Alex Lee, Larry Lee, Yoda Lee, Michaël +Lefebvre, Dag Lem, Igor Lesik, John Li, Kay Li, Zixi Li, Davide Libenzi, +Nandor Licker, Eivind Liland, Ícaro Lima, Kevin Lin, Yu-Sheng Lin, Charlie +Lind, Andrew Ling, Jiuyang Liu, Joey Liu, Paul Liu, Derek Lockhart, Jake +Longo, Geza Lore, Arthur Low, Jose Loyola, Stefan Ludwig, Dan Lussier, +Konstantin Lübeck, Fred Ma, Liwei Ma, Duraid Madina, Oleh Maksymenko, Affe +Mao, Julien Margetts, Chick Markley, Alexis Marquet, Mark Marshall, Alfonso +Martinez, Unai Martinez-Corral, Adrien Le Masle, Yves Mathieu, Vladimir +Matveyenko, Patrick Maupin, Stan Mayer, Jordan McConnon, Conor McCullough, +Jason McMullan, Elliot Mednick, Yuan Mei, Andy Meier, Luiza de Melo, Rodrigo A. Melo, Benjamin Menküc, Jake Merdich, David Metz, Wim Michiels, -Miodrag Milanović, Darryl Miles, Kevin Millis, Andrew Miloradovsky, Wai Sum -Mong, Peter Monsson, Sean Moore, Stuart Morris, Dennis Muhlestein, John -Murphy, Matt Myers, Nathan Myers, Richard Myers, Alex Mykyta, Dimitris -Nalbantis, Peter Nelson, Felix Neumärker, Bob Newgard, Cong Van Nguyen, -Rachit Nigam, Toru Niina, Paul Nitza, Yossi Nivin, Pete Nixon, Lisa Noack, -Mark Nodine, Michael Nolan, Andrew Nolte, Joseph Nwabueze, Kuba Ober, -Andreas Olofsson, Baltazar Ortiz, Aleksander Osman, Don Owen, Tim Paine, -Deepa Palaniappan, James Pallister, Vassilis Papaefstathiou, Sanggyu Park, -Brad Parker, Risto Pejašinović, Morten Borup Petersen, Dan Petrisko, Wesley -Piard, Maciej Piechotka, David Pierce, Cody Piersall, T. Platz, Michael -Platzer, Dominic Plunkett, David Poole, Michael Popoloski, Roman Popov, -Aylon Chaim Porat, Oron Port, Rich Porter, Rick Porter, Stefan Post, -Niranjan Prabhu, Damien Pretet, Harald Pretl, Bill Pringlemeir, Usha -Priyadharshini, Mark Jackson Pulver, Prateek Puri, Jiacheng Qian, Marshal -Qiao, Raynard Qiao, Yujia Qiao, Jasen Qin, Frank Qiu, Nandu Raj, Kamil -Rakoczy, Danilo Ramos, Drew Ranck, Chris Randall, Anton Rapp, Josh Redford, -Odd Magne Reitan, Frédéric Requin, Dustin Richmond, Samuel Riedel, Alberto -Del Rio, Eric Rippey, Oleg Rodionov, Ludwig Rogiers, Paul Rolfe, Michail -Rontionov, Arjen Roodselaar, Tobias Rosenkranz, Yernagula Roshit, Ryszard +Miodrag Milanović, Darryl Miles, Kevin Millis, Andrew Miloradovsky, David +Moberg, Wai Sum Mong, Peter Monsson, Anthony Moore, Sean Moore, Stuart +Morris, Dennis Muhlestein, John Murphy, Matt Myers, Nathan Myers, Richard +Myers, Alex Mykyta, Eric Müller, Dimitris Nalbantis, Peter Nelson, Felix +Neumärker, Bob Newgard, Cong Van Nguyen, Rachit Nigam, Toru Niina, Paul +Nitza, Yossi Nivin, Pete Nixon, Lisa Noack, Mark Nodine, Michael Nolan, +Andrew Nolte, Joseph Nwabueze, Kevin Nygaard, Kuba Ober, Krzysztof +Obłonczek, Andreas Olofsson, Baltazar Ortiz, Aleksander Osman, Don Owen, +Tim Paine, Deepa Palaniappan, James Pallister, Vassilis Papaefstathiou, +Sanggyu Park, Brad Parker, Risto Pejašinović, Seth Pellegrino, Morten Borup +Petersen, Dan Petrisko, Wesley Piard, Maciej Piechotka, David Pierce, Cody +Piersall, T. Platz, Michael Platzer, Dominic Plunkett, Nolan Poe, David +Poole, Michael Popoloski, Roman Popov, Aylon Chaim Porat, Oron Port, Rich +Porter, Rick Porter, Stefan Post, Niranjan Prabhu, Damien Pretet, Harald +Pretl, Bill Pringlemeir, Usha Priyadharshini, Mark Jackson Pulver, Prateek +Puri, Han Qi, Jiacheng Qian, Marshal Qiao, Raynard Qiao, Yujia Qiao, Jasen +Qin, Frank Qiu, Nandu Raj, Kamil Rakoczy, Danilo Ramos, Drew Ranck, Chris +Randall, Anton Rapp, Josh Redford, Odd Magne Reitan, Frédéric Requin, +Dustin Richmond, Samuel Riedel, Alberto Del Rio, Eric Rippey, Narcis Rodas, +Oleg Rodionov, Ludwig Rogiers, Paul Rolfe, Michail Rontionov, Arjen +Roodselaar, Arthur Rosa, Tobias Rosenkranz, Yernagula Roshit, Ryszard Rozak, Huang Rui, Graham Rushton, Jan Egil Ruud, Denis Rystsov, Pawel -Sagan, Robert Sammelson, John Sanguinetti, Josep Sans, Luca Sasselli, -Martin Scharrer, Martin Schmidt, Julie Schwartz, Galen Seitz, Joseph -Shaker, Mark Shaw, Salman Sheikh, Zhou Shen, Hao Shi, James Shi, Michael -Shinkarovsky, Rafael Shirakawa, Jeffrey Short, S Shuba, Fan Shupei, Ethan -Sifferman, Anderson Ignacio da Silva, Rodney Sinclair, Ameya Vikram Singh, -Sanjay Singh, Frans Skarman, Nate Slager, Steven Slatter, Mladen -Slijepcevic, Brian Small, Garrett Smith, Gus Smith, Tim Snyder, Maciej -Sobkowski, Stan Sokorac, Alex Solomatnikov, Flavien Solt, Wei Song, Trefor -Southwell, Martin Stadler, Art Stamness, David Stanford, John Stevenson, -Pete Stevenson, Patrick Stewart, Rob Stoddard, Tood Strader, John Stroebel, -Ray Strouble, Sven Stucki, Howard Su, Emerson Suguimoto, Gene Sullivan, -Qingyao Sun, Renga Sundararajan, Kuba Sunderland-Ober, Gustav Svensk, -Rupert Swarbrick, Jevin Sweval, Shinya T-Y, Thierry Tambe, Jesse Taube, -Drew Taussig, Jose Tejada, Sören Tempel, Peter Tengstrand, Wesley Terpstra, -Rui Terra, Stefan Thiede, Justin Thiel, Gary Thomas, Ian Thompson, Kevin -Thompson, Mike Thyer, Hans Tichelaar, Tudor Timi, Viktor Tomov, Steve Tong, -Topa Topino, Àlex Torregrosa, Topa Tota, Michael Tresidder, Lenny Truong, -David Turner, Neil Turton, Hideto Ueno, Mike Urbach, Joel Vandergriendt, -Srini Vemuri, Srinivasan Venkataramanan, Yuri Victorovich, Ivan Vnučec, -Bogdan Vukobratovic, Holger Waechtler, Philipp Wagner, Johannes Walter, CY -Wang, Chuxuan Wang, Shawn Wang, Zhanglei Wang, Greg Waters, Thomas Watts, -Eugene Weber, John Wehle, Tianrui Wei, David Welch, Thomas J Whatson, -Martin Whitaker, Marco Widmer, Leon Wildman, Daniel S. Wilkerson, Daniel -Wilkerson, Gerald Williams, Trevor Williams, Don Williamson, Jan Van -Winkel, Jeff Winston, Joshua Wise, Clifford Wolf, Johan Wouters, Paul -Wright, Tobias Wölfel, Junyi Xi, Ding Xiaoliang, Liu Xiaoyi, Mandy Xu, -Shanshan Xu, Yinan Xu, SU YANG, Felix Yan, Luke Yang, Amir Yazdanbakhsh, -Chentai (Seven) Yuan, Florian Zaruba, Mat Zeno, Keyi Zhang, Xi Zhang, Yike -Zhou, Jiamin Zhu. +Sagan, Robert Sammelson, Adrian Sampson, John Sanguinetti, Josep Sans, Luca +Sasselli, Martin Scharrer, Martin Schmidt, Jonathan Schröter, Julie +Schwartz, Galen Seitz, Sam Shahrestani, Joseph Shaker, Mark Shaw, Salman +Sheikh, Zhou Shen, Hao Shi, James Shi, Michael Shinkarovsky, Rafael +Shirakawa, Jeffrey Short, S Shuba, Fan Shupei, Ethan Sifferman, Anderson +Ignacio da Silva, Rodney Sinclair, Ameya Vikram Singh, Sanjay Singh, Frans +Skarman, Nate Slager, Steven Slatter, Mladen Slijepcevic, Brian Small, +Garrett Smith, Gus Smith, Tim Snyder, Maciej Sobkowski, Stan Sokorac, Alex +Solomatnikov, Flavien Solt, Wei Song, Trefor Southwell, Martin Stadler, Art +Stamness, David Stanford, Krzysztof Starecki, Baruch Sterin, John +Stevenson, Pete Stevenson, Patrick Stewart, Rob Stoddard, Tood Strader, +John Stroebel, Ray Strouble, Sven Stucki, Howard Su, Udaya Raj Subedi, +Emerson Suguimoto, Gene Sullivan, Qingyao Sun, Renga Sundararajan, Kuba +Sunderland-Ober, Gustav Svensk, Rupert Swarbrick, Jevin Sweval, Paul +Swirhun, Shinya T-Y, Thierry Tambe, Jesse Taube, Drew Taussig, Christopher +Taylor, Greg Taylor, Jose Tejada, Sören Tempel, Peter Tengstrand, Wesley +Terpstra, Rui Terra, Stefan Thiede, Justin Thiel, Gary Thomas, Ian +Thompson, Kevin Thompson, Mike Thyer, Hans Tichelaar, Tudor Timi, Viktor +Tomov, Steve Tong, Topa Topino, Àlex Torregrosa, Topa Tota, Michael +Tresidder, Lenny Truong, David Turner, Neil Turton, Hideto Ueno, Mike +Urbach, Joel Vandergriendt, Srini Vemuri, Srinivasan Venkataramanan, Yuri +Victorovich, Ivan Vnučec, Bogdan Vukobratovic, Holger Waechtler, Philipp +Wagner, Stefan Wallentowitz, Johannes Walter, CY Wang, Chuxuan Wang, Shawn +Wang, Yilou Wang, Zhanglei Wang, Greg Waters, Thomas Watts, Eugene Weber, +John Wehle, Tianrui Wei, David Welch, Thomas J Whatson, Martin Whitaker, +Marco Widmer, Leon Wildman, Daniel S. Wilkerson, Daniel Wilkerson, Gerald +Williams, Trevor Williams, Don Williamson, Jan Van Winkel, Jeff Winston, +Joshua Wise, Clifford Wolf, Johan Wouters, Paul Wright, Tobias Wölfel, +Junyi Xi, Ding Xiaoliang, Liu Xiaoyi, Jinyan Xu, Mandy Xu, Pengcheng Xu, +Shanshan Xu, Yan Xu, Yinan Xu, SU YANG, Felix Yan, Jiaxun Yang, Luke Yang, +Amir Yazdanbakhsh, Chentai (Seven) Yuan, Florian Zaruba, Mat Zeno, Keyi +Zhang, Xi Zhang, Huanghuang Zhou, Yike Zhou, Jiamin Zhu, Ryan Ziegler. Thanks to them, and all those we've missed mentioning above, and to those whom have wished to remain anonymous. diff --git a/docs/guide/copyright.rst b/docs/guide/copyright.rst index 5eb6d516c..e83fcc1ed 100644 --- a/docs/guide/copyright.rst +++ b/docs/guide/copyright.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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-2024 by Wilson Snyder. This program is free software; you +Copyright 2003-2025 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 881583518..130197f18 100644 --- a/docs/guide/deprecations.rst +++ b/docs/guide/deprecations.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 Deprecations @@ -13,7 +13,10 @@ C++14 compiler support Verilator will require C++20 or newer compilers for both compiling Verilator and compiling all Verilated models no sooner than May 2025. + (Likely to be removed shortly after GitHub removes Ubuntu 20.04 + continuous-integration action runners, which are used to test the older + C++ standard). XML output Verilator currently supports XML parser output (enabled with `--xml-only`). - Support for `--xml-*` options will be deprecated no sooner than January 2025. + Support for `--xml-*` options will be deprecated no sooner than January 2026. diff --git a/docs/guide/environment.rst b/docs/guide/environment.rst index d099acea3..f70d35763 100644 --- a/docs/guide/environment.rst +++ b/docs/guide/environment.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 43f895b9b..3085d235d 100644 --- a/docs/guide/example_binary.rst +++ b/docs/guide/example_binary.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 11c7d706f..2173e64e1 100644 --- a/docs/guide/example_cc.rst +++ b/docs/guide/example_cc.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 d7ddb0bab..ecf9f813b 100644 --- a/docs/guide/example_common_install.rst +++ b/docs/guide/example_common_install.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 4b15464b6..cafb63c12 100644 --- a/docs/guide/example_dist.rst +++ b/docs/guide/example_dist.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 f844f4a25..c6e235785 100644 --- a/docs/guide/example_sc.rst +++ b/docs/guide/example_sc.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 c2328b8da..7c27c6d5f 100644 --- a/docs/guide/examples.rst +++ b/docs/guide/examples.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 7a449e3fb..743541794 100644 --- a/docs/guide/exe_sim.rst +++ b/docs/guide/exe_sim.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 0ffe5afb3..7afdb5df6 100644 --- a/docs/guide/exe_verilator.rst +++ b/docs/guide/exe_verilator.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 verilator Arguments @@ -589,10 +589,18 @@ Summary: .. option:: -fno-expand +.. option:: -fno-func-opt + +.. option:: -fno-func-opt-balance-cat + +.. option:: -fno-func-opt-split-cat + .. option:: -fno-gate .. option:: -fno-inline +.. option:: -fno-inline-funcs + .. option:: -fno-life .. option:: -fno-life-post @@ -609,6 +617,8 @@ Summary: .. option:: -fno-reorder +.. option:: -fno-slice + .. option:: -fno-split .. option:: -fno-subst @@ -1357,7 +1367,17 @@ Summary: .. option:: --no-std - Prevents parsing standard library. + Prevents parsing standard input files, alias for + :vlopt:`--no-std-package`, :vlopt:`--no-std-waiver`. This may be extended + to prevent reading other standardized files in future versions. + +.. option:: --no-std-package + + Prevents parsing standard `std::` package file. + +.. option:: --no-std-waiver + + Prevents parsing standard lint waivers (`verilated_std_waiver.vlt`). .. option:: --no-stop-fail @@ -1637,6 +1657,15 @@ Summary: Enable the use of VPI and linking against the :file:`verilated_vpi.cpp` files. +.. option:: --waiver-multiline + + When using :vlopt:`--waiver-output \ <--waiver-output>`, + include a match expression that includes the entire multiline error + message as a match regular expression, as opposed to the default of only + matching the first line of the error message. This provides a starting + point for creating complex waivers, but such generated waivers will + likely require editing for brevity before being reused. + .. option:: --waiver-output Generate a waiver file that contains all waiver statements to suppress @@ -1741,18 +1770,19 @@ Summary: ``-Wwarn-CASEX`` ``-Wwarn-CASTCONST`` ``-Wwarn-CMPCONST`` ``-Wwarn-COLONPLUS`` ``-Wwarn-IMPLICIT`` ``-Wwarn-IMPLICITSTATIC`` ``-Wwarn-LATCH`` ``-Wwarn-MISINDENT`` ``-Wwarn-NEWERSTD`` - ``-Wwarn-PINMISSING`` ``-Wwarn-REALCVT`` ``-Wwarn-STATICVAR`` - ``-Wwarn-UNSIGNED`` ``-Wwarn-WIDTHTRUNC`` ``-Wwarn-WIDTHEXPAND`` - ``-Wwarn-WIDTHXZEXPAND``. + ``-Wwarn-PREPROCZERO`` ``-Wwarn-PINMISSING`` ``-Wwarn-REALCVT`` + ``-Wwarn-STATICVAR`` ``-Wwarn-UNSIGNED`` ``-Wwarn-WIDTHTRUNC`` + ``-Wwarn-WIDTHEXPAND`` ``-Wwarn-WIDTHXZEXPAND``. .. option:: -Wwarn-style Enable all code style-related warning messages. This is equivalent to - ``-Wwarn-ASSIGNDLY`` ``-Wwarn-DECLFILENAME`` ``-Wwarn-DEFPARAM`` - ``-Wwarn-EOFNEWLINE`` ``-Wwarn-GENUNNAMED`` ``-Wwarn-INCABSPATH`` + ``-Wwarn-ASSIGNDLY`` ``-Wwarn-BLKSEQ`` ``-Wwarn-DECLFILENAME`` + ``-Wwarn-DEFPARAM`` ``-Wwarn-EOFNEWLINE`` ``-Wwarn-GENUNNAMED`` + ``-Wwarn-IMPORTSTAR`` ``-Wwarn-INCABSPATH`` ``-Wwarn-PINCONNECTEMPTY`` ``-Wwarn-PINNOCONNECT`` ``-Wwarn-SYNCASYNCNET`` ``-Wwarn-UNDRIVEN`` - ``-Wwarn-UNUSEDGENVAR`` ``-Wwarn-UNUSEDPARAM`` ``-Wwarn-UNUSEDSIGNAL`` - ``-Wwarn-VARHIDDEN``. + ``-Wwarn-UNUSEDGENVAR`` ``-Wwarn-UNUSEDLOOP`` ``-Wwarn-UNUSEDPARAM`` + ``-Wwarn-UNUSEDSIGNAL`` ``-Wwarn-VARHIDDEN``. .. option:: --x-assign 0 @@ -2067,7 +2097,7 @@ The grammar of configuration commands is as follows: .. option:: lint_off [-rule ] [-file "" [-lines [ - ]]] -.. option:: lint_off [-rule ] [-file ""] [-match ""] +.. option:: lint_off [-rule ] [-file ""] [-contents ""] [-match ""] Enable/disables the specified lint warning, in the specified filename (or wildcard with '\*' or '?', or all files if omitted) and range of @@ -2076,17 +2106,28 @@ The grammar of configuration commands is as follows: With lint_off using "\*" will override any lint_on directives in the source, i.e. the warning will still not be printed. - If the -rule is omitted, all lint warnings (see list in + If the :code:`-rule` is omitted, all lint warnings (see list in :vlopt:`-Wno-lint`) are enabled/disabled. This will override all later lint warning enables for the specified region. - If -match is set, the linter warnings are matched against this - (wildcard) string and are waived in case they match, provided with the - rule and file also match. + If :code:`-contents` is provided, the input files must contain the given + wildcard (with '\*' or '?'), and are waived in case they match, provided + the :code:`-rule`, :code:`-file`, and :code:`-contents` also match. The + wildcard should be designed to match a single line; it is unspecified if + the wildcard is allowed to match across multiple lines. The input + contents does not include :vlopt:`--std <--no-std>` standard files, nor + configuration files (with :code:`verilator_config`). Typical use for + this is to match a version number present in the Verilog sources, so + that the waiver will only apply to that version of the sources. - In previous versions -rule was named -msg. The latter is deprecated, but - still works with a deprecation info; it may be removed in future - versions. + If :code:`-match` is provided, the linter warnings are matched against + the given wildcard (with '\*' or '?'), and are waived in case they + match, provided the :code:`-rule`, :code:`-file`, and :code:`-contents` + also match. The wildcard is compared across the entire multi-line + message; see :vlopt:`--waiver-multiline`. + + Before version 4.026, :code:`-rule` was named :code:`-msg`, and + :code:`-msg` remained a deprecated alias until Version 5.000. .. option:: public [-module ""] [-task/-function ""] -var "" diff --git a/docs/guide/exe_verilator_coverage.rst b/docs/guide/exe_verilator_coverage.rst index ddfd8aa93..c29f9d329 100644 --- a/docs/guide/exe_verilator_coverage.rst +++ b/docs/guide/exe_verilator_coverage.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 verilator_coverage @@ -35,11 +35,11 @@ verilator_coverage Example Usage verilator_coverage --help verilator_coverage --version - verilator_coverage --annotate + verilator_coverage --annotate obj_dir coverage.dat - verilator_coverage -write merged.dat ... + verilator_coverage --write merged.dat coverage.dat ... - verilator_coverage -write-info merged.info ... + verilator_coverage --write-info merged.info coverage.dat ... verilator_coverage Arguments diff --git a/docs/guide/exe_verilator_gantt.rst b/docs/guide/exe_verilator_gantt.rst index 6088154b2..9916b0a87 100644 --- a/docs/guide/exe_verilator_gantt.rst +++ b/docs/guide/exe_verilator_gantt.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 verilator_gantt @@ -62,6 +62,17 @@ predicted_thread#_mtask executing. +verilator_gantt Example Usage +----------------------------- + +.. + + verilator_gantt --help + verilator_gantt --version + + verilator_gantt profile_exec.dat + + verilator_gantt Arguments ------------------------- diff --git a/docs/guide/exe_verilator_profcfunc.rst b/docs/guide/exe_verilator_profcfunc.rst index 815109dab..8fb7fba33 100644 --- a/docs/guide/exe_verilator_profcfunc.rst +++ b/docs/guide/exe_verilator_profcfunc.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 verilator_profcfunc @@ -15,6 +15,17 @@ reported as a rounding error. For an overview of the use of verilator_profcfunc, see :ref:`Profiling`. +verilator_profcfunc Example Usage +--------------------------------- + +.. + + verilator_profcfunc --help + verilator_profcfunc --version + + verilator_profcfunc gprof.out + + verilator_profcfunc Arguments ----------------------------- diff --git a/docs/guide/executables.rst b/docs/guide/executables.rst index fee757f8a..229798083 100644 --- a/docs/guide/executables.rst +++ b/docs/guide/executables.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 557ddc015..292534f61 100644 --- a/docs/guide/extensions.rst +++ b/docs/guide/extensions.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 12aa3eb9a..10a5cbde7 100644 --- a/docs/guide/faq.rst +++ b/docs/guide/faq.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 a932eb7f1..9eab365b8 100644 --- a/docs/guide/files.rst +++ b/docs/guide/files.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 7d6a3f1c8..54603d249 100644 --- a/docs/guide/index.rst +++ b/docs/guide/index.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 ###################### diff --git a/docs/guide/install-cmake.rst b/docs/guide/install-cmake.rst index 2120ee951..f096d769b 100644 --- a/docs/guide/install-cmake.rst +++ b/docs/guide/install-cmake.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 .. _CMakeInstallation: diff --git a/docs/guide/install.rst b/docs/guide/install.rst index 05a58d244..c0f180d09 100644 --- a/docs/guide/install.rst +++ b/docs/guide/install.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 .. _Installation: diff --git a/docs/guide/languages.rst b/docs/guide/languages.rst index 9f32a8a03..969d1986c 100644 --- a/docs/guide/languages.rst +++ b/docs/guide/languages.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 *************** diff --git a/docs/guide/overview.rst b/docs/guide/overview.rst index 95cf9cb17..d907ad626 100644 --- a/docs/guide/overview.rst +++ b/docs/guide/overview.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 f62bada5c..1048199b4 100644 --- a/docs/guide/simulating.rst +++ b/docs/guide/simulating.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 .. _Simulating: @@ -224,14 +224,6 @@ at branches). At each such branch, a counter is incremented. At the end of a test, the counters, filename, and line number corresponding to each counter are written into the coverage file. -Verilator automatically disables coverage of branches with a $stop in -them, as it is assumed that $stop branches contain an error check that should -not occur. A :option:`/*verilator&32;coverage_block_off*/` metacomment -will perform a similar function on any code in that block or below, or -:option:`/*verilator&32;coverage_off*/` and -:option:`/*verilator&32;coverage_on*/` will disable and enable coverage -respectively around a block of code. - Verilator may over-count combinatorial (non-clocked) blocks when those blocks receive signals which have had the :option:`UNOPTFLAT` warning disabled; for the most accurate results, do not disable this warning when @@ -278,6 +270,22 @@ A :option:`/*verilator&32;coverage_off*/` signals that do not need toggle analysis, such as RAMs and register files. +.. _Suppressing Coverage: + +Suppressing Coverage +-------------------- + +Using :option:`/*verilator&32;coverage_off*/` and +:option:`/*verilator&32;coverage_on*/` around a block of code will disable +and enable coverage respectively around that block. Or, use the +:option:`coverage_block_off` configuration file option. + +Verilator automatically disables coverage of lines and branches with a +$stop in them, as it is assumed that $stop branches contain an error check +that should not occur. A :option:`/*verilator&32;coverage_block_off*/` +metacomment will perform a similar function on any code in that block or +below. + .. _Coverage Collection: Coverage Collection diff --git a/docs/guide/verilating.rst b/docs/guide/verilating.rst index 5abc3a0aa..497abf025 100644 --- a/docs/guide/verilating.rst +++ b/docs/guide/verilating.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 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 d86bbc0f8..bd8fb5b40 100644 --- a/docs/guide/warnings.rst +++ b/docs/guide/warnings.rst @@ -1,4 +1,4 @@ -.. Copyright 2003-2024 by Wilson Snyder. +.. Copyright 2003-2025 by Wilson Snyder. .. SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 ******************* @@ -1692,6 +1692,9 @@ List Of Warnings Warning that a symbol matches a C++ reserved word, and using this as a symbol name would result in odd C++ compiler errors. You may disable this warning, but Verilator will rename the symbol to avoid conflict. + If you are using `--vpi` and only mark things as public for VPI access + (and not C++ access) then it is advisable to disable this warning with + :code:`-Wno-SYMRSVDWORD`. .. option:: SYNCASYNCNET diff --git a/docs/internals.rst b/docs/internals.rst index 0bea6adc7..bbc62adcb 100644 --- a/docs/internals.rst +++ b/docs/internals.rst @@ -1656,7 +1656,7 @@ field in the section below. +---------------+--------------------------------------------------------+ | ``1:2:`` | The hierarchy of the ``VAR`` is the ``op2p`` | | | pointer under the ``MODULE``, which in turn is the | -| | ``op1p`` pointer under the ``NETLIST`` | +| | ``op1p`` pointer under the ``NETLIST``. | +---------------+--------------------------------------------------------+ | ``VAR`` | The AstNodeType (e.g. ``AstVar``). | +---------------+--------------------------------------------------------+ @@ -1670,7 +1670,7 @@ field in the section below. | | and "aa" the 27th. Then line 22 in that file, then | | | column 8 (aa=0, az=25, ba=26, ...). | +---------------+--------------------------------------------------------+ -| ``@dt=0x...`` | The address of the data type this node contains. | +| ``@dt=0x...`` | The address of the data type this node references. | +---------------+--------------------------------------------------------+ | ``w32`` | The data-type width() is 32 bits. | +---------------+--------------------------------------------------------+ @@ -1678,7 +1678,7 @@ field in the section below. | | variable. | +---------------+--------------------------------------------------------+ | ``[O]`` | Flags which vary with the type of node, in this | -| | case, it means the variable is an output. | +| | case of a VAR, it means the variable is an output. | +---------------+--------------------------------------------------------+ In more detail, the following fields are dumped common to all nodes. They @@ -2411,7 +2411,7 @@ xsim_flags / xsim_flags2 / xsim_run_flags Distribution ============ -Copyright 2008-2024 by Wilson Snyder. Verilator is free software; you can +Copyright 2008-2025 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. diff --git a/docs/spelling.txt b/docs/spelling.txt index 76b0bec90..9270968b7 100644 --- a/docs/spelling.txt +++ b/docs/spelling.txt @@ -294,6 +294,7 @@ NaN Nalbantis Nandor Narayan +Narcis Nassim Nauticus Newgard @@ -343,6 +344,7 @@ Redhat Reitan Renga Requin +Rodas Rodionov Rohan Rolfe @@ -693,6 +695,7 @@ fno fopen forceable foreach +fourstate fprintf fprofile fread diff --git a/docs/xml.rst b/docs/xml.rst index 76c358edf..61390030b 100644 --- a/docs/xml.rst +++ b/docs/xml.rst @@ -70,7 +70,7 @@ The XML document consists of 4 sections within the top level Distribution ============ -Copyright 2020-2024 by Wilson Snyder. Verilator is free software; you can +Copyright 2020-2025 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. diff --git a/include/gtkwave/fstapi.c b/include/gtkwave/fstapi.c index 70f1bb171..ed818bfb8 100644 --- a/include/gtkwave/fstapi.c +++ b/include/gtkwave/fstapi.c @@ -3907,16 +3907,18 @@ while (value) static int fstVcdIDForFwrite(char *buf, unsigned int value) { char *pnt = buf; + int len = 0; /* zero is illegal for a value...it is assumed they start at one */ -while (value) +while (value && len <= 14) { value--; + ++len; *(pnt++) = (char)('!' + value % 94); value = value / 94; } -return(pnt - buf); +return len; } diff --git a/include/verilated.cpp b/include/verilated.cpp index 9bb99166c..15f3b10a9 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -2650,7 +2650,7 @@ const char* VerilatedContext::timeprecisionString() const VL_MT_SAFE { } void VerilatedContext::threads(unsigned n) { - if (n == 0) VL_FATAL_MT(__FILE__, __LINE__, "", "%Error: Simulation threads must be >= 1"); + if (n == 0) VL_FATAL_MT(__FILE__, __LINE__, "", "Simulation threads must be >= 1"); if (m_threadPool) { VL_FATAL_MT( @@ -3326,7 +3326,7 @@ VerilatedScope::~VerilatedScope() { } void VerilatedScope::configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp, - const char* identifier, int8_t timeunit, + const char* identifier, const char* defnamep, int8_t timeunit, const Type& type) VL_MT_UNSAFE { // Slowpath - called once/scope at construction // We don't want the space and reference-count access overhead of strings. @@ -3343,6 +3343,7 @@ void VerilatedScope::configure(VerilatedSyms* symsp, const char* prefixp, const m_namep = namep; } m_identifierp = identifier; + m_defnamep = defnamep; Verilated::threadContextp()->impp()->scopeInsert(this); } diff --git a/include/verilated.h b/include/verilated.h index 65ff30c95..cee813c31 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/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,7 +100,7 @@ class VerilatedFstC; class VerilatedFstSc; class VerilatedScope; class VerilatedScopeNameMap; -template +template class VerilatedTrace; class VerilatedTraceBaseC; class VerilatedTraceConfig; @@ -300,7 +300,7 @@ public: private: // The following are for use by Verilator internals only - template + template friend class VerilatedTrace; // Run-time trace configuration requested by this model virtual std::unique_ptr traceConfig() const; @@ -546,9 +546,9 @@ public: /// 1 = Set all bits to one /// 2 = Randomize all bits void randReset(int val) VL_MT_SAFE; - /// Set default random seed, 0 = seed it automatically - int randSeed() const VL_MT_SAFE { return m_s.m_randSeed; } /// Return default random seed + int randSeed() const VL_MT_SAFE { return m_s.m_randSeed; } + /// Set default random seed, 0 = seed it automatically void randSeed(int val) VL_MT_SAFE; /// Return statistic: CPU time delta from model created until now @@ -714,6 +714,7 @@ private: VerilatedVarNameMap* m_varsp = nullptr; // Variable map const char* m_namep = nullptr; // Scope name (Slowpath) const char* m_identifierp = nullptr; // Identifier of scope (with escapes removed) + const char* m_defnamep = nullptr; // Definition name (SCOPE_MODULE only) int8_t m_timeunit = 0; // Timeunit in negative power-of-10 Type m_type = SCOPE_OTHER; // Type of the scope @@ -721,13 +722,15 @@ public: // But internals only - called from VerilatedModule's VerilatedScope() = default; ~VerilatedScope(); void configure(VerilatedSyms* symsp, const char* prefixp, const char* suffixp, - const char* identifier, int8_t timeunit, const Type& type) VL_MT_UNSAFE; + const char* identifier, const char* defnamep, int8_t timeunit, + const Type& type) VL_MT_UNSAFE; void exportInsert(int finalize, const char* namep, void* cb) VL_MT_UNSAFE; void varInsert(int finalize, const char* namep, void* datap, bool isParam, VerilatedVarType vltype, int vlflags, int dims, ...) VL_MT_UNSAFE; // ACCESSORS const char* name() const VL_MT_SAFE_POSTINIT { return m_namep; } const char* identifier() const VL_MT_SAFE_POSTINIT { return m_identifierp; } + const char* defname() const VL_MT_SAFE_POSTINIT { return m_defnamep; } int8_t timeunit() const VL_MT_SAFE_POSTINIT { return m_timeunit; } VerilatedSyms* symsp() const VL_MT_SAFE_POSTINIT { return m_symsp; } VerilatedVar* varFind(const char* namep) const VL_MT_SAFE_POSTINIT; diff --git a/include/verilated.mk.in b/include/verilated.mk.in index a38afe987..10bf9f100 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-2024 by Wilson Snyder. This program is free software; you +# Copyright 2003-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. @@ -23,6 +23,12 @@ PYTHON3 = @PYTHON3@ CFG_WITH_CCWARN = @CFG_WITH_CCWARN@ CFG_WITH_LONGTESTS = @CFG_WITH_LONGTESTS@ +# Compiler version found during configure. This make variable is not used +# here, but note that if this differs from what `$(CXX) --version` prints, +# then there may be strange results such as unexpected warnings, as +# configure determines compiler characteristics. +CFG_CXX_VERSION = "@CFG_CXX_VERSION@" + # Compiler flags to enable profiling CFG_CXXFLAGS_PROFILE = @CFG_CXXFLAGS_PROFILE@ # Select language required to compile (often empty) diff --git a/include/verilated.v b/include/verilated.v index dcdb10ccd..14cf02559 100644 --- a/include/verilated.v +++ b/include/verilated.v @@ -2,7 +2,7 @@ // // Code available from: https://verilator.org // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -12,11 +12,11 @@ // // DESCRIPTION: Verilator: Include in verilog files to hide verilator defines -`ifdef _VERILATED_V_ `else +`ifndef _VERILATED_V_ `define _VERILATED_V_ 1 // Hide verilator pragmas from other tools - `ifdef VERILATOR `else + `ifndef VERILATOR `define coverage_block_off `endif diff --git a/include/verilated_config.h.in b/include/verilated_config.h.in index 352dc057c..7e82b6b1f 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-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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 3491aa376..bf3153d72 100644 --- a/include/verilated_cov.cpp +++ b/include/verilated_cov.cpp @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2001-2024 by Wilson Snyder. This program is free software; you +// Copyright 2001-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -71,7 +71,7 @@ public: // But only local to this file // This isn't in the header file for auto-magic conversion because it // inlines to too much code and makes compilation too slow. -template +template class VerilatedCoverItemSpec final : public VerilatedCovImpItem { private: // MEMBERS @@ -233,7 +233,7 @@ private: // Little selftest #define SELF_CHECK(got, exp) \ do { \ - if ((got) != (exp)) VL_FATAL_MT(__FILE__, __LINE__, "", "%Error: selftest"); \ + if ((got) != (exp)) VL_FATAL_MT(__FILE__, __LINE__, "", "selftest"); \ } while (0) SELF_CHECK(combineHier("a.b.c", "a.b.c"), "a.b.c"); SELF_CHECK(combineHier("a.b.c", "a.b"), "a.b*"); diff --git a/include/verilated_cov.h b/include/verilated_cov.h index d27b648af..0d27f76ac 100644 --- a/include/verilated_cov.h +++ b/include/verilated_cov.h @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2001-2024 by Wilson Snyder. This program is free software; you +// Copyright 2001-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 7f956c145..f3703838d 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-2024 by Wilson Snyder. This program is free software; you +// Copyright 2001-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 76be56b5e..04a926646 100644 --- a/include/verilated_dpi.cpp +++ b/include/verilated_dpi.cpp @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2009-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2009-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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 56e9e7fd3..cb932510b 100644 --- a/include/verilated_dpi.h +++ b/include/verilated_dpi.h @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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 348ffa001..19f29f7b5 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-2024 by Wilson Snyder. This program is free software; you +// Copyright 2001-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.h b/include/verilated_fst_c.h index 891bf0fc2..8506d3886 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-2024 by Wilson Snyder. This program is free software; you +// Copyright 2001-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 5d375e5c8..3ba722492 100644 --- a/include/verilated_fst_sc.cpp +++ b/include/verilated_fst_sc.cpp @@ -3,7 +3,7 @@ // // THIS MODULE IS PUBLICLY LICENSED // -// Copyright 2001-2024 by Wilson Snyder. This program is free software; you +// Copyright 2001-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 4cda7e548..fb8f008af 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-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2001-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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 eea56ac26..3e3b6af9a 100644 --- a/include/verilated_funcs.h +++ b/include/verilated_funcs.h @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -1604,26 +1604,26 @@ static inline IData VL_PACK_II(int obits, int lbits, const VlQueue& q) { return ret; } -template -static inline IData VL_PACK_II(int obits, int lbits, const VlUnpacked& q) { +template +static inline IData VL_PACK_II(int obits, int lbits, const VlUnpacked& q) { IData ret = 0; - for (size_t i = 0; i < T_Depth; ++i) - ret |= static_cast(q[T_Depth - 1 - i]) << (i * lbits); + for (size_t i = 0; i < N_Depth; ++i) + ret |= static_cast(q[N_Depth - 1 - i]) << (i * lbits); return ret; } -template -static inline IData VL_PACK_II(int obits, int lbits, const VlUnpacked& q) { +template +static inline IData VL_PACK_II(int obits, int lbits, const VlUnpacked& q) { IData ret = 0; - for (size_t i = 0; i < T_Depth; ++i) - ret |= static_cast(q[T_Depth - 1 - i]) << (i * lbits); + for (size_t i = 0; i < N_Depth; ++i) + ret |= static_cast(q[N_Depth - 1 - i]) << (i * lbits); return ret; } -template -static inline IData VL_PACK_II(int obits, int lbits, const VlUnpacked& q) { +template +static inline IData VL_PACK_II(int obits, int lbits, const VlUnpacked& q) { IData ret = 0; - for (size_t i = 0; i < T_Depth; ++i) ret |= q[T_Depth - 1 - i] << (i * lbits); + for (size_t i = 0; i < N_Depth; ++i) ret |= q[N_Depth - 1 - i] << (i * lbits); return ret; } @@ -1645,27 +1645,27 @@ static inline QData VL_PACK_QI(int obits, int lbits, const VlQueue& q) { return ret; } -template -static inline QData VL_PACK_QI(int obits, int lbits, const VlUnpacked& q) { +template +static inline QData VL_PACK_QI(int obits, int lbits, const VlUnpacked& q) { QData ret = 0; - for (size_t i = 0; i < T_Depth; ++i) - ret |= static_cast(q[T_Depth - 1 - i]) << (i * lbits); + for (size_t i = 0; i < N_Depth; ++i) + ret |= static_cast(q[N_Depth - 1 - i]) << (i * lbits); return ret; } -template -static inline QData VL_PACK_QI(int obits, int lbits, const VlUnpacked& q) { +template +static inline QData VL_PACK_QI(int obits, int lbits, const VlUnpacked& q) { QData ret = 0; - for (size_t i = 0; i < T_Depth; ++i) - ret |= static_cast(q[T_Depth - 1 - i]) << (i * lbits); + for (size_t i = 0; i < N_Depth; ++i) + ret |= static_cast(q[N_Depth - 1 - i]) << (i * lbits); return ret; } -template -static inline QData VL_PACK_QI(int obits, int lbits, const VlUnpacked& q) { +template +static inline QData VL_PACK_QI(int obits, int lbits, const VlUnpacked& q) { QData ret = 0; - for (size_t i = 0; i < T_Depth; ++i) - ret |= static_cast(q[T_Depth - 1 - i]) << (i * lbits); + for (size_t i = 0; i < N_Depth; ++i) + ret |= static_cast(q[N_Depth - 1 - i]) << (i * lbits); return ret; } @@ -1675,10 +1675,10 @@ static inline QData VL_PACK_QQ(int obits, int lbits, const VlQueue& q) { return ret; } -template -static inline QData VL_PACK_QQ(int obits, int lbits, const VlUnpacked& q) { +template +static inline QData VL_PACK_QQ(int obits, int lbits, const VlUnpacked& q) { QData ret = 0; - for (size_t i = 0; i < T_Depth; ++i) ret |= q[T_Depth - 1 - i] << (i * lbits); + for (size_t i = 0; i < N_Depth; ++i) ret |= q[N_Depth - 1 - i] << (i * lbits); return ret; } @@ -1703,30 +1703,30 @@ static inline WDataOutP VL_PACK_WI(int obits, int lbits, WDataOutP owp, const Vl return owp; } -template +template static inline WDataOutP VL_PACK_WI(int obits, int lbits, WDataOutP owp, - const VlUnpacked& q) { + const VlUnpacked& q) { VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1); - for (size_t i = 0; i < T_Depth; ++i) - _vl_insert_WI(owp, q[T_Depth - 1 - i], i * lbits + lbits - 1, i * lbits); + for (size_t i = 0; i < N_Depth; ++i) + _vl_insert_WI(owp, q[N_Depth - 1 - i], i * lbits + lbits - 1, i * lbits); return owp; } -template +template static inline WDataOutP VL_PACK_WI(int obits, int lbits, WDataOutP owp, - const VlUnpacked& q) { + const VlUnpacked& q) { VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1); - for (size_t i = 0; i < T_Depth; ++i) - _vl_insert_WI(owp, q[T_Depth - 1 - i], i * lbits + lbits - 1, i * lbits); + for (size_t i = 0; i < N_Depth; ++i) + _vl_insert_WI(owp, q[N_Depth - 1 - i], i * lbits + lbits - 1, i * lbits); return owp; } -template +template static inline WDataOutP VL_PACK_WI(int obits, int lbits, WDataOutP owp, - const VlUnpacked& q) { + const VlUnpacked& q) { VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1); - for (size_t i = 0; i < T_Depth; ++i) - _vl_insert_WI(owp, q[T_Depth - 1 - i], i * lbits + lbits - 1, i * lbits); + for (size_t i = 0; i < N_Depth; ++i) + _vl_insert_WI(owp, q[N_Depth - 1 - i], i * lbits + lbits - 1, i * lbits); return owp; } @@ -1737,30 +1737,30 @@ static inline WDataOutP VL_PACK_WQ(int obits, int lbits, WDataOutP owp, const Vl return owp; } -template +template static inline WDataOutP VL_PACK_WQ(int obits, int lbits, WDataOutP owp, - const VlUnpacked& q) { + const VlUnpacked& q) { VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1); - for (size_t i = 0; i < T_Depth; ++i) - _vl_insert_WQ(owp, q[T_Depth - 1 - i], i * lbits + lbits - 1, i * lbits); + for (size_t i = 0; i < N_Depth; ++i) + _vl_insert_WQ(owp, q[N_Depth - 1 - i], i * lbits + lbits - 1, i * lbits); return owp; } -template +template static inline WDataOutP VL_PACK_WW(int obits, int lbits, WDataOutP owp, - const VlQueue>& q) { + const VlQueue>& q) { VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1); for (size_t i = 0; i < q.size(); ++i) _vl_insert_WW(owp, q.at(i), i * lbits + lbits - 1, i * lbits); return owp; } -template +template static inline WDataOutP VL_PACK_WW(int obits, int lbits, WDataOutP owp, - const VlUnpacked, T_Depth>& q) { + const VlUnpacked, N_Depth>& q) { VL_MEMSET_ZERO_W(owp + 1, VL_WORDS_I(obits) - 1); - for (size_t i = 0; i < T_Depth; ++i) - _vl_insert_WW(owp, q[T_Depth - 1 - i], i * lbits + lbits - 1, i * lbits); + for (size_t i = 0; i < N_Depth; ++i) + _vl_insert_WW(owp, q[N_Depth - 1 - i], i * lbits + lbits - 1, i * lbits); return owp; } @@ -2288,8 +2288,8 @@ static inline void VL_UNPACK_QW(int lbits, int rbits, VlQueue& q, WDataIn } } -template -static inline void VL_UNPACK_WW(int lbits, int rbits, VlQueue>& q, WDataInP rwp) { +template +static inline void VL_UNPACK_WW(int lbits, int rbits, VlQueue>& q, WDataInP rwp) { const int size = (rbits + lbits - 1) / lbits; q.renew(size); for (size_t i = 0; i < size; ++i) { @@ -2297,85 +2297,85 @@ static inline void VL_UNPACK_WW(int lbits, int rbits, VlQueue>& q, WDa } } -template -static inline void VL_UNPACK_II(int lbits, int rbits, VlUnpacked& q, IData from) { +template +static inline void VL_UNPACK_II(int lbits, int rbits, VlUnpacked& q, IData from) { const IData mask = VL_MASK_I(lbits); - for (size_t i = 0; i < T_Depth; ++i) q[i] = (from >> ((T_Depth - 1 - i) * lbits)) & mask; + for (size_t i = 0; i < N_Depth; ++i) q[i] = (from >> ((N_Depth - 1 - i) * lbits)) & mask; } -template -static inline void VL_UNPACK_II(int lbits, int rbits, VlUnpacked& q, IData from) { +template +static inline void VL_UNPACK_II(int lbits, int rbits, VlUnpacked& q, IData from) { const IData mask = VL_MASK_I(lbits); - for (size_t i = 0; i < T_Depth; ++i) q[i] = (from >> ((T_Depth - 1 - i) * lbits)) & mask; + for (size_t i = 0; i < N_Depth; ++i) q[i] = (from >> ((N_Depth - 1 - i) * lbits)) & mask; } -template -static inline void VL_UNPACK_II(int lbits, int rbits, VlUnpacked& q, IData from) { +template +static inline void VL_UNPACK_II(int lbits, int rbits, VlUnpacked& q, IData from) { const IData mask = VL_MASK_I(lbits); - for (size_t i = 0; i < T_Depth; ++i) q[i] = (from >> ((T_Depth - 1 - i) * lbits)) & mask; + for (size_t i = 0; i < N_Depth; ++i) q[i] = (from >> ((N_Depth - 1 - i) * lbits)) & mask; } -template -static inline void VL_UNPACK_IQ(int lbits, int rbits, VlUnpacked& q, QData from) { +template +static inline void VL_UNPACK_IQ(int lbits, int rbits, VlUnpacked& q, QData from) { const IData mask = VL_MASK_I(lbits); - for (size_t i = 0; i < T_Depth; ++i) q[i] = (from >> ((T_Depth - 1 - i) * lbits)) & mask; + for (size_t i = 0; i < N_Depth; ++i) q[i] = (from >> ((N_Depth - 1 - i) * lbits)) & mask; } -template -static inline void VL_UNPACK_IQ(int lbits, int rbits, VlUnpacked& q, QData from) { +template +static inline void VL_UNPACK_IQ(int lbits, int rbits, VlUnpacked& q, QData from) { const IData mask = VL_MASK_I(lbits); - for (size_t i = 0; i < T_Depth; ++i) q[i] = (from >> ((T_Depth - 1 - i) * lbits)) & mask; + for (size_t i = 0; i < N_Depth; ++i) q[i] = (from >> ((N_Depth - 1 - i) * lbits)) & mask; } -template -static inline void VL_UNPACK_IQ(int lbits, int rbits, VlUnpacked& q, QData from) { +template +static inline void VL_UNPACK_IQ(int lbits, int rbits, VlUnpacked& q, QData from) { const IData mask = VL_MASK_I(lbits); - for (size_t i = 0; i < T_Depth; ++i) q[i] = (from >> ((T_Depth - 1 - i) * lbits)) & mask; + for (size_t i = 0; i < N_Depth; ++i) q[i] = (from >> ((N_Depth - 1 - i) * lbits)) & mask; } -template -static inline void VL_UNPACK_QQ(int lbits, int rbits, VlUnpacked& q, QData from) { +template +static inline void VL_UNPACK_QQ(int lbits, int rbits, VlUnpacked& q, QData from) { const QData mask = VL_MASK_Q(lbits); - for (size_t i = 0; i < T_Depth; ++i) q[i] = (from >> ((T_Depth - 1 - i) * lbits)) & mask; + for (size_t i = 0; i < N_Depth; ++i) q[i] = (from >> ((N_Depth - 1 - i) * lbits)) & mask; } -template -static inline void VL_UNPACK_IW(int lbits, int rbits, VlUnpacked& q, +template +static inline void VL_UNPACK_IW(int lbits, int rbits, VlUnpacked& q, WDataInP rwp) { const IData mask = VL_MASK_I(lbits); - for (size_t i = 0; i < T_Depth; ++i) - q[i] = VL_SEL_IWII(rbits, rwp, (T_Depth - 1 - i) * lbits, lbits) & mask; + for (size_t i = 0; i < N_Depth; ++i) + q[i] = VL_SEL_IWII(rbits, rwp, (N_Depth - 1 - i) * lbits, lbits) & mask; } -template -static inline void VL_UNPACK_IW(int lbits, int rbits, VlUnpacked& q, +template +static inline void VL_UNPACK_IW(int lbits, int rbits, VlUnpacked& q, WDataInP rwp) { const IData mask = VL_MASK_I(lbits); - for (size_t i = 0; i < T_Depth; ++i) - q[i] = VL_SEL_IWII(rbits, rwp, (T_Depth - 1 - i) * lbits, lbits) & mask; + for (size_t i = 0; i < N_Depth; ++i) + q[i] = VL_SEL_IWII(rbits, rwp, (N_Depth - 1 - i) * lbits, lbits) & mask; } -template -static inline void VL_UNPACK_IW(int lbits, int rbits, VlUnpacked& q, +template +static inline void VL_UNPACK_IW(int lbits, int rbits, VlUnpacked& q, WDataInP rwp) { const IData mask = VL_MASK_I(lbits); - for (size_t i = 0; i < T_Depth; ++i) - q[i] = VL_SEL_IWII(rbits, rwp, (T_Depth - 1 - i) * lbits, lbits) & mask; + for (size_t i = 0; i < N_Depth; ++i) + q[i] = VL_SEL_IWII(rbits, rwp, (N_Depth - 1 - i) * lbits, lbits) & mask; } -template -static inline void VL_UNPACK_QW(int lbits, int rbits, VlUnpacked& q, +template +static inline void VL_UNPACK_QW(int lbits, int rbits, VlUnpacked& q, WDataInP rwp) { const QData mask = VL_MASK_Q(lbits); - for (size_t i = 0; i < T_Depth; ++i) - q[i] = VL_SEL_QWII(rbits, rwp, (T_Depth - 1 - i) * lbits, lbits) & mask; + for (size_t i = 0; i < N_Depth; ++i) + q[i] = VL_SEL_QWII(rbits, rwp, (N_Depth - 1 - i) * lbits, lbits) & mask; } -template -static inline void VL_UNPACK_WW(int lbits, int rbits, VlUnpacked, T_Depth>& q, +template +static inline void VL_UNPACK_WW(int lbits, int rbits, VlUnpacked, N_Depth>& q, WDataInP rwp) { - for (size_t i = 0; i < T_Depth; ++i) - VL_SEL_WWII(lbits, rbits, q[i], rwp, (T_Depth - 1 - i) * lbits, lbits); + for (size_t i = 0; i < N_Depth; ++i) + VL_SEL_WWII(lbits, rbits, q[i], rwp, (N_Depth - 1 - i) * lbits, lbits); } // Return QData from double (numeric) diff --git a/include/verilated_imp.h b/include/verilated_imp.h index c3e369e17..cdc801b53 100644 --- a/include/verilated_imp.h +++ b/include/verilated_imp.h @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2009-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2009-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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 ff5f56fbd..691281783 100644 --- a/include/verilated_intrinsics.h +++ b/include/verilated_intrinsics.h @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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 8cf9ea573..43c436a59 100644 --- a/include/verilated_probdist.cpp +++ b/include/verilated_probdist.cpp @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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 4f19fc8c0..a07713112 100644 --- a/include/verilated_profiler.cpp +++ b/include/verilated_profiler.cpp @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2012-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2012-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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 6938c338d..b8bb7e50d 100644 --- a/include/verilated_profiler.h +++ b/include/verilated_profiler.h @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2012-2024 by Wilson Snyder. This program is free software; you +// Copyright 2012-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -198,7 +198,7 @@ public: //============================================================================= // VlPgoProfiler is for collecting profiling data for PGO -template +template class VlPgoProfiler final { // TYPES struct Record final { @@ -207,7 +207,7 @@ class VlPgoProfiler final { }; // Counters are stored packed, all together to reduce cache effects - std::array m_counters; // Time spent on this record + std::array m_counters; // Time spent on this record std::vector m_records; // Record information public: @@ -216,7 +216,7 @@ public: ~VlPgoProfiler() = default; void write(const char* modelp, const std::string& filename) VL_MT_SAFE; void addCounter(size_t counter, const std::string& name) { - VL_DEBUG_IF(assert(counter < T_Entries);); + VL_DEBUG_IF(assert(counter < N_Entries);); m_records.emplace_back(Record{name, counter}); } void startCounter(size_t counter) { @@ -227,8 +227,8 @@ public: void stopCounter(size_t counter) { m_counters[counter] += VL_CPU_TICK(); } }; -template -void VlPgoProfiler::write(const char* modelp, const std::string& filename) VL_MT_SAFE { +template +void VlPgoProfiler::write(const char* modelp, const std::string& filename) VL_MT_SAFE { static VerilatedMutex s_mutex; const VerilatedLockGuard lock{s_mutex}; diff --git a/include/verilated_random.cpp b/include/verilated_random.cpp index 324e6cdbe..3dc3b24b0 100644 --- a/include/verilated_random.cpp +++ b/include/verilated_random.cpp @@ -22,6 +22,7 @@ #include "verilated_random.h" +#include #include #include #include @@ -281,37 +282,6 @@ std::string parseNestedSelect(const std::string& nested_select_expr, indices.push_back(idx); return name; } - -std::string flattenIndices(const std::vector& indices, const VlRandomVar* const var) { - int flattenedIndex = 0; - int multiplier = 1; - for (int i = indices.size() - 1; i >= 0; --i) { - int indexValue = 0; - std::string trimmedIndex = indices[i]; - - trimmedIndex.erase(0, trimmedIndex.find_first_not_of(" \t")); - trimmedIndex.erase(trimmedIndex.find_last_not_of(" \t") + 1); - - if (trimmedIndex.find("#x") == 0) { - indexValue = std::strtoul(trimmedIndex.substr(2).c_str(), nullptr, 16); - } else if (trimmedIndex.find("#b") == 0) { - indexValue = std::strtoul(trimmedIndex.substr(2).c_str(), nullptr, 2); - } else { - indexValue = std::strtoul(trimmedIndex.c_str(), nullptr, 10); - } - const int length = var->getLength(i); - if (length == -1) { - VL_WARN_MT(__FILE__, __LINE__, "randomize", - "Internal: Wrong Call: Only RandomArray can call getLength()"); - break; - } - flattenedIndex += indexValue * multiplier; - multiplier *= length; - } - std::string hexString = std::to_string(flattenedIndex); - while (hexString.size() < 8) { hexString.insert(0, "0"); } - return "#x" + hexString; -} //====================================================================== // VlRandomizer:: Methods @@ -404,7 +374,11 @@ bool VlRandomizer::next(VlRNG& rngr) { f << "(define-fun __Vbv ((b Bool)) (_ BitVec 1) (ite b #b1 #b0))\n"; f << "(define-fun __Vbool ((v (_ BitVec 1))) Bool (= #b1 v))\n"; for (const auto& var : m_vars) { - f << "(declare-fun " << var.second->name() << " () "; + if (var.second->dimension() > 0) { + auto arrVarsp = std::make_shared(m_arr_vars); + var.second->setArrayInfo(arrVarsp); + } + f << "(declare-fun " << var.first << " () "; var.second->emitType(f); f << ")\n"; } @@ -444,9 +418,14 @@ bool VlRandomizer::parseSolution(std::iostream& f) { } f << "(get-value ("; - for (const auto& var : m_vars) var.second->emitGetValue(f); + for (const auto& var : m_vars) { + if (var.second->dimension() > 0) { + auto arrVarsp = std::make_shared(m_arr_vars); + var.second->setArrayInfo(arrVarsp); + } + var.second->emitGetValue(f); + } f << "))\n"; - // Quasi-parse S-expression of the form ((x #xVALUE) (y #bVALUE) (z #xVALUE)) char c; f >> c; @@ -455,7 +434,6 @@ bool VlRandomizer::parseSolution(std::iostream& f) { "Internal: Unable to parse solver's response: invalid S-expression"); return false; } - while (true) { f >> c; if (c == ')') break; @@ -471,7 +449,6 @@ bool VlRandomizer::parseSolution(std::iostream& f) { if (name == "(select") { const std::string selectExpr = readUntilBalanced(f); name = parseNestedSelect(selectExpr, indices); - idx = indices[0]; } std::getline(f, value, ')'); const auto it = m_vars.find(name); @@ -480,12 +457,34 @@ bool VlRandomizer::parseSolution(std::iostream& f) { if (m_randmode && !varr.randModeIdxNone()) { if (!(m_randmode->at(varr.randModeIdx()))) continue; } - if (indices.size() > 1) { - const std::string flattenedIndex = flattenIndices(indices, &varr); - varr.set(flattenedIndex, value); - } else { - varr.set(idx, value); + if (!indices.empty()) { + std::ostringstream oss; + oss << varr.name(); + for (const auto& hex_index : indices) { + const size_t start = hex_index.find_first_not_of(" "); + if (start == std::string::npos || hex_index.substr(start, 2) != "#x") { + VL_FATAL_MT(__FILE__, __LINE__, "randomize", + "hex_index contains invalid format"); + continue; + } + const long long index = std::stoll(hex_index.substr(start + 2), nullptr, 16); + oss << "[" << index << "]"; + } + const std::string indexed_name = oss.str(); + const auto it = std::find_if(m_arr_vars.begin(), m_arr_vars.end(), + [&indexed_name](const auto& entry) { + return entry.second->m_name == indexed_name; + }); + if (it != m_arr_vars.end()) { + std::ostringstream ss; + ss << "#x" << std::hex << std::setw(8) << std::setfill('0') << it->second->m_index; + idx = ss.str(); + } else { + VL_FATAL_MT(__FILE__, __LINE__, "randomize", + "indexed_name not found in m_arr_vars"); + } } + varr.set(idx, value); } return true; } diff --git a/include/verilated_random.h b/include/verilated_random.h index 2ae2dcb22..90d92aa9e 100644 --- a/include/verilated_random.h +++ b/include/verilated_random.h @@ -27,10 +27,29 @@ #include "verilated.h" +#include #include //============================================================================= // VlRandomExpr and subclasses represent expressions for the constraint solver. +class ArrayInfo final { +public: + const std::string + m_name; // Name of the array variable, including index notation (e.g., arr[2][1]) + void* const m_datap; // Reference to the array variable data + const int m_index; // Flattened (1D) index of the array element + const std::vector m_indices; // Multi-dimensional indices of the array element + const std::vector m_idxWidths; // Multi-dimensional indices' bit widths + + ArrayInfo(const std::string& name, void* datap, int index, const std::vector& indices, + const std::vector& idxWidths) + : m_name(name) + , m_datap(datap) + , m_index(index) + , m_indices(indices) + , m_idxWidths(idxWidths) {} +}; +using ArrayInfoMap = std::map>; class VlRandomVar VL_NOT_FINAL { const char* const m_name; // Variable name @@ -58,129 +77,100 @@ public: virtual void emitExtract(std::ostream& s, int i) const; virtual void emitType(std::ostream& s) const; virtual int totalWidth() const; - virtual int getLength(int dimension) const { return -1; } -}; - -template -class VlRandomQueueVar final : public VlRandomVar { -public: - VlRandomQueueVar(const char* name, int width, void* datap, int dimension, - std::uint32_t randModeIdx) - : VlRandomVar{name, width, datap, dimension, randModeIdx} {} - void* datap(int idx) const override { - return &static_cast(VlRandomVar::datap(idx))->atWrite(idx); + mutable std::shared_ptr m_arrVarsRefp; + void setArrayInfo(const std::shared_ptr& arrVarsRefp) const { + m_arrVarsRefp = arrVarsRefp; } - void emitSelect(std::ostream& s, int i) const { - s << " (select " << name() << " #x"; - for (int j = 28; j >= 0; j -= 4) s << "0123456789abcdef"[(i >> j) & 0xf]; - s << ')'; - } - void emitGetValue(std::ostream& s) const override { - const int length = static_cast(VlRandomVar::datap(0))->size(); - for (int i = 0; i < length; i++) emitSelect(s, i); - } - void emitType(std::ostream& s) const override { - s << "(Array (_ BitVec 32) (_ BitVec " << width() << "))"; - } - int totalWidth() const override { - const int length = static_cast(VlRandomVar::datap(0))->size(); - return width() * length; - } - void emitExtract(std::ostream& s, int i) const override { - const int j = i / width(); - i = i % width(); - s << " ((_ extract " << i << ' ' << i << ')'; - emitSelect(s, j); - s << ')'; - } -}; - -template -class VlRandomArrayVar final : public VlRandomVar { -public: - VlRandomArrayVar(const char* name, int width, void* datap, int dimension, - std::uint32_t randModeIdx) - : VlRandomVar{name, width, datap, dimension, randModeIdx} {} - - void* datap(int idx) const override { - if (idx < 0) return &static_cast(VlRandomVar::datap(0))->operator[](0); - std::vector indices(dimension()); - for (int dim = dimension() - 1; dim >= 0; --dim) { - const int length = getLength(dim); - indices[dim] = idx % length; - idx /= length; + mutable std::map count_cache; + int countMatchingElements(const ArrayInfoMap& arr_vars, const std::string& base_name) const { + if (VL_LIKELY(count_cache.find(base_name) != count_cache.end())) + return count_cache[base_name]; + int count = 0; + for (int index = 0; arr_vars.find(base_name + std::to_string(index)) != arr_vars.end(); + ++index) { + ++count; } - return &static_cast(VlRandomVar::datap(0))->find_element(indices); + count_cache[base_name] = count; + return count; } - - void emitSelect(std::ostream& s, const std::vector& indices) const { +}; +template +class VlRandomArrayVarTemplate final : public VlRandomVar { +public: + VlRandomArrayVarTemplate(const char* name, int width, void* datap, int dimension, + std::uint32_t randModeIdx) + : VlRandomVar{name, width, datap, dimension, randModeIdx} {} + void* datap(int idx) const override { + const std::string indexed_name = name() + std::to_string(idx); + const auto it = m_arrVarsRefp->find(indexed_name); + if (it != m_arrVarsRefp->end()) { + return it->second->m_datap; + } else { + VL_FATAL_MT(__FILE__, __LINE__, "randomize", "indexed_name not found in m_arr_vars"); + return nullptr; + } + } + void emitSelect(std::ostream& s, const std::vector& indices, + const std::vector& idxWidths) const { for (size_t idx = 0; idx < indices.size(); ++idx) s << "(select "; s << name(); for (size_t idx = 0; idx < indices.size(); ++idx) { s << " #x"; - for (int j = 28; j >= 0; j -= 4) { + const size_t bit_width = idxWidths[idx]; + for (int j = bit_width - 4; j >= 0; j -= 4) { s << "0123456789abcdef"[(indices[idx] >> j) & 0xf]; } s << ")"; } } - - int getLength(int dimension) const override { - const auto var = static_cast(datap(-1)); - const int lenth = var->find_length(dimension); - return lenth; - } - void emitGetValue(std::ostream& s) const override { - const int total_dimensions = dimension(); - std::vector lengths; - for (int dim = 0; dim < total_dimensions; dim++) { - const int len = getLength(dim); - lengths.push_back(len); - } - std::vector indices(total_dimensions, 0); - while (true) { - emitSelect(s, indices); - int currentDimension = total_dimensions - 1; - while (currentDimension >= 0 - && ++indices[currentDimension] >= lengths[currentDimension]) { - indices[currentDimension] = 0; - --currentDimension; + const int elementCounts = countMatchingElements(*m_arrVarsRefp, name()); + for (int i = 0; i < elementCounts; i++) { + const std::string indexed_name = name() + std::to_string(i); + const auto it = m_arrVarsRefp->find(indexed_name); + if (it != m_arrVarsRefp->end()) { + const std::vector& indices = it->second->m_indices; + const std::vector& idxWidths = it->second->m_idxWidths; + emitSelect(s, indices, idxWidths); + } else { + VL_FATAL_MT(__FILE__, __LINE__, "randomize", + "indexed_name not found in m_arr_vars"); } - if (currentDimension < 0) break; } } - void emitType(std::ostream& s) const override { - if (dimension() > 0) { - for (int i = 0; i < dimension(); ++i) s << "(Array (_ BitVec 32) "; - s << "(_ BitVec " << width() << ")"; - for (int i = 0; i < dimension(); ++i) s << ")"; + const std::string indexed_name = name() + std::to_string(0); + const auto it = m_arrVarsRefp->find(indexed_name); + if (it != m_arrVarsRefp->end()) { + const std::vector& idxWidths = it->second->m_idxWidths; + if (dimension() > 0) { + for (int i = 0; i < dimension(); ++i) { + s << "(Array (_ BitVec " << idxWidths[i] << ") "; + } + s << "(_ BitVec " << width() << ")"; + for (int i = 0; i < dimension(); ++i) { s << ")"; } + } + } else { + VL_FATAL_MT(__FILE__, __LINE__, "randomize", "indexed_name not found in m_arr_vars"); } } - int totalWidth() const override { - int totalLength = 1; - for (int dim = 0; dim < dimension(); ++dim) { - const int length = getLength(dim); - if (length == -1) return 0; - totalLength *= length; - } - return width() * totalLength; + const int elementCounts = countMatchingElements(*m_arrVarsRefp, name()); + return width() * elementCounts; } - void emitExtract(std::ostream& s, int i) const override { const int j = i / width(); i = i % width(); - std::vector indices(dimension()); - int idx = j; - for (int dim = dimension() - 1; dim >= 0; --dim) { - int length = getLength(dim); - indices[dim] = idx % length; - idx /= length; - } s << " ((_ extract " << i << ' ' << i << ')'; - emitSelect(s, indices); + const std::string indexed_name = name() + std::to_string(j); + const auto it = m_arrVarsRefp->find(indexed_name); + if (it != m_arrVarsRefp->end()) { + const std::vector& indices = it->second->m_indices; + const std::vector& idxWidths = it->second->m_idxWidths; + emitSelect(s, indices, idxWidths); + } else { + VL_FATAL_MT(__FILE__, __LINE__, "randomize", "indexed_name not found in m_arr_vars"); + } s << ')'; } }; @@ -192,6 +182,8 @@ class VlRandomizer final { std::vector m_constraints; // Solver-dependent constraints std::map> m_vars; // Solver-dependent // variables + ArrayInfoMap m_arr_vars; // Tracks each element in array structures for iteration + std::map seen_values; // Record String Index to avoid conflicts const VlQueue* m_randmode; // rand_mode state; // PRIVATE METHODS @@ -206,6 +198,47 @@ public: // METHODS // Finds the next solution satisfying the constraints bool next(VlRNG& rngr); + + template + typename std::enable_if::value>::type + process_key(const T_Key& key, std::string& indexed_name, size_t& integral_index, + const std::string& base_name, size_t& idx_width) { + integral_index = static_cast(key); + indexed_name = base_name + "[" + std::to_string(integral_index) + "]"; + idx_width = sizeof(T_Key) * 8; + } + template + typename std::enable_if::value>::type + process_key(const T_Key& key, std::string& indexed_name, size_t& integral_index, + const std::string& base_name, size_t& idx_width) { + integral_index = string_to_integral(key); + indexed_name = base_name + "[" + std::to_string(integral_index) + "]"; + idx_width = 64; // 64-bit mask + } + template + typename std::enable_if::value + && !std::is_same::value>::type + process_key(const T_Key& key, std::string& indexed_name, size_t& integral_index, + const std::string& base_name, size_t& idx_width) { + VL_FATAL_MT(__FILE__, __LINE__, "randomize", + "Unsupported: Only integral and string index of associative array is " + "supported currently."); + } + + uint64_t string_to_integral(const std::string& str) { + uint64_t result = 0; + for (char c : str) { result = (result << 8) | static_cast(c); } + +#ifdef VL_DEBUG + if (seen_values.count(result) > 0 && seen_values[result] != str) + VL_WARN_MT(__FILE__, __LINE__, "randomize", + "Conflict detected: Different strings mapped to the same 64-bit index."); + seen_values[result] = str; +#endif + + return result; + } + template void write_var(T& var, int width, const char* name, int dimension, std::uint32_t randmodeIdx = std::numeric_limits::max()) { @@ -218,16 +251,103 @@ public: void write_var(VlQueue& var, int width, const char* name, int dimension, std::uint32_t randmodeIdx = std::numeric_limits::max()) { if (m_vars.find(name) != m_vars.end()) return; - m_vars[name] = std::make_shared>>( + m_vars[name] = std::make_shared>>( name, width, &var, dimension, randmodeIdx); + if (dimension > 0) { + idx = 0; + record_arr_table(var, name, dimension, {}, {}); + } } - template - void write_var(VlUnpacked& var, int width, const char* name, int dimension, + template + void write_var(VlUnpacked& var, int width, const char* name, int dimension, std::uint32_t randmodeIdx = std::numeric_limits::max()) { if (m_vars.find(name) != m_vars.end()) return; - m_vars[name] = std::make_shared>>( + m_vars[name] = std::make_shared>>( name, width, &var, dimension, randmodeIdx); + if (dimension > 0) { + idx = 0; + record_arr_table(var, name, dimension, {}, {}); + } } + template + void write_var(VlAssocArray& var, int width, const char* name, int dimension, + std::uint32_t randmodeIdx = std::numeric_limits::max()) { + if (m_vars.find(name) != m_vars.end()) return; + m_vars[name] + = std::make_shared>>( + name, width, &var, dimension, randmodeIdx); + if (dimension > 0) { + idx = 0; + record_arr_table(var, name, dimension, {}, {}); + } + } + + int idx; + std::string generateKey(const std::string& name, int idx) { + if (!name.empty() && name[0] == '\\') { + const size_t space_pos = name.find(' '); + return (space_pos != std::string::npos ? name.substr(0, space_pos) : name) + + std::to_string(idx); + } + const size_t bracket_pos = name.find('['); + return (bracket_pos != std::string::npos ? name.substr(0, bracket_pos) : name) + + std::to_string(idx); + } + + template + void record_arr_table(T& var, const std::string name, int dimension, + std::vector indices, std::vector idxWidths) { + const std::string key = generateKey(name, idx); + m_arr_vars[key] = std::make_shared(name, &var, idx, indices, idxWidths); + ++idx; + } + template + void record_arr_table(VlQueue& var, const std::string name, int dimension, + std::vector indices, std::vector idxWidths) { + if ((dimension > 0) && (var.size() != 0)) { + idxWidths.push_back(32); + for (size_t i = 0; i < var.size(); ++i) { + const std::string indexed_name = name + "[" + std::to_string(i) + "]"; + indices.push_back(i); + record_arr_table(var.atWrite(i), indexed_name, dimension - 1, indices, idxWidths); + indices.pop_back(); + } + } + } + template + void record_arr_table(VlUnpacked& var, const std::string name, int dimension, + std::vector indices, std::vector idxWidths) { + if ((dimension > 0) && (N_Depth != 0)) { + idxWidths.push_back(32); + for (size_t i = 0; i < N_Depth; ++i) { + const std::string indexed_name = name + "[" + std::to_string(i) + "]"; + indices.push_back(i); + record_arr_table(var.operator[](i), indexed_name, dimension - 1, indices, + idxWidths); + indices.pop_back(); + } + } + } + template + void record_arr_table(VlAssocArray& var, const std::string name, int dimension, + std::vector indices, std::vector idxWidths) { + if ((dimension > 0) && (var.size() != 0)) { + for (auto it = var.begin(); it != var.end(); ++it) { + const T_Key& key = it->first; + const T_Value& value = it->second; + std::string indexed_name; + size_t integral_index; + size_t idx_width; + process_key(key, indexed_name, integral_index, name, idx_width); + idxWidths.push_back(idx_width); + indices.push_back(integral_index); + record_arr_table(var.at(key), indexed_name, dimension - 1, indices, idxWidths); + idxWidths.pop_back(); + indices.pop_back(); + } + } + } + void hard(std::string&& constraint); void clear(); void set_randmode(const VlQueue& randmode) { m_randmode = &randmode; } diff --git a/include/verilated_save.cpp b/include/verilated_save.cpp index c2c8e3cdd..b866de572 100644 --- a/include/verilated_save.cpp +++ b/include/verilated_save.cpp @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2001-2024 by Wilson Snyder. This program is free software; you +// Copyright 2001-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.h b/include/verilated_save.h index 4ff97a154..e49eaeb6d 100644 --- a/include/verilated_save.h +++ b/include/verilated_save.h @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2000-2024 by Wilson Snyder. This program is free software; you +// Copyright 2000-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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 @@ inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, std::string& r VerilatedSerialize& operator<<(VerilatedSerialize& os, VerilatedContext* rhsp); VerilatedDeserialize& operator>>(VerilatedDeserialize& os, VerilatedContext* rhsp); -template +template VerilatedSerialize& operator<<(VerilatedSerialize& os, VlAssocArray& rhs) { os << rhs.atDefault(); const uint32_t len = rhs.size(); @@ -312,7 +312,7 @@ VerilatedSerialize& operator<<(VerilatedSerialize& os, VlAssocArray +template VerilatedDeserialize& operator>>(VerilatedDeserialize& os, VlAssocArray& rhs) { os >> rhs.atDefault(); uint32_t len = 0; diff --git a/include/verilated_sc.h b/include/verilated_sc.h index 3f7b901b4..2fcfb593d 100644 --- a/include/verilated_sc.h +++ b/include/verilated_sc.h @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2009-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2009-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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_trace.h b/include/verilated_sc_trace.h index f9a25a75c..99bffa19f 100644 --- a/include/verilated_sc_trace.h +++ b/include/verilated_sc_trace.h @@ -1,7 +1,7 @@ // -*- mode: C++; c-file-style: "cc-mode" -*- //============================================================================= // -// Copyright 2001-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2001-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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 2741f03bc..4ef8df547 100644 --- a/include/verilated_std.sv +++ b/include/verilated_std.sv @@ -4,7 +4,7 @@ // //************************************************************************* // -// Copyright 2022-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2022-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/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 @@ -14,13 +14,16 @@ /// \file /// \brief Verilated IEEE std:: header /// -/// This file is included automatically by Verilator when a std::mailbox or -/// std::semaphore is referenced. +/// This file is included automatically by Verilator, unless '--no-std-package' +/// is used. /// /// This file is not part of the Verilated public-facing API. /// It is only for internal use. /// //************************************************************************* +// +// The following keywords from this file are hardcoded for detection in the parser: +// "mailbox", "process", "randomize", "semaphore", "std" // verilator lint_off DECLFILENAME // verilator lint_off TIMESCALEMOD diff --git a/include/verilated_std_waiver.vlt b/include/verilated_std_waiver.vlt new file mode 100644 index 000000000..9d4e1534a --- /dev/null +++ b/include/verilated_std_waiver.vlt @@ -0,0 +1,64 @@ +// DESCRIPTION: Verilator: built-in standard lint waivers +// +// Code available from: https://verilator.org +// +//************************************************************************* +// +// Copyright 2022-2025 by Wilson Snyder. This program is free software; you can +// redistribute it and/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 +// +//************************************************************************* +/// +/// \file +/// \brief Verilated built-in standard lint waivers +/// +/// This file is included automatically by Verilator, unless '--no-std-waiver' +/// is used. +/// +/// To assist in building new rules, use: +/// 'verilator --waiver-multiline --waiver-output ' +/// +//************************************************************************* + +`ifndef _VERILATED_STD_WAIVER_VLT_ +`define _VERILATED_STD_WAIVER_VLT_ + +`verilator_config + +//========================================================================= +// UVM + +// Apply these rules to only UVM base files +`define VLT_UVM_FILES -file "*/uvm_*.svh" -contents "*UVM_VERSION_STRING*" + +// Whole-package file waivers +lint_off -rule DECLFILENAME `VLT_UVM_FILES +lint_off -rule VARHIDDEN `VLT_UVM_FILES +lint_off -rule WIDTHEXPAND `VLT_UVM_FILES +lint_off -rule WIDTHTRUNC `VLT_UVM_FILES + +// Context-sensitive waivers +lint_off -rule CASEINCOMPLETE `VLT_UVM_FILES -match "* case ({is_R, is_W})*" +lint_off -rule CASEINCOMPLETE `VLT_UVM_FILES -match "* case(orig_severity)*" +lint_off -rule CASTCONST `VLT_UVM_FILES -match "*class{}uvm_callback*" +lint_off -rule CASTCONST `VLT_UVM_FILES -match "*class{}uvm_component*" +lint_off -rule CASTCONST `VLT_UVM_FILES -match "*class{}uvm_event*" +lint_off -rule CASTCONST `VLT_UVM_FILES -match "*class{}uvm_report_object*" +lint_off -rule CASTCONST `VLT_UVM_FILES -match "*class{}uvm_sequence_item*" +lint_off -rule MISINDENT `VLT_UVM_FILES -match "* foreach (abstractions[i])*" +lint_off -rule MISINDENT `VLT_UVM_FILES -match "* foreach (lock_list[i])*" +lint_off -rule MISINDENT `VLT_UVM_FILES -match "* rw_access.data=*" +lint_off -rule MISINDENT `VLT_UVM_FILES -match "* uvm_cmdline_proc =*" +lint_off -rule REALCVT `VLT_UVM_FILES -match "* m_time *" +lint_off -rule REALCVT `VLT_UVM_FILES -match "*$realtime*" +lint_off -rule SYMRSVDWORD `VLT_UVM_FILES -match "*'delete'*" +lint_off -rule SYMRSVDWORD `VLT_UVM_FILES -match "*'list'*" +lint_off -rule SYMRSVDWORD `VLT_UVM_FILES -match "*'map'*" +lint_off -rule SYMRSVDWORD `VLT_UVM_FILES -match "*'override'*" +lint_off -rule SYMRSVDWORD `VLT_UVM_FILES -match "*'volatile'*" + +//========================================================================= +`undef VLT_UVM_FILES +`endif // Guard diff --git a/include/verilated_sym_props.h b/include/verilated_sym_props.h index 2e7cdf805..5298787b0 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-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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_syms.h b/include/verilated_syms.h index f4eccb301..39fbaa71a 100644 --- a/include/verilated_syms.h +++ b/include/verilated_syms.h @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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 45318f518..4c048e04e 100644 --- a/include/verilated_threads.cpp +++ b/include/verilated_threads.cpp @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2012-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2012-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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 7ba0a4f33..b0e40d3b5 100644 --- a/include/verilated_threads.h +++ b/include/verilated_threads.h @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2012-2024 by Wilson Snyder. This program is free software; you +// Copyright 2012-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -161,10 +161,10 @@ public: ~VlWorkerThread(); // METHODS - template + template void dequeWork(ExecRec* workp) VL_MT_SAFE_EXCLUDES(m_mutex) { // Spin for a while, waiting for new data - if VL_CONSTEXPR_CXX17 (SpinWait) { + if VL_CONSTEXPR_CXX17 (N_SpinWait) { for (unsigned i = 0; i < VL_LOCK_SPINS; ++i) { if (VL_LIKELY(m_ready_size.load(std::memory_order_relaxed))) break; VL_CPU_RELAX(); diff --git a/include/verilated_timing.cpp b/include/verilated_timing.cpp index f7ceec357..0724a43e9 100644 --- a/include/verilated_timing.cpp +++ b/include/verilated_timing.cpp @@ -89,7 +89,7 @@ void VlDelayScheduler::resume() { uint64_t VlDelayScheduler::nextTimeSlot() const { if (!m_queue.empty()) return m_queue.cbegin()->first; if (m_zeroDelayed.empty()) - VL_FATAL_MT(__FILE__, __LINE__, "", "%Error: There is no next time slot scheduled"); + VL_FATAL_MT(__FILE__, __LINE__, "", "There is no next time slot scheduled"); return m_context.time(); } diff --git a/include/verilated_trace.h b/include/verilated_trace.h index 87d5025b4..a297087c6 100644 --- a/include/verilated_trace.h +++ b/include/verilated_trace.h @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2001-2024 by Wilson Snyder. This program is free software; you +// Copyright 2001-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,9 +41,9 @@ // clang-format on class VlThreadPool; -template +template class VerilatedTraceBuffer; -template +template class VerilatedTraceOffloadBuffer; //============================================================================= @@ -100,7 +100,7 @@ enum class VerilatedTraceSigType : uint8_t { // Offloaded tracing // A simple synchronized first in first out queue -template +template class VerilatedThreadQueue final { // LCOV_EXCL_LINE // lcov bug private: mutable VerilatedMutex m_mutex; // Protects m_queue @@ -202,7 +202,7 @@ public: // T_Trace is the format-specific subclass of VerilatedTrace. // T_Buffer is the format-specific base class of VerilatedTraceBuffer. -template +template class VerilatedTrace VL_NOT_FINAL { public: using Buffer = VerilatedTraceBuffer; @@ -442,7 +442,7 @@ public: // T_Buffer is the format-specific base class of VerilatedTraceBuffer. // The format-specific hot-path methods use duck-typing via T_Buffer for performance. -template +template class VerilatedTraceBuffer VL_NOT_FINAL : public T_Buffer { protected: // Type of the owner trace file @@ -543,7 +543,7 @@ public: // T_Buffer is the format-specific base class of VerilatedTraceBuffer. // The format-specific hot-path methods use duck-typing via T_Buffer for performance. -template +template class VerilatedTraceOffloadBuffer final : public VerilatedTraceBuffer { using typename VerilatedTraceBuffer::Trace; diff --git a/include/verilated_trace_imp.h b/include/verilated_trace_imp.h index ba5bd22e2..d13f5bcf6 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-2024 by Wilson Snyder. This program is free software; you +// Copyright 2001-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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_types.h b/include/verilated_types.h index 773b20212..84caafa27 100644 --- a/include/verilated_types.h +++ b/include/verilated_types.h @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -164,12 +164,12 @@ inline std::string VL_TO_STRING(const VlProcessRef& p) { return std::string("pro //=================================================================== // Activity trigger vector -template // +template // class VlTriggerVec final { - // TODO: static assert T_size > 0, and don't generate when empty + // TODO: static assert N_Size > 0, and don't generate when empty // MEMBERS - alignas(16) std::array(T_size) / 64> m_flags; // The flags + alignas(16) std::array(N_Size) / 64> m_flags; // The flags public: // CONSTRUCTOR @@ -200,12 +200,12 @@ public: } // Set all elements true in 'this' that are set in 'other' - void thisOr(const VlTriggerVec& other) { + void thisOr(const VlTriggerVec& other) { for (size_t i = 0; i < m_flags.size(); ++i) m_flags[i] |= other.m_flags[i]; } // Set elements of 'this' to 'a & !b' element-wise - void andNot(const VlTriggerVec& a, const VlTriggerVec& b) { + void andNot(const VlTriggerVec& a, const VlTriggerVec& b) { for (size_t i = 0; i < m_flags.size(); ++i) m_flags[i] = a.m_flags[i] & ~b.m_flags[i]; } }; @@ -309,7 +309,7 @@ public: size_t operator()() { return VL_MASK_I(31) & vl_rand64(); } }; -template +template class VlRandC final { T_Value m_remaining = 0; // Number of values to pull before re-randomize T_Value m_lfsr = 1; // LFSR state @@ -317,8 +317,8 @@ class VlRandC final { public: // CONSTRUCTORS VlRandC() { - static_assert(T_numValues >= 1, ""); - static_assert(sizeof(T_Value) == 8 || (T_numValues < (1ULL << (8 * sizeof(T_Value)))), ""); + static_assert(N_NumValues >= 1, ""); + static_assert(sizeof(T_Value) == 8 || (N_NumValues < (1ULL << (8 * sizeof(T_Value)))), ""); } // METHODS T_Value randomize(VlRNG& rngr) { @@ -337,23 +337,23 @@ public: 0x80000057ULL, // 32 0x100000029ULL // 33 }; - constexpr uint32_t clogWidth = VL_CLOG2_CE_Q(T_numValues) + 1; + constexpr uint32_t clogWidth = VL_CLOG2_CE_Q(N_NumValues) + 1; constexpr uint32_t lfsrWidth = (clogWidth < 2) ? 2 : clogWidth; constexpr T_Value polynomial = static_cast(s_polynomials[lfsrWidth]); - // printf(" numV=%ld w=%d poly=%x\n", T_numValues, lfsrWidth, polynomial); + // printf(" numV=%ld w=%d poly=%x\n", N_NumValues, lfsrWidth, polynomial); // Loop until get reasonable value. Because we picked a LFSR of at most one // extra bit in width, this will only require at most on average 1.5 loops do { m_lfsr = (m_lfsr & 1ULL) ? ((m_lfsr >> 1ULL) ^ polynomial) : (m_lfsr >> 1ULL); - } while (m_lfsr > T_numValues); // Note if == then output value 0 + } while (m_lfsr > N_NumValues); // Note if == then output value 0 --m_remaining; - T_Value result = (m_lfsr == T_numValues) ? 0 : m_lfsr; - // printf(" result=%x (numv=%ld, rem=%d)\n", result, T_numValues, m_remaining); + T_Value result = (m_lfsr == N_NumValues) ? 0 : m_lfsr; + // printf(" result=%x (numv=%ld, rem=%d)\n", result, N_NumValues, m_remaining); return result; } void reseed(VlRNG& rngr) { - constexpr uint32_t lfsrWidth = VL_CLOG2_CE_Q(T_numValues) + 1; - m_remaining = T_numValues; + constexpr uint32_t lfsrWidth = VL_CLOG2_CE_Q(N_NumValues) + 1; + m_remaining = N_NumValues; do { m_lfsr = rngr.rand64() & VL_MASK_Q(lfsrWidth); // printf(" lfsr.reseed=%x\n", m_lfsr); @@ -414,23 +414,23 @@ public: static int _vl_cmp_w(int words, WDataInP const lwp, WDataInP const rwp) VL_PURE; -template +template struct VlWide; // Type trait to check if a type is VlWide template struct VlIsVlWide : public std::false_type {}; -template -struct VlIsVlWide> : public std::true_type {}; +template +struct VlIsVlWide> : public std::true_type {}; -template +template struct VlWide final { - static constexpr size_t Words = T_Words; + static constexpr size_t Words = N_Words; // MEMBERS // This should be the only data member, otherwise generated static initializers need updating - EData m_storage[T_Words]; // Contents of the packed array + EData m_storage[N_Words]; // Contents of the packed array // CONSTRUCTORS // Default constructors and destructor are used. Note however that C++20 requires that @@ -441,8 +441,8 @@ struct VlWide final { // Default copy assignment operators are used. 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) { + bool operator!=(const VlWide& that) const VL_PURE { + for (size_t i = 0; i < N_Words; ++i) { if (m_storage[i] != that.m_storage[i]) return true; } return false; @@ -453,21 +453,21 @@ struct VlWide final { EData& at(size_t index) { return m_storage[index]; } WData* data() { return &m_storage[0]; } const WData* data() const { return &m_storage[0]; } - bool operator<(const VlWide& rhs) const { - return _vl_cmp_w(T_Words, data(), rhs.data()) < 0; + bool operator<(const VlWide& rhs) const { + return _vl_cmp_w(N_Words, data(), rhs.data()) < 0; } }; // Convert a C array to std::array reference by pointer magic, without copy. // Data type (second argument) is so the function template can automatically generate. -template -VlWide& VL_CVT_W_A(const WDataInP inp, const VlWide&) { - return *((VlWide*)inp); +template +VlWide& VL_CVT_W_A(const WDataInP inp, const VlWide&) { + return *((VlWide*)inp); } -template -std::string VL_TO_STRING(const VlWide& obj) { - return VL_TO_STRING_W(T_Words, obj.data()); +template +std::string VL_TO_STRING(const VlWide& obj) { + return VL_TO_STRING_W(N_Words, obj.data()); } //=================================================================== @@ -477,7 +477,7 @@ std::string VL_TO_STRING(const VlWide& obj) { // // Bound here is the maximum size() allowed, e.g. 1 + SystemVerilog bound // For dynamic arrays it is always zero -template +template class VlQueue final { private: // TYPES @@ -485,8 +485,8 @@ private: public: using const_iterator = typename Deque::const_iterator; - template - using WithFuncReturnType = decltype(std::declval()(0, std::declval())); + template + using WithFuncReturnType = decltype(std::declval()(0, std::declval())); private: // MEMBERS @@ -506,11 +506,11 @@ public: 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 - template - VlQueue operator=(const VlQueue& rhs) { + // Also must allow conversion from a different N_MaxSize queue + template + VlQueue operator=(const VlQueue& rhs) { m_deque = rhs.privateDeque(); - if (VL_UNLIKELY(T_MaxSize && T_MaxSize < m_deque.size())) m_deque.resize(T_MaxSize - 1); + if (VL_UNLIKELY(N_MaxSize && N_MaxSize < m_deque.size())) m_deque.resize(N_MaxSize - 1); return *this; } @@ -562,7 +562,7 @@ public: m_deque.resize(size, atDefault()); } // Dynamic array new[]() becomes a renew_copy() - void renew_copy(size_t size, const VlQueue& rhs) { + void renew_copy(size_t size, const VlQueue& rhs) { if (size == 0) { clear(); } else { @@ -570,15 +570,16 @@ public: m_deque.resize(size, atDefault()); } } + void resize(size_t size) { m_deque.resize(size, atDefault()); } // function void q.push_front(value) void push_front(const T_Value& value) { m_deque.push_front(value); - if (VL_UNLIKELY(T_MaxSize != 0 && m_deque.size() > T_MaxSize)) m_deque.pop_back(); + if (VL_UNLIKELY(N_MaxSize != 0 && m_deque.size() > N_MaxSize)) m_deque.pop_back(); } // function void q.push_back(value) void push_back(const T_Value& value) { - if (VL_LIKELY(T_MaxSize == 0 || m_deque.size() < T_MaxSize)) m_deque.push_back(value); + if (VL_LIKELY(N_MaxSize == 0 || m_deque.size() < N_MaxSize)) m_deque.push_back(value); } // function value_t q.pop_front(); T_Value pop_front() { @@ -599,7 +600,7 @@ public: T_Value& atWrite(int32_t index) { // cppcheck-suppress variableScope static thread_local T_Value t_throwAway; - // Needs to work for dynamic arrays, so does not use T_MaxSize + // Needs to work for dynamic arrays, so does not use N_MaxSize if (VL_UNLIKELY(index < 0 || index >= m_deque.size())) { t_throwAway = atDefault(); return t_throwAway; @@ -620,7 +621,7 @@ public: } // Accessing. Verilog: v = assoc[index] const T_Value& at(int32_t index) const { - // Needs to work for dynamic arrays, so does not use T_MaxSize + // Needs to work for dynamic arrays, so does not use N_MaxSize if (VL_UNLIKELY(index < 0 || index >= m_deque.size())) { return atDefault(); } else { @@ -664,8 +665,8 @@ public: // Methods void sort() { std::sort(m_deque.begin(), m_deque.end()); } - template - void sort(Func with_func) { + template + void sort(T_Func with_func) { // with_func returns arbitrary type to use for the sort comparison std::sort(m_deque.begin(), m_deque.end(), [=](const T_Value& a, const T_Value& b) { // index number is meaningless with sort, as it changes @@ -673,8 +674,8 @@ public: }); } void rsort() { std::sort(m_deque.rbegin(), m_deque.rend()); } - template - void rsort(Func with_func) { + template + void rsort(T_Func with_func) { // with_func returns arbitrary type to use for the sort comparison std::sort(m_deque.rbegin(), m_deque.rend(), [=](const T_Value& a, const T_Value& b) { // index number is meaningless with sort, as it changes @@ -695,8 +696,8 @@ public: } return out; } - template - VlQueue unique(Func with_func) const { + template + VlQueue unique(T_Func with_func) const { VlQueue out; std::set saw; for (const auto& i : m_deque) { @@ -723,8 +724,8 @@ public: } return out; } - template - VlQueue unique_index(Func with_func) const { + template + VlQueue unique_index(T_Func with_func) const { VlQueue out; IData index = 0; std::set saw; @@ -739,8 +740,8 @@ public: } return out; } - template - VlQueue find(Func with_func) const { + template + VlQueue find(T_Func with_func) const { VlQueue out; IData index = 0; for (const auto& i : m_deque) { @@ -749,8 +750,8 @@ public: } return out; } - template - VlQueue find_index(Func with_func) const { + template + VlQueue find_index(T_Func with_func) const { VlQueue out; IData index = 0; for (const auto& i : m_deque) { @@ -759,8 +760,8 @@ public: } return out; } - template - VlQueue find_first(Func with_func) const { + template + VlQueue find_first(T_Func with_func) const { // Can't use std::find_if as need index number IData index = 0; for (const auto& i : m_deque) { @@ -769,8 +770,8 @@ public: } return VlQueue{}; } - template - VlQueue find_first_index(Func with_func) const { + template + VlQueue find_first_index(T_Func with_func) const { IData index = 0; for (const auto& i : m_deque) { if (with_func(index, i)) return VlQueue::consV(index); @@ -778,8 +779,8 @@ public: } return VlQueue{}; } - template - VlQueue find_last(Func with_func) const { + template + VlQueue find_last(T_Func with_func) const { IData index = m_deque.size() - 1; for (auto& item : vlstd::reverse_view(m_deque)) { if (with_func(index, item)) return VlQueue::consV(item); @@ -787,8 +788,8 @@ public: } return VlQueue{}; } - template - VlQueue find_last_index(Func with_func) const { + template + VlQueue find_last_index(T_Func with_func) const { IData index = m_deque.size() - 1; for (auto& item : vlstd::reverse_view(m_deque)) { if (with_func(index, item)) return VlQueue::consV(index); @@ -803,8 +804,8 @@ public: const auto it = std::min_element(m_deque.cbegin(), m_deque.cend()); return VlQueue::consV(*it); } - template - VlQueue min(Func with_func) const { + template + VlQueue min(T_Func with_func) const { if (m_deque.empty()) return VlQueue{}; const auto it = std::min_element(m_deque.cbegin(), m_deque.cend(), [&with_func](const IData& a, const IData& b) { @@ -817,8 +818,8 @@ public: const auto it = std::max_element(m_deque.cbegin(), m_deque.cend()); return VlQueue::consV(*it); } - template - VlQueue max(Func with_func) const { + template + VlQueue max(T_Func with_func) const { if (m_deque.empty()) return VlQueue{}; const auto it = std::max_element(m_deque.cbegin(), m_deque.cend(), [&with_func](const IData& a, const IData& b) { @@ -832,9 +833,9 @@ public: for (const auto& i : m_deque) out += i; return out; } - template - WithFuncReturnType r_sum(Func with_func) const { - WithFuncReturnType out = WithFuncReturnType(0); + template + WithFuncReturnType r_sum(T_Func with_func) const { + WithFuncReturnType out = WithFuncReturnType(0); IData index = 0; for (const auto& i : m_deque) out += with_func(index++, i); return out; @@ -845,10 +846,10 @@ public: for (const auto& i : m_deque) out *= i; return out; } - template - WithFuncReturnType r_product(Func with_func) const { - if (m_deque.empty()) return WithFuncReturnType(0); // The big three do it this way - WithFuncReturnType out = WithFuncReturnType(1); + template + WithFuncReturnType r_product(T_Func with_func) const { + if (m_deque.empty()) return WithFuncReturnType(0); // The big three do it this way + WithFuncReturnType out = WithFuncReturnType(1); IData index = 0; for (const auto& i : m_deque) out *= with_func(index++, i); return out; @@ -859,11 +860,11 @@ public: for (const auto& i : m_deque) out &= i; return out; } - template - WithFuncReturnType r_and(Func with_func) const { - if (m_deque.empty()) return WithFuncReturnType(0); // The big three do it this way + template + WithFuncReturnType r_and(T_Func with_func) const { + if (m_deque.empty()) return WithFuncReturnType(0); // The big three do it this way IData index = 0; - WithFuncReturnType out = ~WithFuncReturnType(0); + WithFuncReturnType out = ~WithFuncReturnType(0); for (const auto& i : m_deque) out &= with_func(index++, i); return out; } @@ -872,9 +873,9 @@ public: for (const auto& i : m_deque) out |= i; return out; } - template - WithFuncReturnType r_or(Func with_func) const { - WithFuncReturnType out = WithFuncReturnType(0); + template + WithFuncReturnType r_or(T_Func with_func) const { + WithFuncReturnType out = WithFuncReturnType(0); IData index = 0; for (const auto& i : m_deque) out |= with_func(index++, i); return out; @@ -887,9 +888,9 @@ public: for (const auto& i : m_deque) out ^= i; return out; } - template - WithFuncReturnType r_xor(Func with_func) const { - WithFuncReturnType out = WithFuncReturnType(0); + template + WithFuncReturnType r_xor(T_Func with_func) const { + WithFuncReturnType out = WithFuncReturnType(0); IData index = 0; for (const auto& i : m_deque) out ^= with_func(index++, i); return out; @@ -908,8 +909,8 @@ public: } }; -template -std::string VL_TO_STRING(const VlQueue& obj) { +template +std::string VL_TO_STRING(const VlQueue& obj) { return obj.to_string(); } @@ -918,7 +919,7 @@ std::string VL_TO_STRING(const VlQueue& obj) { // There are no multithreaded locks on this; the base variable must // be protected by other means // -template +template class VlAssocArray final { private: // TYPES @@ -926,9 +927,9 @@ private: public: using const_iterator = typename Map::const_iterator; - template + template using WithFuncReturnType - = decltype(std::declval()(std::declval(), std::declval())); + = decltype(std::declval()(std::declval(), std::declval())); private: // MEMBERS @@ -1037,8 +1038,8 @@ public: } return out; } - template - VlQueue unique(Func with_func) const { + template + VlQueue unique(T_Func with_func) const { VlQueue out; T_Key default_key; using WithType = decltype(with_func(m_map.begin()->first, m_map.begin()->second)); @@ -1065,8 +1066,8 @@ public: } return out; } - template - VlQueue unique_index(Func with_func) const { + template + VlQueue unique_index(T_Func with_func) const { VlQueue out; using WithType = decltype(with_func(m_map.begin()->first, m_map.begin()->second)); std::set saw; @@ -1080,22 +1081,22 @@ public: } return out; } - template - VlQueue find(Func with_func) const { + template + VlQueue find(T_Func with_func) const { VlQueue out; for (const auto& i : m_map) if (with_func(i.first, i.second)) out.push_back(i.second); return out; } - template - VlQueue find_index(Func with_func) const { + template + VlQueue find_index(T_Func with_func) const { VlQueue out; for (const auto& i : m_map) if (with_func(i.first, i.second)) out.push_back(i.first); return out; } - template - VlQueue find_first(Func with_func) const { + template + VlQueue find_first(T_Func with_func) const { const auto it = std::find_if(m_map.cbegin(), m_map.cend(), [=](const std::pair& i) { return with_func(i.first, i.second); @@ -1103,8 +1104,8 @@ public: if (it == m_map.end()) return VlQueue{}; return VlQueue::consV(it->second); } - template - VlQueue find_first_index(Func with_func) const { + template + VlQueue find_first_index(T_Func with_func) const { const auto it = std::find_if(m_map.cbegin(), m_map.cend(), [=](const std::pair& i) { return with_func(i.first, i.second); @@ -1112,16 +1113,16 @@ public: if (it == m_map.end()) return VlQueue{}; return VlQueue::consV(it->first); } - template - VlQueue find_last(Func with_func) const { + template + VlQueue find_last(T_Func with_func) const { const auto it = std::find_if( m_map.crbegin(), m_map.crend(), [=](const std::pair& i) { return with_func(i.first, i.second); }); if (it == m_map.rend()) return VlQueue{}; return VlQueue::consV(it->second); } - template - VlQueue find_last_index(Func with_func) const { + template + VlQueue find_last_index(T_Func with_func) const { const auto it = std::find_if( m_map.crbegin(), m_map.crend(), [=](const std::pair& i) { return with_func(i.first, i.second); }); @@ -1139,8 +1140,8 @@ public: }); return VlQueue::consV(it->second); } - template - VlQueue min(Func with_func) const { + template + VlQueue min(T_Func with_func) const { if (m_map.empty()) return VlQueue(); const auto it = std::min_element( m_map.cbegin(), m_map.cend(), @@ -1158,8 +1159,8 @@ public: }); return VlQueue::consV(it->second); } - template - VlQueue max(Func with_func) const { + template + VlQueue max(T_Func with_func) const { if (m_map.empty()) return VlQueue(); const auto it = std::max_element( m_map.cbegin(), m_map.cend(), @@ -1174,9 +1175,9 @@ public: for (const auto& i : m_map) out += i.second; return out; } - template - WithFuncReturnType r_sum(Func with_func) const { - WithFuncReturnType out = WithFuncReturnType(0); + template + WithFuncReturnType r_sum(T_Func with_func) const { + WithFuncReturnType out = WithFuncReturnType(0); for (const auto& i : m_map) out += with_func(i.first, i.second); return out; } @@ -1186,10 +1187,10 @@ public: for (const auto& i : m_map) out *= i.second; return out; } - template - WithFuncReturnType r_product(Func with_func) const { - if (m_map.empty()) return WithFuncReturnType(0); // The big three do it this way - WithFuncReturnType out = WithFuncReturnType(1); + template + WithFuncReturnType r_product(T_Func with_func) const { + if (m_map.empty()) return WithFuncReturnType(0); // The big three do it this way + WithFuncReturnType out = WithFuncReturnType(1); for (const auto& i : m_map) out *= with_func(i.first, i.second); return out; } @@ -1199,10 +1200,10 @@ public: for (const auto& i : m_map) out &= i.second; return out; } - template - WithFuncReturnType r_and(Func with_func) const { - if (m_map.empty()) return WithFuncReturnType(0); // The big three do it this way - WithFuncReturnType out = ~WithFuncReturnType(0); + template + WithFuncReturnType r_and(T_Func with_func) const { + if (m_map.empty()) return WithFuncReturnType(0); // The big three do it this way + WithFuncReturnType out = ~WithFuncReturnType(0); for (const auto& i : m_map) out &= with_func(i.first, i.second); return out; } @@ -1211,8 +1212,8 @@ public: for (const auto& i : m_map) out |= i.second; return out; } - template - T_Value r_or(Func with_func) const { + template + T_Value r_or(T_Func with_func) const { T_Value out = T_Value(0); for (const auto& i : m_map) out |= with_func(i.first, i.second); return out; @@ -1222,9 +1223,9 @@ public: for (const auto& i : m_map) out ^= i.second; return out; } - template - WithFuncReturnType r_xor(Func with_func) const { - WithFuncReturnType out = WithFuncReturnType(0); + template + WithFuncReturnType r_xor(T_Func with_func) const { + WithFuncReturnType out = WithFuncReturnType(0); for (const auto& i : m_map) out ^= with_func(i.first, i.second); return out; } @@ -1243,12 +1244,12 @@ public: } }; -template +template std::string VL_TO_STRING(const VlAssocArray& obj) { return obj.to_string(); } -template +template void VL_READMEM_N(bool hex, int bits, const std::string& filename, VlAssocArray& obj, QData start, QData end) VL_MT_SAFE { VlReadMem rmem{hex, bits, filename, start, end}; @@ -1264,7 +1265,7 @@ void VL_READMEM_N(bool hex, int bits, const std::string& filename, } } -template +template void VL_WRITEMEM_N(bool hex, int bits, const std::string& filename, const VlAssocArray& obj, QData start, QData end) VL_MT_SAFE { VlWriteMem wmem{hex, bits, filename, start, end}; @@ -1286,12 +1287,11 @@ void VL_WRITEMEM_N(bool hex, int bits, const std::string& filename, /// This class may get exposed to a Verilated Model's top I/O, if the top /// IO has an unpacked array. -template -struct VlUnpacked final { -private: +template +class VlUnpacked final { // TYPES using T_Key = IData; // Index type, for uniformity with other containers - using Unpacked = T_Value[T_Depth]; + using Unpacked = T_Value[N_Depth]; public: // MEMBERS @@ -1312,41 +1312,41 @@ public: WData* data() { return &m_storage[0]; } const WData* data() const { return &m_storage[0]; } - std::size_t size() const { return T_Depth; } + std::size_t size() const { return N_Depth; } // To fit C++14 - template + template int find_length(int dimension, std::false_type) const { return size(); } - template + template int find_length(int dimension, std::true_type) const { - if (dimension == CurrentDimension) { + if (dimension == N_CurrentDimension) { return size(); } else { - return m_storage[0].template find_length(dimension); + return m_storage[0].template find_length(dimension); } } - template + template int find_length(int dimension) const { - return find_length(dimension, std::is_class{}); + return find_length(dimension, std::is_class{}); } - template + template auto& find_element(const std::vector& indices, std::false_type) { - return m_storage[indices[CurrentDimension]]; + return m_storage[indices[N_CurrentDimension]]; } - template + template auto& find_element(const std::vector& indices, std::true_type) { - return m_storage[indices[CurrentDimension]].template find_element( - indices); + return m_storage[indices[N_CurrentDimension]] + .template find_element(indices); } - template + template auto& find_element(const std::vector& indices) { - return find_element(indices, std::is_class{}); + return find_element(indices, std::is_class{}); } T_Value& operator[](size_t index) { return m_storage[index]; } @@ -1354,15 +1354,15 @@ public: // *this != that, which might be used for change detection/trigger computation, but avoid // operator overloading in VlUnpacked for safety in other contexts. - bool neq(const VlUnpacked& that) const { return neq(*this, that); } + bool neq(const VlUnpacked& that) const { return neq(*this, that); } // Similar to 'neq' above, *this = that used for change detection - void assign(const VlUnpacked& that) { *this = that; } - bool operator==(const VlUnpacked& that) const { return !neq(that); } - bool operator!=(const VlUnpacked& that) const { return neq(that); } + void assign(const VlUnpacked& that) { *this = that; } + bool operator==(const VlUnpacked& that) const { return !neq(that); } + bool operator!=(const VlUnpacked& that) const { return neq(that); } // interface to C style arrays (used in ports), see issue #5125 - bool neq(const T_Value that[T_Depth]) const { return neq(*this, that); } - void assign(const T_Value that[T_Depth]) { std::copy_n(that, T_Depth, m_storage); } - void operator=(const T_Value that[T_Depth]) { assign(that); } + bool neq(const T_Value that[N_Depth]) const { return neq(*this, that); } + void assign(const T_Value that[N_Depth]) { std::copy_n(that, N_Depth, m_storage); } + void operator=(const T_Value that[N_Depth]) { assign(that); } // inside (set membership operator) bool inside(const T_Value& value) const { @@ -1370,8 +1370,8 @@ public: } void sort() { std::sort(std::begin(m_storage), std::end(m_storage)); } - template - void sort(Func with_func) { + template + void sort(T_Func with_func) { // with_func returns arbitrary type to use for the sort comparison std::sort(std::begin(m_storage), std::end(m_storage), [=](const T_Value& a, const T_Value& b) { @@ -1383,8 +1383,8 @@ public: void rsort() { std::sort(std::begin(m_storage), std::end(m_storage), std::greater()); } - template - void rsort(Func with_func) { + template + void rsort(T_Func with_func) { // with_func returns arbitrary type to use for the sort comparison // std::rbegin/std::rend not available until C++14, so using > below std::sort(std::begin(m_storage), std::end(m_storage), @@ -1407,8 +1407,8 @@ public: } return out; } - template - VlQueue unique(Func with_func) const { + template + VlQueue unique(T_Func with_func) const { VlQueue out; std::set saw; for (const auto& i : m_storage) { @@ -1435,8 +1435,8 @@ public: } return out; } - template - VlQueue unique_index(Func with_func) const { + template + VlQueue unique_index(T_Func with_func) const { VlQueue out; IData index = 0; std::set saw; @@ -1451,8 +1451,8 @@ public: } return out; } - template - VlQueue find(Func with_func) const { + template + VlQueue find(T_Func with_func) const { VlQueue out; IData index = 0; for (const auto& i : m_storage) { @@ -1461,8 +1461,8 @@ public: } return out; } - template - VlQueue find_index(Func with_func) const { + template + VlQueue find_index(T_Func with_func) const { VlQueue out; IData index = 0; for (const auto& i : m_storage) { @@ -1471,8 +1471,8 @@ public: } return out; } - template - VlQueue find_first(Func with_func) const { + template + VlQueue find_first(T_Func with_func) const { // Can't use std::find_if as need index number IData index = 0; for (const auto& i : m_storage) { @@ -1481,8 +1481,8 @@ public: } return VlQueue{}; } - template - VlQueue find_first_index(Func with_func) const { + template + VlQueue find_first_index(T_Func with_func) const { IData index = 0; for (const auto& i : m_storage) { if (with_func(index, i)) return VlQueue::consV(index); @@ -1490,16 +1490,16 @@ public: } return VlQueue{}; } - template - VlQueue find_last(Func with_func) const { - for (int i = T_Depth - 1; i >= 0; i--) { + template + VlQueue find_last(T_Func with_func) const { + for (int i = N_Depth - 1; i >= 0; i--) { if (with_func(i, m_storage[i])) return VlQueue::consV(m_storage[i]); } return VlQueue{}; } - template - VlQueue find_last_index(Func with_func) const { - for (int i = T_Depth - 1; i >= 0; i--) { + template + VlQueue find_last_index(T_Func with_func) const { + for (int i = N_Depth - 1; i >= 0; i--) { if (with_func(i, m_storage[i])) return VlQueue::consV(i); } return VlQueue{}; @@ -1510,8 +1510,8 @@ public: const auto it = std::min_element(std::begin(m_storage), std::end(m_storage)); return VlQueue::consV(*it); } - template - VlQueue min(Func with_func) const { + template + VlQueue min(T_Func with_func) const { const auto it = std::min_element(std::begin(m_storage), std::end(m_storage), [&with_func](const IData& a, const IData& b) { return with_func(0, a) < with_func(0, b); @@ -1522,8 +1522,8 @@ public: const auto it = std::max_element(std::begin(m_storage), std::end(m_storage)); return VlQueue::consV(*it); } - template - VlQueue max(Func with_func) const { + template + VlQueue max(T_Func with_func) const { const auto it = std::max_element(std::begin(m_storage), std::end(m_storage), [&with_func](const IData& a, const IData& b) { return with_func(0, a) < with_func(0, b); @@ -1535,7 +1535,7 @@ public: std::string to_string() const { std::string out = "'{"; std::string comma; - for (int i = 0; i < T_Depth; ++i) { + for (int i = 0; i < N_Depth; ++i) { out += comma + VL_TO_STRING(m_storage[i]); comma = ", "; } @@ -1543,18 +1543,18 @@ public: } private: - template - static bool neq(const VlUnpacked& a, const VlUnpacked& b) { - for (size_t i = 0; i < T_Dep; ++i) { + template + static bool neq(const VlUnpacked& a, const VlUnpacked& b) { + for (size_t i = 0; i < N_Dep; ++i) { // Recursive 'neq', in case T_Val is also a VlUnpacked<_, _> if (neq(a.m_storage[i], b.m_storage[i])) return true; } return false; } - template - static bool neq(const VlUnpacked& a, const T_Val b[T_Dep]) { - for (size_t i = 0; i < T_Dep; ++i) { + template + static bool neq(const VlUnpacked& a, const T_Val b[N_Dep]) { + for (size_t i = 0; i < N_Dep; ++i) { // Recursive 'neq', in case T_Val is also a VlUnpacked<_, _> if (neq(a.m_storage[i], b[i])) return true; } @@ -1568,25 +1568,25 @@ private: } }; -template -std::string VL_TO_STRING(const VlUnpacked& obj) { +template +std::string VL_TO_STRING(const VlUnpacked& obj) { return obj.to_string(); } //=================================================================== // Helper to apply the given indices to a target expression -template +template struct VlApplyIndices final { VL_ATTR_ALWINLINE static auto& apply(T_Target& target, const size_t* indicesp) { - return VlApplyIndices::apply( - target[indicesp[Curr]], indicesp); + return VlApplyIndices::apply( + target[indicesp[N_Curr]], indicesp); } }; -template -struct VlApplyIndices final { +template +struct VlApplyIndices final { VL_ATTR_ALWINLINE static T_Target& apply(T_Target& target, const size_t*) { return target; } }; @@ -1621,17 +1621,17 @@ template class VlNBACommitQueue; // Specialization for whole element updates only -template -class VlNBACommitQueue final { +template +class VlNBACommitQueue final { // TYPES struct Entry final { T_Element value; - size_t indices[T_Rank]; + size_t indices[N_Rank]; }; // STATE @@ -1643,8 +1643,8 @@ public: VL_UNCOPYABLE(VlNBACommitQueue); // METHODS - template - void enqueue(const T_Element& value, Args... indices) { + template + void enqueue(const T_Element& value, T_Args... indices) { m_pending.emplace_back(Entry{value, {indices...}}); } @@ -1654,20 +1654,20 @@ public: void commit(T_Commit& target) { if (m_pending.empty()) return; for (const Entry& entry : m_pending) { - VlApplyIndices<0, T_Rank, T_Commit>::apply(target, entry.indices) = entry.value; + VlApplyIndices<0, N_Rank, T_Commit>::apply(target, entry.indices) = entry.value; } m_pending.clear(); } }; // With partial element updates -template -class VlNBACommitQueue final { +template +class VlNBACommitQueue final { // TYPES struct Entry final { T_Element value; T_Element mask; - size_t indices[T_Rank]; + size_t indices[N_Rank]; }; // STATE @@ -1728,8 +1728,8 @@ public: VL_UNCOPYABLE(VlNBACommitQueue); // METHODS - template - void enqueue(const T_Element& value, const T_Element& mask, Args... indices) { + template + void enqueue(const T_Element& value, const T_Element& mask, T_Args... indices) { m_pending.emplace_back(Entry{value, mask, {indices...}}); } @@ -1739,7 +1739,7 @@ public: void commit(T_Commit& target) { if (m_pending.empty()) return; for (const Entry& entry : m_pending) { // - auto& ref = VlApplyIndices<0, T_Rank, T_Commit>::apply(target, entry.indices); + auto& ref = VlApplyIndices<0, N_Rank, T_Commit>::apply(target, entry.indices); // Maybe inefficient, but it works for now ... const auto oldValue = ref; ref = bOr(bAnd(entry.value, entry.mask), bAnd(oldValue, bNot(entry.mask))); @@ -1961,13 +1961,13 @@ public: }; }; -template -static inline bool VL_CAST_DYNAMIC(VlClassRef in, VlClassRef& outr) { +template +static inline bool VL_CAST_DYNAMIC(VlClassRef in, VlClassRef& outr) { if (!in) { outr = VlNull{}; return true; } - VlClassRef casted = in.template dynamicCast(); + VlClassRef casted = in.template dynamicCast(); if (VL_LIKELY(casted)) { outr = casted; return true; @@ -1976,8 +1976,8 @@ static inline bool VL_CAST_DYNAMIC(VlClassRef in, VlClassRef& outr) { } } -template -static inline bool VL_CAST_DYNAMIC(VlNull in, VlClassRef& outr) { +template +static inline bool VL_CAST_DYNAMIC(VlNull in, VlClassRef& outr) { outr = VlNull{}; return true; } @@ -2026,7 +2026,7 @@ public: #define VL_KEEP_THIS \ VlClassRef::type> __Vthisref { this } -template // T typically of type VlClassRef +template // T typically of type VlClassRef inline T VL_NULL_CHECK(T t, const char* filename, int linenum) { if (VL_UNLIKELY(!t)) Verilated::nullPointerError(filename, linenum); return t; diff --git a/include/verilated_vcd_c.cpp b/include/verilated_vcd_c.cpp index 9d45ae541..0a523ac0d 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-2024 by Wilson Snyder. This program is free software; you +// Copyright 2001-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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_c.h b/include/verilated_vcd_c.h index fffb4fab3..2ff710c9a 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-2024 by Wilson Snyder. This program is free software; you +// Copyright 2001-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 0e745e4e3..56c8d6c01 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-2024 by Wilson Snyder. This program is free software; you +// Copyright 2001-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 397a75db1..859be41f4 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-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2001-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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 ed2009ecf..6d3a3eaf7 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2009-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2009-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -268,6 +268,7 @@ protected: bool m_toplevel = false; const char* m_name; const char* m_fullname; + const char* m_defname; public: explicit VerilatedVpioScope(const VerilatedScope* scopep) @@ -275,6 +276,7 @@ public: m_fullname = m_scopep->name(); if (std::strncmp(m_fullname, "TOP.", 4) == 0) m_fullname += 4; m_name = m_scopep->identifier(); + m_defname = m_scopep->defname(); } ~VerilatedVpioScope() override = default; static VerilatedVpioScope* castp(vpiHandle h) { @@ -284,6 +286,7 @@ public: const VerilatedScope* scopep() const { return m_scopep; } const char* name() const override { return m_name; } const char* fullname() const override { return m_fullname; } + const char* defname() const override { return m_defname; } bool toplevel() const { return m_toplevel; } }; @@ -2415,9 +2418,11 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep, } else if (varp->vltype() == VLVT_WDATA) { const int words = VL_WORDS_I(varp->packed().elements()); if (VL_UNCOVERABLE(words >= VL_VALUE_STRING_MAX_WORDS)) { - VL_FATAL_MT(__FILE__, __LINE__, "", - "vpi_get_value with more than VL_VALUE_STRING_MAX_WORDS; increase and " - "recompile"); + VL_VPI_ERROR_( + __FILE__, __LINE__, + "vpi_get_value with more than VL_VALUE_STRING_MAX_WORDS; increase and " + "recompile"); + return; } const WDataInP datap = (reinterpret_cast(varDatap)); for (int i = 0; i < words; ++i) { diff --git a/include/verilated_vpi.h b/include/verilated_vpi.h index 51727cb01..9bea201b9 100644 --- a/include/verilated_vpi.h +++ b/include/verilated_vpi.h @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2009-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2009-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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/verilatedos.h b/include/verilatedos.h index 6cb83732f..4022ac2b0 100644 --- a/include/verilatedos.h +++ b/include/verilatedos.h @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/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,11 +67,21 @@ # endif # define VL_LIKELY(x) __builtin_expect(!!(x), 1) // Prefer over C++20 [[likely]] # define VL_UNLIKELY(x) __builtin_expect(!!(x), 0) // Prefer over C++20 [[unlikely]] -# define VL_UNREACHABLE __builtin_unreachable() // C++23 std::unreachable() # define VL_PREFETCH_RD(p) __builtin_prefetch((p), 0) # define VL_PREFETCH_RW(p) __builtin_prefetch((p), 1) #endif +#ifdef __cpp_lib_unreachable +/// Statement that may never be reached (for coverage etc) +# define VL_UNREACHABLE std::unreachable() // C++23 +#elif defined(__GNUC__) +# define VL_UNREACHABLE __builtin_unreachable() +#elif defined(_MSC_VER) // MSVC +# define VL_UNREACHABLE __assume(false) +#else +# define VL_UNREACHABLE +#endif + // Function acquires a capability/lock (-fthread-safety) #define VL_ACQUIRE(...) \ VL_CLANG_ATTR(annotate("ACQUIRE")) \ @@ -179,9 +189,6 @@ #endif /// Boolean expression never hit by users (branch coverage disabled) # define VL_UNCOVERABLE(x) VL_UNLIKELY(x) -#ifndef VL_UNREACHABLE -# define VL_UNREACHABLE ///< Statement that may never be reached (for coverage etc) -#endif #ifndef VL_PREFETCH_RD # define VL_PREFETCH_RD(p) ///< Prefetch pointer argument with read intent #endif @@ -694,7 +701,7 @@ reverse_wrapper reverse_view(const T& v) { // Object that is returned by this function is not considered // as MT_SAFE and any function call on this object still // needs to be `VL_MT_SAFE`. -template +template T const& as_const(T& v) VL_MT_SAFE { return v; } diff --git a/include/verilatedos_c.h b/include/verilatedos_c.h index 71f979529..be932befb 100644 --- a/include/verilatedos_c.h +++ b/include/verilatedos_c.h @@ -3,7 +3,7 @@ // // Code available from: https://verilator.org // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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/clang_check_attributes b/nodist/clang_check_attributes index 34714de5b..c60f09a08 100755 --- a/nodist/clang_check_attributes +++ b/nodist/clang_check_attributes @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # pylint: disable=C0114,C0115,C0116,C0209,C0302,R0902,R0911,R0912,R0914,R0915,E1101 # -# Copyright 2022-2024 by Wilson Snyder. Verilator is free software; you +# Copyright 2022-2025 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 @@ -38,6 +38,7 @@ else: def __getattr__(cls, name: str) -> clang.cindex.CursorKind: return getattr(clang.cindex.CursorKind, name) + # pylint: disable-next=invalid-enum-extension class CursorKind(clang.cindex.CursorKind, metaclass=CursorKindMeta): pass @@ -1079,7 +1080,7 @@ def main(): allow_abbrev=False, formatter_class=argparse.RawDescriptionHelpFormatter, description="""Check function annotations for correctness""", - epilog="""Copyright 2022-2024 by Wilson Snyder. Verilator is free software; + epilog="""Copyright 2022-2025 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""") @@ -1145,10 +1146,14 @@ def main(): for refid, file in enumerate(cmdline.file): filename = os.path.abspath(file) root = default_compilation_root - cxxflags = [] + cxxflags = common_cxxflags[:] if compdb: entry = compdb.getCompileCommands(filename) - entry_list = list(entry) + if entry is None: + print(f"%Error: reading compile commands failed: {filename}", file=sys.stderr) + entry_list = [] + else: + entry_list = list(entry) # Compilation database can contain multiple entries for single file, # e.g. when it has been updated by appending new entries. # Use last entry for the file, if it exists, as it is the newest one. @@ -1160,9 +1165,7 @@ def main(): # compiler executable name/path. CIndex (libclang) always # implicitly prepends executable name, so it shouldn't be passed # here. - cxxflags = common_cxxflags + entry_args[1:] - else: - cxxflags = common_cxxflags[:] + cxxflags.extend(entry_args[1:]) compile_command = CompileCommand(refid, filename, cxxflags, root) compile_commands_list.append(compile_command) diff --git a/nodist/code_coverage b/nodist/code_coverage index 2b9a59fb9..d99f1ec97 100755 --- a/nodist/code_coverage +++ b/nodist/code_coverage @@ -340,7 +340,7 @@ files. Run as: cd $VERILATOR_ROOT nodist/code_coverage""", - epilog="""Copyright 2019-2024 by Wilson Snyder. This program is free software; you + epilog="""Copyright 2019-2025 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it 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 0fd860a54..8f0c785d6 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-2024 by Wilson Snyder. This program is free software; you +# Copyright 2019-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/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,6 +40,7 @@ remove_gcda_regexp(r'test_regress/.*/(Vt_|Vtop_).*\.gcda') # Exclude line entirely, also excludes from function and branch coverage exclude_line_regexp(r'\bv3fatalSrc\b') exclude_line_regexp(r'\bfatalSrc\b') +exclude_line_regexp(r'\bVL_DELETED\b') exclude_line_regexp(r'\bVL_UNCOVERABLE\b') exclude_line_regexp(r'\bVL_UNREACHABLE\b') exclude_line_regexp(r'\bVL_FATAL') diff --git a/nodist/dot_importer b/nodist/dot_importer index 33dba831b..c8d335af5 100755 --- a/nodist/dot_importer +++ b/nodist/dot_importer @@ -79,7 +79,7 @@ parser = argparse.ArgumentParser( description="""dot_importer takes a graphvis .dot file and converts into .cpp file. This x.cpp file is then manually included in V3GraphTest.cpp to verify various xsub-algorithms.""", - epilog="""Copyright 2005-2024 by Wilson Snyder. This program is free software; you + epilog="""Copyright 2005-2025 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it 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/install_test b/nodist/install_test index 8534ebf4f..e345f9474 100755 --- a/nodist/install_test +++ b/nodist/install_test @@ -114,7 +114,7 @@ parser = argparse.ArgumentParser( description="""install_test performs several make-and-install iterations to verify the Verilator kit. It isn't part of the normal "make test" due to the number of builds required.""", - epilog="""Copyright 2009-2024 by Wilson Snyder. This program is free software; you + epilog="""Copyright 2009-2025 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it 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/lint_py_test_filter b/nodist/lint_py_test_filter index 813d11fc0..3cd1c78bf 100755 --- a/nodist/lint_py_test_filter +++ b/nodist/lint_py_test_filter @@ -41,7 +41,7 @@ parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, description="""lint_py_test_filter is used to filter pylint output for expected errors in Verilator test_regress/*.py tests.""", - epilog="""Copyright 2024-2024 by Wilson Snyder. This program is free software; you + epilog="""Copyright 2024-2025 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it 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/log_changes b/nodist/log_changes index a6ec47276..7865c393a 100755 --- a/nodist/log_changes +++ b/nodist/log_changes @@ -101,7 +101,7 @@ parser = argparse.ArgumentParser( allow_abbrev=False, prog="log_changes", description="Create example entries for 'Changes' from parsing 'git log'", - epilog="""Copyright 2019-2024 by Wilson Snyder. This program is free software; you + epilog="""Copyright 2019-2025 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it 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/.gdbinit b/src/.gdbinit index 1a6bac586..c340eb552 100644 --- a/src/.gdbinit +++ b/src/.gdbinit @@ -1,6 +1,6 @@ # DESCRIPTION: Verilator: GDB startup file with useful defines # -# Copyright 2012-2024 by Wilson Snyder. This program is free software; you +# Copyright 2012-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it 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/CMakeLists.txt b/src/CMakeLists.txt index e0b1792a6..480fdb52d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,7 +4,7 @@ # #***************************************************************************** # -# Copyright 2003-2024 by Wilson Snyder. This program is free software; you +# Copyright 2003-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/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,6 +95,7 @@ set(HEADERS V3Force.h V3Fork.h V3FunctionTraits.h + V3FuncOpt.h V3Gate.h V3Global.h V3Graph.h @@ -254,6 +255,7 @@ set(COMMON_SOURCES V3FileLine.cpp V3Force.cpp V3Fork.cpp + V3FuncOpt.cpp V3Gate.cpp V3Global.cpp V3Graph.cpp diff --git a/src/Makefile.in b/src/Makefile.in index 29172e1eb..daf96c38e 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -7,7 +7,7 @@ # #***************************************************************************** # -# Copyright 2003-2024 by Wilson Snyder. This program is free software; you +# Copyright 2003-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it 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 d29baa840..94e828efb 100644 --- a/src/Makefile_obj.in +++ b/src/Makefile_obj.in @@ -7,7 +7,7 @@ # #***************************************************************************** # -# Copyright 2003-2024 by Wilson Snyder. This program is free software; you +# Copyright 2003-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. @@ -142,6 +142,8 @@ BISONPRE = $(srcdir)/bisonpre FLEXFIX = $(srcdir)/flexfix VLCOVGEN = $(srcdir)/vlcovgen +# BISON_DEBUG = -Wcounterexamples + ###################################################################### # CCACHE flags (via environment as no command line option available) CCACHE_SLOPPINESS ?= pch_defines,time_macros @@ -204,6 +206,7 @@ RAW_OBJS_PCH_ASTMT = \ V3EmitCPch.o \ V3EmitV.o \ V3File.o \ + V3FuncOpt.o \ V3Global.o \ V3Hasher.o \ V3Number.o \ @@ -416,7 +419,7 @@ V3ParseBison.h: V3ParseBison.c # Have only one output file in this rule to prevent parallel make issues V3ParseBison.c: verilog.y $(BISONPRE) @echo "If you get errors from verilog.y below, try upgrading bison to version 1.875 or newer." - $(PYTHON3) $(BISONPRE) --yacc ${YACC} -d -v -o V3ParseBison.c $< + $(PYTHON3) $(BISONPRE) --yacc ${YACC} -d -v -o V3ParseBison.c $(BISON_DEBUG) $< V3Lexer_pregen.yy.cpp: verilog.l V3ParseBison.h $(HEADERS) ${LEX} --version diff --git a/src/V3Active.cpp b/src/V3Active.cpp index 6c6070574..f9c419314 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -230,7 +230,7 @@ class ActiveNamer final : public VNVisitor { void visit(AstNode* nodep) override { iterateChildren(nodep); } // Specialized below for the special sensitivity classes - template + template AstActive*& getSpecialActive(); public: @@ -246,17 +246,17 @@ public: } // Make a new AstActive sensitive to the given special sensitivity class and return it - template + template AstActive* makeSpecialActive(FileLine* const fl) { - AstSenTree* const senTreep = new AstSenTree{fl, new AstSenItem{fl, SenItemKind{}}}; + AstSenTree* const senTreep = new AstSenTree{fl, new AstSenItem{fl, T_SenItemKind{}}}; return makeActive(fl, senTreep); } // Return an AstActive sensitive to the given special sensitivity class (possibly pre-created) - template + template AstActive* getSpecialActive(FileLine* fl) { - AstActive*& cachep = getSpecialActive(); - if (!cachep) cachep = makeSpecialActive(fl); + AstActive*& cachep = getSpecialActive(); + if (!cachep) cachep = makeSpecialActive(fl); return cachep; } diff --git a/src/V3Active.h b/src/V3Active.h index 431a46e64..5f9795ff4 100644 --- a/src/V3Active.h +++ b/src/V3Active.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 2ebebdb12..91248a918 100644 --- a/src/V3ActiveTop.cpp +++ b/src/V3ActiveTop.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 979041114..81b14f664 100644 --- a/src/V3ActiveTop.h +++ b/src/V3ActiveTop.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 b90e1e106..85d65a561 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2024 by Wilson Snyder. This program is free software; you +// Copyright 2005-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,10 +510,8 @@ class AssertVisitor final : public VNVisitor { // Don't sample sensitivities void visit(AstSenItem* nodep) override { VL_RESTORER(m_inSampled); - { - m_inSampled = false; - iterateChildren(nodep); - } + m_inSampled = false; + iterateChildren(nodep); } //========== Statements @@ -691,12 +689,10 @@ class AssertVisitor final : public VNVisitor { VL_RESTORER(m_modp); VL_RESTORER(m_modPastNum); VL_RESTORER(m_modStrobeNum); - { - m_modp = nodep; - m_modPastNum = 0; - m_modStrobeNum = 0; - iterateChildren(nodep); - } + m_modp = nodep; + m_modPastNum = 0; + m_modStrobeNum = 0; + iterateChildren(nodep); } void visit(AstNodeProcedure* nodep) override { VL_RESTORER(m_procedurep); @@ -707,10 +703,8 @@ class AssertVisitor final : public VNVisitor { // This code is needed rather than a visitor in V3Begin, // because V3Assert is called before V3Begin VL_RESTORER(m_beginp); - { - m_beginp = nodep; - iterateChildren(nodep); - } + m_beginp = nodep; + iterateChildren(nodep); } void visit(AstNode* nodep) override { iterateChildren(nodep); } diff --git a/src/V3Assert.h b/src/V3Assert.h index 08f6bbb5e..0591a1eb0 100644 --- a/src/V3Assert.h +++ b/src/V3Assert.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2024 by Wilson Snyder. This program is free software; you +// Copyright 2005-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 d22004656..1df9aa2a7 100644 --- a/src/V3AssertPre.cpp +++ b/src/V3AssertPre.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2024 by Wilson Snyder. This program is free software; you +// Copyright 2005-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -45,7 +45,8 @@ private: AstNodeModule* m_modp = nullptr; // Current module AstClocking* m_clockingp = nullptr; // Current clocking block // Reset each module: - AstClocking* m_defaultClockingp = nullptr; // Default clocking for the current module + AstClocking* m_defaultClockingp = nullptr; // Default clocking for current module + AstDefaultDisable* m_defaultDisablep = nullptr; // Default disable for current module // Reset each assertion: AstSenItem* m_senip = nullptr; // Last sensitivity // Reset each always: @@ -522,6 +523,21 @@ private: VL_DO_DANGLING(pushDeletep(nodep), nodep); } + void visit(AstDefaultDisable* nodep) override { + // Done with these + VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); + } + void visit(AstInferredDisable* nodep) override { + AstNode* newp; + if (m_defaultDisablep) { + newp = m_defaultDisablep->condp()->cloneTreePure(true); + } else { + newp = new AstConst{nodep->fileline(), AstConst::BitFalse{}}; + } + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } + void visit(AstPropSpec* nodep) override { nodep = substitutePropertyCall(nodep); // No need to iterate the body, once replace will get iterated @@ -530,6 +546,9 @@ private: nodep->v3warn(E_UNSUPPORTED, "Unsupported: Only one PSL clock allowed per assertion"); // Block is the new expression to evaluate AstNodeExpr* blockp = VN_AS(nodep->propp()->unlinkFrBack(), NodeExpr); + if (!nodep->disablep() && m_defaultDisablep) { + nodep->disablep(m_defaultDisablep->condp()->cloneTreePure(true)); + } if (AstNodeExpr* const disablep = nodep->disablep()) { m_disablep = disablep->cloneTreePure(false); if (VN_IS(nodep->backp(), Cover)) { @@ -547,6 +566,7 @@ private: } void visit(AstNodeModule* nodep) override { VL_RESTORER(m_defaultClockingp); + VL_RESTORER(m_defaultDisablep); VL_RESTORER(m_modp); m_defaultClockingp = nullptr; nodep->foreach([&](AstClocking* const clockingp) { @@ -558,6 +578,14 @@ private: m_defaultClockingp = clockingp; } }); + m_defaultDisablep = nullptr; + nodep->foreach([&](AstDefaultDisable* const disablep) { + if (m_defaultDisablep) { + disablep->v3error("Only one 'default disable iff' allowed per module" + " (IEEE 1800-2023 16.15)"); + } + m_defaultDisablep = disablep; + }); m_modp = nodep; iterateChildren(nodep); } diff --git a/src/V3AssertPre.h b/src/V3AssertPre.h index 2a68a20d1..4b596395e 100644 --- a/src/V3AssertPre.h +++ b/src/V3AssertPre.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2024 by Wilson Snyder. This program is free software; you +// Copyright 2005-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 e0a15b40d..c7d926a3e 100644 --- a/src/V3Ast.cpp +++ b/src/V3Ast.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,12 +222,14 @@ string AstNode::vpiName(const string& namein) { // This is slightly different from prettyName, in that when we encounter escaped characters, // we change that identifier to an escaped identifier, wrapping it with '\' and ' ' // as specified in LRM 23.6 + string name = namein; + if (0 == namein.substr(0, 7).compare("__SYM__")) { name = namein.substr(7); } string pretty; - pretty.reserve(namein.length()); + pretty.reserve(name.length()); bool inEscapedIdent = false; int lastIdent = 0; - for (const char* pos = namein.c_str(); *pos;) { + for (const char* pos = name.c_str(); *pos;) { char specialChar = 0; if (pos[0] == '-' && pos[1] == '>') { // -> specialChar = '.'; @@ -1101,7 +1103,7 @@ bool AstNode::sameTreeIter(const AstNode* node1p, const AstNode* node2p, bool ig (!node1p->dtypep() && !node2p->dtypep()) || (node1p->dtypep() && node2p->dtypep()), node1p, "Comparison of a node with dtypep() with a node without dtypep()\n-node2=" << node2p); if (node1p->dtypep() && !node1p->dtypep()->similarDType(node2p->dtypep())) return false; - if (!node1p->same(node2p) || (gateOnly && !node1p->isGateOptimizable())) return false; + if (!node1p->sameNode(node2p) || (gateOnly && !node1p->isGateOptimizable())) return false; return (sameTreeIter(node1p->m_op1p, node2p->m_op1p, false, gateOnly) && sameTreeIter(node1p->m_op2p, node2p->m_op2p, false, gateOnly) && sameTreeIter(node1p->m_op3p, node2p->m_op3p, false, gateOnly) @@ -1286,10 +1288,17 @@ void AstNode::dumpPtrs(std::ostream& os) const { void AstNode::dumpTree(std::ostream& os, const string& indent, int maxDepth) const { static int s_debugFileline = v3Global.opt.debugSrcLevel("fileline"); // --debugi-fileline 9 os << indent << " " << this << '\n'; + if (VN_DELETED(this)) return; if (debug() > 8) { os << indent << " "; dumpPtrs(os); } + if (VN_DELETED(op1p()) || VN_DELETED(op2p()) // LCOV_EXCL_START + || VN_DELETED(op3p()) || VN_DELETED(op4p())) { + os << indent << "1/2/3/4: %E-0x1/deleted! node " << cvtToHex(this) + << endl; // endl intentional to do flush + return; + } // LCOV_EXCL_STOP if (s_debugFileline >= 9) os << fileline()->warnContextSecondary(); if (maxDepth == 1) { if (op1p() || op2p() || op3p() || op4p()) os << indent << "1: ...(maxDepth)\n"; @@ -1423,8 +1432,13 @@ string AstNode::instanceStr() const { return ""; } void AstNode::v3errorEnd(std::ostringstream& str) const VL_RELEASE(V3Error::s().m_mutex) { + // Don't look for instance name when warning is disabled. + // In case of large number of warnings, this can + // take significant amount of time + const string instanceStrExtra + = m_fileline->warnIsOff(V3Error::s().errorCode()) ? "" : instanceStr(); if (!m_fileline) { - V3Error::v3errorEnd(str, instanceStr()); + V3Error::v3errorEnd(str, instanceStrExtra); } else { std::ostringstream nsstr; nsstr << str.str(); @@ -1434,11 +1448,7 @@ void AstNode::v3errorEnd(std::ostringstream& str) const VL_RELEASE(V3Error::s(). const_cast(this)->dump(nsstr); nsstr << endl; } - // Don't look for instance name when warning is disabled. - // In case of large number of warnings, this can - // take significant amount of time - m_fileline->v3errorEnd( - nsstr, m_fileline->warnIsOff(V3Error::s().errorCode()) ? "" : instanceStr()); + m_fileline->v3errorEnd(nsstr, instanceStrExtra); } } void AstNode::v3errorEndFatal(std::ostringstream& str) const VL_RELEASE(V3Error::s().m_mutex) { diff --git a/src/V3Ast.h b/src/V3Ast.h index 5bd63e855..7d6ddf3dc 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -786,8 +786,8 @@ public: } string prettyName() const { return verilogKwd(); } bool isAny() const { return m_e != NONE; } - // Looks like inout - "ish" because not identical to being an INOUT - bool isInoutish() const { return m_e == INOUT; } + bool isInout() const { return m_e == INOUT; } + bool isInoutOrRef() const { return m_e == INOUT || m_e == REF || m_e == CONSTREF; } bool isInput() const { return m_e == INPUT; } bool isNonOutput() const { return m_e == INPUT || m_e == INOUT || m_e == REF || m_e == CONSTREF; @@ -904,7 +904,7 @@ public: TRIWIRE, TRI0, TRI1, - PORT, // Used in parser and V3Fork to recognize ports + PORT, // Used in parser to recognize ports BLOCKTEMP, MODULETEMP, STMTTEMP, @@ -1745,7 +1745,7 @@ public: explicit VNUser(void* p) { m_u.up = p; } ~VNUser() = default; // Casters - template + template typename std::enable_if::value, T>::type to() const VL_MT_SAFE { return reinterpret_cast(m_u.up); } @@ -2122,7 +2122,7 @@ protected: } // Use instead isSame(), this is for each Ast* class, and assumes node is of same type - virtual bool same(const AstNode*) const { return true; } + virtual bool sameNode(const AstNode*) const { return true; } public: // ACCESSORS @@ -2502,7 +2502,7 @@ public: virtual int instrCount() const { return 0; } // Iff node is identical to another node virtual bool isSame(const AstNode* samep) const { - return type() == samep->type() && same(samep); + return type() == samep->type() && sameNode(samep); } // Iff has a data type; dtype() must be non null virtual bool hasDType() const VL_MT_SAFE { return false; } @@ -2553,21 +2553,21 @@ protected: inline static bool privateTypeTest(const AstNode* nodep); // For internal use only. - template + template constexpr static bool uselessCast() VL_PURE { - using NonRef = typename std::remove_reference::type; + using NonRef = typename std::remove_reference::type; using NonPtr = typename std::remove_pointer::type; using NonCV = typename std::remove_cv::type; - return std::is_base_of::value; + return std::is_base_of::value; } // For internal use only. - template + template constexpr static bool impossibleCast() VL_PURE { - using NonRef = typename std::remove_reference::type; + using NonRef = typename std::remove_reference::type; using NonPtr = typename std::remove_pointer::type; using NonCV = typename std::remove_cv::type; - return !std::is_base_of::value; + return !std::is_base_of::value; } public: @@ -2655,12 +2655,12 @@ private: using ConstCorrectAstNode = typename std::conditional::value, const AstNode, AstNode>::type; - template - inline static void foreachImpl(ConstCorrectAstNode* nodep, const Callable& f, + template + inline static void foreachImpl(ConstCorrectAstNode* nodep, const T_Callable& f, bool visitNext); - template - inline static bool predicateImpl(ConstCorrectAstNode* nodep, const Callable& p); + template + inline static bool predicateImpl(ConstCorrectAstNode* nodep, const T_Callable& p); public: // Given a callable 'f' that takes a single argument of some AstNode subtype 'T_Node', traverse @@ -2670,46 +2670,48 @@ public: // handle a single (or a few) node types, as it's easier to write, but more importantly, the // dispatch to the callable in 'foreach' should be completely predictable by branch target // caches in modern CPUs, while it is basically unpredictable for VNVisitor. - template - void foreach(Callable&& f) { - using T_Node = typename FunctionArgNoPointerNoCV::type; - static_assert(vlstd::is_invocable::value + template + void foreach(T_Callable&& f) { + using T_Node = typename FunctionArgNoPointerNoCV::type; + static_assert(vlstd::is_invocable::value && std::is_base_of::value, - "Callable 'f' must have a signature compatible with 'void(T_Node*)', " + "T_Callable 'f' must have a signature compatible with 'void(T_Node*)', " "with 'T_Node' being a subtype of 'AstNode'"); foreachImpl(this, f, /* visitNext: */ false); } // Same as above, but for 'const' nodes - template - void foreach(Callable&& f) const { - using T_Node = typename FunctionArgNoPointerNoCV::type; - static_assert(vlstd::is_invocable::value - && std::is_base_of::value, - "Callable 'f' must have a signature compatible with 'void(const T_Node*)', " - "with 'T_Node' being a subtype of 'AstNode'"); + template + void foreach(T_Callable&& f) const { + using T_Node = typename FunctionArgNoPointerNoCV::type; + static_assert( + vlstd::is_invocable::value + && std::is_base_of::value, + "T_Callable 'f' must have a signature compatible with 'void(const T_Node*)', " + "with 'T_Node' being a subtype of 'AstNode'"); foreachImpl(this, f, /* visitNext: */ false); } // Same as 'foreach' but also traverses 'this->nextp()' transitively - template - void foreachAndNext(Callable&& f) { - using T_Node = typename FunctionArgNoPointerNoCV::type; - static_assert(vlstd::is_invocable::value + template + void foreachAndNext(T_Callable&& f) { + using T_Node = typename FunctionArgNoPointerNoCV::type; + static_assert(vlstd::is_invocable::value && std::is_base_of::value, - "Callable 'f' must have a signature compatible with 'void(T_Node*)', " + "T_Callable 'f' must have a signature compatible with 'void(T_Node*)', " "with 'T_Node' being a subtype of 'AstNode'"); foreachImpl(this, f, /* visitNext: */ true); } // Same as above, but for 'const' nodes - template - void foreachAndNext(Callable&& f) const { - using T_Node = typename FunctionArgNoPointerNoCV::type; - static_assert(vlstd::is_invocable::value - && std::is_base_of::value, - "Callable 'f' must have a signature compatible with 'void(const T_Node*)', " - "with 'T_Node' being a subtype of 'AstNode'"); + template + void foreachAndNext(T_Callable&& f) const { + using T_Node = typename FunctionArgNoPointerNoCV::type; + static_assert( + vlstd::is_invocable::value + && std::is_base_of::value, + "T_Callable 'f' must have a signature compatible with 'void(const T_Node*)', " + "with 'T_Node' being a subtype of 'AstNode'"); foreachImpl(this, f, /* visitNext: */ true); } @@ -2718,50 +2720,50 @@ public: // that satisfies the predicate 'p'. Returns false if no node of type 'T_Node' is present. // Traversal is performed in some arbitrary order and is terminated as soon as the result can // be determined. - template - bool exists(Callable&& p) { - using T_Node = typename FunctionArgNoPointerNoCV::type; - static_assert(vlstd::is_invocable_r::value + template + bool exists(T_Callable&& p) { + using T_Node = typename FunctionArgNoPointerNoCV::type; + static_assert(vlstd::is_invocable_r::value && std::is_base_of::value, "Predicate 'p' must have a signature compatible with 'bool(T_Node*)', " "with 'T_Node' being a subtype of 'AstNode'"); - return predicateImpl(this, p); + return predicateImpl(this, p); } // Same as above, but for 'const' nodes - template - bool exists(Callable&& p) const { - using T_Node = typename FunctionArgNoPointerNoCV::type; - static_assert(vlstd::is_invocable_r::value + template + bool exists(T_Callable&& p) const { + using T_Node = typename FunctionArgNoPointerNoCV::type; + static_assert(vlstd::is_invocable_r::value && std::is_base_of::value, "Predicate 'p' must have a signature compatible with 'bool(const T_Node*)', " "with 'T_Node' being a subtype of 'AstNode'"); - return predicateImpl(this, p); + return predicateImpl(this, p); } // Given a predicate 'p' that takes a single argument of some AstNode subtype 'T_Node', return // true if and only if all nodes of type 'T_Node' in the tree rooted at this node satisfy the // predicate 'p'. Returns true if no node of type 'T_Node' is present. Traversal is performed // in some arbitrary order and is terminated as soon as the result can be determined. - template - bool forall(Callable&& p) { - using T_Node = typename FunctionArgNoPointerNoCV::type; - static_assert(vlstd::is_invocable_r::value + template + bool forall(T_Callable&& p) { + using T_Node = typename FunctionArgNoPointerNoCV::type; + static_assert(vlstd::is_invocable_r::value && std::is_base_of::value, "Predicate 'p' must have a signature compatible with 'bool(T_Node*)', " "with 'T_Node' being a subtype of 'AstNode'"); - return predicateImpl(this, p); + return predicateImpl(this, p); } // Same as above, but for 'const' nodes - template - bool forall(Callable&& p) const { - using T_Node = typename FunctionArgNoPointerNoCV::type; - static_assert(vlstd::is_invocable_r::value + template + bool forall(T_Callable&& p) const { + using T_Node = typename FunctionArgNoPointerNoCV::type; + static_assert(vlstd::is_invocable_r::value && std::is_base_of::value, "Predicate 'p' must have a signature compatible with 'bool(const T_Node*)', " "with 'T_Node' being a subtype of 'AstNode'"); - return predicateImpl(this, p); + return predicateImpl(this, p); } int nodeCount() const { @@ -2834,8 +2836,8 @@ constexpr bool AstNode::isLeaf() { } // foreach implementation -template -void AstNode::foreachImpl(ConstCorrectAstNode* nodep, const Callable& f, bool visitNext) { +template +void AstNode::foreachImpl(ConstCorrectAstNode* nodep, const T_Callable& f, bool visitNext) { // Pre-order traversal implemented directly (without recursion) for speed reasons. The very // first iteration (the one that operates on the input nodep) is special, as we might or // might not need to enqueue nodep->nextp() depending on VisitNext, while in all other @@ -2915,8 +2917,8 @@ void AstNode::foreachImpl(ConstCorrectAstNode* nodep, const Callable& f, } // predicate implementation -template -bool AstNode::predicateImpl(ConstCorrectAstNode* nodep, const Callable& p) { +template +bool AstNode::predicateImpl(ConstCorrectAstNode* nodep, const T_Callable& p) { // Implementation similar to foreach, but abort traversal as soon as result is determined using T_Arg_NonConst = typename std::remove_const::type; using Node = ConstCorrectAstNode; @@ -2951,7 +2953,7 @@ bool AstNode::predicateImpl(ConstCorrectAstNode* nodep, const Callable& p // Type test this node if (AstNode::privateTypeTest(currp)) { // Call the client function - if (p(static_cast(currp)) != Default) return true; + if (p(static_cast(currp)) != N_Default) return true; // Short circuit if iterating leaf nodes if VL_CONSTEXPR_CXX17 (isLeaf()) return false; } @@ -2968,7 +2970,7 @@ bool AstNode::predicateImpl(ConstCorrectAstNode* nodep, const Callable& p }; // Visit the root node - if (visit(nodep)) return !Default; + if (visit(nodep)) return !N_Default; // Visit the rest of the tree while (VL_LIKELY(topp > basep)) { @@ -2985,15 +2987,17 @@ bool AstNode::predicateImpl(ConstCorrectAstNode* nodep, const Callable& p if (headp->nextp()) *topp++ = headp->nextp(); // Visit the head node - if (visit(headp)) return !Default; + if (visit(headp)) return !N_Default; } - return Default; + return N_Default; } inline std::ostream& operator<<(std::ostream& os, const AstNode* rhs) { - if (!rhs) { - os << "nullptr"; + if (!rhs) { // LCOV_EXCL_LINE + os << "nullptr"; // LCOV_EXCL_LINE + } else if (VN_DELETED(rhs)) { // LCOV_EXCL_LINE + os << "%E-0x1/deleted!"; // LCOV_EXCL_LINE } else { rhs->dump(os); } diff --git a/src/V3AstInlines.h b/src/V3AstInlines.h index 7e55bee79..90ebccfd8 100644 --- a/src/V3AstInlines.h +++ b/src/V3AstInlines.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -77,6 +77,12 @@ int AstNodeArrayDType::lo() const VL_MT_STABLE { return rangep()->loConst(); } int AstNodeArrayDType::elementsConst() const VL_MT_STABLE { return rangep()->elementsConst(); } VNumRange AstNodeArrayDType::declRange() const VL_MT_STABLE { return VNumRange{left(), right()}; } +AstFuncRef::AstFuncRef(FileLine* fl, AstFunc* taskp, AstNodeExpr* pinsp) + : ASTGEN_SUPER_FuncRef(fl, taskp->name(), pinsp) { + this->taskp(taskp); + dtypeFrom(taskp); +} + AstRange::AstRange(FileLine* fl, int left, int right) : ASTGEN_SUPER_Range(fl) { leftp(new AstConst{fl, static_cast(left)}); @@ -96,11 +102,6 @@ int AstRange::rightConst() const VL_MT_STABLE { return (constp ? constp->toSInt() : 0); } -int AstQueueDType::boundConst() const VL_MT_STABLE { - AstConst* const constp = VN_CAST(boundp(), Const); - return (constp ? constp->toSInt() : 0); -} - AstPin::AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp) : ASTGEN_SUPER_Pin(fl) , m_pinNum{pinNum} @@ -127,6 +128,17 @@ AstPackArrayDType::AstPackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* widthForce(width, width); } +int AstQueueDType::boundConst() const VL_MT_STABLE { + AstConst* const constp = VN_CAST(boundp(), Const); + return (constp ? constp->toSInt() : 0); +} + +AstTaskRef::AstTaskRef(FileLine* fl, AstTask* taskp, AstNodeExpr* pinsp) + : ASTGEN_SUPER_TaskRef(fl, taskp->name(), pinsp) { + this->taskp(taskp); + dtypeSetVoid(); +} + int AstBasicDType::hi() const { return (rangep() ? rangep()->hiConst() : m.m_nrange.hi()); } int AstBasicDType::lo() const { return (rangep() ? rangep()->loConst() : m.m_nrange.lo()); } int AstBasicDType::elements() const { @@ -172,7 +184,7 @@ AstVarRef::AstVarRef(FileLine* fl, AstVarScope* varscp, const VAccess& access) string AstVarRef::name() const { return varp() ? varp()->name() : ""; } -bool AstVarRef::same(const AstVarRef* samep) const { +bool AstVarRef::sameNode(const AstVarRef* samep) const { if (varScopep()) { return (varScopep() == samep->varScopep() && access() == samep->access()); } else { diff --git a/src/V3AstNodeDType.h b/src/V3AstNodeDType.h index 3dc9d7d2c..83b80717f 100644 --- a/src/V3AstNodeDType.h +++ b/src/V3AstNodeDType.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -48,6 +48,14 @@ protected: AstNodeDType(VNType t, FileLine* fl) : AstNode{t, fl} {} +private: + // METHODS + const AstNodeDType* skipRefIterp(bool skipConst, bool skipEnum) const VL_MT_STABLE; + +protected: + // METHODS + virtual bool similarDTypeNode(const AstNodeDType* samep) const = 0; + public: ASTGEN_MEMBERS_AstNodeDType; // ACCESSORS @@ -64,12 +72,30 @@ public: virtual bool isIntegralOrPacked() const { return !isCompound(); } // (Slow) recurse down to find basic data type virtual AstBasicDType* basicp() const VL_MT_STABLE = 0; - // recurses over typedefs/const/enum to next non-typeref type - virtual AstNodeDType* skipRefp() const VL_MT_STABLE = 0; - // recurses over typedefs to next non-typeref-or-const type - virtual AstNodeDType* skipRefToConstp() const = 0; - // recurses over typedefs/const to next non-typeref-or-enum/struct type - virtual AstNodeDType* skipRefToEnump() const = 0; + // (Slow) Recurse over MemberDType|ParamTypeDType|RefDType|ConstDType|EnumDType to other type + const AstNodeDType* skipRefp() const VL_MT_STABLE { return skipRefIterp(true, true); } + AstNodeDType* skipRefp() VL_MT_STABLE { + return const_cast( + static_cast(this)->skipRefIterp(true, true)); + } + // (Slow) Recurse over MemberDType|ParamTypeDType|RefDType|EnumDType to ConstDType + const AstNodeDType* skipRefToConstp() const { return skipRefIterp(false, true); } + AstNodeDType* skipRefToConstp() { + return const_cast( + static_cast(this)->skipRefIterp(false, true)); + } + // (Slow) Recurse over MemberDType|ParamTypeDType|RefDType|ConstDType to EnumDType + const AstNodeDType* skipRefToEnump() const { return skipRefIterp(true, false); } + AstNodeDType* skipRefToEnump() { + return const_cast( + static_cast(this)->skipRefIterp(true, false)); + } + // (Slow) Recurse over MemberDType|ParamTypeDType|RefDType to other type + const AstNodeDType* skipRefToNonRefp() const { return skipRefIterp(false, false); } + AstNodeDType* skipRefToNonRefp() { + return const_cast( + static_cast(this)->skipRefIterp(false, false)); + } // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) virtual int widthAlignBytes() const = 0; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... @@ -83,8 +109,16 @@ public: virtual AstNodeDType* virtRefDType2p() const { return nullptr; } // Iff has second dtype, set as generic node function virtual void virtRefDType2p(AstNodeDType* nodep) {} - // Assignable equivalence. Call skipRefp() on this and samep before calling - virtual bool similarDType(const AstNodeDType* samep) const = 0; + // Assignable equivalence. Calls skipRefToNonRefp() during comparisons. + bool similarDType(const AstNodeDType* samep) const { + const AstNodeDType* nodep = this; + nodep = nodep->skipRefToNonRefp(); + samep = samep->skipRefToNonRefp(); + if (nodep == samep) return true; + if (nodep->type() != samep->type()) return false; + return nodep->similarDTypeNode(samep); + } + // Iff has a non-null subDTypep(), as generic node function virtual AstNodeDType* subDTypep() const VL_MT_STABLE { return nullptr; } virtual bool isFourstate() const; @@ -155,16 +189,15 @@ public: BROKEN_RTN(!((m_refDTypep && !childDTypep()) || (!m_refDTypep && childDTypep()))); return nullptr; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstNodeArrayDType* const asamep = VN_DBG_AS(samep, NodeArrayDType); - return (hi() == asamep->hi() && subDTypep() == asamep->subDTypep() - && rangenp()->sameTree(asamep->rangenp())); + return hi() == asamep->hi() && rangenp()->sameTree(asamep->rangenp()) + && subDTypep() == asamep->subDTypep(); } // HashedDT doesn't recurse, so need to check children - bool similarDType(const AstNodeDType* samep) const override { - if (type() != samep->type()) return false; + bool similarDTypeNode(const AstNodeDType* samep) const override { const AstNodeArrayDType* const asamep = VN_DBG_AS(samep, NodeArrayDType); - return (hi() == asamep->hi() && rangenp()->sameTree(asamep->rangenp()) - && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp())); + return hi() == asamep->hi() && rangenp()->sameTree(asamep->rangenp()) + && subDTypep()->similarDType(asamep->subDTypep()); } AstNodeDType* getChildDTypep() const override { return childDTypep(); } AstNodeDType* subDTypep() const override VL_MT_STABLE { @@ -177,9 +210,6 @@ public: AstBasicDType* basicp() const override VL_MT_STABLE { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type - AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; } - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } int widthTotalBytes() const override { return elementsConst() * subDTypep()->widthTotalBytes(); @@ -232,14 +262,11 @@ public: : VN_AS(findBitRangeDType(VNumRange{width() - 1, 0}, width(), numeric()), BasicDType)); } - AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; } - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) int widthAlignBytes() const override; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... int widthTotalBytes() const override; - bool similarDType(const AstNodeDType* samep) const override { + bool similarDTypeNode(const AstNodeDType* samep) const override { return this == samep; // We don't compare members, require exact equivalence } string name() const override VL_MT_STABLE { return m_name; } @@ -311,17 +338,16 @@ public: BROKEN_RTN(!((m_keyDTypep && !childDTypep()) || (!m_keyDTypep && childDTypep()))); return nullptr; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstAssocArrayDType* const asamep = VN_DBG_AS(samep, AssocArrayDType); if (!asamep->subDTypep()) return false; if (!asamep->keyDTypep()) return false; return (subDTypep() == asamep->subDTypep() && keyDTypep() == asamep->keyDTypep()); } - bool similarDType(const AstNodeDType* samep) const override { - if (type() != samep->type()) return false; + bool similarDTypeNode(const AstNodeDType* samep) const override { const AstAssocArrayDType* const asamep = VN_DBG_AS(samep, AssocArrayDType); - return asamep->subDTypep() - && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); + return asamep->subDTypep() && subDTypep()->similarDType(asamep->subDTypep()) + && asamep->keyDTypep() && keyDTypep()->similarDType(asamep->keyDTypep()); } string prettyDTypeName(bool full) const override; void dumpSmall(std::ostream& str) const override; @@ -342,9 +368,6 @@ public: void keyDTypep(AstNodeDType* nodep) { m_keyDTypep = nodep; } // METHODS AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; } - AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; } - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } bool isCompound() const override { return true; } @@ -392,10 +415,8 @@ public: void dump(std::ostream& str) const override; void dumpJson(std::ostream& str) const override; // width/widthMin/numeric compared elsewhere - bool same(const AstNode* samep) const override; - bool similarDType(const AstNodeDType* samep) const override { - return type() == samep->type() && same(samep); - } + bool sameNode(const AstNode* samep) const override; + bool similarDTypeNode(const AstNodeDType* samep) const override { return sameNode(samep); } string name() const override VL_MT_STABLE { return m.m_keyword.ascii(); } string prettyDTypeName(bool full) const override; const char* broken() const override { @@ -412,9 +433,6 @@ public: } // METHODS AstBasicDType* basicp() const override VL_MT_STABLE { return (AstBasicDType*)this; } - AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; } - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) int widthAlignBytes() const override; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... @@ -473,7 +491,7 @@ class AstBracketArrayDType final : public AstNodeDType { // Associative/Queue/Normal array data type, ie "[dtype_or_expr]" // only for early parsing then becomes another data type // @astgen op1 := childDTypep : Optional[AstNodeDType] // moved to refDTypep() in V3Width - // @astgen op2 := elementsp : AstNode // ??? key dtype ??? + // @astgen op2 := elementsp : AstNode // Number of elements in array public: AstBracketArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* childDTypep, AstNode* elementsp) @@ -482,16 +500,13 @@ public: this->elementsp(elementsp); } ASTGEN_MEMBERS_AstBracketArrayDType; - bool similarDType(const AstNodeDType* samep) const override { return same(samep); } + bool similarDTypeNode(const AstNodeDType* samep) const override { return this == samep; } AstNodeDType* subDTypep() const override VL_MT_STABLE { return childDTypep(); } // METHODS // Will be removed in V3Width, which relies on this // being a child not a dtype pointed node bool maybePointedTo() const override VL_MT_SAFE { return false; } AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; } - AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; } - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } int widthAlignBytes() const override { V3ERROR_NA_RETURN(0); } int widthTotalBytes() const override { V3ERROR_NA_RETURN(0); } bool isCompound() const override { return true; } @@ -508,18 +523,15 @@ public: public: ASTGEN_MEMBERS_AstCDType; - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstCDType* const asamep = VN_DBG_AS(samep, CDType); return m_name == asamep->m_name; } - bool similarDType(const AstNodeDType* samep) const override { return same(samep); } + bool similarDTypeNode(const AstNodeDType* samep) const override { return sameNode(samep); } string name() const override VL_MT_STABLE { return m_name; } string prettyDTypeName(bool) const override { return m_name; } // METHODS AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; } - AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; } - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } int widthAlignBytes() const override { return 8; } // Assume int widthTotalBytes() const override { return 8; } // Assume bool isCompound() const override { return true; } @@ -551,22 +563,17 @@ public: } ASTGEN_MEMBERS_AstClassRefDType; // METHODS - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstClassRefDType* const asamep = VN_DBG_AS(samep, ClassRefDType); return (m_classp == asamep->m_classp && m_classOrPackagep == asamep->m_classOrPackagep); } - bool similarDType(const AstNodeDType* samep) const override { - return this == samep || (type() == samep->type() && same(samep)); - } + bool similarDTypeNode(const AstNodeDType* samep) const override { return sameNode(samep); } void dump(std::ostream& str = std::cout) const override; void dumpJson(std::ostream& str = std::cout) const override; void dumpSmall(std::ostream& str) const override; string prettyDTypeName(bool full) const override; string name() const override VL_MT_STABLE; AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; } - AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; } - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } int widthAlignBytes() const override { return 0; } int widthTotalBytes() const override { return 0; } AstNodeDType* virtRefDTypep() const override { return nullptr; } @@ -598,11 +605,11 @@ public: BROKEN_RTN(!((m_refDTypep && !childDTypep()) || (!m_refDTypep && childDTypep()))); return nullptr; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstConstDType* const sp = VN_DBG_AS(samep, ConstDType); return (m_refDTypep == sp->m_refDTypep); } - bool similarDType(const AstNodeDType* samep) const override { + bool similarDTypeNode(const AstNodeDType* samep) const override { return skipRefp()->similarDType(samep->skipRefp()); } AstNodeDType* getChildDTypep() const override { return childDTypep(); } @@ -614,9 +621,6 @@ public: void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } // METHODS AstBasicDType* basicp() const override VL_MT_STABLE { return subDTypep()->basicp(); } - AstNodeDType* skipRefp() const override VL_MT_STABLE { return subDTypep()->skipRefp(); } - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } bool isCompound() const override { @@ -638,14 +642,8 @@ public: AstNodeDType* subDTypep() const override VL_MT_STABLE { return nullptr; } AstNodeDType* virtRefDTypep() const override { return nullptr; } void virtRefDTypep(AstNodeDType* nodep) override {} - bool similarDType(const AstNodeDType* samep) const override { return this == samep; } + bool similarDTypeNode(const AstNodeDType* samep) const override { return this == samep; } AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; } - // cppcheck-suppress csyleCast - AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; } - // cppcheck-suppress csyleCast - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - // cppcheck-suppress csyleCast - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } int widthAlignBytes() const override { return 1; } int widthTotalBytes() const override { return 1; } bool isCompound() const override { return false; } @@ -677,13 +675,11 @@ public: , m_uniqueNum(uniqueNumInc()) {} ASTGEN_MEMBERS_AstDefImplicitDType; int uniqueNum() const { return m_uniqueNum; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstDefImplicitDType* const sp = VN_DBG_AS(samep, DefImplicitDType); return uniqueNum() == sp->uniqueNum(); } - bool similarDType(const AstNodeDType* samep) const override { - return type() == samep->type() && same(samep); - } + bool similarDTypeNode(const AstNodeDType* samep) const override { return sameNode(samep); } AstNodeDType* getChildDTypep() const override { return childDTypep(); } AstNodeDType* subDTypep() const override VL_MT_STABLE { return dtypep() ? dtypep() : childDTypep(); @@ -693,9 +689,6 @@ public: // op1 = Range of variable AstNodeDType* dtypeSkipRefp() const { return dtypep()->skipRefp(); } AstBasicDType* basicp() const override VL_MT_STABLE { return subDTypep()->basicp(); } - AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; } - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); } int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); } string name() const override VL_MT_STABLE { return m_name; } @@ -724,16 +717,14 @@ public: BROKEN_RTN(!((m_refDTypep && !childDTypep()) || (!m_refDTypep && childDTypep()))); return nullptr; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstDynArrayDType* const asamep = VN_DBG_AS(samep, DynArrayDType); if (!asamep->subDTypep()) return false; return subDTypep() == asamep->subDTypep(); } - bool similarDType(const AstNodeDType* samep) const override { - if (type() != samep->type()) return false; + bool similarDTypeNode(const AstNodeDType* samep) const override { const AstDynArrayDType* const asamep = VN_DBG_AS(samep, DynArrayDType); - return asamep->subDTypep() - && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); + return asamep->subDTypep() && subDTypep()->similarDType(asamep->subDTypep()); } string prettyDTypeName(bool full) const override; void dumpSmall(std::ostream& str) const override; @@ -746,9 +737,6 @@ public: void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } // METHODS AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; } - AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; } - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } bool isCompound() const override { return true; } @@ -768,14 +756,8 @@ public: AstNodeDType* subDTypep() const override VL_MT_STABLE { return nullptr; } AstNodeDType* virtRefDTypep() const override { return nullptr; } void virtRefDTypep(AstNodeDType* nodep) override {} - bool similarDType(const AstNodeDType* samep) const override { return this == samep; } + bool similarDTypeNode(const AstNodeDType* samep) const override { return this == samep; } AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; } - // cppcheck-suppress csyleCast - AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; } - // cppcheck-suppress csyleCast - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - // cppcheck-suppress csyleCast - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } int widthAlignBytes() const override { return 1; } int widthTotalBytes() const override { return 1; } bool isCompound() const override { return false; } @@ -812,11 +794,11 @@ public: const char* broken() const override; int uniqueNum() const { return m_uniqueNum; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstEnumDType* const sp = VN_DBG_AS(samep, EnumDType); return uniqueNum() == sp->uniqueNum(); } - bool similarDType(const AstNodeDType* samep) const override { return this == samep; } + bool similarDTypeNode(const AstNodeDType* samep) const override { return sameNode(samep); } AstNodeDType* getChildDTypep() const override { return childDTypep(); } AstNodeDType* subDTypep() const override VL_MT_STABLE { return m_refDTypep ? m_refDTypep : childDTypep(); @@ -832,10 +814,6 @@ public: string prettyDTypeName(bool full) const override; // METHODS AstBasicDType* basicp() const override VL_MT_STABLE { return subDTypep()->basicp(); } - AstNodeDType* skipRefp() const override VL_MT_STABLE { return subDTypep()->skipRefp(); } - AstNodeDType* skipRefToConstp() const override { return subDTypep()->skipRefToConstp(); } - // cppcheck-suppress csyleCast - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } size_t itemCount() const { @@ -855,11 +833,12 @@ class AstIfaceRefDType final : public AstNodeDType { // @astgen ptr := m_ifacep : Optional[AstIface] // Interface; cellp() should override // @astgen ptr := m_cellp : Optional[AstCell] // When exact parent cell known; not a guess // @astgen ptr := m_modportp : Optional[AstModport] // nullptr = unlinked or no modport - bool m_virtual = false; // True if virtual interface FileLine* m_modportFileline; // Where modport token was string m_cellName; // "" = no cell, such as when connects to 'input' iface string m_ifaceName; // Interface name string m_modportName; // "" = no modport + bool m_portDecl = false; // Interface_port_declaration + bool m_virtual = false; // True if virtual interface public: AstIfaceRefDType(FileLine* fl, const string& cellName, const string& ifaceName) : ASTGEN_SUPER_IfaceRefDType(fl) @@ -889,12 +868,11 @@ public: void dumpJson(std::ostream& str = std::cout) const override; void dumpSmall(std::ostream& str) const override; AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; } - AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; } - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } - bool similarDType(const AstNodeDType* samep) const override { return this == samep; } + bool similarDTypeNode(const AstNodeDType* samep) const override { return this == samep; } int widthAlignBytes() const override { return 0; } int widthTotalBytes() const override { return 0; } + bool isPortDecl() const { return m_portDecl; } + void isPortDecl(bool flag) { m_portDecl = flag; } bool isVirtual() const { return m_virtual; } void isVirtual(bool flag) { m_virtual = flag; @@ -904,6 +882,7 @@ public: string cellName() const { return m_cellName; } void cellName(const string& name) { m_cellName = name; } string ifaceName() const { return m_ifaceName; } + string ifaceNameQ() const { return "'" + prettyName(ifaceName()) + "'"; } void ifaceName(const string& name) { m_ifaceName = name; } string modportName() const { return m_modportName; } AstIface* ifaceViaCellp() const; // Use cellp or ifacep @@ -951,23 +930,20 @@ public: bool hasDType() const override VL_MT_SAFE { return true; } bool maybePointedTo() const override VL_MT_SAFE { return true; } AstNodeDType* getChildDTypep() const override { return childDTypep(); } - AstNodeUOrStructDType* getChildStructp() const; + AstNodeUOrStructDType* getChildStructp(); AstNodeDType* subDTypep() const override VL_MT_STABLE { 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); } - bool similarDType(const AstNodeDType* samep) const override { return this == samep; } + bool similarDTypeNode(const AstNodeDType* samep) const override { return this == samep; } // // (Slow) recurse down to find basic data type (Note don't need virtual - // AstVar isn't a NodeDType) AstBasicDType* basicp() const override VL_MT_STABLE { return subDTypep()->basicp(); } // op1 = Range of variable (Note don't need virtual - AstVar isn't a NodeDType) AstNodeDType* dtypeSkipRefp() const { return subDTypep()->skipRefp(); } - AstNodeDType* skipRefp() const override VL_MT_STABLE { return subDTypep()->skipRefp(); } - AstNodeDType* skipRefToConstp() const override { return subDTypep()->skipRefToConstp(); } - AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this) int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,... @@ -998,11 +974,12 @@ public: AstNodeDType* subDTypep() const override VL_MT_STABLE { return m_subDTypep; } bool partial() const { return m_partial; } - bool similarDType(const AstNodeDType* samep) const override { return this == samep; } + bool sameNode(const AstNode* samep) const override { + const AstNBACommitQueueDType* const asamep = VN_DBG_AS(samep, NBACommitQueueDType); + return m_partial == asamep->m_partial; + } + bool similarDTypeNode(const AstNodeDType* samep) const override { return this == samep; } AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; } - AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; } - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } int widthAlignBytes() const override { return 1; } int widthTotalBytes() const override { return 24; } bool isCompound() const override { return true; } @@ -1030,13 +1007,9 @@ public: return dtypep() ? dtypep() : childDTypep(); } AstBasicDType* basicp() const override VL_MT_STABLE { return subDTypep()->basicp(); } - AstNodeDType* skipRefp() const override VL_MT_STABLE { return subDTypep()->skipRefp(); } - AstNodeDType* skipRefToConstp() const override { return subDTypep()->skipRefToConstp(); } - AstNodeDType* skipRefToEnump() const override { return subDTypep()->skipRefToEnump(); } - bool similarDType(const AstNodeDType* samep) const override { - if (type() != samep->type()) return false; + bool similarDTypeNode(const AstNodeDType* samep) const override { const AstParamTypeDType* const sp = VN_DBG_AS(samep, ParamTypeDType); - return this->subDTypep()->skipRefp()->similarDType(sp->subDTypep()->skipRefp()); + return this->subDTypep()->similarDType(sp->subDTypep()); } int widthAlignBytes() const override { return dtypep()->widthAlignBytes(); } int widthTotalBytes() const override { return dtypep()->widthTotalBytes(); } @@ -1063,13 +1036,8 @@ public: ASTGEN_MEMBERS_AstParseTypeDType; AstNodeDType* dtypep() const VL_MT_STABLE { return nullptr; } // METHODS - bool similarDType(const AstNodeDType* samep) const override { return this == samep; } + bool similarDTypeNode(const AstNodeDType* samep) const override { return this == samep; } AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; } - AstNodeDType* skipRefp() const override VL_MT_STABLE { return nullptr; } - // cppcheck-suppress csyleCast - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - // cppcheck-suppress csyleCast - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } int widthAlignBytes() const override { return 0; } int widthTotalBytes() const override { return 0; } bool isCompound() const override { @@ -1102,16 +1070,14 @@ public: BROKEN_RTN(!((m_refDTypep && !childDTypep()) || (!m_refDTypep && childDTypep()))); return nullptr; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstQueueDType* const asamep = VN_DBG_AS(samep, QueueDType); if (!asamep->subDTypep()) return false; return (subDTypep() == asamep->subDTypep()); } - bool similarDType(const AstNodeDType* samep) const override { - if (type() != samep->type()) return false; + bool similarDTypeNode(const AstNodeDType* samep) const override { const AstQueueDType* const asamep = VN_DBG_AS(samep, QueueDType); - return asamep->subDTypep() - && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); + return asamep->subDTypep() && subDTypep()->similarDType(asamep->subDTypep()); } void dumpSmall(std::ostream& str) const override; string prettyDTypeName(bool full) const override; @@ -1125,12 +1091,6 @@ public: void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } // METHODS AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; } - // cppcheck-suppress csyleCast - AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; } - // cppcheck-suppress csyleCast - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - // cppcheck-suppress csyleCast - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } bool isCompound() const override { return true; } @@ -1165,13 +1125,13 @@ public: } ASTGEN_MEMBERS_AstRefDType; // METHODS - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstRefDType* const asamep = VN_DBG_AS(samep, RefDType); return (m_typedefp == asamep->m_typedefp && m_refDTypep == asamep->m_refDTypep && m_name == asamep->m_name && m_classOrPackagep == asamep->m_classOrPackagep); } - bool similarDType(const AstNodeDType* samep) const override { - return skipRefp()->similarDType(samep->skipRefp()); + bool similarDTypeNode(const AstNodeDType* samep) const override { + return subDTypep()->similarDType(samep->subDTypep()); } void dump(std::ostream& str = std::cout) const override; void dumpJson(std::ostream& str = std::cout) const override; @@ -1184,31 +1144,6 @@ public: return subDTypep() ? subDTypep()->basicp() : nullptr; } AstNodeDType* subDTypep() const override VL_MT_STABLE; - AstNodeDType* skipRefp() const override VL_MT_STABLE { - // Skip past both the Ref and the Typedef - if (subDTypep()) { - return subDTypep()->skipRefp(); - } else { - v3fatalSrc("Typedef not linked"); - return nullptr; - } - } - AstNodeDType* skipRefToConstp() const override { - if (subDTypep()) { - return subDTypep()->skipRefToConstp(); - } else { - v3fatalSrc("Typedef not linked"); - return nullptr; - } - } - AstNodeDType* skipRefToEnump() const override { - if (subDTypep()) { - return subDTypep()->skipRefToEnump(); - } else { - v3fatalSrc("Typedef not linked"); - return nullptr; - } - } int widthAlignBytes() const override { return dtypeSkipRefp()->widthAlignBytes(); } int widthTotalBytes() const override { return dtypeSkipRefp()->widthTotalBytes(); } void name(const string& flag) override { m_name = flag; } @@ -1241,16 +1176,14 @@ public: BROKEN_RTN(!((m_refDTypep && !childDTypep()) || (!m_refDTypep && childDTypep()))); return nullptr; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstSampleQueueDType* const asamep = VN_DBG_AS(samep, SampleQueueDType); if (!asamep->subDTypep()) return false; return (subDTypep() == asamep->subDTypep()); } - bool similarDType(const AstNodeDType* samep) const override { - if (type() != samep->type()) return false; + bool similarDTypeNode(const AstNodeDType* samep) const override { const AstSampleQueueDType* const asamep = VN_DBG_AS(samep, SampleQueueDType); - return asamep->subDTypep() - && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); + return asamep->subDTypep() && subDTypep()->similarDType(asamep->subDTypep()); } void dumpSmall(std::ostream& str) const override; AstNodeDType* getChildDTypep() const override { return childDTypep(); } @@ -1263,9 +1196,6 @@ public: void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } // METHODS AstBasicDType* basicp() const override VL_MT_STABLE { return subDTypep()->basicp(); } - AstNodeDType* skipRefp() const override VL_MT_STABLE { 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; } @@ -1286,14 +1216,8 @@ public: AstNodeDType* subDTypep() const override VL_MT_STABLE { return nullptr; } AstNodeDType* virtRefDTypep() const override { return nullptr; } void virtRefDTypep(AstNodeDType* nodep) override {} - bool similarDType(const AstNodeDType* samep) const override { return this == samep; } + bool similarDTypeNode(const AstNodeDType* samep) const override { return this == samep; } AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; } - // cppcheck-suppress csyleCast - AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; } - // cppcheck-suppress csyleCast - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - // cppcheck-suppress csyleCast - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } int widthAlignBytes() const override { return 1; } int widthTotalBytes() const override { return 1; } bool isCompound() const override { return false; } @@ -1320,8 +1244,8 @@ public: BROKEN_RTN(!((m_refDTypep && !childDTypep()) || (!m_refDTypep && childDTypep()))); return nullptr; } - bool same(const AstNode* samep) const override; - bool similarDType(const AstNodeDType* samep) const override; + bool sameNode(const AstNode* samep) const override; + bool similarDTypeNode(const AstNodeDType* samep) const override; void dumpSmall(std::ostream& str) const override; AstNodeDType* getChildDTypep() const override { return childDTypep(); } AstNodeDType* subDTypep() const override VL_MT_STABLE { @@ -1332,9 +1256,6 @@ public: void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } // METHODS AstBasicDType* basicp() const override VL_MT_STABLE { return subDTypep()->basicp(); } - AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; } - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); } int widthTotalBytes() const override { return subDTypep()->widthTotalBytes(); } bool isCompound() const override { return true; } @@ -1354,14 +1275,8 @@ public: AstNodeDType* subDTypep() const override VL_MT_STABLE { return nullptr; } AstNodeDType* virtRefDTypep() const override { return nullptr; } void virtRefDTypep(AstNodeDType* nodep) override {} - bool similarDType(const AstNodeDType* samep) const override { return this == samep; } + bool similarDTypeNode(const AstNodeDType* samep) const override { return this == samep; } AstBasicDType* basicp() const override VL_MT_STABLE { return nullptr; } - // cppcheck-suppress csyleCast - AstNodeDType* skipRefp() const override VL_MT_STABLE { return (AstNodeDType*)this; } - // cppcheck-suppress csyleCast - AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; } - // cppcheck-suppress csyleCast - AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; } int widthAlignBytes() const override { return 1; } int widthTotalBytes() const override { return 1; } bool isCompound() const override { return false; } @@ -1383,8 +1298,8 @@ public: BROKEN_RTN(!((m_refDTypep && !childDTypep()) || (!m_refDTypep && childDTypep()))); return nullptr; } - bool same(const AstNode* samep) const override; - bool similarDType(const AstNodeDType* samep) const override; + bool sameNode(const AstNode* samep) const override; + bool similarDTypeNode(const AstNodeDType* samep) const override; void dumpSmall(std::ostream& str) const override; AstNodeDType* getChildDTypep() const override { return childDTypep(); } AstNodeDType* subDTypep() const override VL_MT_STABLE { @@ -1395,9 +1310,6 @@ public: void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); } // METHODS AstBasicDType* basicp() const override VL_MT_STABLE { return subDTypep()->basicp(); } - AstNodeDType* skipRefp() const override VL_MT_STABLE { 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; } @@ -1438,7 +1350,7 @@ public: } ASTGEN_MEMBERS_AstUnpackArrayDType; string prettyDTypeName(bool full) const override; - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstUnpackArrayDType* const sp = VN_DBG_AS(samep, UnpackArrayDType); return m_isCompound == sp->m_isCompound; } diff --git a/src/V3AstNodeExpr.h b/src/V3AstNodeExpr.h index a883caa2f..13382f64b 100644 --- a/src/V3AstNodeExpr.h +++ b/src/V3AstNodeExpr.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/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 @@ -99,7 +99,7 @@ public: virtual bool signedFlavor() const { return false; } virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors? int instrCount() const override { return widthInstrs(); } - bool same(const AstNode*) const override { return true; } + bool sameNode(const AstNode*) const override { return true; } bool isPure() override; const char* broken() const override; @@ -203,7 +203,7 @@ public: void dump(std::ostream& str = std::cout) const override; void dumpJson(std::ostream& str = std::cout) const override; int instrCount() const override { return INSTR_COUNT_CALL; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstNodeCCall* const asamep = VN_DBG_AS(samep, NodeCCall); return (funcp() == asamep->funcp() && argTypes() == asamep->argTypes()); } @@ -296,7 +296,7 @@ protected: public: ASTGEN_MEMBERS_AstNodePreSel; // METHODS - bool same(const AstNode*) const override { return true; } + bool sameNode(const AstNode*) const override { return true; } string emitVerilog() final override { V3ERROR_NA_RETURN(""); } string emitC() final override { V3ERROR_NA_RETURN(""); } @@ -343,7 +343,7 @@ public: virtual bool sizeMattersThs() const = 0; // True if output result depends on ths size virtual bool sizeMattersFhs() const = 0; // True if output result depends on ths size int instrCount() const override { return widthInstrs(); } - bool same(const AstNode*) const override { return true; } + bool sameNode(const AstNode*) const override { return true; } bool isPure() override; const char* broken() const override; @@ -397,7 +397,7 @@ public: virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size virtual bool sizeMattersThs() const = 0; // True if output result depends on ths size int instrCount() const override { return widthInstrs(); } - bool same(const AstNode*) const override { return true; } + bool sameNode(const AstNode*) const override { return true; } bool isPure() override; const char* broken() const override; @@ -478,7 +478,7 @@ public: virtual bool signedFlavor() const { return false; } virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors? int instrCount() const override { return widthInstrs(); } - bool same(const AstNode*) const override { return true; } + bool sameNode(const AstNode*) const override { return true; } bool isPure() override; const char* broken() const override; }; @@ -629,7 +629,7 @@ public: bool cleanOut() const override { return m_cleanOut; } string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } bool isPure() override { return pure(); } bool pure() const { return m_pure; } void pure(bool flag) { m_pure = flag; } @@ -653,7 +653,7 @@ public: ASTGEN_MEMBERS_AstCMethodHard; string name() const override VL_MT_STABLE { return m_name; } // * = Var name void name(const string& name) override { m_name = name; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstCMethodHard* const asamep = VN_DBG_AS(samep, CMethodHard); return (m_name == asamep->m_name); } @@ -773,16 +773,18 @@ public: } ASTGEN_MEMBERS_AstClassOrPackageRef; // METHODS - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { return (m_classOrPackageNodep == VN_DBG_AS(samep, ClassOrPackageRef)->m_classOrPackageNodep); } void dump(std::ostream& str = std::cout) const override; void dumpJson(std::ostream& str = std::cout) const override; string name() const override VL_MT_STABLE { return m_name; } // * = Var name + // There's no classOrPackagep(); use classOrPackageNodep() to get Node, + // or iterating to package with classOrPackageSkipp() + AstNodeModule* classOrPackageSkipp() const; AstNode* classOrPackageNodep() const { return m_classOrPackageNodep; } void classOrPackageNodep(AstNode* nodep) { m_classOrPackageNodep = nodep; } - AstNodeModule* classOrPackagep() const; AstPackage* packagep() const { return VN_CAST(classOrPackageNodep(), Package); } void classOrPackagep(AstNodeModule* nodep) { m_classOrPackageNodep = (AstNode*)nodep; } @@ -804,7 +806,7 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } int instrCount() const override { return widthInstrs(); } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstConsDynArray final : public AstNodeExpr { // Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs} @@ -836,7 +838,7 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } int instrCount() const override { return widthInstrs(); } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstConsDynArray* const sp = VN_DBG_AS(samep, ConsDynArray); return m_lhsIsValue == sp->m_lhsIsValue && m_rhsIsValue == sp->m_rhsIsValue; } @@ -863,7 +865,7 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } int instrCount() const override { return widthInstrs(); } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstConsPackUOrStruct final : public AstNodeExpr { // Construct a packed struct and return object, '{member1: value1, member2: value2} @@ -886,7 +888,7 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } int instrCount() const override { return widthInstrs(); } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstConsQueue final : public AstNodeExpr { // Construct a queue and return object, '{}. '{lhs}, '{lhs. rhs} @@ -918,7 +920,7 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } int instrCount() const override { return widthInstrs(); } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstConsQueue* const sp = VN_DBG_AS(samep, ConsQueue); return m_lhsIsValue == sp->m_lhsIsValue && m_rhsIsValue == sp->m_rhsIsValue; } @@ -939,7 +941,7 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } int instrCount() const override { return widthInstrs(); } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstConst final : public AstNodeExpr { // A constant @@ -1084,7 +1086,7 @@ public: string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstConst* const sp = VN_DBG_AS(samep, Const); return num().isCaseEq(sp->num()); } @@ -1191,6 +1193,8 @@ class AstDot final : public AstNodeExpr { // These are eliminated in the link stage // @astgen op1 := lhsp : AstNodeExpr // @astgen op2 := rhsp : AstNodeExpr + // + // We don't have a list of elements as it's probably legal to do '(foo.bar).(baz.bap)' const bool m_colon; // Is a "::" instead of a "." (lhs must be package/class) public: AstDot(FileLine* fl, bool colon, AstNodeExpr* lhsp, AstNodeExpr* rhsp) @@ -1220,7 +1224,7 @@ public: ASTGEN_MEMBERS_AstEmptyQueue; string emitC() override { V3ERROR_NA_RETURN(""); } string emitVerilog() override { return "{}"; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } bool cleanOut() const override { return true; } }; class AstEnumItemRef final : public AstNodeExpr { @@ -1238,7 +1242,7 @@ public: void dumpJson(std::ostream& str) const override; string name() const override VL_MT_STABLE { return itemp()->name(); } int instrCount() const override { return 0; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstEnumItemRef* const sp = VN_DBG_AS(samep, EnumItemRef); return itemp() == sp->itemp(); } @@ -1271,7 +1275,7 @@ public: if (AstNode::afterCommentp(stmtsp())) return false; return resultp()->isPure(); } - bool same(const AstNode*) const override { return true; } + bool sameNode(const AstNode*) const override { return true; } }; class AstFError final : public AstNodeExpr { // @astgen op1 := filep : AstNode @@ -1289,7 +1293,7 @@ public: int instrCount() const override { return widthInstrs() * 64; } bool isPredictOptimizable() const override { return false; } bool isPure() override { return false; } // SPECIAL: $display has 'visual' ordering - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstFOpen final : public AstNodeExpr { // @astgen op2 := filenamep : AstNodeExpr @@ -1310,7 +1314,7 @@ public: bool isPure() override { return false; } bool isOutputter() override { return true; } bool isUnlikely() const override { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstFOpenMcd final : public AstNodeExpr { // @astgen op2 := filenamep : AstNodeExpr @@ -1329,7 +1333,7 @@ public: bool isPure() override { return false; } bool isOutputter() override { return true; } bool isUnlikely() const override { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstFRead final : public AstNodeExpr { // @astgen op1 := memp : AstNode // VarRef for result @@ -1353,7 +1357,7 @@ public: bool isPure() override { return false; } // SPECIAL: has 'visual' ordering bool isOutputter() override { return true; } // SPECIAL: makes output bool cleanOut() const override { return false; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstFRewind final : public AstNodeExpr { // @astgen op1 := filep : Optional[AstNode] @@ -1372,7 +1376,7 @@ public: bool isOutputter() override { return true; } bool isUnlikely() const override { return true; } bool cleanOut() const override { return false; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstFScanF final : public AstNodeExpr { // @astgen op1 := exprsp : List[AstNode] // VarRefs for results @@ -1396,7 +1400,7 @@ public: bool isPure() override { return false; } // SPECIAL: has 'visual' ordering bool isOutputter() override { return true; } // SPECIAL: makes output bool cleanOut() const override { return false; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { return text() == VN_DBG_AS(samep, FScanF)->text(); } string text() const { return m_text; } // * = Text to display @@ -1422,7 +1426,7 @@ public: bool isPure() override { return false; } // SPECIAL: has 'visual' ordering bool isOutputter() override { return true; } // SPECIAL: makes output bool cleanOut() const override { return false; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstFTell final : public AstNodeExpr { // @astgen op1 := filep : AstNode // file (must be a VarRef) @@ -1441,7 +1445,7 @@ public: bool isOutputter() override { return true; } bool isUnlikely() const override { return true; } bool cleanOut() const override { return false; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstFell final : public AstNodeExpr { // Verilog $fell @@ -1459,7 +1463,7 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs(); } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstGatePin final : public AstNodeExpr { // Possibly expand a gate primitive input pin value to match the range of the gate primitive @@ -1495,7 +1499,7 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs(); } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstInitArray final : public AstNodeExpr { // This is also used as an array value in V3Simulate/const prop. @@ -1527,7 +1531,7 @@ public: void dumpJson(std::ostream& str) const override; const char* broken() const override; void cloneRelink() override; - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { // Only works if exact same children, instead should override comparison // of children list, and instead use map-vs-map key/value compare return m_map == VN_DBG_AS(samep, InitArray)->m_map; @@ -1587,7 +1591,7 @@ public: : ASTGEN_SUPER_LambdaArgRef(fl) , m_name{name} , m_index(index) {} - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } string emitVerilog() override { return name(); } string emitC() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } @@ -1621,7 +1625,7 @@ public: string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } - bool same(const AstNode* samep) const override; + bool sameNode(const AstNode* samep) const override; int instrCount() const override { return widthInstrs(); } AstVar* varp() const { return m_varp; } void varp(AstVar* nodep) { m_varp = nodep; } @@ -1639,7 +1643,7 @@ public: string emitVerilog() override { return "new"; } string emitC() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } int instrCount() const override { return widthInstrs(); } }; class AstNewDynamic final : public AstNodeExpr { @@ -1657,7 +1661,7 @@ public: string emitVerilog() override { return "new"; } string emitC() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } int instrCount() const override { return widthInstrs(); } }; class AstParseHolder final : public AstNodeExpr { @@ -1694,7 +1698,7 @@ public: void dump(std::ostream& str) const override; void dumpJson(std::ostream& str) const override; string name() const override VL_MT_STABLE { return m_name; } // * = Var name - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstParseRef* const asamep = VN_DBG_AS(samep, ParseRef); return (expect() == asamep->expect() && m_name == asamep->m_name); } @@ -1723,17 +1727,19 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs(); } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstPatMember final : public AstNodeExpr { // Verilog '{a} or '{a{b}} // Parents: AstPattern - // Children: expression, AstPattern, replication count + // Children: expression, AstPattern, replication count, decoded nodep if TEXT // Expression to assign or another AstPattern (list if replicated) // @astgen op1 := lhssp : List[AstNodeExpr] // @astgen op2 := keyp : Optional[AstNode] // @astgen op3 := repp : Optional[AstNodeExpr] // replication count, or nullptr for count 1 - bool m_default = false; + // @astgen op4 := varrefp : Optional[AstNodeExpr] // Decoded variable if TEXT + bool m_isDefault = false; // Has default + bool m_isConcat = false; // From concatenate public: AstPatMember(FileLine* fl, AstNodeExpr* lhssp, AstNode* keyp, AstNodeExpr* repp) @@ -1750,8 +1756,10 @@ public: int instrCount() const override { return widthInstrs() * 2; } void dump(std::ostream& str = std::cout) const override; void dumpJson(std::ostream& str = std::cout) const override; - bool isDefault() const { return m_default; } - void isDefault(bool flag) { m_default = flag; } + bool isConcat() const { return m_isConcat; } + void isConcat(bool flag) { m_isConcat = flag; } + bool isDefault() const { return m_isDefault; } + void isDefault(bool flag) { m_isDefault = flag; } }; class AstPattern final : public AstNodeExpr { // Verilog '{a,b,c,d...} @@ -1823,7 +1831,7 @@ public: bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } int instrCount() const override { return INSTR_COUNT_PLI; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } bool combinable(const AstRand* samep) const { return !seedp() && !samep->seedp() && reset() == samep->reset() && urandom() == samep->urandom(); @@ -1849,7 +1857,7 @@ public: bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } int instrCount() const override { return INSTR_COUNT_PLI; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstRose final : public AstNodeExpr { // Verilog $rose @@ -1867,7 +1875,7 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs(); } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstSFormatF final : public AstNodeExpr { // Convert format to string, generally under an AstDisplay or AstSFormat @@ -1904,7 +1912,7 @@ public: ASTGEN_MEMBERS_AstSFormatF; string name() const override VL_MT_STABLE { return m_text; } int instrCount() const override { return INSTR_COUNT_PLI; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { return text() == VN_DBG_AS(samep, SFormatF)->text(); } string verilogKwd() const override { return "$sformatf"; } @@ -1946,7 +1954,7 @@ public: bool isPure() override { return false; } // SPECIAL: has 'visual' ordering bool isOutputter() override { return true; } // SPECIAL: makes output bool cleanOut() const override { return false; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { return text() == VN_DBG_AS(samep, SScanF)->text(); } string text() const { return m_text; } // * = Text to display @@ -1966,7 +1974,7 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return 0; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstScopeName final : public AstNodeExpr { // For display %m and DPI context imports @@ -1986,7 +1994,7 @@ public: dtypeSetUInt64(); } ASTGEN_MEMBERS_AstScopeName; - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstScopeName* const sp = VN_DBG_AS(samep, ScopeName); return (m_dpiExport == sp->m_dpiExport && m_forFormat == sp->m_forFormat); } @@ -2024,7 +2032,7 @@ public: this->addElementsp(elementsp); } ASTGEN_MEMBERS_AstSelLoopVars; - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } bool maybePointedTo() const override VL_MT_SAFE { return false; } string emitVerilog() override { V3ERROR_NA_RETURN(""); } @@ -2050,7 +2058,7 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } int instrCount() const override { return widthInstrs(); } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstSetWildcard final : public AstNodeExpr { // Set a wildcard assoc array element and return object, '{} @@ -2070,7 +2078,7 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } int instrCount() const override { return widthInstrs(); } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstStable final : public AstNodeExpr { // Verilog $stable @@ -2088,7 +2096,7 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { V3ERROR_NA_RETURN(""); } int instrCount() const override { return widthInstrs(); } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstStackTraceF final : public AstNodeExpr { // $stacktrace used as function @@ -2107,7 +2115,7 @@ public: bool isOutputter() override { return true; } bool isUnlikely() const override { return true; } bool cleanOut() const override { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstStructSel final : public AstNodeExpr { // Unpacked struct/union member access @@ -2131,7 +2139,7 @@ public: // Not a union return VN_IS(fromp()->dtypep()->skipRefp(), StructDType); } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstStructSel* const sp = VN_DBG_AS(samep, StructSel); return m_name == sp->m_name; } @@ -2174,7 +2182,7 @@ public: bool isOutputter() override { return true; } bool isUnlikely() const override { return true; } bool cleanOut() const override { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstTestPlusArgs final : public AstNodeExpr { // Search expression. If nullptr then this is a $test$plusargs instead of $value$plusargs. @@ -2192,7 +2200,7 @@ public: bool isPredictOptimizable() const override { return false; } // but isPure() true bool cleanOut() const override { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstThisRef final : public AstNodeExpr { // Reference to 'this'. @@ -2209,7 +2217,7 @@ public: ASTGEN_MEMBERS_AstThisRef; string emitC() override { return "this"; } string emitVerilog() override { return "this"; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } bool cleanOut() const override { return true; } AstNodeDType* getChildDTypep() const override { return childDTypep(); } AstNodeDType* subDTypep() const VL_MT_STABLE { return dtypep() ? dtypep() : childDTypep(); } @@ -2227,7 +2235,7 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } int instrCount() const override { return widthInstrs(); } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstTimeUnit final : public AstNodeExpr { VTimescale m_timeunit; // Parent module time unit @@ -2243,7 +2251,7 @@ public: string emitSimpleOperator() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } int instrCount() const override { return widthInstrs(); } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } VTimescale timeunit() const { return m_timeunit; } void timeunit(const VTimescale& flag) { m_timeunit = flag; } }; @@ -2265,7 +2273,7 @@ public: bool isSubstOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } int instrCount() const override { return INSTR_COUNT_PLI; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstUnbounded final : public AstNodeExpr { // A $ in the parser, used for unbounded and queues @@ -2317,7 +2325,7 @@ public: bool isPredictOptimizable() const override { return false; } bool isPure() override { return !outp(); } bool cleanOut() const override { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstWith final : public AstNodeExpr { // Used as argument to method, then to AstCMethodHard @@ -2338,7 +2346,7 @@ public: this->addExprp(exprp); } ASTGEN_MEMBERS_AstWith; - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } const char* broken() const override { BROKEN_RTN(!indexArgRefp()); // varp needed to know lambda's arg dtype BROKEN_RTN(!valueArgRefp()); // varp needed to know lambda's arg dtype @@ -2363,7 +2371,7 @@ public: this->addExprsp(exprsp); } ASTGEN_MEMBERS_AstWithParse; - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } string emitVerilog() override { V3ERROR_NA_RETURN(""); } string emitC() override { V3ERROR_NA_RETURN(""); } @@ -4155,7 +4163,7 @@ public: bool sizeMattersRhs() const override { return false; } bool isGateOptimizable() const override { return true; } // esp for V3Const::ifSameAssign bool isPredictOptimizable() const override { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } int instrCount() const override { return widthInstrs(); } // Special operators // Return base var (or const) nodep dereferences @@ -4183,6 +4191,7 @@ public: } string emitVerilog() override { return "%k(%l%f[%r])"; } string emitC() override { return "%li%k[%ri]"; } + string emitSMT() const override { return "(select %l %r)"; } bool cleanOut() const override { return true; } bool cleanLhs() const override { return false; } bool cleanRhs() const override { return true; } @@ -4191,7 +4200,7 @@ public: bool isGateOptimizable() const override { return false; } // AssocSel creates on miss bool isPredictOptimizable() const override { return false; } bool isPure() override { return false; } // AssocSel creates on miss - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } int instrCount() const override { return widthInstrs(); } }; class AstWildcardSel final : public AstNodeSel { @@ -4223,7 +4232,7 @@ public: bool sizeMattersRhs() const override { return false; } bool isGateOptimizable() const override { return true; } // esp for V3Const::ifSameAssign bool isPredictOptimizable() const override { return false; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } int instrCount() const override { return widthInstrs(); } }; class AstWordSel final : public AstNodeSel { @@ -4249,7 +4258,7 @@ public: bool cleanRhs() const override { return true; } bool sizeMattersLhs() const override { return false; } bool sizeMattersRhs() const override { return false; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; // === AstNodeStream === @@ -4366,6 +4375,7 @@ class AstFuncRef final : public AstNodeFTaskRef { // A reference to a function bool m_superReference = false; // Called with super reference public: + inline AstFuncRef(FileLine* fl, AstFunc* taskp, AstNodeExpr* pinsp); AstFuncRef(FileLine* fl, AstParseRef* namep, AstNodeExpr* pinsp) : ASTGEN_SUPER_FuncRef(fl, (AstNode*)namep, pinsp) {} AstFuncRef(FileLine* fl, const string& name, AstNodeExpr* pinsp) @@ -4399,13 +4409,14 @@ public: AstNew(FileLine* fl, AstNodeExpr* pinsp) : ASTGEN_SUPER_New(fl, "new", pinsp) {} ASTGEN_MEMBERS_AstNew; - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } int instrCount() const override { return widthInstrs(); } }; class AstTaskRef final : public AstNodeFTaskRef { // A reference to a task bool m_superReference = false; // Called with super reference public: + inline AstTaskRef(FileLine* fl, AstTask* taskp, AstNodeExpr* pinsp); AstTaskRef(FileLine* fl, AstParseRef* namep, AstNodeExpr* pinsp) : ASTGEN_SUPER_TaskRef(fl, (AstNode*)namep, pinsp) { dtypeSetVoid(); @@ -4498,6 +4509,18 @@ public: }; // === AstNodeTermop === +class AstInferredDisable final : public AstNodeTermop { +public: + AstInferredDisable(FileLine* fl) + : ASTGEN_SUPER_InferredDisable(fl) { + dtypeSetLogicSized(1, VSigning::UNSIGNED); + } + ASTGEN_MEMBERS_AstInferredDisable; + string emitVerilog() override { return "%f$inferred_disable"; } + string emitC() override { V3ERROR_NA_RETURN(""); } + bool cleanOut() const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } +}; class AstTime final : public AstNodeTermop { VTimescale m_timeunit; // Parent module time unit public: @@ -4513,7 +4536,7 @@ public: bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } int instrCount() const override { return INSTR_COUNT_TIME; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } void dump(std::ostream& str = std::cout) const override; void dumpJson(std::ostream& str = std::cout) const override; VTimescale timeunit() const { return m_timeunit; } @@ -4534,7 +4557,7 @@ public: bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } int instrCount() const override { return INSTR_COUNT_TIME; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } void dump(std::ostream& str = std::cout) const override; void dumpJson(std::ostream& str = std::cout) const override; VTimescale timeunit() const { return m_timeunit; } @@ -4704,7 +4727,7 @@ public: bool sizeMattersLhs() const override { return false; } bool sizeMattersRhs() const override { return false; } bool sizeMattersThs() const override { return false; } - bool same(const AstNode*) const override { return true; } + bool sameNode(const AstNode*) const override { return true; } int instrCount() const override { return widthInstrs() * (VN_CAST(lsbp(), Const) ? 3 : 10); } int widthConst() const { return VN_AS(widthp(), Const)->toSInt(); } int lsbConst() const { return VN_AS(lsbp(), Const)->toSInt(); } @@ -4741,7 +4764,7 @@ public: bool sizeMattersLhs() const override { return false; } bool sizeMattersRhs() const override { return false; } bool sizeMattersThs() const override { return false; } - bool same(const AstNode*) const override { return true; } + bool sameNode(const AstNode*) const override { return true; } int instrCount() const override { return 10; } // Removed before matters // For widthConst()/loConst etc, see declRange().elements() and other VNumRange methods VNumRange& declRange() VL_MT_STABLE { return m_declRange; } @@ -4925,7 +4948,7 @@ public: bool cleanOut() const override { return true; } bool cleanLhs() const override { return true; } bool sizeMattersLhs() const override { return false; } // Special cased in V3Cast - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { return size() == VN_DBG_AS(samep, CCast)->size(); } void dump(std::ostream& str = std::cout) const override; @@ -4991,7 +5014,7 @@ public: bool cleanOut() const override { return true; } bool cleanLhs() const override { return true; } bool sizeMattersLhs() const override { return false; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstExtend final : public AstNodeUniop { // Expand a value into a wider entity by 0 extension. Width is implied from nodep->width() @@ -5254,7 +5277,7 @@ public: bool cleanOut() const override { return true; } bool cleanLhs() const override { return true; } bool sizeMattersLhs() const override { return false; } - bool same(const AstNode* samep) const override { return fileline() == samep->fileline(); } + bool sameNode(const AstNode* samep) const override { return fileline() == samep->fileline(); } }; class AstOneHot final : public AstNodeUniop { // True if only single bit set in vector @@ -5703,8 +5726,8 @@ public: void dump(std::ostream& str) const override; void dumpJson(std::ostream& str) const override; const char* broken() const override; - bool same(const AstNode* samep) const override; - inline bool same(const AstVarRef* samep) const; + bool sameNode(const AstNode* samep) const override; + inline bool sameNode(const AstVarRef* samep) const; inline bool sameNoLvalue(AstVarRef* samep) const; int instrCount() const override; string emitVerilog() override { V3ERROR_NA_RETURN(""); } @@ -5736,7 +5759,7 @@ public: string emitC() override { V3ERROR_NA_RETURN(""); } bool cleanOut() const override { return true; } int instrCount() const override { return widthInstrs(); } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstVarXRef* asamep = VN_DBG_AS(samep, VarXRef); return (selfPointer() == asamep->selfPointer() && varp() == asamep->varp() && name() == asamep->name() && dotted() == asamep->dotted()); diff --git a/src/V3AstNodeOther.h b/src/V3AstNodeOther.h index 8387f70c9..811850d71 100644 --- a/src/V3AstNodeOther.h +++ b/src/V3AstNodeOther.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -68,8 +68,6 @@ class AstNodeFTask VL_NOT_FINAL : public AstNode { bool m_taskPublic : 1; // Public task bool m_attrIsolateAssign : 1; // User isolate_assignments attribute bool m_classMethod : 1; // Class method - bool m_externProto : 1; // Extern prototype - bool m_externDef : 1; // Extern definition bool m_prototype : 1; // Just a prototype bool m_dpiExport : 1; // DPI exported bool m_dpiImport : 1; // DPI imported @@ -77,6 +75,8 @@ class AstNodeFTask VL_NOT_FINAL : public AstNode { bool m_dpiOpenChild : 1; // DPI import open array child wrapper bool m_dpiTask : 1; // DPI import task (vs. void function) bool m_isConstructor : 1; // Class constructor + bool m_isExternProto : 1; // Extern prototype + bool m_isExternDef : 1; // Extern definition bool m_isHideLocal : 1; // Verilog local bool m_isHideProtected : 1; // Verilog protected bool m_dpiPure : 1; // DPI import pure (vs. virtual pure) @@ -97,8 +97,6 @@ protected: , m_taskPublic{false} , m_attrIsolateAssign{false} , m_classMethod{false} - , m_externProto{false} - , m_externDef{false} , m_prototype{false} , m_dpiExport{false} , m_dpiImport{false} @@ -106,6 +104,8 @@ protected: , m_dpiOpenChild{false} , m_dpiTask{false} , m_isConstructor{false} + , m_isExternProto{false} + , m_isExternDef{false} , m_isHideLocal{false} , m_isHideProtected{false} , m_dpiPure{false} @@ -144,10 +144,10 @@ public: void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; } bool classMethod() const { return m_classMethod; } void classMethod(bool flag) { m_classMethod = flag; } - bool isExternProto() const { return m_externProto; } - void isExternProto(bool flag) { m_externProto = flag; } - bool isExternDef() const { return m_externDef; } - void isExternDef(bool flag) { m_externDef = flag; } + bool isExternProto() const { return m_isExternProto; } + void isExternProto(bool flag) { m_isExternProto = flag; } + bool isExternDef() const { return m_isExternDef; } + void isExternDef(bool flag) { m_isExternDef = flag; } bool prototype() const { return m_prototype; } void prototype(bool flag) { m_prototype = flag; } bool dpiExport() const { return m_dpiExport; } @@ -214,7 +214,7 @@ public: void dump(std::ostream& str) const override; void dumpJson(std::ostream& str) const override; string name() const override VL_MT_STABLE { return m_name; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstNodeModule VL_NOT_FINAL : public AstNode { // A module, package, program or interface declaration; @@ -375,7 +375,7 @@ public: bool hasDType() const override VL_MT_SAFE { return true; } virtual bool cleanRhs() const { return true; } int instrCount() const override { return widthInstrs(); } - bool same(const AstNode*) const override { return true; } + bool sameNode(const AstNode*) const override { return true; } string verilogKwd() const override { return "="; } bool isTimingControl() const override { return timingControlp(); } virtual bool brokeLhsMustBeLvalue() const = 0; @@ -418,7 +418,7 @@ public: } ASTGEN_MEMBERS_AstNodeCoverOrAssert; string name() const override VL_MT_STABLE { return m_name; } // * = Var name - bool same(const AstNode* samep) const override { return samep->name() == name(); } + bool sameNode(const AstNode* samep) const override { return samep->name() == name(); } void name(const string& name) override { m_name = name; } void dump(std::ostream& str = std::cout) const override; void dumpJson(std::ostream& str = std::cout) const override; @@ -450,7 +450,7 @@ public: ASTGEN_MEMBERS_AstNodeFor; bool isGateOptimizable() const override { return false; } int instrCount() const override { return INSTR_COUNT_BRANCH; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstNodeForeach VL_NOT_FINAL : public AstNodeStmt { // @astgen op1 := arrayp : AstNode @@ -464,7 +464,7 @@ public: ASTGEN_MEMBERS_AstNodeForeach; bool isGateOptimizable() const override { return false; } int instrCount() const override { return INSTR_COUNT_BRANCH; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); } }; class AstNodeIf VL_NOT_FINAL : public AstNodeStmt { @@ -487,7 +487,7 @@ public: bool isGateOptimizable() const override { return false; } bool isGateDedupable() const override { return true; } int instrCount() const override { return INSTR_COUNT_BRANCH; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } void branchPred(VBranchPred flag) { m_branchPred = flag; } VBranchPred branchPred() const { return m_branchPred; } void isBoundsCheck(bool flag) { m_isBoundsCheck = flag; } @@ -519,7 +519,7 @@ public: bool isPure() override { return false; } bool isOutputter() override { return true; } bool isUnlikely() const override { return true; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { return isHex() == VN_DBG_AS(samep, NodeReadWriteMem)->isHex(); } bool isHex() const { return m_isHex; } @@ -540,7 +540,7 @@ public: ASTGEN_MEMBERS_AstNodeText; void dump(std::ostream& str = std::cout) const override; void dumpJson(std::ostream& str = std::cout) const override; - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstNodeText* asamep = VN_DBG_AS(samep, NodeText); return text() == asamep->text(); } @@ -677,7 +677,7 @@ public: bool maybePointedTo() const override VL_MT_SAFE { return true; } void dump(std::ostream& str = std::cout) const override; void dumpJson(std::ostream& str = std::cout) const override; - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstCFunc* const asamep = VN_DBG_AS(samep, CFunc); return ((isTrace() == asamep->isTrace()) && (rtnTypeVoid() == asamep->rtnTypeVoid()) && (argTypes() == asamep->argTypes()) && isLoose() == asamep->isLoose() @@ -807,7 +807,6 @@ class AstCell final : public AstNode { string m_origName; // Original name before dot addition string m_modName; // Module the cell instances bool m_hasIfaceVar : 1; // True if a Var has been created for this cell - bool m_hasNoParens : 1; // Instantiation has no parenthesis bool m_recursive : 1; // Self-recursive module bool m_trace : 1; // Trace this cell public: @@ -819,7 +818,6 @@ public: , m_origName{instName} , m_modName{modName} , m_hasIfaceVar{false} - , m_hasNoParens{false} , m_recursive{false} , m_trace{true} { this->addPinsp(pinsp); @@ -844,8 +842,6 @@ public: void modp(AstNodeModule* nodep) { m_modp = nodep; } bool hasIfaceVar() const { return m_hasIfaceVar; } void hasIfaceVar(bool flag) { m_hasIfaceVar = flag; } - bool hasNoParens() const { return m_hasNoParens; } - void hasNoParens(bool flag) { m_hasNoParens = flag; } void trace(bool flag) { m_trace = flag; } bool isTrace() const { return m_trace; } void recursive(bool flag) { m_recursive = flag; } @@ -1025,8 +1021,14 @@ public: class AstConstraint final : public AstNode { // Constraint // @astgen op1 := itemsp : List[AstNode] + // @astgen op2 := classOrPackagep : Optional[AstNode] string m_name; // Name of constraint - bool m_isStatic = false; // static constraint + VBaseOverride m_baseOverride; // BaseOverride (inital/final/extends) + bool m_isExternDef = false; // Extern prototype definition + bool m_isExternExplicit = false; // Explicit prototype declaration (has extern) + bool m_isExternProto = false; // Prototype declaration (implicit or explicit) + bool m_isKwdPure = false; // Pure constraint + bool m_isStatic = false; // Static constraint public: AstConstraint(FileLine* fl, const string& name, AstNode* itemsp) : ASTGEN_SUPER_Constraint(fl) @@ -1034,11 +1036,23 @@ public: this->addItemsp(itemsp); } ASTGEN_MEMBERS_AstConstraint; + void dump(std::ostream& str) const override; + void dumpJson(std::ostream& str) const override; string name() const override VL_MT_STABLE { return m_name; } // * = Scope name bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } bool maybePointedTo() const override VL_MT_SAFE { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } + void baseOverride(const VBaseOverride& flag) { m_baseOverride = flag; } + VBaseOverride baseOverride() const { return m_baseOverride; } + bool isExternDef() const { return m_isExternDef; } + void isExternDef(bool flag) { m_isExternDef = flag; } + void isExternExplicit(bool flag) { m_isExternExplicit = flag; } + bool isExternExplicit() const { return m_isExternExplicit; } + void isExternProto(bool flag) { m_isExternProto = flag; } + bool isExternProto() const { return m_isExternProto; } + void isKwdPure(bool flag) { m_isKwdPure = flag; } + bool isKwdPure() const { return m_isKwdPure; } void isStatic(bool flag) { m_isStatic = flag; } bool isStatic() const { return m_isStatic; } }; @@ -1055,7 +1069,7 @@ public: ASTGEN_MEMBERS_AstConstraintBefore; bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstDefParam final : public AstNode { // A defparam assignment @@ -1072,9 +1086,19 @@ public: } string name() const override VL_MT_STABLE { return m_name; } // * = Scope name ASTGEN_MEMBERS_AstDefParam; - bool same(const AstNode*) const override { return true; } + bool sameNode(const AstNode*) const override { return true; } string path() const { return m_path; } }; +class AstDefaultDisable final : public AstNode { + // @astgen op1 := condp : AstNodeExpr + +public: + AstDefaultDisable(FileLine* fl, AstNodeExpr* condp) + : ASTGEN_SUPER_DefaultDisable(fl) { + this->condp(condp); + } + ASTGEN_MEMBERS_AstDefaultDisable; +}; class AstDpiExport final : public AstNode { // We could put an AstNodeFTaskRef instead of the verilog function name, // however we're not *calling* it, so that seems somehow wrong. @@ -1110,7 +1134,7 @@ public: bool isPure() override { return false; } // SPECIAL: $display has 'visual' ordering bool isOutputter() override { return true; } // SPECIAL: $display makes output bool isUnlikely() const override { return true; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { return displayType() == VN_DBG_AS(samep, ElabDisplay)->displayType(); } int instrCount() const override { return INSTR_COUNT_PLI; } @@ -1123,7 +1147,7 @@ public: explicit AstEmpty(FileLine* fl) : ASTGEN_SUPER_Empty(fl) {} ASTGEN_MEMBERS_AstEmpty; - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstExecGraph final : public AstNode { // For parallel execution, this node contains a dependency graph. Each @@ -1471,7 +1495,7 @@ public: ASTGEN_MEMBERS_AstPragma; VPragmaType pragType() const { return m_pragType; } // *=type of the pragma bool isPredictOptimizable() const override { return false; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { return pragType() == VN_DBG_AS(samep, Pragma)->pragType(); } }; @@ -1506,7 +1530,7 @@ public: this->lhsp(lhsp); } ASTGEN_MEMBERS_AstPull; - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { return direction() == VN_DBG_AS(samep, Pull)->direction(); } uint32_t direction() const { return (uint32_t)m_direction; } @@ -1544,7 +1568,7 @@ public: void name(const string& name) override { m_name = name; } void dump(std::ostream& str) const override; void dumpJson(std::ostream& str) const override; - bool same(const AstNode* samep) const override; + bool sameNode(const AstNode* samep) const override; string nameDotless() const; AstNodeModule* modp() const { return m_modp; } // @@ -1591,7 +1615,7 @@ public: ASTGEN_MEMBERS_AstSenItem; void dump(std::ostream& str) const override; void dumpJson(std::ostream& str) const override; - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { return edgeType() == VN_DBG_AS(samep, SenItem)->edgeType(); } VEdgeType edgeType() const { return m_edgeType; } @@ -1944,7 +1968,7 @@ public: ASTGEN_MEMBERS_AstVar; void dump(std::ostream& str) const override; void dumpJson(std::ostream& str) const override; - bool same(const AstNode* samep) const override; + bool sameNode(const AstNode* samep) const override; string name() const override VL_MT_STABLE { return m_name; } // * = Var name bool hasDType() const override VL_MT_SAFE { return true; } bool maybePointedTo() const override VL_MT_SAFE { return true; } @@ -2059,7 +2083,8 @@ public: bool isAnsi() const { return m_ansi; } bool isContinuously() const { return m_isContinuously; } bool isDeclTyped() const { return m_declTyped; } - bool isInoutish() const { return m_direction.isInoutish(); } + bool isInout() const { return m_direction.isInout(); } + bool isInoutOrRef() const { return m_direction.isInoutOrRef(); } bool isInput() const { return m_direction.isInput(); } bool isNonOutput() const { return m_direction.isNonOutput(); } bool isReadOnly() const VL_MT_SAFE { return m_direction.isReadOnly(); } @@ -2069,7 +2094,11 @@ public: bool isTristate() const { return m_tristate; } bool isPrimaryIO() const VL_MT_SAFE { return m_primaryIO; } bool isPrimaryInish() const { return isPrimaryIO() && isNonOutput(); } - bool isIfaceRef() const { return (varType() == VVarType::IFACEREF); } + bool isIfaceRef() const { return varType() == VVarType::IFACEREF; } + void setIfaceRef() { + m_direction = VDirection::NONE; + m_varType = VVarType::IFACEREF; + } bool isIfaceParent() const { return m_isIfaceParent; } bool isInternal() const { return m_isInternal; } bool isSignal() const { return varType().isSignal(); } @@ -2085,11 +2114,11 @@ public: && !isSc() && !isPrimaryIO() && !isConst() && !isDouble() && !isString()); } bool isClassMember() const { return varType() == VVarType::MEMBER; } - bool isStatementTemp() const { return (varType() == VVarType::STMTTEMP); } - bool isXTemp() const { return (varType() == VVarType::XTEMP); } + bool isStatementTemp() const { return varType() == VVarType::STMTTEMP; } + bool isXTemp() const { return varType() == VVarType::XTEMP; } bool isParam() const { return varType().isParam(); } - bool isGParam() const { return (varType() == VVarType::GPARAM); } - bool isGenVar() const { return (varType() == VVarType::GENVAR); } + bool isGParam() const { return varType() == VVarType::GPARAM; } + bool isGenVar() const { return varType() == VVarType::GENVAR; } bool isBitLogic() const { AstBasicDType* bdtypep = basicp(); return bdtypep && bdtypep->isBitLogic(); @@ -2105,9 +2134,9 @@ public: bool isScBigUint() const VL_MT_STABLE; bool isScSensitive() const { return m_scSensitive; } bool isSigPublic() const; - bool isSigModPublic() const { return m_sigModPublic; } - bool isSigUserRdPublic() const { return m_sigUserRdPublic; } - bool isSigUserRWPublic() const { return m_sigUserRWPublic; } + bool isSigModPublic() const { return m_sigModPublic && !isIfaceRef(); } + bool isSigUserRdPublic() const { return m_sigUserRdPublic && !isIfaceRef(); } + bool isSigUserRWPublic() const { return m_sigUserRWPublic && !isIfaceRef(); } bool isTrace() const { return m_trace; } bool isRand() const { return m_rand.isRand(); } bool isRandC() const { return m_rand.isRandC(); } @@ -2198,7 +2227,7 @@ public: string name() const override VL_MT_STABLE { return scopep()->name() + "->" + varp()->name(); } void dump(std::ostream& str) const override; void dumpJson(std::ostream& str) const override; - bool same(const AstNode* samep) const override; + bool sameNode(const AstNode* samep) const override; bool hasDType() const override VL_MT_SAFE { return true; } AstVar* varp() const VL_MT_STABLE { return m_varp; } // [After Link] Pointer to variable AstScope* scopep() const VL_MT_STABLE { return m_scopep; } // Pointer to scope it's under @@ -2388,13 +2417,13 @@ public: // Iterates top level members of the class, taking into account inheritance (starting from the // root superclass). Note: after V3Scope, several children are moved under an AstScope and will // not be found by this. - template - void foreachMember(const Callable& f) { - using T_Node = typename FunctionArgNoPointerNoCV::type; + template + void foreachMember(const T_Callable& f) { + using T_Node = typename FunctionArgNoPointerNoCV::type; static_assert( - vlstd::is_invocable::value + vlstd::is_invocable::value && std::is_base_of::value, - "Callable 'f' must have a signature compatible with 'void(AstClass*, T_Node*)', " + "T_Callable 'f' must have a signature compatible with 'void(AstClass*, T_Node*)', " "with 'T_Node' being a subtype of 'AstNode'"); if (AstClassExtends* const cextendsp = this->extendsp()) { cextendsp->classp()->foreachMember(f); @@ -2404,13 +2433,14 @@ public: } } // Same as above, but stops after first match - template - bool existsMember(const Callable& p) const { - using T_Node = typename FunctionArgNoPointerNoCV::type; - static_assert(vlstd::is_invocable_r::value - && std::is_base_of::value, - "Predicate 'p' must have a signature compatible with 'bool(const AstClass*, " - "const T_Node*)', with 'T_Node' being a subtype of 'AstNode'"); + template + bool existsMember(const T_Callable& p) const { + using T_Node = typename FunctionArgNoPointerNoCV::type; + static_assert( + vlstd::is_invocable_r::value + && std::is_base_of::value, + "Predicate 'p' must have a signature compatible with 'bool(const AstClass*, " + "const T_Node*)', with 'T_Node' being a subtype of 'AstNode'"); if (AstClassExtends* const cextendsp = this->extendsp()) { if (cextendsp->classp()->existsMember(p)) return true; } @@ -2585,7 +2615,7 @@ public: ASTGEN_MEMBERS_AstBracketRange; virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitVerilog() { V3ERROR_NA_RETURN(""); } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } // Will be removed in V3Width, which relies on this // being a child not a dtype pointed node bool maybePointedTo() const override VL_MT_SAFE { return false; } @@ -2620,7 +2650,7 @@ public: void dump(std::ostream& str) const override; void dumpJson(std::ostream& str) const override; virtual string emitC() { V3ERROR_NA_RETURN(""); } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstUnsizedRange final : public AstNodeRange { // Unsized range specification, for open arrays @@ -2630,7 +2660,7 @@ public: ASTGEN_MEMBERS_AstUnsizedRange; virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitVerilog() { return "[]"; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstWildcardRange final : public AstNodeRange { // Wildcard range specification, for wildcard index type associative arrays @@ -2640,7 +2670,7 @@ public: ASTGEN_MEMBERS_AstWildcardRange; virtual string emitC() { V3ERROR_NA_RETURN(""); } virtual string emitVerilog() { return "[*]"; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; // === AstNodeStmt === @@ -2656,7 +2686,7 @@ public: addStmtsp(stmtsp); } ASTGEN_MEMBERS_AstAlwaysPublic; - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } // Special accessors bool isJustOneBodyStmt() const { return stmtsp() && !stmtsp()->nextp(); } bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); } @@ -2713,7 +2743,7 @@ public: ASTGEN_MEMBERS_AstCReset; bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstCReturn final : public AstNodeStmt { // C++ return from a function @@ -2725,7 +2755,7 @@ public: } ASTGEN_MEMBERS_AstCReturn; int instrCount() const override { return widthInstrs(); } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstCStmt final : public AstNodeStmt { // Emit C statement @@ -2739,7 +2769,7 @@ public: ASTGEN_MEMBERS_AstCStmt; bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstComment final : public AstNodeStmt { // Some comment to put into the output stream @@ -2752,23 +2782,25 @@ public: , m_showAt{showAt} {} ASTGEN_MEMBERS_AstComment; string name() const override VL_MT_STABLE { return m_name; } // * = Text - bool same(const AstNode* samep) const override { return true; } // Ignore name in comments + bool sameNode(const AstNode* samep) const override { return true; } // Ignore name in comments virtual bool showAt() const { return m_showAt; } }; class AstConstraintExpr final : public AstNodeStmt { // Constraint expression // @astgen op1 := exprp : AstNodeExpr - bool m_isSoft = false; // Soft constraint expression bool m_isDisableSoft = false; // Disable soft constraint expression + bool m_isSoft = false; // Soft constraint expression public: AstConstraintExpr(FileLine* fl, AstNodeExpr* exprp) : ASTGEN_SUPER_ConstraintExpr(fl) { this->exprp(exprp); } ASTGEN_MEMBERS_AstConstraintExpr; + void dump(std::ostream& str) const override; + void dumpJson(std::ostream& str) const override; bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } bool isDisableSoft() const { return m_isDisableSoft; } void isDisableSoft(bool flag) { m_isDisableSoft = flag; } bool isSoft() const { return m_isSoft; } @@ -2785,7 +2817,7 @@ public: ASTGEN_MEMBERS_AstConstraintUnique; bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return false; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstContinue final : public AstNodeStmt { public: @@ -2837,7 +2869,7 @@ public: const string& hier() const { return m_hier; } void hier(const string& flag) { m_hier = flag; } void comment(const string& flag) { m_text = flag; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { const AstCoverDecl* const asamep = VN_DBG_AS(samep, CoverDecl); return (fileline() == asamep->fileline() && linescov() == asamep->linescov() && hier() == asamep->hier() && comment() == asamep->comment()); @@ -2861,7 +2893,7 @@ public: void dump(std::ostream& str) const override; void dumpJson(std::ostream& str) const override; int instrCount() const override { return 1 + 2 * INSTR_COUNT_LD; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { return declp() == VN_DBG_AS(samep, CoverInc)->declp(); } bool isGateOptimizable() const override { return false; } @@ -2885,7 +2917,7 @@ public: } ASTGEN_MEMBERS_AstCoverToggle; int instrCount() const override { return 3 + INSTR_COUNT_BRANCH + INSTR_COUNT_LD; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } bool isGateOptimizable() const override { return false; } bool isPredictOptimizable() const override { return true; } bool isOutputter() override { @@ -2910,7 +2942,7 @@ public: void dump(std::ostream& str) const override; void dumpJson(std::ostream& str) const override; bool isTimingControl() const override { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } void timeunit(const VTimescale& flag) { m_timeunit = flag; } VTimescale timeunit() const { return m_timeunit; } bool isCycleDelay() const { return m_isCycle; } @@ -2972,7 +3004,7 @@ public: bool isPure() override { return false; } // SPECIAL: $display has 'visual' ordering bool isOutputter() override { return true; } // SPECIAL: $display makes output bool isUnlikely() const override { return true; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { return displayType() == VN_DBG_AS(samep, Display)->displayType(); } int instrCount() const override { return INSTR_COUNT_PLI; } @@ -2993,7 +3025,7 @@ public: ASTGEN_MEMBERS_AstDoWhile; bool isGateOptimizable() const override { return false; } int instrCount() const override { return INSTR_COUNT_BRANCH; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } // Stop statement searchback here bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); } }; @@ -3015,7 +3047,7 @@ public: bool isPredictOptimizable() const override { return false; } bool isPure() override { return false; } virtual bool cleanOut() const { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } VDumpCtlType ctlType() const { return m_ctlType; } }; class AstEventControl final : public AstNodeStmt { @@ -3048,7 +3080,7 @@ public: bool isPure() override { return false; } bool isOutputter() override { return true; } bool isUnlikely() const override { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstFFlush final : public AstNodeStmt { // Parents: stmtlist @@ -3065,7 +3097,7 @@ public: bool isPure() override { return false; } bool isOutputter() override { return true; } bool isUnlikely() const override { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstFinish final : public AstNodeStmt { public: @@ -3078,7 +3110,7 @@ public: bool isOutputter() override { return true; } // SPECIAL: $display makes output bool isUnlikely() const override { return true; } int instrCount() const override { return 0; } // Rarely executes - bool same(const AstNode* samep) const override { return fileline() == samep->fileline(); } + bool sameNode(const AstNode* samep) const override { return fileline() == samep->fileline(); } }; class AstFireEvent final : public AstNodeStmt { // '-> _' and '->> _' event trigger statements @@ -3113,7 +3145,7 @@ public: const char* broken() const override; int instrCount() const override { return 0; } bool maybePointedTo() const override VL_MT_SAFE { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } int labelNum() const { return m_labelNum; } void labelNum(int flag) { m_labelNum = flag; } AstJumpLabel* labelp() const { return m_labelp; } @@ -3139,7 +3171,7 @@ public: void dump(std::ostream& str) const override; void dumpJson(std::ostream& str) const override; int instrCount() const override { return INSTR_COUNT_BRANCH; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { return labelp() == VN_DBG_AS(samep, JumpGo)->labelp(); } bool isGateOptimizable() const override { return false; } @@ -3167,7 +3199,7 @@ public: void dump(std::ostream& str) const override; void dumpJson(std::ostream& str) const override; int instrCount() const override { return 0; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { return blockp() == VN_DBG_AS(samep, JumpLabel)->blockp(); } AstJumpBlock* blockp() const { return m_blockp; } @@ -3186,7 +3218,7 @@ public: bool isPure() override { return false; } // Though deleted before opt bool isOutputter() override { return true; } // Though deleted before opt int instrCount() const override { return INSTR_COUNT_PLI; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { return m_off == VN_DBG_AS(samep, MonitorOff)->m_off; } bool off() const { return m_off; } @@ -3244,7 +3276,7 @@ public: ASTGEN_MEMBERS_AstRepeat; bool isGateOptimizable() const override { return false; } // Not relevant - converted to FOR int instrCount() const override { return INSTR_COUNT_BRANCH; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); } }; class AstReturn final : public AstNodeStmt { @@ -3288,7 +3320,7 @@ public: bool isOutputter() override { return false; } virtual bool cleanOut() const { return false; } int instrCount() const override { return INSTR_COUNT_PLI; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstStackTraceT final : public AstNodeStmt { // $stacktrace used as task @@ -3302,7 +3334,7 @@ public: bool isPure() override { return false; } bool isOutputter() override { return true; } bool isUnlikely() const override { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstStmtExpr final : public AstNodeStmt { // Expression in statement position @@ -3330,7 +3362,7 @@ public: bool isOutputter() override { return true; } // SPECIAL: $display makes output bool isUnlikely() const override { return true; } int instrCount() const override { return 0; } // Rarely executes - bool same(const AstNode* samep) const override { return fileline() == samep->fileline(); } + bool sameNode(const AstNode* samep) const override { return fileline() == samep->fileline(); } string emitVerilog() const { return m_isFatal ? "$fatal" : "$stop"; } bool isFatal() const { return m_isFatal; } }; @@ -3350,7 +3382,7 @@ public: bool isPure() override { return true; } bool isOutputter() override { return false; } int instrCount() const override { return 0; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstSystemT final : public AstNodeStmt { // $system used as task @@ -3367,7 +3399,7 @@ public: bool isPure() override { return false; } bool isOutputter() override { return true; } bool isUnlikely() const override { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstTimeFormat final : public AstNodeStmt { // Parents: stmtlist @@ -3425,7 +3457,7 @@ public: string name() const override VL_MT_STABLE { return m_showname; } bool maybePointedTo() const override VL_MT_SAFE { return true; } bool hasDType() const override VL_MT_SAFE { return true; } - bool same(const AstNode* samep) const override { return false; } + bool sameNode(const AstNode* samep) const override { return false; } string showname() const { return m_showname; } // * = Var name // Details on what we're tracing uint32_t code() const { return m_code; } @@ -3466,7 +3498,7 @@ public: void dumpJson(std::ostream& str) const override; int instrCount() const override { return 10 + 2 * INSTR_COUNT_LD; } bool hasDType() const override VL_MT_SAFE { return true; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { return declp() == VN_DBG_AS(samep, TraceInc)->declp(); } bool isGateOptimizable() const override { return false; } @@ -3482,7 +3514,7 @@ public: explicit AstTracePopPrefix(FileLine* fl) : ASTGEN_SUPER_TracePopPrefix(fl) {} ASTGEN_MEMBERS_AstTracePopPrefix; - bool same(const AstNode* samep) const override { return false; } + bool sameNode(const AstNode* samep) const override { return false; } }; class AstTracePushPrefix final : public AstNodeStmt { const string m_prefix; // Prefix to add to signal names @@ -3493,7 +3525,7 @@ public: , m_prefix{prefix} , m_prefixType{prefixType} {} ASTGEN_MEMBERS_AstTracePushPrefix; - bool same(const AstNode* samep) const override { return false; } + bool sameNode(const AstNode* samep) const override { return false; } string prefix() const { return m_prefix; } VTracePrefixType prefixType() const { return m_prefixType; } }; @@ -3510,7 +3542,7 @@ public: bool isPredictOptimizable() const override { return false; } bool isPure() override { return false; } bool isOutputter() override { return true; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } }; class AstWait final : public AstNodeStmt { // @astgen op1 := condp : AstNodeExpr @@ -3550,7 +3582,7 @@ public: void dump(std::ostream& str) const override; bool isGateOptimizable() const override { return false; } int instrCount() const override { return INSTR_COUNT_BRANCH; } - bool same(const AstNode* /*samep*/) const override { return true; } + bool sameNode(const AstNode* /*samep*/) const override { return true; } // Stop statement searchback here void addNextStmt(AstNode* newp, AstNode* belowp) override; bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); } @@ -3682,7 +3714,7 @@ public: , m_casex{casex} {} ASTGEN_MEMBERS_AstCase; string verilogKwd() const override { return casez() ? "casez" : casex() ? "casex" : "case"; } - bool same(const AstNode* samep) const override { + bool sameNode(const AstNode* samep) const override { return m_casex == VN_DBG_AS(samep, Case)->m_casex; } bool casex() const { return m_casex == VCaseType::CT_CASEX; } diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 326a3d77d..b792de2b0 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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 @@ int AstBasicDType::widthTotalBytes() const { } } -bool AstBasicDType::same(const AstNode* samep) const { +bool AstBasicDType::sameNode(const AstNode* samep) const { const AstBasicDType* const sp = VN_DBG_AS(samep, BasicDType); if (!(m == sp->m) || numeric() != sp->numeric()) return false; if (!rangep() && !sp->rangep()) return true; @@ -366,7 +366,35 @@ void AstConsQueue::dumpJson(std::ostream& str) const { dumpJsonBoolFunc(str, rhsIsValue); dumpJsonGen(str); } - +void AstConstraint::dump(std::ostream& str) const { + this->AstNode::dump(str); + if (isExternDef()) str << " [EXTDEF]"; + if (isExternExplicit()) + str << " [PROTOEXP]"; + else if (isExternProto()) + str << " [PROTO]"; + if (isKwdPure()) str << " [KWDPURE]"; + if (isStatic()) str << " [STATIC]"; +} +void AstConstraint::dumpJson(std::ostream& str) const { + dumpJsonBoolFunc(str, isExternDef); + dumpJsonBoolFunc(str, isExternExplicit); + dumpJsonBoolFunc(str, isExternProto); + dumpJsonBoolFunc(str, isKwdPure); + dumpJsonBoolFunc(str, isStatic); + if (baseOverride().isAny()) dumpJsonStr(str, "baseOverride", baseOverride().ascii()); + dumpJsonGen(str); +} +void AstConstraintExpr::dump(std::ostream& str) const { + this->AstNode::dump(str); + if (isDisableSoft()) str << " [DISSOFT]"; + if (isSoft()) str << " [SOFT]"; +} +void AstConstraintExpr::dumpJson(std::ostream& str) const { + dumpJsonBoolFunc(str, isDisableSoft); + dumpJsonBoolFunc(str, isSoft); + dumpJsonGen(str); +} AstConst* AstConst::parseParamLiteral(FileLine* fl, const string& literal) { bool success = false; if (literal[0] == '"') { @@ -418,7 +446,8 @@ void AstNetlist::timeprecisionMerge(FileLine*, const VTimescale& value) { } bool AstVar::isSigPublic() const { - return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar())); + return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar())) + && !isIfaceRef(); } bool AstVar::isScQuad() const { return (isSc() && isQuad() && !isScBv() && !isScBigUint()); } bool AstVar::isScBv() const { @@ -516,7 +545,7 @@ string AstVar::vlEnumType() const { string AstVar::vlEnumDir() const { string out; - if (isInoutish()) { + if (isInout()) { out = "VLVD_INOUT"; } else if (isWritable()) { out = "VLVD_OUT"; @@ -764,6 +793,25 @@ AstVar* AstVar::scVarRecurse(AstNode* nodep) { return nullptr; } +const AstNodeDType* AstNodeDType::skipRefIterp(bool skipConst, bool skipEnum) const VL_MT_STABLE { + const AstNodeDType* nodep = this; + while (true) { + if (VL_UNLIKELY(VN_IS(nodep, MemberDType) || VN_IS(nodep, ParamTypeDType) + || VN_IS(nodep, RefDType) // + || (VN_IS(nodep, ConstDType) && skipConst) // + || (VN_IS(nodep, EnumDType) && skipEnum))) { + if (const AstNodeDType* subp = nodep->subDTypep()) { + nodep = subp; + continue; + } else { + nodep->v3fatalSrc(nodep->prettyTypeName() << " not linked to type"); + return nullptr; + } + } + return nodep; + } +} + bool AstNodeDType::isFourstate() const { return basicp() && basicp()->isFourstate(); } class AstNodeDType::CTypeRecursed final { @@ -1618,9 +1666,11 @@ void AstCellInlineScope::dumpJson(std::ostream& str) const { dumpJsonGen(str); } bool AstClass::isCacheableChild(const AstNode* nodep) { - return (VN_IS(nodep, Var) || VN_IS(nodep, Constraint) || VN_IS(nodep, EnumItemRef) - || (VN_IS(nodep, NodeFTask) && !VN_AS(nodep, NodeFTask)->isExternProto()) - || VN_IS(nodep, CFunc)); + return VN_IS(nodep, Var) + || (VN_IS(nodep, Constraint) && !VN_AS(nodep, Constraint)->isExternProto()) + || VN_IS(nodep, EnumItemRef) + || (VN_IS(nodep, NodeFTask) && !VN_AS(nodep, NodeFTask)->isExternProto()) + || VN_IS(nodep, CFunc); } AstClass* AstClass::baseMostClassp() { AstClass* basep = this; @@ -1760,6 +1810,8 @@ const char* AstEnumDType::broken() const { void AstEnumItemRef::dumpJson(std::ostream& str) const { dumpJsonGen(str); } void AstIfaceRefDType::dump(std::ostream& str) const { this->AstNodeDType::dump(str); + if (isPortDecl()) str << " [PORTDECL]"; + if (isVirtual()) str << " [VIRT]"; if (cellName() != "") str << " cell=" << cellName(); if (ifaceName() != "") str << " if=" << ifaceName(); if (modportName() != "") str << " mp=" << modportName(); @@ -1774,6 +1826,8 @@ void AstIfaceRefDType::dump(std::ostream& str) const { } } void AstIfaceRefDType::dumpJson(std::ostream& str) const { + dumpJsonBoolFunc(str, isPortDecl); + dumpJsonBoolFunc(str, isVirtual); dumpJsonStrFunc(str, cellName); dumpJsonStrFunc(str, ifaceName); dumpJsonStrFunc(str, modportName); @@ -1873,7 +1927,7 @@ void AstMemberDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); str << "member"; } -AstNodeUOrStructDType* AstMemberDType::getChildStructp() const { +AstNodeUOrStructDType* AstMemberDType::getChildStructp() { AstNodeDType* subdtp = skipRefp(); while (AstNodeArrayDType* const asubdtp = VN_CAST(subdtp, NodeArrayDType)) { subdtp = asubdtp->subDTypep(); @@ -1889,10 +1943,10 @@ AstMemberSel::AstMemberSel(FileLine* fl, AstNodeExpr* fromp, AstVar* varp) this->varp(varp); dtypep(varp->dtypep()); } -bool AstMemberSel::same(const AstNode* samep) const { +bool AstMemberSel::sameNode(const AstNode* samep) const { const AstMemberSel* const sp = VN_DBG_AS(samep, MemberSel); return sp != nullptr && access() == sp->access() && fromp()->isSame(sp->fromp()) - && name() == sp->name() && varp()->same(sp->varp()); + && name() == sp->name() && varp()->sameNode(sp->varp()); } void AstMemberSel::dump(std::ostream& str) const { @@ -2221,9 +2275,11 @@ void AstPackageImport::pkgNameFrom() { } void AstPatMember::dump(std::ostream& str) const { this->AstNodeExpr::dump(str); + if (isConcat()) str << " [CONCAT]"; if (isDefault()) str << " [DEFAULT]"; } void AstPatMember::dumpJson(std::ostream& str) const { + if (isConcat()) dumpJsonBoolFunc(str, isConcat); if (isDefault()) dumpJsonBoolFunc(str, isDefault); dumpJsonGen(str); } @@ -2311,16 +2367,14 @@ void AstWildcardArrayDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); str << "[*]"; } -bool AstWildcardArrayDType::same(const AstNode* samep) const { +bool AstWildcardArrayDType::sameNode(const AstNode* samep) const { const AstWildcardArrayDType* const asamep = VN_DBG_AS(samep, WildcardArrayDType); if (!asamep->subDTypep()) return false; return (subDTypep() == asamep->subDTypep()); } -bool AstWildcardArrayDType::similarDType(const AstNodeDType* samep) const { - if (type() != samep->type()) return false; +bool AstWildcardArrayDType::similarDTypeNode(const AstNodeDType* samep) const { const AstWildcardArrayDType* const asamep = VN_DBG_AS(samep, WildcardArrayDType); - return asamep->subDTypep() - && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); + return asamep->subDTypep() && subDTypep()->similarDType(asamep->subDTypep()); } void AstSampleQueueDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); @@ -2330,16 +2384,14 @@ void AstUnsizedArrayDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); str << "[]"; } -bool AstUnsizedArrayDType::same(const AstNode* samep) const { +bool AstUnsizedArrayDType::sameNode(const AstNode* samep) const { const AstUnsizedArrayDType* const asamep = VN_DBG_AS(samep, UnsizedArrayDType); if (!asamep->subDTypep()) return false; return (subDTypep() == asamep->subDTypep()); } -bool AstUnsizedArrayDType::similarDType(const AstNodeDType* samep) const { - if (type() != samep->type()) return false; +bool AstUnsizedArrayDType::similarDTypeNode(const AstNodeDType* samep) const { const AstUnsizedArrayDType* const asamep = VN_DBG_AS(samep, UnsizedArrayDType); - return asamep->subDTypep() - && subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()); + return asamep->subDTypep() && subDTypep()->similarDType(asamep->subDTypep()); } void AstEmptyQueueDType::dumpSmall(std::ostream& str) const { this->AstNodeDType::dumpSmall(str); @@ -2368,9 +2420,9 @@ void AstVarScope::dumpJson(std::ostream& str) const { dumpJsonBoolFunc(str, isTrace); dumpJsonGen(str); } -bool AstVarScope::same(const AstNode* samep) const { +bool AstVarScope::sameNode(const AstNode* samep) const { const AstVarScope* const asamep = VN_DBG_AS(samep, VarScope); - return varp()->same(asamep->varp()) && scopep()->same(asamep->scopep()); + return varp()->sameNode(asamep->varp()) && scopep()->sameNode(asamep->scopep()); } void AstNodeVarRef::dump(std::ostream& str) const { this->AstNodeExpr::dump(str); @@ -2413,7 +2465,7 @@ const char* AstVarRef::broken() const { BROKEN_RTN(!varp()); return nullptr; } -bool AstVarRef::same(const AstNode* samep) const { return same(VN_DBG_AS(samep, VarRef)); } +bool AstVarRef::sameNode(const AstNode* samep) const { return sameNode(VN_DBG_AS(samep, VarRef)); } int AstVarRef::instrCount() const { // Account for the target of hard-coded method calls as just an address computation if (const AstCMethodHard* const callp = VN_CAST(backp(), CMethodHard)) { @@ -2425,7 +2477,7 @@ int AstVarRef::instrCount() const { void AstVar::dump(std::ostream& str) const { this->AstNode::dump(str); if (isSc()) str << " [SC]"; - if (isPrimaryIO()) str << (isInoutish() ? " [PIO]" : (isWritable() ? " [PO]" : " [PI]")); + if (isPrimaryIO()) str << (isInout() ? " [PIO]" : (isWritable() ? " [PO]" : " [PI]")); if (isIO()) str << " " << direction().ascii(); if (isConst()) str << " [CONST]"; if (isPullup()) str << " [PULLUP]"; @@ -2479,7 +2531,7 @@ void AstVar::dumpJson(std::ostream& str) const { dumpJsonBoolFunc(str, attrSFormat); dumpJsonGen(str); } -bool AstVar::same(const AstNode* samep) const { +bool AstVar::sameNode(const AstNode* samep) const { const AstVar* const asamep = VN_DBG_AS(samep, Var); return name() == asamep->name() && varType() == asamep->varType(); } @@ -2497,7 +2549,7 @@ void AstScope::dump(std::ostream& str) const { str << " [modp=" << nodeAddr(modp()) << "]"; } void AstScope::dumpJson(std::ostream& str) const { dumpJsonGen(str); } -bool AstScope::same(const AstNode* samep) const { +bool AstScope::sameNode(const AstNode* samep) const { const AstScope* const asamep = VN_DBG_AS(samep, Scope); return name() == asamep->name() && ((!aboveScopep() && !asamep->aboveScopep()) @@ -2558,11 +2610,16 @@ void AstClassOrPackageRef::dump(std::ostream& str) const { } } void AstClassOrPackageRef::dumpJson(std::ostream& str) const { dumpJsonGen(str); } -AstNodeModule* AstClassOrPackageRef::classOrPackagep() const { +AstNodeModule* AstClassOrPackageRef::classOrPackageSkipp() const { AstNode* foundp = m_classOrPackageNodep; - if (auto* const anodep = VN_CAST(foundp, Typedef)) foundp = anodep->subDTypep(); - if (auto* const anodep = VN_CAST(foundp, NodeDType)) foundp = anodep->skipRefp(); - if (auto* const anodep = VN_CAST(foundp, ClassRefDType)) foundp = anodep->classp(); + AstNode* lastp = nullptr; + while (foundp != lastp) { + lastp = foundp; + if (AstNodeDType* const anodep = VN_CAST(foundp, NodeDType)) foundp = anodep->skipRefp(); + if (AstTypedef* const anodep = VN_CAST(foundp, Typedef)) foundp = anodep->subDTypep(); + if (AstClassRefDType* const anodep = VN_CAST(foundp, ClassRefDType)) + foundp = anodep->classp(); + } return VN_CAST(foundp, NodeModule); } @@ -2606,6 +2663,8 @@ void AstNodeFTask::dump(std::ostream& str) const { if (dpiImport()) str << " [DPII]"; if (dpiOpenChild()) str << " [DPIOPENCHILD]"; if (dpiOpenParent()) str << " [DPIOPENPARENT]"; + if (isExternDef()) str << " [EXTDEF]"; + if (isExternProto()) str << " [EXTPROTO]"; if (prototype()) str << " [PROTOTYPE]"; if (pureVirtual()) str << " [PUREVIRTUAL]"; if (recursive()) str << " [RECURSIVE]"; @@ -2626,7 +2685,7 @@ bool AstNodeFTask::getPurityRecurse() const { // or any write reference to a variable that isn't an automatic function local. for (AstNode* stmtp = this->stmtsp(); stmtp; stmtp = stmtp->nextp()) { if (const AstVar* const varp = VN_CAST(stmtp, Var)) { - if (varp->isInoutish() || varp->isRef()) return false; + if (varp->isInoutOrRef()) return false; } if (!stmtp->isPure()) return false; if (stmtp->exists([](const AstNodeVarRef* const varrefp) { @@ -2643,6 +2702,8 @@ void AstNodeFTask::dumpJson(std::ostream& str) const { dumpJsonBoolFunc(str, dpiImport); dumpJsonBoolFunc(str, dpiOpenChild); dumpJsonBoolFunc(str, dpiOpenParent); + dumpJsonBoolFunc(str, isExternDef); + dumpJsonBoolFunc(str, isExternProto); dumpJsonBoolFunc(str, prototype); dumpJsonBoolFunc(str, recursive); dumpJsonBoolFunc(str, taskPublic); @@ -2880,6 +2941,7 @@ void AstCMethodHard::setPurity() { {"r_xor", true}, {"renew", false}, {"renew_copy", false}, + {"resize", false}, {"resume", false}, {"reverse", false}, {"rsort", false}, diff --git a/src/V3AstUserAllocator.h b/src/V3AstUserAllocator.h index e18aea1b1..ec7e0cd0b 100644 --- a/src/V3AstUserAllocator.h +++ b/src/V3AstUserAllocator.h @@ -7,7 +7,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,22 +27,22 @@ #include #include -template +template class AstUserAllocatorBase VL_NOT_FINAL { - static_assert(1 <= T_UserN && T_UserN <= 4, "Wrong user pointer number"); + static_assert(1 <= N_UserN && N_UserN <= 4, "Wrong user pointer number"); static_assert(std::is_base_of::value, "T_Node must be an AstNode type"); private: std::deque m_allocated; T_Data* getUserp(const T_Node* nodep) const { - if VL_CONSTEXPR_CXX17 (T_UserN == 1) { + if VL_CONSTEXPR_CXX17 (N_UserN == 1) { const VNUser user = nodep->user1u(); return user.to(); - } else if VL_CONSTEXPR_CXX17 (T_UserN == 2) { + } else if VL_CONSTEXPR_CXX17 (N_UserN == 2) { const VNUser user = nodep->user2u(); return user.to(); - } else if VL_CONSTEXPR_CXX17 (T_UserN == 3) { + } else if VL_CONSTEXPR_CXX17 (N_UserN == 3) { const VNUser user = nodep->user3u(); return user.to(); } else { @@ -52,11 +52,11 @@ private: } void setUserp(T_Node* nodep, T_Data* userp) const { - if VL_CONSTEXPR_CXX17 (T_UserN == 1) { + if VL_CONSTEXPR_CXX17 (N_UserN == 1) { nodep->user1u(VNUser{userp}); - } else if VL_CONSTEXPR_CXX17 (T_UserN == 2) { + } else if VL_CONSTEXPR_CXX17 (N_UserN == 2) { nodep->user2u(VNUser{userp}); - } else if VL_CONSTEXPR_CXX17 (T_UserN == 3) { + } else if VL_CONSTEXPR_CXX17 (N_UserN == 3) { nodep->user3u(VNUser{userp}); } else { nodep->user4u(VNUser{userp}); @@ -65,11 +65,11 @@ private: protected: AstUserAllocatorBase() { - if VL_CONSTEXPR_CXX17 (T_UserN == 1) { + if VL_CONSTEXPR_CXX17 (N_UserN == 1) { VNUser1InUse::check(); - } else if VL_CONSTEXPR_CXX17 (T_UserN == 2) { + } else if VL_CONSTEXPR_CXX17 (N_UserN == 2) { VNUser2InUse::check(); - } else if VL_CONSTEXPR_CXX17 (T_UserN == 3) { + } else if VL_CONSTEXPR_CXX17 (N_UserN == 3) { VNUser3InUse::check(); } else { VNUser4InUse::check(); @@ -107,13 +107,13 @@ public: // User pointer allocator classes. T_Node is the type of node the allocator should be applied to // and is there for a bit of extra type safety. T_Data is the type of the data structure // managed by the allocator. -template +template class AstUser1Allocator final : public AstUserAllocatorBase {}; -template +template class AstUser2Allocator final : public AstUserAllocatorBase {}; -template +template class AstUser3Allocator final : public AstUserAllocatorBase {}; -template +template class AstUser4Allocator final : public AstUserAllocatorBase {}; #endif // Guard diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index d6e881f40..4817bd0f1 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,8 +54,10 @@ public: //###################################################################### class BeginVisitor final : public VNVisitor { - // STATE + // STATE - across all visitors BeginState* const m_statep; // Current global state + + // STATE - for current visit position (use VL_RESTORER) AstNodeModule* m_modp = nullptr; // Current module AstNodeFTask* m_ftaskp = nullptr; // Current function/task AstNode* m_liftedp = nullptr; // Local nodes we are lifting into m_ftaskp @@ -145,10 +147,8 @@ class BeginVisitor final : public VNVisitor { } void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); - { - m_modp = nodep; - iterateChildren(nodep); - } + m_modp = nodep; + iterateChildren(nodep); } void visit(AstNodeFTask* nodep) override { UINFO(8, " " << nodep << endl); @@ -164,29 +164,28 @@ class BeginVisitor final : public VNVisitor { // inside the function. // Process children VL_RESTORER(m_displayScope); + VL_RESTORER(m_ftaskp); + VL_RESTORER(m_liftedp); VL_RESTORER(m_namedScope); VL_RESTORER(m_unnamedScope); - { - m_displayScope = dot(m_displayScope, nodep->name()); - m_namedScope = ""; - m_unnamedScope = ""; - m_ftaskp = nodep; - m_liftedp = nullptr; - iterateChildren(nodep); - nodep->foreach([&](AstInitialStatic* const initp) { - initp->unlinkFrBack(); - m_ftaskp->addHereThisAsNext(initp); - }); - if (m_liftedp) { - // Place lifted nodes at beginning of stmtsp, so Var nodes appear before referenced - if (AstNode* const stmtsp = nodep->stmtsp()) { - stmtsp->unlinkFrBackWithNext(); - m_liftedp->addNext(stmtsp); - } - nodep->addStmtsp(m_liftedp); - m_liftedp = nullptr; + m_displayScope = dot(m_displayScope, nodep->name()); + m_namedScope = ""; + m_unnamedScope = ""; + m_ftaskp = nodep; + m_liftedp = nullptr; + iterateChildren(nodep); + nodep->foreach([&](AstInitialStatic* const initp) { + initp->unlinkFrBack(); + m_ftaskp->addHereThisAsNext(initp); + }); + if (m_liftedp) { + // Place lifted nodes at beginning of stmtsp, so Var nodes appear before referenced + if (AstNode* const stmtsp = nodep->stmtsp()) { + stmtsp->unlinkFrBackWithNext(); + m_liftedp->addNext(stmtsp); } - m_ftaskp = nullptr; + nodep->addStmtsp(m_liftedp); + m_liftedp = nullptr; } } void visit(AstBegin* nodep) override { @@ -196,30 +195,28 @@ class BeginVisitor final : public VNVisitor { VL_RESTORER(m_namedScope); VL_RESTORER(m_unnamedScope); { - { - VL_RESTORER(m_keepBegins); - m_keepBegins = false; - dotNames(nodep, "__BEGIN__"); - } - UASSERT_OBJ(!nodep->genforp(), nodep, "GENFORs should have been expanded earlier"); - - // Cleanup - if (m_keepBegins) { - nodep->name(""); - return; - } - AstNode* addsp = nullptr; - if (AstNode* const stmtsp = nodep->stmtsp()) { - stmtsp->unlinkFrBackWithNext(); - addsp = AstNode::addNext(addsp, stmtsp); - } - if (addsp) { - nodep->replaceWith(addsp); - } else { - nodep->unlinkFrBack(); - } - VL_DO_DANGLING(pushDeletep(nodep), nodep); + VL_RESTORER(m_keepBegins); + m_keepBegins = false; + dotNames(nodep, "__BEGIN__"); } + UASSERT_OBJ(!nodep->genforp(), nodep, "GENFORs should have been expanded earlier"); + + // Cleanup + if (m_keepBegins) { + nodep->name(""); + return; + } + AstNode* addsp = nullptr; + if (AstNode* const stmtsp = nodep->stmtsp()) { + stmtsp->unlinkFrBackWithNext(); + addsp = AstNode::addNext(addsp, stmtsp); + } + if (addsp) { + nodep->replaceWith(addsp); + } else { + nodep->unlinkFrBack(); + } + VL_DO_DANGLING(pushDeletep(nodep), nodep); } void visit(AstVar* nodep) override { // If static variable, move it outside a function. @@ -427,6 +424,7 @@ AstNode* V3Begin::convertToWhile(AstForeach* nodep) { AstNode* bodyPointp = new AstBegin{nodep->fileline(), "[EditWrapper]", nullptr}; AstNode* newp = nullptr; AstNode* lastp = nodep; + AstVar* nestedIndexp = nullptr; // subfromp used to traverse each dimension of multi-d variable-sized unpacked array (queue, // dyn-arr and associative-arr) AstNodeExpr* subfromp = fromp->cloneTreePure(false); @@ -459,8 +457,13 @@ AstNode* V3Begin::convertToWhile(AstForeach* nodep) { } } else if (VN_IS(fromDtp, DynArrayDType) || VN_IS(fromDtp, QueueDType)) { AstConst* const leftp = new AstConst{fl, 0}; - AstNodeExpr* const rightp - = new AstCMethodHard{fl, subfromp->cloneTreePure(false), "size"}; + AstNodeExpr* const rightp = new AstCMethodHard{ + fl, + VN_IS(subfromp->dtypep(), NodeArrayDType) + ? new AstArraySel{fl, subfromp->cloneTreePure(false), + new AstVarRef{fl, nestedIndexp, VAccess::READ}} + : subfromp->cloneTreePure(false), + "size"}; AstVarRef* varRefp = new AstVarRef{fl, varp, VAccess::READ}; subfromp = new AstCMethodHard{fl, subfromp, "at", varRefp}; subfromp->dtypep(fromDtp); @@ -511,6 +514,7 @@ AstNode* V3Begin::convertToWhile(AstForeach* nodep) { if (!newp) newp = loopp; } // Prep for next + nestedIndexp = varp; fromDtp = fromDtp->subDTypep(); } // The parser validates we don't have "foreach (array[,,,])" diff --git a/src/V3Begin.h b/src/V3Begin.h index 5be8886e0..1abb06096 100644 --- a/src/V3Begin.h +++ b/src/V3Begin.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 e26b066ee..56ee3f0b8 100644 --- a/src/V3Branch.cpp +++ b/src/V3Branch.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 5d7f291c8..7b9cfbbca 100644 --- a/src/V3Branch.h +++ b/src/V3Branch.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 29910f209..e1b5a73fd 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.h b/src/V3Broken.h index 7e8f7c099..f184f4d67 100644 --- a/src/V3Broken.h +++ b/src/V3Broken.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 afffc75c4..045628e6a 100644 --- a/src/V3CCtors.cpp +++ b/src/V3CCtors.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.h b/src/V3CCtors.h index aa8b84f38..fedf500d0 100644 --- a/src/V3CCtors.h +++ b/src/V3CCtors.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 d40abd5b5..1f90291c7 100644 --- a/src/V3CUse.cpp +++ b/src/V3CUse.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.h b/src/V3CUse.h index 8102c823e..463c4fd69 100644 --- a/src/V3CUse.h +++ b/src/V3CUse.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 403f0ac00..b00190ebd 100644 --- a/src/V3Case.cpp +++ b/src/V3Case.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.h b/src/V3Case.h index bc2fdac11..98ce9fe73 100644 --- a/src/V3Case.h +++ b/src/V3Case.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 4f6897472..3cbd14b09 100644 --- a/src/V3Cast.cpp +++ b/src/V3Cast.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2024 by Wilson Snyder. This program is free software; you +// Copyright 2004-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.h b/src/V3Cast.h index 15cee107e..668f22765 100644 --- a/src/V3Cast.h +++ b/src/V3Cast.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2024 by Wilson Snyder. This program is free software; you +// Copyright 2004-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 5d187a5c0..656ce3db2 100644 --- a/src/V3Class.cpp +++ b/src/V3Class.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -129,24 +129,20 @@ class ClassVisitor final : public VNVisitor { VL_RESTORER(m_classScopep); VL_RESTORER(m_packageScopep); VL_RESTORER(m_modp); - { - m_modp = nodep; - m_classPackagep = packagep; - m_classScopep = classScopep; - m_packageScopep = scopep; - m_prefix = nodep->name() + "__02e"; // . - iterateChildren(nodep); - } + m_modp = nodep; + m_classPackagep = packagep; + m_classScopep = classScopep; + m_packageScopep = scopep; + m_prefix = nodep->name() + "__02e"; // . + iterateChildren(nodep); } 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); - } + m_modp = nodep; + m_prefix = nodep->name() + "__03a__03a"; // :: + iterateChildren(nodep); } void visit(AstVar* nodep) override { @@ -174,12 +170,10 @@ class ClassVisitor final : public VNVisitor { void visit(AstNodeFTask* nodep) override { VL_RESTORER(m_ftaskp); - { - m_ftaskp = nodep; - iterateChildren(nodep); - if (m_packageScopep && nodep->isStatic()) { - m_toScopeMoves.emplace_back(nodep, m_packageScopep); - } + m_ftaskp = nodep; + iterateChildren(nodep); + if (m_packageScopep && nodep->isStatic()) { + m_toScopeMoves.emplace_back(nodep, m_packageScopep); } } void visit(AstCFunc* nodep) override { @@ -214,7 +208,7 @@ class ClassVisitor final : public VNVisitor { m_names.get(dtypep->name() + (VN_IS(dtypep, UnionDType) ? "__union" : "__struct"))); if (dtypep->packed()) m_strDtypeps.insert(dtypep); - for (const AstMemberDType* itemp = dtypep->membersp(); itemp; + for (AstMemberDType* itemp = dtypep->membersp(); itemp; itemp = VN_AS(itemp->nextp(), MemberDType)) { AstNodeUOrStructDType* const subp = itemp->getChildStructp(); // Recurse only into anonymous structs inside this definition, @@ -277,7 +271,7 @@ public: AstNodeUOrStructDType* const dtypep = m_pubStrDtypeps.front(); m_pubStrDtypeps.pop(); if (pubStrDtypeps.insert(dtypep).second) { - for (const AstMemberDType* itemp = dtypep->membersp(); itemp; + for (AstMemberDType* itemp = dtypep->membersp(); itemp; itemp = VN_AS(itemp->nextp(), MemberDType)) { if (AstNodeUOrStructDType* const subp = itemp->getChildStructp()) m_pubStrDtypeps.push(subp); diff --git a/src/V3Class.h b/src/V3Class.h index d23c4bd21..c5703879e 100644 --- a/src/V3Class.h +++ b/src/V3Class.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 9acb79559..ca3a16246 100644 --- a/src/V3Clean.cpp +++ b/src/V3Clean.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -173,10 +173,8 @@ class CleanVisitor final : public VNVisitor { // VISITORS void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); - { - m_modp = nodep; - iterateChildren(nodep); - } + m_modp = nodep; + iterateChildren(nodep); } void visit(AstNodeUniop* nodep) override { iterateChildren(nodep); diff --git a/src/V3Clean.h b/src/V3Clean.h index f7d40f4fc..a93a4f854 100644 --- a/src/V3Clean.h +++ b/src/V3Clean.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 4739d6982..a813f7b80 100644 --- a/src/V3Clock.cpp +++ b/src/V3Clock.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 f7fc9d31d..6ea26fede 100644 --- a/src/V3Clock.h +++ b/src/V3Clock.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 45160d3f3..2dd9574a9 100644 --- a/src/V3Combine.cpp +++ b/src/V3Combine.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 3f84519c8..2c2aed5c6 100644 --- a/src/V3Combine.h +++ b/src/V3Combine.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 abf3eb5e0..3d0f08885 100644 --- a/src/V3Common.cpp +++ b/src/V3Common.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.h b/src/V3Common.h index 249b985e0..17fd3b235 100644 --- a/src/V3Common.h +++ b/src/V3Common.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 b90855564..9b8d38a61 100644 --- a/src/V3Config.cpp +++ b/src/V3Config.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2010-2024 by Wilson Snyder. This program is free software; you +// Copyright 2010-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -118,6 +118,70 @@ public: using V3ConfigVarResolver = V3ConfigWildcardResolver; +//====================================================================== + +class WildcardContents final { + // Not mutex protected, current calling from V3Config::waive is protected by error's mutex + // MEMBERS + std::map m_mapPatterns; // Pattern match results + std::deque m_lines; // Source text lines + + // METHODS + static WildcardContents& s() { // Singleton + static WildcardContents s_s; + return s_s; + } + void clearCacheImp() { m_mapPatterns.clear(); } + void pushTextImp(const string& text) { + // Similar code in VFileContent::pushText() + // Any leftover text is stored on largest line (might be "") + const string leftover = m_lines.back() + text; + m_lines.pop_back(); + + // Insert line-by-line + string::size_type line_start = 0; + while (true) { + const string::size_type line_end = leftover.find('\n', line_start); + if (line_end != string::npos) { + const string oneline(leftover, line_start, line_end - line_start + 1); + if (oneline.size() > 1) m_lines.push_back(oneline); // Keeps newline + UINFO(9, "Push[+" << (m_lines.size() - 1) << "]: " << oneline); + line_start = line_end + 1; + } else { + break; + } + } + // Keep leftover for next time + m_lines.emplace_back(string(leftover, line_start)); // Might be "" + clearCacheImp(); + } + + bool resolveUncachedImp(const string& name) { + for (const string& i : m_lines) { + if (VString::wildmatch(i, name)) return true; + } + return false; + } + bool resolveCachedImp(const string& name) { + // Lookup if it was resolved before, typically is + const auto pair = m_mapPatterns.emplace(name, false); + bool& entryr = pair.first->second; + // Resolve entry when first requested, cache the result + if (pair.second) entryr = resolveUncachedImp(name); + return entryr; + } + +public: + WildcardContents() { + m_lines.emplace_back(""); // start with no leftover + } + ~WildcardContents() = default; + // Return true iff name in parsed contents + static bool resolve(const string& name) { return s().resolveCachedImp(name); } + // Add arbitrary text (need not be line-by-line) + static void pushText(const string& text) { s().pushTextImp(text); } +}; + //###################################################################### // Function or task: Have variables and properties @@ -256,11 +320,28 @@ std::ostream& operator<<(std::ostream& os, const V3ConfigIgnoresLine& rhs) { // and multiple attributes can be attached to a line using V3ConfigLineAttribute = std::bitset; +class WaiverSetting final { +public: + V3ErrorCode m_code; // Error code + string m_contents; // --contents regexp + string m_match; // --match regexp + WaiverSetting(V3ErrorCode code, const string& contents, const string& match) + : m_code{code} + , m_contents{contents} + , m_match{match} {} + ~WaiverSetting() = default; + WaiverSetting& operator=(const WaiverSetting& rhs) { + m_code = rhs.m_code; + m_contents = rhs.m_contents; + m_match = rhs.m_match; + return *this; + } +}; + // File entity class V3ConfigFile final { using LineAttrMap = std::map; // Map line->bitset of attributes using IgnLines = std::multiset; // list of {line,code,on} - using WaiverSetting = std::pair; // Waive code if string matches using Waivers = std::vector; // List of {code,wildcard string} LineAttrMap m_lineAttrs; // Attributes to line mapping @@ -299,8 +380,12 @@ public: m_ignLines.insert(V3ConfigIgnoresLine{code, lineno, on}); m_lastIgnore.it = m_ignLines.begin(); } - void addIgnoreMatch(V3ErrorCode code, const string& match) { - m_waivers.emplace_back(code, match); + void addIgnoreMatch(V3ErrorCode code, const string& contents, const string& match) { + // Since Verilator 5.031 the error message compared has context, so + // allow old rules to still match using a final '*' + string newMatch = match; + if (newMatch.empty() || newMatch.back() != '*') newMatch += '*'; + m_waivers.emplace_back(WaiverSetting{code, contents, newMatch}); } void applyBlock(AstNodeBlock* nodep) { @@ -338,8 +423,9 @@ public: bool waive(V3ErrorCode code, const string& match) { if (code.hardError()) return false; for (const auto& itr : m_waivers) { - if ((code.isUnder(itr.first) || (itr.first == V3ErrorCode::I_LINT)) - && VString::wildmatch(match, itr.second)) { + if ((code.isUnder(itr.m_code) || (itr.m_code == V3ErrorCode::I_LINT)) + && VString::wildmatch(match, itr.m_match) + && WildcardContents::resolve(itr.m_contents)) { return true; } } @@ -512,8 +598,9 @@ void V3Config::addIgnore(V3ErrorCode code, bool on, const string& filename, int } } -void V3Config::addIgnoreMatch(V3ErrorCode code, const string& filename, const string& match) { - V3ConfigResolver::s().files().at(filename).addIgnoreMatch(code, match); +void V3Config::addIgnoreMatch(V3ErrorCode code, const string& filename, const string& contents, + const string& match) { + V3ConfigResolver::s().files().at(filename).addIgnoreMatch(code, contents, match); } void V3Config::addInline(FileLine* fl, const string& module, const string& ftask, bool on) { @@ -647,6 +734,8 @@ bool V3Config::getScopeTraceOn(const string& scope) { return V3ConfigResolver::s().scopeTraces().getScopeTraceOn(scope); } +void V3Config::contentsPushText(const string& text) { return WildcardContents::pushText(text); } + bool V3Config::waive(FileLine* filelinep, V3ErrorCode code, const string& message) { V3ConfigFile* filep = V3ConfigResolver::s().files().resolve(filelinep->filename()); if (!filep) return false; diff --git a/src/V3Config.h b/src/V3Config.h index f5e0668b0..32ee079c0 100644 --- a/src/V3Config.h +++ b/src/V3Config.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2010-2024 by Wilson Snyder. This program is free software; you +// Copyright 2010-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,8 @@ public: static void addCoverageBlockOff(const string& file, int lineno); static void addCoverageBlockOff(const string& module, const string& blockname); static void addIgnore(V3ErrorCode code, bool on, const string& filename, int min, int max); - static void addIgnoreMatch(V3ErrorCode code, const string& filename, const string& match); + static void addIgnoreMatch(V3ErrorCode code, const string& filename, const string& contents, + const string& match); static void addInline(FileLine* fl, const string& module, const string& ftask, bool on); static void addModulePragma(const string& module, VPragmaType pragma); static void addProfileData(FileLine* fl, const string& model, const string& key, @@ -53,6 +54,9 @@ public: static uint64_t getProfileData(const string& model, const string& key); static FileLine* getProfileDataFileLine(); static bool getScopeTraceOn(const string& scope); + + static void contentsPushText(const string& text); + static bool waive(FileLine* filelinep, V3ErrorCode code, const string& message); }; diff --git a/src/V3Const.cpp b/src/V3Const.cpp index dbe81ed4a..406f4c815 100644 --- a/src/V3Const.cpp +++ b/src/V3Const.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -57,7 +57,7 @@ static bool isConst(const AstNode* nodep, uint64_t v) { return constp && constp->toUQuad() == v; } -template +template static typename std::enable_if::value, bool>::type isPow2(T val) { return (val & (val - 1)) == 0; } @@ -227,7 +227,7 @@ class ConstBitOpTreeVisitor final : public VNVisitorConst { return m_knownResult == 1; } const AstVarRef* refp() const { return m_refp; } - bool sameVarAs(const AstNodeVarRef* otherp) const { return m_refp->same(otherp); } + bool sameVarAs(const AstNodeVarRef* otherp) const { return m_refp->sameNode(otherp); } void setPolarity(bool compBit, int bit) { // Ignore if already determined a known reduction if (m_knownResult >= 0) return; @@ -2333,20 +2333,16 @@ class ConstVisitor final : public VNVisitor { } void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); - { - m_modp = nodep; - m_concswapNames.reset(); - iterateChildren(nodep); - } + m_modp = nodep; + m_concswapNames.reset(); + iterateChildren(nodep); } void visit(AstCFunc* nodep) override { // No ASSIGNW removals under funcs, we've long eliminated INITIALs // (We should perhaps rename the assignw's to just assigns) VL_RESTORER(m_wremove); - { - m_wremove = false; - iterateChildren(nodep); - } + m_wremove = false; + iterateChildren(nodep); } void visit(AstCLocalScope* nodep) override { iterateChildren(nodep); @@ -2359,11 +2355,9 @@ class ConstVisitor final : public VNVisitor { // No ASSIGNW removals under scope, we've long eliminated INITIALs VL_RESTORER(m_wremove); VL_RESTORER(m_scopep); - { - m_wremove = false; - m_scopep = nodep; - iterateChildren(nodep); - } + m_wremove = false; + m_scopep = nodep; + iterateChildren(nodep); } void swapSides(AstNodeBiCom* nodep) { @@ -2695,10 +2689,8 @@ class ConstVisitor final : public VNVisitor { void visit(AstAttrOf* nodep) override { VL_RESTORER(m_attrp); - { - m_attrp = nodep; - iterateChildren(nodep); - } + m_attrp = nodep; + iterateChildren(nodep); } void visit(AstArraySel* nodep) override { diff --git a/src/V3Const.h b/src/V3Const.h index 5395a7cb4..1491f7714 100644 --- a/src/V3Const.h +++ b/src/V3Const.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 7f36c409f..afb674551 100644 --- a/src/V3Coverage.cpp +++ b/src/V3Coverage.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.h b/src/V3Coverage.h index a084ba3e5..8e8e9500b 100644 --- a/src/V3Coverage.h +++ b/src/V3Coverage.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 cf0e607a7..86fa0ea6a 100644 --- a/src/V3CoverageJoin.cpp +++ b/src/V3CoverageJoin.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 57da38d8b..0356c8f35 100644 --- a/src/V3CoverageJoin.h +++ b/src/V3CoverageJoin.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 f2657d703..d96a7d54c 100644 --- a/src/V3Dead.cpp +++ b/src/V3Dead.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -109,16 +109,16 @@ class DeadVisitor final : public VNVisitor { if (m_modp) m_modp->user1Inc(); // e.g. Class under Package VL_RESTORER(m_modp); m_modp = nodep; - if (!nodep->dead()) { - iterateChildren(nodep); - checkAll(nodep); - if (AstClass* const classp = VN_CAST(nodep, Class)) { - if (classp->extendsp()) classp->extendsp()->user1Inc(); - if (classp->classOrPackagep()) classp->classOrPackagep()->user1Inc(); - m_classesp.push_back(classp); - // TODO we don't reclaim dead classes yet - graph implementation instead? - classp->user1Inc(); - } + if (nodep->dead()) return; + if (nodep->modPublic()) m_modp->user1Inc(); + iterateChildren(nodep); + checkAll(nodep); + if (AstClass* const classp = VN_CAST(nodep, Class)) { + if (classp->extendsp()) classp->extendsp()->user1Inc(); + if (classp->classOrPackagep()) classp->classOrPackagep()->user1Inc(); + m_classesp.push_back(classp); + // TODO we don't reclaim dead classes yet - graph implementation instead? + classp->user1Inc(); } } void visit(AstCFunc* nodep) override { @@ -540,7 +540,7 @@ public: void V3Dead::deadifyModules(AstNetlist* nodep) { UINFO(2, __FUNCTION__ << ": " << endl); - { + { // node, elimUserVars, elimDTypes, elimScopes, elimCells, elimTopIfaces DeadVisitor{nodep, false, false, false, false, !v3Global.opt.topIfacesSupported()}; } // Destruct before checking V3Global::dumpCheckGlobalTree("deadModules", 0, dumpTreeEitherLevel() >= 6); diff --git a/src/V3Dead.h b/src/V3Dead.h index 17bc01243..740af0029 100644 --- a/src/V3Dead.h +++ b/src/V3Dead.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 5edee1370..6b885b1d9 100644 --- a/src/V3Delayed.cpp +++ b/src/V3Delayed.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -251,10 +251,11 @@ class DelayedVisitor final : public VNVisitor { const AstNodeDType* const dtypep = vscp->dtypep()->skipRefp(); // Unpacked arrays if (const AstUnpackArrayDType* const uaDTypep = VN_CAST(dtypep, UnpackArrayDType)) { + // Basic underlying type of elements, if any. + AstBasicDType* const basicp = uaDTypep->basicp(); // If used in a loop, we must have a dynamic commit queue. (Also works in suspendables) if (vscpInfo.m_inLoop) { // Arrays with compound element types are currently not supported in loops - AstBasicDType* const basicp = uaDTypep->basicp(); if (!basicp || !(basicp->isIntegralOrPacked() // || basicp->isDouble() // @@ -266,8 +267,12 @@ class DelayedVisitor final : public VNVisitor { } // In a suspendable of fork, we must use the unique flag scheme, TODO: why? if (vscpInfo.m_inSuspOrFork) return Scheme::FlagUnique; - // Otherwise use the shared flag scheme - return Scheme::FlagShared; + // Otherwise if an array of packed/basic elements, use the shared flag scheme + if (basicp) return Scheme::FlagShared; + // Finally fall back on the shadow variable scheme, e.g. for + // arrays of unpacked structs. This will be slow. + // TODO: generic LHS scheme as discussed in #5092 + return Scheme::ShadowVar; } // In a suspendable of fork, we must use the unique flag scheme, TODO: why? @@ -529,17 +534,17 @@ class DelayedVisitor final : public VNVisitor { } // Scheme::ValueQueuePartial/Scheme::ValueQueueWhole - template + template void prepareSchemeValueQueue(AstVarScope* vscp, VarScopeInfo& vscpInfo) { - UASSERT_OBJ(Partial ? vscpInfo.m_scheme == Scheme::ValueQueuePartial - : vscpInfo.m_scheme == Scheme::ValueQueueWhole, + UASSERT_OBJ(N_Partial ? vscpInfo.m_scheme == Scheme::ValueQueuePartial + : vscpInfo.m_scheme == Scheme::ValueQueueWhole, vscp, "Inconsistencheme"); FileLine* const flp = vscp->fileline(); AstScope* const scopep = vscp->scopep(); // Create the commit queue variable auto* const cqDTypep - = new AstNBACommitQueueDType{flp, vscp->dtypep()->skipRefp(), Partial}; + = new AstNBACommitQueueDType{flp, vscp->dtypep()->skipRefp(), N_Partial}; v3Global.rootp()->typeTablep()->addTypesp(cqDTypep); const std::string name = "__VdlyCommitQueue" + vscp->varp()->shortName(); AstVarScope* const queueVscp = createTemp(flp, scopep, name, cqDTypep); @@ -891,6 +896,7 @@ class DelayedVisitor final : public VNVisitor { ifp->addThensp(newp); } + UASSERT_OBJ(m_activep, nodep, "No active to handle FireEvent"); AstActive* const activep = new AstActive{flp, "nba-event", m_activep->sensesp()}; m_activep->addNextHere(activep); activep->addStmtsp(prep); diff --git a/src/V3Delayed.h b/src/V3Delayed.h index d01e25f5c..c1b8e7ea4 100644 --- a/src/V3Delayed.h +++ b/src/V3Delayed.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 25a294268..d28db344d 100644 --- a/src/V3Depth.cpp +++ b/src/V3Depth.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -71,35 +71,29 @@ class DepthVisitor final : public VNVisitor { void visit(AstCFunc* nodep) override { VL_RESTORER(m_cfuncp); VL_RESTORER(m_mtaskbodyp); - { - m_cfuncp = nodep; - m_mtaskbodyp = nullptr; - m_depth = 0; - m_maxdepth = 0; - m_tempNames.reset(); - iterateChildren(nodep); - } + m_cfuncp = nodep; + m_mtaskbodyp = nullptr; + m_depth = 0; + m_maxdepth = 0; + m_tempNames.reset(); + iterateChildren(nodep); } void visit(AstMTaskBody* nodep) override { VL_RESTORER(m_cfuncp); VL_RESTORER(m_mtaskbodyp); - { - m_cfuncp = nullptr; - m_mtaskbodyp = nodep; - m_depth = 0; - m_maxdepth = 0; - // We don't reset the names, as must share across tasks - iterateChildren(nodep); - } + m_cfuncp = nullptr; + m_mtaskbodyp = nodep; + m_depth = 0; + m_maxdepth = 0; + // We don't reset the names, as must share across tasks + iterateChildren(nodep); } void visitStmt(AstNodeStmt* nodep) { VL_RESTORER(m_stmtp); - { - m_stmtp = nodep; - m_depth = 0; - m_maxdepth = 0; - iterateChildren(nodep); - } + m_stmtp = nodep; + m_depth = 0; + m_maxdepth = 0; + iterateChildren(nodep); } void visit(AstNodeStmt* nodep) override { visitStmt(nodep); } // Operators diff --git a/src/V3Depth.h b/src/V3Depth.h index d563d2ad9..01c305f14 100644 --- a/src/V3Depth.h +++ b/src/V3Depth.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 54fa3f2b6..21b30e411 100644 --- a/src/V3DepthBlock.cpp +++ b/src/V3DepthBlock.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,21 +70,17 @@ class DepthBlockVisitor final : public VNVisitor { void visit(AstNodeModule* nodep) override { UINFO(4, " MOD " << nodep << endl); VL_RESTORER(m_modp); - { - m_modp = nodep; - m_deepNum = 0; - iterateChildren(nodep); - } + m_modp = nodep; + m_deepNum = 0; + iterateChildren(nodep); } void visit(AstCFunc* nodep) override { // We recurse into this. VL_RESTORER(m_depth); VL_RESTORER(m_cfuncp); - { - m_depth = 0; - m_cfuncp = nodep; - iterateChildren(nodep); - } + m_depth = 0; + m_cfuncp = nodep; + iterateChildren(nodep); } void visit(AstStmtExpr* nodep) override {} // Stop recursion after introducing new function void visit(AstJumpBlock*) override {} // Stop recursion as can't break up across a jump diff --git a/src/V3DepthBlock.h b/src/V3DepthBlock.h index cc1bcbfa0..9d91b4ef8 100644 --- a/src/V3DepthBlock.h +++ b/src/V3DepthBlock.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 42c718c9b..b4b403fc2 100644 --- a/src/V3Descope.cpp +++ b/src/V3Descope.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -208,13 +208,11 @@ class DescopeVisitor final : public VNVisitor { // VISITORS void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); - { - m_modp = nodep; - m_modFuncs.clear(); - m_modSingleton = modIsSingleton(m_modp); - iterateChildren(nodep); - makePublicFuncWrappers(); - } + m_modp = nodep; + m_modFuncs.clear(); + m_modSingleton = modIsSingleton(m_modp); + iterateChildren(nodep); + makePublicFuncWrappers(); } void visit(AstScope* nodep) override { m_scopep = nodep; diff --git a/src/V3Descope.h b/src/V3Descope.h index f94f59d5a..d403fb75b 100644 --- a/src/V3Descope.h +++ b/src/V3Descope.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 7df05cbb4..0cbc69966 100644 --- a/src/V3Dfg.cpp +++ b/src/V3Dfg.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 5fab278ee..3a6e9f154 100644 --- a/src/V3Dfg.h +++ b/src/V3Dfg.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -427,52 +427,52 @@ public: // Implementation of dataflow graph vertices with a fixed number of sources //------------------------------------------------------------------------------ -template +template class DfgVertexWithArity VL_NOT_FINAL : public DfgVertex { - static_assert(1 <= Arity && Arity <= 4, "Arity must be between 1 and 4 inclusive"); + static_assert(1 <= N_Arity && N_Arity <= 4, "N_Arity must be between 1 and 4 inclusive"); - std::array m_srcs; // Source edges + std::array m_srcs; // Source edges protected: DfgVertexWithArity(DfgGraph& dfg, VDfgType type, FileLine* flp, AstNodeDType* dtypep) : DfgVertex{dfg, type, flp, dtypep} { // Initialize source edges - for (size_t i = 0; i < Arity; ++i) m_srcs[i].init(this); + for (size_t i = 0; i < N_Arity; ++i) m_srcs[i].init(this); } ~DfgVertexWithArity() override = default; public: std::pair sourceEdges() final override { // - return {m_srcs.data(), Arity}; + return {m_srcs.data(), N_Arity}; } std::pair sourceEdges() const final override { - return {m_srcs.data(), Arity}; + return {m_srcs.data(), N_Arity}; } - template + template DfgEdge* sourceEdge() { - static_assert(Index < Arity, "Source index out of range"); - return &m_srcs[Index]; + static_assert(N_Index < N_Arity, "Source index out of range"); + return &m_srcs[N_Index]; } - template + template const DfgEdge* sourceEdge() const { - static_assert(Index < Arity, "Source index out of range"); - return &m_srcs[Index]; + static_assert(N_Index < N_Arity, "Source index out of range"); + return &m_srcs[N_Index]; } - template + template DfgVertex* source() const { - static_assert(Index < Arity, "Source index out of range"); - return m_srcs[Index].sourcep(); + static_assert(N_Index < N_Arity, "Source index out of range"); + return m_srcs[N_Index].sourcep(); } - template + template void relinkSource(DfgVertex* newSourcep) { - static_assert(Index < Arity, "Source index out of range"); - UASSERT_OBJ(m_srcs[Index].sinkp() == this, this, "Inconsistent"); - m_srcs[Index].relinkSource(newSourcep); + static_assert(N_Index < N_Arity, "Source index out of range"); + UASSERT_OBJ(m_srcs[N_Index].sinkp() == this, this, "Inconsistent"); + m_srcs[N_Index].relinkSource(newSourcep); } }; diff --git a/src/V3DfgAstToDfg.cpp b/src/V3DfgAstToDfg.cpp index f61380f77..aa5f8715e 100644 --- a/src/V3DfgAstToDfg.cpp +++ b/src/V3DfgAstToDfg.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -37,9 +37,9 @@ namespace { // Create a DfgVertex out of a AstNodeExpr. For most AstNodeExpr subtypes, this can be done // automatically. For the few special cases, we provide specializations below -template -Vertex* makeVertex(const Node* nodep, DfgGraph& dfg) { - return new Vertex{dfg, nodep->fileline(), DfgVertex::dtypeFor(nodep)}; +template +T_Vertex* makeVertex(const T_Node* nodep, DfgGraph& dfg) { + return new T_Vertex{dfg, nodep->fileline(), DfgVertex::dtypeFor(nodep)}; } //====================================================================== diff --git a/src/V3DfgCache.cpp b/src/V3DfgCache.cpp index 036578e2b..f1abdda69 100644 --- a/src/V3DfgCache.cpp +++ b/src/V3DfgCache.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3DfgCache.h b/src/V3DfgCache.h index 09df39f6c..469130340 100644 --- a/src/V3DfgCache.h +++ b/src/V3DfgCache.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -157,8 +157,8 @@ public: }; }; -template -using Cache = std::unordered_map; +template +using Cache = std::unordered_map; using CacheSel = Cache; using CacheUnary = Cache; @@ -246,10 +246,10 @@ inline void setOperands(DfgVertexTernary* vtxp, DfgVertex* src0p, DfgVertex* src } // Get or create (and insert) vertex with given operands -template -inline Vertex* getOrCreate(DfgGraph& dfg, FileLine* flp, AstNodeDType* dtypep, Cache& cache, +template +inline Vertex* getOrCreate(DfgGraph& dfg, FileLine* flp, AstNodeDType* dtypep, T_Cache& cache, Operands... operands) { - typename Cache::mapped_type& entrypr = getEntry(cache, dtypep, operands...); + typename T_Cache::mapped_type& entrypr = getEntry(cache, dtypep, operands...); if (!entrypr) { Vertex* const newp = new Vertex{dfg, flp, dtypep}; setOperands(newp, operands...); diff --git a/src/V3DfgDecomposition.cpp b/src/V3DfgDecomposition.cpp index 815b960c5..a6b540763 100644 --- a/src/V3DfgDecomposition.cpp +++ b/src/V3DfgDecomposition.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3DfgDfgToAst.cpp b/src/V3DfgDfgToAst.cpp index ee7b0c078..64a135e33 100644 --- a/src/V3DfgDfgToAst.cpp +++ b/src/V3DfgDfgToAst.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,9 +40,9 @@ namespace { // Create an AstNodeExpr out of a DfgVertex. For most AstNodeExpr subtypes, this can be done // automatically. For the few special cases, we provide specializations below -template -Node* makeNode(const Vertex* vtxp, Ops... ops) { - Node* const nodep = new Node{vtxp->fileline(), ops...}; +template +T_Node* makeNode(const T_Vertex* vtxp, Ops... ops) { + T_Node* const nodep = new T_Node{vtxp->fileline(), ops...}; UASSERT_OBJ(nodep->width() == static_cast(vtxp->width()), vtxp, "Incorrect width in AstNode created from DfgVertex " << vtxp->typeName() << ": " << nodep->width() << " vs " << vtxp->width()); diff --git a/src/V3DfgOptimizer.cpp b/src/V3DfgOptimizer.cpp index d6c6f1f30..32aba69d2 100644 --- a/src/V3DfgOptimizer.cpp +++ b/src/V3DfgOptimizer.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 067b5e801..d7c400f4d 100644 --- a/src/V3DfgOptimizer.h +++ b/src/V3DfgOptimizer.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 d67642e8c..cf3151720 100644 --- a/src/V3DfgPasses.cpp +++ b/src/V3DfgPasses.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 2b1e08aa6..59eb73312 100644 --- a/src/V3DfgPasses.h +++ b/src/V3DfgPasses.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3DfgPatternStats.h b/src/V3DfgPatternStats.h index cd511a6fc..6163c7505 100644 --- a/src/V3DfgPatternStats.h +++ b/src/V3DfgPatternStats.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 531d5c35b..1e21ea675 100644 --- a/src/V3DfgPeephole.cpp +++ b/src/V3DfgPeephole.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -152,7 +152,7 @@ class V3DfgPeephole final : public DfgVisitor { // METHODS bool checkApplying(VDfgPeepholePattern id) { if (!m_ctx.m_enabled[id]) return false; - UINFO(9, "Applying DFG patten " << id.ascii() << endl); + UINFO(9, "Applying DFG pattern " << id.ascii() << endl); ++m_ctx.m_count[id]; return true; } diff --git a/src/V3DfgPeephole.h b/src/V3DfgPeephole.h index ff3debe57..02895dfa0 100644 --- a/src/V3DfgPeephole.h +++ b/src/V3DfgPeephole.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3DfgRegularize.cpp b/src/V3DfgRegularize.cpp index e521a5ebe..182b891bb 100644 --- a/src/V3DfgRegularize.cpp +++ b/src/V3DfgRegularize.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 44d2361ea..728327637 100644 --- a/src/V3DfgVertices.h +++ b/src/V3DfgVertices.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 af3aec54a..c2b44d93d 100644 --- a/src/V3DupFinder.cpp +++ b/src/V3DupFinder.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 81e59ee43..e2924447f 100644 --- a/src/V3DupFinder.h +++ b/src/V3DupFinder.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2024 by Wilson Snyder. This program is free software; you +// Copyright 2005-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 98231dba4..1d344d9b5 100644 --- a/src/V3EmitC.h +++ b/src/V3EmitC.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 7f9d33cea..547a17884 100644 --- a/src/V3EmitCBase.cpp +++ b/src/V3EmitCBase.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,7 @@ void EmitCBaseVisitorConst::emitVarDecl(const AstVar* nodep, bool asRef) { if (nodep->attrScClocked() && nodep->isReadOnly()) { putns(nodep, "sc_core::sc_in_clk "); } else { - if (nodep->isInoutish()) { + if (nodep->isInout()) { putns(nodep, "sc_core::sc_inout<"); } else if (nodep->isWritable()) { putns(nodep, "sc_core::sc_out<"); @@ -213,7 +213,7 @@ void EmitCBaseVisitorConst::emitVarDecl(const AstVar* nodep, bool asRef) { emitDeclArrayBrackets(nodep); puts(";\n"); } else if (nodep->isIO() && basicp && !basicp->isOpaque()) { - if (nodep->isInoutish()) { + if (nodep->isInout()) { putns(nodep, "VL_INOUT"); } else if (nodep->isWritable()) { putns(nodep, "VL_OUT"); diff --git a/src/V3EmitCBase.h b/src/V3EmitCBase.h index 28bdf76a8..ff2305aaf 100644 --- a/src/V3EmitCBase.h +++ b/src/V3EmitCBase.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -146,8 +146,8 @@ public: void emitCFuncDecl(const AstCFunc* funcp, const AstNodeModule* modp, bool cLinkage = false); void emitVarDecl(const AstVar* nodep, bool asRef = false); void emitVarAccessors(const AstVar* nodep); - template - static void forModCUse(const AstNodeModule* modp, VUseType useType, F action) { + template + static void forModCUse(const AstNodeModule* modp, VUseType useType, T_Callable action) { for (AstNode* itemp = modp->stmtsp(); itemp; itemp = itemp->nextp()) { if (AstCUse* const usep = VN_CAST(itemp, CUse)) { if (usep->useType().containsAny(useType)) { diff --git a/src/V3EmitCConstInit.h b/src/V3EmitCConstInit.h index b91ab9718..7fb761828 100644 --- a/src/V3EmitCConstInit.h +++ b/src/V3EmitCConstInit.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,8 +50,8 @@ protected: m_inUnpacked = true; if (VN_IS(nodep->dtypep()->skipRefp(), AssocArrayDType)) { // Note the double {{ initializer. The first { starts the initializer of the - // VlUnpacked, and the second starts the initializer of m_storage within the - // VlUnpacked. + // VlAssocArray, and the second starts the initializer of m_storage within the + // VlAssocArray. puts("{"); ofp()->putsNoTracking("{"); puts("\n"); diff --git a/src/V3EmitCConstPool.cpp b/src/V3EmitCConstPool.cpp index c373e3160..b94dbc6aa 100644 --- a/src/V3EmitCConstPool.cpp +++ b/src/V3EmitCConstPool.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 c601179a9..d39c8c4b0 100644 --- a/src/V3EmitCFunc.cpp +++ b/src/V3EmitCFunc.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.h b/src/V3EmitCFunc.h index 389b5d012..40c7e5423 100644 --- a/src/V3EmitCFunc.h +++ b/src/V3EmitCFunc.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,7 +354,7 @@ public: * executing in the wrong path to make verilator-generated code * run faster. */ - puts("auto &vlSelfRef = std::ref(*vlSelf).get();\n"); + puts("auto& vlSelfRef = std::ref(*vlSelf).get();\n"); } if (nodep->initsp()) { diff --git a/src/V3EmitCHeaders.cpp b/src/V3EmitCHeaders.cpp index 839dc00ca..5abde202e 100644 --- a/src/V3EmitCHeaders.cpp +++ b/src/V3EmitCHeaders.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -223,7 +223,7 @@ class EmitCHeader final : public EmitCConstInit { std::set& emitted) { if (emitted.count(sdtypep) > 0) return; emitted.insert(sdtypep); - for (const AstMemberDType* itemp = sdtypep->membersp(); itemp; + for (AstMemberDType* itemp = sdtypep->membersp(); itemp; itemp = VN_AS(itemp->nextp(), MemberDType)) { AstNodeUOrStructDType* const subp = itemp->getChildStructp(); if (subp && (!subp->packed() || sdtypep->packed())) { diff --git a/src/V3EmitCImp.cpp b/src/V3EmitCImp.cpp index 5df77cf92..ef8ec9241 100644 --- a/src/V3EmitCImp.cpp +++ b/src/V3EmitCImp.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -733,7 +733,7 @@ class EmitCTrace final : EmitCFunc { puts("," + cvtToStr(enumNum)); // Direction - if (nodep->declDirection().isInoutish()) { + if (nodep->declDirection().isInout()) { puts(", VerilatedTraceSigDirection::INOUT"); } else if (nodep->declDirection().isWritable()) { puts(", VerilatedTraceSigDirection::OUTPUT"); diff --git a/src/V3EmitCInlines.cpp b/src/V3EmitCInlines.cpp index 30d9f4e49..73cfec669 100644 --- a/src/V3EmitCInlines.cpp +++ b/src/V3EmitCInlines.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 10bbd8769..50c59106c 100644 --- a/src/V3EmitCMain.cpp +++ b/src/V3EmitCMain.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 683df4573..a27d5c25c 100644 --- a/src/V3EmitCMain.h +++ b/src/V3EmitCMain.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 0bd768a94..6744098e8 100644 --- a/src/V3EmitCMake.cpp +++ b/src/V3EmitCMake.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2024 by Wilson Snyder. This program is free software; you +// Copyright 2004-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -36,8 +36,8 @@ class CMakeEmitter final { // STATIC FUNCTIONS // Concatenate all strings in 'strs' with ' ' between them. - template - static string cmake_list(const List& strs) { + template + static string cmake_list(const T_List& strs) { string s; for (auto it = strs.begin(); it != strs.end(); ++it) { s += '"'; diff --git a/src/V3EmitCMake.h b/src/V3EmitCMake.h index cc0605b83..d62b51143 100644 --- a/src/V3EmitCMake.h +++ b/src/V3EmitCMake.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 54f625d13..41c1574c7 100644 --- a/src/V3EmitCModel.cpp +++ b/src/V3EmitCModel.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -432,7 +432,8 @@ class EmitCModel final : public EmitCFunc { puts(topModNameProtected + "__" + protect("_eval_settle") + "(&(vlSymsp->TOP));\n"); puts("}\n"); - if (v3Global.opt.profExec()) puts("vlSymsp->__Vm_executionProfilerp->configure();\n"); + if (v3Global.opt.profExec() && !v3Global.opt.hierChild()) + puts("vlSymsp->__Vm_executionProfilerp->configure();\n"); puts("VL_DEBUG_IF(VL_DBG_MSGF(\"+ Eval\\n\"););\n"); puts(topModNameProtected + "__" + protect("_eval") + "(&(vlSymsp->TOP));\n"); @@ -473,8 +474,7 @@ class EmitCModel final : public EmitCFunc { } else { putns(modp, "bool " + topClassName() + "::eventsPending() { return false; }\n\n"); puts("uint64_t " + topClassName() + "::nextTimeSlot() {\n"); - puts("VL_FATAL_MT(__FILE__, __LINE__, \"\", \"%Error: No delays in the " - "design\");\n"); + puts("VL_FATAL_MT(__FILE__, __LINE__, \"\", \"No delays in the design\");\n"); puts("return 0;\n}\n"); } diff --git a/src/V3EmitCPch.cpp b/src/V3EmitCPch.cpp index b5c9ff4dc..ca56694de 100644 --- a/src/V3EmitCPch.cpp +++ b/src/V3EmitCPch.cpp @@ -2,7 +2,7 @@ //************************************************************************* // Code available from: https://verilator.org // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 14323fed6..926342257 100644 --- a/src/V3EmitCSyms.cpp +++ b/src/V3EmitCSyms.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -43,13 +43,15 @@ class EmitCSyms final : EmitCBaseVisitorConst { const AstNode* m_nodep; const string m_symName; const string m_prettyName; + const string m_defName; const int m_timeunit; string m_type; ScopeData(const AstNode* nodep, const string& symName, const string& prettyName, - int timeunit, const string& type) + const string& defName, int timeunit, const string& type) : m_nodep{nodep} , m_symName{symName} , m_prettyName{prettyName} + , m_defName{defName} , m_timeunit{timeunit} , m_type{type} {} }; @@ -156,7 +158,6 @@ class EmitCSyms final : EmitCBaseVisitorConst { } static string scopeDecodeIdentifier(const string& scpname) { - string out = scpname; string::size_type pos = string::npos; // Remove hierarchy @@ -172,17 +173,7 @@ class EmitCSyms final : EmitCBaseVisitorConst { } } - if (pos != std::string::npos) out.erase(0, pos + 1); - - // Decode all escaped characters - while ((pos = out.find("__0")) != string::npos) { - unsigned int x; - std::stringstream ss; - ss << std::hex << out.substr(pos + 3, 2); - ss >> x; - out.replace(pos, 5, 1, (char)x); - } - return out; + return pos != string::npos ? scpname.substr(pos + 1) : scpname; } /// (scp, m_vpiScopeCandidates, m_scopeNames) -> m_scopeNames @@ -253,8 +244,8 @@ class EmitCSyms final : EmitCBaseVisitorConst { if (v3Global.opt.vpi()) varHierarchyScopes(scpName); if (m_scopeNames.find(scpSym) == m_scopeNames.end()) { // cppcheck-suppress stlFindInsert - m_scopeNames.emplace(scpSym, - ScopeData{varp, scpSym, scpPretty, 0, "SCOPE_OTHER"}); + m_scopeNames.emplace(scpSym, ScopeData{varp, scpSym, scpPretty, "", + 0, "SCOPE_OTHER"}); } m_scopeVars.emplace(scpSym + " " + varp->name(), ScopeVarData{scpSym, varBasePretty, varp, modp, scopep}); @@ -311,10 +302,8 @@ class EmitCSyms final : EmitCBaseVisitorConst { void visit(AstNodeModule* nodep) override { nameCheck(nodep); VL_RESTORER(m_modp); - { - m_modp = nodep; - iterateChildrenConst(nodep); - } + m_modp = nodep; + iterateChildrenConst(nodep); } void visit(AstCellInlineScope* nodep) override { if (v3Global.opt.vpi()) { @@ -325,7 +314,9 @@ class EmitCSyms final : EmitCBaseVisitorConst { const int timeunit = m_modp->timeunit().powerOfTen(); m_vpiScopeCandidates.emplace( scopeSymString(name), - ScopeData{nodep, scopeSymString(name), name_pretty, timeunit, type}); + ScopeData{nodep, scopeSymString(name), name_pretty, + type == "SCOPE_MODULE" ? nodep->origModName() : "", timeunit, + type}); } } void visit(AstScope* nodep) override { @@ -338,9 +329,9 @@ class EmitCSyms final : EmitCBaseVisitorConst { const string type = VN_IS(nodep->modp(), Package) ? "SCOPE_PACKAGE" : "SCOPE_MODULE"; const string name_pretty = AstNode::vpiName(nodep->shortName()); const int timeunit = m_modp->timeunit().powerOfTen(); - m_vpiScopeCandidates.emplace( - scopeSymString(nodep->name()), - ScopeData{nodep, scopeSymString(nodep->name()), name_pretty, timeunit, type}); + m_vpiScopeCandidates.emplace(scopeSymString(nodep->name()), + ScopeData{nodep, scopeSymString(nodep->name()), + name_pretty, "", timeunit, type}); } iterateChildrenConst(nodep); } @@ -349,8 +340,8 @@ class EmitCSyms final : EmitCBaseVisitorConst { // UINFO(9, "scnameins sp " << nodep->name() << " sp " << nodep->scopePrettySymName() // << " ss" << name << endl); const int timeunit = m_modp ? m_modp->timeunit().powerOfTen() : 0; - m_scopeNames.emplace( - name, ScopeData{nodep, name, nodep->scopePrettySymName(), timeunit, "SCOPE_OTHER"}); + m_scopeNames.emplace(name, ScopeData{nodep, name, nodep->scopePrettySymName(), "", + timeunit, "SCOPE_OTHER"}); if (nodep->dpiExport()) { UASSERT_OBJ(m_cfuncp, nodep, "ScopeName not under DPI function"); m_scopeFuncs.emplace(name + " " + m_cfuncp->name(), @@ -358,9 +349,10 @@ class EmitCSyms final : EmitCBaseVisitorConst { } else { if (m_scopeNames.find(nodep->scopeDpiName()) == m_scopeNames.end()) { // cppcheck-suppress stlFindInsert - m_scopeNames.emplace(nodep->scopeDpiName(), ScopeData{nodep, nodep->scopeDpiName(), - nodep->scopePrettyDpiName(), - timeunit, "SCOPE_OTHER"}); + m_scopeNames.emplace(nodep->scopeDpiName(), + ScopeData{nodep, nodep->scopeDpiName(), + nodep->scopePrettyDpiName(), "", timeunit, + "SCOPE_OTHER"}); } } } @@ -383,10 +375,8 @@ class EmitCSyms final : EmitCBaseVisitorConst { nameCheck(nodep); if (nodep->dpiImportPrototype() || nodep->dpiExportDispatcher()) m_dpis.push_back(nodep); VL_RESTORER(m_cfuncp); - { - m_cfuncp = nodep; - iterateChildrenConst(nodep); - } + m_cfuncp = nodep; + iterateChildrenConst(nodep); } //--------------------------------------- @@ -900,6 +890,8 @@ void EmitCSyms::emitSymImp() { puts(", "); putsQuoted(protect(scopeDecodeIdentifier(it->second.m_prettyName))); puts(", "); + putsQuoted(it->second.m_defName); + puts(", "); puts(cvtToStr(it->second.m_timeunit)); puts(", VerilatedScope::" + it->second.m_type + ");\n"); ++m_numStmts; diff --git a/src/V3EmitMk.cpp b/src/V3EmitMk.cpp index 48c6ad247..f87463f34 100644 --- a/src/V3EmitMk.cpp +++ b/src/V3EmitMk.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2024 by Wilson Snyder. This program is free software; you +// Copyright 2004-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -346,12 +346,14 @@ private: } } - if (bucket.m_concatenatedFilenames.size() == 1) { + const bool lastBucketAndLeftovers + = (i + 1 == list.m_bucketsNum) && (fileIt != list.m_files.end()); + if (bucket.m_concatenatedFilenames.size() > 1 || lastBucketAndLeftovers) { + m_outputFiles.push_back(std::move(bucket)); + } else if (bucket.m_concatenatedFilenames.size() == 1) { // Unwrap the bucket if it contains only one file. m_outputFiles.push_back( {std::move(bucket.m_concatenatedFilenames.front()), {}}); - } else if (bucket.m_concatenatedFilenames.size() > 1) { - m_outputFiles.push_back(std::move(bucket)); } // Most likely no bucket will be empty in normal situations. If it happen the // bucket will just be dropped. @@ -359,6 +361,8 @@ private: for (; fileIt != list.m_files.end(); ++fileIt) { // The Work List is out of buckets, but some files were left. // Add them to the last bucket. + UASSERT(m_outputFiles.back().isConcatenatingFile(), + "Cannot add leftover files to a single file"); m_outputFiles.back().m_concatenatedFilenames.push_back(fileIt->m_filename); } } diff --git a/src/V3EmitMk.h b/src/V3EmitMk.h index a9b612a01..4270fad3e 100644 --- a/src/V3EmitMk.h +++ b/src/V3EmitMk.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 c3c9c7d8b..b5da1b091 100644 --- a/src/V3EmitV.cpp +++ b/src/V3EmitV.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2024 by Wilson Snyder. This program is free software; you +// Copyright 2004-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -393,13 +393,11 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public EmitCBaseVisitorConst { } void visit(AstTextBlock* nodep) override { visit(static_cast(nodep)); - { - VL_RESTORER(m_suppressSemi); - m_suppressVarSemi = nodep->commas(); - for (AstNode* childp = nodep->nodesp(); childp; childp = childp->nextp()) { - iterateConst(childp); - if (nodep->commas() && childp->nextp()) puts(", "); - } + VL_RESTORER(m_suppressSemi); + m_suppressVarSemi = nodep->commas(); + for (AstNode* childp = nodep->nodesp(); childp; childp = childp->nextp()) { + iterateConst(childp); + if (nodep->commas() && childp->nextp()) puts(", "); } } void visit(AstScopeName* nodep) override {} diff --git a/src/V3EmitV.h b/src/V3EmitV.h index 2d15c39d2..1da5bc2e8 100644 --- a/src/V3EmitV.h +++ b/src/V3EmitV.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 e0b2edc6f..52cf00368 100644 --- a/src/V3EmitXml.cpp +++ b/src/V3EmitXml.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2024 by Wilson Snyder. This program is free software; you +// Copyright 2004-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 04ae09ebc..1cf5e2138 100644 --- a/src/V3EmitXml.h +++ b/src/V3EmitXml.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 60164e66c..23c70a013 100644 --- a/src/V3Error.cpp +++ b/src/V3Error.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -117,6 +117,8 @@ void V3ErrorGuarded::suppressThisWarning() VL_REQUIRES(m_mutex) { // cppcheck-has-bug-suppress constParameter void V3ErrorGuarded::v3errorEnd(std::ostringstream& sstr, const string& extra) VL_REQUIRES(m_mutex) { + // 'extra' is appended to the message, and is is excluded in check for + // duplicate messages. Currently used for reporting instance name. #if defined(__COVERITY__) || defined(__cppcheck__) if (m_errorCode == V3ErrorCode::EC_FATAL) __coverity_panic__(x); #endif diff --git a/src/V3Error.h b/src/V3Error.h index e2b669be3..c381ddfe7 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -254,7 +254,7 @@ public: // Warnings that are style only bool styleError() const VL_MT_SAFE { return (m_e == ASSIGNDLY // More than style, but for backward compatibility - || m_e == BLKSEQ || m_e == DEFPARAM || m_e == DECLFILENAME || m_e == EOFNEWLINE + || m_e == BLKSEQ || m_e == DECLFILENAME || m_e == DEFPARAM || m_e == EOFNEWLINE || m_e == GENUNNAMED || m_e == IMPORTSTAR || m_e == INCABSPATH || m_e == PINCONNECTEMPTY || m_e == PINNOCONNECT || m_e == SYNCASYNCNET || m_e == UNDRIVEN || m_e == UNUSEDGENVAR || m_e == UNUSEDLOOP @@ -564,9 +564,9 @@ void v3errorEndFatal(std::ostringstream& sstr) #define v3info(msg) v3warnCode(V3ErrorCode::EC_INFO, msg) #define v3error(msg) v3warnCode(V3ErrorCode::EC_ERROR, msg) #define v3fatal(msg) v3warnCodeFatal(V3ErrorCode::EC_FATAL, msg) -// Use this instead of fatal() if message gets suppressed with --quiet-exit +// Fatal exit; used instead of fatal() if message gets suppressed with --quiet-exit #define v3fatalExit(msg) v3warnCodeFatal(V3ErrorCode::EC_FATALEXIT, msg) -// Use this instead of fatal() to mention the source code line. +// Fatal exit; used instead of fatal() to mention the source code line #define v3fatalSrc(msg) \ v3errorEndFatal(v3errorBuildMessage( \ V3Error::v3errorPrepFileLine(V3ErrorCode::EC_FATALSRC, __FILE__, __LINE__), msg)) @@ -574,6 +574,10 @@ void v3errorEndFatal(std::ostringstream& sstr) #define v3fatalStatic(msg) \ ::v3errorEndFatal(v3errorBuildMessage(V3Error::v3errorPrep(V3ErrorCode::EC_FATAL), msg)) +/// Print a message when debug() >= level. stmsg is stream; e.g. use as '"foo=" << foo' +// +// Requires debug() function to exist in current scope, to hack this in temporarily: +// auto debug = []() -> bool { return V3Error::debugDefault(); }; #define UINFO(level, stmsg) \ do { \ if (VL_UNCOVERABLE(debug() >= (level))) { \ @@ -585,6 +589,7 @@ void v3errorEndFatal(std::ostringstream& sstr) if (VL_UNCOVERABLE(debug() >= (level))) { std::cout << stmsg; } \ } while (false) +/// Compile statements only when debug build #ifdef VL_DEBUG #define UDEBUGONLY(stmts) \ do { stmts } while (false) @@ -595,12 +600,12 @@ void v3errorEndFatal(std::ostringstream& sstr) } while (false) #endif -// Assertion without object, generally UOBJASSERT preferred +/// Assert without error location, generally UASSERT_OBJ preferred #define UASSERT(condition, stmsg) \ do { \ if (VL_UNCOVERABLE(!(condition))) v3fatalSrc(stmsg); \ } while (false) -// Assertion with object +/// Assert with object to provide error location #define UASSERT_OBJ(condition, obj, stmsg) \ do { \ if (VL_UNCOVERABLE(!(condition))) (obj)->v3fatalSrc(stmsg); \ @@ -614,7 +619,7 @@ void v3errorEndFatal(std::ostringstream& sstr) V3Error::vlAbort(); \ } \ } while (false) -// Check self test values for expected value. Safe from side-effects. +/// Check self test values for expected value. Safe from side-effects. // Type argument can be removed when go to C++11 (use auto). #define UASSERT_SELFTEST(Type, got, exp) \ do { \ @@ -625,6 +630,7 @@ void v3errorEndFatal(std::ostringstream& sstr) << g << " expected=" << e); \ } while (false) +// Error that call not supported; only for some Ast functions #define V3ERROR_NA \ do { \ v3error("Internal: Unexpected Call"); \ diff --git a/src/V3ExecGraph.cpp b/src/V3ExecGraph.cpp index 63649f9c8..5ccc71da5 100644 --- a/src/V3ExecGraph.cpp +++ b/src/V3ExecGraph.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3ExecGraph.h b/src/V3ExecGraph.h index 9b672a780..fd4baa257 100644 --- a/src/V3ExecGraph.h +++ b/src/V3ExecGraph.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3Expand.cpp b/src/V3Expand.cpp index efe51bed3..89ad6a858 100644 --- a/src/V3Expand.cpp +++ b/src/V3Expand.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2024 by Wilson Snyder. This program is free software; you +// Copyright 2004-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3Expand.h b/src/V3Expand.h index c97a273f4..e4f59b880 100644 --- a/src/V3Expand.h +++ b/src/V3Expand.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 a597b704e..49a4e032b 100644 --- a/src/V3File.cpp +++ b/src/V3File.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 2106f908e..b76dad9b1 100644 --- a/src/V3File.h +++ b/src/V3File.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.cpp b/src/V3FileLine.cpp index 138707039..1ff188e88 100644 --- a/src/V3FileLine.cpp +++ b/src/V3FileLine.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,9 +92,13 @@ void FileLineSingleton::fileNameNumMapDumpJson(std::ostream& os) { std::string sep = "\n "; os << "\"files\": {"; for (const auto& itr : m_namemap) { - const std::string name - = itr.first == V3Options::getStdPackagePath() ? "" : itr.first; - os << sep << '"' << filenameLetters(itr.second) << '"' << ": {\"filename\":\"" << name + std::string filename = itr.first; + if (filename == V3Options::getStdPackagePath()) { + filename = ""; + } else if (filename == V3Options::getStdWaiverPath()) { + filename = ""; + } + os << sep << '"' << filenameLetters(itr.second) << '"' << ": {\"filename\":\"" << filename << '"' << ", \"realpath\":\"" << V3OutFormatter::quoteNameControls(V3Os::filenameRealPath(itr.first)) << '"' << ", \"language\":\"" << numberToLang(itr.second).ascii() << "\"}"; @@ -147,6 +151,7 @@ FileLineSingleton::msgEnSetIdx_t FileLineSingleton::msgEnAnd(msgEnSetIdx_t lhsId // VFileContents class functions void VFileContent::pushText(const string& text) { + // Similar code in WildcardContents::pushText() if (m_lines.size() == 0) { m_lines.emplace_back(""); // no such thing as line [0] m_lines.emplace_back(""); // start with no leftover @@ -413,24 +418,36 @@ bool FileLine::warnIsOff(V3ErrorCode code) const { // cppverilator-suppress constParameter void FileLine::v3errorEnd(std::ostringstream& sstr, const string& extra) VL_RELEASE(V3Error::s().m_mutex) { - std::ostringstream nsstr; + // 'extra' is appended to the message, and is is excluded in check for + // duplicate messages. Currently used for reporting instance name. + std::ostringstream nsstr; // sstr with fileline prefix and context + std::ostringstream wsstr; // sstr for waiver (no fileline) with context if (lastLineno()) nsstr << this; nsstr << sstr.str(); + wsstr << sstr.str(); nsstr << "\n"; - std::ostringstream lstr; + wsstr << "\n"; + std::ostringstream extrass; // extra spaced out for prefix if (!extra.empty()) { - lstr << std::setw(ascii().length()) << " " - << ": " << extra; + extrass << std::setw(ascii().length()) << " " + << ": " << extra; } - m_waive = V3Config::waive(this, V3Error::s().errorCode(), sstr.str()); - if (warnIsOff(V3Error::s().errorCode()) || m_waive) { + if (warnIsOff(V3Error::s().errorCode())) { V3Error::s().suppressThisWarning(); - } else if (!V3Error::s().errorContexted()) { - nsstr << warnContextPrimary(); + } else { + if (!V3Error::s().errorContexted()) { + const string add = warnContextPrimary(); + wsstr << add; + nsstr << add; + } + m_waive = V3Config::waive(this, V3Error::s().errorCode(), wsstr.str()); + if (m_waive) { + V3Error::s().suppressThisWarning(); + } else { + V3Waiver::addEntry(V3Error::s().errorCode(), filename(), wsstr.str()); + } } - if (!warnIsOff(V3Error::s().errorCode()) && !m_waive) - V3Waiver::addEntry(V3Error::s().errorCode(), filename(), sstr.str()); - V3Error::v3errorEnd(nsstr, lstr.str()); + V3Error::v3errorEnd(nsstr, extrass.str()); } string FileLine::warnMore() const VL_REQUIRES(V3Error::s().m_mutex) { diff --git a/src/V3FileLine.h b/src/V3FileLine.h index 41d4906f2..5b934416a 100644 --- a/src/V3FileLine.h +++ b/src/V3FileLine.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 fc76d44a4..ee6b4dbb9 100644 --- a/src/V3Force.cpp +++ b/src/V3Force.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 f1c8fe315..6cbcc2b2d 100644 --- a/src/V3Force.h +++ b/src/V3Force.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3Fork.cpp b/src/V3Fork.cpp index 4f0a6490c..848222334 100644 --- a/src/V3Fork.cpp +++ b/src/V3Fork.cpp @@ -7,7 +7,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -433,7 +433,7 @@ class DynScopeVisitor final : public VNVisitor { nodep->v3warn( E_UNSUPPORTED, "Unsupported: Writing to a captured " - << (nodep->varp()->isInoutish() ? "inout" : "output") << " variable in a " + << (nodep->varp()->isInout() ? "inout" : "output") << " variable in a " << (VN_IS(nodep->backp(), AssignDly) ? "non-blocking assignment" : "fork") << " after a timing control"); } @@ -603,9 +603,7 @@ class ForkVisitor final : public VNVisitor { m_modp->addStmtsp(taskp); UINFO(9, "new " << taskp << endl); - AstTaskRef* const taskrefp - = new AstTaskRef{nodep->fileline(), taskp->name(), m_capturedVarRefsp}; - taskrefp->taskp(taskp); + AstTaskRef* const taskrefp = new AstTaskRef{nodep->fileline(), taskp, m_capturedVarRefsp}; AstStmtExpr* const taskcallp = taskrefp->makeStmt(); // Replaced nodes will be revisited, so we don't need to "lift" the arguments // as captures in case of nested forks. @@ -644,8 +642,7 @@ class ForkVisitor final : public VNVisitor { if (m_forkDepth && !nodep->varp()->isFuncLocal() && nodep->varp()->isClassMember()) return; if (m_forkDepth && (m_forkLocalsp.count(nodep->varp()) == 0) - && nodep->varp()->varType() != VVarType::PORT // Basically static, so it's safe - && !nodep->varp()->lifetime().isStatic()) { + && !nodep->varp()->lifetime().isStatic()) { // Basically static, so it's safe if (nodep->access().isWriteOrRW() && (!nodep->isClassHandleValue() || nodep->user2())) { nodep->v3warn( diff --git a/src/V3Fork.h b/src/V3Fork.h index 4671d5901..3c3b2ac3b 100644 --- a/src/V3Fork.h +++ b/src/V3Fork.h @@ -7,7 +7,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3FuncOpt.cpp b/src/V3FuncOpt.cpp new file mode 100644 index 000000000..fd00bcf53 --- /dev/null +++ b/src/V3FuncOpt.cpp @@ -0,0 +1,337 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: Generic optimizations on a per function basis +// +// Code available from: https://verilator.org +// +//************************************************************************* +// +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you +// can redistribute it and/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 +// +//************************************************************************* +// +// - Split assignments to wide locations with Concat on the RHS +// at word boundaries: +// foo = {l, r}; +// becomes (recursively): +// foo[_:_] = r; +// foo[_:_] = l; +// +// - Balance concatenation trees, e.g.: +// {a, {b, {c, d}} +// becomes: +// {{a, b}, {c, d}} +// Reality is more complex here, see the code. +// +//************************************************************************* + +#include "V3PchAstMT.h" + +#include "V3FuncOpt.h" + +#include "V3Global.h" +#include "V3Stats.h" +#include "V3ThreadPool.h" + +VL_DEFINE_DEBUG_FUNCTIONS; + +class BalanceConcatTree final { + // STATELESS + + // We keep the expressions, together with their offsets within a concatenation tree + struct Term final { + AstNodeExpr* exprp = nullptr; + size_t offset = 0; + + Term() = default; + Term(AstNodeExpr* exprp, size_t offset) + : exprp{exprp} + , offset{offset} {} + }; + + // Recursive implementation of 'gatherTerms' below. + static void gatherTermsRecursive(AstNodeExpr* exprp, std::vector& terms) { + if (AstConcat* const catp = VN_CAST(exprp, Concat)) { + // Recursive case: gather sub terms, right to left + gatherTermsRecursive(catp->rhsp(), terms); + gatherTermsRecursive(catp->lhsp(), terms); + return; + } + + // Base case: different operation + terms.emplace_back(exprp); + } + + // Gather terms in the tree rooted at the given node. + // Results are right to left, that is, index 0 in the returned vector + // is the rightmost term, index size()-1 is the leftmost term. + static std::vector gatherTerms(AstConcat* rootp) { + std::vector terms; + gatherTermsRecursive(rootp->rhsp(), terms); + gatherTermsRecursive(rootp->lhsp(), terms); + return terms; + } + + // Construct a balanced concatenation from the given terms, + // between indices begin (inclusive), and end (exclusive). + // Note term[end].offset must be valid. term[end].vtxp is + // never referenced. + static AstNodeExpr* construct(const std::vector& terms, const size_t begin, + const size_t end) { + UASSERT(end < terms.size(), "Invalid end"); + UASSERT(begin < end, "Invalid range"); + // Base case: just return the term + if (end == begin + 1) return terms[begin].exprp; + + // Recursive case: + // Compute the mid-point, trying to create roughly equal width intermediates + const size_t width = terms[end].offset - terms[begin].offset; + const size_t midOffset = width / 2 + terms[begin].offset; + const auto beginIt = terms.begin() + begin; + const auto endIt = terms.begin() + end; + const auto midIt = std::lower_bound(beginIt + 1, endIt - 1, midOffset, // + [&](const Term& term, size_t value) { // + return term.offset < value; + }); + const size_t mid = begin + std::distance(beginIt, midIt); + UASSERT(begin < mid && mid < end, "Must make some progress"); + // Construct the subtrees + AstNodeExpr* const rhsp = construct(terms, begin, mid); + AstNodeExpr* const lhsp = construct(terms, mid, end); + // Construct new node + AstNodeExpr* newp = new AstConcat{lhsp->fileline(), lhsp, rhsp}; + newp->user1(true); // Must not attempt to balance again. + return newp; + } + + // Returns replacement node, or nullptr if no change + static AstConcat* balance(AstConcat* const rootp) { + UINFO(9, "balanceConcat " << rootp << "\n"); + // Gather all input vertices of the tree + const std::vector exprps = gatherTerms(rootp); + // Don't bother with trivial trees + if (exprps.size() <= 3) return nullptr; + // Don't do it if any of the terms are impure + for (AstNodeExpr* const exprp : exprps) { + if (!exprp->isPure()) return nullptr; + } + + // Construct the terms Vector that we are going to do processing on + std::vector terms(exprps.size() + 1); + // These are redundant (constructor does the same), but here they are for clarity + terms[0].offset = 0; + terms[exprps.size()].exprp = nullptr; + for (size_t i = 0; i < exprps.size(); ++i) { + terms[i].exprp = exprps[i]->unlinkFrBack(); + terms[i + 1].offset = terms[i].offset + exprps[i]->width(); + } + + // Round 1: try to create terms ending on VL_EDATASIZE boundaries. + // This ensures we pack bits within a VL_EDATASIZE first is possible, + // and then hopefully we can just assemble VL_EDATASIZE words afterward. + std::vector terms2; + { + terms2.reserve(terms.size()); + + size_t begin = 0; // Start of current range considered + size_t end = 0; // End of current range considered + size_t offset = 0; // Offset of current range considered + + // Create a term from the current range + const auto makeTerm = [&]() { + AstNodeExpr* const exprp = construct(terms, begin, end); + terms2.emplace_back(exprp, offset); + offset += exprp->width(); + begin = end; + }; + + // Create all terms ending on a boundary. + while (++end < terms.size() - 1) { + if (terms[end].offset % VL_EDATASIZE == 0) makeTerm(); + } + // Final term. Loop condition above ensures this always exists, + // and might or might not be on a boundary. + makeTerm(); + // Sentinel term + terms2.emplace_back(nullptr, offset); + // should have ended up with the same number of bits at least... + UASSERT(terms2.back().offset == terms.back().offset, "Inconsitent terms"); + } + + // Round 2: Combine the partial terms + return VN_AS(construct(terms2, 0, terms2.size() - 1), Concat); + } + +public: + static AstConcat* apply(AstConcat* rootp) { return balance(rootp); } +}; + +class FuncOptVisitor final : public VNVisitor { + // NODE STATE + // AstNodeAssign::user() -> bool. Already checked, safe to split. Omit expensive check. + // AstConcat::user() -> bool. Already balanced. + + // STATE - Statistic tracking + VDouble0 m_balancedConcats; // Number of concatenations balanced + VDouble0 m_concatSplits; // Number of splits in assignments with Concat on RHS + + // True for e.g.: foo = foo >> 1; or foo[foo[0]] = ...; + static bool readsLhs(AstNodeAssign* nodep) { + // It is expected that the number of vars written on the LHS is very small (should be 1). + std::unordered_set lhsWrVarps; + std::unordered_set lhsRdVarps; + nodep->lhsp()->foreach([&](const AstVarRef* refp) { + if (refp->access().isWriteOrRW()) lhsWrVarps.emplace(refp->varp()); + if (refp->access().isReadOrRW()) lhsRdVarps.emplace(refp->varp()); + }); + + // Common case of 1 variable on the LHS - special handling for speed + if (lhsWrVarps.size() == 1) { + const AstVar* const lhsWrVarp = *lhsWrVarps.begin(); + // Check Rhs doesn't read the written var + const bool rhsReadsWritten = nodep->rhsp()->exists([=](const AstVarRef* refp) { // + return refp->varp() == lhsWrVarp; + }); + if (rhsReadsWritten) return true; + // Check Lhs doesn't read the written var + return lhsRdVarps.count(lhsWrVarp); + } + + // Generic case of multiple vars written on LHS + // TODO: this might be impossible due to earlier transforms, not sure + // Check Rhs doesn't read the written vars + const bool rhsReadsWritten = nodep->rhsp()->exists([&](const AstVarRef* refp) { // + return lhsWrVarps.count(refp->varp()); + }); + if (rhsReadsWritten) return true; + // Check Lhs doesn't read the written vars + for (const AstVar* const lhsWrVarp : lhsWrVarps) { + if (lhsRdVarps.count(lhsWrVarp)) return true; + } + return false; + } + + // METHODS + // Split wide assignments with a wide concatenation on the RHS. + // Returns true if 'nodep' was deleted + bool splitConcat(AstNodeAssign* nodep) { + UINFO(9, "splitConcat " << nodep << "\n"); + // Only care about concatenations on the right + AstConcat* const rhsp = VN_CAST(nodep->rhsp(), Concat); + if (!rhsp) return false; + // Will need the LHS + AstNodeExpr* lhsp = nodep->lhsp(); + UASSERT_OBJ(lhsp->width() == rhsp->width(), nodep, "Inconsistent assignment"); + // Only consider pure assignments. Nodes inserted below are safe. + if (!nodep->user1() && (!lhsp->isPure() || !rhsp->isPure())) return false; + // Check for a Sel on the LHS if present, and skip over it + uint32_t lsb = 0; + if (AstSel* const selp = VN_CAST(lhsp, Sel)) { + if (AstConst* const lsbp = VN_CAST(selp->lsbp(), Const)) { + lhsp = selp->fromp(); + lsb = lsbp->toUInt(); + } else { + // Don't optimize if it's a variable select + return false; + } + } + // No need to split assignments targeting storage smaller than a machine register + if (lhsp->width() <= VL_QUADSIZE) return false; + + // If it's a concat straddling a word boundary, try to split it. + // The next visit on the new nodes will split it recursively. + // Otherwise, keep the original assignment. + const int lsbWord = lsb / VL_EDATASIZE; + const int msbWord = (lsb + rhsp->width() - 1) / VL_EDATASIZE; + if (lsbWord == msbWord) return false; + + // If the RHS reads the LHS, we can't actually do this. Nodes inserted below are safe. + if (!nodep->user1() && readsLhs(nodep)) return false; + + // Ok, actually split it now + UINFO(5, "splitConcat optimizing " << nodep << "\n"); + ++m_concatSplits; + // The 2 parts and their offsets + AstNodeExpr* const rrp = rhsp->rhsp()->unlinkFrBack(); + AstNodeExpr* const rlp = rhsp->lhsp()->unlinkFrBack(); + const int rLsb = lsb; + const int lLsb = lsb + rrp->width(); + // Insert the 2 assignment right after the original. They will be visited next. + AstAssign* const arp = new AstAssign{ + nodep->fileline(), + new AstSel{lhsp->fileline(), lhsp->cloneTreePure(false), rLsb, rrp->width()}, rrp}; + AstAssign* const alp = new AstAssign{ + nodep->fileline(), + new AstSel{lhsp->fileline(), lhsp->unlinkFrBack(), lLsb, rlp->width()}, rlp}; + nodep->addNextHere(arp); + arp->addNextHere(alp); + // Safe to split these. + arp->user1(true); + alp->user1(true); + // Nuke what is left + VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); + return true; + } + + // VISIT + void visit(AstNodeAssign* nodep) override { + // TODO: Only thing remaining inside functions should be AstAssign (that is, an actual + // assignment statemant), but we stil use AstAssignW, AstAssignDly, and all, fix. + iterateChildren(nodep); + + if (v3Global.opt.fFuncSplitCat()) { + if (splitConcat(nodep)) return; // Must return here, in case more code is added below + } + } + + void visit(AstConcat* nodep) override { + if (v3Global.opt.fFuncBalanceCat() && !nodep->user1() && !VN_IS(nodep->backp(), Concat)) { + if (AstConcat* const newp = BalanceConcatTree::apply(nodep)) { + UINFO(5, "balanceConcat optimizing " << nodep << "\n"); + ++m_balancedConcats; + nodep->replaceWith(newp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + newp->user1(true); // Must not attempt again. + // Return here. The new node will be iterated next. + return; + } + } + iterateChildren(nodep); + } + + void visit(AstNode* nodep) override { iterateChildren(nodep); } + + // CONSTRUCTORS + explicit FuncOptVisitor(AstCFunc* funcp) { iterateChildren(funcp); } + ~FuncOptVisitor() override { + V3Stats::addStatSum("Optimizations, FuncOpt concat trees balanced", m_balancedConcats); + V3Stats::addStatSum("Optimizations, FuncOpt concat splits", m_concatSplits); + } + +public: + static void apply(AstCFunc* funcp) { FuncOptVisitor{funcp}; } +}; + +//###################################################################### + +void V3FuncOpt::funcOptAll(AstNetlist* nodep) { + UINFO(2, __FUNCTION__ << ": " << endl); + { + const VNUser1InUse user1InUse; + V3ThreadScope threadScope; + for (AstNodeModule *modp = nodep->modulesp(), *nextModp; modp; modp = nextModp) { + nextModp = VN_AS(modp->nextp(), NodeModule); + for (AstNode *nodep = modp->stmtsp(), *nextNodep; nodep; nodep = nextNodep) { + nextNodep = nodep->nextp(); + if (AstCFunc* const cfuncp = VN_CAST(nodep, CFunc)) { + threadScope.enqueue([cfuncp]() { FuncOptVisitor::apply(cfuncp); }); + } + } + } + } + V3Global::dumpCheckGlobalTree("funcopt", 0, dumpTreeEitherLevel() >= 3); +} diff --git a/src/V3FuncOpt.h b/src/V3FuncOpt.h new file mode 100644 index 000000000..75a6885f5 --- /dev/null +++ b/src/V3FuncOpt.h @@ -0,0 +1,32 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: Generic optimizations on a per function basis +// +// Code available from: https://verilator.org +// +//************************************************************************* +// +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you +// can redistribute it and/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 VERILATOR_V3FUNCOPT_H_ +#define VERILATOR_V3FUNCOPT_H_ + +#include "config_build.h" +#include "verilatedos.h" + +class AstNetlist; + +//============================================================================ + +class V3FuncOpt final { +public: + static void funcOptAll(AstNetlist* nodep); +}; + +#endif // Guard diff --git a/src/V3FunctionTraits.h b/src/V3FunctionTraits.h index 9287048b8..4890210d4 100644 --- a/src/V3FunctionTraits.h +++ b/src/V3FunctionTraits.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -32,25 +32,25 @@ struct FunctionTraits final : public FunctionTraits::type::operator())> {}; // Specialization for pointers to member function -template -struct FunctionTraits VL_NOT_FINAL { +template +struct FunctionTraits VL_NOT_FINAL { // Number of arguments static constexpr size_t arity = sizeof...(Args); // Type of result - using result_type = ReturnType; + using result_type = T_ReturnType; // Type of arguments - template + template struct arg final { - using type = typename std::tuple_element>::type; + using type = typename std::tuple_element>::type; }; }; -template +template struct FunctionArgNoPointerNoCV final { using Traits = FunctionTraits; - using T_Arg = typename Traits::template arg::type; + using T_Arg = typename Traits::template arg::type; using T_ArgNoPtr = typename std::remove_pointer::type; using type = typename std::remove_cv::type; }; diff --git a/src/V3Gate.cpp b/src/V3Gate.cpp index 371997963..abb8fff7d 100644 --- a/src/V3Gate.cpp +++ b/src/V3Gate.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -681,8 +681,44 @@ class GateInline final { std::unordered_map m_hasPending; size_t m_statInlined = 0; // Statistic tracking - signals inlined size_t m_statRefs = 0; // Statistic tracking + size_t m_statExcluded = 0; // Statistic tracking // METHODS + static bool isCheapWide(const AstNodeExpr* exprp) { + if (const AstSel* const selp = VN_CAST(exprp, Sel)) { + if (selp->lsbConst() % VL_EDATASIZE != 0) return false; + exprp = selp->fromp(); + } + if (const AstArraySel* const aselp = VN_CAST(exprp, ArraySel)) exprp = aselp->fromp(); + return VN_IS(exprp, Const) || VN_IS(exprp, NodeVarRef); + } + static bool excludedWide(GateVarVertex* const vVtxp, const AstNodeExpr* const rhsp) { + // Handle wides with logic drivers that are too wide for V3Expand. + if (!vVtxp->varScp()->isWide() // + || vVtxp->varScp()->widthWords() <= v3Global.opt.expandLimit() // + || vVtxp->inEmpty() // + || isCheapWide(rhsp)) + return false; + + const GateLogicVertex* const lVtxp + = vVtxp->inEdges().frontp()->fromp()->as(); + + // Exclude from inlining variables READ multiple times. + // To decouple actives thus simplifying scheduling, exclude only those + // VarRefs that are referenced under the same active as they were assigned. + if (const AstActive* const primaryActivep = lVtxp->activep()) { + size_t reads = 0; + for (const V3GraphEdge& edge : vVtxp->outEdges()) { + const GateLogicVertex* const lvp = edge.top()->as(); + if (lvp->activep() != primaryActivep) continue; + + reads += edge.weight(); + if (reads > 1) return true; + } + } + return false; + } + void recordSubstitution(AstVarScope* vscp, AstNodeExpr* substp, AstNode* logicp) { m_hasPending.emplace(logicp, ++m_ord); // It's OK if already present const auto pair = m_substitutions(logicp).emplace(vscp, nullptr); @@ -777,6 +813,12 @@ class GateInline final { if (!okVisitor.isSimple()) continue; // If the varScope is already removed from logicp, no need to try substitution. if (!okVisitor.varAssigned(vVtxp->varScp())) continue; + if (excludedWide(vVtxp, okVisitor.substitutionp())) { + ++m_statExcluded; + UINFO(9, "Gate inline exclude '" << vVtxp->name() << "'" << endl); + vVtxp->clearReducible("Excluded wide"); // Check once. + continue; + } // Does it read multiple source variables? if (okVisitor.readVscps().size() > 1) { @@ -876,6 +918,7 @@ class GateInline final { ~GateInline() { V3Stats::addStat("Optimizations, Gate sigs deleted", m_statInlined); V3Stats::addStat("Optimizations, Gate inputs replaced", m_statRefs); + V3Stats::addStat("Optimizations, Gate excluded wide expressions", m_statExcluded); } public: @@ -1190,7 +1233,7 @@ class GateMergeAssignments final { AstSel* merge(AstSel* prevSelp, AstSel* currSelp) { const AstVarRef* const pRefp = VN_CAST(prevSelp->fromp(), VarRef); AstVarRef* const cRefp = VN_CAST(currSelp->fromp(), VarRef); - if (!pRefp || !cRefp || !cRefp->same(pRefp)) return nullptr; // not the same var + if (!pRefp || !cRefp || !cRefp->sameNode(pRefp)) return nullptr; // not the same var const AstConst* const pstart = VN_CAST(prevSelp->lsbp(), Const); const AstConst* const pwidth = VN_CAST(prevSelp->widthp(), Const); diff --git a/src/V3Gate.h b/src/V3Gate.h index b6d3c66fe..b6e86e668 100644 --- a/src/V3Gate.h +++ b/src/V3Gate.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 bb4170898..08bab7a2d 100644 --- a/src/V3Global.cpp +++ b/src/V3Global.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2024 by Wilson Snyder. This program is free software; you +// Copyright 2004-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,12 @@ void V3Global::readFiles() { V3Parse parser{v3Global.rootp(), &filter, &parseSyms}; + // Parse the std waivers + if (v3Global.opt.stdWaiver()) { + parser.parseFile( + new FileLine{V3Options::getStdWaiverPath()}, V3Options::getStdWaiverPath(), false, + "Cannot find verilated_std_waiver.vlt containing built-in lint waivers: "); + } // Read .vlt files const V3StringSet& vltFiles = v3Global.opt.vltFiles(); for (const string& filename : vltFiles) { @@ -66,7 +72,7 @@ void V3Global::readFiles() { } // Parse the std package - if (v3Global.opt.std()) { + if (v3Global.opt.stdPackage()) { parser.parseFile(new FileLine{V3Options::getStdPackagePath()}, V3Options::getStdPackagePath(), false, "Cannot find verilated_std.sv containing built-in std:: definitions: "); @@ -102,6 +108,8 @@ void V3Global::readFiles() { // Resolve all modules cells refer to V3LinkCells::link(v3Global.rootp(), &filter, &parseSyms); } + + V3Global::dumpCheckGlobalTree("cells", false, dumpTreeEitherLevel() >= 9); } void V3Global::removeStd() { diff --git a/src/V3Global.h b/src/V3Global.h index 0b3f755b3..dcbe078ab 100644 --- a/src/V3Global.h +++ b/src/V3Global.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.cpp b/src/V3Graph.cpp index 968e4c261..c5f57f78d 100644 --- a/src/V3Graph.cpp +++ b/src/V3Graph.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,12 +79,12 @@ void V3GraphVertex::rerouteEdges(V3Graph* graphp) { unlinkEdges(graphp); } -template +template V3GraphEdge* V3GraphVertex::findConnectingEdgep(V3GraphVertex* waywardp) { // O(edges) linear search. Searches search both nodes' edge lists in // parallel. The lists probably aren't _both_ huge, so this is // unlikely to blow up even on fairly nasty graphs. - constexpr GraphWay way{T_Way}; + constexpr GraphWay way{N_Way}; constexpr GraphWay inv = way.invert(); auto& aEdges = this->edges(); auto aIt = aEdges.begin(); diff --git a/src/V3Graph.h b/src/V3Graph.h index 911c909b3..9b357ceff 100644 --- a/src/V3Graph.h +++ b/src/V3Graph.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,9 +187,9 @@ public: uint64_t user() const { return m_user; } V3GraphVertex* fromp() const { return m_fromp; } V3GraphVertex* top() const { return m_top; } - template + template V3GraphVertex* furtherp() const { - return T_Way == GraphWay::FORWARD ? top() : fromp(); + return N_Way == GraphWay::FORWARD ? top() : fromp(); } // STATIC ACCESSORS static bool followNotCutable(const V3GraphEdge* edgep) { return !edgep->m_cutable; } @@ -301,9 +301,9 @@ public: void* userp() const VL_MT_STABLE { return m_userp; } V3GraphEdge::IList& inEdges() { return m_ins; } const V3GraphEdge::IList& inEdges() const { return m_ins; } - template + template inline auto& edges(); - template + template inline const auto& edges() const; bool inEmpty() const { return m_ins.empty(); } bool inSize1() const { return m_ins.hasSingleElement(); } @@ -320,7 +320,7 @@ public: void rerouteEdges(V3Graph* graphp) VL_MT_DISABLED; // Find the edge connecting this vertex to the given vertex. // If edge is not found returns nullptr. O(edges) performance. - template + template V3GraphEdge* findConnectingEdgep(V3GraphVertex* otherp) VL_MT_DISABLED; }; diff --git a/src/V3GraphAcyc.cpp b/src/V3GraphAcyc.cpp index 7397f1d3b..cf3ab8b9c 100644 --- a/src/V3GraphAcyc.cpp +++ b/src/V3GraphAcyc.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 7eec461e1..bc0eff17f 100644 --- a/src/V3GraphAlg.cpp +++ b/src/V3GraphAlg.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 63fec5691..c879cc34f 100644 --- a/src/V3GraphAlg.h +++ b/src/V3GraphAlg.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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 @@ // Algorithms - common class // For internal use, most graph algorithms use this as a base class -template // Or sometimes const V3Graph +template // Or sometimes const V3Graph class GraphAlg VL_NOT_FINAL { protected: T_Graph* const m_graphp; // Graph we're operating upon diff --git a/src/V3GraphPathChecker.cpp b/src/V3GraphPathChecker.cpp index f7f72cdfb..f59d76cb4 100644 --- a/src/V3GraphPathChecker.cpp +++ b/src/V3GraphPathChecker.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,9 +53,9 @@ struct GraphPCNode final { //###################################################################### // GraphPathChecker implementation -template +template void GraphPathChecker::initHalfCriticalPaths(bool checkOnly) { - constexpr GraphWay way{T_Way}; + constexpr GraphWay way{N_Way}; constexpr GraphWay rev = way.invert(); GraphStreamUnordered order(m_graphp, way); while (const V3GraphVertex* const vertexp = order.nextp()) { diff --git a/src/V3GraphPathChecker.h b/src/V3GraphPathChecker.h index 495d8cca8..bd4765411 100644 --- a/src/V3GraphPathChecker.h +++ b/src/V3GraphPathChecker.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,7 @@ public: private: bool pathExistsInternal(const V3GraphVertex* ap, const V3GraphVertex* bp, unsigned* costp = nullptr) VL_MT_DISABLED; - template + template void initHalfCriticalPaths(bool checkOnly) VL_MT_DISABLED; void incGeneration() { ++m_generation; } diff --git a/src/V3GraphStream.h b/src/V3GraphStream.h index 7741938b0..835abd261 100644 --- a/src/V3GraphStream.h +++ b/src/V3GraphStream.h @@ -7,7 +7,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,7 @@ // not generally safe. If you want a raw pointer compare, see // GraphStreamUnordered below. -template +template class GraphStream final { // TYPES class VxHolder final { @@ -264,9 +264,9 @@ public: } private: - template // + template // VL_ATTR_NOINLINE void init(V3Graph* graphp) { - constexpr GraphWay way{T_Way}; + constexpr GraphWay way{N_Way}; // Assign every vertex without an incoming edge to ready, others to waiting for (V3GraphVertex& vertex : graphp->vertices()) { const uint32_t nDeps = vertex.edges().size(); @@ -275,9 +275,9 @@ private: } } - template // + template // VL_ATTR_NOINLINE const V3GraphVertex* unblock(const V3GraphVertex* resultp) { - constexpr GraphWay way{T_Way}; + constexpr GraphWay way{N_Way}; for (const V3GraphEdge& edge : resultp->edges()) { V3GraphVertex* const vertexp = edge.furtherp(); #if VL_DEBUG diff --git a/src/V3GraphTest.cpp b/src/V3GraphTest.cpp index 75760d694..4bc98f035 100644 --- a/src/V3GraphTest.cpp +++ b/src/V3GraphTest.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 cb3d5468f..26b2052d6 100644 --- a/src/V3Hash.cpp +++ b/src/V3Hash.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 1aa39b292..d73fbae6f 100644 --- a/src/V3Hash.h +++ b/src/V3Hash.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -57,13 +57,13 @@ public: bool operator<(const V3Hash& rh) const { return m_value < rh.m_value; } // '+' combines hashes - template + template V3Hash operator+(T that) const { return V3Hash{combine(m_value, V3Hash{that}.m_value)}; } // '+=' combines in place - template + template V3Hash& operator+=(T that) { return *this = *this + that; } diff --git a/src/V3Hasher.cpp b/src/V3Hasher.cpp index 9b8be0dc3..d1fde1ff2 100644 --- a/src/V3Hasher.cpp +++ b/src/V3Hasher.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,6 +138,11 @@ class HasherVisitor final : public VNVisitorConst { iterateConstNull(nodep->virtRefDType2p()); }); } + void visit(AstBracketArrayDType* nodep) override { + m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { + iterateConstNull(nodep->virtRefDTypep()); + }); + } void visit(AstDynArrayDType* nodep) override { m_hash += hashNodeAndIterate(nodep, false, HASH_CHILDREN, [this, nodep]() { // iterateConstNull(nodep->virtRefDTypep()); diff --git a/src/V3Hasher.h b/src/V3Hasher.h index 221740b04..f862e9978 100644 --- a/src/V3Hasher.h +++ b/src/V3Hasher.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2024 by Wilson Snyder. This program is free software; you +// Copyright 2005-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 fb79927fe..bc6c0f6fc 100644 --- a/src/V3HierBlock.cpp +++ b/src/V3HierBlock.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -115,6 +115,8 @@ static void V3HierWriteCommonInputs(const V3HierBlock* hblockp, std::ostream* of if (hblockp) topModuleFile = hblockp->vFileIfNecessary(); if (!forCMake) { if (!topModuleFile.empty()) *of << topModuleFile << "\n"; + const V3StringList& vFiles = v3Global.opt.vFiles(); + for (const string& i : vFiles) *of << i << "\n"; } const V3StringSet& libraryFiles = v3Global.opt.libraryFiles(); for (const string& i : libraryFiles) { @@ -253,7 +255,7 @@ void V3HierBlock::writeCommandArgsFile(bool forCMake) const { for (const string& opt : commandOpts) *of << opt << "\n"; *of << hierBlockArgs().front() << "\n"; for (const auto& hierblockp : m_children) *of << hierblockp->hierBlockArgs().front() << "\n"; - *of << v3Global.opt.allArgsStringForHierBlock(false, forCMake) << "\n"; + *of << v3Global.opt.allArgsStringForHierBlock(false) << "\n"; } string V3HierBlock::commandArgsFilename(bool forCMake) const { @@ -271,7 +273,7 @@ void V3HierBlock::writeParametersFile() const { const string moduleName = "Vhsh" + hash.digestSymbol(); const std::unique_ptr of{V3File::new_ofstream(typeParametersFilename())}; *of << "module " << moduleName << ";\n"; - for (const AstParamTypeDType* const gparam : m_params.gTypeParams()) { + for (AstParamTypeDType* const gparam : m_params.gTypeParams()) { AstTypedef* tdefp = new AstTypedef(new FileLine{FileLine::builtInFilename()}, gparam->name(), nullptr, VFlagChildDType{}, gparam->skipRefp()->cloneTreePure(true)); @@ -477,7 +479,7 @@ void V3HierBlockPlan::writeCommandArgsFiles(bool forCMake) const { } *of << "--threads " << cvtToStr(v3Global.opt.threads()) << "\n"; *of << (v3Global.opt.systemC() ? "--sc" : "--cc") << "\n"; - *of << v3Global.opt.allArgsStringForHierBlock(true, forCMake) << "\n"; + *of << v3Global.opt.allArgsStringForHierBlock(true) << "\n"; } string V3HierBlockPlan::topCommandArgsFilename(bool forCMake) { diff --git a/src/V3HierBlock.h b/src/V3HierBlock.h index d3ac4906c..ff6e52fe3 100644 --- a/src/V3HierBlock.h +++ b/src/V3HierBlock.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.cpp b/src/V3Inline.cpp index b577e2bc6..d4a267418 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 f1d0faad3..3d1adbc0c 100644 --- a/src/V3Inline.h +++ b/src/V3Inline.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 d8c810180..5555defd8 100644 --- a/src/V3Inst.cpp +++ b/src/V3Inst.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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 @@ class InstVisitor final : public VNVisitor { AstNodeExpr* const exprp = VN_AS(nodep->exprp(), NodeExpr)->cloneTree(false); UASSERT_OBJ(exprp->width() == nodep->modVarp()->width(), nodep, "Width mismatch, should have been handled in pinReconnectSimple"); - if (nodep->modVarp()->isInoutish()) { + if (nodep->modVarp()->isInout()) { nodep->v3fatalSrc("Unsupported: Verilator is a 2-state simulator"); } else if (nodep->modVarp()->isWritable()) { AstNodeExpr* const rhsp = new AstVarXRef{exprp->fileline(), nodep->modVarp(), @@ -558,7 +558,7 @@ public: // Important to add statement next to cell, in case there is a // generate with same named cell cellp->addNextHere(newvarp); - if (pinVarp->isInoutish()) { + if (pinVarp->isInout()) { pinVarp->v3fatalSrc("Unsupported: Inout connections to pins must be" " direct one-to-one connection (without any expression)"); } else if (pinVarp->isWritable()) { diff --git a/src/V3Inst.h b/src/V3Inst.h index fe23c469f..98a82d78d 100644 --- a/src/V3Inst.h +++ b/src/V3Inst.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 71a05e976..365a67e41 100644 --- a/src/V3InstrCount.cpp +++ b/src/V3InstrCount.cpp @@ -7,7 +7,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 143721f49..be25b331b 100644 --- a/src/V3InstrCount.h +++ b/src/V3InstrCount.h @@ -7,7 +7,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3Interface.cpp b/src/V3Interface.cpp index 146739525..6364ef847 100644 --- a/src/V3Interface.cpp +++ b/src/V3Interface.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3Interface.h b/src/V3Interface.h index 2ff3c71a9..ad649a099 100644 --- a/src/V3Interface.h +++ b/src/V3Interface.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 0de1b5678..c2e1ae390 100644 --- a/src/V3LangCode.h +++ b/src/V3LangCode.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 31a33eae3..ba0f302de 100644 --- a/src/V3LanguageWords.h +++ b/src/V3LanguageWords.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2024 by Wilson Snyder. This program is free software; you +// Copyright 2005-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 6f0dbb755..47a7468b8 100644 --- a/src/V3Life.cpp +++ b/src/V3Life.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 36c6970ac..2eb6b3473 100644 --- a/src/V3Life.h +++ b/src/V3Life.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 44a63688d..e2f96eb01 100644 --- a/src/V3LifePost.cpp +++ b/src/V3LifePost.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 8a4552b00..161f54dae 100644 --- a/src/V3LifePost.h +++ b/src/V3LifePost.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 c240cf76a..6e3d13fe3 100644 --- a/src/V3LinkCells.cpp +++ b/src/V3LinkCells.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -56,7 +56,7 @@ public: , m_modp{modp} {} ~LinkCellsVertex() override = default; AstNodeModule* modp() const VL_MT_STABLE { return m_modp; } - string name() const override VL_MT_STABLE { return modp()->name(); } + string name() const override VL_MT_STABLE { return cvtToHex(modp()) + ' ' + modp()->name(); } FileLine* fileline() const override { return modp()->fileline(); } // Recursive modules get space for maximum recursion uint32_t rankAdder() const override { @@ -109,6 +109,7 @@ class LinkCellsVisitor final : public VNVisitor { // Below state needs to be preserved between each module call. AstNodeModule* m_modp = nullptr; // Current module + AstVar* m_varp = nullptr; // Current variable VSymGraph m_mods; // Symbol table of all module names LinkCellsGraph m_graph; // Linked graph of all cell interconnects LibraryVertex* m_libVertexp = nullptr; // Vertex at root of all libraries @@ -123,6 +124,10 @@ class LinkCellsVisitor final : public VNVisitor { if (!nodep->user1p()) nodep->user1p(new LinkCellsVertex{&m_graph, nodep}); return nodep->user1u().toGraphVertex(); } + void newEdge(V3GraphVertex* fromp, V3GraphVertex* top, int weight, bool cuttable) { + UINFO(9, "newEdge " << fromp->name() << " -> " << top->name() << endl); + new V3GraphEdge{&m_graph, fromp, top, weight, cuttable}; + } AstNodeModule* findModuleSym(const string& modName) { const VSymEnt* const foundp = m_mods.rootp()->findIdFallback(modName); @@ -183,7 +188,7 @@ class LinkCellsVisitor final : public VNVisitor { VL_RESTORER(m_modp); { // For nested modules/classes, child below parent - if (m_modp) new V3GraphEdge{&m_graph, vertex(m_modp), vertex(nodep), 1}; + if (m_modp) newEdge(vertex(m_modp), vertex(nodep), 1, false); // m_modp = nodep; UINFO(4, "Link Module: " << nodep << endl); @@ -215,7 +220,7 @@ class LinkCellsVisitor final : public VNVisitor { // Put under a fake vertex so that the graph ranking won't indicate // this is a top level module if (!m_libVertexp) m_libVertexp = new LibraryVertex{&m_graph}; - new V3GraphEdge{&m_graph, m_libVertexp, vertex(nodep), 1, false}; + newEdge(m_libVertexp, vertex(nodep), 1, false); } // Note AstBind also has iteration on cells iterateChildren(nodep); @@ -232,11 +237,15 @@ class LinkCellsVisitor final : public VNVisitor { if (modp) { if (VN_IS(modp, Iface)) { // Track module depths, so can sort list from parent down to children - new V3GraphEdge{&m_graph, vertex(m_modp), vertex(modp), 1, false}; + newEdge(vertex(m_modp), vertex(modp), 1, false); if (!nodep->cellp()) nodep->ifacep(VN_AS(modp, Iface)); } else if (VN_IS(modp, NotFoundModule)) { // Will error out later } else { - nodep->v3error("Non-interface used as an interface: " << nodep->prettyNameQ()); + nodep->v3error("Non-interface used as an interface: " + << nodep->ifaceNameQ() << "\n" + << nodep->warnMore() + + "... Perhaps intended an instantiation but " + "are missing parenthesis (IEEE 1800-2023 23.3.2)?"); } } iterateChildren(nodep); @@ -244,7 +253,11 @@ class LinkCellsVisitor final : public VNVisitor { pinp->param(true); if (pinp->name() == "") pinp->name("__paramNumber" + cvtToStr(pinp->pinNum())); } + // Parser didn't know what was interface, resolve now + // For historical reasons virtual interface reference variables remain VARs + if (m_varp && !nodep->isVirtual()) m_varp->setIfaceRef(); // Note cannot do modport resolution here; modports are allowed underneath generates + UINFO(4, "Link IfaceRef done: " << nodep << endl); } void visit(AstPackageExport* nodep) override { @@ -271,7 +284,7 @@ class LinkCellsVisitor final : public VNVisitor { return; } } - new V3GraphEdge{&m_graph, vertex(m_modp), vertex(nodep->packagep()), 1, false}; + newEdge(vertex(m_modp), vertex(nodep->packagep()), 1, false); } void visit(AstBind* nodep) override { @@ -286,12 +299,10 @@ class LinkCellsVisitor final : public VNVisitor { AstNode* const cellsp = nodep->cellsp()->unlinkFrBackWithNext(); // Module may have already linked, so need to pick up these new cells VL_RESTORER(m_modp); - { - m_modp = modp; - // Important that this adds to end, as next iterate assumes does all cells - modp->addStmtsp(cellsp); - iterateAndNextNull(cellsp); - } + m_modp = modp; + // Important that this adds to end, as next iterate assumes does all cells + modp->addStmtsp(cellsp); + iterateAndNextNull(cellsp); } VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep); } @@ -343,8 +354,7 @@ class LinkCellsVisitor final : public VNVisitor { // user1 etc will retain its pre-clone value cellmodp->user2p(otherModp); v3Global.rootp()->addModulesp(otherModp); - new V3GraphEdge{&m_graph, vertex(cellmodp), vertex(otherModp), 1, - false}; + newEdge(vertex(cellmodp), vertex(otherModp), 1, false); } cellmodp = otherModp; nodep->modp(cellmodp); @@ -357,7 +367,7 @@ class LinkCellsVisitor final : public VNVisitor { } else { // Non-recursive // Track module depths, so can sort list from parent down to children nodep->modp(cellmodp); - new V3GraphEdge{&m_graph, vertex(m_modp), vertex(cellmodp), 1, false}; + newEdge(vertex(m_modp), vertex(cellmodp), 1, false); } } } @@ -493,10 +503,10 @@ class LinkCellsVisitor final : public VNVisitor { AstIfaceRefDType* const idtypep = new AstIfaceRefDType{ nodep->fileline(), nodep->name(), nodep->modp()->name()}; idtypep->ifacep(nullptr); // cellp overrides - // In the case of arrayed interfaces, we replace cellp when de-arraying in V3Inst idtypep->cellp(nodep); // Only set when real parent cell known. AstVar* varp; if (nodep->rangep()) { + // For arrayed interfaces, we replace cellp when de-arraying in V3Inst AstNodeArrayDType* const arrp = new AstUnpackArrayDType{nodep->fileline(), VFlagChildDType{}, idtypep, nodep->rangep()->cloneTree(true)}; @@ -511,13 +521,6 @@ class LinkCellsVisitor final : public VNVisitor { nodep->hasIfaceVar(true); } } - if (nodep->hasNoParens()) { - // Need in the grammar, otherwise it looks like "id/*data_type*/ id/*new_var*/;" - nodep->v3error("Instantiation " << nodep->prettyNameQ() - << " requires parenthesis (IEEE 1800-2023 23.3.2)\n" - << nodep->warnMore() << "... Suggest use '" - << nodep->prettyName() << "()'"); - } if (nodep->modp()) { // iterateChildren(nodep); } @@ -530,6 +533,10 @@ class LinkCellsVisitor final : public VNVisitor { pinp->param(true); if (pinp->name() == "") pinp->name("__paramNumber" + cvtToStr(pinp->pinNum())); } + if (m_varp) { // Parser didn't know what was interface, resolve now + const AstNodeModule* const varModp = findModuleSym(nodep->name()); + if (VN_IS(varModp, Iface)) m_varp->setIfaceRef(); + } } void visit(AstClassOrPackageRef* nodep) override { iterateChildren(nodep); @@ -543,6 +550,17 @@ class LinkCellsVisitor final : public VNVisitor { } } + void visit(AstVar* nodep) override { + { + VL_RESTORER(m_varp); + m_varp = nodep; + iterateAndNextNull(nodep->childDTypep()); + } + iterateAndNextNull(nodep->delayp()); + iterateAndNextNull(nodep->valuep()); + iterateAndNextNull(nodep->attrsp()); + } + void visit(AstNode* nodep) override { iterateChildren(nodep); } // METHODS diff --git a/src/V3LinkCells.h b/src/V3LinkCells.h index 5400ed83b..99254ef33 100644 --- a/src/V3LinkCells.h +++ b/src/V3LinkCells.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 41a449d33..c747239f4 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -84,6 +84,12 @@ class LinkNodeMatcherClass final : public VNodeMatcher { public: bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, Class); } }; +class LinkNodeMatcherClassOrPackage final : public VNodeMatcher { +public: + bool nodeMatch(const AstNode* nodep) const override { + return VN_IS(nodep, Class) || VN_IS(nodep, Package); + } +}; class LinkNodeMatcherFTask final : public VNodeMatcher { public: bool nodeMatch(const AstNode* nodep) const override { return VN_IS(nodep, NodeFTask); } @@ -274,7 +280,7 @@ public: } else if (foundp->imported()) { // From package // We don't throw VARHIDDEN as if the import is later the symbol // table's import wouldn't warn - } else if (VN_IS(nodep, Begin) && VN_IS(fnodep, Begin) + } else if (forPrimary() && VN_IS(nodep, Begin) && VN_IS(fnodep, Begin) && VN_AS(nodep, Begin)->generate()) { // Begin: ... blocks often replicate under genif/genfor, so // suppress duplicate checks. See t_gen_forif.v for an example. @@ -476,6 +482,15 @@ public: UINFO(9, " insAllIface se" << cvtToHex(varSymp) << " " << varp << endl); AstIfaceRefDType* const ifacerefp = ifaceRefFromArray(varp->subDTypep()); UASSERT_OBJ(ifacerefp, varp, "Non-ifacerefs on list!"); + const bool varGotPort = varp && varp->user4(); + if (ifacerefp->isPortDecl() && !varGotPort) { + varp->v3error("Interface port declaration " + << varp->prettyNameQ() << " doesn't have corresponding port\n" + << varp->warnMore() + + "... Perhaps intended an interface instantiation but " + "are missing parenthesis (IEEE 1800-2023 25.3)?"); + } + ifacerefp->isPortDecl(false); // Only needed for this warning; soon removing AstPort if (!ifacerefp->ifaceViaCellp()) { if (!ifacerefp->cellp()) { // Probably a NotFoundModule, or a normal module if // made mistake @@ -750,6 +765,25 @@ public: if (!foundp) baddot = dotname; return foundp; } + VSymEnt* resolveClassOrPackage(VSymEnt* lookSymp, AstClassOrPackageRef* nodep, bool classOnly, + const string& forWhat) { + if (nodep->classOrPackageSkipp()) return getNodeSym(nodep->classOrPackageSkipp()); + VSymEnt* foundp = lookSymp->findIdFallback(nodep->name()); + if (!foundp && v3Global.rootp()->stdPackagep()) { // Look under implied std:: + foundp = getNodeSym(v3Global.rootp()->stdPackagep())->findIdFlat(nodep->name()); + } + if (foundp) { + nodep->classOrPackageNodep(foundp->nodep()); + return foundp; + } + const string suggest + = suggestSymFallback(lookSymp, nodep->name(), LinkNodeMatcherClassOrPackage{}); + nodep->v3error((classOnly ? "Class" : "Package/class") + << " for '" << forWhat // extends/implements + << "' not found: " << nodep->prettyNameQ() << '\n' + << (suggest.empty() ? "" : nodep->warnMore() + suggest)); + return nullptr; + } string suggestSymFallback(VSymEnt* lookupSymp, const string& name, const VNodeMatcher& matcher) { // Suggest alternative symbol in given point in hierarchy @@ -1002,6 +1036,16 @@ class LinkDotFindVisitor final : public VNVisitor { if (!m_explicitNew && m_statep->forPrimary()) makeImplicitNew(nodep); } } + void visit(AstClassOrPackageRef* nodep) override { + if (!nodep->classOrPackageNodep()) { + if (nodep->name() == "$unit") { + nodep->classOrPackageNodep(v3Global.rootp()->dollarUnitPkgAddp()); + } else if (nodep->name() == "std") { + nodep->classOrPackageNodep(v3Global.rootp()->stdPackagep()); + } + } + iterateChildren(nodep); + } void visit(AstScope* nodep) override { UASSERT_OBJ(m_statep->forScopeCreation(), nodep, "Scopes should only exist right after V3Scope"); @@ -1138,7 +1182,11 @@ class LinkDotFindVisitor final : public VNVisitor { nodep->v3warn(E_UNSUPPORTED, "Unsupported: extern function definition with class-in-class"); } else { - AstClass* const classp = VN_CAST(cpackagerefp->classOrPackagep(), Class); + if (!cpackagerefp->classOrPackageSkipp()) { + m_statep->resolveClassOrPackage(m_curSymp, cpackagerefp, false, + "External definition :: reference"); + } + AstClass* const classp = VN_CAST(cpackagerefp->classOrPackageSkipp(), Class); if (!classp) { nodep->v3error("Extern declaration's scope is not a defined class"); } else { @@ -1159,8 +1207,7 @@ class LinkDotFindVisitor final : public VNVisitor { m_classOrPackagep = VN_AS(m_curSymp->nodep(), Class); } // Create symbol table for the task's vars - const string name - = std::string{nodep->isExternProto() ? "extern " : ""} + nodep->name(); + const string name = (nodep->isExternProto() ? "extern "s : ""s) + nodep->name(); m_curSymp = m_statep->insertBlock(m_curSymp, name, nodep, m_classOrPackagep); m_curSymp->fallbackp(upSymp); // Convert the func's range to the output variable @@ -1251,7 +1298,35 @@ class LinkDotFindVisitor final : public VNVisitor { } void visit(AstConstraint* nodep) override { VL_RESTORER(m_curSymp); - m_curSymp = m_statep->insertBlock(m_curSymp, nodep->name(), nodep, m_classOrPackagep); + // Change to appropriate package if extern declaration (vs definition) + VSymEnt* upSymp = m_curSymp; + if (nodep->classOrPackagep()) { + AstClassOrPackageRef* const cpackagerefp + = VN_CAST(nodep->classOrPackagep(), ClassOrPackageRef); + if (!cpackagerefp) { + nodep->v3warn(E_UNSUPPORTED, + "Unsupported: extern constraint definition with class-in-class"); + } else { + if (!cpackagerefp->classOrPackageSkipp()) { + m_statep->resolveClassOrPackage(m_curSymp, cpackagerefp, false, + "External definition :: reference"); + } + AstClass* const classp = VN_CAST(cpackagerefp->classOrPackageSkipp(), Class); + if (!classp) { + nodep->v3error("Extern declaration's scope is not a defined class"); + } else { + m_curSymp = m_statep->getNodeSym(classp); + upSymp = m_curSymp; + // Move it to proper spot under the target class + nodep->unlinkFrBack(); + classp->addStmtsp(nodep); + nodep->classOrPackagep()->unlinkFrBack()->deleteTree(); + } + } + } + // Set the class as package for iteration + const string name = (nodep->isExternProto() ? "extern "s : ""s) + nodep->name(); + m_curSymp = m_statep->insertBlock(upSymp, name, nodep, m_classOrPackagep); iterateChildren(nodep); } void visit(AstVar* nodep) override { @@ -1644,7 +1719,6 @@ public: LinkDotFindVisitor(AstNetlist* rootp, LinkDotState* statep) : m_statep{statep} { UINFO(4, __FUNCTION__ << ": " << endl); - iterate(rootp); } ~LinkDotFindVisitor() override = default; @@ -2122,7 +2196,7 @@ class LinkDotResolveVisitor final : public VNVisitor { enum DotPosition : uint8_t { // Must match ascii() method below DP_NONE = 0, // Not under a DOT - DP_PACKAGE, // {package}:: DOT + DP_PACKAGE, // {package-or-class}:: DOT DP_FIRST, // {scope-or-var} DOT DP_SCOPE, // DOT... {scope-or-var} DOT DP_FINAL, // [DOT...] {var-or-func-or-dtype} with no following dots @@ -2134,7 +2208,7 @@ class LinkDotResolveVisitor final : public VNVisitor { VSymEnt* m_curSymp = nullptr; // SymEnt for current lookup point VSymEnt* m_modSymp = nullptr; // SymEnt for current module VSymEnt* m_pinSymp = nullptr; // SymEnt for pin lookups - VSymEnt* m_fromSymp = nullptr; // SymEnt for randomize lookups + VSymEnt* m_randSymp = nullptr; // SymEnt for randomize target class's lookups const AstCell* m_cellp = nullptr; // Current cell AstNodeModule* m_modp = nullptr; // Current module AstNodeFTask* m_ftaskp = nullptr; // Current function/task @@ -2180,8 +2254,9 @@ class LinkDotResolveVisitor final : public VNVisitor { std::ostringstream sstr; sstr << "ds=" << names[m_dotPos]; sstr << " dse" << cvtToHex(m_dotSymp); - sstr << "(" << m_dotSymp->nodep()->typeName() << ")"; - + const string dsname = m_dotSymp->nodep()->name().substr(0, 8); + sstr << "(" << m_dotSymp->nodep()->typeName() << (dsname.empty() ? "" : ":") << dsname + << ")"; if (m_dotErr) sstr << " [dotErr]"; if (m_super) sstr << " [super]"; if (m_unresolvedCell) sstr << " [unrCell]"; @@ -2325,48 +2400,63 @@ class LinkDotResolveVisitor final : public VNVisitor { } return classSymp; } - void importImplementsClass(AstClass* implementsClassp, VSymEnt* interfaceSymp, - AstClass* baseClassp) { + void importDerivedClass(AstClass* derivedClassp, VSymEnt* baseSymp, AstClass* baseClassp) { // Also used for standard 'extends' from a base class - UINFO(8, indent() << "importImplementsClass to " << implementsClassp << " from " - << baseClassp << endl); - for (VSymEnt::const_iterator it = interfaceSymp->begin(); it != interfaceSymp->end(); - ++it) { - if (AstNode* interfaceSubp = it->second->nodep()) { - UINFO(8, indent() << " SymFunc " << interfaceSubp << endl); - if (VN_IS(interfaceSubp, NodeFTask)) { - const VSymEnt* const foundp = m_curSymp->findIdFlat(interfaceSubp->name()); - const AstNodeFTask* const interfaceFuncp = VN_CAST(interfaceSubp, NodeFTask); - if (!interfaceFuncp || !interfaceFuncp->pureVirtual()) continue; - bool existsInChild = foundp && !foundp->imported(); - const string impOrExtends - = baseClassp->isInterfaceClass() ? " implements " : " extends "; - if (!existsInChild && !implementsClassp->isInterfaceClass()) { - implementsClassp->v3error( - "Class " << implementsClassp->prettyNameQ() << impOrExtends + UINFO(8, indent() << "importDerivedClass to " << derivedClassp << " from " << baseClassp + << endl); + for (VSymEnt::const_iterator it = baseSymp->begin(); it != baseSymp->end(); ++it) { + if (AstNode* baseSubp = it->second->nodep()) { + UINFO(8, indent() << " SymFunc " << baseSubp << endl); + const string impOrExtends + = baseClassp->isInterfaceClass() ? " implements " : " extends "; + if (VN_IS(baseSubp, NodeFTask)) { + const VSymEnt* const foundp = m_curSymp->findIdFlat(baseSubp->name()); + const AstNodeFTask* const baseFuncp = VN_CAST(baseSubp, NodeFTask); + if (!baseFuncp || !baseFuncp->pureVirtual()) continue; + bool existsInDerived = foundp && !foundp->imported(); + if (!existsInDerived && !derivedClassp->isInterfaceClass()) { + derivedClassp->v3error( + "Class " << derivedClassp->prettyNameQ() << impOrExtends << baseClassp->prettyNameQ() << " but is missing implementation for " - << interfaceSubp->prettyNameQ() << " (IEEE 1800-2023 8.26)\n" - << implementsClassp->warnContextPrimary() << '\n' - << interfaceSubp->warnOther() + << baseSubp->prettyNameQ() << " (IEEE 1800-2023 8.26)\n" + << derivedClassp->warnContextPrimary() << '\n' + << baseSubp->warnOther() << "... Location of interface class's function\n" - << interfaceSubp->warnContextSecondary()); + << baseSubp->warnContextSecondary()); } - const auto itn = m_ifClassImpNames.find(interfaceSubp->name()); - if (!existsInChild && itn != m_ifClassImpNames.end() - && itn->second != interfaceSubp) { // Not exact same function from diamond - implementsClassp->v3error( - "Class " << implementsClassp->prettyNameQ() << impOrExtends + const auto itn = m_ifClassImpNames.find(baseSubp->name()); + if (!existsInDerived && itn != m_ifClassImpNames.end() + && itn->second != baseSubp) { // Not exact same function from diamond + derivedClassp->v3error( + "Class " << derivedClassp->prettyNameQ() << impOrExtends << baseClassp->prettyNameQ() << " but missing inheritance conflict resolution for " - << interfaceSubp->prettyNameQ() - << " (IEEE 1800-2023 8.26.6.2)\n" - << implementsClassp->warnContextPrimary() << '\n' - << interfaceSubp->warnOther() + << baseSubp->prettyNameQ() << " (IEEE 1800-2023 8.26.6.2)\n" + << derivedClassp->warnContextPrimary() << '\n' + << baseSubp->warnOther() << "... Location of interface class's function\n" - << interfaceSubp->warnContextSecondary()); + << baseSubp->warnContextSecondary()); + } + m_ifClassImpNames.emplace(baseSubp->name(), baseSubp); + } + if (VN_IS(baseSubp, Constraint)) { + const VSymEnt* const foundp = m_curSymp->findIdFlat(baseSubp->name()); + const AstConstraint* const baseFuncp = VN_CAST(baseSubp, Constraint); + if (!baseFuncp || !baseFuncp->isKwdPure()) continue; + bool existsInDerived = foundp && !foundp->imported(); + if (!existsInDerived && !derivedClassp->isInterfaceClass() + && !derivedClassp->isVirtual()) { + derivedClassp->v3error( + "Class " << derivedClassp->prettyNameQ() << impOrExtends + << baseClassp->prettyNameQ() + << " but is missing constraint implementation for " + << baseSubp->prettyNameQ() << " (IEEE 1800-2023 18.5.2)\n" + << derivedClassp->warnContextPrimary() << '\n' + << baseSubp->warnOther() + << "... Location of interface class's pure constraint\n" + << baseSubp->warnContextSecondary()); } - m_ifClassImpNames.emplace(interfaceSubp->name(), interfaceSubp); } } } @@ -2374,24 +2464,39 @@ class LinkDotResolveVisitor final : public VNVisitor { void importSymbolsFromExtended(AstClass* const nodep, AstClassExtends* const cextp) { AstClass* const baseClassp = cextp->classp(); VSymEnt* const srcp = m_statep->getNodeSym(baseClassp); - importImplementsClass(nodep, srcp, baseClassp); + importDerivedClass(nodep, srcp, baseClassp); if (!cextp->isImplements()) m_curSymp->importFromClass(m_statep->symsp(), srcp); } void classExtendImport(AstClass* nodep) { // A class reference might be to a class that is later in Ast due to // e.g. parmaeterization or referring to a "class (type T) extends T" // Resolve it so later Class:: references into its base classes work - VL_RESTORER(m_ds); - VSymEnt* const srcp = m_statep->getNodeSym(nodep); - m_ds.init(srcp); - iterate(nodep); + symIterateNull(nodep, m_statep->getNodeSym(nodep)); } + void updateVarUse(AstVar* nodep) { // Avoid dotted.PARAM false positive when in a parameter block // that is if ()'ed off by same dotted name as another block if (nodep && nodep->isParam()) nodep->usedParam(true); } + void symIterateChildren(AstNode* nodep, VSymEnt* symp) { + // Iterate children, changing to given context, with restore to old context + VL_RESTORER(m_ds); + VL_RESTORER(m_curSymp); + m_curSymp = symp; + m_ds.init(m_curSymp); + iterateChildren(nodep); + } + void symIterateNull(AstNode* nodep, VSymEnt* symp) { + // Iterate node, changing to given context, with restore to old context + VL_RESTORER(m_ds); + VL_RESTORER(m_curSymp); + m_curSymp = symp; + m_ds.init(m_curSymp); + iterateNull(nodep); + } + #define LINKDOT_VISIT_START() \ VL_RESTORER(m_indent); \ ++m_indent; @@ -2427,14 +2532,12 @@ class LinkDotResolveVisitor final : public VNVisitor { void visit(AstScope* nodep) override { LINKDOT_VISIT_START(); UINFO(8, indent() << "visit " << nodep << endl); + checkNoDot(nodep); VL_RESTORER(m_modSymp); VL_RESTORER(m_curSymp); - { - checkNoDot(nodep); - m_ds.m_dotSymp = m_curSymp = m_modSymp = m_statep->getScopeSym(nodep); - iterateChildren(nodep); - m_ds.m_dotSymp = m_curSymp = m_modSymp = nullptr; - } + m_ds.m_dotSymp = m_curSymp = m_modSymp = m_statep->getScopeSym(nodep); + iterateChildren(nodep); + m_ds.m_dotSymp = m_curSymp = m_modSymp = nullptr; } void visit(AstCellInline* nodep) override { LINKDOT_VISIT_START(); @@ -2571,7 +2674,7 @@ class LinkDotResolveVisitor final : public VNVisitor { UINFO(8, indent() << m_ds.ascii() << endl); const DotStates lastStates = m_ds; const bool start = (m_ds.m_dotPos == DP_NONE); // Save, as m_dotp will be changed - VL_RESTORER(m_fromSymp); + VL_RESTORER(m_randSymp); { if (start) { // Starting dot sequence if (debug() >= 9) nodep->dumpTree("- dot-in: "); @@ -2603,6 +2706,8 @@ class LinkDotResolveVisitor final : public VNVisitor { } else { if (m_statep->forPrimary() && m_extendsParam.find(classp) != m_extendsParam.end()) { + UINFO(9, indent() << "deferring until post-V3Param: " << nodep->lhsp() + << endl); m_ds.m_unresolvedClass = true; } else { const auto baseClassp = cextp->classp(); @@ -2629,6 +2734,7 @@ class LinkDotResolveVisitor final : public VNVisitor { } if (m_statep->forPrimary() && isParamedClassRef(nodep->lhsp())) { // Dots of paramed classes will be linked after deparameterization + UINFO(9, indent() << "deferring until post-V3Param: " << nodep->lhsp() << endl); m_ds.m_unresolvedClass = true; } if (m_ds.m_unresolvedCell @@ -2641,6 +2747,7 @@ class LinkDotResolveVisitor final : public VNVisitor { // DOT(DOT(x,*here*),real-rhs) which we consider a RHS if (start && m_ds.m_dotPos == DP_SCOPE) m_ds.m_dotPos = DP_FINAL; UINFO(8, indent() << "iter.rhs " << m_ds.ascii() << " " << nodep << endl); + // m_ds.m_dotSymp points at lhsp()'s symbol table, so resolve RHS under that iterateAndNextNull(nodep->rhsp()); UINFO(8, indent() << "iter.rdone " << m_ds.ascii() << " " << nodep << endl); // if (debug() >= 9) nodep->dumpTree("- dot-rho: "); @@ -2683,6 +2790,35 @@ class LinkDotResolveVisitor final : public VNVisitor { m_inSens = true; iterateChildren(nodep); } + void visit(AstPatMember* nodep) override { + LINKDOT_VISIT_START(); + if (nodep->varrefp()) return; // only do this mapping once + // If we have a TEXT token as our key, lookup if it's a LPARAM + if (AstText* const textp = VN_CAST(nodep->keyp(), Text)) { + UINFO(9, indent() << "visit " << nodep << endl); + UINFO(9, indent() << " " << textp << endl); + // Lookup + if (VSymEnt* const foundp = m_curSymp->findIdFallback(textp->text())) { + if (AstVar* const varp = VN_CAST(foundp->nodep(), Var)) { + if (varp->isParam() || varp->isGenVar()) { + // Attach found Text reference to PatMember + nodep->varrefp( + new AstVarRef{nodep->fileline(), + foundp->imported() ? foundp->classOrPackagep() : nullptr, + varp, VAccess::READ}); + UINFO(9, indent() << " new " << nodep->varrefp() << endl); + } + } + if (AstEnumItem* const itemp = VN_CAST(foundp->nodep(), EnumItem)) { + // Attach enum item value to PatMember + nodep->varrefp( + new AstEnumItemRef{nodep->fileline(), itemp, foundp->classOrPackagep()}); + UINFO(9, indent() << " new " << itemp << endl); + } + } + } + iterateChildren(nodep); + } void visit(AstParseRef* nodep) override { if (nodep->user3SetOnce()) return; LINKDOT_VISIT_START(); @@ -2753,23 +2889,30 @@ class LinkDotResolveVisitor final : public VNVisitor { bool allowFTask = false; bool staticAccess = false; if (m_ds.m_dotPos == DP_PACKAGE) { - // {package}::{a} + // {package-or-class}::{a} AstNodeModule* classOrPackagep = nullptr; expectWhat = "scope/variable/func"; allowScope = true; allowVar = true; allowFTask = true; staticAccess = true; + UINFO(9, "chk pkg " << m_ds.ascii() << " lhsp=" << m_ds.m_dotp->lhsp() << endl); UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), ClassOrPackageRef), m_ds.m_dotp->lhsp(), "Bad package link"); AstClassOrPackageRef* const cpackagerefp = VN_AS(m_ds.m_dotp->lhsp(), ClassOrPackageRef); - classOrPackagep = cpackagerefp->classOrPackagep(); - UASSERT_OBJ(classOrPackagep, m_ds.m_dotp->lhsp(), "Bad package link"); if (cpackagerefp->name() == "local::") { - m_fromSymp = nullptr; + m_randSymp = nullptr; first = true; + } else if (!cpackagerefp->classOrPackageSkipp()) { + VSymEnt* const foundp = m_statep->resolveClassOrPackage( + m_ds.m_dotSymp, cpackagerefp, false, ":: reference"); + if (!foundp) return; + classOrPackagep = cpackagerefp->classOrPackageSkipp(); + m_ds.m_dotSymp = m_statep->getNodeSym(classOrPackagep); } else { + classOrPackagep = cpackagerefp->classOrPackageSkipp(); + UASSERT_OBJ(classOrPackagep, m_ds.m_dotp->lhsp(), "Bad package link"); m_ds.m_dotSymp = m_statep->getNodeSym(classOrPackagep); } m_ds.m_dotPos = DP_SCOPE; @@ -2790,8 +2933,8 @@ class LinkDotResolveVisitor final : public VNVisitor { VSymEnt* foundp; string baddot; VSymEnt* okSymp = nullptr; - if (m_fromSymp) { - foundp = m_fromSymp->findIdFlat(nodep->name()); + if (m_randSymp) { + foundp = m_randSymp->findIdFlat(nodep->name()); if (foundp) { if (!start) m_ds.m_dotPos = DP_MEMBER; if (!m_inWith) { @@ -2923,6 +3066,8 @@ class LinkDotResolveVisitor final : public VNVisitor { refp->dotted(dotted.substr(0, pos)); newp = refp; } else { + UINFO(9, indent() + << "deferring until post-V3Param: " << refp << endl); newp = new AstUnlinkedRef{nodep->fileline(), refp, refp->name(), m_ds.m_unlinkedScopep->unlinkFrBack()}; m_ds.m_unlinkedScopep = nullptr; @@ -3032,7 +3177,6 @@ class LinkDotResolveVisitor final : public VNVisitor { if (m_ds.m_dotText != "") m_ds.m_dotText += "." + nodep->name(); ok = m_ds.m_dotPos == DP_SCOPE || m_ds.m_dotPos == DP_FIRST; } else if (const AstNodeFTask* const ftaskp = VN_CAST(foundp->nodep(), NodeFTask)) { - if (!ftaskp->isFunction() || ftaskp->classMethod()) { ok = m_ds.m_dotPos == DP_NONE; if (ok) { @@ -3114,45 +3258,82 @@ class LinkDotResolveVisitor final : public VNVisitor { VL_RESTORER(m_usedPins); m_usedPins.clear(); UASSERT_OBJ(m_statep->forPrimary() || VN_IS(nodep->classOrPackageNodep(), ParamTypeDType) - || nodep->classOrPackagep(), + || nodep->classOrPackageSkipp(), nodep, "ClassRef has unlinked class"); UASSERT_OBJ(m_statep->forPrimary() || !nodep->paramsp(), nodep, "class reference parameter not removed by V3Param"); - VL_RESTORER(m_ds); - VL_RESTORER(m_pinSymp); + { + VL_RESTORER(m_ds); + VL_RESTORER(m_pinSymp); - if (nodep->name() == "std" && !nodep->classOrPackagep()) { - nodep->classOrPackagep(v3Global.rootp()->stdPackagep()); - } - // ClassRef's have pins, so track - if (nodep->classOrPackagep()) { - m_pinSymp = m_statep->getNodeSym(nodep->classOrPackagep()); - } - AstClass* const refClassp = VN_CAST(nodep->classOrPackagep(), Class); - // Make sure any extends() are properly imported within referenced class - if (refClassp && !m_statep->forPrimary()) classExtendImport(refClassp); + if (!nodep->classOrPackageSkipp() && nodep->name() != "local::") { + m_statep->resolveClassOrPackage(m_ds.m_dotSymp, nodep, false, ":: reference"); + } - m_ds.init(m_curSymp); - UINFO(4, indent() << "(Backto) Link ClassOrPackageRef: " << nodep << endl); - iterateChildren(nodep); + // ClassRef's have pins, so track + if (nodep->classOrPackageSkipp()) { + m_pinSymp = m_statep->getNodeSym(nodep->classOrPackageSkipp()); + } + AstClass* const refClassp = VN_CAST(nodep->classOrPackageSkipp(), Class); + // Make sure any extends() are properly imported within referenced class + if (refClassp && !m_statep->forPrimary()) classExtendImport(refClassp); - if (nodep->name() == "local::") { - if (!m_fromSymp) { - nodep->v3error("Illegal 'local::' outside 'randomize() with'"); - m_ds.m_dotErr = true; + m_ds.init(m_curSymp); + UINFO(4, indent() << "(Backto) Link ClassOrPackageRef: " << nodep << endl); + iterateChildren(nodep); + + AstClass* const modClassp = VN_CAST(m_modp, Class); + if (m_statep->forPrimary() && refClassp && !nodep->paramsp() + && nodep->classOrPackageSkipp()->hasGParam() + // Don't warn on typedefs, which are hard to know if there's a param somewhere + // buried + && VN_IS(nodep->classOrPackageNodep(), Class) + // References to class:: within class itself are OK per IEEE (UVM does this) + && modClassp != refClassp) { + nodep->v3error( + "Reference to parameterized class without #() (IEEE 1800-2023 8.25.1)\n" + << nodep->warnMore() << "... Suggest use '" + << nodep->classOrPackageNodep()->prettyName() << "#()'"); } } - AstClass* const modClassp = VN_CAST(m_modp, Class); - if (m_statep->forPrimary() && refClassp && !nodep->paramsp() - && nodep->classOrPackagep()->hasGParam() - // Don't warn on typedefs, which are hard to know if there's a param somewhere buried - && VN_IS(nodep->classOrPackageNodep(), Class) - // References to class:: within class itself are OK per IEEE (UVM does this) - && modClassp != refClassp) { - nodep->v3error("Reference to parameterized class without #() (IEEE 1800-2023 8.25.1)\n" - << nodep->warnMore() << "... Suggest use '" - << nodep->classOrPackageNodep()->prettyName() << "#()'"); + + if (nodep->name() == "local::") { + if (!m_randSymp) { + nodep->v3error("Illegal 'local::' outside 'randomize() with'" + " (IEEE 1800-2023 18.7.1)"); + m_ds.m_dotErr = true; + return; + } } + if (m_ds.m_dotPos == DP_PACKAGE && nodep->classOrPackageSkipp()) { + m_ds.m_dotSymp = m_statep->getNodeSym(nodep->classOrPackageSkipp()); + UINFO(9, indent() << "set sym " << m_ds.ascii() << endl); + } + } + void visit(AstConstraint* nodep) override { + LINKDOT_VISIT_START(); + UINFO(5, indent() << "visit " << nodep << endl); + checkNoDot(nodep); + if (nodep->isExternDef()) { + if (const VSymEnt* const foundp + = m_curSymp->findIdFallback("extern " + nodep->name())) { + const AstConstraint* const protop = VN_AS(foundp->nodep(), Constraint); + // Copy specifiers. + // External definition cannot have any specifiers, so no value will be overwritten. + nodep->isStatic(protop->isStatic()); + } else { + nodep->v3error("extern not found that declares " + nodep->prettyNameQ()); + } + } + if (nodep->isExternProto()) { + if (!m_curSymp->findIdFallback(nodep->name()) && nodep->isExternExplicit()) { + nodep->v3error("Definition not found for extern " + nodep->prettyNameQ()); + } + } + VL_RESTORER(m_curSymp); + VL_RESTORER(m_ds); + m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep); + iterateChildren(nodep); } void visit(AstConstraintRef* nodep) override { if (nodep->user3SetOnce()) return; @@ -3297,7 +3478,7 @@ class LinkDotResolveVisitor final : public VNVisitor { LINKDOT_VISIT_START(); UINFO(5, indent() << "visit " << nodep << endl); VL_RESTORER(m_ds); - VL_RESTORER(m_fromSymp); + VL_RESTORER(m_randSymp); VL_RESTORER(m_randMethodCallp); { m_ds.init(m_curSymp); @@ -3340,7 +3521,7 @@ class LinkDotResolveVisitor final : public VNVisitor { nodep->v3error("'randomize() with' on a non-class-instance " << fromDtp->prettyNameQ()); else - m_fromSymp = m_statep->getNodeSym(classDtp->classp()); + m_randSymp = m_statep->getNodeSym(classDtp->classp()); } } iterateChildren(nodep); @@ -3363,9 +3544,7 @@ class LinkDotResolveVisitor final : public VNVisitor { if (m_ds.m_dotPos != DP_MEMBER || nodep->name() != "randomize") { // Visit arguments at the beginning. // They may be visitted even if the current node can't be linked now. - VL_RESTORER(m_ds); - m_ds.init(m_curSymp); - iterateChildren(nodep); + symIterateChildren(nodep, m_curSymp); } if (m_ds.m_super) { @@ -3376,7 +3555,7 @@ class LinkDotResolveVisitor final : public VNVisitor { } } - VL_RESTORER(m_fromSymp); + VL_RESTORER(m_randSymp); bool first = !m_ds.m_dotp || m_ds.m_dotPos == DP_FIRST; bool staticAccess = false; @@ -3398,12 +3577,15 @@ class LinkDotResolveVisitor final : public VNVisitor { staticAccess = true; AstClassOrPackageRef* const cpackagerefp = VN_AS(m_ds.m_dotp->lhsp(), ClassOrPackageRef); - UASSERT_OBJ(cpackagerefp->classOrPackagep(), m_ds.m_dotp->lhsp(), "Bad package link"); if (cpackagerefp->name() == "local::") { - m_fromSymp = nullptr; + m_randSymp = nullptr; first = true; + } else if (!cpackagerefp->classOrPackageSkipp()) { + VSymEnt* const foundp = m_statep->resolveClassOrPackage( + m_ds.m_dotSymp, cpackagerefp, false, ":: reference"); + if (foundp) nodep->classOrPackagep(cpackagerefp->classOrPackageSkipp()); } else { - nodep->classOrPackagep(cpackagerefp->classOrPackagep()); + nodep->classOrPackagep(cpackagerefp->classOrPackageSkipp()); } // Class/package :: HERE function() . method_called_on_function_return_value() m_ds.m_dotPos = DP_MEMBER; @@ -3472,8 +3654,8 @@ class LinkDotResolveVisitor final : public VNVisitor { dotSymp = m_statep->findDotted(nodep->fileline(), dotSymp, nodep->dotted(), baddot, okSymp, true); // Maybe nullptr } - if (m_fromSymp) { - VSymEnt* const foundp = m_fromSymp->findIdFlat(nodep->name()); + if (m_randSymp) { + VSymEnt* const foundp = m_randSymp->findIdFlat(nodep->name()); if (foundp && m_inWith) { UINFO(9, indent() << "randomize-with fromSym " << foundp->nodep() << endl); AstNodeExpr* argsp = nullptr; @@ -3617,16 +3799,10 @@ class LinkDotResolveVisitor final : public VNVisitor { m_ds.m_unresolvedCell = true; // And pass up m_ds.m_dotText } - // Pass dot state down to fromp() + // Pass dot state down to only fromp() iterateAndNextNull(nodep->fromp()); - { - VL_RESTORER(m_ds); - { - m_ds.init(m_curSymp); - iterateAndNextNull(nodep->bitp()); - iterateAndNextNull(nodep->attrp()); - } - } + symIterateNull(nodep->bitp(), m_curSymp); + symIterateNull(nodep->attrp(), m_curSymp); if (m_ds.m_unresolvedCell && (m_ds.m_dotPos == DP_SCOPE || m_ds.m_dotPos == DP_FIRST)) { AstNodeExpr* const exprp = nodep->bitp()->unlinkFrBack(); AstCellArrayRef* const newp @@ -3648,12 +3824,8 @@ class LinkDotResolveVisitor final : public VNVisitor { return; } iterateAndNextNull(nodep->fromp()); - VL_RESTORER(m_ds); - { - m_ds.init(m_curSymp); - iterateAndNextNull(nodep->rhsp()); - iterateAndNextNull(nodep->thsp()); - } + symIterateNull(nodep->rhsp(), m_curSymp); + symIterateNull(nodep->thsp(), m_curSymp); if (nodep->attrp()) { AstNode* const attrp = nodep->attrp()->unlinkFrBack(); @@ -3677,15 +3849,15 @@ class LinkDotResolveVisitor final : public VNVisitor { LINKDOT_VISIT_START(); UINFO(5, indent() << "visit " << nodep << endl); checkNoDot(nodep); - VL_RESTORER(m_curSymp); { + VL_RESTORER(m_curSymp); + VL_RESTORER(m_ds); if (nodep->name() != "") { m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep); UINFO(5, indent() << "cur=se" << cvtToHex(m_curSymp) << endl); } iterateChildren(nodep); } - m_ds.m_dotSymp = VL_RESTORER_PREV(m_curSymp); UINFO(5, indent() << "cur=se" << cvtToHex(m_curSymp) << endl); } void visit(AstNodeFTask* nodep) override { @@ -3695,14 +3867,14 @@ class LinkDotResolveVisitor final : public VNVisitor { if (nodep->isExternDef()) { if (const VSymEnt* const foundp = m_curSymp->findIdFallback("extern " + nodep->name())) { - const AstNodeFTask* const funcProtop = VN_AS(foundp->nodep(), NodeFTask); + const AstNodeFTask* const protop = VN_AS(foundp->nodep(), NodeFTask); // Copy specifiers. // External definition cannot have any specifiers, so no value will be overwritten. - nodep->isHideLocal(funcProtop->isHideLocal()); - nodep->isHideProtected(funcProtop->isHideProtected()); - nodep->isStatic(funcProtop->isStatic()); - nodep->isVirtual(funcProtop->isVirtual()); - nodep->lifetime(funcProtop->lifetime()); + nodep->isHideLocal(protop->isHideLocal()); + nodep->isHideProtected(protop->isHideProtected()); + nodep->isStatic(protop->isStatic()); + nodep->isVirtual(protop->isVirtual()); + nodep->lifetime(protop->lifetime()); } else { nodep->v3error("extern not found that declares " + nodep->prettyNameQ()); } @@ -3734,12 +3906,7 @@ class LinkDotResolveVisitor final : public VNVisitor { LINKDOT_VISIT_START(); UINFO(5, indent() << "visit " << nodep << endl); checkNoDot(nodep); - VL_RESTORER(m_curSymp); - { - m_ds.m_dotSymp = m_curSymp = m_statep->getNodeSym(nodep); - iterateChildren(nodep); - } - m_ds.m_dotSymp = VL_RESTORER_PREV(m_curSymp); + symIterateChildren(nodep, m_statep->getNodeSym(nodep)); } void visit(AstWith* nodep) override { LINKDOT_VISIT_START(); @@ -3775,7 +3942,11 @@ class LinkDotResolveVisitor final : public VNVisitor { if (AstClassOrPackageRef* lookNodep = VN_CAST(dotp->lhsp(), ClassOrPackageRef)) { iterate(lookNodep); cprp = dotp->rhsp(); - lookSymp = m_statep->getNodeSym(lookNodep->classOrPackagep()); + VSymEnt* const foundp = m_statep->resolveClassOrPackage( + lookSymp, lookNodep, false, nodep->verilogKwd()); + if (!foundp) return; + UASSERT_OBJ(lookNodep->classOrPackageSkipp(), nodep, "Bad package link"); + lookSymp = m_statep->getNodeSym(lookNodep->classOrPackageSkipp()); } else { dotp->lhsp()->v3error("Attempting to extend" // LCOV_EXCL_LINE " using non-class under dot"); @@ -3787,7 +3958,8 @@ class LinkDotResolveVisitor final : public VNVisitor { nodep->v3error("Attempting to extend using non-class"); // LCOV_EXCL_LINE return; } - VSymEnt* const foundp = lookSymp->findIdFallback(cpackagerefp->name()); + VSymEnt* const foundp = m_statep->resolveClassOrPackage(lookSymp, cpackagerefp, true, + nodep->verilogKwd()); if (foundp) { if (AstClass* const classp = VN_CAST(foundp->nodep(), Class)) { AstPin* paramsp = cpackagerefp->paramsp(); @@ -3812,12 +3984,6 @@ class LinkDotResolveVisitor final : public VNVisitor { return; } } else { - const string suggest = m_statep->suggestSymFallback( - m_curSymp, cpackagerefp->name(), LinkNodeMatcherClass{}); - cpackagerefp->v3error( - "Class for '" << nodep->verilogKwd() // extends/implements - << "' not found: " << cpackagerefp->prettyNameQ() << '\n' - << (suggest.empty() ? "" : cpackagerefp->warnMore() + suggest)); return; } if (!nodep->childDTypep()) nodep->v3error("Attempting to extend using non-class"); @@ -3948,14 +4114,21 @@ class LinkDotResolveVisitor final : public VNVisitor { const AstClass* const clsp = VN_CAST(cpackagerefp->classOrPackageNodep(), Class); if (clsp && clsp->isParameterized()) { // Unable to link before the instantiation of parameter classes. - // The class reference node has to be visited to properly link parameters. + // The class reference node still has to be visited now to later link + // parameters. iterate(cpackagep); return; } - nodep->classOrPackagep(cpackagerefp->classOrPackagep()); + if (!cpackagerefp->classOrPackageSkipp()) { + VSymEnt* const foundp = m_statep->resolveClassOrPackage( + m_ds.m_dotSymp, cpackagerefp, false, "class/package reference"); + if (!foundp) return; + } + nodep->classOrPackagep(cpackagerefp->classOrPackageSkipp()); if (!VN_IS(nodep->classOrPackagep(), Class) && !VN_IS(nodep->classOrPackagep(), Package)) { - cpackagerefp->v3error( + // Likely impossible, as error thrown earlier + cpackagerefp->v3error( // LCOV_EXCL_LINE "'::' expected to reference a class/package but referenced '" << (nodep->classOrPackagep() ? nodep->classOrPackagep()->prettyTypeName() : "") @@ -3972,8 +4145,9 @@ class LinkDotResolveVisitor final : public VNVisitor { UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), ClassOrPackageRef), m_ds.m_dotp->lhsp(), "Bad package link"); auto* const cpackagerefp = VN_AS(m_ds.m_dotp->lhsp(), ClassOrPackageRef); - UASSERT_OBJ(cpackagerefp->classOrPackagep(), m_ds.m_dotp->lhsp(), "Bad package link"); - nodep->classOrPackagep(cpackagerefp->classOrPackagep()); + UASSERT_OBJ(cpackagerefp->classOrPackageSkipp(), m_ds.m_dotp->lhsp(), + "Bad package link"); + nodep->classOrPackagep(cpackagerefp->classOrPackageSkipp()); m_ds.m_dotPos = DP_SCOPE; } else { checkNoDot(nodep); @@ -4019,7 +4193,7 @@ class LinkDotResolveVisitor final : public VNVisitor { if (foundp) { nodep->v3error("Expecting a data type: " << nodep->prettyNameQ()); } else { - nodep->v3error("Can't find typedef: " << nodep->prettyNameQ()); + nodep->v3error("Can't find typedef/interface: " << nodep->prettyNameQ()); } } } diff --git a/src/V3LinkDot.h b/src/V3LinkDot.h index 0231c9a64..943baceda 100644 --- a/src/V3LinkDot.h +++ b/src/V3LinkDot.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 fdc6aa9b5..0dd3fc3b4 100644 --- a/src/V3LinkInc.cpp +++ b/src/V3LinkInc.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.h b/src/V3LinkInc.h index 920f77c1d..7a2015ac8 100644 --- a/src/V3LinkInc.h +++ b/src/V3LinkInc.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 7919b9ecb..a69053115 100644 --- a/src/V3LinkJump.cpp +++ b/src/V3LinkJump.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -163,11 +163,9 @@ class LinkJumpVisitor final : public VNVisitor { if (nodep->dead()) return; VL_RESTORER(m_modp); VL_RESTORER(m_modRepeatNum); - { - m_modp = nodep; - m_modRepeatNum = 0; - iterateChildren(nodep); - } + m_modp = nodep; + m_modRepeatNum = 0; + iterateChildren(nodep); } void visit(AstNodeFTask* nodep) override { m_ftaskp = nodep; @@ -236,15 +234,13 @@ class LinkJumpVisitor final : public VNVisitor { m_unrollFull = VOptionBool::OPT_DEFAULT_FALSE; VL_RESTORER(m_loopp); VL_RESTORER(m_loopInc); - { - m_loopp = nodep; - m_loopInc = false; - iterateAndNextNull(nodep->precondsp()); - iterateAndNextNull(nodep->condp()); - iterateAndNextNull(nodep->stmtsp()); - m_loopInc = true; - iterateAndNextNull(nodep->incsp()); - } + m_loopp = nodep; + m_loopInc = false; + iterateAndNextNull(nodep->precondsp()); + iterateAndNextNull(nodep->condp()); + iterateAndNextNull(nodep->stmtsp()); + m_loopInc = true; + iterateAndNextNull(nodep->incsp()); } void visit(AstDoWhile* nodep) override { // It is converted to AstWhile in this visit method @@ -272,10 +268,8 @@ class LinkJumpVisitor final : public VNVisitor { } void visit(AstNodeForeach* nodep) override { VL_RESTORER(m_loopp); - { - m_loopp = nodep; - iterateAndNextNull(nodep->stmtsp()); - } + m_loopp = nodep; + iterateAndNextNull(nodep->stmtsp()); } void visit(AstReturn* nodep) override { iterateChildren(nodep); diff --git a/src/V3LinkJump.h b/src/V3LinkJump.h index 72a7b7f71..3d73d5df8 100644 --- a/src/V3LinkJump.h +++ b/src/V3LinkJump.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 e0d14cdfb..7bdd6b9b5 100644 --- a/src/V3LinkLValue.cpp +++ b/src/V3LinkLValue.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -32,13 +32,13 @@ VL_DEFINE_DEBUG_FUNCTIONS; class LinkLValueVisitor final : public VNVisitor { // NODE STATE - // STATE + // STATE - for current visit position (use VL_RESTORER) bool m_setContinuously = false; // Set that var has some continuous assignment - bool m_setStrengthSpecified = false; // Set that var has assignment with strength specified. bool m_setForcedByCode = false; // Set that var is the target of an AstAssignForce/AstRelease bool m_setIfRand = false; // Update VarRefs if var declared as rand - bool m_inInitialStatic = false; // Set if inside AstInitialStatic + bool m_setStrengthSpecified = false; // Set that var has assignment with strength specified. bool m_inFunc = false; // Set if inside AstNodeFTask + bool m_inInitialStatic = false; // Set if inside AstInitialStatic VAccess m_setRefLvalue; // Set VarRefs to lvalues for pin assignments // VISITs @@ -48,6 +48,13 @@ class LinkLValueVisitor final : public VNVisitor { if (m_setIfRand && !(nodep->varp() && nodep->varp()->isRand())) return; if (m_setRefLvalue != VAccess::NOCHANGE) nodep->access(m_setRefLvalue); if (nodep->varp() && nodep->access().isWriteOrRW()) { + if (nodep->varp()->isParam()) { + // All parameters that did get constified happened before now + // as V3LinkLValue runs after V3Param + nodep->v3error("Storing to parameter variable " + << nodep->prettyNameQ() + << " in a context that is determined only at runtime"); + } if (m_setContinuously) { nodep->varp()->isContinuously(true); // Strength may only be specified in continuous assignment, @@ -74,6 +81,7 @@ class LinkLValueVisitor final : public VNVisitor { // Nodes that start propagating down lvalues void visit(AstPin* nodep) override { + VL_RESTORER(m_setRefLvalue); if (nodep->modVarp() && nodep->modVarp()->isWritable()) { // When the varref's were created, we didn't know the I/O state // Now that we do, and it's from a output, we know it's a lvalue @@ -87,6 +95,7 @@ class LinkLValueVisitor final : public VNVisitor { void visit(AstNodeAssign* nodep) override { VL_RESTORER(m_setRefLvalue); VL_RESTORER(m_setContinuously); + VL_RESTORER(m_setStrengthSpecified); { m_setRefLvalue = VAccess::WRITE; m_setContinuously = VN_IS(nodep, AssignW) || VN_IS(nodep, AssignAlias); @@ -137,75 +146,57 @@ class LinkLValueVisitor final : public VNVisitor { VL_RESTORER(m_setRefLvalue); VL_RESTORER(m_setContinuously); VL_RESTORER(m_setForcedByCode); - { - m_setRefLvalue = VAccess::WRITE; - m_setContinuously = false; - m_setForcedByCode = true; - iterateAndNextNull(nodep->lhsp()); - } + m_setRefLvalue = VAccess::WRITE; + m_setContinuously = false; + m_setForcedByCode = true; + iterateAndNextNull(nodep->lhsp()); } void visit(AstFireEvent* nodep) override { VL_RESTORER(m_setRefLvalue); - { - m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->operandp()); - } + m_setRefLvalue = VAccess::WRITE; + iterateAndNextNull(nodep->operandp()); } void visit(AstCastDynamic* nodep) override { VL_RESTORER(m_setRefLvalue); - { - m_setRefLvalue = VAccess::NOCHANGE; - iterateAndNextNull(nodep->fromp()); - m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->top()); - } + m_setRefLvalue = VAccess::NOCHANGE; + iterateAndNextNull(nodep->fromp()); + m_setRefLvalue = VAccess::WRITE; + iterateAndNextNull(nodep->top()); } void visit(AstFError* nodep) override { VL_RESTORER(m_setRefLvalue); - { - iterateAndNextNull(nodep->filep()); - m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->strp()); - } + iterateAndNextNull(nodep->filep()); + m_setRefLvalue = VAccess::WRITE; + iterateAndNextNull(nodep->strp()); } void visit(AstFGetS* nodep) override { VL_RESTORER(m_setRefLvalue); - { - iterateAndNextNull(nodep->filep()); - m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->strgp()); - } + iterateAndNextNull(nodep->filep()); + m_setRefLvalue = VAccess::WRITE; + iterateAndNextNull(nodep->strgp()); } void visit(AstFRead* nodep) override { VL_RESTORER(m_setRefLvalue); - { - iterateAndNextNull(nodep->filep()); - m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->memp()); - } + iterateAndNextNull(nodep->filep()); + m_setRefLvalue = VAccess::WRITE; + iterateAndNextNull(nodep->memp()); } void visit(AstFScanF* nodep) override { VL_RESTORER(m_setRefLvalue); - { - iterateAndNextNull(nodep->filep()); - m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->exprsp()); - } + iterateAndNextNull(nodep->filep()); + m_setRefLvalue = VAccess::WRITE; + iterateAndNextNull(nodep->exprsp()); } void visit(AstFUngetC* nodep) override { VL_RESTORER(m_setRefLvalue); - { - iterateAndNextNull(nodep->filep()); - m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->rhsp()); - } + iterateAndNextNull(nodep->filep()); + m_setRefLvalue = VAccess::WRITE; + iterateAndNextNull(nodep->rhsp()); } void visit(AstSScanF* nodep) override { VL_RESTORER(m_setRefLvalue); - { - m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->exprsp()); - } + m_setRefLvalue = VAccess::WRITE; + iterateAndNextNull(nodep->exprsp()); } void visit(AstSysIgnore* nodep) override { // Can't know if lvalue or not; presume not @@ -213,46 +204,36 @@ class LinkLValueVisitor final : public VNVisitor { } void visit(AstRand* nodep) override { VL_RESTORER(m_setRefLvalue); - { - if (!nodep->urandom()) m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->seedp()); - } + if (!nodep->urandom()) m_setRefLvalue = VAccess::WRITE; + iterateAndNextNull(nodep->seedp()); } void visit(AstReadMem* nodep) override { VL_RESTORER(m_setRefLvalue); - { - m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->memp()); - m_setRefLvalue = VAccess::NOCHANGE; - iterateAndNextNull(nodep->filenamep()); - iterateAndNextNull(nodep->lsbp()); - iterateAndNextNull(nodep->msbp()); - } + m_setRefLvalue = VAccess::WRITE; + iterateAndNextNull(nodep->memp()); + m_setRefLvalue = VAccess::NOCHANGE; + iterateAndNextNull(nodep->filenamep()); + iterateAndNextNull(nodep->lsbp()); + iterateAndNextNull(nodep->msbp()); } void visit(AstTestPlusArgs* nodep) override { VL_RESTORER(m_setRefLvalue); - { - m_setRefLvalue = VAccess::NOCHANGE; - iterateAndNextNull(nodep->searchp()); - } + m_setRefLvalue = VAccess::NOCHANGE; + iterateAndNextNull(nodep->searchp()); } void visit(AstValuePlusArgs* nodep) override { VL_RESTORER(m_setRefLvalue); - { - m_setRefLvalue = VAccess::NOCHANGE; - iterateAndNextNull(nodep->searchp()); - m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->outp()); - } + m_setRefLvalue = VAccess::NOCHANGE; + iterateAndNextNull(nodep->searchp()); + m_setRefLvalue = VAccess::WRITE; + iterateAndNextNull(nodep->outp()); } void visit(AstSFormat* nodep) override { VL_RESTORER(m_setRefLvalue); - { - m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->lhsp()); - m_setRefLvalue = VAccess::NOCHANGE; - iterateAndNextNull(nodep->fmtp()); - } + m_setRefLvalue = VAccess::WRITE; + iterateAndNextNull(nodep->lhsp()); + m_setRefLvalue = VAccess::NOCHANGE; + iterateAndNextNull(nodep->fmtp()); } void visit(AstNodeDistBiop* nodep) override { VL_RESTORER(m_setRefLvalue); @@ -271,13 +252,11 @@ class LinkLValueVisitor final : public VNVisitor { } void prepost_visit(AstNodeTriop* nodep) { VL_RESTORER(m_setRefLvalue); - { - m_setRefLvalue = VAccess::NOCHANGE; - iterateAndNextNull(nodep->lhsp()); - iterateAndNextNull(nodep->rhsp()); - m_setRefLvalue = VAccess::WRITE; - iterateAndNextNull(nodep->thsp()); - } + m_setRefLvalue = VAccess::NOCHANGE; + iterateAndNextNull(nodep->lhsp()); + iterateAndNextNull(nodep->rhsp()); + m_setRefLvalue = VAccess::WRITE; + iterateAndNextNull(nodep->thsp()); } void visit(AstPreAdd* nodep) override { prepost_visit(nodep); } void visit(AstPostAdd* nodep) override { prepost_visit(nodep); } @@ -287,38 +266,33 @@ class LinkLValueVisitor final : public VNVisitor { // Nodes that change LValue state void visit(AstSel* nodep) override { VL_RESTORER(m_setRefLvalue); - { - iterateAndNextNull(nodep->fromp()); - // Only set lvalues on the from - m_setRefLvalue = VAccess::NOCHANGE; - iterateAndNextNull(nodep->lsbp()); - iterateAndNextNull(nodep->widthp()); - } + iterateAndNextNull(nodep->fromp()); + // Only set lvalues on the from + m_setRefLvalue = VAccess::NOCHANGE; + iterateAndNextNull(nodep->lsbp()); + iterateAndNextNull(nodep->widthp()); } void visit(AstNodeSel* nodep) override { VL_RESTORER(m_setRefLvalue); - { // Only set lvalues on the from - iterateAndNextNull(nodep->fromp()); - m_setRefLvalue = VAccess::NOCHANGE; - iterateAndNextNull(nodep->bitp()); - } + // Only set lvalues on the from + iterateAndNextNull(nodep->fromp()); + m_setRefLvalue = VAccess::NOCHANGE; + iterateAndNextNull(nodep->bitp()); } void visit(AstCellArrayRef* nodep) override { VL_RESTORER(m_setRefLvalue); - { // selp is not an lvalue - m_setRefLvalue = VAccess::NOCHANGE; - iterateAndNextNull(nodep->selp()); - } + // selp is not an lvalue + m_setRefLvalue = VAccess::NOCHANGE; + iterateAndNextNull(nodep->selp()); } void visit(AstNodePreSel* nodep) override { if (AstSelBit* const selbitp = VN_CAST(nodep, SelBit)) selbitp->access(m_setRefLvalue); VL_RESTORER(m_setRefLvalue); - { // Only set lvalues on the from - iterateAndNextNull(nodep->fromp()); - m_setRefLvalue = VAccess::NOCHANGE; - iterateAndNextNull(nodep->rhsp()); - iterateAndNextNull(nodep->thsp()); - } + // Only set lvalues on the from + iterateAndNextNull(nodep->fromp()); + m_setRefLvalue = VAccess::NOCHANGE; + iterateAndNextNull(nodep->rhsp()); + iterateAndNextNull(nodep->thsp()); } void visit(AstMemberSel* nodep) override { if (m_setRefLvalue != VAccess::NOCHANGE) { @@ -350,9 +324,9 @@ class LinkLValueVisitor final : public VNVisitor { AstNodeExpr* const pinp = argp->exprp(); if (!pinp) continue; if (portp->isWritable()) { + VL_RESTORER(m_setRefLvalue); m_setRefLvalue = VAccess::WRITE; iterate(pinp); - m_setRefLvalue = VAccess::NOCHANGE; } else { iterate(pinp); } diff --git a/src/V3LinkLValue.h b/src/V3LinkLValue.h index 99cf582a1..bc9d2acb5 100644 --- a/src/V3LinkLValue.h +++ b/src/V3LinkLValue.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 76254c77c..b982dbbe0 100644 --- a/src/V3LinkLevel.cpp +++ b/src/V3LinkLevel.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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 V3LinkLevel::modSortByLevel() { UASSERT_OBJ(!v3Global.rootp()->modulesp(), v3Global.rootp(), "Unlink didn't work"); for (AstNodeModule* nodep : mods) v3Global.rootp()->addModulesp(nodep); UINFO(9, "modSortByLevel() done\n"); // Comment required for gcc4.6.3 / bug666 - V3Global::dumpCheckGlobalTree("cells", false, dumpTreeEitherLevel() >= 3); + V3Global::dumpCheckGlobalTree("cellsort", false, dumpTreeEitherLevel() >= 3); } void V3LinkLevel::timescaling(const ModVec& mods) { diff --git a/src/V3LinkLevel.h b/src/V3LinkLevel.h index dd98ffa2b..b929eb6a9 100644 --- a/src/V3LinkLevel.h +++ b/src/V3LinkLevel.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 faa31fe0c..ebd9c98f1 100644 --- a/src/V3LinkParse.cpp +++ b/src/V3LinkParse.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -62,6 +62,7 @@ class LinkParseVisitor final : public VNVisitor { int m_beginDepth = 0; // How many begin blocks above current node within current AstNodeModule VLifetime m_lifetime = VLifetime::STATIC; // Propagating lifetime bool m_insideLoop = false; // True if the node is inside a loop + bool m_lifetimeAllowed = false; // True to allow lifetime settings VDouble0 m_statModules; // Number of modules seen // METHODS @@ -101,11 +102,9 @@ class LinkParseVisitor final : public VNVisitor { void visitIterateNodeDType(AstNodeDType* nodep) { if (!nodep->user1SetOnce()) { // Process only once. cleanFileline(nodep); - { - VL_RESTORER(m_dtypep); - m_dtypep = nodep; - iterateChildren(nodep); - } + VL_RESTORER(m_dtypep); + m_dtypep = nodep; + iterateChildren(nodep); } } @@ -186,58 +185,56 @@ class LinkParseVisitor final : public VNVisitor { cleanFileline(nodep); VL_RESTORER(m_ftaskp); VL_RESTORER(m_lifetime); - { - m_ftaskp = nodep; - if (!nodep->lifetime().isNone()) { - m_lifetime = nodep->lifetime(); - } else { - if (nodep->classMethod()) { - // Class methods are automatic by default - m_lifetime = VLifetime::AUTOMATIC; - } else if (nodep->dpiImport() || VN_IS(nodep, Property)) { - // DPI-imported functions and properties don't have lifetime specifiers - m_lifetime = VLifetime::NONE; - } - for (AstNode* itemp = nodep->stmtsp(); itemp; itemp = itemp->nextp()) { - AstVar* const varp = VN_CAST(itemp, Var); - if (varp && varp->valuep() && varp->lifetime().isNone() - && m_lifetime.isStatic() && !varp->isIO()) { - if (VN_IS(m_modp, Module)) { - nodep->v3warn(IMPLICITSTATIC, - "Function/task's lifetime implicitly set to static\n" - << nodep->warnMore() - << "... Suggest use 'function automatic' or " - "'function static'\n" - << nodep->warnContextPrimary() << '\n' - << varp->warnOther() - << "... Location of implicit static variable\n" - << varp->warnContextSecondary() << '\n' - << "... Suggest use 'function automatic' or " - "'function static'"); - } else { - varp->v3warn(IMPLICITSTATIC, - "Variable's lifetime implicitly set to static\n" - << nodep->warnMore() - << "... Suggest use 'static' before " - "variable declaration'"); - } + m_ftaskp = nodep; + VL_RESTORER(m_lifetimeAllowed); + m_lifetimeAllowed = true; + if (!nodep->lifetime().isNone()) { + m_lifetime = nodep->lifetime(); + } else { + if (nodep->classMethod()) { + // Class methods are automatic by default + m_lifetime = VLifetime::AUTOMATIC; + } else if (nodep->dpiImport() || VN_IS(nodep, Property)) { + // DPI-imported functions and properties don't have lifetime specifiers + m_lifetime = VLifetime::NONE; + } + for (AstNode* itemp = nodep->stmtsp(); itemp; itemp = itemp->nextp()) { + AstVar* const varp = VN_CAST(itemp, Var); + if (varp && varp->valuep() && varp->lifetime().isNone() + && m_lifetime.isStatic() && !varp->isIO()) { + if (VN_IS(m_modp, Module)) { + nodep->v3warn(IMPLICITSTATIC, + "Function/task's lifetime implicitly set to static\n" + << nodep->warnMore() + << "... Suggest use 'function automatic' or " + "'function static'\n" + << nodep->warnContextPrimary() << '\n' + << varp->warnOther() + << "... Location of implicit static variable\n" + << varp->warnContextSecondary() << '\n' + << "... Suggest use 'function automatic' or " + "'function static'"); + } else { + varp->v3warn(IMPLICITSTATIC, + "Variable's lifetime implicitly set to static\n" + << nodep->warnMore() + << "... Suggest use 'static' before " + "variable declaration'"); } } - nodep->lifetime(m_lifetime); } - iterateChildren(nodep); + nodep->lifetime(m_lifetime); } + iterateChildren(nodep); } } void visit(AstNodeFTaskRef* nodep) override { if (!nodep->user1SetOnce()) { // Process only once. cleanFileline(nodep); UINFO(5, " " << nodep << endl); - { - VL_RESTORER(m_valueModp); - m_valueModp = nullptr; - iterateChildren(nodep); - } + VL_RESTORER(m_valueModp); + m_valueModp = nullptr; + iterateChildren(nodep); } } void visit(AstNodeDType* nodep) override { visitIterateNodeDType(nodep); } @@ -295,10 +292,19 @@ class LinkParseVisitor final : public VNVisitor { nodep->v3warn(STATICVAR, "Static variable with assignment declaration declared in a " "loop converted to automatic"); } - if (nodep->varType() != VVarType::PORT) { - if (nodep->lifetime().isNone()) nodep->lifetime(m_lifetime); + if (!nodep->direction().isAny()) { // Not a port + if (nodep->lifetime().isNone()) { + if (m_lifetimeAllowed) { + nodep->lifetime(m_lifetime); + } else { // Module's always static per IEEE 1800-2023 6.21 + nodep->lifetime(VLifetime::STATIC); + } + } } else if (m_ftaskp) { nodep->lifetime(VLifetime::AUTOMATIC); + } else if (nodep->lifetime() + .isNone()) { // lifetime shouldn't be unknown, set static if none + nodep->lifetime(VLifetime::STATIC); } if (nodep->isGParam() && !nodep->isAnsi()) { // shadow some parameters into localparams @@ -577,19 +583,15 @@ class LinkParseVisitor final : public VNVisitor { void visit(AstRepeat* nodep) override { cleanFileline(nodep); VL_RESTORER(m_insideLoop); - { - m_insideLoop = true; - checkIndent(nodep, nodep->stmtsp()); - iterateChildren(nodep); - } + m_insideLoop = true; + checkIndent(nodep, nodep->stmtsp()); + iterateChildren(nodep); } void visit(AstDoWhile* nodep) override { cleanFileline(nodep); VL_RESTORER(m_insideLoop); - { - m_insideLoop = true; - iterateChildren(nodep); - } + m_insideLoop = true; + iterateChildren(nodep); } void visit(AstWait* nodep) override { cleanFileline(nodep); @@ -605,11 +607,9 @@ class LinkParseVisitor final : public VNVisitor { void visit(AstWhile* nodep) override { cleanFileline(nodep); VL_RESTORER(m_insideLoop); - { - m_insideLoop = true; - checkIndent(nodep, nodep->stmtsp()); - iterateChildren(nodep); - } + m_insideLoop = true; + checkIndent(nodep, nodep->stmtsp()); + iterateChildren(nodep); } void visit(AstNodeModule* nodep) override { V3Config::applyModule(nodep); @@ -621,6 +621,7 @@ class LinkParseVisitor final : public VNVisitor { VL_RESTORER(m_genblkNum); VL_RESTORER(m_beginDepth); VL_RESTORER(m_lifetime); + VL_RESTORER(m_lifetimeAllowed); { // Module: Create sim table for entire module and iterate cleanFileline(nodep); @@ -633,6 +634,7 @@ class LinkParseVisitor final : public VNVisitor { m_beginDepth = 0; m_valueModp = nodep; m_lifetime = nodep->lifetime(); + m_lifetimeAllowed = VN_IS(nodep, Class); if (m_lifetime.isNone()) { m_lifetime = VN_IS(nodep, Class) ? VLifetime::AUTOMATIC : VLifetime::STATIC; } @@ -648,16 +650,20 @@ class LinkParseVisitor final : public VNVisitor { void visitIterateNoValueMod(AstNode* nodep) { // Iterate a node which shouldn't have any local variables moved to an Initial cleanFileline(nodep); - { - VL_RESTORER(m_valueModp); - m_valueModp = nullptr; - iterateChildren(nodep); - } + VL_RESTORER(m_valueModp); + m_valueModp = nullptr; + iterateChildren(nodep); + } + void visit(AstNodeProcedure* nodep) override { + VL_RESTORER(m_lifetimeAllowed); + m_lifetimeAllowed = true; + visitIterateNoValueMod(nodep); } - void visit(AstNodeProcedure* nodep) override { visitIterateNoValueMod(nodep); } void visit(AstAlways* nodep) override { VL_RESTORER(m_inAlways); m_inAlways = true; + VL_RESTORER(m_lifetimeAllowed); + m_lifetimeAllowed = true; visitIterateNoValueMod(nodep); } void visit(AstCover* nodep) override { visitIterateNoValueMod(nodep); } @@ -718,13 +724,11 @@ class LinkParseVisitor final : public VNVisitor { void visit(AstGenCase* nodep) override { ++m_genblkNum; cleanFileline(nodep); - { - VL_RESTORER(m_genblkAbove); - VL_RESTORER(m_genblkNum); - m_genblkAbove = m_genblkNum; - m_genblkNum = 0; - iterateChildren(nodep); - } + VL_RESTORER(m_genblkAbove); + VL_RESTORER(m_genblkNum); + m_genblkAbove = m_genblkNum; + m_genblkNum = 0; + iterateChildren(nodep); } void visit(AstGenIf* nodep) override { cleanFileline(nodep); @@ -829,9 +833,6 @@ class LinkParseVisitor final : public VNVisitor { VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } } - void visit(AstClassOrPackageRef* nodep) override { // - iterateChildren(nodep); - } void visit(AstClocking* nodep) override { cleanFileline(nodep); VL_RESTORER(m_defaultInSkewp); diff --git a/src/V3LinkParse.h b/src/V3LinkParse.h index 12b2f2c11..3c1c72702 100644 --- a/src/V3LinkParse.h +++ b/src/V3LinkParse.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 426d7b1ca..cb268fa1e 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -47,6 +47,8 @@ class LinkResolveVisitor final : public VNVisitor { // Below state needs to be preserved between each module call. AstNodeModule* m_modp = nullptr; // Current module AstClass* m_classp = nullptr; // Class we're inside + string m_randcIllegalWhy; // Why randc illegal + AstNode* m_randcIllegalp = nullptr; // Node causing randc illegal AstNodeFTask* m_ftaskp = nullptr; // Function or task we're inside AstNodeCoverOrAssert* m_assertp = nullptr; // Current assertion int m_senitemCvtNum = 0; // Temporary signal counter @@ -63,19 +65,49 @@ class LinkResolveVisitor final : public VNVisitor { if (nodep->dead()) return; VL_RESTORER(m_modp); VL_RESTORER(m_senitemCvtNum); - { - m_modp = nodep; - m_senitemCvtNum = 0; - iterateChildren(nodep); - } + m_modp = nodep; + m_senitemCvtNum = 0; + iterateChildren(nodep); } void visit(AstClass* nodep) override { VL_RESTORER(m_classp); - { - m_classp = nodep; - iterateChildren(nodep); - } + m_classp = nodep; + iterateChildren(nodep); } + void visit(AstConstraint* nodep) override { + // V3LinkDot moved the isExternDef into the class, the extern proto was + // checked to exist, and now isn't needed + nodep->isExternDef(false); + if (nodep->isExternProto()) { + VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); + return; + } + iterateChildren(nodep); + } + void visit(AstConstraintBefore* nodep) override { + VL_RESTORER(m_randcIllegalWhy); + VL_RESTORER(m_randcIllegalp); + m_randcIllegalWhy = "'solve before' (IEEE 1800-2023 18.5.9)"; + m_randcIllegalp = nodep; + iterateChildrenConst(nodep); + } + void visit(AstDist* nodep) override { + VL_RESTORER(m_randcIllegalWhy); + VL_RESTORER(m_randcIllegalp); + m_randcIllegalWhy = "'constraint dist' (IEEE 1800-2023 18.5.3)"; + m_randcIllegalp = nodep; + iterateChildrenConst(nodep); + } + void visit(AstConstraintExpr* nodep) override { + VL_RESTORER(m_randcIllegalWhy); + VL_RESTORER(m_randcIllegalp); + if (nodep->isSoft()) { + m_randcIllegalWhy = "'constraint soft' (IEEE 1800-2023 18.5.13.1)"; + m_randcIllegalp = nodep; + } + iterateChildrenConst(nodep); + } + void visit(AstInitialAutomatic* nodep) override { iterateChildren(nodep); // Initial assignments under function/tasks can just be simple @@ -104,13 +136,24 @@ class LinkResolveVisitor final : public VNVisitor { } void visit(AstNodeVarRef* nodep) override { - // VarRef: Resolve its reference - if (nodep->varp()) nodep->varp()->usedParam(true); - // TODO should look for where genvar is valid, but for now catch - // just gross errors of using genvar outside any generate - if (nodep->varp() && nodep->varp()->isGenVar() && !m_underGenFor) { - nodep->v3error("Genvar " << nodep->prettyNameQ() - << " used outside generate for loop (IEEE 1800-2023 27.4)"); + if (nodep->varp()) { // Else due to dead code, might not have var pointer + // VarRef: Resolve its reference + nodep->varp()->usedParam(true); + // TODO should look for where genvar is valid, but for now catch + // just gross errors of using genvar outside any generate + if (nodep->varp()->isGenVar() && !m_underGenFor) { + nodep->v3error("Genvar " + << nodep->prettyNameQ() + << " used outside generate for loop (IEEE 1800-2023 27.4)"); + } + if (nodep->varp()->isRandC() && m_randcIllegalp) { + nodep->v3error("Randc variables not allowed in " + << m_randcIllegalWhy << '\n' + << nodep->warnContextPrimary() << '\n' + << m_randcIllegalp->warnOther() + << "... Location of restricting expression\n" + << m_randcIllegalp->warnContextSecondary()); + } } iterateChildren(nodep); } diff --git a/src/V3LinkResolve.h b/src/V3LinkResolve.h index c84219fb7..cfb849067 100644 --- a/src/V3LinkResolve.h +++ b/src/V3LinkResolve.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 c35ec4b2d..89d6d36b3 100644 --- a/src/V3List.h +++ b/src/V3List.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -89,7 +89,7 @@ class V3List final { // Iterator class template for V3List. This is just enough to support range based for loops // and basic usage. Feel free to extend as required. - template + template class SimpleItertatorImpl final { static_assert(std::is_same::value || std::is_same::value, @@ -99,7 +99,7 @@ class V3List final { template & (B::*)(), typename> friend class V3List; - using IteratorType = SimpleItertatorImpl; + using IteratorType = SimpleItertatorImpl; T_Base* m_currp; // Currently iterated element, or 'nullptr' for 'end()' iterator @@ -109,7 +109,7 @@ class V3List final { VL_ATTR_ALWINLINE static T_Base* step(T_Base* currp) { - if VL_CONSTEXPR_CXX17 (T_Reverse) { + if VL_CONSTEXPR_CXX17 (N_Reverse) { return toLinks(currp).m_prevp; } else { return toLinks(currp).m_nextp; @@ -145,8 +145,8 @@ class V3List final { bool operator!=(const IteratorType& other) const { return m_currp != other.m_currp; } // Convert to const iterator VL_ATTR_ALWINLINE - operator SimpleItertatorImpl() const { - return SimpleItertatorImpl{m_currp}; + operator SimpleItertatorImpl() const { + return SimpleItertatorImpl{m_currp}; } }; @@ -221,10 +221,10 @@ class V3List final { }; public: - using iterator = SimpleItertatorImpl; - using const_iterator = SimpleItertatorImpl; - using reverse_iterator = SimpleItertatorImpl; - using const_reverse_iterator = SimpleItertatorImpl; + using iterator = SimpleItertatorImpl; + using const_iterator = SimpleItertatorImpl; + using reverse_iterator = SimpleItertatorImpl; + using const_reverse_iterator = SimpleItertatorImpl; // CONSTRUCTOR V3List() = default; diff --git a/src/V3Localize.cpp b/src/V3Localize.cpp index 64692fbd4..5a1014a62 100644 --- a/src/V3Localize.cpp +++ b/src/V3Localize.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.h b/src/V3Localize.h index 456b90706..12facd1c6 100644 --- a/src/V3Localize.h +++ b/src/V3Localize.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3MemberMap.h b/src/V3MemberMap.h index 9b9035133..5053c6e35 100644 --- a/src/V3MemberMap.h +++ b/src/V3MemberMap.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 6bd1ea098..538bbbb28 100644 --- a/src/V3MergeCond.cpp +++ b/src/V3MergeCond.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.h b/src/V3MergeCond.h index 1b78dab0f..9607f398a 100644 --- a/src/V3MergeCond.h +++ b/src/V3MergeCond.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3Mutex.h b/src/V3Mutex.h index 77496d752..892a596c3 100644 --- a/src/V3Mutex.h +++ b/src/V3Mutex.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2005-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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 91c67b98b..bce4a577c 100644 --- a/src/V3Name.cpp +++ b/src/V3Name.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 514e6e12f..81d2d6ffe 100644 --- a/src/V3Name.h +++ b/src/V3Name.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 c446947aa..cb5fc9bd4 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -198,7 +198,12 @@ void V3Number::create(const char* sourcep) { } // Otherwise... else if (!sized()) { - width(v3Global.opt.maxNumWidth(), false); // Will change width below + // We don't use v3Global.opt.maxNumWidth() here, as it can be arbitrarily large, + // and cause extremely slow parsing. We will resize the value at the end anyway. + // We just need a width big enough to fit the constant, so we use a conservative + // upper bound to start from. Should never need more than 4 bits per digit. + const int widthBound = std::max(32, std::strlen(value_startp) * 4); + width(widthBound, false); // Will change width below if (unbased) isSigned(true); // Also says the spec. } diff --git a/src/V3Number.h b/src/V3Number.h index 19b449ca3..a18c59f81 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 c71a4590e..701c0219e 100644 --- a/src/V3OptionParser.cpp +++ b/src/V3OptionParser.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -37,14 +37,14 @@ struct V3OptionParser::Impl final { VALUE // "-opt val" }; // Base class of actual action classes - template + template class ActionBase VL_NOT_FINAL : public ActionIfs { bool m_undocumented = false; // This option is not documented public: - bool isValueNeeded() const override final { return MODE == en::VALUE; } - bool isFOnOffAllowed() const override final { return MODE == en::FONOFF; } - bool isOnOffAllowed() const override final { return MODE == en::ONOFF; } - bool isPartialMatchAllowed() const override final { return ALLOW_PARTIAL_MATCH; } + bool isValueNeeded() const override final { return N_Mode == en::VALUE; } + bool isFOnOffAllowed() const override final { return N_Mode == en::FONOFF; } + bool isOnOffAllowed() const override final { return N_Mode == en::ONOFF; } + bool isPartialMatchAllowed() const override final { return N_Allow_Partial_Match; } bool isUndocumented() const override { return m_undocumented; } void undocumented() override { m_undocumented = true; } }; @@ -52,14 +52,14 @@ struct V3OptionParser::Impl final { // Actual action classes template class ActionSet; // "-opt" for bool-ish, "-opt val" for int and string - template + template class ActionFOnOff; // "-fopt" and "-fno-opt" for bool-ish - template + template class ActionOnOff; // "-opt" and "-no-opt" for bool-ish class ActionCbCall; // Callback without argument for "-opt" class ActionCbFOnOff; // Callback for "-fopt" and "-fno-opt" class ActionCbOnOff; // Callback for "-opt" and "-no-opt" - template + template class ActionCbVal; // Callback for "-opt val" class ActionCbPartialMatch; // Callback "-O3" for "-O" class ActionCbPartialMatchVal; // Callback "-debugi-V3Options 3" for "-debugi-" @@ -171,10 +171,10 @@ V3OptionParser::ActionIfs* V3OptionParser::find(const char* optp) { return nullptr; } -template -V3OptionParser::ActionIfs& V3OptionParser::add(const std::string& opt, ARG arg) { +template +V3OptionParser::ActionIfs& V3OptionParser::add(const std::string& opt, T_Arg arg) { UASSERT(!m_pimpl->m_isFinalized, "Cannot add after finalize() is called"); - std::unique_ptr act{new ACT{std::move(arg)}}; + std::unique_ptr act{new T_Act{std::move(arg)}}; UASSERT(opt.size() >= 2, opt << " is too short"); UASSERT(opt[0] == '-' || opt[0] == '+', opt << " does not start with either '-' or '+'"); UASSERT(!(opt[0] == '-' && opt[1] == '-'), "Option must have single '-', but " << opt); diff --git a/src/V3OptionParser.h b/src/V3OptionParser.h index 9b35b9e48..b7bcc60b9 100644 --- a/src/V3OptionParser.h +++ b/src/V3OptionParser.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,8 +65,8 @@ private: // METHODS ActionIfs* find(const char* optp) VL_MT_DISABLED; - template - ActionIfs& add(const string& opt, ARG arg) VL_MT_DISABLED; + template + ActionIfs& add(const string& opt, T_Arg arg) VL_MT_DISABLED; // Returns true if strp starts with "-fno" static bool hasPrefixFNo(const char* strp) VL_MT_DISABLED; // Returns true if strp starts with "-no" diff --git a/src/V3Options.cpp b/src/V3Options.cpp index dee87bee0..7a7714b1e 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -412,30 +412,29 @@ string V3Options::allArgsString() const VL_MT_SAFE { } // Delete some options for Verilation of the hierarchical blocks. -string V3Options::allArgsStringForHierBlock(bool forTop, bool forCMake) const { +string V3Options::allArgsStringForHierBlock(bool forTop) const { std::set vFiles; for (const auto& vFile : m_vFiles) vFiles.insert(vFile); string out; bool stripArg = false; bool stripArgIfNum = false; - for (std::list::const_iterator it = m_impp->m_lineArgs.begin(); - it != m_impp->m_lineArgs.end(); ++it) { + for (const string& arg : m_impp->m_lineArgs) { if (stripArg) { stripArg = false; continue; } if (stripArgIfNum) { stripArgIfNum = false; - if (isdigit((*it)[0])) continue; + if (isdigit(arg[0])) continue; } int skip = 0; - if (it->length() >= 2 && (*it)[0] == '-' && (*it)[1] == '-') { + if (arg.length() >= 2 && arg[0] == '-' && arg[1] == '-') { skip = 2; - } else if (it->length() >= 1 && (*it)[0] == '-') { + } else if (arg.length() >= 1 && arg[0] == '-') { skip = 1; } - if (skip > 0) { // *it is an option - const string opt = it->substr(skip); // Remove '-' in the beginning + if (skip > 0) { // arg is an option + const string opt = arg.substr(skip); // Remove '-' in the beginning const int numStrip = stripOptionsForChildRun(opt, forTop); if (numStrip) { UASSERT(0 <= numStrip && numStrip <= 3, "should be one of 0, 1, 2, 3"); @@ -444,15 +443,15 @@ string V3Options::allArgsStringForHierBlock(bool forTop, bool forCMake) const { continue; } } else { // Not an option - if ((forCMake && vFiles.find(*it) != vFiles.end()) // Remove HDL - || m_cppFiles.find(*it) != m_cppFiles.end()) { // Remove C++ + if (vFiles.find(arg) != vFiles.end() // Remove HDL + || m_cppFiles.find(arg) != m_cppFiles.end()) { // Remove C++ continue; } } if (out != "") out += " "; - // Don't use opt here because '-' is removed in it - // Use double quote because *it may contain whitespaces - out += '"' + VString::quoteAny(*it, '"', '\\') + '"'; + // Don't use opt here because '-' is removed in arg + // Use double quote because arg may contain whitespaces + out += '"' + VString::quoteAny(arg, '"', '\\') + '"'; } return out; } @@ -550,9 +549,10 @@ string V3Options::filePathCheckOneDir(const string& modname, const string& dirna // 3: Delete the option and its argument if it is a number int V3Options::stripOptionsForChildRun(const string& opt, bool forTop) { if (opt == "j") return 3; - if (opt == "Mdir" || opt == "clk" || opt == "lib-create" || opt == "f" || opt == "v" - || opt == "l2-name" || opt == "mod-prefix" || opt == "prefix" || opt == "protect-lib" - || opt == "protect-key" || opt == "threads" || opt == "top-module") { + if (opt == "Mdir" || opt == "clk" || opt == "lib-create" || opt == "f" || opt == "F" + || opt == "v" || opt == "l2-name" || opt == "mod-prefix" || opt == "prefix" + || opt == "protect-lib" || opt == "protect-key" || opt == "threads" + || opt == "top-module") { return 2; } if (opt == "build" || (!forTop && (opt == "cc" || opt == "exe" || opt == "sc")) @@ -562,6 +562,12 @@ int V3Options::stripOptionsForChildRun(const string& opt, bool forTop) { return 0; } +void V3Options::validateIdentifier(FileLine* fl, const string& arg, const string& opt) { + if (!VString::isIdentifier(arg)) { + fl->v3error(opt << " argument must be a legal C++ identifier: '" << arg << "'"); + } +} + string V3Options::filePath(FileLine* fl, const string& modname, const string& lastpath, const string& errmsg) { // Error prefix or "" to suppress error // Find a filename to read the specified module name, @@ -569,7 +575,7 @@ string V3Options::filePath(FileLine* fl, const string& modname, const string& la // Return "" if not found. const string filename = V3Os::filenameCleanup(VName::dehash(modname)); if (!V3Os::filenameIsRel(filename)) { - // filename is an absolute path, so can find getStdPackagePath() + // filename is an absolute path, so can find getStdPackagePath()/getStdWaiverPath() string exists = filePathCheckOneDir(filename, ""); if (exists != "") return exists; } @@ -632,7 +638,7 @@ void V3Options::filePathLookedMsg(FileLine* fl, const string& modname) { V3LangCode V3Options::fileLanguage(const string& filename) { string ext = V3Os::filenameNonDir(filename); string::size_type pos; - if (filename == V3Options::getStdPackagePath()) { + if (filename == V3Options::getStdPackagePath() || filename == V3Options::getStdWaiverPath()) { return V3LangCode::mostRecent(); } else if ((pos = ext.rfind('.')) != string::npos) { ext.erase(0, pos + 1); @@ -794,6 +800,9 @@ string V3Options::getenvVERILATOR_SOLVER() { string V3Options::getStdPackagePath() { return V3Os::filenameJoin(getenvVERILATOR_ROOT(), "include", "verilated_std.sv"); } +string V3Options::getStdWaiverPath() { + return V3Os::filenameJoin(getenvVERILATOR_ROOT(), "include", "verilated_std_waiver.vlt"); +} string V3Options::getSupported(const string& var) { // If update below, also update V3Options::showVersion() @@ -940,6 +949,9 @@ void V3Options::notify() VL_MT_DISABLED { if (coverage() && savable()) { cmdfl->v3error("Unsupported: --coverage and --savable not supported together"); } + if (v3Global.opt.timing().isSetTrue() && savable()) { + cmdfl->v3error("Unsupported: --timing and --savable not supported together"); + } // Mark options as available m_available = true; @@ -1259,7 +1271,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, DECL_OPTION("-json-edit-nums", OnOff, &m_jsonEditNums); DECL_OPTION("-json-ids", OnOff, &m_jsonIds); DECL_OPTION("-E", CbOnOff, [this](bool flag) { - if (flag) m_std = false; + if (flag) { + m_stdPackage = false; + m_stdWaiver = false; + } m_preprocOnly = flag; }); DECL_OPTION("-emit-accessors", OnOff, &m_emitAccessors); @@ -1304,8 +1319,15 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, DECL_OPTION("-fdead-assigns", FOnOff, &m_fDeadAssigns); DECL_OPTION("-fdead-cells", FOnOff, &m_fDeadCells); DECL_OPTION("-fexpand", FOnOff, &m_fExpand); + DECL_OPTION("-ffunc-opt", CbFOnOff, [this](bool flag) { // + m_fFuncSplitCat = flag; + m_fFuncBalanceCat = flag; + }); + DECL_OPTION("-ffunc-opt-balance-cat", FOnOff, &m_fFuncBalanceCat); + DECL_OPTION("-ffunc-opt-split-cat", FOnOff, &m_fFuncSplitCat); DECL_OPTION("-fgate", FOnOff, &m_fGate); DECL_OPTION("-finline", FOnOff, &m_fInline); + DECL_OPTION("-finline-funcs", FOnOff, &m_fInlineFuncs); DECL_OPTION("-flife", FOnOff, &m_fLife); DECL_OPTION("-flife-post", FOnOff, &m_fLifePost); DECL_OPTION("-flocalize", FOnOff, &m_fLocalize); @@ -1314,6 +1336,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, DECL_OPTION("-fmerge-const-pool", FOnOff, &m_fMergeConstPool); DECL_OPTION("-freloop", FOnOff, &m_fReloop); DECL_OPTION("-freorder", FOnOff, &m_fReorder); + DECL_OPTION("-fslice", FOnOff, &m_fSlice); DECL_OPTION("-fsplit", FOnOff, &m_fSplit); DECL_OPTION("-fsubst", FOnOff, &m_fSubst); DECL_OPTION("-fsubst-const", FOnOff, &m_fSubstConst); @@ -1374,7 +1397,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, }; DECL_OPTION("-default-language", CbVal, setLang); DECL_OPTION("-language", CbVal, setLang); - DECL_OPTION("-lib-create", Set, &m_libCreate); + DECL_OPTION("-lib-create", CbVal, [this, fl](const char* valp) { + validateIdentifier(fl, valp, "--lib-create"); + m_libCreate = valp; + }); DECL_OPTION("-lint-only", OnOff, &m_lintOnly); DECL_OPTION("-localize-max-size", Set, &m_localizeMaxSize); DECL_OPTION("-main-top-name", Set, &m_mainTopName); @@ -1397,7 +1423,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, } }); DECL_OPTION("-max-num-width", Set, &m_maxNumWidth); - DECL_OPTION("-mod-prefix", Set, &m_modPrefix); + DECL_OPTION("-mod-prefix", CbVal, [this, fl](const char* valp) { + validateIdentifier(fl, valp, "--mod-prefix"); + m_modPrefix = valp; + }); DECL_OPTION("-O0", CbCall, [this]() { optimize(0); }); DECL_OPTION("-O1", CbCall, [this]() { optimize(1); }); @@ -1448,7 +1477,10 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, DECL_OPTION("-pins-uint8", OnOff, &m_pinsUint8); DECL_OPTION("-pipe-filter", Set, &m_pipeFilter); DECL_OPTION("-pp-comments", OnOff, &m_ppComments); - DECL_OPTION("-prefix", Set, &m_prefix); + DECL_OPTION("-prefix", CbVal, [this, fl](const char* valp) { + validateIdentifier(fl, valp, "--prefix"); + m_prefix = valp; + }); DECL_OPTION("-private", CbCall, [this]() { m_public = false; }); DECL_OPTION("-prof-c", OnOff, &m_profC); DECL_OPTION("-prof-cfuncs", CbCall, [this]() { m_profC = m_profCFuncs = true; }); @@ -1458,7 +1490,8 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, DECL_OPTION("-prof-pgo", OnOff, &m_profPgo); DECL_OPTION("-protect-ids", OnOff, &m_protectIds); DECL_OPTION("-protect-key", Set, &m_protectKey); - DECL_OPTION("-protect-lib", CbVal, [this](const char* valp) { + DECL_OPTION("-protect-lib", CbVal, [this, fl](const char* valp) { + validateIdentifier(fl, valp, "--protect-lib"); m_libCreate = valp; m_protectIds = true; }); @@ -1507,7 +1540,12 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, m_statsVars = flag; m_stats |= flag; }); - DECL_OPTION("-std", OnOff, &m_std); + DECL_OPTION("-std", CbOnOff, [this](bool flag) { + m_stdPackage = flag; + m_stdWaiver = flag; + }); + DECL_OPTION("-std-package", OnOff, &m_stdPackage); + DECL_OPTION("-std-waiver", OnOff, &m_stdWaiver); DECL_OPTION("-stop-fail", OnOff, &m_stopFail); DECL_OPTION("-structs-packed", OnOff, &m_structsPacked); DECL_OPTION("-sv", CbCall, [this]() { m_defaultLanguage = V3LangCode::L1800_2023; }); @@ -1701,6 +1739,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, FileLine::globalWarnOff(V3ErrorCode::WIDTH, false); V3Error::pretendError(V3ErrorCode::WIDTH, false); }); + DECL_OPTION("-waiver-multiline", OnOff, &m_waiverMultiline); DECL_OPTION("-waiver-output", Set, &m_waiverOutput); DECL_OPTION("-x-assign", CbVal, [this, fl](const char* valp) { @@ -1963,7 +2002,7 @@ void V3Options::showVersion(bool verbose) { if (!verbose) return; cout << "\n"; - cout << "Copyright 2003-2024 by Wilson Snyder. Verilator is free software; you can\n"; + cout << "Copyright 2003-2025 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 2ac99bf04..eb3d14194 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -279,7 +279,8 @@ 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_std = true; // main switch: --std + bool m_stdPackage = true; // main switch: --std-package + bool m_stdWaiver = true; // main switch: --std-waiver 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 @@ -297,6 +298,7 @@ private: bool m_underlineZero = false; // main switch: --underline-zero; undocumented old Verilator 2 bool m_verilate = true; // main switch: --verilate bool m_vpi = false; // main switch: --vpi + bool m_waiverMultiline = false; // main switch: --waiver-multiline bool m_xInitialEdge = false; // main switch: --x-initial-edge bool m_xmlOnly = false; // main switch: --xml-only bool m_jsonOnly = false; // main switch: --json-only @@ -384,8 +386,11 @@ private: bool m_fDeadAssigns; // main switch: -fno-dead-assigns: remove dead assigns bool m_fDeadCells; // main switch: -fno-dead-cells: remove dead cells bool m_fExpand; // main switch: -fno-expand: expansion of C macros + bool m_fFuncBalanceCat = true; // main switch: -fno-func-balance-cat: expansion of C macros + bool m_fFuncSplitCat = true; // main switch: -fno-func-split-cat: expansion of C macros bool m_fGate; // main switch: -fno-gate: gate wire elimination bool m_fInline; // main switch: -fno-inline: module inlining + bool m_fInlineFuncs = true; // main switch: -fno-inline-funcs: function inlining bool m_fLife; // main switch: -fno-life: variable lifetime bool m_fLifePost; // main switch: -fno-life-post: delayed assignment elimination bool m_fLocalize; // main switch: -fno-localize: convert temps to local variables @@ -394,6 +399,7 @@ private: bool m_fMergeConstPool = true; // main switch: -fno-merge-const-pool bool m_fReloop; // main switch: -fno-reloop: reform loops bool m_fReorder; // main switch: -fno-reorder: reorder assignments in blocks + bool m_fSlice = true; // main switch: -fno-slice: array assignment slicing bool m_fSplit; // main switch: -fno-split: always assignment splitting bool m_fSubst; // main switch: -fno-subst: substitute expression temp values bool m_fSubstConst; // main switch: -fno-subst-const: final constant substitution @@ -423,6 +429,7 @@ private: static string parseFileArg(const string& optdir, const string& relfilename); string filePathCheckOneDir(const string& modname, const string& dirname); static int stripOptionsForChildRun(const string& opt, bool forTop); + void validateIdentifier(FileLine* fl, const string& arg, const string& opt); // CONSTRUCTORS VL_UNCOPYABLE(V3Options); @@ -463,7 +470,8 @@ public: bool savable() const VL_MT_SAFE { return m_savable; } bool stats() const { return m_stats; } bool statsVars() const { return m_statsVars; } - bool std() const { return m_std; } + bool stdPackage() const { return m_stdPackage; } + bool stdWaiver() const { return m_stdWaiver; } bool structsPacked() const { return m_structsPacked; } bool assertOn() const { return m_assert; } // assertOn as __FILE__ may be defined bool assertCaseOn() const { return m_assertCase || m_assert; } @@ -542,6 +550,7 @@ public: bool reportUnoptflat() const { return m_reportUnoptflat; } bool verilate() const { return m_verilate; } bool vpi() const { return m_vpi; } + bool waiverMultiline() const { return m_waiverMultiline; } bool xInitialEdge() const { return m_xInitialEdge; } bool xmlOnly() const { return m_xmlOnly; } bool jsonOnly() const { return m_jsonOnly; } @@ -674,8 +683,12 @@ public: bool fDeadAssigns() const { return m_fDeadAssigns; } bool fDeadCells() const { return m_fDeadCells; } bool fExpand() const { return m_fExpand; } + bool fFuncBalanceCat() const { return m_fFuncBalanceCat; } + bool fFuncSplitCat() const { return m_fFuncSplitCat; } + bool fFunc() const { return fFuncSplitCat() || fFuncBalanceCat(); } bool fGate() const { return m_fGate; } bool fInline() const { return m_fInline; } + bool fInlineFuncs() const { return m_fInlineFuncs; } bool fLife() const { return m_fLife; } bool fLifePost() const { return m_fLifePost; } bool fLocalize() const { return m_fLocalize; } @@ -684,6 +697,7 @@ public: bool fMergeConstPool() const { return m_fMergeConstPool; } bool fReloop() const { return m_fReloop; } bool fReorder() const { return m_fReorder; } + bool fSlice() const { return m_fSlice; } bool fSplit() const { return m_fSplit; } bool fSubst() const { return m_fSubst; } bool fSubstConst() const { return m_fSubstConst; } @@ -713,7 +727,7 @@ public: string allArgsString() const VL_MT_SAFE; ///< Return all passed arguments as simple string // Return options for child hierarchical blocks when forTop==false, otherwise returns args for // the top module. - string allArgsStringForHierBlock(bool forTop, bool forCMake) const; + string allArgsStringForHierBlock(bool forTop) const; void parseOpts(FileLine* fl, int argc, char** argv) VL_MT_DISABLED; void parseOptsList(FileLine* fl, const string& optdir, int argc, char** argv) VL_MT_DISABLED; void parseOptsFile(FileLine* fl, const string& filename, bool rel) VL_MT_DISABLED; @@ -734,6 +748,7 @@ public: static string getenvVERILATOR_ROOT(); static string getenvVERILATOR_SOLVER(); static string getStdPackagePath(); + static string getStdWaiverPath(); static string getSupported(const string& var); static bool systemCSystemWide(); static bool systemCFound(); // SystemC installed, or environment points to it diff --git a/src/V3Order.cpp b/src/V3Order.cpp index 431a5f956..fcc1e859a 100644 --- a/src/V3Order.cpp +++ b/src/V3Order.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -123,8 +123,10 @@ AstCFunc* V3Order::order(AstNetlist* netlistp, // }(); if (v3Global.opt.profExec()) { - funcp->addStmtsp(new AstCStmt{flp, "VL_EXEC_TRACE_ADD_RECORD(vlSymsp).sectionPush(\"func " - + tag + "\");\n"}); + const string name + = (v3Global.opt.hierChild() ? (v3Global.opt.topModule() + " ") : "") + "func " + tag; + funcp->addStmtsp(new AstCStmt{flp, "VL_EXEC_TRACE_ADD_RECORD(vlSymsp).sectionPush(\"" + + name + "\");\n"}); } // Build the OrderGraph diff --git a/src/V3Order.h b/src/V3Order.h index cf4c117e2..d3b27a7d4 100644 --- a/src/V3Order.h +++ b/src/V3Order.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3OrderCFuncEmitter.h b/src/V3OrderCFuncEmitter.h index 37cda41f3..03752a509 100644 --- a/src/V3OrderCFuncEmitter.h +++ b/src/V3OrderCFuncEmitter.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 7b08f4c62..697aa2fe3 100644 --- a/src/V3OrderGraph.h +++ b/src/V3OrderGraph.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3OrderGraphBuilder.cpp b/src/V3OrderGraphBuilder.cpp index d885a399c..3dfe3c321 100644 --- a/src/V3OrderGraphBuilder.cpp +++ b/src/V3OrderGraphBuilder.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3OrderInternal.h b/src/V3OrderInternal.h index 10bb446f4..93c25c210 100644 --- a/src/V3OrderInternal.h +++ b/src/V3OrderInternal.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.cpp b/src/V3OrderMoveGraph.cpp index 6907e2263..af04e45f0 100644 --- a/src/V3OrderMoveGraph.cpp +++ b/src/V3OrderMoveGraph.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 6d4b346c6..bab6ac630 100644 --- a/src/V3OrderMoveGraph.h +++ b/src/V3OrderMoveGraph.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3OrderParallel.cpp b/src/V3OrderParallel.cpp index cc614b211..67fe62bd3 100644 --- a/src/V3OrderParallel.cpp +++ b/src/V3OrderParallel.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -268,7 +268,7 @@ static_assert(!std::is_polymorphic::value, "Should not have a vtable" class MTaskEdge final : public V3GraphEdge, public MergeCandidate { VL_RTTI_IMPL(MTaskEdge, V3GraphEdge) friend class LogicMTask; - template + template friend class PropagateCp; // MEMBERS @@ -280,7 +280,7 @@ public: // CONSTRUCTORS MTaskEdge(V3Graph* graphp, LogicMTask* fromp, LogicMTask* top, int weight); // METHODS - template + template inline LogicMTask* furtherMTaskp() const; inline LogicMTask* fromMTaskp() const; inline LogicMTask* toMTaskp() const; @@ -307,7 +307,7 @@ private: class LogicMTask final : public V3GraphVertex { VL_RTTI_IMPL(LogicMTask, V3GraphVertex) - template + template friend class PropagateCp; public: @@ -419,28 +419,28 @@ public: #endif } - template + template void addRelativeEdge(MTaskEdge* edgep) { - constexpr GraphWay way{T_Way}; + constexpr GraphWay way{N_Way}; constexpr GraphWay inv = way.invert(); // Add to the edge heap - LogicMTask* const relativep = edgep->furtherMTaskp(); + LogicMTask* const relativep = edgep->furtherMTaskp(); // Value is !way cp to this edge const uint32_t cp = relativep->stepCost() + relativep->critPathCost(inv); // m_edgeHeap[way].insert(&edgep->m_edgeHeapNode[way], {relativep->id(), cp}); } - template + template void stealRelativeEdge(MTaskEdge* edgep) { - constexpr GraphWay way{T_Way}; + constexpr GraphWay way{N_Way}; // Make heap node insertable, ruining the heap it is currently in. edgep->m_edgeHeapNode[way].yank(); // Add the edge as new - addRelativeEdge(edgep); + addRelativeEdge(edgep); } - template + template void removeRelativeEdge(MTaskEdge* edgep) { - constexpr GraphWay way{T_Way}; + constexpr GraphWay way{N_Way}; // Remove from the edge heap m_edgeHeap[way].remove(&edgep->m_edgeHeapNode[way]); } @@ -456,12 +456,12 @@ public: } bool hasRelativeMTask(LogicMTask* relativep) const { return m_edgeSet.count(relativep); } - template + template void checkRelativesCp() const { - constexpr GraphWay way{T_Way}; - for (const V3GraphEdge& edge : edges()) { + constexpr GraphWay way{N_Way}; + for (const V3GraphEdge& edge : edges()) { const LogicMTask* const relativep - = static_cast(edge.furtherp()); + = static_cast(edge.furtherp()); const uint32_t cachedCp = static_cast(edge).cachedCp(way); const uint32_t cp = relativep->critPathCost(way.invert()) + relativep->stepCost(); partCheckCachedScoreVsActual(cachedCp, cp); @@ -479,14 +479,14 @@ public: void setCritPathCost(GraphWay way, uint32_t cost) { m_critPathCost[way] = cost; } uint32_t critPathCost(GraphWay way) const { return m_critPathCost[way]; } - template + template uint32_t critPathCostWithout(const V3GraphEdge* withoutp) const { - const GraphWay way{T_Way}; + const GraphWay way{N_Way}; const GraphWay inv = way.invert(); // Compute the critical path cost wayward to this node, without considering edge // 'withoutp'. We need to look at two edges at most, the critical path if that is not via // 'withoutp', or the second-worst path, if the critical path is via 'withoutp'. - UDEBUGONLY(UASSERT(withoutp->furtherp() == this, + UDEBUGONLY(UASSERT(withoutp->furtherp() == this, "In critPathCostWithout(), edge 'withoutp' must further to 'this'");); const EdgeHeap& edgeHeap = m_edgeHeap[inv]; const EdgeHeap::Node* const maxp = edgeHeap.max(); @@ -690,9 +690,9 @@ MTaskEdge::MTaskEdge(V3Graph* graphp, LogicMTask* fromp, LogicMTask* top, int we top->addRelativeEdge(this); } -template +template LogicMTask* MTaskEdge::furtherMTaskp() const { - return static_cast(this->furtherp()); + return static_cast(this->furtherp()); } LogicMTask* MTaskEdge::fromMTaskp() const { return static_cast(fromp()); } LogicMTask* MTaskEdge::toMTaskp() const { return static_cast(top()); } @@ -716,9 +716,9 @@ void MTaskEdge::resetCriticalPaths() { // Look at vertex costs (in one way) to form critical paths for each // vertex. -template +template static void partInitHalfCriticalPaths(V3Graph& mTaskGraph, bool checkOnly) { - constexpr GraphWay way{T_Way}; + constexpr GraphWay way{N_Way}; constexpr GraphWay rev = way.invert(); GraphStreamUnordered order{&mTaskGraph, way}; for (const V3GraphVertex* vertexp; (vertexp = order.nextp());) { @@ -776,7 +776,7 @@ static void partCheckCriticalPaths(V3Graph& mTaskGraph) { // ###################################################################### // PropagateCp -template +template class PropagateCp final { // Propagate increasing critical path (CP) costs through a graph. // @@ -862,7 +862,7 @@ private: public: void cpHasIncreased(V3GraphVertex* vxp, uint32_t newInclusiveCp) { - constexpr GraphWay way{T_Way}; + constexpr GraphWay way{N_Way}; constexpr GraphWay inv{way.invert()}; // For *vxp, whose CP-inclusive has just increased to @@ -871,7 +871,7 @@ public: for (V3GraphEdge& graphEdge : vxp->edges()) { MTaskEdge& edge = static_cast(graphEdge); - LogicMTask* const relativep = edge.furtherMTaskp(); + LogicMTask* const relativep = edge.furtherMTaskp(); EdgeHeap::Node& edgeHeapNode = edge.m_edgeHeapNode[inv]; if (newInclusiveCp > edgeHeapNode.key().m_score) { relativep->m_edgeHeap[inv].increaseKey(&edgeHeapNode, newInclusiveCp); @@ -899,7 +899,7 @@ public: } void go() { - constexpr GraphWay way{T_Way}; + constexpr GraphWay way{N_Way}; constexpr GraphWay inv{way.invert()}; // m_pending maps each pending vertex to the amount that it wayward @@ -982,7 +982,7 @@ public: partInitCriticalPaths(graph); - PropagateCp prop{true}; + PropagateCp prop{true}; // Seed the propagator with every input node; // This should result in the complete graph getting all CP's assigned. @@ -1316,9 +1316,9 @@ public: } private: - template + template NewCp newCp(LogicMTask* mtaskp, LogicMTask* otherp, MTaskEdge* mergeEdgep) { - constexpr GraphWay way{T_Way}; + constexpr GraphWay way{N_Way}; // Return new wayward-CP for mtaskp reflecting its upcoming merge // with otherp. Set 'result.propagate' if mtaskp's wayward // relatives will see a new wayward CP from this merge. @@ -1528,9 +1528,9 @@ private: } } - template + template void siblingPairFromRelatives(V3GraphVertex* mtaskp) { - constexpr GraphWay way{T_Way}; + constexpr GraphWay way{N_Way}; // Need at least 2 edges auto& edges = mtaskp->edges(); if (!edges.hasMultipleElements()) return; @@ -1575,7 +1575,7 @@ private: // Just make a few pairs. constexpr size_t MAX_NONEXHAUSTIVE_PAIRS = 3; - if (Exhaustive || n <= 2 * MAX_NONEXHAUSTIVE_PAIRS) { + if (N_Exhaustive || n <= 2 * MAX_NONEXHAUSTIVE_PAIRS) { 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) { diff --git a/src/V3OrderProcessDomains.cpp b/src/V3OrderProcessDomains.cpp index 7a27593fb..bb028342f 100644 --- a/src/V3OrderProcessDomains.cpp +++ b/src/V3OrderProcessDomains.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3OrderSerial.cpp b/src/V3OrderSerial.cpp index 1627b78f7..a23280d8a 100644 --- a/src/V3OrderSerial.cpp +++ b/src/V3OrderSerial.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 b11f92e61..cd38daf44 100644 --- a/src/V3Os.cpp +++ b/src/V3Os.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 5974dc18b..115d01971 100644 --- a/src/V3Os.h +++ b/src/V3Os.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 32c451f9c..98b22b1e6 100644 --- a/src/V3PairingHeap.h +++ b/src/V3PairingHeap.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3Param.cpp b/src/V3Param.cpp index fe580f853..17ecb785b 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -318,7 +318,7 @@ class ParamProcessor final { static string paramValueString(const AstNode* nodep) { if (const AstRefDType* const refp = VN_CAST(nodep, RefDType)) { - nodep = refp->skipRefToEnump(); + nodep = refp->skipRefToNonRefp(); } string key = nodep->name(); if (const AstIfaceRefDType* const ifrtp = VN_CAST(nodep, IfaceRefDType)) { @@ -373,9 +373,7 @@ class ParamProcessor final { // TODO: This parameter value number lookup via a constructed key string is not // particularly robust for type parameters. We should really have a type // equivalence predicate function. - if (const AstRefDType* const refp = VN_CAST(nodep, RefDType)) { - nodep = refp->skipRefToEnump(); - } + if (AstRefDType* const refp = VN_CAST(nodep, RefDType)) nodep = refp->skipRefToNonRefp(); const string paramStr = paramValueString(nodep); // cppcheck-has-bug-suppress unreadVariable V3Hash hash = V3Hasher::uncachedHash(nodep) + paramStr; @@ -417,7 +415,7 @@ class ParamProcessor final { return nullptr; } bool isString(AstNodeDType* nodep) { - if (AstBasicDType* const basicp = VN_CAST(nodep->skipRefToEnump(), BasicDType)) + if (AstBasicDType* const basicp = VN_CAST(nodep->skipRefToNonRefp(), BasicDType)) return basicp->isString(); return false; } @@ -532,7 +530,7 @@ class ParamProcessor final { // nullptr means that the parameter is using some default value. params.emplace(varp->name(), constp); } - } else if (const AstParamTypeDType* const p = VN_CAST(stmtp, ParamTypeDType)) { + } else if (AstParamTypeDType* const p = VN_CAST(stmtp, ParamTypeDType)) { params.emplace(p->name(), p->skipRefp()); } } @@ -595,7 +593,8 @@ class ParamProcessor final { if (AstClassRefDType* const classRefp = VN_CAST(nodep, ClassRefDType)) { if (classRefp->classp() == oldClassp) classRefp->classp(newClassp); } else if (AstClassOrPackageRef* const classRefp = VN_CAST(nodep, ClassOrPackageRef)) { - if (classRefp->classOrPackagep() == oldClassp) classRefp->classOrPackagep(newClassp); + if (classRefp->classOrPackageSkipp() == oldClassp) + classRefp->classOrPackagep(newClassp); } if (nodep->op1p()) replaceRefsRecurse(nodep->op1p(), oldClassp, newClassp); @@ -769,8 +768,8 @@ class ParamProcessor final { } } else if (AstParamTypeDType* const modvarp = pinp->modPTypep()) { AstNodeDType* rawTypep = VN_CAST(pinp->exprp(), NodeDType); - AstNodeDType* const exprp = rawTypep ? rawTypep->skipRefToEnump() : nullptr; - const AstNodeDType* const origp = modvarp->skipRefToEnump(); + AstNodeDType* exprp = rawTypep ? rawTypep->skipRefToNonRefp() : nullptr; + const AstNodeDType* const origp = modvarp->skipRefToNonRefp(); if (!exprp) { pinp->v3error("Parameter type pin value isn't a type: Param " << pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); @@ -784,7 +783,9 @@ class ParamProcessor final { // This prevents making additional modules, and makes coverage more // obvious as it won't show up under a unique module page name. } else { - V3Const::constifyParamsEdit(exprp); + VL_DO_DANGLING(V3Const::constifyParamsEdit(exprp), exprp); + rawTypep = VN_CAST(pinp->exprp(), NodeDType); + exprp = rawTypep ? rawTypep->skipRefToNonRefp() : nullptr; longnamer += "_" + paramSmallName(srcModp, modvarp) + paramValueNumber(exprp); any_overridesr = true; } @@ -924,13 +925,15 @@ class ParamProcessor final { for (auto* stmtp = srcModpr->stmtsp(); stmtp; stmtp = stmtp->nextp()) { if (AstParamTypeDType* dtypep = VN_CAST(stmtp, ParamTypeDType)) { if (VN_IS(dtypep->subDTypep(), VoidDType)) { - nodep->v3error("Missing type parameter: " << dtypep->prettyNameQ()); + nodep->v3error( + "Class parameter type without default value is never given value" + << " (IEEE 1800-2023 6.20.1): " << dtypep->prettyNameQ()); VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep); } } if (AstVar* const varp = VN_CAST(stmtp, Var)) { if (VN_IS(srcModpr, Class) && varp->isParam() && !varp->valuep()) { - nodep->v3error("Class parameter without initial value is never given value" + nodep->v3error("Class parameter without default value is never given value" << " (IEEE 1800-2023 6.20.1): " << varp->prettyNameQ()); } } @@ -1082,7 +1085,7 @@ class ParamVisitor final : public VNVisitor { if (const auto* modCellp = VN_CAST(cellp, Cell)) { srcModp = modCellp->modp(); } else if (const auto* classRefp = VN_CAST(cellp, ClassOrPackageRef)) { - srcModp = classRefp->classOrPackagep(); + srcModp = classRefp->classOrPackageSkipp(); if (VN_IS(classRefp->classOrPackageNodep(), ParamTypeDType)) continue; } else if (const auto* classRefp = VN_CAST(cellp, ClassRefDType)) { srcModp = classRefp->classp(); @@ -1200,13 +1203,20 @@ class ParamVisitor final : public VNVisitor { iterateChildren(nodep); if (nodep->isParam()) { if (!nodep->valuep() && !VN_IS(m_modp, Class)) { - nodep->v3error("Parameter without initial value is never given value" + nodep->v3error("Parameter without default value is never given value" << " (IEEE 1800-2023 6.20.1): " << nodep->prettyNameQ()); } else { V3Const::constifyParamsEdit(nodep); // The variable, not just the var->init() } } } + void visit(AstParamTypeDType* nodep) override { + iterateChildren(nodep); + if (VN_IS(nodep->subDTypep(), VoidDType)) { + nodep->v3error("Parameter type without default value is never given value" + << " (IEEE 1800-2023 6.20.1): " << nodep->prettyNameQ()); + } + } // Make sure varrefs cause vars to constify before things above void visit(AstVarRef* nodep) override { // Might jump across functions, so beware if ever add a m_funcp @@ -1239,18 +1249,25 @@ class ParamVisitor final : public VNVisitor { UINFO(9, "Hit module boundary, done looking for interface" << endl); break; } - if (VN_IS(backp, Var) && VN_AS(backp, Var)->isIfaceRef() - && VN_AS(backp, Var)->childDTypep() - && (VN_CAST(VN_CAST(backp, Var)->childDTypep(), IfaceRefDType) - || (VN_CAST(VN_CAST(backp, Var)->childDTypep(), UnpackArrayDType) - && VN_CAST(VN_CAST(backp, Var)->childDTypep()->getChildDTypep(), - IfaceRefDType)))) { - const AstIfaceRefDType* ifacerefp - = VN_CAST(VN_CAST(backp, Var)->childDTypep(), IfaceRefDType); - if (!ifacerefp) { - ifacerefp = VN_CAST(VN_CAST(backp, Var)->childDTypep()->getChildDTypep(), - IfaceRefDType); + if (const AstVar* const varp = VN_CAST(backp, Var)) { + if (!varp->isIfaceRef()) { continue; } + const AstIfaceRefDType* ifacerefp = nullptr; + if (const AstNodeDType* const typep = varp->childDTypep()) { + ifacerefp = VN_CAST(typep, IfaceRefDType); + if (!ifacerefp) { + if (const AstUnpackArrayDType* const unpackp + = VN_CAST(typep, UnpackArrayDType)) { + ifacerefp = VN_CAST(typep->getChildDTypep(), IfaceRefDType); + } + } + if (!ifacerefp) { + if (const AstBracketArrayDType* const unpackp + = VN_CAST(typep, BracketArrayDType)) { + ifacerefp = VN_CAST(typep->subDTypep(), IfaceRefDType); + } + } } + if (!ifacerefp) { continue; } // Interfaces passed in on the port map have ifaces if (const AstIface* const ifacep = ifacerefp->ifacep()) { if (dotted == backp->name()) { diff --git a/src/V3Param.h b/src/V3Param.h index 0d0c832d0..f730628a7 100644 --- a/src/V3Param.h +++ b/src/V3Param.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 767467702..58f318bfa 100644 --- a/src/V3Parse.h +++ b/src/V3Parse.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 6451ba514..0d0cbd5c6 100644 --- a/src/V3ParseGrammar.cpp +++ b/src/V3ParseGrammar.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,7 +193,8 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, const string& name, AstNodeDType* dtypep = GRAMMARP->m_varDTypep; UINFO(5, " creVar " << name << " decl=" << GRAMMARP->m_varDecl << " io=" << GRAMMARP->m_varIO << " dt=" << (dtypep ? "set" : "") << endl); - if (GRAMMARP->m_varIO == VDirection::NONE && GRAMMARP->m_varDecl == VVarType::PORT) { + if (GRAMMARP->m_varIO == VDirection::NONE // In non-ANSI port list + && GRAMMARP->m_varDecl == VVarType::PORT) { // Just a port list with variable name (not v2k format); AstPort already created if (dtypep) fileline->v3warn(E_UNSUPPORTED, "Unsupported: Ranges ignored in port-lists"); if (arrayp) VL_DO_DANGLING(arrayp->deleteTree(), arrayp); @@ -222,7 +223,7 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, const string& name, // UINFO(0,"CREVAR "<ascii()<<" decl="<m_varDecl.ascii()<<" // io="<m_varIO.ascii()<m_varDecl; - if (type == VVarType::UNKNOWN) { + if (type == VVarType::UNKNOWN) { // e.g. "output" non-ANSI standalone direction (vs "reg") if (GRAMMARP->m_varIO.isAny()) { type = VVarType::PORT; } else { diff --git a/src/V3ParseImp.cpp b/src/V3ParseImp.cpp index 1a8076be4..c2cc2cf6f 100644 --- a/src/V3ParseImp.cpp +++ b/src/V3ParseImp.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,6 +70,25 @@ V3ParseImp::~V3ParseImp() { //###################################################################### // Parser utility methods +void V3ParseImp::importIfInStd(FileLine* fileline, const string& id) { + // Keywords that auto-import to require use of verilated_std.vh. + // OK if overly sensitive; will over-import and keep std:: around + // longer than migt otherwise. + if (v3Global.usesStdPackage()) return; // Run once then short-circuit + const bool identifierImportsStd = (id == "mailbox" || id == "process" || id == "randomize" + || id == "semaphore" || id == "std"); + if (!identifierImportsStd) return; + // Ignore Std:: used inside verilated_std.vh itself + if (fileline->filename() == V3Options::getStdPackagePath()) return; + if (AstPackage* const stdpkgp + = v3Global.rootp()->stdPackagep()) { // else e.g. --no-std-package + UINFO(9, "import and keep std:: for " << fileline << "\n"); + AstPackageImport* const impp = new AstPackageImport{stdpkgp->fileline(), stdpkgp, "*"}; + unitPackage(stdpkgp->fileline())->addStmtsp(impp); + v3Global.setUsesStdPackage(); + } +} + void V3ParseImp::lexPpline(const char* textp) { // Handle lexer `line directive // FileLine* const prevFl = lexFileline(); @@ -271,8 +290,8 @@ void V3ParseImp::preprocDumps(std::ostream& os, bool forInputs) { for (auto& buf : m_ppBuffers) { if (noblanks) { bool blank = true; - for (string::iterator its = buf.begin(); its != buf.end(); ++its) { - if (!std::isspace(*its) && *its != '\n') { + for (const char ch : buf) { + if (!std::isspace(ch) && ch != '\n') { blank = false; break; } @@ -332,7 +351,9 @@ void V3ParseImp::parseFile(FileLine* fileline, const string& modfilename, bool i } V3Stats::addStatSum(V3Stats::STAT_SOURCE_CHARS, m_ppBytes); - if (debug() && modfilename != V3Options::getStdPackagePath()) dumpInputsFile(); + if (debug() && modfilename != V3Options::getStdPackagePath() + && modfilename != V3Options::getStdWaiverPath()) + dumpInputsFile(); // Parse it if (!v3Global.opt.preprocOnly()) { @@ -394,19 +415,75 @@ const V3ParseBisonYYSType* V3ParseImp::tokenPeekp(size_t depth) { return &m_tokensAhead.at(depth); } -size_t V3ParseImp::tokenPipeScanParam(size_t depth) { +size_t V3ParseImp::tokenPipeScanIdCell(size_t depthIn) { + // Search around IEEE module_instantiation/interface_instantiation/program_instantiation + // Return location of following token, or input if not found + // yaID/*module_identifier*/ [ '#' '('...')' ] yaID/*name_of_instance*/ [ '['...']' ] '(' ... + // yaID/*module_identifier*/ [ '#' id|etc ] yaID/*name_of_instance*/ [ '['...']' ] '(' ... + size_t depth = depthIn; + depth = tokenPipeScanParam(depth, true); + + if (tokenPeekp(depth)->token != yaID__LEX) return depthIn; + ++depth; + + depth = tokenPipeScanBracket(depth); // [ '['..']' ]* + if (tokenPeekp(depth)->token != '(') return depthIn; + + return depth; +} + +size_t V3ParseImp::tokenPipeScanBracket(size_t inDepth) { + // Return location of following token, or input if not found + // [ '['...']' ]* + int depth = inDepth; + int bra = 0; + while (tokenPeekp(depth)->token == '[') { + do { // Scan brackets + const int tok = tokenPeekp(depth)->token; + if (tok == 0) { // LCOV_EXCL_BR_LINE + UINFO(9, "tokenPipeScanBracket hit EOF; probably syntax error to come"); + return inDepth; // LCOV_EXCL_LINE + } else if (tok == '[') { + ++bra; + ++depth; + } else if (bra && tok == ']') { + --bra; + ++depth; + } else if (bra) { + ++depth; + } + } while (bra); + } + return depth; +} + +size_t V3ParseImp::tokenPipeScanParam(size_t inDepth, bool forCell) { // Search around IEEE parameter_value_assignment to see if :: follows // Return location of following token, or input if not found // yaID [ '#(' ... ')' ] - if (tokenPeekp(depth)->token != '#') return depth; - if (tokenPeekp(depth + 1)->token != '(') return depth; - depth += 2; // Past the ( + // if forCell: yaID [ '#' number/etc ] + int depth = inDepth; + if (tokenPeekp(depth)->token != '#') return inDepth; + ++depth; + + if (tokenPeekp(depth)->token != '(') { + if (!forCell) return inDepth; + // For module cells, we can have '#' and a number, or, annoyingly an idDotted + int ntoken = tokenPeekp(depth)->token; + if (ntoken == yaINTNUM || ntoken == yaFLOATNUM || ntoken == yaTIMENUM + || ntoken == yaID__LEX) { + ++depth; + return depth; + } + return inDepth; // Miss + } + ++depth; int parens = 1; // Count first ( while (true) { const int tok = tokenPeekp(depth)->token; if (tok == 0) { // LCOV_EXCL_BR_LINE UINFO(9, "tokenPipeScanParam hit EOF; probably syntax error to come"); - break; // LCOV_EXCL_LINE + return inDepth; // LCOV_EXCL_LINE } else if (tok == '(') { ++parens; } else if (tok == ')') { @@ -450,12 +527,16 @@ size_t V3ParseImp::tokenPipeScanTypeEq(size_t depth) { int V3ParseImp::tokenPipelineId(int token) { const V3ParseBisonYYSType* nexttokp = tokenPeekp(0); // First char after yaID const int nexttok = nexttokp->token; + UINFO(9, "tokenPipelineId tok=" << yylval.token << endl); UASSERT(yylval.token == yaID__LEX, "Start with ID"); if (nexttok == yP_COLONCOLON) { return yaID__CC; } VL_RESTORER(yylval); // Remember value, as about to read ahead - if (nexttok == '#') { - VL_RESTORER(yylval); // Remember value, as about to read ahead - const size_t depth = tokenPipeScanParam(0); + if (m_tokenLastBison.token != '@' && m_tokenLastBison.token != '#' + && m_tokenLastBison.token != '.') { + if (const size_t depth = tokenPipeScanIdCell(0)) return yaID__aCELL; + } + if (nexttok == '#') { // e.g. class_type parameter_value_assignment '::' + const size_t depth = tokenPipeScanParam(0, false); if (tokenPeekp(depth)->token == yP_COLONCOLON) return yaID__CC; } return token; @@ -585,6 +666,9 @@ void V3ParseImp::tokenPipelineSym() { // Note above sometimes converts yGLOBAL to a yaID__LEX tokenPipeline(); // sets yylval int token = yylval.token; + if (token == yaID__LEX || token == yaID__CC || token == yaID__aTYPE) { + importIfInStd(yylval.fl, *(yylval.strp)); + } if (token == yaID__LEX || token == yaID__CC) { const VSymEnt* foundp; if (const VSymEnt* const look_underp = V3ParseImp::parsep()->symp()->nextId()) { @@ -607,12 +691,6 @@ void V3ParseImp::tokenPipelineSym() { VSymEnt* const stdsymp = stdpkgp->user4u().toSymEnt(); foundp = stdsymp->findIdFallback(*(yylval.strp)); } - if (foundp && !v3Global.usesStdPackage()) { - AstPackageImport* const impp - = new AstPackageImport{stdpkgp->fileline(), stdpkgp, "*"}; - unitPackage(stdpkgp->fileline())->addStmtsp(impp); - v3Global.setUsesStdPackage(); - } } if (foundp) { AstNode* const scp = foundp->nodep(); @@ -630,8 +708,6 @@ void V3ParseImp::tokenPipelineSym() { } else { token = yaID__ETC; } - } else if (!m_afterColonColon && *(yylval.strp) == "std") { - v3Global.setUsesStdPackage(); } } else { // Not found yylval.scp = nullptr; @@ -662,6 +738,7 @@ int V3ParseImp::tokenToBison() { // Called as global since bison doesn't have our pointer tokenPipelineSym(); // sets yylval m_bisonLastFileline = yylval.fl; + m_tokenLastBison = yylval; // yylval.scp = nullptr; // Symbol table not yet needed - no packages if (debug() >= 6 || debugFlex() >= 6 @@ -680,6 +757,7 @@ std::ostream& operator<<(std::ostream& os, const V3ParseBisonYYSType& rhs) { if (rhs.token == yaID__ETC // || rhs.token == yaID__CC // || rhs.token == yaID__LEX // + || rhs.token == yaID__aCELL // || rhs.token == yaID__aTYPE) { os << " strp='" << *(rhs.strp) << "'"; } diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index d54b714c9..916bdb48c 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2009-2024 by Wilson Snyder. This program is free software; you +// Copyright 2009-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -156,6 +156,7 @@ class V3ParseImp final { int m_lexPrevToken = 0; // previous parsed token (for lexer) bool m_afterColonColon = false; // The previous token was '::' + V3ParseBisonYYSType m_tokenLastBison; // Token we last sent to Bison std::deque m_tokensAhead; // Tokens we parsed ahead of parser std::deque m_stringps; // Created strings for later cleanup @@ -308,11 +309,14 @@ private: void preprocDumps(std::ostream& os); void lexFile(const string& modname) VL_MT_DISABLED; void yylexReadTok() VL_MT_DISABLED; + void importIfInStd(FileLine* fileline, const string& id); void tokenPull() VL_MT_DISABLED; void tokenPipeline() VL_MT_DISABLED; // Internal; called from tokenToBison int tokenPipelineId(int token) VL_MT_DISABLED; void tokenPipelineSym() VL_MT_DISABLED; - size_t tokenPipeScanParam(size_t depth) VL_MT_DISABLED; + size_t tokenPipeScanIdCell(size_t depth) VL_MT_DISABLED; + size_t tokenPipeScanBracket(size_t depth) VL_MT_DISABLED; + size_t tokenPipeScanParam(size_t depth, bool forCell) VL_MT_DISABLED; size_t tokenPipeScanTypeEq(size_t depth) VL_MT_DISABLED; const V3ParseBisonYYSType* tokenPeekp(size_t depth) VL_MT_DISABLED; void preprocDumps(std::ostream& os, bool forInputs) VL_MT_DISABLED; diff --git a/src/V3ParseLex.cpp b/src/V3ParseLex.cpp index 552d3b652..a4709ec5f 100644 --- a/src/V3ParseLex.cpp +++ b/src/V3ParseLex.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 9342c2b8a..1f24cd76c 100644 --- a/src/V3ParseSym.h +++ b/src/V3ParseSym.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2009-2024 by Wilson Snyder. This program is free software; you +// Copyright 2009-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3PchAstMT.h b/src/V3PchAstMT.h index 552c0f452..8e5aaf470 100644 --- a/src/V3PchAstMT.h +++ b/src/V3PchAstMT.h @@ -2,7 +2,7 @@ //************************************************************************* // Code available from: https://verilator.org // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3PchAstNoMT.h b/src/V3PchAstNoMT.h index 0971316ce..0b67f4306 100644 --- a/src/V3PchAstNoMT.h +++ b/src/V3PchAstNoMT.h @@ -2,7 +2,7 @@ //************************************************************************* // Code available from: https://verilator.org // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3PreExpr.h b/src/V3PreExpr.h index 18d69cb12..b89746c15 100644 --- a/src/V3PreExpr.h +++ b/src/V3PreExpr.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2000-2023 by Wilson Snyder. This program is free software; you +// Copyright 2000-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 7d11a9e3f..5a7cd8acf 100644 --- a/src/V3PreLex.h +++ b/src/V3PreLex.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2000-2024 by Wilson Snyder. This program is free software; you +// Copyright 2000-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.l b/src/V3PreLex.l index fa605d72a..7f71af112 100644 --- a/src/V3PreLex.l +++ b/src/V3PreLex.l @@ -5,7 +5,7 @@ * ************************************************************************** * - * Copyright 2003-2024 by Wilson Snyder. This program is free software; you + * Copyright 2003-2025 by Wilson Snyder. This program is free software; you * can redistribute it and/or modify it 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 31bd2dccc..63894e72a 100644 --- a/src/V3PreProc.cpp +++ b/src/V3PreProc.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2000-2024 by Wilson Snyder. This program is free software; you +// Copyright 2000-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -490,7 +490,7 @@ void V3PreProcImp::comment(const string& text) { if (VString::startsWith(cmd, "public_flat_rw")) { // "/*verilator public_flat_rw @(foo) */" -> "/*verilator public_flat_rw*/ @(foo)" string::size_type endOfCmd = std::strlen("public_flat_rw"); - while (VString::isWordChar(cmd[endOfCmd])) ++endOfCmd; + while (VString::isIdentifierChar(cmd[endOfCmd])) ++endOfCmd; string baseCmd = cmd.substr(0, endOfCmd); string arg = cmd.substr(endOfCmd); while (std::isspace(arg[0])) arg = arg.substr(1); @@ -824,6 +824,21 @@ void V3PreProcImp::openFile(FileLine*, VInFilter* filterp, const string& filenam flsp->newContent(); for (const string& i : wholefile) flsp->contentp()->pushText(i); + // Save contents for V3Config --contents + if (filename != V3Options::getStdPackagePath()) { + bool containsVlt = false; + for (const string& i : wholefile) { + // TODO this is overly sensitive, might be in a comment + if (i.find("`verilator_config") != string::npos) { + containsVlt = true; + break; + } + } + if (!containsVlt) { + for (const string& i : wholefile) V3Config::contentsPushText(i); + } + } + // Create new stream structure m_lexp->scanNewFile(flsp); addLineComment(1); // Enter diff --git a/src/V3PreProc.h b/src/V3PreProc.h index 2560ce9bd..da6c0d8d8 100644 --- a/src/V3PreProc.h +++ b/src/V3PreProc.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2000-2024 by Wilson Snyder. This program is free software; you +// Copyright 2000-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 2b02b658d..6655c0786 100644 --- a/src/V3PreShell.cpp +++ b/src/V3PreShell.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2024 by Wilson Snyder. This program is free software; you +// Copyright 2004-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.h b/src/V3PreShell.h index 7c15e43fd..7e8f73e90 100644 --- a/src/V3PreShell.h +++ b/src/V3PreShell.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2024 by Wilson Snyder. This program is free software; you +// Copyright 2004-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.cpp b/src/V3Premit.cpp index 14106e86b..6fb3bc8c5 100644 --- a/src/V3Premit.cpp +++ b/src/V3Premit.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 82388168f..5be58992d 100644 --- a/src/V3Premit.h +++ b/src/V3Premit.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 7335379f7..ec66dba2d 100644 --- a/src/V3ProtectLib.cpp +++ b/src/V3ProtectLib.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.h b/src/V3ProtectLib.h index 4d4cfe04e..f9ecfaa5b 100644 --- a/src/V3ProtectLib.h +++ b/src/V3ProtectLib.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 49ef24aff..96c3f6945 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -131,7 +131,7 @@ class RandomizeMarkVisitor final : public VNVisitor { BaseToDerivedMap m_baseToDerivedMap; // Mapping from base classes to classes that extend them AstClass* m_classp = nullptr; // Current class - AstNode* m_constraintExprp = nullptr; // Current constraint expression + AstNode* m_constraintExprGenp = nullptr; // Current constraint or constraint if expression AstNodeModule* m_modp; // Current module AstNodeStmt* m_stmtp = nullptr; // Current statement std::set m_staticRefs; // References to static variables under `with` clauses @@ -402,44 +402,34 @@ class RandomizeMarkVisitor final : public VNVisitor { } } void visit(AstConstraintExpr* nodep) override { - VL_RESTORER(m_constraintExprp); - m_constraintExprp = nodep; + VL_RESTORER(m_constraintExprGenp); + m_constraintExprGenp = nodep; iterateChildrenConst(nodep); } void visit(AstConstraintIf* nodep) override { { - VL_RESTORER(m_constraintExprp); - m_constraintExprp = nodep; + VL_RESTORER(m_constraintExprGenp); + m_constraintExprGenp = nodep; iterateConst(nodep->condp()); } iterateAndNextConstNull(nodep->thensp()); iterateAndNextConstNull(nodep->elsesp()); } void visit(AstNodeVarRef* nodep) override { - if (!m_constraintExprp) return; + if (!m_constraintExprGenp) return; if (nodep->varp()->lifetime().isStatic()) m_staticRefs.emplace(nodep); - if (!nodep->varp()->rand().isRandomizable()) return; - for (AstNode* backp = nodep; backp != m_constraintExprp && !backp->user1(); - backp = backp->backp()) - backp->user1(true); + if (nodep->varp()->rand().isRandomizable()) nodep->user1(true); } void visit(AstMemberSel* nodep) override { - if (!m_constraintExprp) return; - if (VN_IS(nodep->fromp(), LambdaArgRef)) { - if (!nodep->varp()->rand().isRandomizable()) return; - for (AstNode* backp = nodep; backp != m_constraintExprp && !backp->user1(); - backp = backp->backp()) - backp->user1(true); - } - } - void visit(AstArraySel* nodep) override { - if (!m_constraintExprp) return; - for (AstNode* backp = nodep; backp != m_constraintExprp && !backp->user1(); - backp = backp->backp()) - backp->user1(true); + if (!m_constraintExprGenp) return; iterateChildrenConst(nodep); + // Member select are randomized when both object and member are marked as rand. + // Variable references in with clause are converted to member selects and their from() is + // of type AstLambdaArgRef. They are randomized too. + const bool randObject = nodep->fromp()->user1() || VN_IS(nodep->fromp(), LambdaArgRef); + nodep->user1(randObject && nodep->varp()->rand().isRandomizable()); } void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); @@ -455,6 +445,14 @@ class RandomizeMarkVisitor final : public VNVisitor { iterateChildrenConst(nodep); } + void visit(AstNodeExpr* nodep) override { + iterateChildrenConst(nodep); + if (!m_constraintExprGenp) return; + nodep->user1((nodep->op1p() && nodep->op1p()->user1()) + || (nodep->op2p() && nodep->op2p()->user1()) + || (nodep->op3p() && nodep->op3p()->user1()) + || (nodep->op4p() && nodep->op4p()->user1())); + } void visit(AstNode* nodep) override { iterateChildrenConst(nodep); } public: @@ -588,6 +586,12 @@ class ConstraintExprVisitor final : public VNVisitor { // VISITORS void visit(AstNodeVarRef* nodep) override { AstVar* const varp = nodep->varp(); + if (varp->user4p()) { + varp->user4p()->v3warn( + CONSTRAINTIGN, + "Size constraint combined with element constraint may not work correctly"); + } + AstNodeModule* const classOrPackagep = nodep->classOrPackagep(); const RandomizeMode randMode = {.asInt = varp->user1()}; if (!randMode.usesMode && editFormat(nodep)) return; @@ -618,7 +622,8 @@ class ConstraintExprVisitor final : public VNVisitor { VAccess::READWRITE}, "write_var"}; uint32_t dimension = 0; - if (VN_IS(varp->dtypep(), UnpackArrayDType)) { + if (VN_IS(varp->dtypep(), UnpackArrayDType) || VN_IS(varp->dtypep(), DynArrayDType) + || VN_IS(varp->dtypep(), QueueDType) || VN_IS(varp->dtypep(), AssocArrayDType)) { const std::pair dims = varp->dtypep()->dimensions(/*includeBasic=*/true); const uint32_t unpackedDimensions = dims.second; @@ -631,8 +636,11 @@ class ConstraintExprVisitor final : public VNVisitor { varRefp->classOrPackagep(classOrPackagep); methodp->addPinsp(varRefp); size_t width = varp->width(); - if (VN_IS(varp->dtypep(), DynArrayDType) || VN_IS(varp->dtypep(), QueueDType)) - width = varp->dtypep()->subDTypep()->width(); + AstNodeDType* tmpDtypep = varp->dtypep(); + while (VN_IS(tmpDtypep, UnpackArrayDType) || VN_IS(tmpDtypep, DynArrayDType) + || VN_IS(tmpDtypep, QueueDType) || VN_IS(tmpDtypep, AssocArrayDType)) + tmpDtypep = tmpDtypep->subDTypep(); + width = tmpDtypep->width(); methodp->addPinsp( new AstConst{varp->dtypep()->fileline(), AstConst::Unsized64{}, width}); AstNodeExpr* const varnamep @@ -698,6 +706,44 @@ class ConstraintExprVisitor final : public VNVisitor { editSMT(nodep, nodep->fromp(), lsbp, msbp); } + void visit(AstAssocSel* nodep) override { + if (editFormat(nodep)) return; + FileLine* const fl = nodep->fileline(); + if (VN_IS(nodep->bitp(), CvtPackString)) { + // Extract and truncate the string index to fit within 64 bits + AstCvtPackString* const stringp = VN_AS(nodep->bitp(), CvtPackString); + VNRelinker handle; + AstNodeExpr* const strIdxp = new AstSFormatF{ + fl, "#x%16x", false, + new AstAnd{fl, stringp->lhsp()->unlinkFrBack(&handle), + new AstConst(fl, AstConst::Unsized64{}, 0xFFFFFFFFFFFFFFFF)}}; + handle.relink(strIdxp); + editSMT(nodep, nodep->fromp(), strIdxp); + } else { + VNRelinker handle; + const int actual_width = nodep->bitp()->width(); + std::string fmt; + // Normalize to standard bit width + if (actual_width <= 8) { + fmt = "#x%2x"; + } else if (actual_width <= 16) { + fmt = "#x%4x"; + } else if (actual_width <= 32) { + fmt = "#x%8x"; + } else if (actual_width <= 64) { + fmt = "#x%16x"; + } else { + nodep->v3warn(CONSTRAINTIGN, + "Unsupported: Associative array index " + "widths of more than 64 bits during constraint randomization."); + return; + } + AstNodeExpr* const idxp + = new AstSFormatF{fl, fmt, false, nodep->bitp()->unlinkFrBack(&handle)}; + handle.relink(idxp); + editSMT(nodep, nodep->fromp(), idxp); + } + } void visit(AstArraySel* nodep) override { if (editFormat(nodep)) return; FileLine* const fl = nodep->fileline(); @@ -707,6 +753,12 @@ class ConstraintExprVisitor final : public VNVisitor { handle.relink(indexp); editSMT(nodep, nodep->fromp(), indexp); } + void visit(AstMemberSel* nodep) override { + if (nodep->user1()) { + nodep->v3warn(CONSTRAINTIGN, "Global constraints ignored (unsupported)"); + } + editFormat(nodep); + } void visit(AstSFormatF* nodep) override {} void visit(AstStmtExpr* nodep) override {} void visit(AstConstraintIf* nodep) override { @@ -902,14 +954,14 @@ class CaptureVisitor final : public VNVisitor { return false; } - template - void fixupClassOrPackage(AstNode* memberp, NodeT refp) { + template + void fixupClassOrPackage(AstNode* memberp, T_Node refp) { AstNodeModule* const declClassp = VN_AS(memberp->user2p(), NodeModule); if (declClassp != m_targetp) refp->classOrPackagep(declClassp); } - template - bool isReferenceToInnerMember(NodeT nodep) { + template + bool isReferenceToInnerMember(T_Node nodep) { return VN_IS(nodep->fromp(), LambdaArgRef); } @@ -1053,13 +1105,11 @@ class CaptureVisitor final : public VNVisitor { AstNodeExpr* const pinsp = nodep->pinsp() ? nodep->pinsp()->unlinkFrBackWithNext() : nullptr; AstNodeFTaskRef* taskRefp = nullptr; - if (VN_IS(nodep->taskp(), Task)) - taskRefp = new AstTaskRef{nodep->fileline(), nodep->name(), pinsp}; - else if (VN_IS(nodep->taskp(), Func)) - taskRefp = new AstFuncRef{nodep->fileline(), nodep->name(), pinsp}; + if (AstTask* const taskp = VN_CAST(nodep->taskp(), Task)) + taskRefp = new AstTaskRef{nodep->fileline(), taskp, pinsp}; + else if (AstFunc* const taskp = VN_CAST(nodep->taskp(), Func)) + taskRefp = new AstFuncRef{nodep->fileline(), taskp, pinsp}; UASSERT_OBJ(taskRefp, nodep, "Node needs to point to regular method"); - taskRefp->taskp(nodep->taskp()); - taskRefp->dtypep(nodep->dtypep()); fixupClassOrPackage(nodep->taskp(), taskRefp); taskRefp->user1(nodep->user1()); nodep->replaceWith(taskRefp); @@ -1110,7 +1160,9 @@ class RandomizeVisitor final : public VNVisitor { // AstClass::user2p() -> AstVar*. Rand mode state variable // AstVar::user3() -> bool. Handled in constraints // AstClass::user3p() -> AstVar*. Constrained randomizer variable + // AstConstraint::user3p() -> AstTask*. Pointer to resize procedure // AstClass::user4p() -> AstVar*. Constraint mode state variable + // AstVar::user4p() -> AstVar*. Size variable for constrained queues // VNUser1InUse m_inuser1; (Allocated for use in RandomizeMarkVisitor) // VNUser2InUse m_inuser2; (Allocated for use in RandomizeMarkVisitor) const VNUser3InUse m_inuser3; @@ -1128,6 +1180,7 @@ class RandomizeVisitor final : public VNVisitor { size_t m_enumValueTabCount = 0; // Number of tables with enum values created int m_randCaseNum = 0; // Randcase number within a module for var naming std::map m_randcDtypes; // RandC data type deduplication + AstConstraint* m_constraintp = nullptr; // Current constraint // METHODS void createRandomGenerator(AstClass* const classp) { @@ -1158,6 +1211,17 @@ class RandomizeVisitor final : public VNVisitor { m_memberMap.insert(classp, setupAllTaskp); return setupAllTaskp; } + AstTask* getCreateAggrResizeTask(AstClass* const classp) { + static const char* const name = "__Vresize_constrained_arrays"; + AstTask* resizeTaskp = VN_AS(m_memberMap.findMember(classp, name), Task); + if (resizeTaskp) return resizeTaskp; + resizeTaskp = new AstTask{classp->fileline(), name, nullptr}; + resizeTaskp->classMethod(true); + resizeTaskp->isVirtual(true); + classp->addMembersp(resizeTaskp); + m_memberMap.insert(classp, resizeTaskp); + return resizeTaskp; + } AstVar* getCreateRandModeVar(AstClass* const classp) { if (classp->user2p()) return VN_AS(classp->user2p(), Var); if (AstClassExtends* const extendsp = classp->extendsp()) { @@ -1259,8 +1323,7 @@ class RandomizeVisitor final : public VNVisitor { FileLine* fl = modeVarp->fileline(); AstCMethodHard* const dynarrayNewp = new AstCMethodHard{fl, new AstVarRef{fl, modeVarModp, modeVarp, VAccess::WRITE}, - "renew_copy", new AstConst{fl, modeCount}}; - dynarrayNewp->addPinsp(new AstVarRef{fl, modeVarModp, modeVarp, VAccess::READ}); + "resize", new AstConst{fl, modeCount}}; dynarrayNewp->dtypeSetVoid(); AstNodeFTask* const newp = VN_AS(m_memberMap.findMember(classp, "new"), NodeFTask); UASSERT_OBJ(newp, classp, "No new() in class"); @@ -1471,9 +1534,12 @@ class RandomizeVisitor final : public VNVisitor { AstMethodCall* const callp = new AstMethodCall{fl, exprp, "randomize", nullptr}; callp->taskp(memberFuncp); callp->dtypeFrom(memberFuncp); - return new AstAssign{ + AstAssign* const assignp = new AstAssign{ fl, new AstVarRef{fl, outputVarp, VAccess::WRITE}, new AstAnd{fl, new AstVarRef{fl, outputVarp, VAccess::READ}, callp}}; + return new AstIf{ + fl, new AstNeq{fl, exprp->cloneTree(false), new AstConst{fl, AstConst::Null{}}}, + assignp}; } else if (AstDynArrayDType* const dynarrayDtp = VN_CAST(memberDtp, DynArrayDType)) { return createArrayForeachLoop(fl, dynarrayDtp, exprp, outputVarp); } else if (AstQueueDType* const queueDtp = VN_CAST(memberDtp, QueueDType)) { @@ -1528,9 +1594,7 @@ class RandomizeVisitor final : public VNVisitor { } void addPrePostCall(AstClass* const classp, AstFunc* const funcp, const string& name) { if (AstTask* userFuncp = VN_CAST(m_memberMap.findMember(classp, name), Task)) { - AstTaskRef* const callp - = new AstTaskRef{userFuncp->fileline(), userFuncp->name(), nullptr}; - callp->taskp(userFuncp); + AstTaskRef* const callp = new AstTaskRef{userFuncp->fileline(), userFuncp, nullptr}; funcp->addStmtsp(callp->makeStmt()); } } @@ -1540,6 +1604,13 @@ class RandomizeVisitor final : public VNVisitor { nodep->addMembersp(taskp); return taskp; } + AstTask* newResizeConstrainedArrayTask(AstClass* const nodep, const std::string& name) { + AstTask* const taskp + = new AstTask{nodep->fileline(), name + "_resize_constrained_array", nullptr}; + taskp->classMethod(true); + nodep->addMembersp(taskp); + return taskp; + } AstNodeStmt* implementConstraintsClear(FileLine* const fileline, AstVar* const genp) { AstCMethodHard* const clearp = new AstCMethodHard{ fileline, @@ -1865,14 +1936,21 @@ class RandomizeVisitor final : public VNVisitor { constrp->user2p(taskp); } AstTaskRef* const setupTaskRefp - = new AstTaskRef{constrp->fileline(), taskp->name(), nullptr}; - setupTaskRefp->taskp(taskp); + = new AstTaskRef{constrp->fileline(), taskp, nullptr}; setupTaskRefp->classOrPackagep(classp); AstTask* const setupAllTaskp = getCreateConstraintSetupFunc(nodep); setupAllTaskp->addStmtsp(setupTaskRefp->makeStmt()); + if (AstTask* const resizeTaskp = VN_CAST(constrp->user3p(), Task)) { + AstTask* const resizeAllTaskp = getCreateAggrResizeTask(nodep); + AstTaskRef* const resizeTaskRefp + = new AstTaskRef{constrp->fileline(), resizeTaskp, nullptr}; + resizeTaskRefp->classOrPackagep(classp); + resizeAllTaskp->addStmtsp(resizeTaskRefp->makeStmt()); + } + ConstraintExprVisitor{m_memberMap, constrp->itemsp(), nullptr, genp, randModeVarp}; if (constrp->itemsp()) { taskp->addStmtsp(wrapIfConstraintMode( @@ -1881,9 +1959,7 @@ class RandomizeVisitor final : public VNVisitor { }); randomizep->addStmtsp(implementConstraintsClear(fl, genp)); AstTask* setupAllTaskp = getCreateConstraintSetupFunc(nodep); - AstTaskRef* const setupTaskRefp = new AstTaskRef{fl, setupAllTaskp->name(), nullptr}; - setupTaskRefp->taskp(setupAllTaskp); - randomizep->addStmtsp(implementConstraintsClear(fl, genp)); + AstTaskRef* const setupTaskRefp = new AstTaskRef{fl, setupAllTaskp, nullptr}; randomizep->addStmtsp(setupTaskRefp->makeStmt()); AstNodeModule* const genModp = VN_AS(genp->user2p(), NodeModule); @@ -1909,12 +1985,16 @@ class RandomizeVisitor final : public VNVisitor { AstVarRef* const fvarRefp = new AstVarRef{fl, fvarp, VAccess::WRITE}; randomizep->addStmtsp(new AstAssign{fl, fvarRefp, beginValp}); + if (AstTask* const resizeAllTaskp + = VN_AS(m_memberMap.findMember(nodep, "__Vresize_constrained_arrays"), Task)) { + AstTaskRef* const resizeTaskRefp = new AstTaskRef{fl, resizeAllTaskp, nullptr}; + randomizep->addStmtsp(resizeTaskRefp->makeStmt()); + } + AstFunc* const basicRandomizep = V3Randomize::newRandomizeFunc(m_memberMap, nodep, "__Vbasic_randomize"); addBasicRandomizeBody(basicRandomizep, nodep, randModeVarp); - AstFuncRef* const basicRandomizeCallp = new AstFuncRef{fl, "__Vbasic_randomize", nullptr}; - basicRandomizeCallp->taskp(basicRandomizep); - basicRandomizeCallp->dtypep(basicRandomizep->dtypep()); + AstFuncRef* const basicRandomizeCallp = new AstFuncRef{fl, basicRandomizep, nullptr}; AstVarRef* const fvarRefReadp = fvarRefp->cloneTree(false); fvarRefReadp->access(VAccess::READ); @@ -2086,16 +2166,12 @@ class RandomizeVisitor final : public VNVisitor { AstFunc* const basicRandomizeFuncp = V3Randomize::newRandomizeFunc(m_memberMap, classp, "__Vbasic_randomize"); AstFuncRef* const basicRandomizeFuncCallp - = new AstFuncRef{nodep->fileline(), "__Vbasic_randomize", nullptr}; - basicRandomizeFuncCallp->taskp(basicRandomizeFuncp); - basicRandomizeFuncCallp->dtypep(basicRandomizeFuncp->dtypep()); + = new AstFuncRef{nodep->fileline(), basicRandomizeFuncp, nullptr}; // Copy (derive) class constraints if present if (classGenp) { AstTask* const constrSetupFuncp = getCreateConstraintSetupFunc(classp); - AstTaskRef* const callp - = new AstTaskRef{nodep->fileline(), constrSetupFuncp->name(), nullptr}; - callp->taskp(constrSetupFuncp); + AstTaskRef* const callp = new AstTaskRef{nodep->fileline(), constrSetupFuncp, nullptr}; randomizeFuncp->addStmtsp(callp->makeStmt()); randomizeFuncp->addStmtsp(new AstAssign{ nodep->fileline(), new AstVarRef{nodep->fileline(), localGenp, VAccess::WRITE}, @@ -2137,6 +2213,57 @@ class RandomizeVisitor final : public VNVisitor { UINFO(9, "Added `%s` randomization procedure"); VL_DO_DANGLING(withp->deleteTree(), withp); } + void visit(AstConstraint* nodep) override { + VL_RESTORER(m_constraintp); + m_constraintp = nodep; + iterateChildren(nodep); + } + void visit(AstCMethodHard* nodep) override { + iterateChildren(nodep); + FileLine* const fl = nodep->fileline(); + if (m_constraintp && nodep->fromp()->user1() && nodep->name() == "size") { + AstClass* const classp = VN_AS(m_modp, Class); + AstVarRef* const queueVarRefp = VN_CAST(nodep->fromp(), VarRef); + if (!queueVarRefp) { + // Warning from ConstraintExprVisitor will be thrown + return; + } + AstVar* const queueVarp = queueVarRefp->varp(); + AstVar* sizeVarp = VN_CAST(queueVarp->user4p(), Var); + if (!sizeVarp) { + sizeVarp = new AstVar{fl, VVarType::BLOCKTEMP, "__V" + queueVarp->name() + "_size", + nodep->findSigned32DType()}; + classp->addMembersp(sizeVarp); + m_memberMap.insert(classp, sizeVarp); + sizeVarp->user2p(classp); + + queueVarp->user4p(sizeVarp); + + AstTask* resizerTaskp = VN_AS(m_constraintp->user3p(), Task); + if (!resizerTaskp) { + resizerTaskp = newResizeConstrainedArrayTask(classp, m_constraintp->name()); + m_constraintp->user3p(resizerTaskp); + } + AstCMethodHard* const resizep + = new AstCMethodHard{fl, nodep->fromp()->unlinkFrBack(), "resize", + new AstVarRef{fl, sizeVarp, VAccess::READ}}; + resizep->dtypep(nodep->findVoidDType()); + resizerTaskp->addStmtsp(new AstStmtExpr{fl, resizep}); + + // Since size variable is signed int, we need additional constraint + // to make sure it is always >= 0. + AstVarRef* const sizeVarRefp = new AstVarRef{fl, sizeVarp, VAccess::READ}; + sizeVarRefp->user1(true); + AstGteS* const sizeGtep = new AstGteS{fl, sizeVarRefp, new AstConst{fl, 0}}; + sizeGtep->user1(true); + m_constraintp->addItemsp(new AstConstraintExpr{fl, sizeGtep}); + } + AstVarRef* const sizeVarRefp = new AstVarRef{fl, sizeVarp, VAccess::READ}; + sizeVarRefp->user1(true); + nodep->replaceWith(sizeVarRefp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); + } + } void visit(AstNodeStmt* nodep) override { VL_RESTORER(m_stmtp); m_stmtp = nodep; diff --git a/src/V3Randomize.h b/src/V3Randomize.h index 896c14895..f37b6a7fe 100644 --- a/src/V3Randomize.h +++ b/src/V3Randomize.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 15c4afbc7..fc0f69f30 100644 --- a/src/V3Reloop.cpp +++ b/src/V3Reloop.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -145,11 +145,9 @@ class ReloopVisitor final : public VNVisitor { // VISITORS void visit(AstCFunc* nodep) override { VL_RESTORER(m_cfuncp); - { - m_cfuncp = nodep; - iterateChildren(nodep); - mergeEnd(); // Finish last pending merge, if any - } + m_cfuncp = nodep; + iterateChildren(nodep); + mergeEnd(); // Finish last pending merge, if any } void visit(AstNodeAssign* nodep) override { if (!m_cfuncp) return; diff --git a/src/V3Reloop.h b/src/V3Reloop.h index 756de4dd7..1324e10c7 100644 --- a/src/V3Reloop.h +++ b/src/V3Reloop.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3Rtti.h b/src/V3Rtti.h index e671a4d50..627310e02 100644 --- a/src/V3Rtti.h +++ b/src/V3Rtti.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3Sampled.cpp b/src/V3Sampled.cpp index e933ba869..8058fa683 100644 --- a/src/V3Sampled.cpp +++ b/src/V3Sampled.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3Sampled.h b/src/V3Sampled.h index bd24873e3..766b747e8 100644 --- a/src/V3Sampled.h +++ b/src/V3Sampled.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 46fb79354..61a7f21d1 100644 --- a/src/V3Sched.cpp +++ b/src/V3Sched.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -156,7 +156,9 @@ AstNodeStmt* checkIterationLimit(AstNetlist* netlistp, const string& name, AstVa return ifp; } -AstNodeStmt* profExecSectionPush(FileLine* flp, const string& name) { +AstNodeStmt* profExecSectionPush(FileLine* flp, const string& section) { + const string name + = (v3Global.opt.hierChild() ? (v3Global.opt.topModule() + " ") : "") + section; return new AstCStmt{flp, "VL_EXEC_TRACE_ADD_RECORD(vlSymsp).sectionPush(\"" + name + "\");\n"}; } @@ -291,6 +293,7 @@ AstCFunc* splitCheckCreateNewSubFunc(AstCFunc* ofuncp) { subFuncp->isLoose(true); subFuncp->slow(ofuncp->slow()); subFuncp->declPrivate(ofuncp->declPrivate()); + if (ofuncp->needProcess()) subFuncp->setNeedProcess(); return subFuncp; }; diff --git a/src/V3Sched.h b/src/V3Sched.h index 6e0dd505d..4c430919b 100644 --- a/src/V3Sched.h +++ b/src/V3Sched.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3SchedAcyclic.cpp b/src/V3SchedAcyclic.cpp index 05ef424a5..a1dbcaffc 100644 --- a/src/V3SchedAcyclic.cpp +++ b/src/V3SchedAcyclic.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 caf64561e..8da831672 100644 --- a/src/V3SchedPartition.cpp +++ b/src/V3SchedPartition.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3SchedReplicate.cpp b/src/V3SchedReplicate.cpp index 172dbc3ff..fbe68e266 100644 --- a/src/V3SchedReplicate.cpp +++ b/src/V3SchedReplicate.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 0532ba998..b86ef9320 100644 --- a/src/V3SchedTiming.cpp +++ b/src/V3SchedTiming.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,7 +368,9 @@ void transformForks(AstNetlist* const netlistp) { // Start with children, so later we only find awaits that are actually in this begin m_beginHasAwaits = false; iterateChildrenConst(nodep); - if (m_beginHasAwaits || nodep->needProcess()) { + if (!nodep->stmtsp()) { + nodep->unlinkFrBack(); + } else if (m_beginHasAwaits || nodep->needProcess()) { UASSERT_OBJ(!nodep->name().empty(), nodep, "Begin needs a name"); // Create a function to put this begin's statements in FileLine* const flp = nodep->fileline(); @@ -407,11 +409,7 @@ void transformForks(AstNetlist* const netlistp) { } else { // The begin has neither awaits nor a process::self call, just inline the // statements - if (nodep->stmtsp()) { - nodep->replaceWith(nodep->stmtsp()->unlinkFrBackWithNext()); - } else { - nodep->unlinkFrBack(); - } + nodep->replaceWith(nodep->stmtsp()->unlinkFrBackWithNext()); } VL_DO_DANGLING(nodep->deleteTree(), nodep); } @@ -422,7 +420,6 @@ void transformForks(AstNetlist* const netlistp) { void visit(AstExprStmt* nodep) override { iterateChildren(nodep); } //-------------------- - void visit(AstNodeExpr*) override {} // Accelerate void visit(AstNode* nodep) override { iterateChildren(nodep); } public: diff --git a/src/V3SchedVirtIface.cpp b/src/V3SchedVirtIface.cpp index a49aec90b..6fa88ee37 100644 --- a/src/V3SchedVirtIface.cpp +++ b/src/V3SchedVirtIface.cpp @@ -7,7 +7,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 81621ca3e..f295d478a 100644 --- a/src/V3Scope.cpp +++ b/src/V3Scope.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -149,32 +149,30 @@ class ScopeVisitor final : public VNVisitor { VL_RESTORER(m_aboveCellp); VL_RESTORER(m_aboveScopep); VL_RESTORER(m_modp); - { - m_aboveScopep = m_scopep; - m_modp = nodep; + m_aboveScopep = m_scopep; + m_modp = nodep; - string scopename; - if (!m_aboveScopep) { - scopename = "TOP"; - } else { - scopename = m_aboveScopep->name() + "." + nodep->name(); - } - - UINFO(4, " CLASS AT " << scopename << " " << nodep << endl); - AstNode::user1ClearTree(); - - const AstNode* const abovep = (m_aboveCellp ? static_cast(m_aboveCellp) - : static_cast(nodep)); - m_scopep - = new AstScope{abovep->fileline(), m_modp, scopename, m_aboveScopep, m_aboveCellp}; - m_packageScopes.emplace(nodep, m_scopep); - - // Create scope for the current usage of this cell - AstNode::user1ClearTree(); - nodep->addMembersp(m_scopep); - - iterateChildren(nodep); + string scopename; + if (!m_aboveScopep) { + scopename = "TOP"; + } else { + scopename = m_aboveScopep->name() + "." + nodep->name(); } + + UINFO(4, " CLASS AT " << scopename << " " << nodep << endl); + AstNode::user1ClearTree(); + + const AstNode* const abovep + = (m_aboveCellp ? static_cast(m_aboveCellp) : static_cast(nodep)); + m_scopep + = new AstScope{abovep->fileline(), m_modp, scopename, m_aboveScopep, m_aboveCellp}; + m_packageScopes.emplace(nodep, m_scopep); + + // Create scope for the current usage of this cell + AstNode::user1ClearTree(); + nodep->addMembersp(m_scopep); + + iterateChildren(nodep); } void visit(AstCellInline* nodep) override { // if (v3Global.opt.vpi()) { @@ -334,10 +332,8 @@ class ScopeCleanupVisitor final : public VNVisitor { void visit(AstScope* nodep) override { // Want to ignore blocks under it VL_RESTORER(m_scopep); - { - m_scopep = nodep; - iterateChildren(nodep); - } + m_scopep = nodep; + iterateChildren(nodep); } virtual void movedDeleteOrIterate(AstNode* nodep) { diff --git a/src/V3Scope.h b/src/V3Scope.h index c7b18e01c..d93c5256b 100644 --- a/src/V3Scope.h +++ b/src/V3Scope.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 0628d05d6..c0f72da01 100644 --- a/src/V3Scoreboard.cpp +++ b/src/V3Scoreboard.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 34656a4ff..548abdaab 100644 --- a/src/V3Scoreboard.h +++ b/src/V3Scoreboard.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 4ce5f5f86..f837a960c 100644 --- a/src/V3SenExprBuilder.h +++ b/src/V3SenExprBuilder.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 f78370e00..77ff33514 100644 --- a/src/V3SenTree.h +++ b/src/V3SenTree.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 1a96ca74d..4e727cd21 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 434f09e81..ab5fdea73 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -31,7 +31,7 @@ // ARRAYSEL // Modify bitp() for the new value and set ->length(1) // -// TODO: This code was written before SLICESEL was a type it might be +// TODO: This code was written before SLICESEL was a type, it might be // simplified to look primarily for SLICESELs. //************************************************************************* @@ -39,6 +39,8 @@ #include "V3Slice.h" +#include "V3Stats.h" + VL_DEFINE_DEBUG_FUNCTIONS; //************************************************************************* @@ -54,13 +56,15 @@ class SliceVisitor final : public VNVisitor { // AstInitItem::user2() -> Corresponding first elemIdx const VNUser2InUse m_inuser2; - // STATE + // STATE - across all visitors + VDouble0 m_statAssigns; // Statistic tracking + + // STATE - for current visit position (use VL_RESTORER) AstNode* m_assignp = nullptr; // Assignment we are under bool m_assignError = false; // True if the current assign already has an error bool m_okInitArray = false; // Allow InitArray children // METHODS - AstNodeExpr* cloneAndSel(AstNode* nodep, int elements, int elemIdx) { // Insert an ArraySel, except for a few special cases const AstUnpackArrayDType* const arrayp @@ -219,42 +223,58 @@ class SliceVisitor final : public VNVisitor { return newp; } + bool assignOptimize(AstNodeAssign* nodep) { + // Return true if did optimization + AstNodeDType* const dtp = nodep->lhsp()->dtypep()->skipRefp(); + AstNode* stp = nodep->rhsp(); + const AstUnpackArrayDType* const arrayp = VN_CAST(dtp, UnpackArrayDType); + if (!arrayp) return false; + if (VN_IS(stp, CvtPackedToArray)) return false; + + // Any isSc variables must be expanded regardless of --fno-slice + const bool hasSc + = nodep->exists([&](const AstVarRef* refp) -> bool { return refp->varp()->isSc(); }); + if (!hasSc && !v3Global.opt.fSlice()) { + m_okInitArray = true; // VL_RESTORER in visit(AstNodeAssign) + return false; + } + + UINFO(4, "Slice optimizing " << nodep << endl); + ++m_statAssigns; + + // Left and right could have different ascending/descending range, + // but #elements is common and all variables are realigned to start at zero + // Assign of an ascending range slice to a descending range one must reverse + // the elements + AstNodeAssign* newlistp = nullptr; + const int elements = arrayp->rangep()->elementsConst(); + for (int elemIdx = 0; elemIdx < elements; ++elemIdx) { + AstNodeAssign* const newp + = nodep->cloneType(cloneAndSel(nodep->lhsp(), elements, elemIdx), + cloneAndSel(nodep->rhsp(), elements, elemIdx)); + if (debug() >= 9) newp->dumpTree("- new: "); + newlistp = AstNode::addNext(newlistp, newp); + } + if (debug() >= 9) nodep->dumpTree("- Deslice-Dn: "); + nodep->replaceWith(newlistp); + VL_DO_DANGLING(nodep->deleteTree(), nodep); + // Normal edit iterator will now iterate on all of the expansion assignments + // This will potentially call this function again to resolve next level of slicing + return true; + } + void visit(AstNodeAssign* nodep) override { // Called recursively on newly created assignments - if (!nodep->user1() && !VN_IS(nodep, AssignAlias)) { - nodep->user1(true); - m_assignError = false; - if (debug() >= 9) nodep->dumpTree("- Deslice-In: "); - AstNodeDType* const dtp = nodep->lhsp()->dtypep()->skipRefp(); - AstNode* stp = nodep->rhsp(); - if (const AstUnpackArrayDType* const arrayp = VN_CAST(dtp, UnpackArrayDType)) { - if (!VN_IS(stp, CvtPackedToArray)) { - // Left and right could have different ascending/descending range, - // but #elements is common and all variables are realigned to start at zero - // Assign of an ascending range slice to a descending range one must reverse - // the elements - AstNodeAssign* newlistp = nullptr; - const int elements = arrayp->rangep()->elementsConst(); - for (int elemIdx = 0; elemIdx < elements; ++elemIdx) { - AstNodeAssign* const newp - = nodep->cloneType(cloneAndSel(nodep->lhsp(), elements, elemIdx), - cloneAndSel(nodep->rhsp(), elements, elemIdx)); - if (debug() >= 9) newp->dumpTree("- new: "); - newlistp = AstNode::addNext(newlistp, newp); - } - if (debug() >= 9) nodep->dumpTree("- Deslice-Dn: "); - nodep->replaceWith(newlistp); - VL_DO_DANGLING(nodep->deleteTree(), nodep); - // Normal edit iterator will now iterate on all of the expansion assignments - // This will potentially call this function again to resolve next level of - // slicing - return; - } - } - VL_RESTORER(m_assignp); - m_assignp = nodep; - iterateChildren(nodep); - } + if (nodep->user1SetOnce()) return; // Process once + if (VN_IS(nodep, AssignAlias)) return; + if (debug() >= 9) nodep->dumpTree("- Deslice-In: "); + VL_RESTORER(m_assignError); + VL_RESTORER(m_assignp); + VL_RESTORER(m_okInitArray); // Set in assignOptimize + m_assignError = false; + m_assignp = nodep; + if (assignOptimize(nodep)) return; + iterateChildren(nodep); } void visit(AstConsPackUOrStruct* nodep) override { @@ -278,57 +298,55 @@ class SliceVisitor final : public VNVisitor { } void expandBiOp(AstNodeBiop* nodep) { - if (!nodep->user1()) { - nodep->user1(true); - // If it's an unpacked array, blow it up into comparing each element - AstNodeDType* const fromDtp = nodep->lhsp()->dtypep()->skipRefp(); - UINFO(9, " Bi-Eq/Neq expansion " << nodep << endl); - if (const AstUnpackArrayDType* const adtypep = VN_CAST(fromDtp, UnpackArrayDType)) { - AstNodeBiop* logp = nullptr; - if (!VN_IS(nodep->lhsp()->dtypep()->skipRefp(), NodeArrayDType)) { - nodep->lhsp()->v3error( - "Slice operator " - << nodep->lhsp()->prettyTypeName() - << " on non-slicable (e.g. non-vector) left-hand-side operand"); - } else if (!VN_IS(nodep->rhsp()->dtypep()->skipRefp(), NodeArrayDType)) { - nodep->rhsp()->v3error( - "Slice operator " - << nodep->rhsp()->prettyTypeName() - << " on non-slicable (e.g. non-vector) right-hand-side operand"); - } else { - const int elements = adtypep->rangep()->elementsConst(); - for (int elemIdx = 0; elemIdx < elements; ++elemIdx) { - // EQ(a,b) -> LOGAND(EQ(ARRAYSEL(a,0), ARRAYSEL(b,0)), ...[1]) - AstNodeBiop* const clonep = VN_AS( - nodep->cloneType(cloneAndSel(nodep->lhsp(), elements, elemIdx), - cloneAndSel(nodep->rhsp(), elements, elemIdx)), - NodeBiop); - if (!logp) { - logp = clonep; - } else { - switch (nodep->type()) { - case VNType::atEq: // FALLTHRU - case VNType::atEqCase: - logp = new AstLogAnd{nodep->fileline(), logp, clonep}; - break; - case VNType::atNeq: // FALLTHRU - case VNType::atNeqCase: - logp = new AstLogOr{nodep->fileline(), logp, clonep}; - break; - default: - nodep->v3fatalSrc("Unknown node type processing array slice"); - break; - } + if (nodep->user1SetOnce()) return; // Process once + // If it's an unpacked array, blow it up into comparing each element + AstNodeDType* const fromDtp = nodep->lhsp()->dtypep()->skipRefp(); + UINFO(9, " Bi-Eq/Neq expansion " << nodep << endl); + if (const AstUnpackArrayDType* const adtypep = VN_CAST(fromDtp, UnpackArrayDType)) { + AstNodeBiop* logp = nullptr; + if (!VN_IS(nodep->lhsp()->dtypep()->skipRefp(), NodeArrayDType)) { + nodep->lhsp()->v3error( + "Slice operator " + << nodep->lhsp()->prettyTypeName() + << " on non-slicable (e.g. non-vector) left-hand-side operand"); + } else if (!VN_IS(nodep->rhsp()->dtypep()->skipRefp(), NodeArrayDType)) { + nodep->rhsp()->v3error( + "Slice operator " + << nodep->rhsp()->prettyTypeName() + << " on non-slicable (e.g. non-vector) right-hand-side operand"); + } else { + const int elements = adtypep->rangep()->elementsConst(); + for (int elemIdx = 0; elemIdx < elements; ++elemIdx) { + // EQ(a,b) -> LOGAND(EQ(ARRAYSEL(a,0), ARRAYSEL(b,0)), ...[1]) + AstNodeBiop* const clonep + = VN_AS(nodep->cloneType(cloneAndSel(nodep->lhsp(), elements, elemIdx), + cloneAndSel(nodep->rhsp(), elements, elemIdx)), + NodeBiop); + if (!logp) { + logp = clonep; + } else { + switch (nodep->type()) { + case VNType::atEq: // FALLTHRU + case VNType::atEqCase: + logp = new AstLogAnd{nodep->fileline(), logp, clonep}; + break; + case VNType::atNeq: // FALLTHRU + case VNType::atNeqCase: + logp = new AstLogOr{nodep->fileline(), logp, clonep}; + break; + default: + nodep->v3fatalSrc("Unknown node type processing array slice"); + break; } } - UASSERT_OBJ(logp, nodep, "Unpacked array with empty indices range"); - nodep->replaceWith(logp); - VL_DO_DANGLING(pushDeletep(nodep), nodep); - nodep = logp; } + UASSERT_OBJ(logp, nodep, "Unpacked array with empty indices range"); + nodep->replaceWith(logp); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + nodep = logp; } - iterateChildren(nodep); } + iterateChildren(nodep); } void visit(AstEq* nodep) override { expandBiOp(nodep); } void visit(AstNeq* nodep) override { expandBiOp(nodep); } @@ -340,7 +358,9 @@ class SliceVisitor final : public VNVisitor { public: // CONSTRUCTORS explicit SliceVisitor(AstNetlist* nodep) { iterate(nodep); } - ~SliceVisitor() override = default; + ~SliceVisitor() override { + V3Stats::addStat("Optimizations, Slice array assignments", m_statAssigns); + } }; //###################################################################### diff --git a/src/V3Slice.h b/src/V3Slice.h index 14d2a8de0..b22bc37ee 100644 --- a/src/V3Slice.h +++ b/src/V3Slice.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 76c531644..fe0b48d89 100644 --- a/src/V3Split.cpp +++ b/src/V3Split.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 d0ef26847..d5de1edd4 100644 --- a/src/V3Split.h +++ b/src/V3Split.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 145e81a39..e0de302db 100644 --- a/src/V3SplitAs.cpp +++ b/src/V3SplitAs.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 3fe08466a..830a65567 100644 --- a/src/V3SplitAs.h +++ b/src/V3SplitAs.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 23847a076..26b2cd208 100644 --- a/src/V3SplitVar.cpp +++ b/src/V3SplitVar.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -186,7 +186,7 @@ struct SplitVarImpl VL_NOT_FINAL { static const char* cannotSplitPackedVarReason(const AstVar* varp); - template + template void insertBeginCore(T_ALWAYSLIKE* ap, AstNodeStmt* stmtp, AstNodeModule* modp) { if (ap->isJustOneBodyStmt() && ap->stmtsp() == stmtp) { stmtp->unlinkFrBack(); @@ -775,7 +775,7 @@ public: const std::pair dim = nodep->dtypep()->dimensions(false); UINFO(7, nodep->prettyNameQ() << " pub:" << nodep->isSigPublic() << " pri:" << nodep->isPrimaryIO() - << " io:" << nodep->isInoutish() << " typ:" << nodep->varType() << "\n"); + << " io:" << nodep->isInout() << " typ:" << nodep->varType() << "\n"); const char* reason = nullptr; // Public variable cannot be split. // at least one unpacked dimension must exist diff --git a/src/V3SplitVar.h b/src/V3SplitVar.h index 32128ebb6..6a3e25088 100644 --- a/src/V3SplitVar.h +++ b/src/V3SplitVar.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3StackCount.cpp b/src/V3StackCount.cpp index 19850cd27..23202acf9 100644 --- a/src/V3StackCount.cpp +++ b/src/V3StackCount.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3StackCount.h b/src/V3StackCount.h index 468a0d952..dad765c65 100644 --- a/src/V3StackCount.h +++ b/src/V3StackCount.h @@ -7,7 +7,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 0212d2816..76fdb92c6 100644 --- a/src/V3Stats.cpp +++ b/src/V3Stats.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2024 by Wilson Snyder. This program is free software; you +// Copyright 2005-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 a516df343..5ca56cc29 100644 --- a/src/V3Stats.h +++ b/src/V3Stats.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2024 by Wilson Snyder. This program is free software; you +// Copyright 2005-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 5aa2aa159..ec62aa3da 100644 --- a/src/V3StatsReport.cpp +++ b/src/V3StatsReport.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2024 by Wilson Snyder. This program is free software; you +// Copyright 2005-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3StdFuture.h b/src/V3StdFuture.h index 2e4d2f31b..67736d885 100644 --- a/src/V3StdFuture.h +++ b/src/V3StdFuture.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -22,7 +22,7 @@ namespace vlstd { // constexpr std::max with arguments passed by value (required by constexpr before C++14) -template +template constexpr T max(T a, T b) { return a > b ? a : b; } diff --git a/src/V3String.cpp b/src/V3String.cpp index d79a6ff58..61e180c16 100644 --- a/src/V3String.cpp +++ b/src/V3String.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -216,6 +216,13 @@ string VString::removeWhitespace(const string& str) { return result; } +bool VString::isIdentifier(const string& str) { + for (const char c : str) { + if (!isIdentifierChar(c)) return false; + } + return true; +} + bool VString::isWhitespace(const string& str) { for (const char c : str) { if (!std::isspace(c)) return false; @@ -256,8 +263,8 @@ string VString::replaceWord(const string& str, const string& from, const string& UASSERT_STATIC(len > 0, "Cannot replace empty string"); for (size_t pos = 0; (pos = result.find(from, pos)) != string::npos; pos += len) { // Only replace whole words - if (((pos > 0) && VString::isWordChar(result[pos - 1])) || // - ((pos + len < result.size()) && VString::isWordChar(result[pos + len]))) { + if (((pos > 0) && VString::isIdentifierChar(result[pos - 1])) || // + ((pos + len < result.size()) && VString::isIdentifierChar(result[pos + len]))) { continue; } result.replace(pos, len, to); diff --git a/src/V3String.h b/src/V3String.h index a69036cc9..db21577bd 100644 --- a/src/V3String.h +++ b/src/V3String.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,20 +33,20 @@ //###################################################################### // Global string-related functions -template +template std::string cvtToStr(const T& t) VL_PURE { std::ostringstream os; os << t; return os.str(); } -template +template typename std::enable_if::value, std::string>::type cvtToHex(const T tp) VL_PURE { std::ostringstream os; os << static_cast(tp); return os.str(); } -template +template typename std::enable_if::value, std::string>::type cvtToHex(const T t) { std::ostringstream os; os << std::hex << std::setw(sizeof(T) * 8 / 4) << std::setfill('0') << t; @@ -114,6 +114,10 @@ public: static string spaceUnprintable(const string& str) VL_PURE; // Remove any whitespace static string removeWhitespace(const string& str); + // Return true if only identifer or "" + static bool isIdentifier(const string& str); + // Return true if char is valid character in C identifiers + static bool isIdentifierChar(char c) { return isalnum(c) || c == '_'; } // Return true if only whitespace or "" static bool isWhitespace(const string& str); // Return number of spaces/tabs leading in string @@ -128,8 +132,6 @@ public: static bool startsWith(const string& str, const string& prefix); // Predicate to check if 'str' ends with 'suffix' static bool endsWith(const string& str, const string& suffix); - // Return true if char is valid character in word - static bool isWordChar(char c) { return isalnum(c) || c == '_'; } // Return proper article (a/an) for a word. May be inaccurate for some special words static string aOrAn(const char* word); static string aOrAn(const string& word) { return aOrAn(word.c_str()); } diff --git a/src/V3Subst.cpp b/src/V3Subst.cpp index 5b68583a9..049258a17 100644 --- a/src/V3Subst.cpp +++ b/src/V3Subst.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2024 by Wilson Snyder. This program is free software; you +// Copyright 2004-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 edf07151f..1e4b174da 100644 --- a/src/V3Subst.h +++ b/src/V3Subst.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 cc6940fe4..984df3d09 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 e027db84d..95b71a0ac 100644 --- a/src/V3TSP.cpp +++ b/src/V3TSP.cpp @@ -11,7 +11,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.h b/src/V3TSP.h index 37bfb8891..5bed130e6 100644 --- a/src/V3TSP.h +++ b/src/V3TSP.h @@ -7,7 +7,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 0c356dd38..62c4d7be9 100644 --- a/src/V3Table.cpp +++ b/src/V3Table.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -383,11 +383,9 @@ private: void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); VL_RESTORER(m_modTables); - { - m_modp = nodep; - m_modTables = 0; - iterateChildren(nodep); - } + m_modp = nodep; + m_modTables = 0; + iterateChildren(nodep); } void visit(AstScope* nodep) override { UINFO(4, " SCOPE " << nodep << endl); diff --git a/src/V3Table.h b/src/V3Table.h index c6d5a1123..d2cb81fa9 100644 --- a/src/V3Table.h +++ b/src/V3Table.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 460647692..0fe3624d3 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -30,6 +30,7 @@ #include "V3Const.h" #include "V3EmitCBase.h" #include "V3Graph.h" +#include "V3Stats.h" #include @@ -132,7 +133,9 @@ public: void remapFuncClassp(AstNodeFTask* nodep, AstNodeFTask* newp) { m_funcToClassMap[newp] = getClassp(nodep); } - bool ftaskNoInline(AstNodeFTask* nodep) { return getFTaskVertex(nodep)->noInline(); } + bool ftaskNoInline(AstNodeFTask* nodep) { + return !v3Global.opt.fInlineFuncs() || getFTaskVertex(nodep)->noInline(); + } AstCFunc* ftaskCFuncp(AstNodeFTask* nodep) { return getFTaskVertex(nodep)->cFuncp(); } void ftaskCFuncp(AstNodeFTask* nodep, AstCFunc* cfuncp) { getFTaskVertex(nodep)->cFuncp(cfuncp); @@ -217,20 +220,18 @@ private: } void visit(AstNodeFTask* nodep) override { UINFO(9, " TASK " << nodep << endl); - { - VL_RESTORER(m_curVxp); - m_curVxp = getFTaskVertex(nodep); - if (nodep->dpiImport()) m_curVxp->noInline(true); - if (nodep->classMethod()) m_curVxp->noInline(true); // Until V3Task supports it - if (nodep->recursive()) m_curVxp->noInline(true); - if (nodep->isConstructor()) { - m_curVxp->noInline(true); - m_ctorp = nodep; - UASSERT_OBJ(m_classp, nodep, "Ctor not under class"); - m_funcToClassMap[nodep] = m_classp; - } - iterateChildren(nodep); + VL_RESTORER(m_curVxp); + m_curVxp = getFTaskVertex(nodep); + if (nodep->dpiImport()) m_curVxp->noInline(true); + if (nodep->classMethod()) m_curVxp->noInline(true); // Until V3Task supports it + if (nodep->recursive()) m_curVxp->noInline(true); + if (nodep->isConstructor()) { + m_curVxp->noInline(true); + m_ctorp = nodep; + UASSERT_OBJ(m_classp, nodep, "Ctor not under class"); + m_funcToClassMap[nodep] = m_classp; } + iterateChildren(nodep); } void visit(AstPragma* nodep) override { if (nodep->pragType() == VPragmaType::NO_INLINE_TASK) { @@ -367,7 +368,10 @@ class TaskVisitor final : public VNVisitor { AstNode* m_insStmtp = nullptr; // Where to insert statement bool m_inSensesp = false; // Are we under a senitem? int m_modNCalls = 0; // Incrementing func # for making symbols + + // STATE - across all visitors DpiCFuncs m_dpiNames; // Map of all created DPI functions + VDouble0 m_statInlines; // Statistic tracking // METHODS @@ -517,7 +521,7 @@ class TaskVisitor final : public VNVisitor { pinp->v3fatalSrc("ref argument should have caused non-inline of function"); } } - } else if (portp->isInoutish()) { + } else if (portp->isInout()) { // if (debug() >= 9) pinp->dumpTree("-pinrsize- "); AstVarScope* const newvscp @@ -902,7 +906,7 @@ class TaskVisitor final : public VNVisitor { if (portp->isNonOutput()) { std::string frName - = portp->isInoutish() && portp->basicp()->isDpiPrimitive() + = portp->isInout() && portp->basicp()->isDpiPrimitive() && portp->dtypep()->skipRefp()->arrayUnpackedElements() == 1 ? "*" : ""; @@ -1393,10 +1397,8 @@ class TaskVisitor final : public VNVisitor { // scope then the caller, so we need to restore state. VL_RESTORER(m_scopep); VL_RESTORER(m_insStmtp); - { - m_scopep = m_statep->getScope(nodep); - iterate(nodep); - } + m_scopep = m_statep->getScope(nodep); + iterate(nodep); } void insertBeforeStmt(AstNode* nodep, AstNode* newp) { if (debug() >= 9) nodep->dumpTree("- newstmt: "); @@ -1409,12 +1411,10 @@ class TaskVisitor final : public VNVisitor { void visit(AstNodeModule* nodep) override { VL_RESTORER(m_modp); VL_RESTORER(m_modNCalls); - { - m_modp = nodep; - m_insStmtp = nullptr; - m_modNCalls = 0; - iterateChildren(nodep); - } + m_modp = nodep; + m_insStmtp = nullptr; + m_modNCalls = 0; + iterateChildren(nodep); } void visit(AstWith* nodep) override { if (nodep->user1SetOnce()) { @@ -1460,6 +1460,7 @@ class TaskVisitor final : public VNVisitor { beginp = createNonInlinedFTask(nodep, namePrefix, outvscp, cnewp /*ref*/); } else { beginp = createInlinedFTask(nodep, namePrefix, outvscp); + ++m_statInlines; } if (VN_IS(nodep, New)) { @@ -1612,7 +1613,7 @@ public: : m_statep{statep} { iterate(nodep); } - ~TaskVisitor() override = default; + ~TaskVisitor() { V3Stats::addStat("Optimizations, Functions inlined", m_statInlines); } }; //###################################################################### @@ -1848,16 +1849,13 @@ AstNodeFTask* V3Task::taskConnectWrapNew(AstNodeFTask* taskp, const string& newn newFVarp->name(newTaskp->name()); newTaskp->fvarp(newFVarp); newTaskp->dtypeFrom(newFVarp); - newCallp = new AstFuncRef{taskp->fileline(), taskp->name(), nullptr}; - newCallp->taskp(taskp); - newCallp->dtypeFrom(newFVarp); + newCallp = new AstFuncRef{taskp->fileline(), VN_AS(taskp, Func), nullptr}; newCallInsertp = new AstAssign{taskp->fileline(), new AstVarRef{fvarp->fileline(), newFVarp, VAccess::WRITE}, newCallp}; newCallInsertp->dtypeFrom(newFVarp); } else if (VN_IS(taskp, Task)) { - newCallp = new AstTaskRef{taskp->fileline(), taskp->name(), nullptr}; - newCallp->taskp(taskp); + newCallp = new AstTaskRef{taskp->fileline(), VN_AS(taskp, Task), nullptr}; newCallInsertp = new AstStmtExpr{taskp->fileline(), newCallp}; } else { taskp->v3fatalSrc("Unsupported: Non-constant default value in missing argument in a " diff --git a/src/V3Task.h b/src/V3Task.h index 5faf2aec4..af9c45a16 100644 --- a/src/V3Task.h +++ b/src/V3Task.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3ThreadPool.cpp b/src/V3ThreadPool.cpp index 576c9c86a..7730417ca 100644 --- a/src/V3ThreadPool.cpp +++ b/src/V3ThreadPool.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2005-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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/V3ThreadPool.h b/src/V3ThreadPool.h index a2365e6ac..0a385958a 100644 --- a/src/V3ThreadPool.h +++ b/src/V3ThreadPool.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2005-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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 ff0514d40..49298d7ad 100644 --- a/src/V3Timing.cpp +++ b/src/V3Timing.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -233,8 +233,8 @@ class TimingSuspendableVisitor final : public VNVisitor { if (passFlag(parentp, depp, flag)) propagateFlags(depVxp, flag); } } - template - void propagateFlagsIf(DepVtx* const vxp, NodeFlag flag, Predicate p) { + template + void propagateFlagsIf(DepVtx* const vxp, NodeFlag flag, T_Predicate p) { auto* const parentp = vxp->nodep(); for (V3GraphEdge& edge : vxp->outEdges()) { auto* const depVxp = static_cast(edge.top()); @@ -242,8 +242,8 @@ class TimingSuspendableVisitor final : public VNVisitor { if (p(&edge) && passFlag(parentp, depp, flag)) propagateFlagsIf(depVxp, flag, p); } } - template - void propagateFlagsReversedIf(DepVtx* const vxp, NodeFlag flag, Predicate p) { + template + void propagateFlagsReversedIf(DepVtx* const vxp, NodeFlag flag, T_Predicate p) { auto* const parentp = vxp->nodep(); for (V3GraphEdge& edge : vxp->inEdges()) { auto* const depVxp = static_cast(edge.fromp()); diff --git a/src/V3Timing.h b/src/V3Timing.h index f1704d3b1..97d5ccf0f 100644 --- a/src/V3Timing.h +++ b/src/V3Timing.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 6022bc377..e495693f0 100644 --- a/src/V3Trace.cpp +++ b/src/V3Trace.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -883,10 +883,8 @@ class TraceVisitor final : public VNVisitor { } } VL_RESTORER(m_cfuncp); - { - m_cfuncp = nodep; - iterateChildren(nodep); - } + m_cfuncp = nodep; + iterateChildren(nodep); } void visit(AstTraceDecl* nodep) override { UINFO(8, " TRACE " << nodep << endl); diff --git a/src/V3Trace.h b/src/V3Trace.h index 4dc831b33..73c6c9c8b 100644 --- a/src/V3Trace.h +++ b/src/V3Trace.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 181953f5f..a4a83c3d5 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.h b/src/V3TraceDecl.h index 013e625f8..39bdb9afb 100644 --- a/src/V3TraceDecl.h +++ b/src/V3TraceDecl.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 6663c879e..c8f39c26d 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -23,7 +23,7 @@ // Over each module, from child to parent: // Build a graph, connecting signals together so we can propagate tristates // Variable becomes tristate with -// VAR->isInoutish +// VAR->isInout // VAR->isPullup/isPulldown (converted to AstPullup/AstPulldown // BufIf0/1 // All variables on the LHS need to become tristate when there is: @@ -487,8 +487,9 @@ class TristateVisitor final : public TristateBaseVisitor { // Return the master __en for the specified input variable if (!invarp->user1p()) { AstVar* const newp - = new AstVar{invarp->fileline(), isTop ? VVarType::PORT : VVarType::MODULETEMP, + = new AstVar{invarp->fileline(), isTop ? VVarType::VAR : VVarType::MODULETEMP, invarp->name() + "__en", invarp}; + // Inherited VDirection::INPUT UINFO(9, " newenv " << newp << endl); modAddStmtp(invarp, newp); invarp->user1p(newp); // find envar given invarp @@ -540,8 +541,9 @@ class TristateVisitor final : public TristateBaseVisitor { // Return the master __out for the specified input variable if (!m_varAux(invarp).outVarp) { AstVar* const newp - = new AstVar{invarp->fileline(), isTop ? VVarType::PORT : VVarType::MODULETEMP, + = new AstVar{invarp->fileline(), isTop ? VVarType::VAR : VVarType::MODULETEMP, invarp->name() + "__out", invarp}; + // Inherited VDirection::OUTPUT UINFO(9, " newout " << newp << endl); modAddStmtp(invarp, newp); m_varAux(invarp).outVarp = newp; // find outvar given invarp @@ -1410,9 +1412,9 @@ class TristateVisitor final : public TristateBaseVisitor { } } void visitEqNeqWild(AstNodeBiop* nodep) { - if (!VN_IS(nodep->rhsp(), Const)) { - nodep->v3warn(E_UNSUPPORTED, // Says spac. - "Unsupported: RHS of ==? or !=? must be constant to be synthesizable"); + if (!VN_IS(nodep->rhsp(), Const) && nodep->rhsp()->dtypep()->isFourstate()) { + nodep->v3warn(E_UNSUPPORTED, + "Unsupported: RHS of ==? or !=? is fourstate but not a constant"); // rhs we want to keep X/Z intact, so otherwise ignore } iterateAndNextNull(nodep->lhsp()); @@ -1779,7 +1781,7 @@ class TristateVisitor final : public TristateBaseVisitor { nodep->addNextHere(newp); // We'll iterate on the new AstPull later } - if (nodep->isInoutish() + if (nodep->isInout() //|| varp->isOutput() // Note unconnected output only changes behavior vs. previous // versions and causes outputs that don't come from anywhere to diff --git a/src/V3Tristate.h b/src/V3Tristate.h index 791621668..98f48aaaa 100644 --- a/src/V3Tristate.h +++ b/src/V3Tristate.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 f89d1937a..542024cfe 100644 --- a/src/V3Undriven.cpp +++ b/src/V3Undriven.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2004-2024 by Wilson Snyder. This program is free software; you +// Copyright 2004-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -279,7 +279,7 @@ class UndrivenVisitor final : public VNVisitorConst { bool m_inContAssign = false; // In continuous assignment bool m_inProcAssign = false; // In procedural assignment bool m_inFTaskRef = false; // In function or task call - bool m_inInoutPin = false; // Connected to pin that is inout + bool m_inInoutOrRefPin = false; // Connected to pin that is inout const AstNodeFTask* m_taskp = nullptr; // Current task const AstAlways* m_alwaysCombp = nullptr; // Current always if combo, otherwise nullptr @@ -452,7 +452,7 @@ class UndrivenVisitor final : public VNVisitorConst { // Inouts have only isWrite set, as we don't have more // information and operating on module boundary, treat as // both read and writing - || m_inInoutPin) + || m_inInoutOrRefPin) entryp->usedWhole(); } } @@ -460,46 +460,36 @@ class UndrivenVisitor final : public VNVisitorConst { // Don't know what black boxed calls do, assume in+out void visit(AstSysIgnore* nodep) override { VL_RESTORER(m_inBBox); - { - m_inBBox = true; - iterateChildrenConst(nodep); - } + m_inBBox = true; + iterateChildrenConst(nodep); } void visit(AstAssign* nodep) override { VL_RESTORER(m_inProcAssign); - { - m_inProcAssign = true; - iterateChildrenConst(nodep); - } + m_inProcAssign = true; + iterateChildrenConst(nodep); } void visit(AstAssignDly* nodep) override { VL_RESTORER(m_inProcAssign); - { - m_inProcAssign = true; - iterateChildrenConst(nodep); - } + m_inProcAssign = true; + iterateChildrenConst(nodep); } void visit(AstAssignW* nodep) override { VL_RESTORER(m_inContAssign); - { - m_inContAssign = true; - iterateChildrenConst(nodep); - } + m_inContAssign = true; + iterateChildrenConst(nodep); } void visit(AstAlways* nodep) override { VL_RESTORER(m_alwaysCombp); - { - AstNode::user2ClearTree(); - if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) { - UINFO(9, " " << nodep << endl); - m_alwaysCombp = nodep; - } else { - m_alwaysCombp = nullptr; - } - iterateChildrenConst(nodep); - if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) UINFO(9, " Done " << nodep << endl); + AstNode::user2ClearTree(); + if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) { + UINFO(9, " " << nodep << endl); + m_alwaysCombp = nodep; + } else { + m_alwaysCombp = nullptr; } + iterateChildrenConst(nodep); + if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) UINFO(9, " Done " << nodep << endl); } void visit(AstNodeFTaskRef* nodep) override { VL_RESTORER(m_inFTaskRef); @@ -509,14 +499,12 @@ class UndrivenVisitor final : public VNVisitorConst { void visit(AstNodeFTask* nodep) override { VL_RESTORER(m_taskp); - { - m_taskp = nodep; - iterateChildrenConst(nodep); - } + m_taskp = nodep; + iterateChildrenConst(nodep); } void visit(AstPin* nodep) override { - VL_RESTORER(m_inInoutPin); - m_inInoutPin = nodep->modVarp()->isInoutish(); + VL_RESTORER(m_inInoutOrRefPin); + m_inInoutOrRefPin = nodep->modVarp()->isInoutOrRef(); iterateChildrenConst(nodep); } diff --git a/src/V3Undriven.h b/src/V3Undriven.h index 3dd1a6550..f086912fe 100644 --- a/src/V3Undriven.h +++ b/src/V3Undriven.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 92e97f154..41886942b 100644 --- a/src/V3UniqueNames.h +++ b/src/V3UniqueNames.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2005-2024 by Wilson Snyder. This program is free software; you +// Copyright 2005-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 13107c8a4..dd2683b76 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -99,7 +99,8 @@ class UnknownVisitor final : public VNVisitor { AstNodeExpr* prep = nodep; // Scan back to put the condlvalue above all selects (IE top of the lvalue) - while (VN_IS(prep->backp(), NodeSel) || VN_IS(prep->backp(), Sel)) { + while (VN_IS(prep->backp(), NodeSel) || VN_IS(prep->backp(), Sel) + || VN_IS(prep->backp(), StructSel)) { prep = VN_AS(prep->backp(), NodeExpr); } FileLine* const fl = nodep->fileline(); @@ -119,28 +120,7 @@ class UnknownVisitor final : public VNVisitor { = new AstVar{fl, VVarType::MODULETEMP, m_lvboundNames.get(prep), prep->dtypep()}; m_modp->addStmtsp(varp); AstNode* const abovep = prep->backp(); // Grab above point before we replace 'prep' - AstNode* currentStmtp = abovep; - while (currentStmtp && !VN_IS(currentStmtp, NodeStmt)) - currentStmtp = currentStmtp->backp(); - VNRelinker linkContext; - currentStmtp = currentStmtp->unlinkFrBackWithNext(&linkContext); - AstNodeExpr* const selExprp = prep->cloneTree(true); - AstNodeExpr* currentExprp = selExprp; - while (AstNodeExpr* itrSelExprp = VN_AS(currentExprp->op1p(), NodeExpr)) { - if (AstVarRef* const selRefp = VN_CAST(itrSelExprp, VarRef)) { - // Mark the variable reference as READ access to avoid assignment issues - selRefp->access(VAccess::READ); - break; - } - currentExprp = itrSelExprp; - } - // Before assigning the value to the temporary variable, first assign the current array - // element to it. This ensures any field modifications happen on the correct instance - // and prevents overwriting other fields. - AstNode* const newAssignp - = new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE}, selExprp}; - newAssignp->addNextStmt(currentStmtp, newAssignp); - linkContext.relink(newAssignp); + prep->replaceWith(new AstVarRef{fl, varp, VAccess::WRITE}); if (m_timingControlp) m_timingControlp->unlinkFrBack(); AstIf* const newp = new AstIf{ @@ -179,43 +159,33 @@ class UnknownVisitor final : public VNVisitor { void visit(AstAssignDly* nodep) override { VL_RESTORER(m_assigndlyp); VL_RESTORER(m_timingControlp); - { - m_assigndlyp = nodep; - m_timingControlp = nodep->timingControlp(); - VL_DO_DANGLING(iterateChildren(nodep), nodep); // May delete nodep. - } + m_assigndlyp = nodep; + m_timingControlp = nodep->timingControlp(); + VL_DO_DANGLING(iterateChildren(nodep), nodep); // May delete nodep. } void visit(AstAssignW* nodep) override { VL_RESTORER(m_assignwp); VL_RESTORER(m_timingControlp); - { - m_assignwp = nodep; - m_timingControlp = nodep->timingControlp(); - VL_DO_DANGLING(iterateChildren(nodep), nodep); // May delete nodep. - } + m_assignwp = nodep; + m_timingControlp = nodep->timingControlp(); + VL_DO_DANGLING(iterateChildren(nodep), nodep); // May delete nodep. } void visit(AstNodeAssign* nodep) override { VL_RESTORER(m_timingControlp); - { - m_timingControlp = nodep->timingControlp(); - iterateChildren(nodep); - } + m_timingControlp = nodep->timingControlp(); + iterateChildren(nodep); } void visit(AstCaseItem* nodep) override { VL_RESTORER(m_constXCvt); - { - m_constXCvt = false; // Avoid losing the X's in casex - iterateAndNextNull(nodep->condsp()); - m_constXCvt = true; - iterateAndNextNull(nodep->stmtsp()); - } + m_constXCvt = false; // Avoid losing the X's in casex + iterateAndNextNull(nodep->condsp()); + m_constXCvt = true; + iterateAndNextNull(nodep->stmtsp()); } void visit(AstNodeDType* nodep) override { VL_RESTORER(m_constXCvt); - { - m_constXCvt = false; // Avoid losing the X's in casex - iterateChildren(nodep); - } + m_constXCvt = false; // Avoid losing the X's in casex + iterateChildren(nodep); } void visit(AstVar* nodep) override { VL_RESTORER(m_allowXUnique); @@ -267,9 +237,11 @@ class UnknownVisitor final : public VNVisitor { AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack(); AstNodeExpr* newp; if (!VN_IS(rhsp, Const)) { - nodep->v3warn(E_UNSUPPORTED, "Unsupported: RHS of ==? or !=? must be " - "constant to be synthesizable"); // Says spec. - // Replace with anything that won't cause more errors + if (rhsp->dtypep()->isFourstate()) { + nodep->v3warn( + E_UNSUPPORTED, + "Unsupported: RHS of ==? or !=? is fourstate but not a constant"); + } newp = new AstEq{nodep->fileline(), lhsp, rhsp}; } else { // X or Z's become mask, ala case statements. diff --git a/src/V3Unknown.h b/src/V3Unknown.h index b5967f5a1..acc68773b 100644 --- a/src/V3Unknown.h +++ b/src/V3Unknown.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 6e5d55b7b..ac707874b 100644 --- a/src/V3Unroll.cpp +++ b/src/V3Unroll.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 f748171ca..50d51b86b 100644 --- a/src/V3Unroll.h +++ b/src/V3Unroll.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 0aad4a3d6..ea884cb17 100644 --- a/src/V3VariableOrder.cpp +++ b/src/V3VariableOrder.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 3816ca3a0..2963578a4 100644 --- a/src/V3VariableOrder.h +++ b/src/V3VariableOrder.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 bd4ad0883..c8d36bd26 100644 --- a/src/V3Waiver.cpp +++ b/src/V3Waiver.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2020-2024 by Wilson Snyder. This program is free software; you +// Copyright 2020-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,21 +19,59 @@ #include "V3Waiver.h" #include "V3File.h" +#include "V3Global.h" #include "V3Options.h" #include #include -void V3Waiver::addEntry(V3ErrorCode errorCode, const std::string& filename, const std::string& str) +void V3Waiver::addEntry(V3ErrorCode errorCode, const std::string& filename, const std::string& msg) VL_MT_SAFE_EXCLUDES(s_mutex) { if (filename == V3Options::getStdPackagePath()) return; + if (filename == V3Options::getStdWaiverPath()) return; const V3LockGuard lock{s_mutex}; + + string trimmsg = msg; + if (!v3Global.opt.waiverMultiline()) { + const size_t pos = trimmsg.find('\n'); + trimmsg = trimmsg.substr(0, pos); + if (pos != std::string::npos) trimmsg += '*'; + } + { // Remove line numbers and context "\n [0-9] | ", "\n ^[~]+" + string result; + for (const char* cp = trimmsg.c_str(); *cp; cp = *cp ? cp + 1 : cp) { + while (*cp == ' ' || isdigit(*cp)) ++cp; + if (*cp == '|') ++cp; + // ^~~~~ + while (*cp == ' ' || *cp == '^') ++cp; + while (*cp == '~') ++cp; + while (*cp && *cp != '\n') result += *cp++; + while (*cp == '\n') result += *cp++; + } + trimmsg = result; + } + trimmsg += '*'; + { // "\n"->"*", " *"->"*", "* "->"*" + string result; + string add; + result.reserve(trimmsg.size()); + for (const char& c : trimmsg) { + if (c == '*' || !std::isprint(c)) { + add = "*"; + } else if (c == ' ') { + if (add != "*") add += c; + } else { + result += add + c; + add = ""; + } + } + result += add; + trimmsg = result; + } + std::stringstream entry; - const size_t pos = str.find('\n'); entry << "lint_off -rule " << errorCode.ascii() << " -file \"*" << filename << "\" -match \"" - << str.substr(0, pos); - if (pos != std::string::npos) entry << "*"; - entry << "\""; + << trimmsg << "\""; s_waiverList.push_back(entry.str()); } @@ -46,9 +84,9 @@ void V3Waiver::write(const std::string& filename) VL_MT_SAFE_EXCLUDES(s_mutex) { *ofp << "`verilator_config\n\n"; - *ofp << "// Below you find suggested waivers. You have three options:\n"; - *ofp << "// 1. Fix the reason for the linter warning\n"; - *ofp << "// 2. Keep the waiver permanently if you are sure this is okay\n"; + *ofp << "// Below are suggested waivers. You have three options:\n"; + *ofp << "// 1. Fix the reason for the linter warning in the Verilog sources\n"; + *ofp << "// 2. Keep the waiver permanently if you are sure it is okay\n"; *ofp << "// 3. Keep the waiver temporarily to suppress the output\n\n"; const V3LockGuard lock{s_mutex}; diff --git a/src/V3Waiver.h b/src/V3Waiver.h index 8ccc1f8e9..1302ac1de 100644 --- a/src/V3Waiver.h +++ b/src/V3Waiver.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -30,7 +30,7 @@ class V3Waiver final { static WaiverList s_waiverList VL_GUARDED_BY(s_mutex); public: - static void addEntry(V3ErrorCode errorCode, const string& filename, const std::string& str) + static void addEntry(V3ErrorCode errorCode, const string& filename, const std::string& msg) VL_MT_SAFE_EXCLUDES(s_mutex); static void write(const std::string& filename) VL_MT_SAFE_EXCLUDES(s_mutex); }; diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 1f7c25235..969209609 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -573,7 +573,6 @@ class WidthVisitor final : public VNVisitor { // to determine if value or push userIterateAndNext(nodep->lhsp(), WidthVP{vdtypep, PRELIM}.p()); userIterateAndNext(nodep->rhsp(), WidthVP{vdtypep, PRELIM}.p()); - // Queue "element 0" is lhsp, so we need to swap arguments const bool lhsIsValue = AstNode::computeCastable(adtypep->subDTypep(), nodep->lhsp()->dtypep(), nullptr) .isAssignable(); @@ -670,6 +669,11 @@ class WidthVisitor final : public VNVisitor { } } } + void visit(AstDefaultDisable* nodep) override { + assertAtStatement(nodep); + // it's like an if() condition. + iterateCheckBool(nodep, "default disable iff condition", nodep->condp(), BOTH); + } void visit(AstDelay* nodep) override { if (VN_IS(m_procedurep, Final)) { nodep->v3error("Delays are not legal in final blocks (IEEE 1800-2023 9.2.3)"); @@ -1391,6 +1395,9 @@ class WidthVisitor final : public VNVisitor { // queue_slice[#:$] and queue_bitsel[$] etc handled in V3WidthSel nodep->v3warn(E_UNSUPPORTED, "Unsupported/illegal unbounded ('$') in this context."); } + void visit(AstInferredDisable* nodep) override { + if (m_vup->prelim()) nodep->dtypeSetBit(); + } void visit(AstIsUnbounded* nodep) override { if (m_vup->prelim()) { userIterateAndNext(nodep->lhsp(), WidthVP{SELF, BOTH}.p()); @@ -2346,6 +2353,13 @@ class WidthVisitor final : public VNVisitor { UINFO(5, " ENUMDTYPE " << nodep << endl); nodep->refDTypep(iterateEditMoveDTypep(nodep, nodep->subDTypep())); nodep->dtypep(nodep); + AstBasicDType* basicp = nodep->dtypep()->skipRefp()->basicp(); + if (!basicp || !basicp->keyword().isIntNumeric()) { + nodep->v3error( + "Enum type must be an integer atom or vector type (IEEE 1800-2023 6.19)"); + basicp = nodep->findSigned32DType()->basicp(); + nodep->refDTypep(basicp); + } nodep->widthFromSub(nodep->subDTypep()); // Assign widths userIterateAndNext(nodep->itemsp(), WidthVP{nodep->dtypep(), BOTH}.p()); @@ -2376,17 +2390,11 @@ class WidthVisitor final : public VNVisitor { itemp->v3error("Enum value that is unassigned cannot follow value with X/Zs " "(IEEE 1800-2023 6.19)"); } - if (!nodep->dtypep()->basicp() - && !nodep->dtypep()->basicp()->keyword().isIntNumeric()) { - itemp->v3error("Enum names without values only allowed on numeric types"); - // as can't +1 to resolve them. - } itemp->valuep(new AstConst{itemp->fileline(), num}); } const AstConst* const constp = VN_AS(itemp->valuep(), Const); - if (constp->num().isFourState() && nodep->dtypep()->basicp() - && !nodep->dtypep()->basicp()->isFourstate()) { + if (constp->num().isFourState() && basicp->basicp() && !basicp->isFourstate()) { itemp->v3error("Enum value with X/Zs cannot be assigned to non-fourstate type " "(IEEE 1800-2023 6.19)"); } @@ -2662,33 +2670,37 @@ class WidthVisitor final : public VNVisitor { } AstBasicDType* dtype = VN_CAST(nodep->exprp()->dtypep(), BasicDType); - AstNodeDType* subDTypep = nullptr; + AstNodeDType* expDTypep = nullptr; if (dtype && dtype->isString()) { nodep->dtypeSetString(); - subDTypep = nodep->findStringDType(); + expDTypep = nodep->findStringDType(); } else if (dtype && dtype->isDouble()) { nodep->dtypeSetDouble(); - subDTypep = nodep->findDoubleDType(); + expDTypep = nodep->findDoubleDType(); } else { // Take width as maximum across all items int width = nodep->exprp()->width(); int mwidth = nodep->exprp()->widthMin(); + bool isFourstate = nodep->exprp()->dtypep()->isFourstate(); for (const AstNode* itemp = nodep->itemsp(); itemp; itemp = itemp->nextp()) { width = std::max(width, itemp->width()); mwidth = std::max(mwidth, itemp->widthMin()); + isFourstate |= itemp->dtypep()->isFourstate(); } nodep->dtypeSetBit(); - subDTypep = nodep->findLogicDType(width, mwidth, nodep->exprp()->dtypep()->numeric()); + const VSigning numeric = nodep->exprp()->dtypep()->numeric(); + expDTypep = isFourstate ? nodep->findLogicDType(width, mwidth, numeric) + : nodep->findBitDType(width, mwidth, numeric); } - iterateCheck(nodep, "Inside expression", nodep->exprp(), CONTEXT_DET, FINAL, subDTypep, + iterateCheck(nodep, "Inside expression", nodep->exprp(), CONTEXT_DET, FINAL, expDTypep, EXTEND_EXP); for (AstNode *nextip, *itemp = nodep->itemsp(); itemp; itemp = nextip) { nextip = itemp->nextp(); // iterate may cause the node to get replaced // InsideRange will get replaced with Lte&Gte and finalized later if (!VN_IS(itemp, InsideRange)) - iterateCheck(nodep, "Inside Item", itemp, CONTEXT_DET, FINAL, subDTypep, + iterateCheck(nodep, "Inside Item", itemp, CONTEXT_DET, FINAL, expDTypep, EXTEND_EXP); } @@ -3128,7 +3140,9 @@ class WidthVisitor final : public VNVisitor { // Any AstWith is checked later when know types, in methodWithArgument for (AstNode* pinp = nodep->pinsp(); pinp; pinp = pinp->nextp()) { if (AstArg* const argp = VN_CAST(pinp, Arg)) { - if (argp->exprp()) userIterate(argp->exprp(), WidthVP{SELF, BOTH}.p()); + if (argp->exprp()) + userIterate(argp->exprp(), + WidthVP{nodep->fromp()->dtypep()->subDTypep(), BOTH}.p()); } } // Find the fromp dtype - should be a class @@ -3778,11 +3792,10 @@ class WidthVisitor final : public VNVisitor { if (nodep->pinsp()) argsp = nodep->pinsp()->unlinkFrBackWithNext(); AstNodeFTaskRef* newp = nullptr; if (VN_IS(ftaskp, Task)) { - newp = new AstTaskRef{nodep->fileline(), ftaskp->name(), argsp}; + newp = new AstTaskRef{nodep->fileline(), VN_AS(ftaskp, Task), argsp}; } else { - newp = new AstFuncRef{nodep->fileline(), ftaskp->name(), argsp}; + newp = new AstFuncRef{nodep->fileline(), VN_AS(ftaskp, Func), argsp}; } - newp->taskp(ftaskp); newp->classOrPackagep(ifacep); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); @@ -3917,11 +3930,10 @@ class WidthVisitor final : public VNVisitor { if (nodep->pinsp()) argsp = nodep->pinsp()->unlinkFrBackWithNext(); AstNodeFTaskRef* newp = nullptr; if (VN_IS(ftaskp, Task)) { - newp = new AstTaskRef{nodep->fileline(), ftaskp->name(), argsp}; + newp = new AstTaskRef{nodep->fileline(), VN_AS(ftaskp, Task), argsp}; } else { - newp = new AstFuncRef{nodep->fileline(), ftaskp->name(), argsp}; + newp = new AstFuncRef{nodep->fileline(), VN_AS(ftaskp, Func), argsp}; } - newp->taskp(ftaskp); newp->classOrPackagep(classp); nodep->replaceWith(newp); VL_DO_DANGLING(nodep->deleteTree(), nodep); @@ -4526,6 +4538,7 @@ class WidthVisitor final : public VNVisitor { UINFO(9, "ent " << range.left() << " to " << range.right() << endl); AstNode* newp = nullptr; bool allConstant = true; + const bool isConcat = nodep->itemsp() && VN_AS(nodep->itemsp(), PatMember)->isConcat(); for (int entn = 0, ent = range.left(); entn < range.elements(); ++entn, ent += range.leftToRightInc()) { AstPatMember* newpatp = nullptr; @@ -4535,10 +4548,10 @@ class WidthVisitor final : public VNVisitor { if (defaultp) { newpatp = defaultp->cloneTree(false); patp = newpatp; - } else if (!(VN_IS(arrayDtp, UnpackArrayDType) && !allConstant)) { + } else if (!(VN_IS(arrayDtp, UnpackArrayDType) && !allConstant && isConcat)) { // If arrayDtp is an unpacked array and item is not constant, - // the number of elemnt cannot be determined here as the dtype of each element - // is not set yet. V3Slice checks for such cases. + // the number of elements cannot be determined here as the dtype of each + // element is not set yet. V3Slice checks for such cases. nodep->v3error("Assignment pattern missed initializing elements: " << ent); } } else { @@ -6130,6 +6143,15 @@ class WidthVisitor final : public VNVisitor { if (v3Global.opt.timing().isSetTrue()) { iterateCheckBool(nodep, "Wait", nodep->condp(), BOTH); // it's like an if() condition. + // TODO check also inside complex event expressions + if (AstNodeVarRef* const varrefp = VN_CAST(nodep->condp(), NodeVarRef)) { + if (varrefp->isEvent()) { + varrefp->v3error("Wait statement conditions do not take raw events" + " (IEEE 1800-2023 15.5.3)\n" + << varrefp->warnMore() << "... Suggest use '" + << varrefp->prettyName() << ".triggered'"); + } + } iterateNull(nodep->stmtsp()); return; } else if (v3Global.opt.timing().isSetFalse()) { @@ -6848,7 +6870,7 @@ class WidthVisitor final : public VNVisitor { return false; } void checkClassAssign(AstNode* nodep, const char* side, AstNode* rhsp, - const AstNodeDType* const lhsDTypep) { + AstNodeDType* const lhsDTypep) { if (AstClassRefDType* const lhsClassRefp = VN_CAST(lhsDTypep->skipRefp(), ClassRefDType)) { UASSERT_OBJ(rhsp->dtypep(), rhsp, "Node has no type"); AstNodeDType* const rhsDtypep = rhsp->dtypep()->skipRefp(); @@ -7812,8 +7834,11 @@ class WidthVisitor final : public VNVisitor { for (AstPatMember* patp = VN_AS(nodep->itemsp(), PatMember); patp; patp = VN_AS(patp->nextp(), PatMember)) { if (patp->keyp()) { + if (patp->varrefp()) V3Const::constifyParamsEdit(patp->varrefp()); if (const AstConst* const constp = VN_CAST(patp->keyp(), Const)) { element = constp->toSInt(); + } else if (const AstConst* const constp = VN_CAST(patp->varrefp(), Const)) { + element = constp->toSInt(); } else { patp->keyp()->v3error("Assignment pattern key not supported/understood: " << patp->keyp()->prettyTypeName()); @@ -7832,14 +7857,18 @@ class WidthVisitor final : public VNVisitor { if (AstConcat* lhsp = VN_CAST(nodep->lhsp(), Concat)) { patConcatConvertRecurse(patternp, lhsp); } else { - patternp->addItemsp(new AstPatMember{nodep->lhsp()->fileline(), - nodep->lhsp()->unlinkFrBack(), nullptr, nullptr}); + AstPatMember* const newp = new AstPatMember{ + nodep->lhsp()->fileline(), nodep->lhsp()->unlinkFrBack(), nullptr, nullptr}; + newp->isConcat(true); + patternp->addItemsp(newp); } if (AstConcat* rhsp = VN_CAST(nodep->rhsp(), Concat)) { patConcatConvertRecurse(patternp, rhsp); } else { - patternp->addItemsp(new AstPatMember{nodep->rhsp()->fileline(), - nodep->rhsp()->unlinkFrBack(), nullptr, nullptr}); + AstPatMember* const newp = new AstPatMember{ + nodep->rhsp()->fileline(), nodep->rhsp()->unlinkFrBack(), nullptr, nullptr}; + newp->isConcat(true); + patternp->addItemsp(newp); } } @@ -7951,36 +7980,28 @@ class WidthVisitor final : public VNVisitor { } void userIterate(AstNode* nodep, WidthVP* vup) { if (!nodep) return; - { - VL_RESTORER(m_vup); - m_vup = vup; - iterate(nodep); - } + VL_RESTORER(m_vup); + m_vup = vup; + iterate(nodep); } void userIterateAndNext(AstNode* nodep, WidthVP* vup) { if (!nodep) return; if (nodep->didWidth()) return; // Avoid iterating list we have already iterated - { - VL_RESTORER(m_vup); - m_vup = vup; - iterateAndNextNull(nodep); - } + VL_RESTORER(m_vup); + m_vup = vup; + iterateAndNextNull(nodep); } void userIterateChildren(AstNode* nodep, WidthVP* vup) { if (!nodep) return; - { - VL_RESTORER(m_vup); - m_vup = vup; - iterateChildren(nodep); - } + VL_RESTORER(m_vup); + m_vup = vup; + iterateChildren(nodep); } void userIterateChildrenBackwardsConst(AstNode* nodep, WidthVP* vup) { if (!nodep) return; - { - VL_RESTORER(m_vup); - m_vup = vup; - iterateChildrenBackwardsConst(nodep); - } + VL_RESTORER(m_vup); + m_vup = vup; + iterateChildrenBackwardsConst(nodep); } public: diff --git a/src/V3Width.h b/src/V3Width.h index f7aa836bc..88eb86c2a 100644 --- a/src/V3Width.h +++ b/src/V3Width.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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.cpp b/src/V3WidthCommit.cpp index 1c9e1640f..5050fda8d 100644 --- a/src/V3WidthCommit.cpp +++ b/src/V3WidthCommit.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -162,6 +162,18 @@ private: nodep->replaceWith(nodep->lhsp()->unlinkFrBack()); VL_DO_DANGLING(pushDeletep(nodep), nodep); } + void visit(AstConstraint* nodep) override { + iterateChildren(nodep); + editDType(nodep); + { + const AstClass* const classp = VN_CAST(m_modp, Class); + if (nodep->isKwdPure() + && (!classp || (!classp->isInterfaceClass() && !classp->isVirtual()))) { + nodep->v3error("Illegal to have 'pure constraint' in non-abstract class" + " (IEEE 1800-2023 18.5.2)"); + } + } + } void visit(AstNodeDType* nodep) override { // Note some specific dtypes have unique visitors visitIterateNodeDType(nodep); diff --git a/src/V3WidthCommit.h b/src/V3WidthCommit.h index b8c963d13..c2b124f0e 100644 --- a/src/V3WidthCommit.h +++ b/src/V3WidthCommit.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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/V3WidthRemove.h b/src/V3WidthRemove.h index 7c9a6a8a9..b879058f6 100644 --- a/src/V3WidthRemove.h +++ b/src/V3WidthRemove.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 1ebfa828a..7073cf8d4 100644 --- a/src/V3WidthSel.cpp +++ b/src/V3WidthSel.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 d6b58ea9c..002994745 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/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,6 +53,7 @@ #include "V3File.h" #include "V3Force.h" #include "V3Fork.h" +#include "V3FuncOpt.h" #include "V3Gate.h" #include "V3Global.h" #include "V3Graph.h" @@ -497,6 +498,9 @@ static void process() { // --GENERATION------------------ if (!v3Global.opt.serializeOnly()) { + // Generic optimizations on a per-function basis + if (v3Global.opt.fFunc()) V3FuncOpt::funcOptAll(v3Global.rootp()); + // Remove unused vars V3Const::constifyAll(v3Global.rootp()); V3Dead::deadifyAll(v3Global.rootp()); diff --git a/src/VlcBucket.h b/src/VlcBucket.h index 0f2697db0..203d86290 100644 --- a/src/VlcBucket.h +++ b/src/VlcBucket.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 89b592a2d..fbabc9b07 100644 --- a/src/VlcMain.cpp +++ b/src/VlcMain.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -107,7 +107,7 @@ void VlcOptions::showVersion(bool verbose) { if (!verbose) return; std::cout << "\n"; - std::cout << "Copyright 2003-2024 by Wilson Snyder. Verilator is free software; you can\n"; + std::cout << "Copyright 2003-2025 by Wilson Snyder. Verilator is free software; you can\n"; std::cout << "redistribute it and/or modify the Verilator internals under the terms of\n"; std::cout << "either the GNU Lesser General Public License Version 3 or the Perl Artistic\n"; std::cout << "License Version 2.0.\n"; diff --git a/src/VlcOptions.h b/src/VlcOptions.h index 02671951d..edd889957 100644 --- a/src/VlcOptions.h +++ b/src/VlcOptions.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 aeb326fca..afb546f46 100644 --- a/src/VlcPoint.h +++ b/src/VlcPoint.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -63,6 +63,7 @@ public: // KEY ACCESSORS string filename() const { return keyExtract(VL_CIK_FILENAME); } string comment() const { return keyExtract(VL_CIK_COMMENT); } + string hier() const { return keyExtract(VL_CIK_HIER); } string type() const { return keyExtract(VL_CIK_TYPE); } string thresh() const { return keyExtract(VL_CIK_THRESH); } // string as maybe "" string linescov() const { return keyExtract(VL_CIK_LINESCOV); } @@ -98,7 +99,7 @@ public: void dumpAnnotate(std::ostream& os, unsigned annotateMin) const { os << (ok(annotateMin) ? "+" : "-"); os << std::setw(6) << std::setfill('0') << count(); - os << " point: comment=" << comment(); + os << " point: comment=" << comment() << " hier=" << hier(); os << "\n"; } }; diff --git a/src/VlcSource.h b/src/VlcSource.h index 35a99a065..8e00667a1 100644 --- a/src/VlcSource.h +++ b/src/VlcSource.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 a9ca1d8a3..32de7d662 100644 --- a/src/VlcTest.h +++ b/src/VlcTest.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 55a5753e7..adedf4425 100644 --- a/src/VlcTop.cpp +++ b/src/VlcTop.cpp @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 d48568bd5..b0f3dc5a9 100644 --- a/src/VlcTop.h +++ b/src/VlcTop.h @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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 238216720..215364a28 100755 --- a/src/astgen +++ b/src/astgen @@ -1254,7 +1254,7 @@ parser = argparse.ArgumentParser( allow_abbrev=False, formatter_class=argparse.RawDescriptionHelpFormatter, description="""Generate V3Ast headers to reduce C++ code duplication.""", - epilog="""Copyright 2002-2024 by Wilson Snyder. This program is free software; you + epilog="""Copyright 2002-2025 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it 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 8c505c312..21bffd544 100755 --- a/src/bisonpre +++ b/src/bisonpre @@ -485,7 +485,7 @@ BISON GRAMMAR EXTENSIONS If the bison version is >= the specified version, include the given command. -Copyright 2002-2024 by Wilson Snyder. This program is free software; you +Copyright 2002-2025 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it 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 b/src/config_build.h index e842f0444..74ebf4029 100644 --- a/src/config_build.h +++ b/src/config_build.h @@ -8,7 +8,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it 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_package.h.in b/src/config_package.h.in index 663244ce3..7a7088a82 100644 --- a/src/config_package.h.in +++ b/src/config_package.h.in @@ -6,7 +6,7 @@ // // Code available from: https://verilator.org // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; +// Copyright 2003-2025 by Wilson Snyder. This program is free software; // you can redistribute it and/or modify it 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 bbbcf9b3f..3d187ba59 100755 --- a/src/config_rev +++ b/src/config_rev @@ -2,7 +2,7 @@ # pylint: disable=C0103,C0114 ###################################################################### # -# Copyright 2005-2024 by Wilson Snyder. This program is free software; you +# Copyright 2005-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it 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 894c1aad7..ccf633938 100755 --- a/src/cppcheck_filtered +++ b/src/cppcheck_filtered @@ -177,7 +177,7 @@ filters out unnecessary warnings related to Verilator. Run as: cd $VERILATOR_ROOT make -k cppcheck""", - epilog="""Copyright 2014-2024 by Wilson Snyder. This program is free software; you + epilog="""Copyright 2014-2025 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it 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 13abaec70..a6479b8e1 100755 --- a/src/flexfix +++ b/src/flexfix @@ -2,7 +2,7 @@ # pylint: disable=C0114,C0301 ###################################################################### # -# Copyright 2002-2024 by Wilson Snyder. This program is free software; you +# Copyright 2002-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it 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 7c11ebc67..b1a536557 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -6,7 +6,7 @@ * ************************************************************************** * - * Copyright 2003-2024 by Wilson Snyder. Verilator is free software; you + * Copyright 2003-2025 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. @@ -137,6 +137,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "tracing_on" { FL; return yVLT_TRACING_ON; } -?"-block" { FL; return yVLT_D_BLOCK; } + -?"-contents" { FL; return yVLT_D_CONTENTS; } -?"-cost" { FL; return yVLT_D_COST; } -?"-file" { FL; return yVLT_D_FILE; } -?"-function" { FL; return yVLT_D_FUNCTION; } @@ -473,6 +474,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5} "$fell_gclk" { FL; return yD_FELL_GCLK; } "$high" { FL; return yD_HIGH; } "$increment" { FL; return yD_INCREMENT; } + "$inferred_disable" { FL; return yD_INFERRED_DISABLE; } "$info" { FL; return yD_INFO; } "$isunbounded" { FL; return yD_ISUNBOUNDED; } "$isunknown" { FL; return yD_ISUNKNOWN; } diff --git a/src/verilog.y b/src/verilog.y index 9fbf16bde..08ac1a969 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -6,7 +6,7 @@ // //************************************************************************* // -// Copyright 2003-2024 by Wilson Snyder. This program is free software; you +// Copyright 2003-2025 by Wilson Snyder. This program is free software; you // can redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -89,8 +89,8 @@ public: FileLine* m_instModuleFl = nullptr; // Fileline of module referenced for instantiations AstPin* m_instParamp = nullptr; // Parameters for instantiations string m_instModule; // Name of module referenced for instantiations - VVarType m_varDecl; // Type for next signal declaration (reg/wire/etc) - VDirection m_varIO; // Direction for next signal declaration (reg/wire/etc) + VVarType m_varDecl = VVarType::UNKNOWN; // Type for next signal declaration (reg/wire/etc) + VDirection m_varIO = VDirection::NONE; // Direction for next signal declaration (reg/wire/etc) VLifetime m_varLifetime; // Static/Automatic for next signal bool m_impliedDecl = false; // Allow implied wire declarations bool m_varDeclTyped = false; // Var got reg/wire for dedup check @@ -110,10 +110,7 @@ public: static int s_modTypeImpNum; // Implicit type number, incremented each module // CONSTRUCTORS - V3ParseGrammar() { - m_varDecl = VVarType::UNKNOWN; - m_varIO = VDirection::NONE; - } + V3ParseGrammar() {} static V3ParseGrammar* singletonp() { static V3ParseGrammar singleton; return &singleton; @@ -135,21 +132,9 @@ public: string newtext = GRAMMARP->unquoteString(fileline, text); return new AstText{fileline, newtext}; } - AstNode* createCellOrIfaceRef(FileLine* fileline, const string& name, AstPin* pinlistp, - AstNodeRange* rangelistp, bool parens) { + AstNode* createCell(FileLine* fileline, const string& name, AstPin* pinlistp, + AstNodeRange* rangelistp) { // Must clone m_instParamp as may be comma'ed list of instances - VSymEnt* const foundp = SYMP->symCurrentp()->findIdFallback(name); - if (foundp && VN_IS(foundp->nodep(), Port)) { - // It's a non-ANSI interface, not a cell declaration - m_varAttrp = nullptr; - m_varDecl = VVarType::IFACEREF; - m_varIO = VDirection::NONE; - m_varLifetime = VLifetime::NONE; - setDType(new AstIfaceRefDType{fileline, "", GRAMMARP->m_instModule}); - m_varDeclTyped = true; - AstVar* const nodep = createVariable(fileline, name, rangelistp, nullptr); - return nodep; - } AstCell* const nodep = new AstCell{ fileline, GRAMMARP->m_instModuleFl, @@ -158,7 +143,6 @@ public: pinlistp, (GRAMMARP->m_instParamp ? GRAMMARP->m_instParamp->cloneTree(true) : nullptr), GRAMMARP->scrubRange(rangelistp)}; - nodep->hasNoParens(!parens); nodep->trace(GRAMMARP->allTracingOn(fileline)); return nodep; } @@ -184,6 +168,14 @@ public: AstSenTree* createGlobalClockSenTree(FileLine* fl) { return createClockSenTree(fl, createGlobalClockParseRef(fl)); } + AstNode* createNettype(FileLine* fl, const string& name) { + // As nettypes are unsupported, we just alias to logic + AstTypedef* const nodep = new AstTypedef{fl, name, nullptr, VFlagChildDType{}, + new AstBasicDType{fl, VFlagLogicPacked{}, 1}}; + SYMP->reinsert(nodep); + PARSEP->tagNodep(nodep); + return nodep; + } AstNode* createTypedef(FileLine* fl, const string& name, AstNode* attrsp, AstNodeDType* basep, AstNodeRange* rangep) { AstTypedef* const nodep = new AstTypedef{fl, name, attrsp, VFlagChildDType{}, @@ -208,7 +200,6 @@ public: << name << "'"); } } - void setVarDecl(VVarType type) { m_varDecl = type; } void setDType(AstNodeDType* dtypep) { if (m_varDTypep) VL_DO_CLEAR(m_varDTypep->deleteTree(), m_varDTypep = nullptr); m_varDTypep = dtypep; @@ -317,30 +308,26 @@ int V3ParseGrammar::s_modTypeImpNum = 0; #define CRELINE() (PARSEP->bisonLastFileline()->copyOrSameFileLineApplied()) #define FILELINE_OR_CRE(nodep) ((nodep) ? (nodep)->fileline() : CRELINE()) -#define VARRESET_LIST(decl) \ +#define VARRESET_LIST(decl) VARRESET__PVT(decl, 1) // Start of pinlist +#define VARRESET_NONLIST(decl) VARRESET__PVT(decl, 0); // Not in a pinlist +#define VARRESET__PVT(decl, pinNumStart) \ { \ - GRAMMARP->m_pinNum = 1; \ - VARRESET(); \ VARDECL(decl); \ - } // Start of pinlist -#define VARRESET_NONLIST(decl) \ - { \ - GRAMMARP->m_pinNum = 0; \ - VARRESET(); \ - VARDECL(decl); \ - } // Not in a pinlist -#define VARRESET() \ - { \ - VARDECL(UNKNOWN); \ VARIO(NONE); \ VARDTYPE_NDECL(nullptr); \ + GRAMMARP->m_pinNum = (pinNumStart); \ GRAMMARP->m_varLifetime = VLifetime::NONE; \ GRAMMARP->m_varDeclTyped = false; \ } #define VARDECL(type) \ - { GRAMMARP->setVarDecl(VVarType::type); } + { GRAMMARP->m_varDecl = VVarType::type; } #define VARIO(type) \ { GRAMMARP->m_varIO = VDirection::type; } +// Set direction to default-input when detect inside an ANSI port list +#define VARIOANSI(type) \ + { \ + if (GRAMMARP->m_varIO == VDirection::NONE) VARIO(INPUT); \ + } #define VARLIFE(flag) \ { GRAMMARP->m_varLifetime = flag; } #define VARDTYPE(dtypep) \ @@ -442,7 +429,8 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) %token yaID__ETC "IDENTIFIER" %token yaID__CC "IDENTIFIER-::" %token yaID__LEX "IDENTIFIER-in-lex" -%token yaID__aTYPE "TYPE-IDENTIFIER" +%token yaID__aCELL "IDENTIFIER-for-cell" +%token yaID__aTYPE "IDENTIFIER-for-type" // Can't predecode aFUNCTION, can declare after use // Can't predecode aINTERFACE, can declare after use // Can't predecode aTASK, can declare after use @@ -499,6 +487,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) %token yVLT_TRACING_ON "tracing_on" %token yVLT_D_BLOCK "--block" +%token yVLT_D_CONTENTS "--contents" %token yVLT_D_COST "--cost" %token yVLT_D_FILE "--file" %token yVLT_D_FUNCTION "--function" @@ -891,6 +880,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"}) %token yD_HIGH "$high" %token yD_HYPOT "$hypot" %token yD_INCREMENT "$increment" +%token yD_INFERRED_DISABLE "$inferred_disable" %token yD_INFO "$info" %token yD_ISUNBOUNDED "$isunbounded" %token yD_ISUNKNOWN "$isunknown" @@ -1425,6 +1415,7 @@ parameter_value_assignmentClassE: // IEEE: [ parameter_value_assignme parameter_value_assignmentInst: // IEEE: parameter_value_assignment for instance '#' '(' cellparamListE ')' { $$ = $3; } // // Parentheses are optional around a single parameter + // // IMPORTANT: Below hardcoded in tokenPipeScanParam | '#' yaINTNUM { $$ = new AstPin{$2, 1, "", new AstConst{$2, *$2}}; } | '#' yaFLOATNUM { $$ = new AstPin{$2, 1, "", new AstConst{$2, AstConst::RealDouble{}, $2}}; } @@ -1435,7 +1426,7 @@ parameter_value_assignmentInst: // IEEE: parameter_value_assignment // // '#' delay_value { UNSUP } ; -parameter_value_assignmentClass: // IEEE: [ parameter_value_assignment ] (for classes) +parameter_value_assignmentClass: // IEEE: parameter_value_assignment (for classes) // // Like parameter_value_assignment, but for classes only, which always have #() '#' '(' cellparamListE ')' { $$ = $3; } ; @@ -1479,13 +1470,13 @@ portsStarE: // IEEE: .* + list_of_ports + list_of_port_decla | '(' ')' { $$ = nullptr; } // // .* expanded from module_declaration //UNSUP '(' yP_DOTSTAR ')' { UNSUP } - | '(' { VARRESET_LIST(PORT); - GRAMMARP->m_pinAnsi = true; } - /*cont*/ list_of_ports ')' { $$ = $3; VARRESET_NONLIST(UNKNOWN); - GRAMMARP->m_pinAnsi = false; } + | '(' + /*mid*/ { VARRESET_LIST(PORT); GRAMMARP->m_pinAnsi = true; } + /*cont*/ list_of_ports ')' + { $$ = $3; VARRESET_NONLIST(UNKNOWN); GRAMMARP->m_pinAnsi = false; } ; -list_of_portsE: // IEEE: list_of_ports + list_of_port_declarations +list_of_portsE: // IEEE: [ list_of_ports + list_of_port_declarations ] portAndTagE { $$ = $1; } | list_of_portsE ',' portAndTagE { $$ = addNextNull($1, $3); } ; @@ -1500,7 +1491,7 @@ portAndTagE: { int p = PINNUMINC(); const string name = "__pinNumber" + cvtToStr(p); $$ = new AstPort{CRELINE(), p, name}; - AstVar* varp = new AstVar{CRELINE(), VVarType::PORT, name, VFlagChildDType{}, + AstVar* varp = new AstVar{CRELINE(), VVarType::WIRE, name, VFlagChildDType{}, new AstBasicDType{CRELINE(), LOGIC_IMPLICIT}}; varp->declDirection(VDirection::INPUT); varp->direction(VDirection::INPUT); @@ -1529,15 +1520,17 @@ port: // ==IEEE: port // // IEEE: interface_port_header port_identifier { unpacked_dimension } // // Expanded interface_port_header // // We use instantCb here because the non-port form looks just like a module instantiation - portDirNetE id/*interface*/ portSig variable_dimensionListE sigAttrListE - { $$ = $3; VARDECL(IFACEREF); VARIO(NONE); + portDirNetE id/*interface*/ portSig variable_dimensionListE sigAttrListE + { // VAR for now, but V3LinkCells may call setIfcaeRef on it later + $$ = $3; VARDECL(VAR); VARIO(NONE); AstNodeDType* const dtp = new AstIfaceRefDType{$2, "", *$2}; - VARDTYPE(dtp); + VARDTYPE(dtp); VARIOANSI(); addNextNull($$, VARDONEP($$, $4, $5)); } | portDirNetE id/*interface*/ '.' idAny/*modport*/ portSig variable_dimensionListE sigAttrListE - { $$ = $5; VARDECL(IFACEREF); VARIO(NONE); + { // VAR for now, but V3LinkCells may call setIfcaeRef on it later + $$ = $5; VARDECL(VAR); VARIO(NONE); AstNodeDType* const dtp = new AstIfaceRefDType{$2, $4, "", *$2, *$4}; - VARDTYPE(dtp); + VARDTYPE(dtp); VARIOANSI(); addNextNull($$, VARDONEP($$, $6, $7)); } | portDirNetE yINTERFACE portSig rangeListE sigAttrListE { $$ = nullptr; BBUNSUP($2, "Unsupported: generic interfaces"); } @@ -1549,7 +1542,7 @@ port: // ==IEEE: port BBUNSUP($2, "Unsupported: interconnect"); AstNodeDType* const dtp = GRAMMARP->addRange( new AstBasicDType{$2, LOGIC_IMPLICIT, $3}, $4, true); - VARDTYPE(dtp); + VARDTYPE(dtp); VARIOANSI(); addNextNull($$, VARDONEP($$, $6, $7)); } // // // IEEE: ansi_port_declaration, with [port_direction] removed @@ -1588,15 +1581,15 @@ port: // ==IEEE: port // // IEEE: portDirNetE data_type '.' portSig -> handled with AstDot in expr. // | portDirNetE data_type portSig variable_dimensionListE sigAttrListE - { $$ = $3; VARDTYPE($2); addNextNull($$, VARDONEP($$, $4, $5)); } + { $$ = $3; VARDTYPE($2); VARIOANSI(); addNextNull($$, VARDONEP($$, $4, $5)); } | portDirNetE yVAR data_type portSig variable_dimensionListE sigAttrListE - { $$ = $4; VARDTYPE($3); addNextNull($$, VARDONEP($$, $5, $6)); } + { $$ = $4; VARDTYPE($3); VARIOANSI(); addNextNull($$, VARDONEP($$, $5, $6)); } | portDirNetE yVAR implicit_typeE portSig variable_dimensionListE sigAttrListE - { $$ = $4; VARDTYPE($3); addNextNull($$, VARDONEP($$, $5, $6)); } + { $$ = $4; VARDTYPE($3); VARIOANSI(); addNextNull($$, VARDONEP($$, $5, $6)); } | portDirNetE signing portSig variable_dimensionListE sigAttrListE { $$ = $3; AstNodeDType* const dtp = new AstBasicDType{$3->fileline(), LOGIC_IMPLICIT, $2}; - VARDTYPE_NDECL(dtp); + VARDTYPE_NDECL(dtp); VARIOANSI(); addNextNull($$, VARDONEP($$, $4, $5)); } | portDirNetE signingE rangeList portSig variable_dimensionListE sigAttrListE { $$ = $4; @@ -1608,13 +1601,13 @@ port: // ==IEEE: port { $$ = $2; /*VARDTYPE-same*/ addNextNull($$, VARDONEP($$, $3, $4)); } // | portDirNetE data_type portSig variable_dimensionListE sigAttrListE '=' constExpr - { $$ = $3; VARDTYPE($2); + { $$ = $3; VARDTYPE($2); VARIOANSI(); if (AstVar* vp = VARDONEP($$, $4, $5)) { addNextNull($$, vp); vp->valuep($7); } } | portDirNetE yVAR data_type portSig variable_dimensionListE sigAttrListE '=' constExpr - { $$ = $4; VARDTYPE($3); + { $$ = $4; VARDTYPE($3); VARIOANSI(); if (AstVar* vp = VARDONEP($$, $5, $6)) { addNextNull($$, vp); vp->valuep($8); } } | portDirNetE yVAR implicit_typeE portSig variable_dimensionListE sigAttrListE '=' constExpr - { $$ = $4; VARDTYPE($3); + { $$ = $4; VARDTYPE($3); VARIOANSI(); if (AstVar* vp = VARDONEP($$, $5, $6)) { addNextNull($$, vp); vp->valuep($8); } } | portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE '=' constExpr { $$ = $2; /*VARDTYPE-same*/ @@ -1695,8 +1688,8 @@ interface_item: // IEEE: interface_item + non_port_interface_ite ; interface_or_generate_item: // ==IEEE: interface_or_generate_item - // // module_common_item in interface_item, as otherwise duplicated - // // with module_or_generate_item's module_common_item + // // module_common_item in interface_item, as otherwise duplicated + // // with module_or_generate_item's module_common_item modport_declaration { $$ = $1; } | extern_tf_declaration { $$ = $1; } ; @@ -2063,19 +2056,40 @@ port_declaration: // ==IEEE: port_declaration | port_directionReset port_declNetE /*implicit*/ /*mid*/ { VARDTYPE_NDECL(nullptr); /*default_nettype*/ } /*cont*/ list_of_variable_decl_assignments { $$ = $4; } - // // IEEE: interface_declaration - // // Looks just like variable declaration unless has a period - // // See etcInst + // + // // IEEE: interface_port_declaration + // // IEEE: interface_identifier list_of_interface_identifiers + | id/*interface*/ + /*mid*/ { VARRESET_NONLIST(VVarType::IFACEREF); + AstIfaceRefDType* const dtp = new AstIfaceRefDType{$1, "", *$1}; + dtp->isPortDecl(true); + VARDTYPE(dtp); } + /*cont*/ mpInstnameList + { $$ = VARDONEP($3, nullptr, nullptr); } + // // IEEE: interface_port_declaration + // // IEEE: interface_identifier '.' modport_identifier list_of_interface_identifiers + | id/*interface*/ '.' idAny/*modport*/ + /*mid*/ { VARRESET_NONLIST(VVarType::IFACEREF); + AstIfaceRefDType* const dtp = new AstIfaceRefDType{$1, $3, "", *$1, *$3}; + dtp->isPortDecl(true); + VARDTYPE(dtp); } + /*cont*/ mpInstnameList + { $$ = VARDONEP($5, nullptr, nullptr); } + //UNSUP: strengthSpecE for udp_instantiations ; tf_port_declaration: // ==IEEE: tf_port_declaration // // Used inside function; followed by ';' // // SEE ALSO port_declaration, port, data_declarationVarFront // - port_directionReset data_type { VARDTYPE($2); } list_of_tf_variable_identifiers ';' { $$ = $4; } - | port_directionReset implicit_typeE { VARDTYPE_NDECL($2); } list_of_tf_variable_identifiers ';' { $$ = $4; } - | port_directionReset yVAR data_type { VARDTYPE($3); } list_of_tf_variable_identifiers ';' { $$ = $5; } - | port_directionReset yVAR implicit_typeE { VARDTYPE($3); } list_of_tf_variable_identifiers ';' { $$ = $5; } + port_directionReset data_type { VARDTYPE($2); } list_of_tf_variable_identifiers ';' + { $$ = $4; } + | port_directionReset implicit_typeE { VARDTYPE_NDECL($2); } list_of_tf_variable_identifiers ';' + { $$ = $4; } + | port_directionReset yVAR data_type { VARDTYPE($3); } list_of_tf_variable_identifiers ';' + { $$ = $5; } + | port_directionReset yVAR implicit_typeE { VARDTYPE($3); } list_of_tf_variable_identifiers ';' + { $$ = $5; } ; integer_atom_type: // ==IEEE: integer_atom_type @@ -2348,7 +2362,7 @@ tf_variable_identifier: // IEEE: part of list_of_tf_variable_ide variable_declExpr: // IEEE: part of variable_decl_assignment - rhs of expr expr { $$ = $1; } | dynamic_array_new { $$ = $1; } - | class_new { $$ = $1; } + | class_newNoScope { $$ = $1; } ; variable_dimensionListE: // IEEE: variable_dimension + empty @@ -2572,25 +2586,25 @@ nettype_declaration: // IEEE: nettype_declaration/net_type_declaration // // Union of data_typeAny and nettype_identifier matching yNETTYPE data_typeNoRef /*cont*/ idAny/*nettype_identifier*/ ';' - { $$ = nullptr; BBUNSUP($1, "Unsupported: nettype"); } + { $$ = GRAMMARP->createNettype($3, *$3); BBUNSUP($1, "Unsupported: nettype"); } | yNETTYPE data_typeNoRef /*cont*/ idAny/*nettype_identifier*/ /*cont*/ yWITH__ETC packageClassScopeE id/*tf_identifier*/ ';' - { $$ = nullptr; BBUNSUP($1, "Unsupported: nettype with"); } + { $$ = GRAMMARP->createNettype($3, *$3); BBUNSUP($1, "Unsupported: nettype with"); } | yNETTYPE packageClassScopeE idAny packed_dimensionListE /*cont*/ idAny/*nettype_identifier*/ ';' - { $$ = nullptr; BBUNSUP($1, "Unsupported: nettype"); } + { $$ = GRAMMARP->createNettype($5, *$5); BBUNSUP($1, "Unsupported: nettype"); } | yNETTYPE packageClassScopeE idAny packed_dimensionListE /*cont*/ idAny/*nettype_identifier*/ /*cont*/ yWITH__ETC packageClassScopeE id/*tf_identifier*/ ';' - { $$ = nullptr; BBUNSUP($1, "Unsupported: nettype with"); } + { $$ = GRAMMARP->createNettype($5, *$5); BBUNSUP($1, "Unsupported: nettype with"); } | yNETTYPE packageClassScopeE idAny parameter_value_assignmentClass packed_dimensionListE /*cont*/ idAny/*nettype_identifier*/ ';' - { $$ = nullptr; BBUNSUP($1, "Unsupported: nettype"); } + { $$ = GRAMMARP->createNettype($6, *$6); BBUNSUP($1, "Unsupported: nettype"); } | yNETTYPE packageClassScopeE idAny parameter_value_assignmentClass packed_dimensionListE /*cont*/ idAny/*nettype_identifier*/ /*cont*/ yWITH__ETC packageClassScopeE id/*tf_identifier*/ ';' - { $$ = nullptr; BBUNSUP($1, "Unsupported: nettype with"); } + { $$ = GRAMMARP->createNettype($6, *$6); BBUNSUP($1, "Unsupported: nettype with"); } ; implicit_typeE: // IEEE: part of *data_type_or_implicit @@ -2758,11 +2772,9 @@ always_construct: // IEEE: == always_construct continuous_assign: // IEEE: continuous_assign yASSIGN driveStrengthE delay_controlE assignList ';' - { - $$ = $4; - STRENGTH_LIST($4, $2, AssignW); - DELAY_LIST($3, $4); - } + { $$ = $4; + STRENGTH_LIST($4, $2, AssignW); + DELAY_LIST($3, $4); } ; initial_construct: // IEEE: initial_construct @@ -2779,8 +2791,12 @@ module_or_generate_item_declaration: // ==IEEE: module_or_generate_it | clocking_declaration { $$ = $1; } | yDEFAULT yCLOCKING idAny/*new-clocking_identifier*/ ';' { $$ = nullptr; BBUNSUP($1, "Unsupported: default clocking identifier"); } - | yDEFAULT yDISABLE yIFF expr/*expression_or_dist*/ ';' - { $$ = nullptr; BBUNSUP($1, "Unsupported: default disable iff"); } + | defaultDisable { $$ = $1; } + ; + +defaultDisable: // IEEE: part of module_/checker_or_generate_item_declaration + yDEFAULT yDISABLE yIFF expr/*expression_or_dist*/ ';' + { $$ = new AstDefaultDisable{$1, $4}; } ; aliasEqList: // IEEE: part of net_alias @@ -3041,9 +3057,9 @@ assignOne: delay_or_event_controlE: // IEEE: delay_or_event_control plus empty /* empty */ { $$ = nullptr; } - | delay_control { $$ = $1; } - | event_control { $$ = $1; } - | yREPEAT '(' expr ')' event_control + | delay_control { $$ = $1; } + | event_control { $$ = $1; } + | yREPEAT '(' expr ')' event_control { $$ = $5; BBUNSUP($1, "Unsupported: repeat event control"); } ; @@ -3065,7 +3081,7 @@ delay_control: //== IEEE: delay_control delay_value: // ==IEEE:delay_value // // IEEE: ps_identifier - packageClassScopeE varRefBase { $$ = AstDot::newIfPkg($2, $1, $2); } + idClass { $$ = $1; } | yaINTNUM { $$ = new AstConst{$1, *$1}; } | yaFLOATNUM { $$ = new AstConst{$1, AstConst::RealDouble{}, $1}; } | timeNumAdjusted { $$ = $1; } @@ -3249,10 +3265,9 @@ etcInst: // IEEE: module_instantiation + gate_instantiati ; instDecl: - // // Currently disambiguated from data_declaration based on - // // VARs being type, and cells non-type. - // // IEEE requires a '(' to disambiguate, we need TODO force this - id parameter_value_assignmentInstE + // // Disambigurated from data_declaration based on + // // idCell which is found as IEEE requires a later '(' + idCell parameter_value_assignmentInstE /*mid*/ { INSTPREP($1, *$1, $2); } /*cont*/ instnameList ';' { $$ = $4; @@ -3261,14 +3276,7 @@ instDecl: VL_DO_CLEAR(GRAMMARP->m_instParamp->deleteTree(), GRAMMARP->m_instParamp = nullptr); } } - // // IEEE: interface_identifier' .' modport_identifier list_of_interface_identifiers - | id/*interface*/ '.' idAny/*modport*/ - /*mid*/ { VARRESET_NONLIST(VVarType::IFACEREF); - AstNodeDType* const dtp = new AstIfaceRefDType{$1, $3, "", *$1, *$3}; - VARDTYPE(dtp); } - /*cont*/ mpInstnameList ';' - { $$ = VARDONEP($5, nullptr, nullptr); } - //UNSUP: strengthSpecE for udp_instantiations + // // // IEEE: part of udp_instance when no name_of_instance // // Note no unpacked dimension nor list of instances | id @@ -3293,14 +3301,12 @@ instnameList: instnameParen: id instRangeListE '(' cellpinListE ')' - { $$ = GRAMMARP->createCellOrIfaceRef($1, *$1, $4, $2, true); } - | id instRangeListE - { $$ = GRAMMARP->createCellOrIfaceRef($1, *$1, nullptr, $2, false); } + { $$ = GRAMMARP->createCell($1, *$1, $4, $2); } ; instnameParenUdpn: // IEEE: part of udp_instance when no name_of_instance '(' cellpinListE ')' // When UDP has empty name, unpacked dimensions must not be used - { $$ = GRAMMARP->createCellOrIfaceRef($1, "", $2, nullptr, true); } + { $$ = GRAMMARP->createCell($1, "", $2, nullptr); } ; instRangeListE: @@ -3609,7 +3615,7 @@ statement_item: // IEEE: statement_item // // IEEE: blocking_assignment // // 1800-2009 restricts LHS of assignment to new to not have a range // // This is ignored to avoid conflicts - | fexprLvalue '=' class_new ';' { $$ = new AstAssign{$2, $1, $3}; } + | fexprLvalue '=' class_newNoScope ';' { $$ = new AstAssign{$2, $1, $3}; } | fexprLvalue '=' dynamic_array_new ';' { $$ = new AstAssign{$2, $1, $3}; } // // IEEE: inc_or_dec_expression | finc_or_dec_expression ';' { $$ = $1; } @@ -3695,7 +3701,7 @@ statement_item: // IEEE: statement_item | yDISABLE yFORK ';' { $$ = new AstDisableFork{$1}; } | yDISABLE idAny/*UNSUP: hierarchical_identifier-task_or_block*/ ';' { $$ = new AstDisable{$1, *$2}; } - | yDISABLE idAny '.' idDotted ';' + | yDISABLE idAny '.' idDottedSel ';' { $$ = nullptr; BBUNSUP($4, "Unsupported: disable with '.'"); } // // IEEE: event_trigger | yP_MINUSGT expr ';' @@ -3782,7 +3788,7 @@ statementFor: // IEEE: part of statement $$->addStmtsp(new AstWhile{$1, new AstConst{$1, AstConst::BitTrue{}}, $7, $5}); } ; beginForParen: // IEEE: Part of statement (for loop beginning paren) - '(' { VARRESET(); } + '(' { VARRESET_NONLIST(UNKNOWN); } ; statementVerilatorPragmas: @@ -3858,8 +3864,8 @@ pinc_or_dec_expression: // IEEE: inc_or_dec_expression (for property //UNSUP BISONPRE_COPY(inc_or_dec_expression,{s/~l~/pev_/g}) // {copied} //UNSUP ; -class_new: // ==IEEE: class_new - // // Special precence so (...) doesn't match expr +class_newNoScope: // IEEE: class_new but no packageClassScope (issue #4199) + // // Special precedence so (...) doesn't match expr yNEW__ETC { $$ = new AstNew{$1, nullptr}; } | yNEW__ETC expr { $$ = new AstNewCopy{$1, $2}; } | yNEW__PAREN '(' list_of_argumentsE ')' { $$ = new AstNew{$1, $3}; } @@ -3927,11 +3933,11 @@ range_list: // ==IEEE: range_list/open_range_list + value_range/o value_range: // ==IEEE: value_range/open_value_range expr { $$ = $1; } | '[' expr ':' expr ']' { $$ = new AstInsideRange{$1, $2, $4}; } - // // IEEE-2023: added all four: - // // Skipped as '$' is part of our expr - // // IEEE-2023: '[' '$' ':' expr ']' - // // Skipped as '$' is part of our expr - // // IEEE-2023: '[' expr ':' '$' ']' + // // IEEE-2023: added all four: + // // Skipped as '$' is part of our expr + // // IEEE-2023: '[' '$' ':' expr ']' + // // Skipped as '$' is part of our expr + // // IEEE-2023: '[' expr ':' '$' ']' | '[' expr yP_PLUSSLASHMINUS expr ']' { $$ = nullptr; BBUNSUP($1, "Unsupported: +/- range"); } | '[' expr yP_PLUSPCTMINUS expr ']' @@ -3942,11 +3948,11 @@ covergroup_value_range: // ==IEEE-2012: covergroup_value_range cgexpr { $$ = $1; } | '[' cgexpr ':' cgexpr ']' { $$ = nullptr; BBUNSUP($1, "Unsupported: covergroup value range"); } - // // IEEE-2023: added all four: - // // Skipped as '$' is part of our expr - // // IEEE-2023: '[' '$' ':' cgexpr ']' - // // Skipped as '$' is part of our expr - // // IEEE-2023: '[' cgexpr ':' '$' ']' + // // IEEE-2023: added all four: + // // Skipped as '$' is part of our expr + // // IEEE-2023: '[' '$' ':' cgexpr ']' + // // Skipped as '$' is part of our expr + // // IEEE-2023: '[' cgexpr ':' '$' ']' | '[' cgexpr yP_PLUSSLASHMINUS cgexpr ']' { $$ = nullptr; BBUNSUP($1, "Unsupported: covergroup value range"); } | '[' cgexpr yP_PLUSPCTMINUS cgexpr ']' @@ -4006,11 +4012,18 @@ patternKey: // IEEE: merge structure_pattern_key, array_patt // // "foo"member (if structure) // // So for now we only allow a true constant number, or an // // identifier which we treat as a structure member name - yaINTNUM { $$ = new AstConst{$1, *$1}; } - | yaFLOATNUM { $$ = new AstConst{$1, AstConst::RealDouble{}, $1}; } - | id { $$ = new AstText{$1, *$1}; } - | strAsInt { $$ = $1; } - | simple_typeNoRef { $$ = $1; } + yaINTNUM + { $$ = new AstConst{$1, *$1}; } + | '-' yaINTNUM + { V3Number neg{*$2}; neg.opNegate(*$2); $$ = new AstConst{$2, neg}; } + | yaFLOATNUM + { $$ = new AstConst{$1, AstConst::RealDouble{}, $1}; } + | id + { $$ = new AstText{$1, *$1}; } + | strAsInt + { $$ = $1; } + | simple_typeNoRef + { $$ = $1; } // // expanded from simple_type ps_type_identifier (part of simple_type) // // expanded from simple_type ps_parameter_identifier (part of simple_type) | packageClassScopeE idType @@ -4124,20 +4137,20 @@ funcRef: // IEEE: part of tf_call | packageClassScope id '(' list_of_argumentsE ')' { $$ = AstDot::newIfPkg($2, $1, new AstFuncRef{$2, *$2, $4}); } //UNSUP list_of_argumentE should be pev_list_of_argumentE - //UNSUP: idDotted is really just id to allow dotted method calls + //UNSUP: idDottedSel is really just id to allow dotted method calls ; task_subroutine_callNoSemi: // similar to IEEE task_subroutine_call but without ';' // // Expr included here to resolve our not knowing what is a method call // // Expr here must result in a subroutine_call - task_subroutine_callNoMethod { $$ = $1->makeStmt(); } + task_subroutine_callNoMethod { $$ = $1->makeStmt(); } | fexpr '.' task_subroutine_callNoMethod { $$ = (new AstDot{$2, false, $1, $3})->makeStmt(); } - | system_t_call { $$ = $1; } + | system_t_call { $$ = $1; } // // Not here in IEEE; from class_constructor_declaration // // Because we've joined class_constructor_declaration into generic functions // // Way over-permissive; // // IEEE: [ ySUPER '.' yNEW [ '(' list_of_arguments ')' ] ';' ] - | fexpr '.' class_new { $$ = (new AstDot{$2, false, $1, $3})->makeStmt(); } + | fexpr '.' class_newNoScope { $$ = (new AstDot{$2, false, $1, $3})->makeStmt(); } ; task_subroutine_callNoMethod: // function_subroutine_callNoMethod (as task) @@ -4168,7 +4181,6 @@ function_subroutine_callNoMethod: // IEEE: function_subroutine // // We implement randomize as a normal funcRef, since randomize isn't a keyword // // Note yNULL is already part of expressions, so they come for free | funcRef yWITH__CUR constraint_block { $$ = new AstWithParse{$2, $1, $3}; } - | funcRef yWITH__CUR '{' '}' { $$ = new AstWithParse{$2, $1, nullptr}; } ; system_t_call: // IEEE: system_tf_call (as task) @@ -4177,7 +4189,7 @@ system_t_call: // IEEE: system_tf_call (as task) refp->pli(true); $$ = refp->makeStmt(); } // - | yD_DUMPPORTS '(' idDotted ',' expr ')' { $$ = new AstDumpCtl{$1, VDumpCtlType::FILE, $5}; DEL($3); + | yD_DUMPPORTS '(' idDottedSel ',' expr ')' { $$ = new AstDumpCtl{$1, VDumpCtlType::FILE, $5}; DEL($3); $$->addNext(new AstDumpCtl{$1, VDumpCtlType::VARS, new AstConst{$1, 1}}); } | yD_DUMPPORTS '(' ',' expr ')' { $$ = new AstDumpCtl{$1, VDumpCtlType::FILE, $4}; @@ -4407,6 +4419,7 @@ system_f_call_or_t: // IEEE: part of system_tf_call (can be task | yD_HYPOT '(' expr ',' expr ')' { $$ = new AstHypotD{$1, $3, $5}; } | yD_INCREMENT '(' exprOrDataType ')' { $$ = new AstAttrOf{$1, VAttrType::DIM_INCREMENT, $3, nullptr}; } | yD_INCREMENT '(' exprOrDataType ',' expr ')' { $$ = new AstAttrOf{$1, VAttrType::DIM_INCREMENT, $3, $5}; } + | yD_INFERRED_DISABLE parenE { $$ = new AstInferredDisable{$1}; } | yD_ISUNBOUNDED '(' expr ')' { $$ = new AstIsUnbounded{$1, $3}; } | yD_ISUNKNOWN '(' expr ')' { $$ = new AstIsUnknown{$1, $3}; } | yD_ITOR '(' expr ')' { $$ = new AstIToRD{$1, $3}; } @@ -4644,12 +4657,12 @@ funcId: // IEEE: function_data_type_or_implicit + part o { $$ = $2; $$->fvarp($1); SYMP->pushNewUnderNodeOrCurrent($$, $2); } - | packageClassScopeE idType packed_dimensionListE fIdScoped + | packageClassScopeE idCellType packed_dimensionListE fIdScoped { AstRefDType* const refp = new AstRefDType{$2, *$2, $1, nullptr}; $$ = $4; $$->fvarp(GRAMMARP->createArray(refp, $3, true)); SYMP->pushNewUnderNodeOrCurrent($$, $4); } - | packageClassScopeE idType parameter_value_assignmentClass packed_dimensionListE fIdScoped + | packageClassScopeE idCellType parameter_value_assignmentClass packed_dimensionListE fIdScoped { AstRefDType* const refp = new AstRefDType{$2, *$2, $1, $3}; $$ = $5; $$->fvarp(GRAMMARP->createArray(refp, $4, true)); @@ -5427,7 +5440,7 @@ let_declaration: // IEEE: let_declaration let_port_listE: // IEEE: [ let_port_list ] /*empty*/ { $$ = nullptr; } | /*emptyStart*/ - /*mid*/ { VARRESET_LIST(UNKNOWN); VARIO(INOUT); } + /*mid*/ { VARRESET_LIST(VAR); VARIO(INOUT); } /*cont*/ let_port_list { $$ = $2; VARRESET_NONLIST(UNKNOWN); } ; @@ -5439,7 +5452,7 @@ let_port_list: // IEEE: let_port_list let_port_item: // IEEE: let_port_Item // // IEEE: Expanded let_formal_type yUNTYPED idAny/*formal_port_identifier*/ variable_dimensionListE exprEqE - { $$ = new AstVar{$2, VVarType::PORT, *$2, VFlagChildDType{}, + { $$ = new AstVar{$2, VVarType::VAR, *$2, VFlagChildDType{}, new AstBasicDType{$2, LOGIC_IMPLICIT}}; $$->direction(VDirection::INOUT); $$->lifetime(VLifetime::AUTOMATIC); @@ -5447,7 +5460,7 @@ let_port_item: // IEEE: let_port_Item PINNUMINC(); } | data_type idAny/*formal_port_identifier*/ variable_dimensionListE exprEqE { BBUNSUP($1, "Unsupported: let typed ports"); - $$ = new AstVar{$2, VVarType::PORT, *$2, VFlagChildDType{}, + $$ = new AstVar{$2, VVarType::VAR, *$2, VFlagChildDType{}, new AstBasicDType{$2, LOGIC_IMPLICIT}}; $$->direction(VDirection::INOUT); $$->lifetime(VLifetime::AUTOMATIC); @@ -5455,7 +5468,7 @@ let_port_item: // IEEE: let_port_Item PINNUMINC(); } | implicit_typeE id/*formal_port_identifier*/ variable_dimensionListE exprEqE { if ($1) BBUNSUP($1, "Unsupported: let typed ports"); - $$ = new AstVar{$2, VVarType::PORT, *$2, VFlagChildDType{}, + $$ = new AstVar{$2, VVarType::VAR, *$2, VFlagChildDType{}, new AstBasicDType{$2, LOGIC_IMPLICIT}}; $$->direction(VDirection::INOUT); $$->lifetime(VLifetime::AUTOMATIC); @@ -5767,15 +5780,28 @@ id: idAny: // Any kind of identifier yaID__ETC { $$ = $1; $$ = $1; } + | yaID__aCELL { $$ = $1; $$ = $1; } | yaID__aTYPE { $$ = $1; $$ = $1; } | idRandomize { $$ = $1; $$ = $1; } ; +idCell: // IEEE: instance_identifier or similar with another id then '(' + // // See V3ParseImp::tokenPipeScanIdCell + // // [^': '@' '.'] yaID/*module_id*/ [ '#' '('...')' ] yaID/*name_of_instance*/ [ '['...']' ] '(' ... + // // [^':' @' '.'] yaID/*module_id*/ [ '#' id|etc ] yaID/*name_of_instance*/ [ '['...']' ] '(' ... + yaID__aCELL { $$ = $1; $$ = $1; } + ; + idType: // IEEE: class_identifier or other type identifier // // Used where reference is needed yaID__aTYPE { $$ = $1; $$ = $1; } ; +idCellType: // type_identifier for functions which have a following id then '(' + yaID__aCELL { $$ = $1; $$ = $1; } + | yaID__aTYPE { $$ = $1; $$ = $1; } + ; + idCC: // IEEE: class/package then :: // lexer matches this: yaID_LEX [ '#' '(' ... ')' ] yP_COLONCOLON yaID__CC { $$ = $1; $$ = $1; } @@ -5793,7 +5819,7 @@ idSVKwd: // Warn about non-forward compatible Verilog 200 { static string s = "final"; $$ = &s; ERRSVKWD($1, *$$); $$ = $1; } ; -variable_lvalue: // IEEE: variable_lvalue or net_lvalue +variable_lvalue: // IEEE: variable_lvalue or net_lvalue // // Note many variable_lvalue's must use exprOkLvalue when arbitrary expressions may also exist idClassSel { $$ = $1; } | '{' variable_lvalueConcList '}' { $$ = $2; } @@ -5805,7 +5831,7 @@ variable_lvalue: // IEEE: variable_lvalue or net_lvalue | streaming_concatenation { $$ = $1; } ; -variable_lvalueConcList: // IEEE: part of variable_lvalue: '{' variable_lvalue { ',' variable_lvalue } '}' +variable_lvalueConcList: // IEEE: part of variable_lvalue: '{' variable_lvalue { ',' variable_lvalue } '}' variable_lvalue { $$ = $1; } | variable_lvalueConcList ',' variable_lvalue { $$ = new AstConcat{$2, $1, $3}; } ; @@ -5815,8 +5841,7 @@ variable_lvalueConcList: // IEEE: part of variable_lvalue: '{' variab //UNSUP | variable_lvalueList ',' variable_lvalue { $$ = addNextNull($1, $3); } //UNSUP ; -// VarRef to dotted, and/or arrayed, and/or bit-ranged variable -idClassSel: // Misc Ref to dotted, and/or arrayed, and/or bit-ranged variable +idClass: // Misc Ref to dotted, and/or arrayed, and/or bit-ranged variable idDotted { $$ = $1; } // // IEEE: [ implicit_class_handle . | package_scope ] hierarchical_variable_identifier select | yTHIS '.' idDotted @@ -5824,10 +5849,22 @@ idClassSel: // Misc Ref to dotted, and/or arraye | ySUPER '.' idDotted { $$ = new AstDot{$2, false, new AstParseRef{$1, VParseRefExp::PX_ROOT, "super"}, $3}; } | yTHIS '.' ySUPER '.' idDotted { $$ = $5; BBUNSUP($1, "Unsupported: this.super"); } - // // Expanded: package_scope idDotted + // // Expanded: package_scope idDottedSel | packageClassScope idDotted { $$ = new AstDot{$2, true, $1, $2}; } ; +idClassSel: // Misc Ref to dotted, and/or arrayed, and/or bit-ranged variable + idDottedSel { $$ = $1; } + // // IEEE: [ implicit_class_handle . | package_scope ] hierarchical_variable_identifier select + | yTHIS '.' idDottedSel + { $$ = new AstDot{$2, false, new AstParseRef{$1, VParseRefExp::PX_ROOT, "this"}, $3}; } + | ySUPER '.' idDottedSel + { $$ = new AstDot{$2, false, new AstParseRef{$1, VParseRefExp::PX_ROOT, "super"}, $3}; } + | yTHIS '.' ySUPER '.' idDottedSel { $$ = $5; BBUNSUP($1, "Unsupported: this.super"); } + // // Expanded: package_scope idDottedSel + | packageClassScope idDottedSel { $$ = new AstDot{$2, true, $1, $2}; } + ; + idClassSelForeach: idDottedForeach { $$ = $1; } // // IEEE: [ implicit_class_handle . | package_scope ] hierarchical_variable_identifier select @@ -5846,6 +5883,12 @@ idDotted: | idDottedMore { $$ = $1; } ; +idDottedSel: + yD_ROOT '.' idDottedSelMore + { $$ = new AstDot{$2, false, new AstParseRef{$1, VParseRefExp::PX_ROOT, "$root"}, $3}; } + | idDottedSelMore { $$ = $1; } + ; + idDottedForeach: yD_ROOT '.' idDottedMoreForeach { $$ = new AstDot{$2, false, new AstParseRef{$1, VParseRefExp::PX_ROOT, "$root"}, $3}; } @@ -5853,8 +5896,13 @@ idDottedForeach: ; idDottedMore: + varRefBase { $$ = $1; } + | idDottedMore '.' varRefBase { $$ = new AstDot{$2, false, $1, $3}; } + ; + +idDottedSelMore: idArrayed { $$ = $1; } - | idDottedMore '.' idArrayed { $$ = new AstDot{$2, false, $1, $3}; } + | idDottedSelMore '.' idArrayed { $$ = new AstDot{$2, false, $1, $3}; } ; idDottedMoreForeach: @@ -6024,11 +6072,11 @@ clocking_skew: // IEEE: clocking_skew cycle_delay: // IEEE: cycle_delay yP_POUNDPOUND yaINTNUM - { $$ = new AstDelay{$1, new AstConst{$2, *$2}, true}; } + { $$ = new AstDelay{$1, new AstConst{$2, *$2}, true}; } | yP_POUNDPOUND idAny - { $$ = new AstDelay{$1, new AstParseRef{$2, VParseRefExp::PX_TEXT, *$2, nullptr, nullptr}, true}; } + { $$ = new AstDelay{$1, new AstParseRef{$2, VParseRefExp::PX_TEXT, *$2, nullptr, nullptr}, true}; } | yP_POUNDPOUND '(' expr ')' - { $$ = new AstDelay{$1, $3, true}; } + { $$ = new AstDelay{$1, $3, true}; } ; //************************************************ @@ -6157,9 +6205,9 @@ property_declarationFront: // IEEE: part of property_declaration ; property_port_listE: // IEEE: [ ( [ property_port_list ] ) ] - /* empty */ { $$ = nullptr; } - | '(' ')' { $$ = nullptr; } - | '(' property_port_list ')' { $$ = $2; } + /* empty */ { $$ = nullptr; } + | '(' ')' { $$ = nullptr; } + | '(' property_port_list ')' { $$ = $2; } ; property_port_list: // ==IEEE: property_port_list @@ -6177,7 +6225,7 @@ property_port_item: // IEEE: property_port_item/sequence_port_item property_port_itemFront property_port_itemAssignment { $$ = $2; } ; -property_port_itemFront: // IEEE: part of property_port_item/sequence_port_item +property_port_itemFront: // IEEE: part of property_port_item/sequence_port_item property_port_itemDirE property_formal_typeNoDt { VARDTYPE($2); } // // data_type_or_implicit | property_port_itemDirE data_type @@ -6207,14 +6255,15 @@ property_port_itemDirE: ; property_declarationBody: // IEEE: part of property_declaration - //UNSUP assertion_variable_declarationList property_statement_spec {} + assertion_variable_declarationList + { $$ = nullptr; BBUNSUP($1->fileline(), "Unsupported: property variable declaration"); } // // IEEE-2012: Incorrectly has yCOVER ySEQUENCE then property_spec here. // // Fixed in IEEE 1800-2017 - property_spec { $$ = $1; } - | property_spec ';' { $$ = $1; } + | property_spec { $$ = $1; } + | property_spec ';' { $$ = $1; } ; -assertion_variable_declarationList: // IEEE: part of assertion_variable_declaration +assertion_variable_declarationList: // IEEE: part of assertion_variable_declaration assertion_variable_declaration { $$ = $1; } | assertion_variable_declarationList assertion_variable_declaration { $$ = addNextNull($1, $2); } @@ -6280,8 +6329,8 @@ property_spec: // IEEE: property_spec '@' '(' senitemEdge ')' yDISABLE yIFF '(' expr ')' pexpr { $$ = new AstPropSpec{$1, $3, $8, $10}; } | '@' '(' senitemEdge ')' pexpr { $$ = new AstPropSpec{$1, $3, nullptr, $5}; } - // // Disable applied after the event occurs, - // // so no existing AST can represent this + // // Disable applied after the event occurs, + // // so no existing AST can represent this | yDISABLE yIFF '(' expr ')' '@' '(' senitemEdge ')' pexpr { $$ = new AstPropSpec{$1, $8, nullptr, new AstLogOr{$1, $4, $10}}; BBUNSUP($1, "Unsupported: property '(disable iff (...) @ (...)'\n" @@ -6953,7 +7002,7 @@ rs_prodList: // IEEE: rs_prod+ ; rs_prod: // ==IEEE: rs_prod - rs_production_item { $$ = $1; } + rs_production_item { $$ = $1; } | rs_code_block { $$ = $1; } // // IEEE: rs_if_else | yIF '(' expr ')' rs_production_item %prec prLOWER_THAN_ELSE @@ -7061,7 +7110,7 @@ checker_or_generate_item_declaration: // ==IEEE: checker_or_generate_ite | clocking_declaration { $$ = $1; } | yDEFAULT yCLOCKING idAny/*clocking_identifier*/ ';' { } { $$ = nullptr; BBUNSUP($1, "Unsupported: checker default clocking"); } - | yDEFAULT yDISABLE yIFF expr/*expression_or_dist*/ ';' { } + | defaultDisable { $$ = nullptr; BBUNSUP($1, "Unsupported: checker default disable iff"); } | ';' { $$ = nullptr; } ; @@ -7141,23 +7190,32 @@ classExtendsOne: // IEEE: part of class_declaration class_typeExtImpList { $$ = new AstClassExtends{$1->fileline(), $1, GRAMMARP->m_inImplements}; $$ = $1; } + | class_typeExtImpList '(' list_of_argumentsE ')' + { $$ = new AstClassExtends{$1->fileline(), $1, GRAMMARP->m_inImplements}; + BBUNSUP($2, "Unsupported: 'extends' with class list_of_arguments"); + $$ = $1; } + // // IEEE-2023: Added: yEXTENDS class_type '(' yDEFAULT ')' + | class_typeExtImpList '(' yDEFAULT ')' + { $$ = new AstClassExtends{$1->fileline(), $1, GRAMMARP->m_inImplements}; + BBUNSUP($2, "Unsupported: 'extends' with 'default'"); + $$ = $1; } ; classImplementsE: // IEEE: part of class_declaration // // All 1800-2012 /* empty */ { $$ = nullptr; $$ = nullptr; } | yIMPLEMENTS - /*mid*/ { GRAMMARP->m_inImplements = true; $$ = nullptr; } + /*mid*/ { GRAMMARP->m_inImplements = true; $$ = nullptr; } /*cont*/ classImplementsList - { $$ = $3; $$ = $3; - GRAMMARP->m_inImplements = false; } + { $$ = $3; $$ = $3; + GRAMMARP->m_inImplements = false; } ; classImplementsList: // IEEE: part of class_declaration // // All 1800-2012 classExtendsOne { $$ = $1; $$ = $1; } | classImplementsList ',' classExtendsOne - { $$ = addNextNull($1, $3); $$ = $3; } + { $$ = addNextNull($1, $3); $$ = $3; } ; class_typeExtImpList: // IEEE: class_type: "[package_scope] id [ parameter_value_assignment ]" @@ -7178,12 +7236,12 @@ class_typeExtImpOne: // part of IEEE: class_type, where we either ge idAny /*mid*/ { /* no nextId as not refing it above this*/ } /*cont*/ parameter_value_assignmentClassE - { $$ = new AstClassOrPackageRef{$1, *$1, $1, $3}; + { $$ = new AstClassOrPackageRef{$1, *$1, nullptr, $3}; $$ = $1; } | idCC /*mid*/ { /* no nextId as not refing it above this*/ } /*cont*/ parameter_value_assignmentClassE - { $$ = new AstClassOrPackageRef{$1, *$1, $1, $3}; + { $$ = new AstClassOrPackageRef{$1, *$1, nullptr, $3}; $$ = $1; } // // // package_sopeIdFollows expanded @@ -7191,12 +7249,6 @@ class_typeExtImpOne: // part of IEEE: class_type, where we either ge { $$ = new AstClassOrPackageRef{$1, "$unit", nullptr, nullptr}; $$ = nullptr; // No purpose otherwise, every symtab can see root SYMP->nextId(PARSEP->rootp()); } - // - | yLOCAL__COLONCOLON yP_COLONCOLON - { $$ = new AstClassOrPackageRef{$1, "local::", nullptr, nullptr}; - $$ = nullptr; // UNSUP - SYMP->nextId(PARSEP->rootp()); - BBUNSUP($1, "Unsupported: Randomize 'local::'"); } ; //========= @@ -7251,12 +7303,12 @@ packageClassScopeItem: // IEEE: package_scope or [package_scope]::[ idCC /*mid*/ { SYMP->nextId($1); } /*cont*/ yP_COLONCOLON - { $$ = new AstClassOrPackageRef{$1, *$1, $1, nullptr}; $$ = $1; } + { $$ = new AstClassOrPackageRef{$1, *$1, nullptr, nullptr}; $$ = $1; } // | idCC parameter_value_assignmentClass /*mid*/ { SYMP->nextId($1); } // Change next *after* we handle parameters, not before /*cont*/ yP_COLONCOLON - { $$ = new AstClassOrPackageRef{$1, *$1, $1, $2}; $$ = $1; } + { $$ = new AstClassOrPackageRef{$1, *$1, nullptr, $2}; $$ = $1; } ; dollarUnitNextId: // $unit @@ -7264,17 +7316,17 @@ dollarUnitNextId: // $unit // // if not needed must use packageClassScopeNoId // // Must call nextId without any additional tokens following yD_UNIT - { $$ = new AstClassOrPackageRef{$1, "$unit", PARSEP->unitPackage($1), nullptr}; + { $$ = new AstClassOrPackageRef{$1, "$unit", nullptr, nullptr}; SYMP->nextId(PARSEP->rootp()); } ; -localNextId: // local +localNextId: // local:: // // IMPORTANT: The lexer will parse the following ID to be in the found package // // if not needed must use packageClassScopeNoId // // Must call nextId without any additional tokens following yLOCAL__COLONCOLON - { $$ = new AstClassOrPackageRef{$1, "local::", PARSEP->unitPackage($1), nullptr}; - SYMP->nextId(PARSEP->rootp()); } + { $$ = new AstClassOrPackageRef{$1, "local::", nullptr, nullptr}; + /* No SYMP->nextId(...); normal search upward we should find local's vars */ } ; //^^^========= @@ -7374,18 +7426,16 @@ memberQualOne: // IEEE: property_qualifier + me class_constraint: // ==IEEE: class_constraint // // IEEE: constraint_declaration constraintStaticE yCONSTRAINT dynamic_override_specifiersE constraintIdNew constraint_block - { $$ = $4; $$->isStatic($1); $$->addItemsp($5); SYMP->popScope($$); } - | constraintStaticE yCONSTRAINT dynamic_override_specifiersE constraintIdNew '{' '}' - { $$ = $4; $$->isStatic($1); SYMP->popScope($$); } + { $$ = $4; $$->isStatic($1); $$->baseOverride($3); $$->addItemsp($5); SYMP->popScope($$); } // // IEEE: constraint_prototype + constraint_prototype_qualifier | constraintStaticE yCONSTRAINT dynamic_override_specifiersE constraintIdNew ';' - { $$ = $4; $$->isStatic($1); SYMP->popScope($$); } - | yEXTERN constraintStaticE yCONSTRAINT constraintIdNew ';' - { $$ = $4; $$->isStatic($1); SYMP->popScope($4); - BBUNSUP($1, "Unsupported: extern constraint"); } + { $$ = $4; $$->isStatic($1); $$->baseOverride($3); + $$->isExternProto(true); SYMP->popScope($$); } + | yEXTERN constraintStaticE yCONSTRAINT dynamic_override_specifiersE constraintIdNew ';' + { $$ = $5; $$->isStatic($2); $$->baseOverride($4); + $$->isExternProto(true); $$->isExternExplicit(true); SYMP->popScope($$); } | yPURE constraintStaticE yCONSTRAINT constraintIdNew ';' - { $$ = $4; $$->isStatic($1); SYMP->popScope($4); - BBUNSUP($1, "Unsupported: pure constraint"); } + { $$ = $4; $$->isKwdPure($1); $$->isStatic($2); SYMP->popScope($4); } ; constraintIdNew: // IEEE: id part of class_constraint @@ -7395,7 +7445,8 @@ constraintIdNew: // IEEE: id part of class_constraint ; constraint_block: // ==IEEE: constraint_block - '{' constraint_block_itemList '}' { $$ = $2; } + '{' '}' { $$ = nullptr; } + | '{' constraint_block_itemList '}' { $$ = $2; } // | '{' error '}' { $$ = nullptr; } | '{' constraint_block_itemList error '}' { $$ = $2; } @@ -7480,15 +7531,16 @@ dist_item: // ==IEEE: dist_item + dist_weight { $$ = new AstDistItem{$2, $1, $3}; } | value_range yP_COLONDIV expr { $$ = new AstDistItem{$2, $1, $3}; $$->isWhole(true); } - // // IEEE 1800-2023 added: + // // IEEE 1800-2023 added: | yDEFAULT yP_COLONDIV expr { BBUNSUP($2, "Unsupported: 'default :/' constraint"); $$ = nullptr; } ; -extern_constraint_declaration: // ==IEEE: extern_constraint_declaration - constraintStaticE yCONSTRAINT dynamic_override_specifiersE packageClassScopeE idAny constraint_block - { $$ = nullptr; BBUNSUP($2, "Unsupported: extern constraint"); } +extern_constraint_declaration: // ==IEEE: extern_constraint_declaration + constraintStaticE yCONSTRAINT dynamic_override_specifiersE packageClassScopeE constraintIdNew constraint_block + { $$ = $5; $$->isStatic($1); $$->isExternDef(true); + $$->baseOverride($3); $$->classOrPackagep($4); $$->addItemsp($6); SYMP->popScope($5); } ; constraintStaticE: // IEEE: part of extern_constraint_declaration @@ -7517,77 +7569,89 @@ colon: // Generic colon that isn't making a label (e.g. // VLT Files vltItem: - + // // TODO support arbitrary order of arguments vltOffFront { V3Config::addIgnore($1, false, "*", 0, 0); } - | vltOffFront yVLT_D_FILE yaSTRING - { V3Config::addIgnore($1, false, *$3, 0, 0); } - | vltOffFront yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM - { V3Config::addIgnore($1, false, *$3, $5->toUInt(), $5->toUInt() + 1); } - | vltOffFront yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM '-' yaINTNUM - { V3Config::addIgnore($1, false, *$3, $5->toUInt(), $7->toUInt() + 1); } - | vltOffFront yVLT_D_SCOPE yaSTRING - { if ($1 != V3ErrorCode::I_TRACING) { - $1->v3error("Argument -scope only supported for tracing_on/off"); - } else { - V3Config::addScopeTraceOn(false, *$3, 0); - }} - | vltOffFront yVLT_D_SCOPE yaSTRING yVLT_D_LEVELS yaINTNUM - { if ($1 != V3ErrorCode::I_TRACING) { - $1->v3error("Argument -scope only supported for tracing_on/off_off"); - } else { - V3Config::addScopeTraceOn(false, *$3, $5->toUInt()); - }} - | vltOffFront yVLT_D_FILE yaSTRING yVLT_D_MATCH yaSTRING + | vltOffFront vltDFile + { V3Config::addIgnore($1, false, *$2, 0, 0); } + | vltOffFront vltDFile yVLT_D_LINES yaINTNUM + { V3Config::addIgnore($1, false, *$2, $4->toUInt(), $4->toUInt() + 1); } + | vltOffFront vltDFile yVLT_D_LINES yaINTNUM '-' yaINTNUM + { V3Config::addIgnore($1, false, *$2, $4->toUInt(), $6->toUInt() + 1); } + | vltOffFront vltDFile vltDMatch { if (($1 == V3ErrorCode::I_COVERAGE) || ($1 == V3ErrorCode::I_TRACING)) { $1->v3error("Argument -match only supported for lint_off"); } else { - V3Config::addIgnoreMatch($1, *$3, *$5); + V3Config::addIgnoreMatch($1, *$2, "", *$3); }} - | vltOnFront - { V3Config::addIgnore($1, true, "*", 0, 0); } - | vltOnFront yVLT_D_FILE yaSTRING - { V3Config::addIgnore($1, true, *$3, 0, 0); } - | vltOnFront yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM - { V3Config::addIgnore($1, true, *$3, $5->toUInt(), $5->toUInt() + 1); } - | vltOnFront yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM '-' yaINTNUM - { V3Config::addIgnore($1, true, *$3, $5->toUInt(), $7->toUInt() + 1); } - | vltOnFront yVLT_D_SCOPE yaSTRING + | vltOffFront vltDFile vltDContents + { if (($1 == V3ErrorCode::I_COVERAGE) || ($1 == V3ErrorCode::I_TRACING)) { + $1->v3error("Argument -match only supported for lint_off"); + } else { + V3Config::addIgnoreMatch($1, *$2, *$3, "*"); + }} + | vltOffFront vltDFile vltDContents vltDMatch + { if (($1 == V3ErrorCode::I_COVERAGE) || ($1 == V3ErrorCode::I_TRACING)) { + $1->v3error("Argument -match only supported for lint_off"); + } else { + V3Config::addIgnoreMatch($1, *$2, *$3, *$4); + }} + | vltOffFront vltDScope { if ($1 != V3ErrorCode::I_TRACING) { $1->v3error("Argument -scope only supported for tracing_on/off"); } else { - V3Config::addScopeTraceOn(true, *$3, 0); + V3Config::addScopeTraceOn(false, *$2, 0); }} - | vltOnFront yVLT_D_SCOPE yaSTRING yVLT_D_LEVELS yaINTNUM + | vltOffFront vltDScope vltDLevels { if ($1 != V3ErrorCode::I_TRACING) { $1->v3error("Argument -scope only supported for tracing_on/off_off"); } else { - V3Config::addScopeTraceOn(true, *$3, $5->toUInt()); + V3Config::addScopeTraceOn(false, *$2, $3->toUInt()); + }} + | vltOnFront + { V3Config::addIgnore($1, true, "*", 0, 0); } + | vltOnFront vltDFile + { V3Config::addIgnore($1, true, *$2, 0, 0); } + | vltOnFront vltDFile yVLT_D_LINES yaINTNUM + { V3Config::addIgnore($1, true, *$2, $4->toUInt(), $4->toUInt() + 1); } + | vltOnFront vltDFile yVLT_D_LINES yaINTNUM '-' yaINTNUM + { V3Config::addIgnore($1, true, *$2, $4->toUInt(), $6->toUInt() + 1); } + | vltOnFront vltDScope + { if ($1 != V3ErrorCode::I_TRACING) { + $1->v3error("Argument -scope only supported for tracing_on/off"); + } else { + V3Config::addScopeTraceOn(true, *$2, 0); + }} + | vltOnFront vltDScope vltDLevels + { if ($1 != V3ErrorCode::I_TRACING) { + $1->v3error("Argument -scope only supported for tracing_on/off_off"); + } else { + V3Config::addScopeTraceOn(true, *$2, $3->toUInt()); }} | vltVarAttrFront vltDModuleE vltDFTaskE vltVarAttrVarE attr_event_controlE { V3Config::addVarAttr($1, *$2, *$3, *$4, $1, $5); } | vltInlineFront vltDModuleE vltDFTaskE { V3Config::addInline($1, *$2, *$3, $1); } - | yVLT_COVERAGE_BLOCK_OFF yVLT_D_FILE yaSTRING - { V3Config::addCoverageBlockOff(*$3, 0); } - | yVLT_COVERAGE_BLOCK_OFF yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM - { V3Config::addCoverageBlockOff(*$3, $5->toUInt()); } - | yVLT_COVERAGE_BLOCK_OFF yVLT_D_MODULE yaSTRING yVLT_D_BLOCK yaSTRING - { V3Config::addCoverageBlockOff(*$3, *$5); } - | yVLT_FULL_CASE yVLT_D_FILE yaSTRING - { V3Config::addCaseFull(*$3, 0); } - | yVLT_FULL_CASE yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM - { V3Config::addCaseFull(*$3, $5->toUInt()); } + | yVLT_COVERAGE_BLOCK_OFF vltDFile + { V3Config::addCoverageBlockOff(*$2, 0); } + | yVLT_COVERAGE_BLOCK_OFF vltDFile yVLT_D_LINES yaINTNUM + { V3Config::addCoverageBlockOff(*$2, $4->toUInt()); } + | yVLT_COVERAGE_BLOCK_OFF vltDModule vltDBlock + { V3Config::addCoverageBlockOff(*$2, *$3); } + | yVLT_FULL_CASE vltDFile + { V3Config::addCaseFull(*$2, 0); } + | yVLT_FULL_CASE vltDFile yVLT_D_LINES yaINTNUM + { V3Config::addCaseFull(*$2, $4->toUInt()); } | yVLT_HIER_BLOCK vltDModuleE { V3Config::addModulePragma(*$2, VPragmaType::HIER_BLOCK); } | yVLT_HIER_PARAMS vltDModuleE { V3Config::addModulePragma(*$2, VPragmaType::HIER_PARAMS); } - | yVLT_PARALLEL_CASE yVLT_D_FILE yaSTRING - { V3Config::addCaseParallel(*$3, 0); } - | yVLT_PARALLEL_CASE yVLT_D_FILE yaSTRING yVLT_D_LINES yaINTNUM - { V3Config::addCaseParallel(*$3, $5->toUInt()); } - | yVLT_PROFILE_DATA yVLT_D_MODEL yaSTRING yVLT_D_MTASK yaSTRING yVLT_D_COST yaINTNUM - { V3Config::addProfileData($1, *$3, *$5, $7->toUQuad()); } + | yVLT_PARALLEL_CASE vltDFile + { V3Config::addCaseParallel(*$2, 0); } + | yVLT_PARALLEL_CASE vltDFile yVLT_D_LINES yaINTNUM + { V3Config::addCaseParallel(*$2, $4->toUInt()); } + | yVLT_PROFILE_DATA vltDModel vltDMtask vltDCost + { V3Config::addProfileData($1, *$2, *$3, $4->toUQuad()); } ; vltOffFront: @@ -7614,9 +7678,49 @@ vltOnFront: if ($$ == V3ErrorCode::EC_ERROR) { $1->v3error("Unknown error code: '" << *$3 << "'"); } } ; -vltDModuleE: +vltDBlock: // --block + yVLT_D_BLOCK str { $$ = $2; } + ; + +vltDContents: + yVLT_D_CONTENTS str { $$ = $2; } + ; + +vltDCost: // --cost + yVLT_D_COST yaINTNUM { $$ = $2; } + ; + +vltDFile: // --file + yVLT_D_FILE str { $$ = $2; } + ; + +vltDLevels: // --levels + yVLT_D_LEVELS yaINTNUM { $$ = $2; } + ; + +vltDMatch: // --match + yVLT_D_MATCH str { $$ = $2; } + ; + +vltDModel: // --model + yVLT_D_MODEL str { $$ = $2; } + ; + +vltDMtask: // --mtask + yVLT_D_MTASK str { $$ = $2; } + ; + +vltDModule: // --module + yVLT_D_MODULE str { $$ = $2; } + ; + +vltDModuleE: // [--module ] /* empty */ { static string unit = "__024unit"; $$ = &unit; } - | yVLT_D_MODULE str { $$ = $2; } + | vltDModule { $$ = $1; } + ; + +vltDScope: // --scope + yVLT_D_SCOPE str { $$ = $2; } ; vltDFTaskE: diff --git a/src/vlcovgen b/src/vlcovgen index 819556b6f..28c70e423 100755 --- a/src/vlcovgen +++ b/src/vlcovgen @@ -78,7 +78,7 @@ parser = argparse.ArgumentParser( allow_abbrev=False, formatter_class=argparse.RawDescriptionHelpFormatter, description="""Generate verilated_cov headers to reduce C++ code duplication.""", - epilog="""Copyright 2002-2024 by Wilson Snyder. This program is free software; you + epilog="""Copyright 2002-2025 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it 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 bc75319c7..274813b07 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-2024 by Wilson Snyder. This program is free software; you +# Copyright 2003-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it 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 509d2624a..0ff0e757f 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-2024 by Wilson Snyder. This program is free software; you +# Copyright 2003-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it 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 5e1fa1424..81620d2f1 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-2024 by Wilson Snyder. This program is free software; you +# Copyright 2003-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it 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/driver.py b/test_regress/driver.py index 71d3ed4d0..86ff9f340 100755 --- a/test_regress/driver.py +++ b/test_regress/driver.py @@ -48,6 +48,8 @@ test = None Arg_Tests = [] Quitting = False Vltmt_Threads = 3 +forker = None +Start = None # So an 'import vltest_bootstrap' inside test files will do nothing sys.modules['vltest_bootstrap'] = {} @@ -178,7 +180,7 @@ class Capabilities: if Capabilities._cached_have_solver is None: out = VtOs.run_capture('(z3 --help || cvc5 --help || cvc4 --help) 2>/dev/null', check=False) - Capabilities._cached_have_solver = bool('Usage' in out) + Capabilities._cached_have_solver = bool('usage' in out.casefold()) return Capabilities._cached_have_solver @staticproperty @@ -447,7 +449,7 @@ class Runner: else: error_msg = test.errors if test.errors else test.errors_keep_going test.oprint("FAILED: " + error_msg) - makecmd = VtOs.getenv_def('VERILATOR_MAKE', os.environ['MAKE']) + " &&" + makecmd = VtOs.getenv_def('VERILATOR_MAKE', os.environ['MAKE'] + "&&") upperdir = 'test_regress/' if re.search(r'test_regress', os.getcwd()) else '' self.fail_msgs.append("\t#" + test.soprint("%Error: " + error_msg) + "\t\t" + makecmd + " " + upperdir + test.py_filename + ' ' + @@ -601,6 +603,7 @@ class VlTest: self.running_id = running_id self.scenario = scenario + self._force_pass = False self._have_solver_called = False self._inputs = {} self._ok = False @@ -658,7 +661,7 @@ class VlTest: scen_dir = re.sub(r'^t/\.\./', '', scen_dir) # Not mkpath so error if try to build somewhere odd VtOs.mkdir_ok(scen_dir) - self.obj_dir = scen_dir + "/" + self.name + self.obj_dir = scen_dir + "/" + self.name + Args.obj_suffix define_opt = self._define_opt_calc() @@ -683,7 +686,8 @@ class VlTest: self.all_run_flags = [] self.pli_flags = [ - "-I" + os.environ['VERILATOR_ROOT'] + "/include/vltstd", "-fPIC", "-shared" + "-I" + os.environ['VERILATOR_ROOT'] + "/include/vltstd", + "-I" + os.environ['VERILATOR_ROOT'] + "/include", "-fPIC", "-shared" ] if platform.system() == 'Darwin': self.pli_flags += ["-Wl,-undefined,dynamic_lookup"] @@ -811,6 +815,8 @@ class VlTest: """Called from tests as: error("Reason message") Newline is optional. Only first line is passed to summaries Throws a VtErrorException, so rest of testing is not executed""" + if self._force_pass: + return message = message.rstrip() + "\n" print("%Warning: " + self.scenario + "/" + self.name + ": " + message, file=sys.stderr, @@ -823,7 +829,7 @@ class VlTest: def error_keep_going(self, message: str) -> None: """Called from tests as: error_keep_going("Reason message") Newline is optional. Only first line is passed to summaries""" - if self._quit: + if self._quit or self._force_pass: return message = message.rstrip() + "\n" print("%Warning: " + self.scenario + "/" + self.name + ": " + message, @@ -1628,7 +1634,7 @@ class VlTest: return VtOs.run_capture(cmd, check=check) def setenv(self, var: str, val: str) -> None: - """Set enviornment variable""" + """Set environment variable""" print("\texport %s='%s'" % (var, val)) os.environ[var] = val @@ -1707,6 +1713,9 @@ class VlTest: got = proc.stdout.readinto(rawbuf) if got: data = rawbuf[0:got] + if re.search(r'--debug-exit-uvm23: Exiting', str(data)): + self._force_pass = True + print("EXIT: " + str(data)) if tee: sys.stdout.write(data.decode('latin-1')) if Args.interactive_debugger: @@ -1738,20 +1747,12 @@ class VlTest: print("driver: Leaving directory '" + os.path.abspath(entering) + "'") if not fails and status: - firstline = "" - if logfile: - with open(logfile, 'r', encoding="utf8") as fh: - for line in fh: - line = line.rstrip() - if re.match(r'^- ', line): # Debug message - continue - firstline = line - break - self.error("Exec of " + cmd[0] + " failed: " + firstline) + firstline = self._error_log_summary(logfile) + self.error("Exec of " + self._error_cmd_simplify(cmd) + " failed: " + firstline) if fails and status: print("(Exec expected to fail, and did.)") if fails and not status: - self.error("Exec of " + cmd[0] + " ok, but expected to fail") + self.error("Exec of " + self._error_cmd_simplify(cmd) + " ok, but expected to fail") if self.errors or self._skips: return False @@ -1790,17 +1791,34 @@ class VlTest: # Little utilities @staticmethod - def _try_regex(text: str, regex) -> None: - # Try to eval a regexp - # Returns: - # 1 if $text ~= /$regex/ms - # 0 if no match - # -1 if $regex is invalid, doesn't compile - try: - m = re.search(regex, text) - return 1 if m else 0 - except re.error: - return -1 + def _error_cmd_simplify(cmd: list) -> str: + if cmd[0] == "perl" and re.search(r'/bin/verilator', cmd[1]): + return "verilator" + return cmd[0] + + def _error_log_summary(self, filename: str) -> str: + size = "" + if False: # Show test size for fault grading # pylint: disable=using-constant-test + if self.top_filename and os.path.exists(self.top_filename): + size = "(Test " + str(os.stat(self.top_filename).st_size) + " B) " + if not filename: + return size + firstline = "" + with open(filename, 'r', encoding="utf8") as fh: + lineno = 0 + for line in fh: + lineno += 1 + if lineno > 100: + break + line = line.rstrip() + if re.match(r'^- ', line): # Debug message + continue + if not firstline: + firstline = line + if (re.search(r'error|warn', line, re.IGNORECASE) + and not re.search(r'-Werror', line)): + return size + line + return size + firstline def _make_main(self, timing_loop: bool) -> None: if timing_loop and self.sc: @@ -2409,7 +2427,7 @@ class VlTest: if VlTest._cached_cfg_with_ccache is None: mkf = VlTest._file_contents_static(os.environ['VERILATOR_ROOT'] + "/include/verilated.mk") - VlTest._cached_cfg_with_ccache = bool(re.match(r'OBJCACHE \?= ccache', mkf)) + VlTest._cached_cfg_with_ccache = bool(re.search(r'OBJCACHE \?= ccache', mkf)) return VlTest._cached_cfg_with_ccache def glob_some(self, pattern: str) -> list: @@ -2447,7 +2465,7 @@ class VlTest: if not match: self.error("File_grep: " + filename + ": Regexp not found: " + regexp) return None - if expvalue and str(expvalue) != match.group(1): + if expvalue is not None and str(expvalue) != match.group(1): self.error("File_grep: " + filename + ": Got='" + match.group(1) + "' Expected='" + str(expvalue) + "' in regexp: '" + regexp + "'") return None @@ -2469,7 +2487,7 @@ class VlTest: return match = re.search(regexp, contents) if match: - if expvalue and str(expvalue) != match.group(1): + if expvalue is not None and str(expvalue) != match.group(1): self.error("file_grep: " + filename + ": Got='" + match.group(1) + "' Expected='" + str(expvalue) + "' in regexp: " + regexp) return @@ -2691,7 +2709,6 @@ if __name__ == '__main__': sys.exit("%Error: TEST_REGRESS environment variable is already set") os.environ['TEST_REGRESS'] = os.getcwd() - forker = None Start = time.time() _Parameter_Next_Level = None @@ -2715,7 +2732,7 @@ if __name__ == '__main__': epilog="""driver.py invokes Verilator or another simulator on each test file. See docs/internals.rst in the distribution for more information. - Copyright 2024-2024 by Wilson Snyder. This program is free software; you + Copyright 2024-2025 by Wilson Snyder. This program is free software; you can redistribute it and/or modify it under the terms of either the GNU Lesser General Public License Version 3 or the Perl Artistic License Version 2.0. @@ -2728,7 +2745,7 @@ if __name__ == '__main__': parser.add_argument('--fail-max', action='store', default=None, - help='run Verilator executable with gdb') + help='after specified number of failures, skip remaining tests') parser.add_argument('--gdb', action='store_true', help='run Verilator executable with gdb') parser.add_argument('--gdbbt', action='store_true', @@ -2742,6 +2759,10 @@ if __name__ == '__main__': default=0, type=int, help='parallel job count (0=cpu count)') + parser.add_argument('--obj-suffix', + action='store', + default='', + help='suffix to add to obj_ test directory name') parser.add_argument('--quiet', action='store_true', help='suppress output except failures and progress') diff --git a/test_regress/t/TestCheck.h b/test_regress/t/TestCheck.h index 0551634ac..d2a376f12 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-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2013-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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 a5fe6c53b..b99537a78 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-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2013-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it 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/TestVpi.h b/test_regress/t/TestVpi.h index aa44dda90..4a87b8e51 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-2024 by Wilson Snyder. This program is free software; you can +// Copyright 2013-2025 by Wilson Snyder. This program is free software; you can // redistribute it and/or modify it under the terms of either the GNU // Lesser General Public License Version 3 or the Perl Artistic License // Version 2.0. @@ -521,3 +521,47 @@ const char* strFromVpiConstType(PLI_INT32 constType) { if (constType < 0) return names[0]; return names[(constType <= vpiTimeConst) ? constType : 0]; } + +#define FILENM basename(strdup(__FILE__)) + +#define CHECK_RESULT_VH(got, exp) \ + if ((got) != (exp)) { \ + printf("%%Error: %s:%d: GOT = %p EXP = %p\n", FILENM, __LINE__, (got), (exp)); \ + return __LINE__; \ + } + +#define CHECK_RESULT_NZ(got) \ + if (!(got)) { \ + printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM, __LINE__); \ + return __LINE__; \ + } + +#define CHECK_RESULT_Z(got) \ + if (got) { \ + printf("%%Error: %s:%d: GOT = !NULL EXP = NULL\n", FILENM, __LINE__); \ + return __LINE__; \ + } + +// Use cout to avoid issues with %d/%lx etc +#define CHECK_RESULT(got, exp) \ + if ((got) != (exp)) { \ + std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << ": GOT = " << (got) \ + << " EXP = " << (exp) << std::endl; \ + return __LINE__; \ + } + +#define CHECK_RESULT_HEX(got, exp) \ + if ((got) != (exp)) { \ + std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << std::hex \ + << ": GOT = " << (got) << " EXP = " << (exp) << std::endl; \ + return __LINE__; \ + } + +#define CHECK_RESULT_CSTR(got, exp) \ + if (std::strcmp((got), (exp))) { \ + printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \ + (got) ? (got) : "", (exp) ? (exp) : ""); \ + return __LINE__; \ + } + +#define CHECK_RESULT_CSTR_STRIP(got, exp) CHECK_RESULT_CSTR(got + strspn(got, " "), exp) diff --git a/test_regress/t/t_EXAMPLE.v b/test_regress/t/t_EXAMPLE.v index 75a416220..c3eb28a02 100644 --- a/test_regress/t/t_EXAMPLE.v +++ b/test_regress/t/t_EXAMPLE.v @@ -16,6 +16,9 @@ // any use, without warranty, 2024 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 +`define stop $stop +`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0x exp=%0x (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0); + module t(/*AUTOARG*/ // Inputs clk @@ -64,10 +67,9 @@ module t(/*AUTOARG*/ end else if (cyc == 99) begin $write("[%0t] cyc==%0d crc=%x sum=%x\n", $time, cyc, crc, sum); - if (crc !== 64'hc77bb9b3784ea091) $stop; + `checkh(crc, 64'hc77bb9b3784ea091); // What checksum will we end up with (above print should match) -`define EXPECTED_SUM 64'h4afe43fb79d7b71e - if (sum !== `EXPECTED_SUM) $stop; + `checkh(sum, 64'h4afe43fb79d7b71e); $write("*-* All Finished *-*\n"); $finish; end diff --git a/test_regress/t/t_pkg_using_dollar_unit_items.py b/test_regress/t/t_array_non_blocking_loop.py similarity index 100% rename from test_regress/t/t_pkg_using_dollar_unit_items.py rename to test_regress/t/t_array_non_blocking_loop.py diff --git a/test_regress/t/t_array_non_blocking_loop.v b/test_regress/t/t_array_non_blocking_loop.v new file mode 100644 index 000000000..aada1da78 --- /dev/null +++ b/test_regress/t/t_array_non_blocking_loop.v @@ -0,0 +1,38 @@ +// DESCRIPTION: Verilator: Demonstrate struct literal param assignment problem +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + + +interface intf + #( + parameter int write_data_width) (); + logic [write_data_width-1:0] writedata; +endinterface +module t( /*AUTOARG*/ + clk +); + + input clk; + generate + genvar num_chunks; + for (num_chunks = 1; num_chunks <= 2; num_chunks++) begin : gen_n + localparam int decoded_width = 55 * num_chunks; + intf #( + .write_data_width(decoded_width)) + the_intf (); + always @(posedge clk) begin + for (int i = 0; i < decoded_width; i++) + the_intf.writedata[i] <= '1; + $display("%0d", the_intf.writedata); + end + end + endgenerate + + // finish report + always @ (posedge clk) begin + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_array_pattern_2d.v b/test_regress/t/t_array_pattern_2d.v index dba37eef2..051e1f1d8 100644 --- a/test_regress/t/t_array_pattern_2d.v +++ b/test_regress/t/t_array_pattern_2d.v @@ -13,6 +13,8 @@ module t (/*AUTOARG*/); logic [31:0] larray_assign [0:3]; logic [31:0] larray_other [0:3]; + logic [31:0] array_neg [-1:1]; + initial begin array_assign[0] = 32'd1; array_assign[3:1] = '{32'd4, 32'd3, 32'd2}; @@ -34,6 +36,11 @@ module t (/*AUTOARG*/); if (larray_other[2] != 3) $stop; if (larray_other[3] != 2) $stop; + array_neg = '{-1: 5, 1: 7, default: 'd6}; + if (array_neg[-1] != 5) $stop; + if (array_neg[0] != 6) $stop; + if (array_neg[1] != 7) $stop; + $write("*-* All Finished *-*\n"); $finish; end diff --git a/test_regress/t/t_assert_disable_bad.v b/test_regress/t/t_assert_disable_bad.v index 07b3bc342..7bb6c04ad 100644 --- a/test_regress/t/t_assert_disable_bad.v +++ b/test_regress/t/t_assert_disable_bad.v @@ -5,7 +5,8 @@ // SPDX-License-Identifier: CC0-1.0 module t (/*AUTOARG*/ - clk + // Inputs + clk ); input clk; @@ -18,8 +19,7 @@ module t (/*AUTOARG*/ end property check(int cyc_mod_2, logic expected); - @(posedge clk) - disable iff (cyc == 0) cyc % 2 == cyc_mod_2 |=> val == expected; + @(posedge clk) disable iff (cyc == 0) cyc % 2 == cyc_mod_2 |=> val == expected; endproperty // Test should fail due to duplicated disable iff statements diff --git a/test_regress/t/t_assert_disable_count.py b/test_regress/t/t_assert_disable_count.py new file mode 100755 index 000000000..2c4ffdce2 --- /dev/null +++ b/test_regress/t/t_assert_disable_count.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile(verilator_flags2=['--assert']) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_assert_disable_count.v b/test_regress/t/t_assert_disable_count.v new file mode 100644 index 000000000..3a424467c --- /dev/null +++ b/test_regress/t/t_assert_disable_count.v @@ -0,0 +1,69 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +`define stop $stop +`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0); + +module t (/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + + int cyc; + + Sub sub (); + + default disable iff (cyc[0]); + + int a_false; + always @(posedge clk iff !cyc[0]) begin + if (cyc < 4 || cyc > 9) ; + else a_false = a_false + 1; + end + + int a0_false; + a0: assert property (@(posedge clk) disable iff (cyc[0]) (cyc < 4 || cyc > 9)) + else a0_false = a0_false + 1; + + int a1_false; + // Note that Verilator supports $inferred_disable in general expression locations + // This is a superset of what IEEE specifies + a1: assert property (@(posedge clk) disable iff ($inferred_disable) (cyc < 4 || cyc > 9)) + else a1_false = a1_false + 1; + + int a2_false; + // Implicitly uses $inferred_disable + a2: assert property (@(posedge clk) (cyc < 4 || cyc > 9)) + else a2_false = a2_false + 1; + + int a3_false; + // A different disable iff expression + a3: assert property (@(posedge clk) disable iff (cyc == 5) (cyc < 4 || cyc > 9)) + else a3_false = a3_false + 1; + + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 20) begin + `checkd(a_false, 3); + `checkd(a0_false, a_false); + `checkd(a1_false, a_false); + `checkd(a2_false, a_false); + `checkd(a3_false, 5); + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule + +module Sub; + + initial begin + if ($inferred_disable !== 0) $stop; + end + +endmodule diff --git a/test_regress/t/t_assert_disable_iff.v b/test_regress/t/t_assert_disable_iff.v index 7a5b2b2fd..23ec387bc 100644 --- a/test_regress/t/t_assert_disable_iff.v +++ b/test_regress/t/t_assert_disable_iff.v @@ -10,73 +10,47 @@ module t (/*AUTOARG*/ ); input clk; - integer cyc; initial cyc=1; + int cyc; Test test (/*AUTOINST*/ // Inputs .clk (clk)); - always @ (posedge clk) begin - if (cyc!=0) begin - cyc <= cyc + 1; - if (cyc==10) begin - $write("*-* All Finished *-*\n"); - $finish; - end + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 10) begin + $write("*-* All Finished *-*\n"); + $finish; end end endmodule -module Test - ( - input clk - ); +module Test ( + input clk +); `ifdef FAIL_ASSERT_1 - assert property ( - @(posedge clk) disable iff (0) - 0 - ) else $display("wrong disable"); + assert property (@(posedge clk) disable iff (0) 0) + else $display("wrong disable"); `endif - assert property ( - @(posedge clk) disable iff (1) - 0 - ); + assert property (@(posedge clk) disable iff (1) 0); - assert property ( - @(posedge clk) disable iff (1) - 1 - ); + assert property (@(posedge clk) disable iff (1) 1); - assert property ( - @(posedge clk) disable iff (0) - 1 - ); + assert property (@(posedge clk) disable iff (0) 1); // // Cover properties behave differently // - cover property ( - @(posedge clk) disable iff (1) - 1 - ) $stop; + cover property (@(posedge clk) disable iff (1) 1) $stop; - cover property ( - @(posedge clk) disable iff (1) - 0 - ) $stop; + cover property (@(posedge clk) disable iff (1) 0) $stop; - cover property ( - @(posedge clk) disable iff (0) - 1 - ) $display("*COVER: ok"); + cover property (@(posedge clk) disable iff (0) 1) $display("*COVER: ok"); - cover property ( - @(posedge clk) disable iff (0) - 0 - ) $stop; + cover property (@(posedge clk) disable iff (0) 0) $stop; endmodule diff --git a/test_regress/t/t_assert_property_var_unsup.out b/test_regress/t/t_assert_property_var_unsup.out index ad85bd9df..16e308717 100644 --- a/test_regress/t/t_assert_property_var_unsup.out +++ b/test_regress/t/t_assert_property_var_unsup.out @@ -1,10 +1,14 @@ -%Error: t/t_assert_property_var_unsup.v:17:11: syntax error, unexpected IDENTIFIER, expecting "'{" +%Error-UNSUPPORTED: t/t_assert_property_var_unsup.v:17:11: Unsupported: property variable declaration 17 | int prevcyc; | ^~~~~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error: t/t_assert_property_var_unsup.v:18:7: syntax error, unexpected '(', expecting endproperty + 18 | (valid, prevcyc = cyc) |=> (cyc == prevcyc + 1); + | ^ %Error-UNSUPPORTED: t/t_assert_property_var_unsup.v:24:31: Unsupported: property variable default value 24 | property with_def(int nine = 9); | ^ - ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest %Error: Internal Error: t/t_assert_property_var_unsup.v:7:8: ../V3ParseSym.h:#: Symbols suggest ending PROPERTY 'prop' but parser thinks ending MODULE 't' 7 | module t ( | ^ + ... See the manual at https://verilator.org/verilator_doc.html for more assistance. diff --git a/test_regress/t/t_balance_cats.py b/test_regress/t/t_balance_cats.py new file mode 100755 index 000000000..b3cdbade4 --- /dev/null +++ b/test_regress/t/t_balance_cats.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=["--stats"]) + +test.file_grep(test.stats, r'Optimizations, FuncOpt concat trees balanced\s+(\d+)', 1) +test.file_grep(test.stats, r'Optimizations, FuncOpt concat splits\s+(\d+)', 62) + +test.passes() diff --git a/test_regress/t/t_balance_cats.v b/test_regress/t/t_balance_cats.v new file mode 100644 index 000000000..4562ca1e5 --- /dev/null +++ b/test_regress/t/t_balance_cats.v @@ -0,0 +1,35 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +// verilator lint_off UNOPTFLAT + +module t(i, o); + localparam N = 2000; // Deliberately not multiple of 32 + + input i; + wire [N-1:0] i; + + output o; + wire [N-1:0] o; + + for (genvar n = 0 ; n + 31 < N ; n += 32) begin + assign o[n+ 0 +: 1] = i[(N-1-n)- 0 -: 1]; + assign o[n+ 1 +: 1] = i[(N-1-n)- 1 -: 1]; + assign o[n+ 2 +: 2] = i[(N-1-n)- 2 -: 2]; + assign o[n+ 4 +: 4] = i[(N-1-n)- 4 -: 4]; + assign o[n+ 8 +: 8] = i[(N-1-n)- 8 -: 8]; + assign o[n+16 +: 8] = i[(N-1-n)-16 -: 8]; + assign o[n+24 +: 4] = i[(N-1-n)-24 -: 4]; + assign o[n+28 +: 2] = i[(N-1-n)-28 -: 2]; + assign o[n+30 +: 1] = i[(N-1-n)-30 -: 1]; + assign o[n+31 +: 1] = i[(N-1-n)-31 -: 1]; + end + + for (genvar n = N / 32 * 32; n < N ; ++n) begin + assign o[n] = i[N-1-n]; + end + +endmodule diff --git a/test_regress/t/t_balance_cats_nofunc.py b/test_regress/t/t_balance_cats_nofunc.py new file mode 100755 index 000000000..6ce07d2c6 --- /dev/null +++ b/test_regress/t/t_balance_cats_nofunc.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.top_filename = "t/t_balance_cats.v" + +test.compile(verilator_flags2=["--stats", "-fno-func-opt"]) + +test.file_grep_not(test.stats, r'Optimizations, FuncOpt concat trees balances') +test.file_grep_not(test.stats, r'Optimizations, FuncOpt concat splits') + +test.passes() diff --git a/test_regress/t/t_class_extends_arg.out b/test_regress/t/t_class_extends_arg.out new file mode 100644 index 000000000..a1ec3e818 --- /dev/null +++ b/test_regress/t/t_class_extends_arg.out @@ -0,0 +1,8 @@ +%Error-UNSUPPORTED: t/t_class_extends_arg.v:14:25: Unsupported: 'extends' with 'default' + 14 | class Cls1 extends Base1(default); + | ^ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error-UNSUPPORTED: t/t_class_extends_arg.v:18:25: Unsupported: 'extends' with class list_of_arguments + 18 | class Cls5 extends Base1(5); + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_class_extends_arg.py b/test_regress/t/t_class_extends_arg.py new file mode 100755 index 000000000..30c3d4f77 --- /dev/null +++ b/test_regress/t/t_class_extends_arg.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(fails=test.vlt_all, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_class_extends_arg.v b/test_regress/t/t_class_extends_arg.v new file mode 100644 index 000000000..c32818463 --- /dev/null +++ b/test_regress/t/t_class_extends_arg.v @@ -0,0 +1,36 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2020 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Base1; + int s = 2; + function new(int def = 3); + s = def; + endfunction +endclass + +class Cls1 extends Base1(default); + // Gets new(int def) +endclass + +class Cls5 extends Base1(5); + // Gets new() +endclass + +module t (/*AUTOARG*/); + initial begin + Cls1 c1; + Cls1 c5; + c1 = new(57); + if (c1.s !== 57) $stop; + + c5 = new; + if (c5.s !== 5) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_class_extends_nf_bad.out b/test_regress/t/t_class_extends_nf_bad.out index d01cc3eea..b0aac0bf5 100644 --- a/test_regress/t/t_class_extends_nf_bad.out +++ b/test_regress/t/t_class_extends_nf_bad.out @@ -1,5 +1,9 @@ -%Error: t/t_class_extends_nf_bad.v:10:19: Class for 'extends' not found: 'IsNotFound' +%Error: t/t_class_extends_nf_bad.v:15:19: Class for 'extends' not found: 'IsNotFound' : ... Suggested alternative: 'IsFound' - 10 | class Cls extends IsNotFound; + 15 | class Cls extends IsNotFound; | ^~~~~~~~~~ +%Error: t/t_class_extends_nf_bad.v:18:25: Class for 'extends' not found: 'NotFound2' + : ... Suggested alternative: 'otFound2' + 18 | class Cls2 extends Pkg::NotFound2; + | ^~~~~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_class_extends_nf_bad.v b/test_regress/t/t_class_extends_nf_bad.v index 2285ba8e6..533887e56 100644 --- a/test_regress/t/t_class_extends_nf_bad.v +++ b/test_regress/t/t_class_extends_nf_bad.v @@ -4,10 +4,18 @@ // any use, without warranty, 2020 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 +package Pkg; +class otFound2; +endclass +endpackage + class IsFound; endclass -class Cls extends IsNotFound; +class Cls extends IsNotFound; // BAD: not found +endclass + +class Cls2 extends Pkg::NotFound2; // BAD: not found endclass module t (/*AUTOARG*/); diff --git a/test_regress/t/t_class_mod_bad.out b/test_regress/t/t_class_mod_bad.out index 08ae3c20d..359343923 100644 --- a/test_regress/t/t_class_mod_bad.out +++ b/test_regress/t/t_class_mod_bad.out @@ -1,5 +1,7 @@ -%Error: t/t_class_mod_bad.v:21:7: '::' expected to reference a class/package but referenced 'MODULE 'M'' - : ... Suggest '.' instead of '::' +%Error: t/t_class_mod_bad.v:21:7: Package/class for ':: reference' not found: 'M' + 21 | M::Cls p; + | ^ +%Error: t/t_class_mod_bad.v:21:7: Package/class for 'class/package reference' not found: 'M' 21 | M::Cls p; | ^ %Error: Exiting due to diff --git a/test_regress/t/t_class_new_scoped.out b/test_regress/t/t_class_new_scoped.out new file mode 100644 index 000000000..2e1ac485d --- /dev/null +++ b/test_regress/t/t_class_new_scoped.out @@ -0,0 +1,13 @@ +%Error: t/t_class_new_scoped.v:45:21: syntax error, unexpected new, expecting IDENTIFIER-for-type + 45 | b = ClsNoArg::new; + | ^~~ +%Error: t/t_class_new_scoped.v:50:19: syntax error, unexpected new-then-paren, expecting IDENTIFIER-for-type + 50 | b = ClsArg::new(20, 1); + | ^~~ +%Error: t/t_class_new_scoped.v:55:27: syntax error, unexpected new-then-paren, expecting IDENTIFIER-for-type + 55 | b = ClsParam#(100)::new(33); + | ^~~ +%Error: t/t_class_new_scoped.v:60:27: syntax error, unexpected new-then-paren, expecting IDENTIFIER-for-type + 60 | b = ClsParam#(200)::new(44); + | ^~~ +%Error: Exiting due to diff --git a/test_regress/t/t_randomize_extern.py b/test_regress/t/t_class_new_scoped.py similarity index 100% rename from test_regress/t/t_randomize_extern.py rename to test_regress/t/t_class_new_scoped.py diff --git a/test_regress/t/t_class_new_scoped.v b/test_regress/t/t_class_new_scoped.v new file mode 100644 index 000000000..e1c5d1f65 --- /dev/null +++ b/test_regress/t/t_class_new_scoped.v @@ -0,0 +1,66 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +`define stop $stop +`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0); + +class Base; + int imembera = 10; + function new(int i); + imembera = i; + endfunction +endclass + +class ClsNoArg extends Base; + function new(); + super.new(5); + endfunction : new +endclass + +class ClsArg extends Base; + function new(int i, int j); + super.new(i + j); + endfunction +endclass + +class ClsParam #(int ADD = 100) extends Base; + function new(int def = 42); + super.new(def + ADD); + endfunction +endclass + +module t (/*AUTOARG*/); + initial begin + Base b; + ClsNoArg c1; + ClsArg c2; + ClsParam#(100) c3; + ClsParam#(200) c4; + + c1 = new; + `checkd(c1.imembera, 5); + b = ClsNoArg::new; + `checkd(b.imembera, 5); + + c2 = new(20, 1); + `checkd(c2.imembera, 21); + b = ClsArg::new(20, 1); + `checkd(b.imembera, 21); + + c3 = new(33); + `checkd(c3.imembera, 133); + b = ClsParam#(100)::new(33); + `checkd(b.imembera, 133); + + c4 = new(44); + `checkd(c4.imembera, 244); + b = ClsParam#(200)::new(44); + `checkd(b.imembera, 244); + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_class_param_bad2.out b/test_regress/t/t_class_param_bad2.out index 1eadc4902..6def63ba0 100644 --- a/test_regress/t/t_class_param_bad2.out +++ b/test_regress/t/t_class_param_bad2.out @@ -1,5 +1,9 @@ -%Error: t/t_class_param_bad2.v:12:4: Missing type parameter: 'PARAMB' +%Error: t/t_class_param_bad2.v:12:4: Class parameter type without default value is never given value (IEEE 1800-2023 6.20.1): 'PARAMB' : ... note: In instance 't' 12 | Cls c; | ^~~ +%Error: t/t_class_param_bad2.v:7:18: Parameter type without default value is never given value (IEEE 1800-2023 6.20.1): 'PARAMB' + : ... note: In instance 't' + 7 | class Cls #(type PARAMB); + | ^~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_class_param_comma_bad.out b/test_regress/t/t_class_param_comma_bad.out index b7de6da25..a775e47c0 100644 --- a/test_regress/t/t_class_param_comma_bad.out +++ b/test_regress/t/t_class_param_comma_bad.out @@ -1,16 +1,16 @@ -%Error: t/t_class_param_comma_bad.v:16:22: syntax error, unexpected ')', expecting TYPE-IDENTIFIER +%Error: t/t_class_param_comma_bad.v:16:22: syntax error, unexpected ')', expecting IDENTIFIER-for-type 16 | Cls #(.PARAMB(14),) ce; | ^ -%Error: t/t_class_param_comma_bad.v:17:13: syntax error, unexpected ')', expecting TYPE-IDENTIFIER +%Error: t/t_class_param_comma_bad.v:17:13: syntax error, unexpected ')', expecting IDENTIFIER-for-type 17 | Cls #(14,) cf; | ^ -%Error: t/t_class_param_comma_bad.v:18:14: syntax error, unexpected ')', expecting TYPE-IDENTIFIER +%Error: t/t_class_param_comma_bad.v:18:14: syntax error, unexpected ')', expecting IDENTIFIER-for-type 18 | Cls2 #(15,) cg; | ^ -%Error: t/t_class_param_comma_bad.v:19:23: syntax error, unexpected ')', expecting TYPE-IDENTIFIER +%Error: t/t_class_param_comma_bad.v:19:23: syntax error, unexpected ')', expecting IDENTIFIER-for-type 19 | Cls2 #(.PARAMB(16),) ch; | ^ -%Error: t/t_class_param_comma_bad.v:20:23: syntax error, unexpected ')', expecting TYPE-IDENTIFIER +%Error: t/t_class_param_comma_bad.v:20:23: syntax error, unexpected ')', expecting IDENTIFIER-for-type 20 | Cls2 #(.PARAMC(17),) ci; | ^ %Error: Exiting due to diff --git a/test_regress/t/t_class_param_noinit_bad.out b/test_regress/t/t_class_param_noinit_bad.out index 3495bc6aa..c3e85d2f3 100644 --- a/test_regress/t/t_class_param_noinit_bad.out +++ b/test_regress/t/t_class_param_noinit_bad.out @@ -1,5 +1,10 @@ -%Error: t/t_class_param_noinit_bad.v:13:7: Class parameter without initial value is never given value (IEEE 1800-2023 6.20.1): 'B' +%Error: t/t_class_param_noinit_bad.v:13:7: Class parameter without default value is never given value (IEEE 1800-2023 6.20.1): 'B' : ... note: In instance 't' 13 | Cls #(1) c; | ^~~ -%Error: Exiting due to +%Error: t/t_class_param_noinit_bad.v:13:7: Class parameter type without default value is never given value (IEEE 1800-2023 6.20.1): 'T' + : ... note: In instance 't' + 13 | Cls #(1) c; + | ^~~ +%Error: Verilator internal fault, sorry. Suggest trying --debug --gdbbt +%Error: Command Failed diff --git a/test_regress/t/t_class_param_noinit_bad.v b/test_regress/t/t_class_param_noinit_bad.v index 52398d589..856842f33 100644 --- a/test_regress/t/t_class_param_noinit_bad.v +++ b/test_regress/t/t_class_param_noinit_bad.v @@ -5,7 +5,7 @@ // SPDX-License-Identifier: CC0-1.0 // No init value is legal with classes, as long as not used without the parameter -class Cls #(int A, int B); +class Cls #(int A, int B, type T); endclass module t(/*AUTOARG*/); diff --git a/test_regress/t/t_class_ref_bad.out b/test_regress/t/t_class_ref_bad.out index d11276ec2..e675eef7e 100644 --- a/test_regress/t/t_class_ref_bad.out +++ b/test_regress/t/t_class_ref_bad.out @@ -1,4 +1,5 @@ -%Error: Internal Error: t/t_class_ref_bad.v:15:11: ../V3LinkDot.cpp:#: Bad package link +%Error: t/t_class_ref_bad.v:15:11: Package/class for ':: reference' not found: 'ClsRigh' + : ... Suggested alternative: 'ClsRight' 15 | s = ClsRigh::m_s; | ^~~~~~~ - ... See the manual at https://verilator.org/verilator_doc.html for more assistance. +%Error: Exiting due to diff --git a/test_regress/t/t_clk_concat.py b/test_regress/t/t_clk_concat.py index 66ab4b571..5aa73e2c5 100755 --- a/test_regress/t/t_clk_concat.py +++ b/test_regress/t/t_clk_concat.py @@ -18,15 +18,15 @@ test.compile(verilator_flags2=["+define+ATTRIBUTES --no-json-edit-nums"]) if test.vlt_all: test.file_grep( out_filename, - r'{"type":"VAR","name":"clk0",.*"loc":"e,74:[^"]*",.*"origName":"clk0",.*"direction":"INPUT",.*"isSigPublic":true,.*"attrClocker":"clker",.*"varType":"PORT",.*"dtypeName":"logic"' + r'{"type":"VAR","name":"clk0",.*"loc":"\w,74:[^"]*",.*"origName":"clk0",.*"direction":"INPUT",.*"isSigPublic":true,.*"attrClocker":"clker",.*"varType":"PORT",.*"dtypeName":"logic"' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"clk1",.*"loc":"e,75:[^"]*",.*"origName":"clk1",.*"direction":"INPUT",.*"isSigPublic":true,.*"attrClocker":"clker",.*"varType":"PORT",.*"dtypeName":"logic"' + r'{"type":"VAR","name":"clk1",.*"loc":"\w,75:[^"]*",.*"origName":"clk1",.*"direction":"INPUT",.*"isSigPublic":true,.*"attrClocker":"clker",.*"varType":"PORT",.*"dtypeName":"logic"' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"clk2",.*"loc":"e,76:[^"]*",.*"origName":"clk2",.*"direction":"INPUT",.*"isSigPublic":true,.*"attrClocker":"clker",.*"varType":"PORT",.*"dtypeName":"logic"' + r'{"type":"VAR","name":"clk2",.*"loc":"\w,76:[^"]*",.*"origName":"clk2",.*"direction":"INPUT",.*"isSigPublic":true,.*"attrClocker":"clker",.*"varType":"PORT",.*"dtypeName":"logic"' ) test.execute() diff --git a/test_regress/t/t_clk_concat_vlt.py b/test_regress/t/t_clk_concat_vlt.py index b634813cc..e4857e329 100755 --- a/test_regress/t/t_clk_concat_vlt.py +++ b/test_regress/t/t_clk_concat_vlt.py @@ -19,19 +19,19 @@ test.compile(verilator_flags2=["--no-json-edit-nums", "t/t_clk_concat.vlt"]) if test.vlt_all: test.file_grep( out_filename, - r'{"type":"VAR","name":"clk0",.*"loc":"f,78:[^"]*",.*"origName":"clk0",.*"direction":"INPUT",.*"isSigPublic":true,.*"attrClocker":"clker",.*"varType":"PORT",.*"dtypeName":"logic"' + r'{"type":"VAR","name":"clk0",.*"loc":"\w,78:[^"]*",.*"origName":"clk0",.*"direction":"INPUT",.*"isSigPublic":true,.*"attrClocker":"clker",.*"varType":"PORT",.*"dtypeName":"logic"' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"clk1",.*"loc":"f,79:[^"]*",.*"origName":"clk1",.*"direction":"INPUT",.*"isSigPublic":true,.*"attrClocker":"clker",.*"varType":"PORT",.*"dtypeName":"logic"' + r'{"type":"VAR","name":"clk1",.*"loc":"\w,79:[^"]*",.*"origName":"clk1",.*"direction":"INPUT",.*"isSigPublic":true,.*"attrClocker":"clker",.*"varType":"PORT",.*"dtypeName":"logic"' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"clk2",.*"loc":"f,80:[^"]*",.*"origName":"clk2",.*"direction":"INPUT",.*"isSigPublic":true,.*"attrClocker":"clker",.*"varType":"PORT",.*"dtypeName":"logic"' + r'{"type":"VAR","name":"clk2",.*"loc":"\w,80:[^"]*",.*"origName":"clk2",.*"direction":"INPUT",.*"isSigPublic":true,.*"attrClocker":"clker",.*"varType":"PORT",.*"dtypeName":"logic"' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"data_in",.*"loc":"f,82:[^"]*",.*"origName":"data_in",.*"direction":"INPUT",.*"isSigPublic":true,.*"attrClocker":"non_clker",.*"varType":"PORT",.*"dtypeName":"logic"' + r'{"type":"VAR","name":"data_in",.*"loc":"\w,82:[^"]*",.*"origName":"data_in",.*"direction":"INPUT",.*"isSigPublic":true,.*"attrClocker":"non_clker",.*"varType":"PORT",.*"dtypeName":"logic"' ) test.execute() diff --git a/test_regress/t/t_const_number_unsized_parse.py b/test_regress/t/t_const_number_unsized_parse.py new file mode 100755 index 000000000..6b8b2c82e --- /dev/null +++ b/test_regress/t/t_const_number_unsized_parse.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import signal +import vltest_bootstrap + +test.scenarios('vlt') + +test.top_filename = f"{test.obj_dir}/in.v" + +with open(test.top_filename, "w", encoding="utf8") as f: + f.write("module top;\n") + for i in range(50000): + f.write(f" int x{i} = 'd{i};\n") + f.write("endmodule\n") + +signal.alarm(30) # 30s timeout + +test.lint(verilator_flags2=[f"--max-num-width {2**29}"]) + +test.passes() diff --git a/test_regress/t/t_constraint.v b/test_regress/t/t_constraint.v index dd700f2d9..b30f4847a 100644 --- a/test_regress/t/t_constraint.v +++ b/test_regress/t/t_constraint.v @@ -9,6 +9,8 @@ class Packet; constraint a { one > 0 && one < 2; } + constraint empty { } + endclass module t (/*AUTOARG*/); diff --git a/test_regress/t/t_constraint_assoc_arr_bad.out b/test_regress/t/t_constraint_assoc_arr_bad.out new file mode 100644 index 000000000..a048591fc --- /dev/null +++ b/test_regress/t/t_constraint_assoc_arr_bad.out @@ -0,0 +1,9 @@ +%Warning-CONSTRAINTIGN: t/t_constraint_assoc_arr_bad.v:14:22: Unsupported: Associative array index widths of more than 64 bits during constraint randomization. + 14 | bit_index_arr[79'd66] == 65; + | ^ + ... For warning description see https://verilator.org/warn/CONSTRAINTIGN?v=latest + ... Use "/* verilator lint_off CONSTRAINTIGN */" and lint_on around source to disable this message. +%Warning-CONSTRAINTIGN: t/t_constraint_assoc_arr_bad.v:15:24: Unsupported: Associative array index widths of more than 64 bits during constraint randomization. + 15 | logic_index_arr[65'd3] == 70; + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_constraint_assoc_arr_bad.py b/test_regress/t/t_constraint_assoc_arr_bad.py new file mode 100755 index 000000000..efe8cc01c --- /dev/null +++ b/test_regress/t/t_constraint_assoc_arr_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_constraint_assoc_arr_bad.v b/test_regress/t/t_constraint_assoc_arr_bad.v new file mode 100644 index 000000000..2050f2643 --- /dev/null +++ b/test_regress/t/t_constraint_assoc_arr_bad.v @@ -0,0 +1,38 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by PlanV GmbH. +// SPDX-License-Identifier: CC0-1.0 + + +class AssocArrayWarningTest; + + rand int bit_index_arr [bit[78:0]]; + rand int logic_index_arr [logic[64:0]]; + + constraint c { + bit_index_arr[79'd66] == 65; + logic_index_arr[65'd3] == 70; + } + function new(); + bit_index_arr = '{79'd66:0}; + logic_index_arr = '{65'd3:0}; + endfunction + +endclass + +module t_constraint_assoc_arr_bad; + + AssocArrayWarningTest test_obj; + + initial begin + test_obj = new(); + repeat(2) begin + int success; + success = test_obj.randomize(); + if (success != 1) $stop; + end + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_randomize_array_constraints.py b/test_regress/t/t_constraint_assoc_arr_basic.py similarity index 100% rename from test_regress/t/t_randomize_array_constraints.py rename to test_regress/t/t_constraint_assoc_arr_basic.py diff --git a/test_regress/t/t_constraint_assoc_arr_basic.v b/test_regress/t/t_constraint_assoc_arr_basic.v new file mode 100644 index 000000000..105cdb96a --- /dev/null +++ b/test_regress/t/t_constraint_assoc_arr_basic.v @@ -0,0 +1,180 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by PlanV GmbH. +// SPDX-License-Identifier: CC0-1.0 + +class constrained_associative_array_basic; + + rand int int_index_arr [int]; + rand int string_index_arr [string]; + /* verilator lint_off SIDEEFFECT */ + // Constraints for both arrays + constraint int_index_constraints { + foreach (int_index_arr[i]) int_index_arr[i] inside {10, 20, 30, 40, 50}; + } + constraint string_index_constraints { + string_index_arr["Alice"] == 35; + string_index_arr["Bob"] inside {50, 60}; + string_index_arr["Charlie"] > 25; + } + + // Constructor to initialize arrays + function new(); + int_index_arr = '{1: 0, 8: 0, 7: 0}; + string_index_arr = '{"Alice": 25, "Bob": 50, "Charlie": 45}; + endfunction + + // Function to check and display the arrays + function void self_check(); + foreach (int_index_arr[i]) begin + if (!(int_index_arr[i] inside {10, 20, 30, 40, 50})) $stop; + end + foreach (string_index_arr[name]) begin + if ((name == "Alice" && string_index_arr[name] != 35) || + (name == "Bob" && !(string_index_arr[name] inside {50, 60})) || + (name == "Charlie" && string_index_arr[name] <= 25)) $stop; + end + endfunction + +endclass + +class constrained_1d_associative_array; + + rand int string_index_arr [string]; + rand int int_index_arr [int]; + rand int shortint_index_arr [shortint]; + rand int longint_index_arr[longint]; + rand int byte_index_arr [byte]; + rand int bit_index_arr [bit[5:0]]; + rand int logic_index_arr [logic[3:0]]; + rand int bit_index_arr_1 [bit[55:0]]; + + // Constraints + constraint associative_array_constraints { + string_index_arr["key1"] == 100; + string_index_arr["key2"] inside {200, 300, 400}; + int_index_arr[40000] + int_index_arr[2000000000] == 2; + shortint_index_arr[2000] == 200; + longint_index_arr[64'd4000000000] == 300; + byte_index_arr[8'd255] == 50; + bit_index_arr[6'd30] - bit_index_arr_1[56'd66] == 3; + logic_index_arr[4'b0011] == 70; + } + + function new(); + string_index_arr = '{"key1":0, "key2":0}; + int_index_arr = '{40000:0, 2000000000:0}; + shortint_index_arr = '{2000:0}; + longint_index_arr = '{64'd4000000000:0}; + byte_index_arr = '{8'd255:0}; + bit_index_arr = '{6'd30:0}; + bit_index_arr_1 = '{56'd66:0}; + logic_index_arr = '{4'd3:0}; + endfunction + + function void self_check(); + if (string_index_arr["key1"] != 100) $stop; + if (!(string_index_arr["key2"] inside {200, 300, 400})) $stop; + if ((int_index_arr[40000] + int_index_arr[2000000000]) != 2) $stop; + if (shortint_index_arr[2000] != 200) $stop; + if (longint_index_arr[64'd4000000000] != 300) $stop; + if (byte_index_arr[8'd255] != 50) $stop; + if (bit_index_arr[6'd30] - bit_index_arr_1[56'd66] != 3) $stop; + if (logic_index_arr[4'd3] != 70) $stop; + endfunction + + function void debug_display(); + $display("string_index_arr[\"key1\"] = %0d", string_index_arr["key1"]); + $display("string_index_arr[\"key2\"] = %0d", string_index_arr["key2"]); + $display("int_index_arr[40000] = %0d", int_index_arr[40000]); + $display("int_index_arr[2000000000] = %0d", int_index_arr[2000000000]); + $display("shortint_index_arr[2000] = %0d", shortint_index_arr[2000]); + $display("longint_index_arr[4000000000] = %0d", longint_index_arr[64'd4000000000]); + $display("byte_index_arr[255] = %0d", byte_index_arr[8'd255]); + $display("bit_index_arr[30] = %0d", bit_index_arr[6'd30]); + $display("bit_index_arr_1[66] = %0d", bit_index_arr_1[56'd66]); + $display("logic_index_arr[3] = %0d", logic_index_arr[4'd3]); + endfunction + +endclass + +class constrained_2d_associative_array; + + rand int string_int_index_arr [string][int]; + rand int int_bit_index_arr [int][bit[5:0]]; + rand int string_bit_index_arr [string][bit[7:0]]; + rand int unpacked_assoc_array_2d [string][2]; + + // Constraints + constraint associative_array_constraints { + string_int_index_arr["key1"][2000] == 100; + string_int_index_arr["key2"][3000] inside {200, 300, 400}; + int_bit_index_arr[40000][6'd30] == 60; + int_bit_index_arr[50000][6'd40] inside {100, 200}; + string_bit_index_arr["key3"][8'd100] == 150; + string_bit_index_arr["key4"][8'd200] inside {250, 350}; + unpacked_assoc_array_2d["key5"][0] == 7; + } + + function new(); + string_int_index_arr = '{"key1":'{2000:0}, "key2":'{3000:0}}; + int_bit_index_arr = '{40000:'{6'd30:0}, 50000:'{6'd40:0}}; + string_bit_index_arr = '{"key3":'{8'd100:0}, "key4":'{8'd200:0}}; + unpacked_assoc_array_2d["key5"][0] = 0; + unpacked_assoc_array_2d["key5"][1] = 0; + endfunction + + function void self_check(); + if (string_int_index_arr["key1"][2000] != 100) $stop; + if (!(string_int_index_arr["key2"][3000] inside {200, 300, 400})) $stop; + if (int_bit_index_arr[40000][6'd30] != 60) $stop; + if (!(int_bit_index_arr[50000][6'd40] inside {100, 200})) $stop; + if (string_bit_index_arr["key3"][8'd100] != 150) $stop; + if (!(string_bit_index_arr["key4"][8'd200] inside {250, 350})) $stop; + if (unpacked_assoc_array_2d["key5"][0] != 7) $stop; + endfunction + + function void debug_display(); + $display("string_int_index_arr[\"key1\"][2000] = %0d", string_int_index_arr["key1"][2000]); + $display("string_int_index_arr[\"key2\"][3000] = %0d", string_int_index_arr["key2"][3000]); + $display("int_bit_index_arr[40000][30] = %0d", int_bit_index_arr[40000][6'd30]); + $display("int_bit_index_arr[50000][40] = %0d", int_bit_index_arr[50000][6'd40]); + $display("string_bit_index_arr[\"key3\"][100] = %0d", string_bit_index_arr["key3"][8'd100]); + $display("string_bit_index_arr[\"key4\"][200] = %0d", string_bit_index_arr["key4"][8'd200]); + $display("unpacked_assoc_array_2d[\"key5\"][0] = %0d", unpacked_assoc_array_2d["key5"][0]); + endfunction + /* verilator lint_off SIDEEFFECT */ +endclass + +module t_constraint_assoc_arr_basic; + + constrained_associative_array_basic my_array; + constrained_1d_associative_array my_1d_array; + constrained_2d_associative_array my_2d_array; + int success; + + initial begin + my_array = new(); + success = my_array.randomize(); + if (success == 0) $stop; + my_array.self_check(); + + my_1d_array = new(); + success = my_1d_array.randomize(); + if (success == 0) $stop; + my_1d_array.self_check(); + + my_1d_array = new(); + success = my_1d_array.randomize(); + if (success == 0) $stop; + my_1d_array.self_check(); + + // my_1d_array.debug_display(); + // my_2d_array.debug_display(); + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_constraint_before_randc_bad.out b/test_regress/t/t_constraint_before_randc_bad.out new file mode 100644 index 000000000..4cbf1a3a8 --- /dev/null +++ b/test_regress/t/t_constraint_before_randc_bad.out @@ -0,0 +1,7 @@ +%Error: t/t_constraint_before_randc_bad.v:11:45: Randc variables not allowed in 'solve before' (IEEE 1800-2023 18.5.9) + 11 | constraint raint2_bad { solve b1 before b2; } + | ^~ + t/t_constraint_before_randc_bad.v:11:29: ... Location of restricting expression + 11 | constraint raint2_bad { solve b1 before b2; } + | ^~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_constraint_before_randc_bad.py b/test_regress/t/t_constraint_before_randc_bad.py new file mode 100755 index 000000000..30c3d4f77 --- /dev/null +++ b/test_regress/t/t_constraint_before_randc_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(fails=test.vlt_all, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_constraint_before_randc_bad.v b/test_regress/t/t_constraint_before_randc_bad.v new file mode 100644 index 000000000..effeefd30 --- /dev/null +++ b/test_regress/t/t_constraint_before_randc_bad.v @@ -0,0 +1,15 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Cls1; + rand bit b1; + randc int b2; + + constraint raint2_bad { solve b1 before b2; } // BAD no randc vars here +endclass + +module t (/*AUTOARG*/); +endmodule diff --git a/test_regress/t/t_constraint_dist_randc_bad.out b/test_regress/t/t_constraint_dist_randc_bad.out new file mode 100644 index 000000000..faff6e9be --- /dev/null +++ b/test_regress/t/t_constraint_dist_randc_bad.out @@ -0,0 +1,7 @@ +%Error: t/t_constraint_dist_randc_bad.v:10:23: Randc variables not allowed in 'constraint dist' (IEEE 1800-2023 18.5.3) + 10 | constraint c_bad { rc dist {3 := 0, 10 := 5}; } + | ^~ + t/t_constraint_dist_randc_bad.v:10:26: ... Location of restricting expression + 10 | constraint c_bad { rc dist {3 := 0, 10 := 5}; } + | ^~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_constraint_dist_randc_bad.py b/test_regress/t/t_constraint_dist_randc_bad.py new file mode 100755 index 000000000..30c3d4f77 --- /dev/null +++ b/test_regress/t/t_constraint_dist_randc_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(fails=test.vlt_all, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_constraint_dist_randc_bad.v b/test_regress/t/t_constraint_dist_randc_bad.v new file mode 100644 index 000000000..40cd2a770 --- /dev/null +++ b/test_regress/t/t_constraint_dist_randc_bad.v @@ -0,0 +1,14 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Cls1; + randc int rc; + + constraint c_bad { rc dist {3 := 0, 10 := 5}; } // Bad, no dist on randc +endclass + +module t (/*AUTOARG*/); +endmodule diff --git a/test_regress/t/t_constraint_dyn_queue_basic.py b/test_regress/t/t_constraint_dyn_queue_basic.py new file mode 100755 index 000000000..a2b131082 --- /dev/null +++ b/test_regress/t/t_constraint_dyn_queue_basic.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +if not test.have_solver: + test.skip("No constraint solver installed") + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_constraint_dyn_queue_basic.v b/test_regress/t/t_constraint_dyn_queue_basic.v new file mode 100755 index 000000000..f115be10c --- /dev/null +++ b/test_regress/t/t_constraint_dyn_queue_basic.v @@ -0,0 +1,113 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by PlanV GmbH. +// SPDX-License-Identifier: CC0-1.0 + +`define stop $stop +`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); + +class ConstrainedDynamicQueueArray; + rand int queue_1d[$]; + rand int queue[$][$]; + rand int dyn[][]; + rand int queue_dyn[$][]; + rand int dyn_queue[][$]; + rand int queue_unp[$][3]; + rand int unp_queue[3][$]; + rand int \array_w[ith_es]cape [3][2]; + + // Constraints for the queues and dynamic arrays + constraint queue_constraints { + foreach (queue_1d[i]) queue_1d[i] == i + 2; + foreach (queue[i, j]) queue[i][j] == (2 * i) + j; + } + + constraint dyn_constraints { + dyn[0][0] == 10; + dyn[1][0] inside {20, 30, 40}; + dyn[1][1] > 50; + dyn[0][1] < 100; + dyn[0][2] inside {5, 15, 25}; + } + + constraint queue_dyn_constraints { + foreach (queue_dyn[i, j]) queue_dyn[i][j] == i + j + 3; + } + + constraint dyn_queue_constraints { + foreach (dyn_queue[i, j]) dyn_queue[i][j] == (3 * i) + j + 2; + } + + constraint unp_queue_constraints { + foreach (unp_queue[i, j]) unp_queue[i][j] == (i * 5) + j + 1; + } + + constraint array_with_escape_constraints { + \array_w[ith_es]cape [0][0] == 6; + } + + // Constructor + function new(); + queue_1d = {1, 2, 3, 4}; + queue = '{ '{1, 2}, '{3, 4, 5}, '{6}}; + dyn = new[2]; + dyn[0] = new[3]; + dyn[1] = new[4]; + + queue_dyn = {}; + queue_dyn[0] = new[3]; + queue_dyn[1] = new[4]; + + dyn_queue = new[2]; + dyn_queue[0] = {7, 8, 9}; + dyn_queue[1] = {10}; + + queue_unp = {}; + + unp_queue[0] = {17, 18}; + unp_queue[1] = {19}; + unp_queue[2] = {20}; + endfunction + + // Self-check function + function void check(); + foreach (queue_1d[i]) `checkh(queue_1d[i], i + 2) + + foreach (queue[i, j]) `checkh(queue[i][j], (2 * i) + j) + + `checkh(dyn[0][0], 10) + `checkh(dyn[1][0] inside {20, 30, 40}, 1'b1) + `checkh(dyn[1][1] > 50, 1'b1) + `checkh(dyn[0][1] < 100, 1'b1) + `checkh(dyn[0][2] inside {5, 15, 25}, 1'b1) + + foreach (queue_dyn[i, j]) `checkh(queue_dyn[i][j], i + j + 3) + + foreach (dyn_queue[i, j]) `checkh(dyn_queue[i][j], (3 * i) + j + 2) + + `checkh(unp_queue[0][0], (0 * 5) + 0 + 1) + `checkh(unp_queue[0][1], (0 * 5) + 1 + 1) + `checkh(unp_queue[1][0], (1 * 5) + 0 + 1) + `checkh(unp_queue[2][0], (2 * 5) + 0 + 1) + + `checkh(\array_w[ith_es]cape [0][0], 6) + endfunction +endclass + +module t_constraint_dyn_queue_basic; + ConstrainedDynamicQueueArray array_test; + int success; + initial begin + $display("Test: Randomization for dynamic and mixed queues and arrays:"); + array_test = new(); + repeat(2) begin + success = array_test.randomize(); + `checkh(success, 1) + array_test.check(); + end + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_constraint_extern.py b/test_regress/t/t_constraint_extern.py new file mode 100755 index 000000000..dbae8a1dc --- /dev/null +++ b/test_regress/t/t_constraint_extern.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +if not test.have_solver: + test.skip("No constraint solver installed") + +test.compile(verilator_flags2=['-Wno-CONSTRAINTIGN']) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_constraint_extern.v b/test_regress/t/t_constraint_extern.v new file mode 100644 index 000000000..ec3888f08 --- /dev/null +++ b/test_regress/t/t_constraint_extern.v @@ -0,0 +1,41 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Packet; + rand int one; + rand int two; + + extern function void f(); + constraint cone; + extern constraint ctwo; + constraint cmissing; // Ok per IEEE 1800-2023 18.5.1 + +endclass + +constraint Packet::cone { one > 0 && one < 2; } + +constraint Packet::ctwo { two > 1 && two < 3; } + +function void Packet::f(); +endfunction + +module t (/*AUTOARG*/); + + Packet p; + + int v; + + initial begin + p = new; + v = p.randomize(); + if (v != 1) $stop; + if (p.one != 1) $stop; + if (p.two != 2) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_constraint_extern_bad.out b/test_regress/t/t_constraint_extern_bad.out new file mode 100644 index 000000000..e63efbb03 --- /dev/null +++ b/test_regress/t/t_constraint_extern_bad.out @@ -0,0 +1,7 @@ +%Error: t/t_constraint_extern_bad.v:8:22: Definition not found for extern 'missing_bad' + 8 | extern constraint missing_bad; + | ^~~~~~~~~~~ +%Error: t/t_constraint_extern_bad.v:11:20: extern not found that declares 'missing_extern' + 11 | constraint Packet::missing_extern { } + | ^~~~~~~~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_constraint_extern_bad.py b/test_regress/t/t_constraint_extern_bad.py new file mode 100755 index 000000000..30c3d4f77 --- /dev/null +++ b/test_regress/t/t_constraint_extern_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(fails=test.vlt_all, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_constraint_extern_bad.v b/test_regress/t/t_constraint_extern_bad.v new file mode 100644 index 000000000..743d9f4b1 --- /dev/null +++ b/test_regress/t/t_constraint_extern_bad.v @@ -0,0 +1,14 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Packet; + extern constraint missing_bad; +endclass + +constraint Packet::missing_extern { } + +module t (/*AUTOARG*/); +endmodule diff --git a/test_regress/t/t_constraint_json_only.out b/test_regress/t/t_constraint_json_only.out index ae7c64ed3..a146d88be 100644 --- a/test_regress/t/t_constraint_json_only.out +++ b/test_regress/t/t_constraint_json_only.out @@ -27,7 +27,7 @@ {"type":"VAR","name":"if_state_ok","addr":"(W)","loc":"d,13:13,13:24","dtypep":"(U)","origName":"if_state_ok","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VAUTOM","varType":"MEMBER","dtypeName":"bit","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"array","addr":"(X)","loc":"d,15:13,15:18","dtypep":"(Y)","origName":"array","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VAUTOM","varType":"MEMBER","dtypeName":"","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"state","addr":"(Z)","loc":"d,17:11,17:16","dtypep":"(M)","origName":"state","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VAUTOM","varType":"MEMBER","dtypeName":"string","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"FUNC","name":"strings_equal","addr":"(AB)","loc":"d,61:17,61:30","dtypep":"(U)","method":true,"dpiExport":false,"dpiImport":false,"dpiOpenChild":false,"dpiOpenParent":false,"prototype":false,"recursive":false,"taskPublic":false,"cname":"strings_equal", + {"type":"FUNC","name":"strings_equal","addr":"(AB)","loc":"d,61:17,61:30","dtypep":"(U)","method":true,"dpiExport":false,"dpiImport":false,"dpiOpenChild":false,"dpiOpenParent":false,"isExternDef":false,"isExternProto":false,"prototype":false,"recursive":false,"taskPublic":false,"cname":"strings_equal", "fvarp": [ {"type":"VAR","name":"strings_equal","addr":"(BB)","loc":"d,61:17,61:30","dtypep":"(U)","origName":"strings_equal","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":true,"isFuncLocal":true,"attrClocker":"UNKNOWN","lifetime":"VAUTOM","varType":"MEMBER","dtypeName":"bit","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"classOrPackagep": [], @@ -48,7 +48,7 @@ {"type":"VARREF","name":"strings_equal","addr":"(JB)","loc":"d,62:7,62:13","dtypep":"(U)","access":"WR","varp":"(BB)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} ],"timingControlp": []} ],"scopeNamep": []}, - {"type":"FUNC","name":"new","addr":"(KB)","loc":"d,7:1,7:6","dtypep":"(LB)","method":true,"dpiExport":false,"dpiImport":false,"dpiOpenChild":false,"dpiOpenParent":false,"prototype":false,"recursive":false,"taskPublic":false,"cname":"new","fvarp": [],"classOrPackagep": [],"stmtsp": [],"scopeNamep": []}, + {"type":"FUNC","name":"new","addr":"(KB)","loc":"d,7:1,7:6","dtypep":"(LB)","method":true,"dpiExport":false,"dpiImport":false,"dpiOpenChild":false,"dpiOpenParent":false,"isExternDef":false,"isExternProto":false,"prototype":false,"recursive":false,"taskPublic":false,"cname":"new","fvarp": [],"classOrPackagep": [],"stmtsp": [],"scopeNamep": []}, {"type":"VAR","name":"constraint","addr":"(MB)","loc":"d,7:1,7:6","dtypep":"(NB)","origName":"constraint","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"MEMBER","dtypeName":"VlRandomizer","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"activesp": [],"extendsp": []} ],"activesp": []} diff --git a/test_regress/t/t_constraint_nosolver_bad.out b/test_regress/t/t_constraint_nosolver_bad.out index 9b379f091..2f4435757 100644 --- a/test_regress/t/t_constraint_nosolver_bad.out +++ b/test_regress/t/t_constraint_nosolver_bad.out @@ -3,5 +3,5 @@ Process::open: execvp(someimaginarysolver): No such file or directory %Warning: Unable to communicate with SAT solver, please check its installation or specify a different one in VERILATOR_SOLVER environment variable. ... Tried: $ someimaginarysolver -%Error: t/t_constraint.v:23: Verilog $stop +%Error: t/t_constraint.v:25: Verilog $stop Aborting... diff --git a/test_regress/t/t_constraint_pure.py b/test_regress/t/t_constraint_pure.py new file mode 100755 index 000000000..a2b131082 --- /dev/null +++ b/test_regress/t/t_constraint_pure.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +if not test.have_solver: + test.skip("No constraint solver installed") + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_constraint_pure.v b/test_regress/t/t_constraint_pure.v new file mode 100644 index 000000000..c3fc3f64a --- /dev/null +++ b/test_regress/t/t_constraint_pure.v @@ -0,0 +1,26 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +virtual class Base; + pure constraint raint; +endclass + +class Cls extends Base; + rand int b2; + constraint raint { b2 == 5; } +endclass + +virtual class Virt extends Base; + // No constraint needed +endclass + +module t; + initial begin + Cls c = new; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_constraint_pure_missing_bad.out b/test_regress/t/t_constraint_pure_missing_bad.out new file mode 100644 index 000000000..e9b226c01 --- /dev/null +++ b/test_regress/t/t_constraint_pure_missing_bad.out @@ -0,0 +1,7 @@ +%Error: t/t_constraint_pure_missing_bad.v:11:1: Class 'Cls' extends 'Base' but is missing constraint implementation for 'raint' (IEEE 1800-2023 18.5.2) + 11 | class Cls extends Base; + | ^~~~~ + t/t_constraint_pure_missing_bad.v:8:21: ... Location of interface class's pure constraint + 8 | pure constraint raint; + | ^~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_constraint_pure_missing_bad.py b/test_regress/t/t_constraint_pure_missing_bad.py new file mode 100755 index 000000000..e33e10acf --- /dev/null +++ b/test_regress/t/t_constraint_pure_missing_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_constraint_pure_missing_bad.v b/test_regress/t/t_constraint_pure_missing_bad.v new file mode 100644 index 000000000..9d81382d5 --- /dev/null +++ b/test_regress/t/t_constraint_pure_missing_bad.v @@ -0,0 +1,16 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +virtual class Base; + pure constraint raint; +endclass + +class Cls extends Base; + // Bad: Missing 'constraint raint' +endclass + +module t; +endmodule diff --git a/test_regress/t/t_constraint_pure_nonabs_bad.out b/test_regress/t/t_constraint_pure_nonabs_bad.out new file mode 100644 index 000000000..039a415a0 --- /dev/null +++ b/test_regress/t/t_constraint_pure_nonabs_bad.out @@ -0,0 +1,5 @@ +%Error: t/t_constraint_pure_nonabs_bad.v:8:21: Illegal to have 'pure constraint' in non-abstract class (IEEE 1800-2023 18.5.2) + : ... note: In instance 't' + 8 | pure constraint raintBad; + | ^~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_constraint_pure_nonabs_bad.py b/test_regress/t/t_constraint_pure_nonabs_bad.py new file mode 100755 index 000000000..e33e10acf --- /dev/null +++ b/test_regress/t/t_constraint_pure_nonabs_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_constraint_pure_nonabs_bad.v b/test_regress/t/t_constraint_pure_nonabs_bad.v new file mode 100644 index 000000000..0ea5366d2 --- /dev/null +++ b/test_regress/t/t_constraint_pure_nonabs_bad.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, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class NonAsbstract; + pure constraint raintBad; // Bad: Not in abstract class +endclass + +module t; +endmodule diff --git a/test_regress/t/t_constraint_soft_randc_bad.out b/test_regress/t/t_constraint_soft_randc_bad.out new file mode 100644 index 000000000..d87a61b02 --- /dev/null +++ b/test_regress/t/t_constraint_soft_randc_bad.out @@ -0,0 +1,7 @@ +%Error: t/t_constraint_soft_randc_bad.v:10:28: Randc variables not allowed in 'constraint soft' (IEEE 1800-2023 18.5.13.1) + 10 | constraint c_bad { soft rc > 4; } + | ^~ + t/t_constraint_soft_randc_bad.v:10:23: ... Location of restricting expression + 10 | constraint c_bad { soft rc > 4; } + | ^~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_constraint_soft_randc_bad.py b/test_regress/t/t_constraint_soft_randc_bad.py new file mode 100755 index 000000000..30c3d4f77 --- /dev/null +++ b/test_regress/t/t_constraint_soft_randc_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(fails=test.vlt_all, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_constraint_soft_randc_bad.v b/test_regress/t/t_constraint_soft_randc_bad.v new file mode 100644 index 000000000..f10a49f34 --- /dev/null +++ b/test_regress/t/t_constraint_soft_randc_bad.v @@ -0,0 +1,14 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Cls1; + randc int rc; + + constraint c_bad { soft rc > 4; } // Bad, no soft on randc +endclass + +module t (/*AUTOARG*/); +endmodule diff --git a/test_regress/t/t_constraint_state.v b/test_regress/t/t_constraint_state.v index 799dea166..f89f2819a 100644 --- a/test_regress/t/t_constraint_state.v +++ b/test_regress/t/t_constraint_state.v @@ -4,12 +4,50 @@ // any use, without warranty, 2023 by Antmicro Ltd. // SPDX-License-Identifier: CC0-1.0 + +`define check_rand(cl, field, cond) \ +begin \ + longint prev_result; \ + int ok = 0; \ + if (!bit'(cl.randomize())) $stop; \ + prev_result = longint'(field); \ + if (!(cond)) $stop; \ + repeat(9) begin \ + longint result; \ + if (!bit'(cl.randomize())) $stop; \ + result = longint'(field); \ + if (!(cond)) $stop; \ + if (result != prev_result) ok = 1; \ + prev_result = result; \ + end \ + if (ok != 1) $stop; \ +end + +class Foo; + int x; +endclass + +class Bar; + rand int y; +endclass + class Packet; rand int rf; int state; + rand int a; + rand Foo foo; + Bar bar; - constraint c { rf == state; } + constraint c1 { rf == state; } + constraint c2 { a > foo.x; a < bar.y; } + function new(int s, int x, int y); + state = s; + foo = new; + foo.x = x; + bar = new; + bar.y = y; + endfunction endclass module t (/*AUTOARG*/); @@ -19,12 +57,15 @@ module t (/*AUTOARG*/); int v; initial begin - p = new; - p.state = 123; + p = new(123, 10, 20); v = p.randomize(); if (v != 1) $stop; if (p.rf != 123) $stop; + `check_rand(p, p.a, p.a > 10 && p.a < 20) + if (p.foo.x != 10) $stop; + if (p.bar.y != 20) $stop; + p.state = 234; v = p.randomize(); if (v != 1) $stop; diff --git a/test_regress/t/t_constraint_unpacked_array.py b/test_regress/t/t_constraint_unpacked_array.py new file mode 100755 index 000000000..a2b131082 --- /dev/null +++ b/test_regress/t/t_constraint_unpacked_array.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +if not test.have_solver: + test.skip("No constraint solver installed") + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_randomize_array_constraints.v b/test_regress/t/t_constraint_unpacked_array.v similarity index 99% rename from test_regress/t/t_randomize_array_constraints.v rename to test_regress/t/t_constraint_unpacked_array.v index f56cab447..1d7ecfbc6 100755 --- a/test_regress/t/t_randomize_array_constraints.v +++ b/test_regress/t/t_constraint_unpacked_array.v @@ -125,7 +125,7 @@ class con_rand_3d_array_test; endclass -module t_randomize_array_constraints; +module t_constraint_unpacked_array; con_rand_1d_array_test rand_test_1; con_rand_2d_array_test rand_test_2; con_rand_3d_array_test rand_test_3; diff --git a/test_regress/t/t_cover_line.out b/test_regress/t/t_cover_line.out index 4ca952e78..ec76b5936 100644 --- a/test_regress/t/t_cover_line.out +++ b/test_regress/t/t_cover_line.out @@ -14,11 +14,11 @@ reg toggle; %000001 initial toggle=0; --000001 point: comment=block +-000001 point: comment=block hier=top.t integer cyc; %000001 initial cyc=1; --000001 point: comment=block +-000001 point: comment=block hier=top.t wire [7:0] cyc_copy = cyc[7:0]; @@ -52,136 +52,136 @@ par par1 (/*AUTOINST*/); 000010 always @ (posedge clk) begin -+000010 point: comment=block ++000010 point: comment=block hier=top.t ~000010 if (cyc!=0) begin -+000010 point: comment=if --000000 point: comment=else ++000010 point: comment=if hier=top.t +-000000 point: comment=else hier=top.t 000010 cyc <= cyc + 1; -+000010 point: comment=if ++000010 point: comment=if hier=top.t 000010 toggle <= '0; -+000010 point: comment=if ++000010 point: comment=if hier=top.t // Single and multiline if %000009 if (cyc==3) $write(""); --000001 point: comment=if --000009 point: comment=else +-000001 point: comment=if hier=top.t +-000009 point: comment=else hier=top.t %000009 if (cyc==3) --000001 point: comment=if --000009 point: comment=else +-000001 point: comment=if hier=top.t +-000009 point: comment=else hier=top.t %000001 begin --000001 point: comment=if +-000001 point: comment=if hier=top.t %000001 $write(""); --000001 point: comment=if +-000001 point: comment=if hier=top.t end // Single and multiline else %000009 if (cyc==3) ; else $write(""); --000001 point: comment=if --000009 point: comment=else +-000001 point: comment=if hier=top.t +-000009 point: comment=else hier=top.t %000009 if (cyc==3) ; --000001 point: comment=if --000009 point: comment=else +-000001 point: comment=if hier=top.t +-000009 point: comment=else hier=top.t else %000009 begin --000009 point: comment=else +-000009 point: comment=else hier=top.t %000009 $write(""); --000009 point: comment=else +-000009 point: comment=else hier=top.t end // Single and multiline if else %000009 if (cyc==3) $write(""); else $write(""); --000001 point: comment=if --000009 point: comment=else +-000001 point: comment=if hier=top.t +-000009 point: comment=else hier=top.t %000009 if (cyc==3) --000001 point: comment=if --000009 point: comment=else +-000001 point: comment=if hier=top.t +-000009 point: comment=else hier=top.t %000001 begin --000001 point: comment=if +-000001 point: comment=if hier=top.t %000001 $write(""); --000001 point: comment=if +-000001 point: comment=if hier=top.t end else %000009 begin --000009 point: comment=else +-000009 point: comment=else hier=top.t %000009 $write(""); --000009 point: comment=else +-000009 point: comment=else hier=top.t end // multiline elseif %000001 if (cyc==3) --000001 point: comment=elsif +-000001 point: comment=elsif hier=top.t %000001 begin --000001 point: comment=elsif +-000001 point: comment=elsif hier=top.t %000001 $write(""); --000001 point: comment=elsif +-000001 point: comment=elsif hier=top.t end %000001 else if (cyc==4) --000001 point: comment=elsif +-000001 point: comment=elsif hier=top.t %000001 begin --000001 point: comment=elsif +-000001 point: comment=elsif hier=top.t %000001 $write(""); --000001 point: comment=elsif +-000001 point: comment=elsif hier=top.t end %000007 else if (cyc==5) --000001 point: comment=if --000007 point: comment=else +-000001 point: comment=if hier=top.t +-000007 point: comment=else hier=top.t %000001 begin --000001 point: comment=if +-000001 point: comment=if hier=top.t %000001 $write(""); --000001 point: comment=if +-000001 point: comment=if hier=top.t end else %000007 begin --000007 point: comment=else +-000007 point: comment=else hier=top.t %000007 $write(""); --000007 point: comment=else +-000007 point: comment=else hier=top.t end // Single and multiline while %000000 while (0); --000000 point: comment=block +-000000 point: comment=block hier=top.t %000000 while (0) begin --000000 point: comment=block +-000000 point: comment=block hier=top.t %000000 $write(""); --000000 point: comment=block +-000000 point: comment=block hier=top.t end %000000 do ; while (0); --000000 point: comment=block +-000000 point: comment=block hier=top.t ~000010 do begin --000000 point: comment=block -+000010 point: comment=if +-000000 point: comment=block hier=top.t ++000010 point: comment=if hier=top.t ~000010 $write(""); --000000 point: comment=block -+000010 point: comment=if +-000000 point: comment=block hier=top.t ++000010 point: comment=if hier=top.t %000000 end while (0); --000000 point: comment=block +-000000 point: comment=block hier=top.t //=== // Task and complicated %000001 if (cyc==3) begin --000001 point: comment=elsif +-000001 point: comment=elsif hier=top.t %000001 toggle <= '1; --000001 point: comment=elsif +-000001 point: comment=elsif hier=top.t end %000001 else if (cyc==5) begin --000001 point: comment=elsif +-000001 point: comment=elsif hier=top.t `ifdef VERILATOR %000001 $c("this->call_task();"); --000001 point: comment=elsif +-000001 point: comment=elsif hier=top.t `else call_task(); `endif end %000007 else if (cyc==10) begin --000001 point: comment=if --000007 point: comment=else +-000001 point: comment=if hier=top.t +-000007 point: comment=else hier=top.t %000001 $write("*-* All Finished *-*\n"); --000001 point: comment=if +-000001 point: comment=if hier=top.t %000001 $finish; --000001 point: comment=if +-000001 point: comment=if hier=top.t end end end %000001 task call_task; --000001 point: comment=block +-000001 point: comment=block hier=top.t /* verilator public */ %000001 t1.center_task(1'b1); --000001 point: comment=block +-000001 point: comment=block hier=top.t endtask endmodule @@ -193,16 +193,16 @@ input clk; input toggle; 000020 always @ (posedge clk) begin -+000020 point: comment=block ++000020 point: comment=block hier=top.t.a* ~000018 if (toggle) begin // CHECK_COVER(0,"top.t.a*",18) --000002 point: comment=if -+000018 point: comment=else +-000002 point: comment=if hier=top.t.a* ++000018 point: comment=else hier=top.t.a* %000002 $write(""); --000002 point: comment=if +-000002 point: comment=if hier=top.t.a* // t.a1 and t.a2 collapse to a count of 2 end 000018 if (toggle) begin // *** t_cover_line.vlt turns this off -+000018 point: comment=else ++000018 point: comment=else hier=top.t.a* $write(""); // CHECK_COVER_MISSING(0) // This doesn't even get added `ifdef ATTRIBUTE @@ -222,25 +222,25 @@ /* verilator public_module */ 000020 always @ (posedge clk) begin -+000020 point: comment=block ++000020 point: comment=block hier=top.t.b* 000020 $write(""); // Always covered -+000020 point: comment=block ++000020 point: comment=block hier=top.t.b* ~000020 if (0) begin // CHECK_COVER(0,"top.t.b*",0) --000000 point: comment=if -+000020 point: comment=else +-000000 point: comment=if hier=top.t.b* ++000020 point: comment=else hier=top.t.b* // Make sure that we don't optimize away zero buckets %000000 $write(""); --000000 point: comment=if +-000000 point: comment=if hier=top.t.b* end ~000018 if (toggle) begin // CHECK_COVER(0,"top.t.b*",2) --000002 point: comment=if -+000018 point: comment=else +-000002 point: comment=if hier=top.t.b* ++000018 point: comment=else hier=top.t.b* // t.b1 and t.b2 collapse to a count of 2 %000002 $write(""); --000002 point: comment=if +-000002 point: comment=if hier=top.t.b* end 000018 if (toggle) begin : block -+000018 point: comment=else ++000018 point: comment=else hier=top.t.b* // This doesn't `ifdef ATTRIBUTE // verilator coverage_block_off @@ -255,32 +255,32 @@ class Cls; bit m_toggle; %000001 function new(bit toggle); --000001 point: comment=block +-000001 point: comment=block hier=top.$unit::Cls__Vclpkg %000001 m_toggle = toggle; --000001 point: comment=block +-000001 point: comment=block hier=top.$unit::Cls__Vclpkg %000001 if (m_toggle) begin // CHECK_COVER(0,"top.$unit::Cls",1) --000001 point: comment=if --000000 point: comment=else +-000001 point: comment=if hier=top.$unit::Cls__Vclpkg +-000000 point: comment=else hier=top.$unit::Cls__Vclpkg %000001 $write(""); --000001 point: comment=if +-000001 point: comment=if hier=top.$unit::Cls__Vclpkg end endfunction 000011 static function void fstatic(bit toggle); -+000011 point: comment=block ++000011 point: comment=block hier=top.$unit::Cls__Vclpkg ~000011 if (1) begin // CHECK_COVER(0,"top.$unit::Cls",1) -+000011 point: comment=if --000000 point: comment=else ++000011 point: comment=if hier=top.$unit::Cls__Vclpkg +-000000 point: comment=else hier=top.$unit::Cls__Vclpkg 000011 $write(""); -+000011 point: comment=if ++000011 point: comment=if hier=top.$unit::Cls__Vclpkg end endfunction 000011 function void fauto(); -+000011 point: comment=block ++000011 point: comment=block hier=top.$unit::Cls__Vclpkg ~000011 if (m_toggle) begin // CHECK_COVER(0,"top.$unit::Cls",11) -+000011 point: comment=if --000000 point: comment=else ++000011 point: comment=if hier=top.$unit::Cls__Vclpkg +-000000 point: comment=else hier=top.$unit::Cls__Vclpkg 000011 $write(""); -+000011 point: comment=if ++000011 point: comment=if hier=top.$unit::Cls__Vclpkg end endfunction endclass @@ -295,37 +295,37 @@ /* verilator public_module */ 000010 always @ (posedge clk) begin -+000010 point: comment=block ++000010 point: comment=block hier=top.t.t1 000010 center_task(1'b0); -+000010 point: comment=block ++000010 point: comment=block hier=top.t.t1 end 000011 task center_task; -+000011 point: comment=block ++000011 point: comment=block hier=top.t.t1 input external; 000011 begin -+000011 point: comment=block ++000011 point: comment=block hier=top.t.t1 ~000010 if (toggle) begin // CHECK_COVER(0,"top.t.t1",1) --000001 point: comment=if -+000010 point: comment=else +-000001 point: comment=if hier=top.t.t1 ++000010 point: comment=else hier=top.t.t1 %000001 $write(""); --000001 point: comment=if +-000001 point: comment=if hier=top.t.t1 end ~000010 if (external) begin // CHECK_COVER(0,"top.t.t1",1) --000001 point: comment=if -+000010 point: comment=else +-000001 point: comment=if hier=top.t.t1 ++000010 point: comment=else hier=top.t.t1 %000001 $write("[%0t] Got external pulse\n", $time); --000001 point: comment=if +-000001 point: comment=if hier=top.t.t1 end end 000011 begin -+000011 point: comment=block ++000011 point: comment=block hier=top.t.t1 %000001 Cls c = new(1'b1); --000001 point: comment=block +-000001 point: comment=block hier=top.t.t1 000011 c.fauto(); -+000011 point: comment=block ++000011 point: comment=block hier=top.t.t1 000011 Cls::fstatic(1'b1); -+000011 point: comment=block ++000011 point: comment=block hier=top.t.t1 end endtask endmodule @@ -346,16 +346,16 @@ end // verilator coverage_on 000010 always @ (posedge clk) begin -+000010 point: comment=block ++000010 point: comment=block hier=top.t.o1 %000009 if (toggle) begin --000001 point: comment=if --000009 point: comment=else +-000001 point: comment=if hier=top.t.o1 +-000009 point: comment=else hier=top.t.o1 // because under coverage_module_off %000001 $write(""); --000001 point: comment=if +-000001 point: comment=if hier=top.t.o1 %000001 if (0) ; // CHECK_COVER(0,"top.t.o1",1) --000000 point: comment=if --000001 point: comment=else +-000000 point: comment=if hier=top.t.o1 +-000001 point: comment=else hier=top.t.o1 end end endmodule @@ -365,28 +365,28 @@ int decoded; 000010 always @ (posedge clk) begin -+000010 point: comment=block ++000010 point: comment=block hier=top.t.tab1 000010 case (cyc4) -+000010 point: comment=block ++000010 point: comment=block hier=top.t.tab1 %000001 1: decoded = 10; --000001 point: comment=case +-000001 point: comment=case hier=top.t.tab1 %000001 2: decoded = 20; --000001 point: comment=case +-000001 point: comment=case hier=top.t.tab1 %000001 3: decoded = 30; --000001 point: comment=case +-000001 point: comment=case hier=top.t.tab1 %000001 4: decoded = 40; --000001 point: comment=case +-000001 point: comment=case hier=top.t.tab1 %000001 5: decoded = 50; --000001 point: comment=case +-000001 point: comment=case hier=top.t.tab1 %000005 default: decoded = 0; --000005 point: comment=case +-000005 point: comment=case hier=top.t.tab1 endcase end 000010 always @ (posedge clk) begin -+000010 point: comment=block ++000010 point: comment=block hier=top.t.tab1 000010 cyc4 <= cyc4 + 1; -+000010 point: comment=block ++000010 point: comment=block hier=top.t.tab1 end endmodule @@ -397,20 +397,20 @@ // seems safer for functions used both at elaboration time and not - but may // revisit this. %000000 function automatic int param_func(int i); --000000 point: comment=block +-000000 point: comment=block hier=top.t.par1 %000000 if (i == 0) begin --000000 point: comment=if --000000 point: comment=else +-000000 point: comment=if hier=top.t.par1 +-000000 point: comment=else hier=top.t.par1 %000000 i = 99; // Uncovered --000000 point: comment=if +-000000 point: comment=if hier=top.t.par1 end %000000 else begin --000000 point: comment=else +-000000 point: comment=else hier=top.t.par1 %000000 i = i + 1; --000000 point: comment=else +-000000 point: comment=else hier=top.t.par1 end %000000 return i; --000000 point: comment=block +-000000 point: comment=block hier=top.t.par1 endfunction endmodule diff --git a/test_regress/t/t_cover_toggle_points.out b/test_regress/t/t_cover_toggle_points.out index 2154b19f1..17279cd14 100644 --- a/test_regress/t/t_cover_toggle_points.out +++ b/test_regress/t/t_cover_toggle_points.out @@ -11,11 +11,11 @@ ); 000019 input clk; -+000019 point: comment=clk ++000019 point: comment=clk hier=top.t input real check_real; // Check issue #2741 000021 input real check_array_real [1:0]; -+000021 point: comment=check_array_real[0] -+000021 point: comment=check_array_real[1] ++000021 point: comment=check_array_real[0] hier=top.t ++000021 point: comment=check_array_real[1] hier=top.t input string check_string; // Check issue #2766 typedef struct packed { @@ -27,11 +27,11 @@ } str_t; %000002 reg toggle; initial toggle='0; --000002 point: comment=toggle +-000002 point: comment=toggle hier=top.t %000002 str_t stoggle; initial stoggle='0; --000002 point: comment=stoggle.b --000002 point: comment=stoggle.u.ua +-000002 point: comment=stoggle.b hier=top.t +-000002 point: comment=stoggle.u.ua hier=top.t union { real val1; // TODO use bit [7:0] here @@ -41,23 +41,23 @@ const reg aconst = '0; %000002 reg [1:0][1:0] ptoggle; initial ptoggle=0; --000002 point: comment=ptoggle[0][0] --000000 point: comment=ptoggle[0][1] --000000 point: comment=ptoggle[1][0] --000000 point: comment=ptoggle[1][1] +-000002 point: comment=ptoggle[0][0] hier=top.t +-000000 point: comment=ptoggle[0][1] hier=top.t +-000000 point: comment=ptoggle[1][0] hier=top.t +-000000 point: comment=ptoggle[1][1] hier=top.t integer cyc; initial cyc=1; ~000011 wire [7:0] cyc_copy = cyc[7:0]; -+000011 point: comment=cyc_copy[0] --000005 point: comment=cyc_copy[1] --000002 point: comment=cyc_copy[2] --000001 point: comment=cyc_copy[3] --000000 point: comment=cyc_copy[4] --000000 point: comment=cyc_copy[5] --000000 point: comment=cyc_copy[6] --000000 point: comment=cyc_copy[7] ++000011 point: comment=cyc_copy[0] hier=top.t +-000005 point: comment=cyc_copy[1] hier=top.t +-000002 point: comment=cyc_copy[2] hier=top.t +-000001 point: comment=cyc_copy[3] hier=top.t +-000000 point: comment=cyc_copy[4] hier=top.t +-000000 point: comment=cyc_copy[5] hier=top.t +-000000 point: comment=cyc_copy[6] hier=top.t +-000000 point: comment=cyc_copy[7] hier=top.t %000002 wire toggle_up; --000002 point: comment=toggle_up +-000002 point: comment=toggle_up hier=top.t typedef struct { int q[$]; @@ -90,30 +90,30 @@ .toggle (toggle)); %000001 reg [1:0] memory[121:110]; --000001 point: comment=memory[110][0] --000000 point: comment=memory[110][1] --000000 point: comment=memory[111][0] --000000 point: comment=memory[111][1] --000000 point: comment=memory[112][0] --000000 point: comment=memory[112][1] --000000 point: comment=memory[113][0] --000000 point: comment=memory[113][1] --000000 point: comment=memory[114][0] --000000 point: comment=memory[114][1] --000000 point: comment=memory[115][0] --000000 point: comment=memory[115][1] --000000 point: comment=memory[116][0] --000000 point: comment=memory[116][1] --000000 point: comment=memory[117][0] --000000 point: comment=memory[117][1] --000000 point: comment=memory[118][0] --000000 point: comment=memory[118][1] --000000 point: comment=memory[119][0] --000000 point: comment=memory[119][1] --000000 point: comment=memory[120][0] --000000 point: comment=memory[120][1] --000000 point: comment=memory[121][0] --000000 point: comment=memory[121][1] +-000001 point: comment=memory[110][0] hier=top.t +-000000 point: comment=memory[110][1] hier=top.t +-000000 point: comment=memory[111][0] hier=top.t +-000000 point: comment=memory[111][1] hier=top.t +-000000 point: comment=memory[112][0] hier=top.t +-000000 point: comment=memory[112][1] hier=top.t +-000000 point: comment=memory[113][0] hier=top.t +-000000 point: comment=memory[113][1] hier=top.t +-000000 point: comment=memory[114][0] hier=top.t +-000000 point: comment=memory[114][1] hier=top.t +-000000 point: comment=memory[115][0] hier=top.t +-000000 point: comment=memory[115][1] hier=top.t +-000000 point: comment=memory[116][0] hier=top.t +-000000 point: comment=memory[116][1] hier=top.t +-000000 point: comment=memory[117][0] hier=top.t +-000000 point: comment=memory[117][1] hier=top.t +-000000 point: comment=memory[118][0] hier=top.t +-000000 point: comment=memory[118][1] hier=top.t +-000000 point: comment=memory[119][0] hier=top.t +-000000 point: comment=memory[119][1] hier=top.t +-000000 point: comment=memory[120][0] hier=top.t +-000000 point: comment=memory[120][1] hier=top.t +-000000 point: comment=memory[121][0] hier=top.t +-000000 point: comment=memory[121][1] hier=top.t wire [1023:0] largeish = {992'h0, cyc}; // CHECK_COVER_MISSING(-1) @@ -154,22 +154,22 @@ // t.a1 and t.a2 collapse to a count of 2 000038 input clk; -+000038 point: comment=clk ++000038 point: comment=clk hier=top.t.a* %000004 input toggle; --000004 point: comment=toggle +-000004 point: comment=toggle hier=top.t.a* // CHECK_COVER(-1,"top.t.a*",4) // 2 edges * (t.a1 and t.a2) ~000022 input [7:0] cyc_copy; -+000022 point: comment=cyc_copy[0] -+000010 point: comment=cyc_copy[1] --000004 point: comment=cyc_copy[2] --000002 point: comment=cyc_copy[3] --000000 point: comment=cyc_copy[4] --000000 point: comment=cyc_copy[5] --000000 point: comment=cyc_copy[6] --000000 point: comment=cyc_copy[7] ++000022 point: comment=cyc_copy[0] hier=top.t.a* ++000010 point: comment=cyc_copy[1] hier=top.t.a* +-000004 point: comment=cyc_copy[2] hier=top.t.a* +-000002 point: comment=cyc_copy[3] hier=top.t.a* +-000000 point: comment=cyc_copy[4] hier=top.t.a* +-000000 point: comment=cyc_copy[5] hier=top.t.a* +-000000 point: comment=cyc_copy[6] hier=top.t.a* +-000000 point: comment=cyc_copy[7] hier=top.t.a* // 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) @@ -180,12 +180,12 @@ // CHECK_COVER(-8,"top.t.a*","cyc_copy[7]",0) %000004 reg toggle_internal; --000004 point: comment=toggle_internal +-000004 point: comment=toggle_internal hier=top.t.a* // CHECK_COVER(-1,"top.t.a*",4) // 2 edges * (t.a1 and t.a2) %000004 output reg toggle_up; --000004 point: comment=toggle_up +-000004 point: comment=toggle_up hier=top.t.a* // CHECK_COVER(-1,"top.t.a*",4) // 2 edges * (t.a1 and t.a2) @@ -201,10 +201,10 @@ ); 000019 input clk; -+000019 point: comment=clk ++000019 point: comment=clk hier=top.t.b1 %000002 input toggle_up; --000002 point: comment=toggle_up +-000002 point: comment=toggle_up hier=top.t.b1 // CHECK_COVER(-1,"top.t.b1","toggle_up",2) /* verilator public_module */ @@ -225,7 +225,7 @@ // verilator coverage_on %000002 input toggle; --000002 point: comment=toggle +-000002 point: comment=toggle hier=top.t.o1 // CHECK_COVER(-1,"top.t.o1","toggle",2) endmodule diff --git a/test_regress/t/t_delay.v b/test_regress/t/t_delay.v index 4b01e9eb8..e541a10d0 100644 --- a/test_regress/t/t_delay.v +++ b/test_regress/t/t_delay.v @@ -18,12 +18,14 @@ module t (/*AUTOARG*/ wire [31:0] dly1; wire [31:0] dly2 = dly1 + 32'h1; wire [31:0] dly3; + wire [31:0] dly4; typedef struct packed { int dly; } dly_s_t; dly_s_t dly_s; assign #(1.2000000000000000) dly1 = dly0 + 32'h1; assign #(sub.delay) dly3 = dly1 + 1; + assign #sub.delay dly4 = dly1 + 1; sub sub(); diff --git a/test_regress/t/t_delay_stmtdly_bad.out b/test_regress/t/t_delay_stmtdly_bad.out index 40b0b31a3..441588a9c 100644 --- a/test_regress/t/t_delay_stmtdly_bad.out +++ b/test_regress/t/t_delay_stmtdly_bad.out @@ -1,39 +1,47 @@ -%Warning-ASSIGNDLY: t/t_delay.v:25:11: Ignoring timing control on this assignment/primitive due to --no-timing +%Warning-ASSIGNDLY: t/t_delay.v:26:11: Ignoring timing control on this assignment/primitive due to --no-timing : ... note: In instance 't' - 25 | assign #(1.2000000000000000) dly1 = dly0 + 32'h1; + 26 | assign #(1.2000000000000000) dly1 = dly0 + 32'h1; | ^ ... For warning description see https://verilator.org/warn/ASSIGNDLY?v=latest ... Use "/* verilator lint_off ASSIGNDLY */" and lint_on around source to disable this message. -%Warning-ASSIGNDLY: t/t_delay.v:26:11: Ignoring timing control on this assignment/primitive due to --no-timing +%Warning-ASSIGNDLY: t/t_delay.v:27:11: Ignoring timing control on this assignment/primitive due to --no-timing : ... note: In instance 't' - 26 | assign #(sub.delay) dly3 = dly1 + 1; + 27 | assign #(sub.delay) dly3 = dly1 + 1; | ^ -%Warning-ASSIGNDLY: t/t_delay.v:33:18: Ignoring timing control on this assignment/primitive due to --no-timing +%Warning-ASSIGNDLY: t/t_delay.v:28:11: Ignoring timing control on this assignment/primitive due to --no-timing : ... note: In instance 't' - 33 | dly0 <= #0 32'h11; - | ^ -%Warning-ASSIGNDLY: t/t_delay.v:36:18: Ignoring timing control on this assignment/primitive due to --no-timing + 28 | assign #sub.delay dly4 = dly1 + 1; + | ^ +%Warning-ASSIGNDLY: t/t_delay.v:35:18: Ignoring timing control on this assignment/primitive due to --no-timing : ... note: In instance 't' - 36 | dly0 <= #0.12 dly0 + 32'h12; + 35 | dly0 <= #0 32'h11; | ^ -%Warning-ASSIGNDLY: t/t_delay.v:44:18: Ignoring timing control on this assignment/primitive due to --no-timing +%Warning-ASSIGNDLY: t/t_delay.v:38:18: Ignoring timing control on this assignment/primitive due to --no-timing : ... note: In instance 't' - 44 | dly0 <= #(dly_s.dly) 32'h55; + 38 | dly0 <= #0.12 dly0 + 32'h12; | ^ -%Warning-STMTDLY: t/t_delay.v:50:10: Ignoring delay on this statement due to --no-timing +%Warning-ASSIGNDLY: t/t_delay.v:46:18: Ignoring timing control on this assignment/primitive due to --no-timing + : ... note: In instance 't' + 46 | dly0 <= #(dly_s.dly) 32'h55; + | ^ +%Warning-STMTDLY: t/t_delay.v:52:10: Ignoring delay on this statement due to --no-timing : ... note: In instance 't' - 50 | #100 $finish; + 52 | #100 $finish; | ^ -%Warning-UNUSEDSIGNAL: t/t_delay.v:23:12: Signal is not used: 'dly_s' +%Warning-UNUSEDSIGNAL: t/t_delay.v:21:16: Signal is not used: 'dly4' : ... note: In instance 't' - 23 | dly_s_t dly_s; + 21 | wire [31:0] dly4; + | ^~~~ +%Warning-UNUSEDSIGNAL: t/t_delay.v:24:12: Signal is not used: 'dly_s' + : ... note: In instance 't' + 24 | dly_s_t dly_s; | ^~~~~ -%Warning-UNUSEDSIGNAL: t/t_delay.v:57:13: Signal is not used: 'delay' +%Warning-UNUSEDSIGNAL: t/t_delay.v:59:13: Signal is not used: 'delay' : ... note: In instance 't.sub' - 57 | realtime delay = 2.3; + 59 | realtime delay = 2.3; | ^~~~~ -%Warning-BLKSEQ: t/t_delay.v:43:20: Blocking assignment '=' in sequential logic process +%Warning-BLKSEQ: t/t_delay.v:45:20: Blocking assignment '=' in sequential logic process : ... Suggest using delayed assignment '<=' - 43 | dly_s.dly = 55; + 45 | dly_s.dly = 55; | ^ %Error: Exiting due to diff --git a/test_regress/t/t_disable_fork2.v b/test_regress/t/t_disable_fork2.v index 118e3e7f5..6e52acac8 100644 --- a/test_regress/t/t_disable_fork2.v +++ b/test_regress/t/t_disable_fork2.v @@ -15,7 +15,8 @@ // - a function taking VlProcess argument shared between a process that // allocates VlProcess, and one that doesnt, // - a function that has a delay and obtains VlProcess argument, -// - a function that has a delay and doesn't obtain it. +// - a function that has a delay and doesn't obtain it, +// - an empty fork with disable fork. // // Blocks below contain info on whether they should (YES) or shouldn't (NO) // be emitted as functions with a VlProcess argument. @@ -38,6 +39,13 @@ class Cls; task delay_func; /*NO*/ fork /*NO*/ #1 $write("Finished *-*\n"); join_none endtask + task empty_fork; + fork + begin + end + join_none + disable fork; + endtask endclass module t; @@ -47,6 +55,7 @@ module t; fork /*YES*/ cls.common_func(); join_none cls.fork_func(); cls.disable_fork_func(); + cls.empty_fork(); cls.print(); end diff --git a/test_regress/t/t_disable_fork2_split.py b/test_regress/t/t_disable_fork2_split.py new file mode 100755 index 000000000..3e66b3894 --- /dev/null +++ b/test_regress/t/t_disable_fork2_split.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') +test.top_filename = "t_disable_fork2.v" + +# Validate if splitted functions get vlProcess handle +test.compile(verilator_flags2=["--timing --output-split-cfuncs 1"]) + +test.passes() diff --git a/test_regress/t/t_disable_iff_multi_bad.out b/test_regress/t/t_disable_iff_multi_bad.out index 24b6b78a6..cf6dedeb4 100644 --- a/test_regress/t/t_disable_iff_multi_bad.out +++ b/test_regress/t/t_disable_iff_multi_bad.out @@ -1,8 +1,5 @@ -%Error-UNSUPPORTED: t/t_disable_iff_multi_bad.v:13:4: Unsupported: default disable iff - 13 | default disable iff (!rstn); - | ^~~~~~~ - ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest -%Error-UNSUPPORTED: t/t_disable_iff_multi_bad.v:14:4: Unsupported: default disable iff +%Error: t/t_disable_iff_multi_bad.v:14:4: Only one 'default disable iff' allowed per module (IEEE 1800-2023 16.15) + : ... note: In instance 't' 14 | default disable iff (!rstn); | ^~~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_dist_copyright.py b/test_regress/t/t_dist_copyright.py index 33f1ea63f..76ef97b24 100755 --- a/test_regress/t/t_dist_copyright.py +++ b/test_regress/t/t_dist_copyright.py @@ -42,10 +42,10 @@ EXEMPT_FILES_LIST = """ 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_uvm_pkg_all.vh - test_regress/t/t_uvm_pkg_todo.vh test_regress/t/tsub/t_flag_f_tsub.v test_regress/t/tsub/t_flag_f_tsub_inc.v + test_regress/t/uvm/uvm_pkg_all.svh + test_regress/t/uvm/uvm_pkg_todo.svh verilator.pc.in """ diff --git a/test_regress/t/t_dist_warn_coverage.py b/test_regress/t/t_dist_warn_coverage.py index 3ad81cedc..cf8133fb1 100755 --- a/test_regress/t/t_dist_warn_coverage.py +++ b/test_regress/t/t_dist_warn_coverage.py @@ -20,7 +20,6 @@ Suppressed = {} for s in [ ' exited with ', # Is hit; driver.py 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 'Import package not found: ', # Errors earlier, until future parser released 'Return with return value isn\'t underneath a function', # Hard to hit, get other bad return messages @@ -48,14 +47,12 @@ for s in [ 'Illegal +: or -: select; type already selected, or bad dimension: ', 'Illegal bit or array select; type already selected, or bad dimension: ', 'Illegal range select; type already selected, or bad dimension: ', - 'Interface port ', 'Member selection of non-struct/union object \'', 'Modport item is not a function/task: ', 'Modport item is not a variable: ', 'Modport item not found: ', 'Modport not referenced as .', 'Modport not referenced from underneath an interface: ', - 'Non-interface used as an interface: ', 'Parameter type pin value isn\'t a type: Param ', 'Parameter type variable isn\'t a type: Param ', 'Pattern replication value of 0 is not legal.', @@ -87,12 +84,9 @@ for s in [ 'Unsupported: Modport dotted port name', 'Unsupported: Modport export with prototype', 'Unsupported: Modport import with prototype', - 'Unsupported: Non-variable on LHS of built-in method \'', 'Unsupported: Only one PSL clock allowed per assertion', 'Unsupported: Per-bit array instantiations ', 'Unsupported: Public functions with >64 bit outputs; ', - 'Unsupported: RHS of ==? or !=? must be ', - 'Unsupported: Randomize \'local::\'', 'Unsupported: Replication to form ', 'Unsupported: Shifting of by over 32-bit number isn\'t supported.', 'Unsupported: Signal strengths are unsupported ', @@ -112,11 +106,6 @@ for s in [ 'Unsupported: extern interface', 'Unsupported: extern module', 'Unsupported: extern task', - 'Unsupported: interface decls within interface decls', - 'Unsupported: interface decls within module decls', - 'Unsupported: module decls within module decls', - 'Unsupported: program decls within interface decls', - 'Unsupported: program decls within module decls', 'Unsupported: property port \'local\'', 'Unsupported: randsequence production list', 'Unsupported: randsequence repeat', @@ -124,10 +113,7 @@ for s in [ 'Unsupported: s_always (in property expression)', 'Unsupported: this.super', 'Unsupported: trireg', - 'Unsupported: wand', 'Unsupported: with[] stream expression', - 'Unsupported: wor', - 'Unsupported: event arrays', 'Unsupported: modport export', 'Unsupported: no_inline for tasks', 'Unsupported: static cast to ', diff --git a/test_regress/t/t_dist_whitespace.py b/test_regress/t/t_dist_whitespace.py index 1c9da5b27..3a6ae33be 100755 --- a/test_regress/t/t_dist_whitespace.py +++ b/test_regress/t/t_dist_whitespace.py @@ -103,13 +103,14 @@ if fcount < 50: if len(warns): # First warning lists everything as that's shown in the driver summary + msg = "" if 'HARNESS_UPDATE_GOLDEN' in os.environ: - test.error("Updated files with whitespace errors: " + ' '.join(sorted(warns.keys()))) - test.error("To auto-fix: HARNESS_UPDATE_GOLDEN=1 {command} or --golden") + msg += "Updated files with whitespace errors: " + ' '.join(sorted(warns.keys())) + "\n" else: - test.error("Files have whitespace errors: " + ' '.join(sorted(warns.keys()))) - test.error("To auto-fix: HARNESS_UPDATE_GOLDEN=1 {command} or --golden") + msg += "Files have whitespace errors: " + ' '.join(sorted(warns.keys())) + "\n" + msg += "To auto-fix: HARNESS_UPDATE_GOLDEN=1 {command} or --golden\n" for filename in sorted(warns.keys()): - test.error(warns[filename]) + msg += warns[filename] + "\n" + test.error(msg) test.passes() diff --git a/test_regress/t/t_dpi_var.py b/test_regress/t/t_dpi_var.py index 87e0c90a1..0cf3bcd6e 100755 --- a/test_regress/t/t_dpi_var.py +++ b/test_regress/t/t_dpi_var.py @@ -21,19 +21,19 @@ test.compile( if test.vlt_all: test.file_grep( out_filename, - r'{"type":"VAR","name":"formatted",.*"loc":"e,56:[^"]*",.*"origName":"formatted",.*"direction":"INPUT",.*"dtypeName":"string",.*"attrSFormat":true' + r'{"type":"VAR","name":"formatted",.*"loc":"\w,56:[^"]*",.*"origName":"formatted",.*"direction":"INPUT",.*"dtypeName":"string",.*"attrSFormat":true' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"t.sub.in",.*"loc":"e,77:[^"]*",.*"origName":"in",.*"dtypeName":"int",.*"isSigUserRdPublic":true' + r'{"type":"VAR","name":"t.sub.in",.*"loc":"\w,77:[^"]*",.*"origName":"in",.*"dtypeName":"int",.*"isSigUserRdPublic":true' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"t.sub.fr_a",.*"loc":"e,78:[^"]*",.*"origName":"fr_a",.*"dtypeName":"int",.*"isSigUserRdPublic":true,.*"isSigUserRWPublic":true' + r'{"type":"VAR","name":"t.sub.fr_a",.*"loc":"\w,78:[^"]*",.*"origName":"fr_a",.*"dtypeName":"int",.*"isSigUserRdPublic":true,.*"isSigUserRWPublic":true' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"t.sub.fr_b",.*"loc":"e,79:[^"]*",.*"origName":"fr_b",.*"dtypeName":"int",.*"isSigUserRdPublic":true,.*"isSigUserRWPublic":true' + r'{"type":"VAR","name":"t.sub.fr_b",.*"loc":"\w,79:[^"]*",.*"origName":"fr_b",.*"dtypeName":"int",.*"isSigUserRdPublic":true,.*"isSigUserRWPublic":true' ) test.execute() diff --git a/test_regress/t/t_dpi_var_vlt.py b/test_regress/t/t_dpi_var_vlt.py index b625c8c09..152593adc 100755 --- a/test_regress/t/t_dpi_var_vlt.py +++ b/test_regress/t/t_dpi_var_vlt.py @@ -24,19 +24,19 @@ test.compile(make_top_shell=False, if test.vlt_all: test.file_grep( out_filename, - r'{"type":"VAR","name":"formatted","addr":"[^"]*","loc":"f,58:[^"]*",.*"origName":"formatted",.*"direction":"INPUT",.*"dtypeName":"string",.*"attrSFormat":true' + r'{"type":"VAR","name":"formatted","addr":"[^"]*","loc":"\w,58:[^"]*",.*"origName":"formatted",.*"direction":"INPUT",.*"dtypeName":"string",.*"attrSFormat":true' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"t.sub.in","addr":"[^"]*","loc":"f,81:[^"]*",.*"origName":"in",.*"dtypeName":"int",.*"isSigUserRdPublic":true' + r'{"type":"VAR","name":"t.sub.in","addr":"[^"]*","loc":"\w,81:[^"]*",.*"origName":"in",.*"dtypeName":"int",.*"isSigUserRdPublic":true' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"t.sub.fr_a","addr":"[^"]*","loc":"f,82:[^"]*",.*"origName":"fr_a",.*"dtypeName":"int",.*"isSigUserRdPublic":true,.*"isSigUserRWPublic":true' + r'{"type":"VAR","name":"t.sub.fr_a","addr":"[^"]*","loc":"\w,82:[^"]*",.*"origName":"fr_a",.*"dtypeName":"int",.*"isSigUserRdPublic":true,.*"isSigUserRWPublic":true' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"t.sub.fr_b","addr":"[^"]*","loc":"f,83:[^"]*",.*"origName":"fr_b",.*"dtypeName":"int",.*"isSigUserRdPublic":true,.*"isSigUserRWPublic":true' + r'{"type":"VAR","name":"t.sub.fr_b","addr":"[^"]*","loc":"\w,83:[^"]*",.*"origName":"fr_b",.*"dtypeName":"int",.*"isSigUserRdPublic":true,.*"isSigUserRWPublic":true' ) test.execute() diff --git a/test_regress/t/t_dump_json.out b/test_regress/t/t_dump_json.out index 4a302d04d..602123ff9 100644 --- a/test_regress/t/t_dump_json.out +++ b/test_regress/t/t_dump_json.out @@ -1,427 +1,427 @@ {"type":"NETLIST","name":"$root","addr":"(B)","loc":"a,0:0,0:0","timeunit":"1ps","timeprecision":"1ps","typeTablep":"(C)","constPoolp":"(D)","dollarUnitPkgp":"UNLINKED","stdPackagep":"UNLINKED","evalp":"UNLINKED","evalNbap":"UNLINKED","dpiExportTriggerp":"UNLINKED","delaySchedulerp":"UNLINKED","nbaEventp":"UNLINKED","nbaEventTriggerp":"UNLINKED","topScopep":"UNLINKED", "modulesp": [ - {"type":"MODULE","name":"t","addr":"(E)","loc":"d,7:8,7:9","origName":"t","level":2,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], + {"type":"MODULE","name":"t","addr":"(E)","loc":"e,7:8,7:9","origName":"t","level":2,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"PORT","name":"clk","addr":"(F)","loc":"d,9:4,9:7","exprp": []}, - {"type":"VAR","name":"clk","addr":"(G)","loc":"d,11:10,11:13","dtypep":"UNLINKED","origName":"clk","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", + {"type":"PORT","name":"clk","addr":"(F)","loc":"e,9:4,9:7","exprp": []}, + {"type":"VAR","name":"clk","addr":"(G)","loc":"e,11:10,11:13","dtypep":"UNLINKED","origName":"clk","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", "childDTypep": [ - {"type":"BASICDTYPE","name":"LOGIC_IMPLICIT","addr":"(H)","loc":"d,11:10,11:13","dtypep":"(H)","keyword":"LOGIC_IMPLICIT","generic":false,"rangep": []} + {"type":"BASICDTYPE","name":"LOGIC_IMPLICIT","addr":"(H)","loc":"e,11:10,11:13","dtypep":"(H)","keyword":"LOGIC_IMPLICIT","generic":false,"rangep": []} ],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"cyc","addr":"(I)","loc":"d,13:12,13:15","dtypep":"UNLINKED","origName":"cyc","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"VAR","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", + {"type":"VAR","name":"cyc","addr":"(I)","loc":"e,13:12,13:15","dtypep":"UNLINKED","origName":"cyc","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"VAR","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", "childDTypep": [ - {"type":"BASICDTYPE","name":"integer","addr":"(J)","loc":"d,13:4,13:11","dtypep":"(J)","keyword":"integer","range":"31:0","generic":false,"rangep": []} + {"type":"BASICDTYPE","name":"integer","addr":"(J)","loc":"e,13:4,13:11","dtypep":"(J)","keyword":"integer","range":"31:0","generic":false,"rangep": []} ],"delayp": [], "valuep": [ - {"type":"CONST","name":"?32?sh0","addr":"(K)","loc":"d,13:18,13:19","dtypep":"(L)"} + {"type":"CONST","name":"?32?sh0","addr":"(K)","loc":"e,13:18,13:19","dtypep":"(L)"} ],"attrsp": []}, - {"type":"VAR","name":"crc","addr":"(M)","loc":"d,14:15,14:18","dtypep":"UNLINKED","origName":"crc","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"VAR","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", + {"type":"VAR","name":"crc","addr":"(M)","loc":"e,14:15,14:18","dtypep":"UNLINKED","origName":"crc","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"VAR","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", "childDTypep": [ - {"type":"BASICDTYPE","name":"logic","addr":"(N)","loc":"d,14:4,14:7","dtypep":"(N)","keyword":"logic","generic":false, + {"type":"BASICDTYPE","name":"logic","addr":"(N)","loc":"e,14:4,14:7","dtypep":"(N)","keyword":"logic","generic":false, "rangep": [ - {"type":"RANGE","name":"","addr":"(O)","loc":"d,14:8,14:9","ascending":false, + {"type":"RANGE","name":"","addr":"(O)","loc":"e,14:8,14:9","ascending":false, "leftp": [ - {"type":"CONST","name":"?32?sh3f","addr":"(P)","loc":"d,14:9,14:11","dtypep":"(Q)"} + {"type":"CONST","name":"?32?sh3f","addr":"(P)","loc":"e,14:9,14:11","dtypep":"(Q)"} ], "rightp": [ - {"type":"CONST","name":"?32?sh0","addr":"(R)","loc":"d,14:12,14:13","dtypep":"(L)"} + {"type":"CONST","name":"?32?sh0","addr":"(R)","loc":"e,14:12,14:13","dtypep":"(L)"} ]} ]} ],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"sum","addr":"(S)","loc":"d,15:15,15:18","dtypep":"UNLINKED","origName":"sum","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"VAR","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", + {"type":"VAR","name":"sum","addr":"(S)","loc":"e,15:15,15:18","dtypep":"UNLINKED","origName":"sum","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"VAR","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", "childDTypep": [ - {"type":"BASICDTYPE","name":"logic","addr":"(T)","loc":"d,15:4,15:7","dtypep":"(T)","keyword":"logic","generic":false, + {"type":"BASICDTYPE","name":"logic","addr":"(T)","loc":"e,15:4,15:7","dtypep":"(T)","keyword":"logic","generic":false, "rangep": [ - {"type":"RANGE","name":"","addr":"(U)","loc":"d,15:8,15:9","ascending":false, + {"type":"RANGE","name":"","addr":"(U)","loc":"e,15:8,15:9","ascending":false, "leftp": [ - {"type":"CONST","name":"?32?sh3f","addr":"(V)","loc":"d,15:9,15:11","dtypep":"(Q)"} + {"type":"CONST","name":"?32?sh3f","addr":"(V)","loc":"e,15:9,15:11","dtypep":"(Q)"} ], "rightp": [ - {"type":"CONST","name":"?32?sh0","addr":"(W)","loc":"d,15:12,15:13","dtypep":"(L)"} + {"type":"CONST","name":"?32?sh0","addr":"(W)","loc":"e,15:12,15:13","dtypep":"(L)"} ]} ]} ],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"in","addr":"(X)","loc":"d,18:16,18:18","dtypep":"UNLINKED","origName":"in","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"WIRE","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", + {"type":"VAR","name":"in","addr":"(X)","loc":"e,18:16,18:18","dtypep":"UNLINKED","origName":"in","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"WIRE","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", "childDTypep": [ - {"type":"BASICDTYPE","name":"logic","addr":"(Y)","loc":"d,18:9,18:10","dtypep":"(Y)","keyword":"logic","generic":false, + {"type":"BASICDTYPE","name":"logic","addr":"(Y)","loc":"e,18:9,18:10","dtypep":"(Y)","keyword":"logic","generic":false, "rangep": [ - {"type":"RANGE","name":"","addr":"(Z)","loc":"d,18:9,18:10","ascending":false, + {"type":"RANGE","name":"","addr":"(Z)","loc":"e,18:9,18:10","ascending":false, "leftp": [ - {"type":"CONST","name":"?32?sh1f","addr":"(AB)","loc":"d,18:10,18:12","dtypep":"(BB)"} + {"type":"CONST","name":"?32?sh1f","addr":"(AB)","loc":"e,18:10,18:12","dtypep":"(BB)"} ], "rightp": [ - {"type":"CONST","name":"?32?sh0","addr":"(CB)","loc":"d,18:13,18:14","dtypep":"(L)"} + {"type":"CONST","name":"?32?sh0","addr":"(CB)","loc":"e,18:13,18:14","dtypep":"(L)"} ]} ]} ],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"ASSIGNW","name":"","addr":"(DB)","loc":"d,18:19,18:20","dtypep":"UNLINKED", + {"type":"ASSIGNW","name":"","addr":"(DB)","loc":"e,18:19,18:20","dtypep":"UNLINKED", "rhsp": [ - {"type":"SELEXTRACT","name":"","addr":"(EB)","loc":"d,18:24,18:25","dtypep":"UNLINKED", + {"type":"SELEXTRACT","name":"","addr":"(EB)","loc":"e,18:24,18:25","dtypep":"UNLINKED", "fromp": [ - {"type":"PARSEREF","name":"crc","addr":"(FB)","loc":"d,18:21,18:24","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"crc","addr":"(FB)","loc":"e,18:21,18:24","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "leftp": [ - {"type":"CONST","name":"?32?sh1f","addr":"(GB)","loc":"d,18:25,18:27","dtypep":"(BB)"} + {"type":"CONST","name":"?32?sh1f","addr":"(GB)","loc":"e,18:25,18:27","dtypep":"(BB)"} ], "rightp": [ - {"type":"CONST","name":"?32?sh0","addr":"(HB)","loc":"d,18:28,18:29","dtypep":"(L)"} + {"type":"CONST","name":"?32?sh0","addr":"(HB)","loc":"e,18:28,18:29","dtypep":"(L)"} ],"attrp": []} ], "lhsp": [ - {"type":"PARSEREF","name":"in","addr":"(IB)","loc":"d,18:16,18:18","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"in","addr":"(IB)","loc":"e,18:16,18:18","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ],"timingControlp": [],"strengthSpecp": []}, - {"type":"VAR","name":"out","addr":"(JB)","loc":"d,22:25,22:28","dtypep":"UNLINKED","origName":"out","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"WIRE","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", + {"type":"VAR","name":"out","addr":"(JB)","loc":"e,22:25,22:28","dtypep":"UNLINKED","origName":"out","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"WIRE","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", "childDTypep": [ - {"type":"BASICDTYPE","name":"logic","addr":"(KB)","loc":"d,22:9,22:10","dtypep":"(KB)","keyword":"logic","generic":false, + {"type":"BASICDTYPE","name":"logic","addr":"(KB)","loc":"e,22:9,22:10","dtypep":"(KB)","keyword":"logic","generic":false, "rangep": [ - {"type":"RANGE","name":"","addr":"(LB)","loc":"d,22:9,22:10","ascending":false, + {"type":"RANGE","name":"","addr":"(LB)","loc":"e,22:9,22:10","ascending":false, "leftp": [ - {"type":"CONST","name":"?32?sh1f","addr":"(MB)","loc":"d,22:10,22:12","dtypep":"(BB)"} + {"type":"CONST","name":"?32?sh1f","addr":"(MB)","loc":"e,22:10,22:12","dtypep":"(BB)"} ], "rightp": [ - {"type":"CONST","name":"?32?sh0","addr":"(NB)","loc":"d,22:13,22:14","dtypep":"(L)"} + {"type":"CONST","name":"?32?sh0","addr":"(NB)","loc":"e,22:13,22:14","dtypep":"(L)"} ]} ]} ],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"CELL","name":"test","addr":"(OB)","loc":"d,25:9,25:13","origName":"test","recursive":false,"modp":"(PB)", + {"type":"CELL","name":"test","addr":"(OB)","loc":"e,25:9,25:13","origName":"test","recursive":false,"modp":"(PB)", "pinsp": [ - {"type":"PIN","name":"out","addr":"(QB)","loc":"d,27:15,27:18","svDotName":true,"svImplicit":false,"modVarp":"UNLINKED","modPTypep":"UNLINKED", + {"type":"PIN","name":"out","addr":"(QB)","loc":"e,27:15,27:18","svDotName":true,"svImplicit":false,"modVarp":"UNLINKED","modPTypep":"UNLINKED", "exprp": [ - {"type":"SELEXTRACT","name":"","addr":"(RB)","loc":"d,27:45,27:46","dtypep":"UNLINKED", + {"type":"SELEXTRACT","name":"","addr":"(RB)","loc":"e,27:45,27:46","dtypep":"UNLINKED", "fromp": [ - {"type":"PARSEREF","name":"out","addr":"(SB)","loc":"d,27:42,27:45","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"out","addr":"(SB)","loc":"e,27:42,27:45","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "leftp": [ - {"type":"CONST","name":"?32?sh1f","addr":"(TB)","loc":"d,27:46,27:48","dtypep":"(BB)"} + {"type":"CONST","name":"?32?sh1f","addr":"(TB)","loc":"e,27:46,27:48","dtypep":"(BB)"} ], "rightp": [ - {"type":"CONST","name":"?32?sh0","addr":"(UB)","loc":"d,27:49,27:50","dtypep":"(L)"} + {"type":"CONST","name":"?32?sh0","addr":"(UB)","loc":"e,27:49,27:50","dtypep":"(L)"} ],"attrp": []} ]}, - {"type":"PIN","name":"clk","addr":"(VB)","loc":"d,29:15,29:18","svDotName":true,"svImplicit":false,"modVarp":"UNLINKED","modPTypep":"UNLINKED", + {"type":"PIN","name":"clk","addr":"(VB)","loc":"e,29:15,29:18","svDotName":true,"svImplicit":false,"modVarp":"UNLINKED","modPTypep":"UNLINKED", "exprp": [ - {"type":"PARSEREF","name":"clk","addr":"(WB)","loc":"d,29:42,29:45","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"clk","addr":"(WB)","loc":"e,29:42,29:45","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ]}, - {"type":"PIN","name":"in","addr":"(XB)","loc":"d,30:15,30:17","svDotName":true,"svImplicit":false,"modVarp":"UNLINKED","modPTypep":"UNLINKED", + {"type":"PIN","name":"in","addr":"(XB)","loc":"e,30:15,30:17","svDotName":true,"svImplicit":false,"modVarp":"UNLINKED","modPTypep":"UNLINKED", "exprp": [ - {"type":"SELEXTRACT","name":"","addr":"(YB)","loc":"d,30:44,30:45","dtypep":"UNLINKED", + {"type":"SELEXTRACT","name":"","addr":"(YB)","loc":"e,30:44,30:45","dtypep":"UNLINKED", "fromp": [ - {"type":"PARSEREF","name":"in","addr":"(ZB)","loc":"d,30:42,30:44","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"in","addr":"(ZB)","loc":"e,30:42,30:44","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "leftp": [ - {"type":"CONST","name":"?32?sh1f","addr":"(AC)","loc":"d,30:45,30:47","dtypep":"(BB)"} + {"type":"CONST","name":"?32?sh1f","addr":"(AC)","loc":"e,30:45,30:47","dtypep":"(BB)"} ], "rightp": [ - {"type":"CONST","name":"?32?sh0","addr":"(BC)","loc":"d,30:48,30:49","dtypep":"(L)"} + {"type":"CONST","name":"?32?sh0","addr":"(BC)","loc":"e,30:48,30:49","dtypep":"(L)"} ],"attrp": []} ]} ],"paramsp": [],"rangep": [],"intfRefsp": []}, - {"type":"VAR","name":"result","addr":"(CC)","loc":"d,33:16,33:22","dtypep":"UNLINKED","origName":"result","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"WIRE","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", + {"type":"VAR","name":"result","addr":"(CC)","loc":"e,33:16,33:22","dtypep":"UNLINKED","origName":"result","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"WIRE","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", "childDTypep": [ - {"type":"BASICDTYPE","name":"logic","addr":"(DC)","loc":"d,33:9,33:10","dtypep":"(DC)","keyword":"logic","generic":false, + {"type":"BASICDTYPE","name":"logic","addr":"(DC)","loc":"e,33:9,33:10","dtypep":"(DC)","keyword":"logic","generic":false, "rangep": [ - {"type":"RANGE","name":"","addr":"(EC)","loc":"d,33:9,33:10","ascending":false, + {"type":"RANGE","name":"","addr":"(EC)","loc":"e,33:9,33:10","ascending":false, "leftp": [ - {"type":"CONST","name":"?32?sh3f","addr":"(FC)","loc":"d,33:10,33:12","dtypep":"(Q)"} + {"type":"CONST","name":"?32?sh3f","addr":"(FC)","loc":"e,33:10,33:12","dtypep":"(Q)"} ], "rightp": [ - {"type":"CONST","name":"?32?sh0","addr":"(GC)","loc":"d,33:13,33:14","dtypep":"(L)"} + {"type":"CONST","name":"?32?sh0","addr":"(GC)","loc":"e,33:13,33:14","dtypep":"(L)"} ]} ]} ],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"ASSIGNW","name":"","addr":"(HC)","loc":"d,33:23,33:24","dtypep":"UNLINKED", + {"type":"ASSIGNW","name":"","addr":"(HC)","loc":"e,33:23,33:24","dtypep":"UNLINKED", "rhsp": [ - {"type":"REPLICATE","name":"","addr":"(IC)","loc":"d,33:25,33:26","dtypep":"(JC)", + {"type":"REPLICATE","name":"","addr":"(IC)","loc":"e,33:25,33:26","dtypep":"(JC)", "srcp": [ - {"type":"CONCAT","name":"","addr":"(KC)","loc":"d,33:31,33:32","dtypep":"UNLINKED", + {"type":"CONCAT","name":"","addr":"(KC)","loc":"e,33:31,33:32","dtypep":"UNLINKED", "lhsp": [ - {"type":"CONST","name":"32'h0","addr":"(LC)","loc":"d,33:26,33:31","dtypep":"(MC)"} + {"type":"CONST","name":"32'h0","addr":"(LC)","loc":"e,33:26,33:31","dtypep":"(MC)"} ], "rhsp": [ - {"type":"PARSEREF","name":"out","addr":"(NC)","loc":"d,33:33,33:36","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"out","addr":"(NC)","loc":"e,33:33,33:36","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ]} ], "countp": [ - {"type":"CONST","name":"32'h1","addr":"(OC)","loc":"d,33:25,33:26","dtypep":"(MC)"} + {"type":"CONST","name":"32'h1","addr":"(OC)","loc":"e,33:25,33:26","dtypep":"(MC)"} ]} ], "lhsp": [ - {"type":"PARSEREF","name":"result","addr":"(PC)","loc":"d,33:16,33:22","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"result","addr":"(PC)","loc":"e,33:16,33:22","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ],"timingControlp": [],"strengthSpecp": []}, - {"type":"ALWAYS","name":"","addr":"(QC)","loc":"d,36:4,36:10","keyword":"always","isSuspendable":false,"needProcess":false,"sensesp": [], + {"type":"ALWAYS","name":"","addr":"(QC)","loc":"e,36:4,36:10","keyword":"always","isSuspendable":false,"needProcess":false,"sensesp": [], "stmtsp": [ - {"type":"EVENTCONTROL","name":"","addr":"(RC)","loc":"d,36:11,36:12", + {"type":"EVENTCONTROL","name":"","addr":"(RC)","loc":"e,36:11,36:12", "sensesp": [ - {"type":"SENTREE","name":"","addr":"(SC)","loc":"d,36:11,36:12","isMulti":false, + {"type":"SENTREE","name":"","addr":"(SC)","loc":"e,36:11,36:12","isMulti":false, "sensesp": [ - {"type":"SENITEM","name":"","addr":"(TC)","loc":"d,36:14,36:21","edgeType":"POS", + {"type":"SENITEM","name":"","addr":"(TC)","loc":"e,36:14,36:21","edgeType":"POS", "sensp": [ - {"type":"PARSEREF","name":"clk","addr":"(UC)","loc":"d,36:22,36:25","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"clk","addr":"(UC)","loc":"e,36:22,36:25","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ],"condp": []} ]} ], "stmtsp": [ - {"type":"BEGIN","name":"","addr":"(VC)","loc":"d,36:27,36:32","generate":false,"genfor":false,"implied":false,"needProcess":false,"unnamed":true,"genforp": [], + {"type":"BEGIN","name":"","addr":"(VC)","loc":"e,36:27,36:32","generate":false,"genfor":false,"implied":false,"needProcess":false,"unnamed":true,"genforp": [], "stmtsp": [ - {"type":"ASSIGNDLY","name":"","addr":"(WC)","loc":"d,40:11,40:13","dtypep":"UNLINKED", + {"type":"ASSIGNDLY","name":"","addr":"(WC)","loc":"e,40:11,40:13","dtypep":"UNLINKED", "rhsp": [ - {"type":"ADD","name":"","addr":"(XC)","loc":"d,40:18,40:19","dtypep":"UNLINKED", + {"type":"ADD","name":"","addr":"(XC)","loc":"e,40:18,40:19","dtypep":"UNLINKED", "lhsp": [ - {"type":"PARSEREF","name":"cyc","addr":"(YC)","loc":"d,40:14,40:17","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"cyc","addr":"(YC)","loc":"e,40:14,40:17","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "rhsp": [ - {"type":"CONST","name":"?32?sh1","addr":"(ZC)","loc":"d,40:20,40:21","dtypep":"(L)"} + {"type":"CONST","name":"?32?sh1","addr":"(ZC)","loc":"e,40:20,40:21","dtypep":"(L)"} ]} ], "lhsp": [ - {"type":"PARSEREF","name":"cyc","addr":"(AD)","loc":"d,40:7,40:10","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"cyc","addr":"(AD)","loc":"e,40:7,40:10","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ],"timingControlp": []}, - {"type":"ASSIGNDLY","name":"","addr":"(BD)","loc":"d,41:11,41:13","dtypep":"UNLINKED", + {"type":"ASSIGNDLY","name":"","addr":"(BD)","loc":"e,41:11,41:13","dtypep":"UNLINKED", "rhsp": [ - {"type":"REPLICATE","name":"","addr":"(CD)","loc":"d,41:14,41:15","dtypep":"(JC)", + {"type":"REPLICATE","name":"","addr":"(CD)","loc":"e,41:14,41:15","dtypep":"(JC)", "srcp": [ - {"type":"CONCAT","name":"","addr":"(DD)","loc":"d,41:24,41:25","dtypep":"UNLINKED", + {"type":"CONCAT","name":"","addr":"(DD)","loc":"e,41:24,41:25","dtypep":"UNLINKED", "lhsp": [ - {"type":"SELEXTRACT","name":"","addr":"(ED)","loc":"d,41:18,41:19","dtypep":"UNLINKED", + {"type":"SELEXTRACT","name":"","addr":"(ED)","loc":"e,41:18,41:19","dtypep":"UNLINKED", "fromp": [ - {"type":"PARSEREF","name":"crc","addr":"(FD)","loc":"d,41:15,41:18","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"crc","addr":"(FD)","loc":"e,41:15,41:18","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "leftp": [ - {"type":"CONST","name":"?32?sh3e","addr":"(GD)","loc":"d,41:19,41:21","dtypep":"(Q)"} + {"type":"CONST","name":"?32?sh3e","addr":"(GD)","loc":"e,41:19,41:21","dtypep":"(Q)"} ], "rightp": [ - {"type":"CONST","name":"?32?sh0","addr":"(HD)","loc":"d,41:22,41:23","dtypep":"(L)"} + {"type":"CONST","name":"?32?sh0","addr":"(HD)","loc":"e,41:22,41:23","dtypep":"(L)"} ],"attrp": []} ], "rhsp": [ - {"type":"XOR","name":"","addr":"(ID)","loc":"d,41:43,41:44","dtypep":"UNLINKED", + {"type":"XOR","name":"","addr":"(ID)","loc":"e,41:43,41:44","dtypep":"UNLINKED", "lhsp": [ - {"type":"XOR","name":"","addr":"(JD)","loc":"d,41:34,41:35","dtypep":"UNLINKED", + {"type":"XOR","name":"","addr":"(JD)","loc":"e,41:34,41:35","dtypep":"UNLINKED", "lhsp": [ - {"type":"SELBIT","name":"","addr":"(KD)","loc":"d,41:29,41:30","dtypep":"UNLINKED", + {"type":"SELBIT","name":"","addr":"(KD)","loc":"e,41:29,41:30","dtypep":"UNLINKED", "fromp": [ - {"type":"PARSEREF","name":"crc","addr":"(LD)","loc":"d,41:26,41:29","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"crc","addr":"(LD)","loc":"e,41:26,41:29","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "bitp": [ - {"type":"CONST","name":"?32?sh3f","addr":"(MD)","loc":"d,41:30,41:32","dtypep":"(Q)"} + {"type":"CONST","name":"?32?sh3f","addr":"(MD)","loc":"e,41:30,41:32","dtypep":"(Q)"} ],"thsp": [],"attrp": []} ], "rhsp": [ - {"type":"SELBIT","name":"","addr":"(ND)","loc":"d,41:39,41:40","dtypep":"UNLINKED", + {"type":"SELBIT","name":"","addr":"(ND)","loc":"e,41:39,41:40","dtypep":"UNLINKED", "fromp": [ - {"type":"PARSEREF","name":"crc","addr":"(OD)","loc":"d,41:36,41:39","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"crc","addr":"(OD)","loc":"e,41:36,41:39","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "bitp": [ - {"type":"CONST","name":"?32?sh2","addr":"(PD)","loc":"d,41:40,41:41","dtypep":"(QD)"} + {"type":"CONST","name":"?32?sh2","addr":"(PD)","loc":"e,41:40,41:41","dtypep":"(QD)"} ],"thsp": [],"attrp": []} ]} ], "rhsp": [ - {"type":"SELBIT","name":"","addr":"(RD)","loc":"d,41:48,41:49","dtypep":"UNLINKED", + {"type":"SELBIT","name":"","addr":"(RD)","loc":"e,41:48,41:49","dtypep":"UNLINKED", "fromp": [ - {"type":"PARSEREF","name":"crc","addr":"(SD)","loc":"d,41:45,41:48","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"crc","addr":"(SD)","loc":"e,41:45,41:48","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "bitp": [ - {"type":"CONST","name":"?32?sh0","addr":"(TD)","loc":"d,41:49,41:50","dtypep":"(L)"} + {"type":"CONST","name":"?32?sh0","addr":"(TD)","loc":"e,41:49,41:50","dtypep":"(L)"} ],"thsp": [],"attrp": []} ]} ]} ], "countp": [ - {"type":"CONST","name":"32'h1","addr":"(UD)","loc":"d,41:14,41:15","dtypep":"(MC)"} + {"type":"CONST","name":"32'h1","addr":"(UD)","loc":"e,41:14,41:15","dtypep":"(MC)"} ]} ], "lhsp": [ - {"type":"PARSEREF","name":"crc","addr":"(VD)","loc":"d,41:7,41:10","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"crc","addr":"(VD)","loc":"e,41:7,41:10","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ],"timingControlp": []}, - {"type":"ASSIGNDLY","name":"","addr":"(WD)","loc":"d,42:11,42:13","dtypep":"UNLINKED", + {"type":"ASSIGNDLY","name":"","addr":"(WD)","loc":"e,42:11,42:13","dtypep":"UNLINKED", "rhsp": [ - {"type":"XOR","name":"","addr":"(XD)","loc":"d,42:21,42:22","dtypep":"UNLINKED", + {"type":"XOR","name":"","addr":"(XD)","loc":"e,42:21,42:22","dtypep":"UNLINKED", "lhsp": [ - {"type":"PARSEREF","name":"result","addr":"(YD)","loc":"d,42:14,42:20","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"result","addr":"(YD)","loc":"e,42:14,42:20","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "rhsp": [ - {"type":"REPLICATE","name":"","addr":"(ZD)","loc":"d,42:23,42:24","dtypep":"(JC)", + {"type":"REPLICATE","name":"","addr":"(ZD)","loc":"e,42:23,42:24","dtypep":"(JC)", "srcp": [ - {"type":"CONCAT","name":"","addr":"(AE)","loc":"d,42:33,42:34","dtypep":"UNLINKED", + {"type":"CONCAT","name":"","addr":"(AE)","loc":"e,42:33,42:34","dtypep":"UNLINKED", "lhsp": [ - {"type":"SELEXTRACT","name":"","addr":"(BE)","loc":"d,42:27,42:28","dtypep":"UNLINKED", + {"type":"SELEXTRACT","name":"","addr":"(BE)","loc":"e,42:27,42:28","dtypep":"UNLINKED", "fromp": [ - {"type":"PARSEREF","name":"sum","addr":"(CE)","loc":"d,42:24,42:27","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"sum","addr":"(CE)","loc":"e,42:24,42:27","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "leftp": [ - {"type":"CONST","name":"?32?sh3e","addr":"(DE)","loc":"d,42:28,42:30","dtypep":"(Q)"} + {"type":"CONST","name":"?32?sh3e","addr":"(DE)","loc":"e,42:28,42:30","dtypep":"(Q)"} ], "rightp": [ - {"type":"CONST","name":"?32?sh0","addr":"(EE)","loc":"d,42:31,42:32","dtypep":"(L)"} + {"type":"CONST","name":"?32?sh0","addr":"(EE)","loc":"e,42:31,42:32","dtypep":"(L)"} ],"attrp": []} ], "rhsp": [ - {"type":"XOR","name":"","addr":"(FE)","loc":"d,42:52,42:53","dtypep":"UNLINKED", + {"type":"XOR","name":"","addr":"(FE)","loc":"e,42:52,42:53","dtypep":"UNLINKED", "lhsp": [ - {"type":"XOR","name":"","addr":"(GE)","loc":"d,42:43,42:44","dtypep":"UNLINKED", + {"type":"XOR","name":"","addr":"(GE)","loc":"e,42:43,42:44","dtypep":"UNLINKED", "lhsp": [ - {"type":"SELBIT","name":"","addr":"(HE)","loc":"d,42:38,42:39","dtypep":"UNLINKED", + {"type":"SELBIT","name":"","addr":"(HE)","loc":"e,42:38,42:39","dtypep":"UNLINKED", "fromp": [ - {"type":"PARSEREF","name":"sum","addr":"(IE)","loc":"d,42:35,42:38","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"sum","addr":"(IE)","loc":"e,42:35,42:38","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "bitp": [ - {"type":"CONST","name":"?32?sh3f","addr":"(JE)","loc":"d,42:39,42:41","dtypep":"(Q)"} + {"type":"CONST","name":"?32?sh3f","addr":"(JE)","loc":"e,42:39,42:41","dtypep":"(Q)"} ],"thsp": [],"attrp": []} ], "rhsp": [ - {"type":"SELBIT","name":"","addr":"(KE)","loc":"d,42:48,42:49","dtypep":"UNLINKED", + {"type":"SELBIT","name":"","addr":"(KE)","loc":"e,42:48,42:49","dtypep":"UNLINKED", "fromp": [ - {"type":"PARSEREF","name":"sum","addr":"(LE)","loc":"d,42:45,42:48","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"sum","addr":"(LE)","loc":"e,42:45,42:48","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "bitp": [ - {"type":"CONST","name":"?32?sh2","addr":"(ME)","loc":"d,42:49,42:50","dtypep":"(QD)"} + {"type":"CONST","name":"?32?sh2","addr":"(ME)","loc":"e,42:49,42:50","dtypep":"(QD)"} ],"thsp": [],"attrp": []} ]} ], "rhsp": [ - {"type":"SELBIT","name":"","addr":"(NE)","loc":"d,42:57,42:58","dtypep":"UNLINKED", + {"type":"SELBIT","name":"","addr":"(NE)","loc":"e,42:57,42:58","dtypep":"UNLINKED", "fromp": [ - {"type":"PARSEREF","name":"sum","addr":"(OE)","loc":"d,42:54,42:57","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"sum","addr":"(OE)","loc":"e,42:54,42:57","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "bitp": [ - {"type":"CONST","name":"?32?sh0","addr":"(PE)","loc":"d,42:58,42:59","dtypep":"(L)"} + {"type":"CONST","name":"?32?sh0","addr":"(PE)","loc":"e,42:58,42:59","dtypep":"(L)"} ],"thsp": [],"attrp": []} ]} ]} ], "countp": [ - {"type":"CONST","name":"32'h1","addr":"(QE)","loc":"d,42:23,42:24","dtypep":"(MC)"} + {"type":"CONST","name":"32'h1","addr":"(QE)","loc":"e,42:23,42:24","dtypep":"(MC)"} ]} ]} ], "lhsp": [ - {"type":"PARSEREF","name":"sum","addr":"(RE)","loc":"d,42:7,42:10","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"sum","addr":"(RE)","loc":"e,42:7,42:10","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ],"timingControlp": []}, - {"type":"IF","name":"","addr":"(SE)","loc":"d,43:7,43:9", + {"type":"IF","name":"","addr":"(SE)","loc":"e,43:7,43:9", "condp": [ - {"type":"EQ","name":"","addr":"(TE)","loc":"d,43:15,43:17","dtypep":"(UE)", + {"type":"EQ","name":"","addr":"(TE)","loc":"e,43:15,43:17","dtypep":"(UE)", "lhsp": [ - {"type":"PARSEREF","name":"cyc","addr":"(VE)","loc":"d,43:11,43:14","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"cyc","addr":"(VE)","loc":"e,43:11,43:14","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "rhsp": [ - {"type":"CONST","name":"?32?sh0","addr":"(WE)","loc":"d,43:18,43:19","dtypep":"(L)"} + {"type":"CONST","name":"?32?sh0","addr":"(WE)","loc":"e,43:18,43:19","dtypep":"(L)"} ]} ], "thensp": [ - {"type":"BEGIN","name":"","addr":"(XE)","loc":"d,43:21,43:26","generate":false,"genfor":false,"implied":false,"needProcess":false,"unnamed":true,"genforp": [], + {"type":"BEGIN","name":"","addr":"(XE)","loc":"e,43:21,43:26","generate":false,"genfor":false,"implied":false,"needProcess":false,"unnamed":true,"genforp": [], "stmtsp": [ - {"type":"ASSIGNDLY","name":"","addr":"(YE)","loc":"d,45:14,45:16","dtypep":"UNLINKED", + {"type":"ASSIGNDLY","name":"","addr":"(YE)","loc":"e,45:14,45:16","dtypep":"UNLINKED", "rhsp": [ - {"type":"CONST","name":"64'h5aef0c8dd70a4497","addr":"(ZE)","loc":"d,45:17,45:38","dtypep":"(AF)"} + {"type":"CONST","name":"64'h5aef0c8dd70a4497","addr":"(ZE)","loc":"e,45:17,45:38","dtypep":"(AF)"} ], "lhsp": [ - {"type":"PARSEREF","name":"crc","addr":"(BF)","loc":"d,45:10,45:13","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"crc","addr":"(BF)","loc":"e,45:10,45:13","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ],"timingControlp": []}, - {"type":"ASSIGNDLY","name":"","addr":"(CF)","loc":"d,46:14,46:16","dtypep":"UNLINKED", + {"type":"ASSIGNDLY","name":"","addr":"(CF)","loc":"e,46:14,46:16","dtypep":"UNLINKED", "rhsp": [ - {"type":"CONST","name":"'0","addr":"(DF)","loc":"d,46:17,46:19","dtypep":"(UE)"} + {"type":"CONST","name":"'0","addr":"(DF)","loc":"e,46:17,46:19","dtypep":"(UE)"} ], "lhsp": [ - {"type":"PARSEREF","name":"sum","addr":"(EF)","loc":"d,46:10,46:13","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"sum","addr":"(EF)","loc":"e,46:10,46:13","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ],"timingControlp": []} ]} ], "elsesp": [ - {"type":"IF","name":"","addr":"(FF)","loc":"d,48:12,48:14", + {"type":"IF","name":"","addr":"(FF)","loc":"e,48:12,48:14", "condp": [ - {"type":"LT","name":"","addr":"(GF)","loc":"d,48:20,48:21","dtypep":"(UE)", + {"type":"LT","name":"","addr":"(GF)","loc":"e,48:20,48:21","dtypep":"(UE)", "lhsp": [ - {"type":"PARSEREF","name":"cyc","addr":"(HF)","loc":"d,48:16,48:19","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"cyc","addr":"(HF)","loc":"e,48:16,48:19","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "rhsp": [ - {"type":"CONST","name":"?32?sha","addr":"(IF)","loc":"d,48:22,48:24","dtypep":"(JF)"} + {"type":"CONST","name":"?32?sha","addr":"(IF)","loc":"e,48:22,48:24","dtypep":"(JF)"} ]} ], "thensp": [ - {"type":"BEGIN","name":"","addr":"(KF)","loc":"d,48:26,48:31","generate":false,"genfor":false,"implied":false,"needProcess":false,"unnamed":true,"genforp": [], + {"type":"BEGIN","name":"","addr":"(KF)","loc":"e,48:26,48:31","generate":false,"genfor":false,"implied":false,"needProcess":false,"unnamed":true,"genforp": [], "stmtsp": [ - {"type":"ASSIGNDLY","name":"","addr":"(LF)","loc":"d,49:14,49:16","dtypep":"UNLINKED", + {"type":"ASSIGNDLY","name":"","addr":"(LF)","loc":"e,49:14,49:16","dtypep":"UNLINKED", "rhsp": [ - {"type":"CONST","name":"'0","addr":"(MF)","loc":"d,49:17,49:19","dtypep":"(UE)"} + {"type":"CONST","name":"'0","addr":"(MF)","loc":"e,49:17,49:19","dtypep":"(UE)"} ], "lhsp": [ - {"type":"PARSEREF","name":"sum","addr":"(NF)","loc":"d,49:10,49:13","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"sum","addr":"(NF)","loc":"e,49:10,49:13","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ],"timingControlp": []} ]} ], "elsesp": [ - {"type":"IF","name":"","addr":"(OF)","loc":"d,51:12,51:14", + {"type":"IF","name":"","addr":"(OF)","loc":"e,51:12,51:14", "condp": [ - {"type":"LT","name":"","addr":"(PF)","loc":"d,51:20,51:21","dtypep":"(UE)", + {"type":"LT","name":"","addr":"(PF)","loc":"e,51:20,51:21","dtypep":"(UE)", "lhsp": [ - {"type":"PARSEREF","name":"cyc","addr":"(QF)","loc":"d,51:16,51:19","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"cyc","addr":"(QF)","loc":"e,51:16,51:19","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "rhsp": [ - {"type":"CONST","name":"?32?sh5a","addr":"(RF)","loc":"d,51:22,51:24","dtypep":"(SF)"} + {"type":"CONST","name":"?32?sh5a","addr":"(RF)","loc":"e,51:22,51:24","dtypep":"(SF)"} ]} ], "thensp": [ - {"type":"BEGIN","name":"","addr":"(TF)","loc":"d,51:26,51:31","generate":false,"genfor":false,"implied":false,"needProcess":false,"unnamed":true,"genforp": [],"stmtsp": []} + {"type":"BEGIN","name":"","addr":"(TF)","loc":"e,51:26,51:31","generate":false,"genfor":false,"implied":false,"needProcess":false,"unnamed":true,"genforp": [],"stmtsp": []} ], "elsesp": [ - {"type":"IF","name":"","addr":"(UF)","loc":"d,53:12,53:14", + {"type":"IF","name":"","addr":"(UF)","loc":"e,53:12,53:14", "condp": [ - {"type":"EQ","name":"","addr":"(VF)","loc":"d,53:20,53:22","dtypep":"(UE)", + {"type":"EQ","name":"","addr":"(VF)","loc":"e,53:20,53:22","dtypep":"(UE)", "lhsp": [ - {"type":"PARSEREF","name":"cyc","addr":"(WF)","loc":"d,53:16,53:19","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"cyc","addr":"(WF)","loc":"e,53:16,53:19","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "rhsp": [ - {"type":"CONST","name":"?32?sh63","addr":"(XF)","loc":"d,53:23,53:25","dtypep":"(SF)"} + {"type":"CONST","name":"?32?sh63","addr":"(XF)","loc":"e,53:23,53:25","dtypep":"(SF)"} ]} ], "thensp": [ - {"type":"BEGIN","name":"","addr":"(YF)","loc":"d,53:27,53:32","generate":false,"genfor":false,"implied":false,"needProcess":false,"unnamed":true,"genforp": [], + {"type":"BEGIN","name":"","addr":"(YF)","loc":"e,53:27,53:32","generate":false,"genfor":false,"implied":false,"needProcess":false,"unnamed":true,"genforp": [], "stmtsp": [ - {"type":"DISPLAY","name":"","addr":"(ZF)","loc":"d,54:10,54:16", + {"type":"DISPLAY","name":"","addr":"(ZF)","loc":"e,54:10,54:16", "fmtp": [ - {"type":"SFORMATF","name":"","addr":"(AG)","loc":"d,54:10,54:16","dtypep":"(BG)", + {"type":"SFORMATF","name":"","addr":"(AG)","loc":"e,54:10,54:16","dtypep":"(BG)", "exprsp": [ - {"type":"CONST","name":"232'h5b2530745d206379633d3d253064206372633d25782073756d3d25780a","addr":"(CG)","loc":"d,54:17,54:49","dtypep":"(DG)"}, - {"type":"TIME","name":"","addr":"(EG)","loc":"d,54:51,54:56","dtypep":"(FG)","timeunit":"NONE"}, - {"type":"PARSEREF","name":"cyc","addr":"(GG)","loc":"d,54:58,54:61","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []}, - {"type":"PARSEREF","name":"crc","addr":"(HG)","loc":"d,54:63,54:66","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []}, - {"type":"PARSEREF","name":"sum","addr":"(IG)","loc":"d,54:68,54:71","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"CONST","name":"232'h5b2530745d206379633d3d253064206372633d25782073756d3d25780a","addr":"(CG)","loc":"e,54:17,54:49","dtypep":"(DG)"}, + {"type":"TIME","name":"","addr":"(EG)","loc":"e,54:51,54:56","dtypep":"(FG)","timeunit":"NONE"}, + {"type":"PARSEREF","name":"cyc","addr":"(GG)","loc":"e,54:58,54:61","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []}, + {"type":"PARSEREF","name":"crc","addr":"(HG)","loc":"e,54:63,54:66","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []}, + {"type":"PARSEREF","name":"sum","addr":"(IG)","loc":"e,54:68,54:71","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ],"scopeNamep": []} ],"filep": []}, - {"type":"IF","name":"","addr":"(JG)","loc":"d,55:10,55:12", + {"type":"IF","name":"","addr":"(JG)","loc":"e,55:10,55:12", "condp": [ - {"type":"NEQCASE","name":"","addr":"(KG)","loc":"d,55:18,55:21","dtypep":"(UE)", + {"type":"NEQCASE","name":"","addr":"(KG)","loc":"e,55:18,55:21","dtypep":"(UE)", "lhsp": [ - {"type":"PARSEREF","name":"crc","addr":"(LG)","loc":"d,55:14,55:17","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"crc","addr":"(LG)","loc":"e,55:14,55:17","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "rhsp": [ - {"type":"CONST","name":"64'hc77bb9b3784ea091","addr":"(MG)","loc":"d,55:22,55:42","dtypep":"(AF)"} + {"type":"CONST","name":"64'hc77bb9b3784ea091","addr":"(MG)","loc":"e,55:22,55:42","dtypep":"(AF)"} ]} ], "thensp": [ - {"type":"STOP","name":"","addr":"(NG)","loc":"d,55:44,55:49","isFatal":false} + {"type":"STOP","name":"","addr":"(NG)","loc":"e,55:44,55:49","isFatal":false} ],"elsesp": []}, - {"type":"IF","name":"","addr":"(OG)","loc":"d,58:10,58:12", + {"type":"IF","name":"","addr":"(OG)","loc":"e,58:10,58:12", "condp": [ - {"type":"NEQCASE","name":"","addr":"(PG)","loc":"d,58:18,58:21","dtypep":"(UE)", + {"type":"NEQCASE","name":"","addr":"(PG)","loc":"e,58:18,58:21","dtypep":"(UE)", "lhsp": [ - {"type":"PARSEREF","name":"sum","addr":"(QG)","loc":"d,58:14,58:17","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"sum","addr":"(QG)","loc":"e,58:14,58:17","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "rhsp": [ - {"type":"CONST","name":"64'h4afe43fb79d7b71e","addr":"(RG)","loc":"d,58:22,58:42","dtypep":"(AF)"} + {"type":"CONST","name":"64'h4afe43fb79d7b71e","addr":"(RG)","loc":"e,58:22,58:42","dtypep":"(AF)"} ]} ], "thensp": [ - {"type":"STOP","name":"","addr":"(SG)","loc":"d,58:44,58:49","isFatal":false} + {"type":"STOP","name":"","addr":"(SG)","loc":"e,58:44,58:49","isFatal":false} ],"elsesp": []}, - {"type":"DISPLAY","name":"","addr":"(TG)","loc":"d,59:10,59:16", + {"type":"DISPLAY","name":"","addr":"(TG)","loc":"e,59:10,59:16", "fmtp": [ - {"type":"SFORMATF","name":"","addr":"(UG)","loc":"d,59:10,59:16","dtypep":"(BG)", + {"type":"SFORMATF","name":"","addr":"(UG)","loc":"e,59:10,59:16","dtypep":"(BG)", "exprsp": [ - {"type":"CONST","name":"168'h2a2d2a20416c6c2046696e6973686564202a2d2a0a","addr":"(VG)","loc":"d,59:17,59:41","dtypep":"(WG)"} + {"type":"CONST","name":"168'h2a2d2a20416c6c2046696e6973686564202a2d2a0a","addr":"(VG)","loc":"e,59:17,59:41","dtypep":"(WG)"} ],"scopeNamep": []} ],"filep": []}, - {"type":"FINISH","name":"","addr":"(XG)","loc":"d,60:10,60:17"} + {"type":"FINISH","name":"","addr":"(XG)","loc":"e,60:10,60:17"} ]} ],"elsesp": []} ]} @@ -431,85 +431,85 @@ ]} ]} ],"activesp": []}, - {"type":"MODULE","name":"Test","addr":"(PB)","loc":"d,66:8,66:12","origName":"Test","level":3,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], + {"type":"MODULE","name":"Test","addr":"(PB)","loc":"e,66:8,66:12","origName":"Test","level":3,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"PORT","name":"out","addr":"(YG)","loc":"d,68:4,68:7","exprp": []}, - {"type":"PORT","name":"clk","addr":"(ZG)","loc":"d,70:4,70:7","exprp": []}, - {"type":"PORT","name":"in","addr":"(AH)","loc":"d,70:9,70:11","exprp": []}, - {"type":"VAR","name":"clk","addr":"(BH)","loc":"d,78:10,78:13","dtypep":"UNLINKED","origName":"clk","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", + {"type":"PORT","name":"out","addr":"(YG)","loc":"e,68:4,68:7","exprp": []}, + {"type":"PORT","name":"clk","addr":"(ZG)","loc":"e,70:4,70:7","exprp": []}, + {"type":"PORT","name":"in","addr":"(AH)","loc":"e,70:9,70:11","exprp": []}, + {"type":"VAR","name":"clk","addr":"(BH)","loc":"e,78:10,78:13","dtypep":"UNLINKED","origName":"clk","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", "childDTypep": [ - {"type":"BASICDTYPE","name":"LOGIC_IMPLICIT","addr":"(CH)","loc":"d,78:10,78:13","dtypep":"(CH)","keyword":"LOGIC_IMPLICIT","generic":false,"rangep": []} + {"type":"BASICDTYPE","name":"LOGIC_IMPLICIT","addr":"(CH)","loc":"e,78:10,78:13","dtypep":"(CH)","keyword":"LOGIC_IMPLICIT","generic":false,"rangep": []} ],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"in","addr":"(DH)","loc":"d,79:17,79:19","dtypep":"UNLINKED","origName":"in","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", + {"type":"VAR","name":"in","addr":"(DH)","loc":"e,79:17,79:19","dtypep":"UNLINKED","origName":"in","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", "childDTypep": [ - {"type":"BASICDTYPE","name":"logic","addr":"(EH)","loc":"d,79:10,79:11","dtypep":"(EH)","keyword":"logic","generic":false, + {"type":"BASICDTYPE","name":"logic","addr":"(EH)","loc":"e,79:10,79:11","dtypep":"(EH)","keyword":"logic","generic":false, "rangep": [ - {"type":"RANGE","name":"","addr":"(FH)","loc":"d,79:10,79:11","ascending":false, + {"type":"RANGE","name":"","addr":"(FH)","loc":"e,79:10,79:11","ascending":false, "leftp": [ - {"type":"CONST","name":"?32?sh1f","addr":"(GH)","loc":"d,79:11,79:13","dtypep":"(BB)"} + {"type":"CONST","name":"?32?sh1f","addr":"(GH)","loc":"e,79:11,79:13","dtypep":"(BB)"} ], "rightp": [ - {"type":"CONST","name":"?32?sh0","addr":"(HH)","loc":"d,79:14,79:15","dtypep":"(L)"} + {"type":"CONST","name":"?32?sh0","addr":"(HH)","loc":"e,79:14,79:15","dtypep":"(L)"} ]} ]} ],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"out","addr":"(IH)","loc":"d,80:22,80:25","dtypep":"UNLINKED","origName":"out","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", + {"type":"VAR","name":"out","addr":"(IH)","loc":"e,80:22,80:25","dtypep":"UNLINKED","origName":"out","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED", "childDTypep": [ - {"type":"BASICDTYPE","name":"logic","addr":"(JH)","loc":"d,80:11,80:14","dtypep":"(JH)","keyword":"logic","generic":false, + {"type":"BASICDTYPE","name":"logic","addr":"(JH)","loc":"e,80:11,80:14","dtypep":"(JH)","keyword":"logic","generic":false, "rangep": [ - {"type":"RANGE","name":"","addr":"(KH)","loc":"d,80:15,80:16","ascending":false, + {"type":"RANGE","name":"","addr":"(KH)","loc":"e,80:15,80:16","ascending":false, "leftp": [ - {"type":"CONST","name":"?32?sh1f","addr":"(LH)","loc":"d,80:16,80:18","dtypep":"(BB)"} + {"type":"CONST","name":"?32?sh1f","addr":"(LH)","loc":"e,80:16,80:18","dtypep":"(BB)"} ], "rightp": [ - {"type":"CONST","name":"?32?sh0","addr":"(MH)","loc":"d,80:19,80:20","dtypep":"(L)"} + {"type":"CONST","name":"?32?sh0","addr":"(MH)","loc":"e,80:19,80:20","dtypep":"(L)"} ]} ]} ],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"ALWAYS","name":"","addr":"(NH)","loc":"d,82:4,82:10","keyword":"always","isSuspendable":false,"needProcess":false,"sensesp": [], + {"type":"ALWAYS","name":"","addr":"(NH)","loc":"e,82:4,82:10","keyword":"always","isSuspendable":false,"needProcess":false,"sensesp": [], "stmtsp": [ - {"type":"EVENTCONTROL","name":"","addr":"(OH)","loc":"d,82:11,82:12", + {"type":"EVENTCONTROL","name":"","addr":"(OH)","loc":"e,82:11,82:12", "sensesp": [ - {"type":"SENTREE","name":"","addr":"(PH)","loc":"d,82:11,82:12","isMulti":false, + {"type":"SENTREE","name":"","addr":"(PH)","loc":"e,82:11,82:12","isMulti":false, "sensesp": [ - {"type":"SENITEM","name":"","addr":"(QH)","loc":"d,82:13,82:20","edgeType":"POS", + {"type":"SENITEM","name":"","addr":"(QH)","loc":"e,82:13,82:20","edgeType":"POS", "sensp": [ - {"type":"PARSEREF","name":"clk","addr":"(RH)","loc":"d,82:21,82:24","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"clk","addr":"(RH)","loc":"e,82:21,82:24","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ],"condp": []} ]} ], "stmtsp": [ - {"type":"BEGIN","name":"","addr":"(SH)","loc":"d,82:26,82:31","generate":false,"genfor":false,"implied":false,"needProcess":false,"unnamed":true,"genforp": [], + {"type":"BEGIN","name":"","addr":"(SH)","loc":"e,82:26,82:31","generate":false,"genfor":false,"implied":false,"needProcess":false,"unnamed":true,"genforp": [], "stmtsp": [ - {"type":"ASSIGNDLY","name":"","addr":"(TH)","loc":"d,83:11,83:13","dtypep":"UNLINKED", + {"type":"ASSIGNDLY","name":"","addr":"(TH)","loc":"e,83:11,83:13","dtypep":"UNLINKED", "rhsp": [ - {"type":"PARSEREF","name":"in","addr":"(UH)","loc":"d,83:14,83:16","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"in","addr":"(UH)","loc":"e,83:14,83:16","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ], "lhsp": [ - {"type":"PARSEREF","name":"out","addr":"(VH)","loc":"d,83:7,83:10","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} + {"type":"PARSEREF","name":"out","addr":"(VH)","loc":"e,83:7,83:10","dtypep":"UNLINKED","expect":"TEXT","lhsp": [],"ftaskrefp": []} ],"timingControlp": []}, - {"type":"ASSERTCTL","name":"","addr":"(WH)","loc":"d,86:7,86:17","ctlType":"$assertoff", + {"type":"ASSERTCTL","name":"","addr":"(WH)","loc":"e,86:7,86:17","ctlType":"$assertoff", "controlTypep": [ - {"type":"CONST","name":"32'h4","addr":"(XH)","loc":"d,86:7,86:17","dtypep":"(MC)"} + {"type":"CONST","name":"32'h4","addr":"(XH)","loc":"e,86:7,86:17","dtypep":"(MC)"} ],"assertTypesp": [],"directiveTypesp": []}, - {"type":"ASSERTCTL","name":"","addr":"(YH)","loc":"d,87:7,87:18","ctlType":"$assertkill", + {"type":"ASSERTCTL","name":"","addr":"(YH)","loc":"e,87:7,87:18","ctlType":"$assertkill", "controlTypep": [ - {"type":"CONST","name":"32'h5","addr":"(ZH)","loc":"d,87:7,87:18","dtypep":"(MC)"} + {"type":"CONST","name":"32'h5","addr":"(ZH)","loc":"e,87:7,87:18","dtypep":"(MC)"} ],"assertTypesp": [],"directiveTypesp": []}, - {"type":"ASSERT","name":"","addr":"(AI)","loc":"d,88:7,88:13","type":"[SIMPLE_IMMEDIATE]", + {"type":"ASSERT","name":"","addr":"(AI)","loc":"e,88:7,88:13","type":"[SIMPLE_IMMEDIATE]", "propp": [ - {"type":"CONST","name":"?32?sh0","addr":"(BI)","loc":"d,88:14,88:15","dtypep":"(L)"} + {"type":"CONST","name":"?32?sh0","addr":"(BI)","loc":"e,88:14,88:15","dtypep":"(L)"} ],"sentreep": [],"failsp": [],"passsp": []}, - {"type":"ASSERTCTL","name":"","addr":"(CI)","loc":"d,89:7,89:16","ctlType":"$asserton", + {"type":"ASSERTCTL","name":"","addr":"(CI)","loc":"e,89:7,89:16","ctlType":"$asserton", "controlTypep": [ - {"type":"CONST","name":"32'h3","addr":"(DI)","loc":"d,89:7,89:16","dtypep":"(MC)"} + {"type":"CONST","name":"32'h3","addr":"(DI)","loc":"e,89:7,89:16","dtypep":"(MC)"} ],"assertTypesp": [],"directiveTypesp": []}, - {"type":"ASSERTCTL","name":"","addr":"(EI)","loc":"d,90:7,90:21","ctlType":"", + {"type":"ASSERTCTL","name":"","addr":"(EI)","loc":"e,90:7,90:21","ctlType":"", "controlTypep": [ - {"type":"CONST","name":"?32?sh3","addr":"(FI)","loc":"d,90:22,90:23","dtypep":"(QD)"} + {"type":"CONST","name":"?32?sh3","addr":"(FI)","loc":"e,90:22,90:23","dtypep":"(QD)"} ], "assertTypesp": [ - {"type":"CONST","name":"?32?sh8","addr":"(GI)","loc":"d,90:25,90:26","dtypep":"(JF)"} + {"type":"CONST","name":"?32?sh8","addr":"(GI)","loc":"e,90:25,90:26","dtypep":"(JF)"} ],"directiveTypesp": []} ]} ]} @@ -519,24 +519,24 @@ "miscsp": [ {"type":"TYPETABLE","name":"","addr":"(C)","loc":"a,0:0,0:0","constraintRefp":"UNLINKED","emptyQueuep":"UNLINKED","queueIndexp":"UNLINKED","streamp":"UNLINKED","voidp":"(HI)", "typesp": [ - {"type":"BASICDTYPE","name":"integer","addr":"(II)","loc":"c,31:27,31:28","dtypep":"(II)","keyword":"integer","range":"31:0","generic":true,"rangep": []}, - {"type":"BASICDTYPE","name":"logic","addr":"(L)","loc":"c,33:32,33:33","dtypep":"(L)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, - {"type":"BASICDTYPE","name":"logic","addr":"(UE)","loc":"c,50:22,50:24","dtypep":"(UE)","keyword":"logic","generic":true,"rangep": []}, - {"type":"VOIDDTYPE","name":"","addr":"(HI)","loc":"c,51:21,51:30","dtypep":"(HI)","generic":false}, - {"type":"BASICDTYPE","name":"logic","addr":"(QD)","loc":"c,125:22,125:23","dtypep":"(QD)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, - {"type":"BASICDTYPE","name":"logic","addr":"(JI)","loc":"c,127:22,127:23","dtypep":"(JI)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, - {"type":"BASICDTYPE","name":"logic","addr":"(KI)","loc":"c,162:17,162:56","dtypep":"(KI)","keyword":"logic","range":"295:0","generic":true,"rangep": []}, - {"type":"BASICDTYPE","name":"string","addr":"(BG)","loc":"c,162:10,162:16","dtypep":"(BG)","keyword":"string","generic":true,"rangep": []}, - {"type":"BASICDTYPE","name":"logic","addr":"(Q)","loc":"d,14:9,14:11","dtypep":"(Q)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, - {"type":"BASICDTYPE","name":"logic","addr":"(BB)","loc":"d,18:10,18:12","dtypep":"(BB)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, - {"type":"BASICDTYPE","name":"logic","addr":"(MC)","loc":"d,33:26,33:31","dtypep":"(MC)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, - {"type":"BASICDTYPE","name":"logic","addr":"(JC)","loc":"d,33:25,33:26","dtypep":"(JC)","keyword":"logic","generic":true,"rangep": []}, - {"type":"BASICDTYPE","name":"logic","addr":"(AF)","loc":"d,45:17,45:38","dtypep":"(AF)","keyword":"logic","range":"63:0","generic":true,"rangep": []}, - {"type":"BASICDTYPE","name":"logic","addr":"(JF)","loc":"d,48:22,48:24","dtypep":"(JF)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, - {"type":"BASICDTYPE","name":"logic","addr":"(SF)","loc":"d,51:22,51:24","dtypep":"(SF)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, - {"type":"BASICDTYPE","name":"logic","addr":"(DG)","loc":"d,54:17,54:49","dtypep":"(DG)","keyword":"logic","range":"231:0","generic":true,"rangep": []}, - {"type":"BASICDTYPE","name":"QData","addr":"(FG)","loc":"d,54:51,54:56","dtypep":"(FG)","keyword":"QData","range":"63:0","generic":true,"rangep": []}, - {"type":"BASICDTYPE","name":"logic","addr":"(WG)","loc":"d,59:17,59:41","dtypep":"(WG)","keyword":"logic","range":"167:0","generic":true,"rangep": []} + {"type":"BASICDTYPE","name":"integer","addr":"(II)","loc":"d,34:27,34:28","dtypep":"(II)","keyword":"integer","range":"31:0","generic":true,"rangep": []}, + {"type":"BASICDTYPE","name":"logic","addr":"(L)","loc":"d,36:32,36:33","dtypep":"(L)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, + {"type":"BASICDTYPE","name":"logic","addr":"(UE)","loc":"d,53:22,53:24","dtypep":"(UE)","keyword":"logic","generic":true,"rangep": []}, + {"type":"VOIDDTYPE","name":"","addr":"(HI)","loc":"d,54:21,54:30","dtypep":"(HI)","generic":false}, + {"type":"BASICDTYPE","name":"logic","addr":"(QD)","loc":"d,128:22,128:23","dtypep":"(QD)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, + {"type":"BASICDTYPE","name":"logic","addr":"(JI)","loc":"d,130:22,130:23","dtypep":"(JI)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, + {"type":"BASICDTYPE","name":"logic","addr":"(KI)","loc":"d,165:17,165:56","dtypep":"(KI)","keyword":"logic","range":"295:0","generic":true,"rangep": []}, + {"type":"BASICDTYPE","name":"string","addr":"(BG)","loc":"d,165:10,165:16","dtypep":"(BG)","keyword":"string","generic":true,"rangep": []}, + {"type":"BASICDTYPE","name":"logic","addr":"(Q)","loc":"e,14:9,14:11","dtypep":"(Q)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, + {"type":"BASICDTYPE","name":"logic","addr":"(BB)","loc":"e,18:10,18:12","dtypep":"(BB)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, + {"type":"BASICDTYPE","name":"logic","addr":"(MC)","loc":"e,33:26,33:31","dtypep":"(MC)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, + {"type":"BASICDTYPE","name":"logic","addr":"(JC)","loc":"e,33:25,33:26","dtypep":"(JC)","keyword":"logic","generic":true,"rangep": []}, + {"type":"BASICDTYPE","name":"logic","addr":"(AF)","loc":"e,45:17,45:38","dtypep":"(AF)","keyword":"logic","range":"63:0","generic":true,"rangep": []}, + {"type":"BASICDTYPE","name":"logic","addr":"(JF)","loc":"e,48:22,48:24","dtypep":"(JF)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, + {"type":"BASICDTYPE","name":"logic","addr":"(SF)","loc":"e,51:22,51:24","dtypep":"(SF)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, + {"type":"BASICDTYPE","name":"logic","addr":"(DG)","loc":"e,54:17,54:49","dtypep":"(DG)","keyword":"logic","range":"231:0","generic":true,"rangep": []}, + {"type":"BASICDTYPE","name":"QData","addr":"(FG)","loc":"e,54:51,54:56","dtypep":"(FG)","keyword":"QData","range":"63:0","generic":true,"rangep": []}, + {"type":"BASICDTYPE","name":"logic","addr":"(WG)","loc":"e,59:17,59:41","dtypep":"(WG)","keyword":"logic","range":"167:0","generic":true,"rangep": []} ]}, {"type":"CONSTPOOL","name":"","addr":"(D)","loc":"a,0:0,0:0", "modulep": [ diff --git a/test_regress/t/t_dump_json.py b/test_regress/t/t_dump_json.py index d0cc13c96..71ce0e5d0 100755 --- a/test_regress/t/t_dump_json.py +++ b/test_regress/t/t_dump_json.py @@ -14,7 +14,7 @@ test.top_filename = "t/t_dump.v" test.lint(v_flags=["--dump-tree-json --no-json-edit-nums"]) -test.files_identical(test.obj_dir + "/Vt_dump_json_001_cells.tree.json", test.golden_filename, +test.files_identical(test.obj_dir + "/Vt_dump_json_002_cellsort.tree.json", test.golden_filename, 'logfile') test.passes() diff --git a/test_regress/t/t_duplicated_gen_blocks_bad.out b/test_regress/t/t_duplicated_gen_blocks_bad.out new file mode 100644 index 000000000..5d14ab424 --- /dev/null +++ b/test_regress/t/t_duplicated_gen_blocks_bad.out @@ -0,0 +1,15 @@ +%Error: t/t_duplicated_gen_blocks_bad.v:11:12: Duplicate declaration of block: 'block' + : ... note: In instance 't' + 11 | begin : block + | ^~~~~ + t/t_duplicated_gen_blocks_bad.v:9:12: ... Location of original declaration + 9 | begin : block + | ^~~~~ +%Error: t/t_duplicated_gen_blocks_bad.v:15:23: Duplicate declaration of block: 'block1' + : ... note: In instance 't' + 15 | if (X > 1) begin : block1 + | ^~~~~~ + t/t_duplicated_gen_blocks_bad.v:13:23: ... Location of original declaration + 13 | if (X > 0) begin : block1 + | ^~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_pkg_identifier_bad.py b/test_regress/t/t_duplicated_gen_blocks_bad.py similarity index 100% rename from test_regress/t/t_pkg_identifier_bad.py rename to test_regress/t/t_duplicated_gen_blocks_bad.py diff --git a/test_regress/t/t_duplicated_gen_blocks_bad.v b/test_regress/t/t_duplicated_gen_blocks_bad.v new file mode 100644 index 000000000..43f7742a9 --- /dev/null +++ b/test_regress/t/t_duplicated_gen_blocks_bad.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, 2024 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + parameter X = 2; + begin : block + end + begin : block + end + if (X > 0) begin : block1 + end + if (X > 1) begin : block1 + end +endmodule diff --git a/test_regress/t/t_emit_accessors.py b/test_regress/t/t_emit_accessors.py index a85bb33eb..6bb128038 100755 --- a/test_regress/t/t_emit_accessors.py +++ b/test_regress/t/t_emit_accessors.py @@ -13,4 +13,6 @@ test.scenarios('vlt') test.compile(make_main=False, verilator_flags2=["--emit-accessors", "--exe", test.pli_filename]) +test.execute() + test.passes() diff --git a/test_regress/t/t_enum_base_bad.out b/test_regress/t/t_enum_base_bad.out new file mode 100644 index 000000000..74839d10a --- /dev/null +++ b/test_regress/t/t_enum_base_bad.out @@ -0,0 +1,5 @@ +%Error: t/t_enum_base_bad.v:13:12: Enum type must be an integer atom or vector type (IEEE 1800-2023 6.19) + : ... note: In instance 't' + 13 | typedef enum s_t { + | ^~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_enum_base_bad.py b/test_regress/t/t_enum_base_bad.py new file mode 100755 index 000000000..31228c9a7 --- /dev/null +++ b/test_regress/t/t_enum_base_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_enum_base_bad.v b/test_regress/t/t_enum_base_bad.v new file mode 100644 index 000000000..2647b47e8 --- /dev/null +++ b/test_regress/t/t_enum_base_bad.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, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(/*AUTOARG*/); + + typedef struct { + int a; + } s_t; + + typedef enum s_t { + EN_ZERO } bad_t; + + typedef int int_t; + + typedef enum int_t { EN_ONE = 1 } ok1_t; + + s_t s; + int_t i; + +endmodule diff --git a/test_regress/t/t_eq_wild.py b/test_regress/t/t_eq_wild.py new file mode 100755 index 000000000..d4f986441 --- /dev/null +++ b/test_regress/t/t_eq_wild.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_eq_wild.v b/test_regress/t/t_eq_wild.v new file mode 100644 index 000000000..7777eb6a3 --- /dev/null +++ b/test_regress/t/t_eq_wild.v @@ -0,0 +1,21 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +function bit get_1_or_0(bit get_1); + return get_1 ? 1'b1 : 1'b0; +endfunction + +module t (/*AUTOARG*/); + + initial begin + if (get_1_or_0(0) ==? get_1_or_0(1)) $stop; + if (!(get_1_or_0(0) !=? get_1_or_0(1))) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_eq_wild_unsup.out b/test_regress/t/t_eq_wild_unsup.out new file mode 100644 index 000000000..94c1a1f65 --- /dev/null +++ b/test_regress/t/t_eq_wild_unsup.out @@ -0,0 +1,6 @@ +%Error-UNSUPPORTED: t/t_eq_wild_unsup.v:13:13: Unsupported: RHS of ==? or !=? is fourstate but not a constant + : ... note: In instance 't' + 13 | if (1 ==? get_x_or_0(0)) $stop; + | ^~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error: Exiting due to diff --git a/test_regress/t/t_eq_wild_unsup.py b/test_regress/t/t_eq_wild_unsup.py new file mode 100755 index 000000000..e33e10acf --- /dev/null +++ b/test_regress/t/t_eq_wild_unsup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_eq_wild_unsup.v b/test_regress/t/t_eq_wild_unsup.v new file mode 100644 index 000000000..9e7f8b7c6 --- /dev/null +++ b/test_regress/t/t_eq_wild_unsup.v @@ -0,0 +1,19 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +function logic get_x_or_0(logic get_x); + return get_x ? 1'bx : 1'b0; +endfunction + +module t; + initial begin + if (1 ==? get_x_or_0(0)) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_event_class_fire.out b/test_regress/t/t_event_class_fire.out new file mode 100644 index 000000000..5cd5a3d51 --- /dev/null +++ b/test_regress/t/t_event_class_fire.out @@ -0,0 +1,5 @@ +%Error: Internal Error: t/t_event_class_fire.v:10:7: ../V3Delayed.cpp:#: No active to handle FireEvent + : ... note: In instance '$unit::Cls' + 10 | ->> e; + | ^~~ + ... See the manual at https://verilator.org/verilator_doc.html for more assistance. diff --git a/test_regress/t/t_event_class_fire.py b/test_regress/t/t_event_class_fire.py new file mode 100755 index 000000000..9de681711 --- /dev/null +++ b/test_regress/t/t_event_class_fire.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +# Issue #5597 makes this fail +test.compile(fails=test.vlt_all, + expect_filename=test.golden_filename, + verilator_flags2=['--timing']) + +#test.execute() + +test.passes() diff --git a/test_regress/t/t_event_class_fire.v b/test_regress/t/t_event_class_fire.v new file mode 100644 index 000000000..325fbafc0 --- /dev/null +++ b/test_regress/t/t_event_class_fire.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, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Cls; + event e; + task trig_e(); + ->> e; + endtask +endclass + +module top(); + event e; + initial begin + Cls c; + c = new; + c.trig_e(); + wait(e.triggered); + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_f_bad.out b/test_regress/t/t_flag_f_bad.out similarity index 100% rename from test_regress/t/t_f_bad.out rename to test_regress/t/t_flag_f_bad.out diff --git a/test_regress/t/t_f_bad.py b/test_regress/t/t_flag_f_bad.py similarity index 100% rename from test_regress/t/t_f_bad.py rename to test_regress/t/t_flag_f_bad.py diff --git a/test_regress/t/t_flag_libcreate_bad.out b/test_regress/t/t_flag_libcreate_bad.out new file mode 100644 index 000000000..c4912f7c5 --- /dev/null +++ b/test_regress/t/t_flag_libcreate_bad.out @@ -0,0 +1,2 @@ +%Error: --lib-create argument must be a legal C++ identifier: 'bad/name' +%Error: Exiting due to diff --git a/test_regress/t/t_flag_libcreate_bad.py b/test_regress/t/t_flag_libcreate_bad.py new file mode 100755 index 000000000..8923eb5f0 --- /dev/null +++ b/test_regress/t/t_flag_libcreate_bad.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') +test.top_filename = 't/t_EXAMPLE.v' # Anything + +test.lint(verilator_flags2=["--lib-create bad/name"], + fails=True, + expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_flag_modprefix_bad.out b/test_regress/t/t_flag_modprefix_bad.out new file mode 100644 index 000000000..e20cabf72 --- /dev/null +++ b/test_regress/t/t_flag_modprefix_bad.out @@ -0,0 +1,2 @@ +%Error: --mod-prefix argument must be a legal C++ identifier: 'bad/name' +%Error: Exiting due to diff --git a/test_regress/t/t_flag_modprefix_bad.py b/test_regress/t/t_flag_modprefix_bad.py new file mode 100755 index 000000000..7d78e05da --- /dev/null +++ b/test_regress/t/t_flag_modprefix_bad.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') +test.top_filename = 't/t_EXAMPLE.v' # Anything + +test.lint(verilator_flags2=["--mod-prefix bad/name"], + fails=True, + expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_flag_prefix_bad.out b/test_regress/t/t_flag_prefix_bad.out new file mode 100644 index 000000000..d87a75861 --- /dev/null +++ b/test_regress/t/t_flag_prefix_bad.out @@ -0,0 +1,2 @@ +%Error: --prefix argument must be a legal C++ identifier: 'bad/name' +%Error: Exiting due to diff --git a/test_regress/t/t_flag_prefix_bad.py b/test_regress/t/t_flag_prefix_bad.py new file mode 100755 index 000000000..70b21989f --- /dev/null +++ b/test_regress/t/t_flag_prefix_bad.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') +test.top_filename = 't/t_EXAMPLE.v' # Anything + +test.lint(verilator_flags2=["--prefix bad/name"], fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_force_mid.cpp b/test_regress/t/t_force_mid.cpp index 5afb7e5a3..ca91e6179 100644 --- a/test_regress/t/t_force_mid.cpp +++ b/test_regress/t/t_force_mid.cpp @@ -10,10 +10,12 @@ // OS header #include "verilatedos.h" // Generated header -#include "Vt_force_mid.h" +#include VM_PREFIX_INCLUDE // General headers #include "verilated.h" -std::unique_ptr topp; + +std::unique_ptr topp; + int main(int argc, char** argv) { uint64_t sim_time = 1100; const std::unique_ptr contextp{new VerilatedContext}; diff --git a/test_regress/t/t_foreach_array.v b/test_regress/t/t_foreach_array.v index 7b4a8eca6..2f4297c14 100755 --- a/test_regress/t/t_foreach_array.v +++ b/test_regress/t/t_foreach_array.v @@ -5,19 +5,30 @@ // SPDX-License-Identifier: CC0-1.0 module t_foreach_array; - + // Define various structures to test foreach behavior int dyn_arr[][]; int queue[$][$]; int unpacked_arr [3:1][9:8]; int associative_array_3d[string][string][string]; - int count_que; - int exp_count_que; - int count_dyn; - int exp_count_dyn; - int count_unp; - int exp_count_unp; + int queue_unp[$][3]; // Outer dynamic queue with fixed-size inner arrays + int unp_queue[3][$]; // Fixed-size outer array with dynamic inner queues + int dyn_queue[][]; // Fully dynamic 2D array + int queue_dyn[$][]; // Outer dynamic queue with dynamic inner queues + int dyn_unp[][3]; // Dynamic outer array with fixed-size inner arrays + int unp_dyn[3][]; // Fixed-size outer array with dynamic inner arrays + + // Define counter for various structures of array + int count_que, exp_count_que; + int count_dyn, exp_count_dyn; + int count_unp, exp_count_unp; int count_assoc; + int count_queue_unp, exp_count_queue_unp; + int count_unp_queue, exp_count_unp_queue; + int count_dyn_queue, exp_count_dyn_queue; + int count_queue_dyn, exp_count_queue_dyn; + int count_dyn_unp, exp_count_dyn_unp; + int count_unp_dyn, exp_count_unp_dyn; string k1, k2, k3; @@ -35,57 +46,77 @@ module t_foreach_array; associative_array_3d["key2"]["subkey1"]["subsubkey2"] = 8; associative_array_3d["key2"]["subkey3"]["subsubkey1"] = 9; + queue_unp = '{'{1, 2, 3}, '{4, 5, 6}, '{7, 8, 9}}; + unp_queue[0] = '{10, 11}; + unp_queue[1] = '{12, 13, 14}; + unp_queue[2] = '{15}; + dyn_queue = '{'{16, 17}, '{18, 19, 20}}; + queue_dyn = '{'{21, 22}, '{23, 24, 25}}; + dyn_unp = '{'{26, 27, 28}, '{29, 30, 31}}; + unp_dyn[0] = '{32, 33}; + unp_dyn[1] = '{34, 35, 36}; + unp_dyn[2] = '{37}; + + // Perform foreach loop counting and expected value calculation count_que = 0; - - foreach(queue[i, j]) begin - count_que++; - end - + foreach(queue[i, j]) count_que++; exp_count_que = 0; - foreach(queue[i]) begin - foreach(queue[i][j]) begin - exp_count_que++; - end - end + foreach(queue[i]) foreach(queue[i][j]) exp_count_que++; count_dyn = 0; - - foreach(dyn_arr[i, j]) begin - count_dyn++; - end - + foreach(dyn_arr[i, j]) count_dyn++; exp_count_dyn = 0; - - foreach(dyn_arr[i]) begin - foreach(dyn_arr[i][j]) begin - exp_count_dyn++; - end - end + foreach(dyn_arr[i]) foreach(dyn_arr[i][j]) exp_count_dyn++; count_unp = 0; - - foreach(unpacked_arr[i, j]) begin - count_unp++; - end - + foreach(unpacked_arr[i, j]) count_unp++; exp_count_unp = 0; - - foreach(unpacked_arr[i]) begin - foreach(unpacked_arr[i][j]) begin - exp_count_unp++; - end - end + foreach(unpacked_arr[i]) foreach(unpacked_arr[i][j]) exp_count_unp++; count_assoc = 0; + foreach(associative_array_3d[k1, k2, k3]) count_assoc++; - foreach(associative_array_3d[k1, k2, k3]) begin - count_assoc++; - end + count_queue_unp = 0; + foreach (queue_unp[i, j]) count_queue_unp++; + exp_count_queue_unp = 0; + foreach (queue_unp[i]) foreach (queue_unp[i][j]) exp_count_queue_unp++; + count_unp_queue = 0; + foreach (unp_queue[i, j]) count_unp_queue++; + exp_count_unp_queue = 0; + foreach (unp_queue[i]) foreach (unp_queue[i][j]) exp_count_unp_queue++; + + count_dyn_queue = 0; + foreach (dyn_queue[i, j]) count_dyn_queue++; + exp_count_dyn_queue = 0; + foreach (dyn_queue[i]) foreach (dyn_queue[i][j]) exp_count_dyn_queue++; + + count_queue_dyn = 0; + foreach (queue_dyn[i, j]) count_queue_dyn++; + exp_count_queue_dyn = 0; + foreach (queue_dyn[i]) foreach (queue_dyn[i][j]) exp_count_queue_dyn++; + + count_dyn_unp = 0; + foreach (dyn_unp[i, j]) count_dyn_unp++; + exp_count_dyn_unp = 0; + foreach (dyn_unp[i]) foreach (dyn_unp[i][j]) exp_count_dyn_unp++; + + count_unp_dyn = 0; + foreach (unp_dyn[i, j]) count_unp_dyn++; + exp_count_unp_dyn = 0; + foreach (unp_dyn[i]) foreach (unp_dyn[i][j]) exp_count_unp_dyn++; + + // Verification checks if (count_que != 6 || count_que != exp_count_que) $stop; if (count_dyn != 12 || count_dyn != exp_count_dyn) $stop; if (count_unp != 6 || count_unp != exp_count_unp) $stop; if (count_assoc != 9) $stop; + if (count_queue_unp != exp_count_queue_unp) $stop; + if (count_unp_queue != exp_count_unp_queue) $stop; + if (count_dyn_queue != exp_count_dyn_queue) $stop; + if (count_queue_dyn != exp_count_queue_dyn) $stop; + if (count_dyn_unp != exp_count_dyn_unp) $stop; + if (count_unp_dyn != exp_count_unp_dyn) $stop; $write("*-* All Finished *-*\\n"); $finish; diff --git a/test_regress/t/t_func_dotted_inl0.py b/test_regress/t/t_func_dotted_inl0.py index ac6c72de4..1c461adb2 100755 --- a/test_regress/t/t_func_dotted_inl0.py +++ b/test_regress/t/t_func_dotted_inl0.py @@ -19,17 +19,17 @@ test.compile(v_flags2=['--no-json-edit-nums', '+define+ATTRIBUTES', '+define+NOU if test.vlt_all: test.file_grep( out_filename, - r'{"type":"MODULE","name":"ma",.*"loc":"e,84:[^"]*","origName":"ma",.*,"modPublic":true') + r'{"type":"MODULE","name":"ma",.*"loc":"\w,84:[^"]*","origName":"ma",.*,"modPublic":true') test.file_grep( out_filename, - r'{"type":"MODULE","name":"mb",.*"loc":"e,99:[^"]*","origName":"mb",.*"modPublic":true') + r'{"type":"MODULE","name":"mb",.*"loc":"\w,99:[^"]*","origName":"mb",.*"modPublic":true') test.file_grep( out_filename, - r'{"type":"MODULE","name":"mc","addr":"[^"]*","loc":"e,127:[^"]*","origName":"mc",.*"modPublic":true' + r'{"type":"MODULE","name":"mc","addr":"[^"]*","loc":"\w,127:[^"]*","origName":"mc",.*"modPublic":true' ) test.file_grep( out_filename, - r'{"type":"MODULE","name":"mc__PB1","addr":"[^"]*","loc":"e,127:[^"]*","origName":"mc",.*"modPublic":true' + r'{"type":"MODULE","name":"mc__PB1","addr":"[^"]*","loc":"\w,127:[^"]*","origName":"mc",.*"modPublic":true' ) test.execute() diff --git a/test_regress/t/t_func_dotted_inl0_vlt.py b/test_regress/t/t_func_dotted_inl0_vlt.py index dd12a7af4..eefa82526 100755 --- a/test_regress/t/t_func_dotted_inl0_vlt.py +++ b/test_regress/t/t_func_dotted_inl0_vlt.py @@ -19,16 +19,17 @@ test.compile(v_flags2=["--no-json-edit-nums", test.t_dir + "/t_func_dotted_inl0. if test.vlt_all: test.file_grep( out_filename, - r'{"type":"MODULE","name":"ma",.*"loc":"f,84:[^"]*",.*"origName":"ma",.*"modPublic":true') + r'{"type":"MODULE","name":"ma",.*"loc":"\w,84:[^"]*",.*"origName":"ma",.*"modPublic":true') test.file_grep( out_filename, - r'{"type":"MODULE","name":"mb",.*"loc":"f,99:[^"]*",.*"origName":"mb",.*"modPublic":true') + r'{"type":"MODULE","name":"mb",.*"loc":"\w,99:[^"]*",.*"origName":"mb",.*"modPublic":true') test.file_grep( out_filename, - r'{"type":"MODULE","name":"mc",.*"loc":"f,127:[^"]*",.*"origName":"mc",.*"modPublic":true') + r'{"type":"MODULE","name":"mc",.*"loc":"\w,127:[^"]*",.*"origName":"mc",.*"modPublic":true' + ) test.file_grep( out_filename, - r'{"type":"MODULE","name":"mc__PB1",.*"loc":"f,127:[^"]*",.*"origName":"mc",.*"modPublic":true' + r'{"type":"MODULE","name":"mc__PB1",.*"loc":"\w,127:[^"]*",.*"origName":"mc",.*"modPublic":true' ) test.execute() diff --git a/test_regress/t/t_func_dotted_inl2.py b/test_regress/t/t_func_dotted_inl2.py index 1ab47172d..f0180cc32 100755 --- a/test_regress/t/t_func_dotted_inl2.py +++ b/test_regress/t/t_func_dotted_inl2.py @@ -19,11 +19,11 @@ test.compile(v_flags2=["--no-json-edit-nums", '+define+ATTRIBUTES', '+define+USE if test.vlt_all: modps = test.file_grep( out_filename, - r'{"type":"MODULE","name":"mb","addr":"([^"]*)","loc":"e,99:[^"]*",.*"origName":"mb"') + r'{"type":"MODULE","name":"mb","addr":"([^"]*)","loc":"\w,99:[^"]*",.*"origName":"mb"') modp = modps[0][0] test.file_grep( out_filename, - r'{"type":"CELL","name":"t.ma0.mb0","addr":"[^"]*","loc":"e,87:[^"]*",.*"origName":"mb0",.*"modp":"([^"]*)"', + r'{"type":"CELL","name":"t.ma0.mb0","addr":"[^"]*","loc":"\w,87:[^"]*",.*"origName":"mb0",.*"modp":"([^"]*)"', modp) test.execute() diff --git a/test_regress/t/t_func_dotted_inl2_vlt.py b/test_regress/t/t_func_dotted_inl2_vlt.py index 76860999e..f572fb45b 100755 --- a/test_regress/t/t_func_dotted_inl2_vlt.py +++ b/test_regress/t/t_func_dotted_inl2_vlt.py @@ -18,11 +18,11 @@ test.compile(v_flags2=["--no-json-edit-nums", "t/t_func_dotted_inl2.vlt"]) if test.vlt_all: modps = test.file_grep( out_filename, - r'{"type":"MODULE","name":"mb","addr":"([^"]*)","loc":"f,99:[^"]*",.*"origName":"mb"') + r'{"type":"MODULE","name":"mb","addr":"([^"]*)","loc":"\w,99:[^"]*",.*"origName":"mb"') modp = modps[0][0] test.file_grep( out_filename, - r'{"type":"CELL","name":"t.ma0.mb0","addr":"[^"]*","loc":"f,87:[^"]*",.*"origName":"mb0",.*"modp":"([^"]*)"', + r'{"type":"CELL","name":"t.ma0.mb0","addr":"[^"]*","loc":"\w,87:[^"]*",.*"origName":"mb0",.*"modp":"([^"]*)"', modp) test.execute() diff --git a/test_regress/t/t_func_ref.v b/test_regress/t/t_func_ref.v index b650ecf2b..1559a5d82 100644 --- a/test_regress/t/t_func_ref.v +++ b/test_regress/t/t_func_ref.v @@ -24,6 +24,16 @@ module t (/*AUTOARG*/); int b; int arr[1]; MyInt mi; + + task update_inout(inout int flag, input bit upflag); + flag = upflag ? 1 + flag : flag; + endtask + task update_ref(ref int flag, input bit upflag); + flag = upflag ? 1 + flag : flag; + endtask + + int my_flag; + initial begin mi = new(1); b = get_val_set_5(mi.x); @@ -35,6 +45,15 @@ module t (/*AUTOARG*/); `checkh(arr[0], 5); `checkh(b, 10); + update_ref(my_flag, 1); + if (my_flag !== 1) $stop; + update_ref(my_flag, 0); + if (my_flag !== 1) $stop; + update_inout(my_flag, 1); + if (my_flag !== 2) $stop; + update_inout(my_flag, 0); + if (my_flag !== 2) $stop; + $write("*-* All Finished *-*\n"); $finish; end diff --git a/test_regress/t/t_func_ref_noinline.py b/test_regress/t/t_func_ref_noinline.py new file mode 100755 index 000000000..475f46f55 --- /dev/null +++ b/test_regress/t/t_func_ref_noinline.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') +test.top_filename = "t/t_func_ref.v" + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_gantt_hier.py b/test_regress/t/t_gantt_hier.py new file mode 100755 index 000000000..19d2e439c --- /dev/null +++ b/test_regress/t/t_gantt_hier.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +# Test for bin/verilator_gantt, + +import vltest_bootstrap + +test.scenarios('vlt_all') +test.top_filename = "t/t_gen_alw.v" # Any, as long as runs a few cycles + +test.compile( + v_flags2=["--prof-exec", "--hierarchical"], + # Checks below care about thread count, so use 2 (minimum reasonable) + threads=(2 if test.vltmt else 1)) + +test.execute(all_run_flags=[ + "+verilator+prof+exec+start+2", + " +verilator+prof+exec+window+2", + " +verilator+prof+exec+file+" + test.obj_dir + "/profile_exec.dat", + " +verilator+prof+vlt+file+" + test.obj_dir + "/profile.vlt"]) # yapf:disable + +# For now, verilator_gantt still reads from STDIN +# (probably it should take a file, gantt.dat like verilator_profcfunc) +# The profiling data still goes direct to the runtime's STDOUT +# (maybe that should go to a separate file - gantt.dat?) +test.run(cmd=[ + os.environ["VERILATOR_ROOT"] + "/bin/verilator_gantt", test.obj_dir + + "/profile_exec.dat", "--vcd " + test.obj_dir + "/profile_exec.vcd", "| tee " + test.obj_dir + + "/gantt.log" +]) + +if test.vltmt: + test.file_grep(test.obj_dir + "/gantt.log", r'Total threads += 2') + test.file_grep(test.obj_dir + "/gantt.log", r'Total mtasks += 8') + # Predicted thread utilization should be less than 100% + test.file_grep_not(test.obj_dir + "/gantt.log", r'Thread utilization =\s*\d\d\d+\.\d+%') +else: + test.file_grep(test.obj_dir + "/gantt.log", r'Total threads += 1') + test.file_grep(test.obj_dir + "/gantt.log", r'Total mtasks += 0') + +test.file_grep(test.obj_dir + "/gantt.log", r'\|\s+2\s+\|\s+2\.0+\s+\|\s+eval') + +# Diff to itself, just to check parsing +test.vcd_identical(test.obj_dir + "/profile_exec.vcd", test.obj_dir + "/profile_exec.vcd") + +test.passes() diff --git a/test_regress/t/t_gate_inline_wide_exclude_multiple.py b/test_regress/t/t_gate_inline_wide_exclude_multiple.py new file mode 100755 index 000000000..516288695 --- /dev/null +++ b/test_regress/t/t_gate_inline_wide_exclude_multiple.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.lint(verilator_flags2=['--stats', '--expand-limit 5']) + +test.file_grep(test.stats, r'Optimizations, Gate excluded wide expressions\s+(\d+)', 2) +test.file_grep(test.stats, r'Optimizations, Gate sigs deleted\s+(\d+)', 4) + +test.passes() diff --git a/test_regress/t/t_gate_inline_wide_exclude_multiple.v b/test_regress/t/t_gate_inline_wide_exclude_multiple.v new file mode 100644 index 000000000..5e2ae1a80 --- /dev/null +++ b/test_regress/t/t_gate_inline_wide_exclude_multiple.v @@ -0,0 +1,26 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +localparam N = 256; // Wider than expand limit. + +module t( + input wire [N-1:0] i, + output logic [N-1:0] o_multiple1, + output logic [N-1:0] o_multiple2, + output wire [N-1:0] o + ); + + // Exclude from inline wide expressions referenced multiple times. + wire [N-1:0] wide_multiple_assigns = N >> i; + wire [N-1:0] wide = N << i; + + for (genvar n = 0; n < N - 1; ++n) begin + assign o[n] = i[N-1-n] | wide[N-1-n]; + end + + assign o_multiple1 = wide_multiple_assigns | i + 1; + assign o_multiple2 = wide_multiple_assigns | i + 2; +endmodule diff --git a/test_regress/t/t_gate_inline_wide_noexclude_arraysel.py b/test_regress/t/t_gate_inline_wide_noexclude_arraysel.py new file mode 100755 index 000000000..16d0c0d48 --- /dev/null +++ b/test_regress/t/t_gate_inline_wide_noexclude_arraysel.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.lint(verilator_flags2=['--stats', '--expand-limit 5']) + +test.file_grep(test.stats, r'Optimizations, Gate excluded wide expressions\s+(\d+)', 0) +test.file_grep(test.stats, r'Optimizations, Gate sigs deleted\s+(\d+)', 1) + +test.passes() diff --git a/test_regress/t/t_gate_inline_wide_noexclude_arraysel.v b/test_regress/t/t_gate_inline_wide_noexclude_arraysel.v new file mode 100644 index 000000000..282929316 --- /dev/null +++ b/test_regress/t/t_gate_inline_wide_noexclude_arraysel.v @@ -0,0 +1,19 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +module t; + logic [255:0] arrd [0:0] = '{ 1 }; + logic [255:0] y0; + + // Do not exclude from inlining wide arraysels. + always_comb y0 = arrd[0]; + + always_comb begin + if (y0 != 1 && y0 != 0) begin + $stop; + end + end +endmodule diff --git a/test_regress/t/t_gate_inline_wide_noexclude_const.py b/test_regress/t/t_gate_inline_wide_noexclude_const.py new file mode 100755 index 000000000..00b053a42 --- /dev/null +++ b/test_regress/t/t_gate_inline_wide_noexclude_const.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.lint(verilator_flags2=['--stats', '--expand-limit 5']) + +test.file_grep(test.stats, r'Optimizations, Gate excluded wide expressions\s+(\d+)', 0) +test.file_grep(test.stats, r'Optimizations, Gate sigs deleted\s+(\d+)', 2) + +test.passes() diff --git a/test_regress/t/t_gate_inline_wide_noexclude_const.v b/test_regress/t/t_gate_inline_wide_noexclude_const.v new file mode 100644 index 000000000..d45648982 --- /dev/null +++ b/test_regress/t/t_gate_inline_wide_noexclude_const.v @@ -0,0 +1,19 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +module t; + logic [255:0] arrd = 256'b0; + logic [255:0] y0; + + // Do not exclude from inlining wide variables with const assignments. + always_comb y0 = 256'(arrd[0]); + + always_comb begin + if (y0 != 1 && y0 != 0) begin + $stop; + end + end +endmodule diff --git a/test_regress/t/t_gate_inline_wide_noexclude_other_scope.py b/test_regress/t/t_gate_inline_wide_noexclude_other_scope.py new file mode 100755 index 000000000..0226ac927 --- /dev/null +++ b/test_regress/t/t_gate_inline_wide_noexclude_other_scope.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.lint(verilator_flags2=['--stats', '--expand-limit 5']) + +test.file_grep(test.stats, r'Optimizations, Gate excluded wide expressions\s+(\d+)', 0) + +test.passes() diff --git a/test_regress/t/t_gate_inline_wide_noexclude_other_scope.v b/test_regress/t/t_gate_inline_wide_noexclude_other_scope.v new file mode 100644 index 000000000..2181f9504 --- /dev/null +++ b/test_regress/t/t_gate_inline_wide_noexclude_other_scope.v @@ -0,0 +1,26 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +localparam N = 256; // Wider than expand limit. + +module t( + input wire [N-1:0] i, + output wire [N-1:0] o + ); + + // Do not exclude from inlining wides referenced in different scope. + wire [N-1:0] wide = N ~^ i; + + sub sub(i, wide, o); +endmodule + +module sub(input wire [N-1:0] i, input wire [N-1:0] wide, output logic [N-1:0] o); + initial begin + for (integer n = 0; n < N ; ++n) begin + o[n] = i[N-1-n] | wide[N-1-n]; + end + end +endmodule diff --git a/test_regress/t/t_gate_inline_wide_noexclude_sel.py b/test_regress/t/t_gate_inline_wide_noexclude_sel.py new file mode 100755 index 000000000..28148d585 --- /dev/null +++ b/test_regress/t/t_gate_inline_wide_noexclude_sel.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.lint(verilator_flags2=['--stats', '--expand-limit 5']) + +test.file_grep(test.stats, r'Optimizations, Gate excluded wide expressions\s+(\d+)', 1) +test.file_grep(test.stats, r'Optimizations, Gate sigs deleted\s+(\d+)', 9) + +test.passes() diff --git a/test_regress/t/t_gate_inline_wide_noexclude_sel.v b/test_regress/t/t_gate_inline_wide_noexclude_sel.v new file mode 100644 index 000000000..931ca0d62 --- /dev/null +++ b/test_regress/t/t_gate_inline_wide_noexclude_sel.v @@ -0,0 +1,44 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +module t ( + output reg [1020:0] res1, + output reg [1020:0] res2, + output reg [1022:0] res3, + output reg [1022:0] res4 + ); + always_inline always_inline(res1, res2); + dont_inline dont_inline(res3, res4); +endmodule + +module always_inline( + output reg [1020:0] res1, + output reg [1020:0] res2 + ); + + wire [1023:0] a; + wire [478:0] b; + + assign b = a[510:32]; + assign res1 = {542'b0, b}; + assign res2 = {542'b1, b}; +endmodule + +// SEL does not have proper offset so we do not have guarantee that it will be +// emitted as '[' operator, thus we do not exclude it from inlining. +module dont_inline( + output reg [1022:0] res1, + output reg [1022:0] res2 + ); + + wire [1023:0] a; + wire [480:0] b; + + // LSB % 32 != 0 + assign b = a[510:30]; + assign res1 = {542'b0, b}; + assign res2 = {542'b1, b}; +endmodule diff --git a/test_regress/t/t_gate_inline_wide_noexclude_small_wide.py b/test_regress/t/t_gate_inline_wide_noexclude_small_wide.py new file mode 100755 index 000000000..0226ac927 --- /dev/null +++ b/test_regress/t/t_gate_inline_wide_noexclude_small_wide.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.lint(verilator_flags2=['--stats', '--expand-limit 5']) + +test.file_grep(test.stats, r'Optimizations, Gate excluded wide expressions\s+(\d+)', 0) + +test.passes() diff --git a/test_regress/t/t_gate_inline_wide_noexclude_small_wide.v b/test_regress/t/t_gate_inline_wide_noexclude_small_wide.v new file mode 100644 index 000000000..bbb3022a3 --- /dev/null +++ b/test_regress/t/t_gate_inline_wide_noexclude_small_wide.v @@ -0,0 +1,21 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +localparam N = 65; // Wide but narrower than expand limit + +module t( + input wire [N-1:0] i, + output wire [N-1:0] o + ); + + // Do not exclude from inlining wides small enough to be handled by + // V3Expand. + wire [65:0] wide_small = N << i * i / N; + + for (genvar n = 0; n < N; ++n) begin + assign o[n] = i[n] ^ wide_small[n]; + end +endmodule diff --git a/test_regress/t/t_gate_inline_wide_noexclude_varref.py b/test_regress/t/t_gate_inline_wide_noexclude_varref.py new file mode 100755 index 000000000..bab7603d6 --- /dev/null +++ b/test_regress/t/t_gate_inline_wide_noexclude_varref.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.lint(verilator_flags2=['--stats', '--expand-limit 5']) + +test.file_grep(test.stats, r'Optimizations, Gate excluded wide expressions\s+(\d+)', 0) +test.file_grep(test.stats, r'Optimizations, Gate sigs deleted\s+(\d+)', 3) + +test.passes() diff --git a/test_regress/t/t_gate_inline_wide_noexclude_varref.v b/test_regress/t/t_gate_inline_wide_noexclude_varref.v new file mode 100644 index 000000000..4b4b94d64 --- /dev/null +++ b/test_regress/t/t_gate_inline_wide_noexclude_varref.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, 2024 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +module t(input [255:0] clk); + // Do not exclude from inlining wide reference assignments. + mod1 mod1(clk); + mod2 mod2(clk); +endmodule + +module mod1(input [255:0] clk); +endmodule + +module mod2(input [255:0] clk); +endmodule diff --git a/test_regress/t/t_gen_alw.v b/test_regress/t/t_gen_alw.v index 21b953839..27b86e96b 100644 --- a/test_regress/t/t_gen_alw.v +++ b/test_regress/t/t_gen_alw.v @@ -59,7 +59,7 @@ endmodule module Test (/*AUTOARG*/ // Inputs clk, in - ); + ); /*verilator hier_block*/ input clk; input [9:0] in; diff --git a/test_regress/t/t_hier_block_import.py b/test_regress/t/t_hier_block_import.py new file mode 100755 index 000000000..d9142462d --- /dev/null +++ b/test_regress/t/t_hier_block_import.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you can +# redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt_all') + +# stats will be deleted but generation will be skipped if libs of hierarchical blocks exist. +test.clean_objs() + +test.setenv('TEST_ROOT', test.t_dir + "/t_hier_block_import") + +# 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 performance, but ok. + +test.compile(verilator_flags2=[ + '$TEST_ROOT/t_hier_block_import_def.vh', '-f $TEST_ROOT/t_hier_block_import_args.f', + '-I$TEST_ROOT' +], + threads=(6 if test.vltmt else 1)) + +test.execute() + +test.file_grep(test.obj_dir + "/VsubA/subA.sv", r'^module\s+(\S+)\s+', "subA") +test.file_grep(test.stats, r'HierBlock,\s+Hierarchical blocks\s+(\d+)', 2) + +test.passes() diff --git a/test_regress/t/t_hier_block_import.v b/test_regress/t/t_hier_block_import.v new file mode 100644 index 000000000..c2ad81e44 --- /dev/null +++ b/test_regress/t/t_hier_block_import.v @@ -0,0 +1,30 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2024 by Antmicro. This program is free software; you can +// redistribute it and/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(/*AUTOARG*/ + // inputs + clk +); + input clk; + bit [31:0] outA; + bit [31:0] outB; + + subA subA(.out(outA)); + subB subB(.out(outB)); + + always @(posedge clk) begin + if (outA == `VALUE_A && outB == `VALUE_B) begin + $write("*-* All Finished *-*\n"); + $finish; + end + else begin + $write("Mismatch\n"); + $stop; + end + end +endmodule diff --git a/test_regress/t/t_hier_block_import/t_hier_block_import.vh b/test_regress/t/t_hier_block_import/t_hier_block_import.vh new file mode 100644 index 000000000..d0cc5e74d --- /dev/null +++ b/test_regress/t/t_hier_block_import/t_hier_block_import.vh @@ -0,0 +1,13 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2024 by Wilson Snyder. This program is free software; you can +// redistribute it and/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 + +// No include guards to validate if included once. + +parameter param_t pt = '{ + PARAM_VALUE: `VALUE_A +} diff --git a/test_regress/t/t_hier_block_import/t_hier_block_import_args.f b/test_regress/t/t_hier_block_import/t_hier_block_import_args.f new file mode 100644 index 000000000..11c92e3ab --- /dev/null +++ b/test_regress/t/t_hier_block_import/t_hier_block_import_args.f @@ -0,0 +1,11 @@ +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 +--hierarchical +$TEST_ROOT/t_hier_block_import_subA.v +-v $TEST_ROOT/t_hier_block_import_subB.v +$TEST_ROOT/t_hier_block_import_subsub.v diff --git a/test_regress/t/t_hier_block_import/t_hier_block_import_def.vh b/test_regress/t/t_hier_block_import/t_hier_block_import_def.vh new file mode 100644 index 000000000..e2877ac06 --- /dev/null +++ b/test_regress/t/t_hier_block_import/t_hier_block_import_def.vh @@ -0,0 +1,16 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2024 by Wilson Snyder. This program is free software; you can +// redistribute it and/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 + +// No include guards to validate if included once. + +`define VALUE_A 32'h12345678 +`define VALUE_B 32'h87654321 + +typedef struct packed { + bit [31:0] PARAM_VALUE; +} param_t; diff --git a/test_regress/t/t_hier_block_import/t_hier_block_import_subA.v b/test_regress/t/t_hier_block_import/t_hier_block_import_subA.v new file mode 100644 index 000000000..770b57f67 --- /dev/null +++ b/test_regress/t/t_hier_block_import/t_hier_block_import_subA.v @@ -0,0 +1,11 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2024 by Antmicro. This program is free software; you can +// redistribute it and/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 subA (output bit [31:0] out); /*verilator hier_block*/ + subsub subsub(.out(out)); +endmodule diff --git a/test_regress/t/t_hier_block_import/t_hier_block_import_subB.v b/test_regress/t/t_hier_block_import/t_hier_block_import_subB.v new file mode 100644 index 000000000..3fb930bd8 --- /dev/null +++ b/test_regress/t/t_hier_block_import/t_hier_block_import_subB.v @@ -0,0 +1,12 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2024 by Antmicro. This program is free software; you can +// redistribute it and/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 + +// Note: no hier_block pragma here to validate partial hier_block design +module subB (output bit [31:0] out); + assign out = `VALUE_B; +endmodule diff --git a/test_regress/t/t_hier_block_import/t_hier_block_import_subsub.v b/test_regress/t/t_hier_block_import/t_hier_block_import_subsub.v new file mode 100644 index 000000000..13d6d4014 --- /dev/null +++ b/test_regress/t/t_hier_block_import/t_hier_block_import_subsub.v @@ -0,0 +1,15 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2024 by Antmicro. This program is free software; you can +// redistribute it and/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 subsub +#( + `include "t_hier_block_import.vh" +) +(output bit [31:0] out); /*verilator hier_block*/ + assign out = pt.PARAM_VALUE; +endmodule diff --git a/test_regress/t/t_hier_block_import_cmake.py b/test_regress/t/t_hier_block_import_cmake.py new file mode 100755 index 000000000..866eb3ff7 --- /dev/null +++ b/test_regress/t/t_hier_block_import_cmake.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you can +# redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt_all') +# CMake build executes from a different directory than the Make one. +test.top_filename = os.path.abspath("t/t_hier_block_import.v") + +# stats will be deleted but generation will be skipped if libs of hierarchical blocks exist. +test.clean_objs() + +test.setenv('TEST_ROOT', test.t_dir + "/t_hier_block_import") + +test.compile(verilator_make_cmake=True, + verilator_make_gmake=False, + verilator_flags2=[ + '$TEST_ROOT/t_hier_block_import_def.vh', + '-f $TEST_ROOT/t_hier_block_import_args.f', '-I$TEST_ROOT' + ], + threads=(6 if test.vltmt else 1)) + +test.execute() + +test.file_grep(test.obj_dir + "/VsubA/subA.sv", r'^module\s+(\S+)\s+', "subA") +test.file_grep(test.stats, r'HierBlock,\s+Hierarchical blocks\s+(\d+)', 2) + +test.passes() diff --git a/test_regress/t/t_inside_extend.py b/test_regress/t/t_inside_extend.py new file mode 100755 index 000000000..78d425f95 --- /dev/null +++ b/test_regress/t/t_inside_extend.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile(verilator_flags2=["-Wno-WIDTH"]) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_inside_extend.v b/test_regress/t/t_inside_extend.v new file mode 100644 index 000000000..e388cdb58 --- /dev/null +++ b/test_regress/t/t_inside_extend.v @@ -0,0 +1,21 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +typedef enum bit [4:0] {V0 = 1} my_enum; +class Cls; + my_enum sp = V0; +endclass + +module t (/*AUTOARG*/); + initial begin + Cls c = new; + int i = 0; + if (i inside {c.sp}) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_inside_queue_elem.py b/test_regress/t/t_inside_queue_elem.py new file mode 100755 index 000000000..d4f986441 --- /dev/null +++ b/test_regress/t/t_inside_queue_elem.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_inside_queue_elem.v b/test_regress/t/t_inside_queue_elem.v new file mode 100644 index 000000000..2854757bd --- /dev/null +++ b/test_regress/t/t_inside_queue_elem.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, 2024 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + + initial begin + int q[$] = {1, 2}; + if (!(1 inside {q[0], q[1]})) $stop; + if (3 inside {q[0], q[1]}) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_inst_param_comma_bad.out b/test_regress/t/t_inst_param_comma_bad.out index a272b2577..0f1ad9b1a 100644 --- a/test_regress/t/t_inst_param_comma_bad.out +++ b/test_regress/t/t_inst_param_comma_bad.out @@ -1,19 +1,19 @@ -%Error: t/t_inst_param_comma_bad.v:35:15: syntax error, unexpected ')', expecting TYPE-IDENTIFIER +%Error: t/t_inst_param_comma_bad.v:35:15: syntax error, unexpected ')', expecting IDENTIFIER-for-type 35 | M #(.P(13),) m1( | ^ -%Error: t/t_inst_param_comma_bad.v:40:11: syntax error, unexpected ')', expecting TYPE-IDENTIFIER +%Error: t/t_inst_param_comma_bad.v:40:11: syntax error, unexpected ')', expecting IDENTIFIER-for-type 40 | M #(14,) m2 ( | ^ -%Error: t/t_inst_param_comma_bad.v:45:11: syntax error, unexpected ')', expecting TYPE-IDENTIFIER +%Error: t/t_inst_param_comma_bad.v:45:11: syntax error, unexpected ')', expecting IDENTIFIER-for-type 45 | M #(14,) m3 ( | ^ -%Error: t/t_inst_param_comma_bad.v:50:15: syntax error, unexpected ')', expecting TYPE-IDENTIFIER +%Error: t/t_inst_param_comma_bad.v:50:15: syntax error, unexpected ')', expecting IDENTIFIER-for-type 50 | N #(.P(13),) n1( | ^ -%Error: t/t_inst_param_comma_bad.v:55:11: syntax error, unexpected ')', expecting TYPE-IDENTIFIER +%Error: t/t_inst_param_comma_bad.v:55:11: syntax error, unexpected ')', expecting IDENTIFIER-for-type 55 | N #(14,) n2 ( | ^ -%Error: t/t_inst_param_comma_bad.v:60:11: syntax error, unexpected ')', expecting TYPE-IDENTIFIER +%Error: t/t_inst_param_comma_bad.v:60:11: syntax error, unexpected ')', expecting IDENTIFIER-for-type 60 | N #(14,) n3 ( | ^ %Error: Exiting due to diff --git a/test_regress/t/t_inst_paren_bad.out b/test_regress/t/t_inst_paren_bad.out index e19bc13b5..b802de3e6 100644 --- a/test_regress/t/t_inst_paren_bad.out +++ b/test_regress/t/t_inst_paren_bad.out @@ -1,5 +1,15 @@ -%Error: t/t_inst_paren_bad.v:11:8: Instantiation 'sub_inst' requires parenthesis (IEEE 1800-2023 23.3.2) - : ... Suggest use 'sub_inst()' +%Error: t/t_inst_paren_bad.v:11:4: Non-interface used as an interface: 'sub' + : ... Perhaps intended an instantiation but are missing parenthesis (IEEE 1800-2023 23.3.2)? 11 | sub sub_inst; - | ^~~~~~~~ + | ^~~ +%Warning-MULTITOP: t/t_inst_paren_bad.v:10:8: Multiple top level modules + : ... Suggest see manual; fix the duplicates, or use --top-module to select top. + ... For warning description see https://verilator.org/warn/MULTITOP?v=latest + ... Use "/* verilator lint_off MULTITOP */" and lint_on around source to disable this message. + : ... Top module 'sub' + 7 | module sub; + | ^~~ + : ... Top module 't' + 10 | module t( ); + | ^ %Error: Exiting due to diff --git a/test_regress/t/t_inst_public.py b/test_regress/t/t_inst_public.py new file mode 100755 index 000000000..c4062aa79 --- /dev/null +++ b/test_regress/t/t_inst_public.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile(verilator_make_gmake=False) + +test.file_grep(test.obj_dir + "/" + test.vm_prefix + "_Pub.h", r'') +test.file_grep_not(test.obj_dir + "/" + test.vm_prefix + "__Syms.h", r'Dead') + +test.passes() diff --git a/test_regress/t/t_inst_public.v b/test_regress/t/t_inst_public.v new file mode 100644 index 000000000..4b30fab8f --- /dev/null +++ b/test_regress/t/t_inst_public.v @@ -0,0 +1,31 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + + Pub pub(); + + localparam ZERO = 0; + if (ZERO) Dead dead(); + + initial begin + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule + +module Pub; + + // verilator public_module + + // no signals here + +endmodule + +module Dead; + // verilator public_module +endmodule diff --git a/test_regress/t/t_inst_tree_inl0_pub0.py b/test_regress/t/t_inst_tree_inl0_pub0.py index 25514c89e..e55e72830 100755 --- a/test_regress/t/t_inst_tree_inl0_pub0.py +++ b/test_regress/t/t_inst_tree_inl0_pub0.py @@ -18,17 +18,17 @@ test.compile(v_flags2=["--no-json-edit-nums", test.t_dir + "/" + test.name + ".v if test.vlt_all: test.file_grep(out_filename, - r'{"type":"MODULE","name":"l1",.*"loc":"f,56:[^"]*",.*"origName":"l1"') + r'{"type":"MODULE","name":"l1",.*"loc":"\w,56:[^"]*",.*"origName":"l1"') test.file_grep(out_filename, - r'{"type":"MODULE","name":"l2",.*"loc":"f,62:[^"]*",.*"origName":"l2"') + r'{"type":"MODULE","name":"l2",.*"loc":"\w,62:[^"]*",.*"origName":"l2"') test.file_grep(out_filename, - r'{"type":"MODULE","name":"l3",.*"loc":"f,69:[^"]*",.*"origName":"l3"') + r'{"type":"MODULE","name":"l3",.*"loc":"\w,69:[^"]*",.*"origName":"l3"') test.file_grep(out_filename, - r'{"type":"MODULE","name":"l4",.*"loc":"f,76:[^"]*",.*"origName":"l4"') + r'{"type":"MODULE","name":"l4",.*"loc":"\w,76:[^"]*",.*"origName":"l4"') test.file_grep(out_filename, - r'{"type":"MODULE","name":"l5__P1",.*"loc":"f,83:[^"]*",.*"origName":"l5"') + r'{"type":"MODULE","name":"l5__P1",.*"loc":"\w,83:[^"]*",.*"origName":"l5"') test.file_grep(out_filename, - r'{"type":"MODULE","name":"l5__P2",.*"loc":"f,83:[^"]*",.*"origName":"l5"') + r'{"type":"MODULE","name":"l5__P2",.*"loc":"\w,83:[^"]*",.*"origName":"l5"') test.execute() test.file_grep(test.run_log_filename, r"\] (%m|.*t\.ps): Clocked") diff --git a/test_regress/t/t_inst_tree_inl1_pub0.py b/test_regress/t/t_inst_tree_inl1_pub0.py index c3ddf6de9..a22a7e648 100755 --- a/test_regress/t/t_inst_tree_inl1_pub0.py +++ b/test_regress/t/t_inst_tree_inl1_pub0.py @@ -21,15 +21,15 @@ test.compile(v_flags2=[ if test.vlt_all: test.file_grep( out_filename, - r'{"type":"VAR","name":"t.u.u0.u0.z1",.*"loc":"f,70:[^"]*",.*"origName":"z1",.*"dtypeName":"logic"' + r'{"type":"VAR","name":"t.u.u0.u0.z1",.*"loc":"\w,70:[^"]*",.*"origName":"z1",.*"dtypeName":"logic"' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"t.u.u0.u1.z1",.*"loc":"f,70:[^"]*",.*"origName":"z1",.*"dtypeName":"logic"' + r'{"type":"VAR","name":"t.u.u0.u1.z1",.*"loc":"\w,70:[^"]*",.*"origName":"z1",.*"dtypeName":"logic"' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"t.u.u1.u0.z0",.*"loc":"f,70:[^"]*",.*"origName":"z0",.*"dtypeName":"logic"' + r'{"type":"VAR","name":"t.u.u1.u0.z0",.*"loc":"\w,70:[^"]*",.*"origName":"z0",.*"dtypeName":"logic"' ) test.execute() diff --git a/test_regress/t/t_inst_tree_inl1_pub1.py b/test_regress/t/t_inst_tree_inl1_pub1.py index 0a61713b5..2a4f5c98b 100755 --- a/test_regress/t/t_inst_tree_inl1_pub1.py +++ b/test_regress/t/t_inst_tree_inl1_pub1.py @@ -22,15 +22,15 @@ test.compile(v_flags2=[ if test.vlt_all: test.file_grep( out_filename, - r'{"type":"VAR","name":"u.u0.u0.z0",.*"loc":"f,70:[^"]*",.*"origName":"z0",.*"isSigPublic":true,.*"dtypeName":"logic",.*"isSigUserRdPublic":true.*"isSigUserRWPublic":true' + r'{"type":"VAR","name":"u.u0.u0.z0",.*"loc":"\w,70:[^"]*",.*"origName":"z0",.*"isSigPublic":true,.*"dtypeName":"logic",.*"isSigUserRdPublic":true.*"isSigUserRWPublic":true' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"u.u0.u0.u0.u0.z1",.*"loc":"f,85:[^"]*",.*"origName":"z1",.*"isSigPublic":true,.*"dtypeName":"logic",.*"isSigUserRdPublic":true,.*"isSigUserRWPublic":true' + r'{"type":"VAR","name":"u.u0.u0.u0.u0.z1",.*"loc":"\w,85:[^"]*",.*"origName":"z1",.*"isSigPublic":true,.*"dtypeName":"logic",.*"isSigUserRdPublic":true,.*"isSigUserRWPublic":true' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"u.u0.u1.u0.u0.z",.*"loc":"f,83:[^"]*",.*"origName":"z",.*,"isSigPublic":true,.*dtypeName":"logic",.*"isSigUserRdPublic":true,.*"isSigUserRWPublic":true' + r'{"type":"VAR","name":"u.u0.u1.u0.u0.z",.*"loc":"\w,83:[^"]*",.*"origName":"z",.*,"isSigPublic":true,.*dtypeName":"logic",.*"isSigUserRdPublic":true,.*"isSigUserRWPublic":true' ) test.execute() diff --git a/test_regress/t/t_interface_and_struct_pattern.py b/test_regress/t/t_interface_and_struct_pattern.py new file mode 100755 index 000000000..d4f986441 --- /dev/null +++ b/test_regress/t/t_interface_and_struct_pattern.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_interface_and_struct_pattern.v b/test_regress/t/t_interface_and_struct_pattern.v new file mode 100644 index 000000000..2b75dca53 --- /dev/null +++ b/test_regress/t/t_interface_and_struct_pattern.v @@ -0,0 +1,59 @@ +// DESCRIPTION: Verilator: SystemVerilog interface test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2012 by Iztok Jeras. +// SPDX-License-Identifier: CC0-1.0 + +package Package_pkg; + typedef struct packed { + int bar; + int baz; + } pkg_struct_t; +endpackage + +interface intf + #(parameter type data_type = bit) + (input wire clk, + input wire rst); + data_type data; + modport source ( + input clk, rst, + output data + ); +endinterface + +module sub ( + intf.source bar, + input clk, + input rst); + + typedef struct packed { + int foo; + int baz; + } struct_t; + + intf #(.data_type(struct_t)) the_intf (.*); + + Package_pkg::pkg_struct_t output_bar = Package_pkg::pkg_struct_t'{ + bar: the_intf.data.foo, + baz: the_intf.data.baz + }; +endmodule + +module t(clk); + input clk; + logic rst; + + intf bar (.*); + sub the_sub ( + .bar(bar), + .clk, + .rst + ); + + // finish report + always @ (posedge clk) begin + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_interface_array_parameter_access.py b/test_regress/t/t_interface_array_parameter_access.py new file mode 100755 index 000000000..d4f986441 --- /dev/null +++ b/test_regress/t/t_interface_array_parameter_access.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_interface_array_parameter_access.v b/test_regress/t/t_interface_array_parameter_access.v new file mode 100644 index 000000000..33de01a6a --- /dev/null +++ b/test_regress/t/t_interface_array_parameter_access.v @@ -0,0 +1,39 @@ +// DESCRIPTION: Verilator: Get parameter from array of interfaces +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2024 by Todd Strader +// SPDX-License-Identifier: CC0-1.0 + +interface intf + #(parameter int FOO = 4) + (input wire clk, + input wire rst); + modport modp (input clk, rst); +endinterface + +module sub (intf.modp the_intf_port [4]); + localparam int intf_foo = the_intf_port[0].FOO; + + initial begin + if (intf_foo != 4) $stop; + end +endmodule + +module t ( + clk +); + logic rst; + input clk; + + intf the_intf [4] (.*); + + sub + the_sub ( + .the_intf_port (the_intf) + ); + + always @(posedge clk) begin + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_interface_colon_bad.out b/test_regress/t/t_interface_colon_bad.out new file mode 100644 index 000000000..f19261595 --- /dev/null +++ b/test_regress/t/t_interface_colon_bad.out @@ -0,0 +1,7 @@ +%Error: t/t_interface_colon_bad.v:14:7: Package/class for ':: reference' not found: 'iface' + 14 | iface::func(); + | ^~~~~ +%Error: t/t_interface_colon_bad.v:14:14: Can't find definition of task/function: 'func' + 14 | iface::func(); + | ^~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_interface_colon_bad.py b/test_regress/t/t_interface_colon_bad.py new file mode 100755 index 000000000..31228c9a7 --- /dev/null +++ b/test_regress/t/t_interface_colon_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_interface_colon_bad.v b/test_regress/t/t_interface_colon_bad.v new file mode 100644 index 000000000..904468bca --- /dev/null +++ b/test_regress/t/t_interface_colon_bad.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, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +interface iface; + function static func; + endfunction +endinterface + +module t; + initial begin + iface::func(); // BAD + $stop; + end +endmodule diff --git a/test_regress/t/t_interface_find.py b/test_regress/t/t_interface_find.py new file mode 100755 index 000000000..d4f986441 --- /dev/null +++ b/test_regress/t/t_interface_find.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_interface_find.v b/test_regress/t/t_interface_find.v new file mode 100644 index 000000000..6566a7381 --- /dev/null +++ b/test_regress/t/t_interface_find.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, 2013 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +// Auto-resolved by t_interface_find_ifc.v +// interface t_interface_find_ifc; + +module t (/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + integer cyc=1; + + t_interface_find_ifc itop(); + + sub c1 (.isub(itop), + .i_value(4'h4)); + + always @ (posedge clk) begin + cyc <= cyc + 1; + if (cyc==20) begin + if (c1.i_value != 4) $stop; // 'Normal' crossref just for comparison + if (itop.value != 4) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule + +module sub + ( + t_interface_find_ifc isub, + input logic [3:0] i_value + ); + + always @* begin + isub.value = i_value; + end +endmodule : sub diff --git a/test_regress/t/t_interface_find_ifc.v b/test_regress/t/t_interface_find_ifc.v new file mode 100644 index 000000000..2866d850b --- /dev/null +++ b/test_regress/t/t_interface_find_ifc.v @@ -0,0 +1,9 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2013 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +interface t_interface_find_ifc; + logic [3:0] value; +endinterface diff --git a/test_regress/t/t_interface_hidden.py b/test_regress/t/t_interface_hidden.py new file mode 100755 index 000000000..d4f986441 --- /dev/null +++ b/test_regress/t/t_interface_hidden.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_interface_hidden.v b/test_regress/t/t_interface_hidden.v new file mode 100644 index 000000000..04b460d92 --- /dev/null +++ b/test_regress/t/t_interface_hidden.v @@ -0,0 +1,76 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2013 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + integer cyc=1; + + ifc ifc(); // Cell name hides interface's name + assign ifc.ifi = 55; + + sub sub (.isub(ifc)); // Cell name hides module's name + + int om; + + mod_or_type mot (.*); + + hides_with_type hides_type(); + hides_with_decl hides_decl(); + + always @ (posedge clk) begin + cyc <= cyc + 1; + if (cyc == 20) begin + if (om != 22) $stop; + if (mot.LOCAL != 22) $stop; + if (ifc.ifo != 55) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule + +module sub + ( + ifc isub + ); + always @* begin + isub.ifo = isub.ifi; + end +endmodule + +module mod_or_type(output int om); + localparam LOCAL = 22; + initial om = 22; +endmodule + +module hides_with_type(); + typedef int ifc; // Hides interface + typedef int mod_or_type; // Hides module + + ifc /*=int*/ hides_ifc; + mod_or_type /*=int*/ hides_mod; + + initial hides_ifc = 33; + initial hides_mod = 44; +endmodule + +module hides_with_decl(); + int ifc; // Hides interface + int mod_or_type; // Hides module + + initial ifc = 66; + initial mod_or_type = 77; +endmodule + +interface ifc; + localparam LOCAL = 12; + int ifi; + int ifo; +endinterface diff --git a/test_regress/t/t_interface_notpublic.py b/test_regress/t/t_interface_notpublic.py new file mode 100755 index 000000000..d4f986441 --- /dev/null +++ b/test_regress/t/t_interface_notpublic.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_interface_notpublic.v b/test_regress/t/t_interface_notpublic.v new file mode 100644 index 000000000..7619519e8 --- /dev/null +++ b/test_regress/t/t_interface_notpublic.v @@ -0,0 +1,29 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2012 by Iztok Jeras. +// SPDX-License-Identifier: CC0-1.0 + +interface intf + (input wire clk, + input wire rst); + modport intf_modp (input clk, rst); +endinterface + +module sub + // verilator public_on + (intf.intf_modp intf_port); + + always @ (posedge intf_port.clk) begin + $write("*-* All Finished *-*\n"); + $finish; + end + // verilator public_off +endmodule + +module t(clk); + input clk /*verilator public*/ ; + logic rst; + intf the_intf (.clk, .rst); + sub the_sub (.intf_port (the_intf)); +endmodule diff --git a/test_regress/t/t_interface_paren_missing_bad.out b/test_regress/t/t_interface_paren_missing_bad.out index 70a167b83..a0b038347 100644 --- a/test_regress/t/t_interface_paren_missing_bad.out +++ b/test_regress/t/t_interface_paren_missing_bad.out @@ -1,5 +1,5 @@ -%Error: t/t_interface_paren_missing_bad.v:13:9: Instantiation 'intf_i' requires parenthesis (IEEE 1800-2023 23.3.2) - : ... Suggest use 'intf_i()' +%Error: t/t_interface_paren_missing_bad.v:13:9: Interface port declaration 'intf_i' doesn't have corresponding port + : ... Perhaps intended an interface instantiation but are missing parenthesis (IEEE 1800-2023 25.3)? 13 | intf intf_i; | ^~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_interface_paren_missing_bad.v b/test_regress/t/t_interface_paren_missing_bad.v index c1a9edae4..5a02d2ae1 100644 --- a/test_regress/t/t_interface_paren_missing_bad.v +++ b/test_regress/t/t_interface_paren_missing_bad.v @@ -1,11 +1,11 @@ // DESCRIPTION: Verilator: Verilog Test module // -// Interface instantiation without paranthesis -// // 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 instantiation without parenthesis + interface intf; endinterface diff --git a/test_regress/t/t_interface_wire_bad.out b/test_regress/t/t_interface_wire_bad.out new file mode 100644 index 000000000..c792bf9b6 --- /dev/null +++ b/test_regress/t/t_interface_wire_bad.out @@ -0,0 +1,5 @@ +%Error: t/t_interface_wire_bad.v:17:20: Operator ASSIGNW expected non-interface on Assign RHS but 'a__Viftop' is an interface. + : ... note: In instance 't' + 17 | wire wbad = sub.a; + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_interface_wire_bad.py b/test_regress/t/t_interface_wire_bad.py new file mode 100755 index 000000000..31228c9a7 --- /dev/null +++ b/test_regress/t/t_interface_wire_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_interface_wire_bad.v b/test_regress/t/t_interface_wire_bad.v new file mode 100644 index 000000000..d4401b6e1 --- /dev/null +++ b/test_regress/t/t_interface_wire_bad.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, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +interface Ifc; +endinterface + +module Sub; + Ifc a(); +endmodule + +module t; + Sub sub(); + // Issue #5649 + wire wbad = sub.a; +endmodule diff --git a/test_regress/t/t_interface_wire_bad_param.out b/test_regress/t/t_interface_wire_bad_param.out new file mode 100644 index 000000000..7aebb6752 --- /dev/null +++ b/test_regress/t/t_interface_wire_bad_param.out @@ -0,0 +1,5 @@ +%Error: Internal Error: t/t_interface_wire_bad_param.v:17:20: ../V3Broken.cpp:#: Broken link in node (or something without maybePointedTo): 'm_varp && !m_varp->brokeExists()' @ ./V3Ast__gen_impl.h:# + : ... note: In instance 't' + 17 | wire wbad = sub.a; + | ^ + ... See the manual at https://verilator.org/verilator_doc.html for more assistance. diff --git a/test_regress/t/t_interface_wire_bad_param.py b/test_regress/t/t_interface_wire_bad_param.py new file mode 100755 index 000000000..31228c9a7 --- /dev/null +++ b/test_regress/t/t_interface_wire_bad_param.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_interface_wire_bad_param.v b/test_regress/t/t_interface_wire_bad_param.v new file mode 100644 index 000000000..5399bbd9a --- /dev/null +++ b/test_regress/t/t_interface_wire_bad_param.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, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +interface Ifc; +endinterface + +module Sub #(parameter P); + Ifc a(); +endmodule + +module t; + Sub #(0) sub(); + // Issue #5649 + wire wbad = sub.a; +endmodule diff --git a/test_regress/t/t_json_only_debugcheck.out b/test_regress/t/t_json_only_debugcheck.out index 2cc666c9a..d8f2eeb9a 100644 --- a/test_regress/t/t_json_only_debugcheck.out +++ b/test_regress/t/t_json_only_debugcheck.out @@ -2,7 +2,7 @@ "modulesp": [ {"type":"MODULE","name":"$root","addr":"(I)","loc":"d,11:8,11:9","origName":"$root","level":1,"modPublic":true,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"clk","addr":"(J)","loc":"d,15:10,15:13","dtypep":"(K)","origName":"clk","isSc":false,"isPrimaryIO":true,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":true,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"clker","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"clk","addr":"(J)","loc":"d,15:10,15:13","dtypep":"(K)","origName":"clk","isSc":false,"isPrimaryIO":true,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":true,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"clker","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"t.e","addr":"(L)","loc":"d,24:9,24:10","dtypep":"(M)","origName":"e","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"VAR","dtypeName":"my_t","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"__Vtrigprevexpr___TOP__clk__0","addr":"(N)","loc":"d,11:8,11:9","dtypep":"(K)","origName":"__Vtrigprevexpr___TOP__clk__0","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"MODULETEMP","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"__VactContinue","addr":"(O)","loc":"d,11:8,11:9","dtypep":"(P)","origName":"__VactContinue","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":true,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"MODULETEMP","dtypeName":"bit","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, diff --git a/test_regress/t/t_json_only_first.out b/test_regress/t/t_json_only_first.out index 67f9fa721..4be43ef77 100644 --- a/test_regress/t/t_json_only_first.out +++ b/test_regress/t/t_json_only_first.out @@ -3,8 +3,8 @@ {"type":"MODULE","name":"t","addr":"(E)","loc":"d,7:8,7:9","origName":"t","level":2,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ {"type":"VAR","name":"q","addr":"(F)","loc":"d,15:22,15:23","dtypep":"(G)","origName":"q","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"WIRE","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"clk","addr":"(H)","loc":"d,13:10,13:13","dtypep":"(I)","origName":"clk","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"d","addr":"(J)","loc":"d,14:16,14:17","dtypep":"(G)","origName":"d","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"clk","addr":"(H)","loc":"d,13:10,13:13","dtypep":"(I)","origName":"clk","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"d","addr":"(J)","loc":"d,14:16,14:17","dtypep":"(G)","origName":"d","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"between","addr":"(K)","loc":"d,17:22,17:29","dtypep":"(G)","origName":"between","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"VAR","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"CELL","name":"cell1","addr":"(L)","loc":"d,20:4,20:9","origName":"cell1","recursive":false,"modp":"(M)", "pinsp": [ @@ -39,8 +39,8 @@ ],"activesp": []}, {"type":"MODULE","name":"mod2","addr":"(X)","loc":"d,46:8,46:12","origName":"mod2","level":3,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"clk","addr":"(FB)","loc":"d,48:10,48:13","dtypep":"(I)","origName":"clk","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"d","addr":"(Z)","loc":"d,49:16,49:17","dtypep":"(G)","origName":"d","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"clk","addr":"(FB)","loc":"d,48:10,48:13","dtypep":"(I)","origName":"clk","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"d","addr":"(Z)","loc":"d,49:16,49:17","dtypep":"(G)","origName":"d","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"q","addr":"(CB)","loc":"d,50:22,50:23","dtypep":"(G)","origName":"q","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"WIRE","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"ASSIGNW","name":"","addr":"(HB)","loc":"d,53:13,53:14","dtypep":"(G)", "rhsp": [ @@ -56,9 +56,9 @@ "valuep": [ {"type":"CONST","name":"32'sh4","addr":"(MB)","loc":"d,19:18,19:19","dtypep":"(LB)"} ],"attrsp": []}, - {"type":"VAR","name":"clk","addr":"(R)","loc":"d,34:24,34:27","dtypep":"(I)","origName":"clk","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"d","addr":"(U)","loc":"d,35:30,35:31","dtypep":"(G)","origName":"d","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"q","addr":"(O)","loc":"d,36:30,36:31","dtypep":"(G)","origName":"q","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"clk","addr":"(R)","loc":"d,34:24,34:27","dtypep":"(I)","origName":"clk","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"d","addr":"(U)","loc":"d,35:30,35:31","dtypep":"(G)","origName":"d","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"q","addr":"(O)","loc":"d,36:30,36:31","dtypep":"(G)","origName":"q","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"IGNORED","addr":"(NB)","loc":"d,39:15,39:22","dtypep":"(LB)","origName":"IGNORED","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"LPARAM","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":true,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], "valuep": [ {"type":"CONST","name":"32'sh1","addr":"(OB)","loc":"d,39:25,39:26","dtypep":"(LB)"} diff --git a/test_regress/t/t_json_only_flat.out b/test_regress/t/t_json_only_flat.out index d50bd17e5..7159c2b8e 100644 --- a/test_regress/t/t_json_only_flat.out +++ b/test_regress/t/t_json_only_flat.out @@ -3,25 +3,25 @@ {"type":"MODULE","name":"$root","addr":"(F)","loc":"d,7:8,7:9","origName":"$root","level":1,"modPublic":true,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ {"type":"VAR","name":"q","addr":"(G)","loc":"d,15:22,15:23","dtypep":"(H)","origName":"q","isSc":false,"isPrimaryIO":true,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"WIRE","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"clk","addr":"(I)","loc":"d,13:10,13:13","dtypep":"(J)","origName":"clk","isSc":false,"isPrimaryIO":true,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"clker","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"d","addr":"(K)","loc":"d,14:16,14:17","dtypep":"(H)","origName":"d","isSc":false,"isPrimaryIO":true,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"clk","addr":"(I)","loc":"d,13:10,13:13","dtypep":"(J)","origName":"clk","isSc":false,"isPrimaryIO":true,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"clker","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"d","addr":"(K)","loc":"d,14:16,14:17","dtypep":"(H)","origName":"d","isSc":false,"isPrimaryIO":true,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"t.q","addr":"(L)","loc":"d,15:22,15:23","dtypep":"(H)","origName":"q","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"WIRE","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.clk","addr":"(M)","loc":"d,13:10,13:13","dtypep":"(J)","origName":"clk","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.d","addr":"(N)","loc":"d,14:16,14:17","dtypep":"(H)","origName":"d","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.clk","addr":"(M)","loc":"d,13:10,13:13","dtypep":"(J)","origName":"clk","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.d","addr":"(N)","loc":"d,14:16,14:17","dtypep":"(H)","origName":"d","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"t.between","addr":"(O)","loc":"d,17:22,17:29","dtypep":"(H)","origName":"between","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"VAR","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"t.cell1.WIDTH","addr":"(P)","loc":"d,32:15,32:20","dtypep":"(Q)","origName":"WIDTH","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"GPARAM","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":true,"isParam":true,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], "valuep": [ {"type":"CONST","name":"32'sh4","addr":"(R)","loc":"d,19:18,19:19","dtypep":"(Q)"} ],"attrsp": []}, - {"type":"VAR","name":"t.cell1.clk","addr":"(S)","loc":"d,34:24,34:27","dtypep":"(J)","origName":"clk","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.cell1.d","addr":"(T)","loc":"d,35:30,35:31","dtypep":"(H)","origName":"d","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.cell1.q","addr":"(U)","loc":"d,36:30,36:31","dtypep":"(H)","origName":"q","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.cell1.clk","addr":"(S)","loc":"d,34:24,34:27","dtypep":"(J)","origName":"clk","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.cell1.d","addr":"(T)","loc":"d,35:30,35:31","dtypep":"(H)","origName":"d","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.cell1.q","addr":"(U)","loc":"d,36:30,36:31","dtypep":"(H)","origName":"q","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"t.cell1.IGNORED","addr":"(V)","loc":"d,39:15,39:22","dtypep":"(Q)","origName":"IGNORED","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"LPARAM","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":true,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [], "valuep": [ {"type":"CONST","name":"32'sh1","addr":"(W)","loc":"d,39:25,39:26","dtypep":"(Q)"} ],"attrsp": []}, - {"type":"VAR","name":"t.cell2.clk","addr":"(X)","loc":"d,48:10,48:13","dtypep":"(J)","origName":"clk","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"t.cell2.d","addr":"(Y)","loc":"d,49:16,49:17","dtypep":"(H)","origName":"d","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.cell2.clk","addr":"(X)","loc":"d,48:10,48:13","dtypep":"(J)","origName":"clk","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"t.cell2.d","addr":"(Y)","loc":"d,49:16,49:17","dtypep":"(H)","origName":"d","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"t.cell2.q","addr":"(Z)","loc":"d,50:22,50:23","dtypep":"(H)","origName":"q","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"WIRE","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"TOPSCOPE","name":"","addr":"(E)","loc":"d,7:8,7:9","senTreesp": [], "scopep": [ diff --git a/test_regress/t/t_json_only_flat_no_inline_mod.out b/test_regress/t/t_json_only_flat_no_inline_mod.out index 9740d57fb..1c177751a 100644 --- a/test_regress/t/t_json_only_flat_no_inline_mod.out +++ b/test_regress/t/t_json_only_flat_no_inline_mod.out @@ -2,9 +2,9 @@ "modulesp": [ {"type":"MODULE","name":"$root","addr":"(F)","loc":"d,11:8,11:11","origName":"$root","level":1,"modPublic":true,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"i_clk","addr":"(G)","loc":"d,11:24,11:29","dtypep":"(H)","origName":"i_clk","isSc":false,"isPrimaryIO":true,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"top.i_clk","addr":"(I)","loc":"d,11:24,11:29","dtypep":"(H)","origName":"i_clk","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"top.f.i_clk","addr":"(J)","loc":"d,7:24,7:29","dtypep":"(H)","origName":"i_clk","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"i_clk","addr":"(G)","loc":"d,11:24,11:29","dtypep":"(H)","origName":"i_clk","isSc":false,"isPrimaryIO":true,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"top.i_clk","addr":"(I)","loc":"d,11:24,11:29","dtypep":"(H)","origName":"i_clk","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"top.f.i_clk","addr":"(J)","loc":"d,7:24,7:29","dtypep":"(H)","origName":"i_clk","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"TOPSCOPE","name":"","addr":"(E)","loc":"d,11:8,11:11","senTreesp": [], "scopep": [ {"type":"SCOPE","name":"TOP","addr":"(K)","loc":"d,11:8,11:11","aboveScopep":"UNLINKED","aboveCellp":"UNLINKED","modp":"(F)", diff --git a/test_regress/t/t_json_only_flat_pub_mod.out b/test_regress/t/t_json_only_flat_pub_mod.out index 9740d57fb..1c177751a 100644 --- a/test_regress/t/t_json_only_flat_pub_mod.out +++ b/test_regress/t/t_json_only_flat_pub_mod.out @@ -2,9 +2,9 @@ "modulesp": [ {"type":"MODULE","name":"$root","addr":"(F)","loc":"d,11:8,11:11","origName":"$root","level":1,"modPublic":true,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"i_clk","addr":"(G)","loc":"d,11:24,11:29","dtypep":"(H)","origName":"i_clk","isSc":false,"isPrimaryIO":true,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"top.i_clk","addr":"(I)","loc":"d,11:24,11:29","dtypep":"(H)","origName":"i_clk","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"top.f.i_clk","addr":"(J)","loc":"d,7:24,7:29","dtypep":"(H)","origName":"i_clk","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"i_clk","addr":"(G)","loc":"d,11:24,11:29","dtypep":"(H)","origName":"i_clk","isSc":false,"isPrimaryIO":true,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"top.i_clk","addr":"(I)","loc":"d,11:24,11:29","dtypep":"(H)","origName":"i_clk","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"top.f.i_clk","addr":"(J)","loc":"d,7:24,7:29","dtypep":"(H)","origName":"i_clk","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"TOPSCOPE","name":"","addr":"(E)","loc":"d,11:8,11:11","senTreesp": [], "scopep": [ {"type":"SCOPE","name":"TOP","addr":"(K)","loc":"d,11:8,11:11","aboveScopep":"UNLINKED","aboveCellp":"UNLINKED","modp":"(F)", diff --git a/test_regress/t/t_json_only_flat_vlvbound.out b/test_regress/t/t_json_only_flat_vlvbound.out index eea5a88fa..9745e13a3 100644 --- a/test_regress/t/t_json_only_flat_vlvbound.out +++ b/test_regress/t/t_json_only_flat_vlvbound.out @@ -2,14 +2,14 @@ "modulesp": [ {"type":"MODULE","name":"$root","addr":"(F)","loc":"d,7:8,7:21","origName":"$root","level":1,"modPublic":true,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"i_a","addr":"(G)","loc":"d,9:25,9:28","dtypep":"(H)","origName":"i_a","isSc":false,"isPrimaryIO":true,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"i_b","addr":"(I)","loc":"d,10:25,10:28","dtypep":"(H)","origName":"i_b","isSc":false,"isPrimaryIO":true,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"o_a","addr":"(J)","loc":"d,11:25,11:28","dtypep":"(K)","origName":"o_a","isSc":false,"isPrimaryIO":true,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"o_b","addr":"(L)","loc":"d,12:25,12:28","dtypep":"(K)","origName":"o_b","isSc":false,"isPrimaryIO":true,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"vlvbound_test.i_a","addr":"(M)","loc":"d,9:25,9:28","dtypep":"(H)","origName":"i_a","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"vlvbound_test.i_b","addr":"(N)","loc":"d,10:25,10:28","dtypep":"(H)","origName":"i_b","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"vlvbound_test.o_a","addr":"(O)","loc":"d,11:25,11:28","dtypep":"(K)","origName":"o_a","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"vlvbound_test.o_b","addr":"(P)","loc":"d,12:25,12:28","dtypep":"(K)","origName":"o_b","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"i_a","addr":"(G)","loc":"d,9:25,9:28","dtypep":"(H)","origName":"i_a","isSc":false,"isPrimaryIO":true,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"i_b","addr":"(I)","loc":"d,10:25,10:28","dtypep":"(H)","origName":"i_b","isSc":false,"isPrimaryIO":true,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"o_a","addr":"(J)","loc":"d,11:25,11:28","dtypep":"(K)","origName":"o_a","isSc":false,"isPrimaryIO":true,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"o_b","addr":"(L)","loc":"d,12:25,12:28","dtypep":"(K)","origName":"o_b","isSc":false,"isPrimaryIO":true,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":true,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"vlvbound_test.i_a","addr":"(M)","loc":"d,9:25,9:28","dtypep":"(H)","origName":"i_a","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"vlvbound_test.i_b","addr":"(N)","loc":"d,10:25,10:28","dtypep":"(H)","origName":"i_b","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"vlvbound_test.o_a","addr":"(O)","loc":"d,11:25,11:28","dtypep":"(K)","origName":"o_a","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"vlvbound_test.o_b","addr":"(P)","loc":"d,12:25,12:28","dtypep":"(K)","origName":"o_b","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"TOPSCOPE","name":"","addr":"(E)","loc":"d,7:8,7:21","senTreesp": [], "scopep": [ {"type":"SCOPE","name":"TOP","addr":"(Q)","loc":"d,7:8,7:21","aboveScopep":"UNLINKED","aboveCellp":"UNLINKED","modp":"(F)", diff --git a/test_regress/t/t_json_only_output.out b/test_regress/t/t_json_only_output.out index 781242642..bb3109dc7 100644 --- a/test_regress/t/t_json_only_output.out +++ b/test_regress/t/t_json_only_output.out @@ -2,7 +2,7 @@ "modulesp": [ {"type":"MODULE","name":"m","addr":"(E)","loc":"d,7:8,7:9","origName":"m","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"clk","addr":"(F)","loc":"d,8:10,8:13","dtypep":"(G)","origName":"clk","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"clk","addr":"(F)","loc":"d,8:10,8:13","dtypep":"(G)","origName":"clk","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"activesp": []} ],"filesp": [], "miscsp": [ diff --git a/test_regress/t/t_json_only_tag.out b/test_regress/t/t_json_only_tag.out index edadeff67..cb03e77cd 100644 --- a/test_regress/t/t_json_only_tag.out +++ b/test_regress/t/t_json_only_tag.out @@ -2,9 +2,9 @@ "modulesp": [ {"type":"MODULE","name":"m","addr":"(E)","loc":"d,12:8,12:9","origName":"m","level":2,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"clk_ip","addr":"(F)","loc":"d,14:11,14:17","dtypep":"(G)","origName":"clk_ip","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"rst_ip","addr":"(H)","loc":"d,15:11,15:17","dtypep":"(G)","origName":"rst_ip","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"foo_op","addr":"(I)","loc":"d,16:11,16:17","dtypep":"(G)","origName":"foo_op","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"clk_ip","addr":"(F)","loc":"d,14:11,14:17","dtypep":"(G)","origName":"clk_ip","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"rst_ip","addr":"(H)","loc":"d,15:11,15:17","dtypep":"(G)","origName":"rst_ip","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"foo_op","addr":"(I)","loc":"d,16:11,16:17","dtypep":"(G)","origName":"foo_op","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"TYPEDEF","name":"my_struct","addr":"(J)","loc":"d,25:6,25:15","dtypep":"(K)","attrPublic":false,"childDTypep": [],"attrsp": []}, {"type":"CELL","name":"itop","addr":"(L)","loc":"d,29:8,29:12","origName":"itop","recursive":false,"modp":"(M)","pinsp": [],"paramsp": [],"rangep": [],"intfRefsp": []}, {"type":"VAR","name":"itop__Viftop","addr":"(N)","loc":"d,29:8,29:12","dtypep":"(O)","origName":"itop__Viftop","isSc":false,"isPrimaryIO":false,"direction":"NONE","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"IFACEREF","dtypeName":"","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, @@ -17,7 +17,7 @@ "lhsp": [ {"type":"VARREF","name":"dotted","addr":"(X)","loc":"d,33:16,33:22","dtypep":"(S)","access":"WR","varp":"(R)","varScopep":"UNLINKED","classOrPackagep":"UNLINKED"} ],"timingControlp": [],"strengthSpecp": []}, - {"type":"FUNC","name":"f","addr":"(Y)","loc":"d,35:13,35:14","dtypep":"(G)","method":false,"dpiExport":false,"dpiImport":false,"dpiOpenChild":false,"dpiOpenParent":false,"prototype":false,"recursive":false,"taskPublic":false,"cname":"f", + {"type":"FUNC","name":"f","addr":"(Y)","loc":"d,35:13,35:14","dtypep":"(G)","method":false,"dpiExport":false,"dpiImport":false,"dpiOpenChild":false,"dpiOpenParent":false,"isExternDef":false,"isExternProto":false,"prototype":false,"recursive":false,"taskPublic":false,"cname":"f", "fvarp": [ {"type":"VAR","name":"f","addr":"(Z)","loc":"d,35:13,35:14","dtypep":"(G)","origName":"f","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":true,"isFuncLocal":true,"attrClocker":"UNKNOWN","lifetime":"VAUTOM","varType":"VAR","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"classOrPackagep": [], @@ -74,7 +74,7 @@ {"type":"MEMBERDTYPE","name":"enable","addr":"(UB)","loc":"d,23:19,23:25","dtypep":"(UB)","generic":false,"childDTypep": [],"valuep": []}, {"type":"MEMBERDTYPE","name":"data","addr":"(VB)","loc":"d,24:19,24:23","dtypep":"(VB)","generic":false,"childDTypep": [],"valuep": []} ]}, - {"type":"IFACEREFDTYPE","name":"","addr":"(O)","loc":"d,29:8,29:12","dtypep":"(O)","cellName":"itop","ifaceName":"ifc","modportName":"","generic":false,"ifacep":"UNLINKED","cellp":"(L)","modportp":"UNLINKED","paramsp": []}, + {"type":"IFACEREFDTYPE","name":"","addr":"(O)","loc":"d,29:8,29:12","dtypep":"(O)","isPortDecl":false,"isVirtual":false,"cellName":"itop","ifaceName":"ifc","modportName":"","generic":false,"ifacep":"UNLINKED","cellp":"(L)","modportp":"UNLINKED","paramsp": []}, {"type":"BASICDTYPE","name":"logic","addr":"(S)","loc":"d,31:27,31:28","dtypep":"(S)","keyword":"logic","range":"31:0","generic":true,"rangep": []}, {"type":"REFDTYPE","name":"my_struct","addr":"(WB)","loc":"d,31:4,31:13","dtypep":"(K)","generic":false,"typedefp":"UNLINKED","refDTypep":"(K)","classOrPackagep":"UNLINKED","typeofp": [],"classOrPackageOpp": [],"paramsp": []}, {"type":"UNPACKARRAYDTYPE","name":"","addr":"(Q)","loc":"d,31:26,31:27","dtypep":"(Q)","isCompound":false,"declRange":"[0:1]","generic":false,"refDTypep":"(WB)","childDTypep": [], diff --git a/test_regress/t/t_lint_iface_array_topmodule_bad.out b/test_regress/t/t_lint_iface_array_topmodule_bad.out index 15778c71b..dda9a0753 100644 --- a/test_regress/t/t_lint_iface_array_topmodule_bad.out +++ b/test_regress/t/t_lint_iface_array_topmodule_bad.out @@ -1,4 +1,4 @@ -%Error: t/t_lint_iface_array_topmodule_bad.v:8:24: Parameter without initial value is never given value (IEEE 1800-2023 6.20.1): 'DW' +%Error: t/t_lint_iface_array_topmodule_bad.v:8:24: Parameter without default value is never given value (IEEE 1800-2023 6.20.1): 'DW' : ... note: In instance 't' 8 | parameter integer DW | ^~ diff --git a/test_regress/t/t_lint_iface_topmodule_bad.out b/test_regress/t/t_lint_iface_topmodule_bad.out index b7a2efc8d..617ac75a9 100644 --- a/test_regress/t/t_lint_iface_topmodule_bad.out +++ b/test_regress/t/t_lint_iface_topmodule_bad.out @@ -1,4 +1,4 @@ -%Error: t/t_lint_iface_topmodule_bad.v:8:23: Parameter without initial value is never given value (IEEE 1800-2023 6.20.1): 'DW' +%Error: t/t_lint_iface_topmodule_bad.v:8:23: Parameter without default value is never given value (IEEE 1800-2023 6.20.1): 'DW' : ... note: In instance 't' 8 | parameter integer DW | ^~ diff --git a/test_regress/t/t_lint_implicit_type_bad.out b/test_regress/t/t_lint_implicit_type_bad.out index 8f0e6e645..27fc9c53d 100644 --- a/test_regress/t/t_lint_implicit_type_bad.out +++ b/test_regress/t/t_lint_implicit_type_bad.out @@ -1,4 +1,4 @@ -%Error: t/t_lint_implicit_type_bad.v:11:11: syntax error, unexpected TYPE-IDENTIFIER +%Error: t/t_lint_implicit_type_bad.v:11:11: syntax error, unexpected IDENTIFIER-for-type 11 | assign imp_type_conflict = 1'b1; | ^~~~~~~~~~~~~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_lint_pkg_colon_bad.out b/test_regress/t/t_lint_pkg_colon_bad.out index 9058994fd..dacf56eda 100644 --- a/test_regress/t/t_lint_pkg_colon_bad.out +++ b/test_regress/t/t_lint_pkg_colon_bad.out @@ -2,7 +2,7 @@ 7 | module t (input mispkg::foo_t a); | ^~~~~~ ... For error description see https://verilator.org/warn/PKGNODECL?v=latest -%Error: t/t_lint_pkg_colon_bad.v:7:25: syntax error, unexpected IDENTIFIER, expecting TYPE-IDENTIFIER +%Error: t/t_lint_pkg_colon_bad.v:7:25: syntax error, unexpected IDENTIFIER, expecting IDENTIFIER-for-type 7 | module t (input mispkg::foo_t a); | ^~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_mailbox_array.py b/test_regress/t/t_mailbox_array.py new file mode 100755 index 000000000..4839f3e66 --- /dev/null +++ b/test_regress/t/t_mailbox_array.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile(verilator_flags2=['--fno-slice']) # TODO remove -fno-slice, issue #5632/#5644 + +test.execute() + +test.passes() diff --git a/test_regress/t/t_mailbox_array.v b/test_regress/t/t_mailbox_array.v new file mode 100644 index 000000000..0917b3cc1 --- /dev/null +++ b/test_regress/t/t_mailbox_array.v @@ -0,0 +1,26 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +class Cls; + localparam DWIDTH = 6; + typedef int my_type_t [2**DWIDTH]; + mailbox #(my_type_t) m_mbx; + + function new(); + this.m_mbx = new(1); + endfunction +endclass + +module tb_top(); + Cls c; + initial begin + c = new(); + $display("%p", c); + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_mod_automatic.py b/test_regress/t/t_mod_automatic.py new file mode 100755 index 000000000..d4f986441 --- /dev/null +++ b/test_regress/t/t_mod_automatic.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_mod_automatic.v b/test_regress/t/t_mod_automatic.v new file mode 100644 index 000000000..c3ffb868a --- /dev/null +++ b/test_regress/t/t_mod_automatic.v @@ -0,0 +1,47 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module automatic t(/*AUTOARG*/); + + task static accum_s(input integer value, output integer result); + static int acc = 1; + acc = acc + value; + result = acc; + endtask + + task accum_a(input integer value, output integer result); + int acc = 1; // automatic + acc = acc + value; + result = acc; + endtask + + integer value; + + reg failed = 0; // Static + + initial begin + accum_s(2, value); + $display("%d", value); + if (value !== 3) failed = 1; + + accum_s(3, value); + $display("%d", value); + if (value !== 6) failed = 1; + + accum_a(2, value); + $display("%d", value); + if (value !== 3) failed = 1; + + accum_a(3, value); + $display("%d", value); + if (value !== 4) failed = 1; + + if (failed) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_mod_interface_array3.out b/test_regress/t/t_mod_interface_array3.out index 2e9aaf9d7..a2b8ecba7 100644 --- a/test_regress/t/t_mod_interface_array3.out +++ b/test_regress/t/t_mod_interface_array3.out @@ -1,5 +1,5 @@ %Error-UNSUPPORTED: t/t_mod_interface_array3.v:22:20: Unsupported: Multidimensional instances/interfaces. - 22 | a_if iface [2:0][1:0]; + 22 | a_if iface [2:0][1:0] (); | ^ ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest %Error-UNSUPPORTED: t/t_mod_interface_array3.v:24:18: Unsupported: Multidimensional instances/interfaces. diff --git a/test_regress/t/t_mod_interface_array3.v b/test_regress/t/t_mod_interface_array3.v index 7ea8a209e..3a83a9ce4 100644 --- a/test_regress/t/t_mod_interface_array3.v +++ b/test_regress/t/t_mod_interface_array3.v @@ -19,7 +19,7 @@ module t; string str [2:0][1:0]; - a_if iface [2:0][1:0]; + a_if iface [2:0][1:0] (); sub i_sub[2:0][1:0] (.s(str)); diff --git a/test_regress/t/t_mod_mod.out b/test_regress/t/t_mod_mod.out new file mode 100644 index 000000000..755121ab5 --- /dev/null +++ b/test_regress/t/t_mod_mod.out @@ -0,0 +1,17 @@ +%Error-UNSUPPORTED: t/t_mod_mod.v:10:3: Unsupported: module decls within module decls + 10 | program p_in_m(); + | ^~~~~~~ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error-UNSUPPORTED: t/t_mod_mod.v:12:3: Unsupported: program decls within module decls + 12 | interface i_in_m(); + | ^~~~~~~~~ +%Error-UNSUPPORTED: t/t_mod_mod.v:14:1: Unsupported: interface decls within module decls + 14 | endmodule + | ^~~~~~~~~ +%Error-UNSUPPORTED: t/t_mod_mod.v:19:3: Unsupported: interface decls within interface decls + 19 | program p_in_i(); + | ^~~~~~~ +%Error-UNSUPPORTED: t/t_mod_mod.v:21:1: Unsupported: program decls within interface decls + 21 | endinterface + | ^~~~~~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_mod_mod.py b/test_regress/t/t_mod_mod.py new file mode 100755 index 000000000..6585af685 --- /dev/null +++ b/test_regress/t/t_mod_mod.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.lint(fails=test.vlt_all, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_mod_mod.v b/test_regress/t/t_mod_mod.v new file mode 100644 index 000000000..8e4465d0f --- /dev/null +++ b/test_regress/t/t_mod_mod.v @@ -0,0 +1,21 @@ +// 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 m(); + module m_in_m; + endmodule + program p_in_m(); + endprogram + interface i_in_m(); + endinterface +endmodule + +interface i(); + interface i_in_i(); + endinterface + program p_in_i(); + endprogram +endinterface diff --git a/test_regress/t/t_nba_struct_array.py b/test_regress/t/t_nba_struct_array.py new file mode 100755 index 000000000..f64ff6ad9 --- /dev/null +++ b/test_regress/t/t_nba_struct_array.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile() + +test.execute(check_finished=True) + +test.passes() diff --git a/test_regress/t/t_nba_struct_array.v b/test_regress/t/t_nba_struct_array.v new file mode 100644 index 000000000..6233c3cf1 --- /dev/null +++ b/test_regress/t/t_nba_struct_array.v @@ -0,0 +1,93 @@ + +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +`define stop $stop +`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0) + +module t(clk); + input clk; + + logic [31:0] cyc = 0; + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 99) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + +`define at_posedge_clk_on_cycle(n) always @(posedge clk) if (cyc == n) + + struct { + int foo; + int bar; + } arr [2]; + + initial begin + arr[0].foo = 0; + arr[0].bar = 100; + arr[1].foo = 0; + arr[1].bar = 100; + end + + `at_posedge_clk_on_cycle(0) begin + for (int i = 0; i < 2; ++i) begin + `checkh(arr[i].foo, 0); + `checkh(arr[i].bar, 100); + end + end + `at_posedge_clk_on_cycle(1) begin + for (int i = 0; i < 2; ++i) begin + `checkh(arr[i].foo, 0); + `checkh(arr[i].bar, 100); + end + arr[0].foo <= 0; + arr[0].bar <= -0; + arr[1].foo <= 1; + arr[1].bar <= -1; + for (int i = 0; i < 2; ++i) begin + `checkh(arr[i].foo, 0); + `checkh(arr[i].bar, 100); + end + end + `at_posedge_clk_on_cycle(2) begin + for (int i = 0; i < 2; ++i) begin + `checkh(arr[i].foo, i); + `checkh(arr[i].bar, -i); + end + arr[0].foo <= ~0; + arr[0].bar <= 0; + arr[1].foo <= ~1; + arr[1].bar <= 1; + for (int i = 0; i < 2; ++i) begin + `checkh(arr[i].foo, i); + `checkh(arr[i].bar, -i); + end + end + `at_posedge_clk_on_cycle(3) begin + for (int i = 0; i < 2; ++i) begin + `checkh(arr[i].foo, ~i); + `checkh(arr[i].bar, i); + end + arr[0].foo <= -1; + arr[0].bar <= -2; + arr[1].foo <= -1; + arr[1].bar <= -2; + for (int i = 0; i < 2; ++i) begin + `checkh(arr[i].foo, ~i); + `checkh(arr[i].bar, i); + end + end + `at_posedge_clk_on_cycle(4) begin + for (int i = 0; i < 2; ++i) begin + `checkh(arr[i].foo, -1); + `checkh(arr[i].bar, -2); + end + end + + +endmodule diff --git a/test_regress/t/t_no_std_pkg_bad.py b/test_regress/t/t_no_std_pkg_bad.py new file mode 100755 index 000000000..84dacb568 --- /dev/null +++ b/test_regress/t/t_no_std_pkg_bad.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') +test.top_filename = "t/t_no_std_bad.v" +test.golden_filename = "t/t_no_std_bad.out" + +test.lint(fails=True, + verilator_flags2=["--no-std-package", "--exe --main --timing -Wall"], + expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_opt_inline_funcs.py b/test_regress/t/t_opt_inline_funcs.py new file mode 100755 index 000000000..53c9b79fa --- /dev/null +++ b/test_regress/t/t_opt_inline_funcs.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.compile(verilator_flags2=['--stats'], verilator_make_gmake=False) + +test.file_grep(test.stats, r'Optimizations, Functions inlined\s+(\d+)', 2) + +test.passes() diff --git a/test_regress/t/t_opt_inline_funcs.v b/test_regress/t/t_opt_inline_funcs.v new file mode 100644 index 000000000..0fb2c6e2b --- /dev/null +++ b/test_regress/t/t_opt_inline_funcs.v @@ -0,0 +1,21 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/); + + function void allfin; + $write("*-* All Finished *-*\n"); + endfunction + + task done; + $finish; + endtask + + initial begin + allfin(); + done(); + end +endmodule diff --git a/test_regress/t/t_opt_inline_funcs_no.py b/test_regress/t/t_opt_inline_funcs_no.py new file mode 100755 index 000000000..28f5acd13 --- /dev/null +++ b/test_regress/t/t_opt_inline_funcs_no.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') +test.top_filename = "t/t_opt_inline_funcs.v" + +test.compile(verilator_flags2=['--fno-inline-funcs', '--stats'], verilator_make_gmake=False) + +test.file_grep(test.stats, r'Optimizations, Functions inlined\s+(\d+)', 0) + +test.passes() diff --git a/test_regress/t/t_opt_slice.py b/test_regress/t/t_opt_slice.py new file mode 100755 index 000000000..b39ad3229 --- /dev/null +++ b/test_regress/t/t_opt_slice.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile(verilator_flags2=['--sc', '--stats']) + +test.file_grep(test.stats, r'Optimizations, Slice array assignments\s+(\d+)', 3) + +test.passes() diff --git a/test_regress/t/t_opt_slice.v b/test_regress/t/t_opt_slice.v new file mode 100644 index 000000000..92ac3dd37 --- /dev/null +++ b/test_regress/t/t_opt_slice.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, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/ + // Outputs + o1a2, + // Inputs + i1a2 + ); + + input i1a2 [1:0]; + output logic o1a2 [1:0]; + + always o1a2 = i1a2; + + initial begin + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_opt_slice_no.py b/test_regress/t/t_opt_slice_no.py new file mode 100755 index 000000000..3ee92e4e0 --- /dev/null +++ b/test_regress/t/t_opt_slice_no.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') +test.top_filename = 't/t_opt_slice.v' + +test.compile(verilator_flags2=['--sc', '--stats', '-fno-slice']) + +test.file_grep(test.stats, r'Optimizations, Slice array assignments\s+(\d+)', 2) + +test.passes() diff --git a/test_regress/t/t_package_identifier_bad.out b/test_regress/t/t_package_identifier_bad.out new file mode 100644 index 000000000..6097d0e73 --- /dev/null +++ b/test_regress/t/t_package_identifier_bad.out @@ -0,0 +1,5 @@ +%Error-PKGNODECL: t/t_package_identifier_bad.v:15:20: Package/class 'Bar' not found, and needs to be predeclared (IEEE 1800-2023 26.3) + 15 | int baz = Foo::Bar::baz; + | ^~~ + ... For error description see https://verilator.org/warn/PKGNODECL?v=latest +%Error: Exiting due to diff --git a/test_regress/t/t_package_identifier_bad.py b/test_regress/t/t_package_identifier_bad.py new file mode 100755 index 000000000..31228c9a7 --- /dev/null +++ b/test_regress/t/t_package_identifier_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_pkg_identifier_bad.v b/test_regress/t/t_package_identifier_bad.v similarity index 83% rename from test_regress/t/t_pkg_identifier_bad.v rename to test_regress/t/t_package_identifier_bad.v index a3cd4a068..a3457cee5 100644 --- a/test_regress/t/t_pkg_identifier_bad.v +++ b/test_regress/t/t_package_identifier_bad.v @@ -4,13 +4,13 @@ // any use, without warranty, 2023 by Antmicro Ltd. // SPDX-License-Identifier: CC0-1.0 -package foo; +package Foo; endpackage -package bar; +package Bar; static int baz; endpackage module t; - int baz = foo::bar::baz; + int baz = Foo::Bar::baz; endmodule diff --git a/test_regress/t/t_package_local_bad.out b/test_regress/t/t_package_local_bad.out index 8cad1cb2e..8a3dbab30 100644 --- a/test_regress/t/t_package_local_bad.out +++ b/test_regress/t/t_package_local_bad.out @@ -1,7 +1,4 @@ -%Error: t/t_package_local_bad.v:9:16: Illegal 'local::' outside 'randomize() with' +%Error: t/t_package_local_bad.v:9:16: Illegal 'local::' outside 'randomize() with' (IEEE 1800-2023 18.7.1) 9 | $display(local::x); | ^~~~~ -%Error: t/t_package_local_bad.v:9:23: Can't find definition of scope/variable/func: 'x' - 9 | $display(local::x); - | ^ %Error: Exiting due to diff --git a/test_regress/t/t_package_using_dollar_unit.py b/test_regress/t/t_package_using_dollar_unit.py new file mode 100755 index 000000000..d4f986441 --- /dev/null +++ b/test_regress/t/t_package_using_dollar_unit.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_pkg_using_dollar_unit_items.v b/test_regress/t/t_package_using_dollar_unit.v similarity index 100% rename from test_regress/t/t_pkg_using_dollar_unit_items.v rename to test_regress/t/t_package_using_dollar_unit.v diff --git a/test_regress/t/t_param_default_bad.out b/test_regress/t/t_param_default_bad.out index b08438467..b4a331abb 100644 --- a/test_regress/t/t_param_default_bad.out +++ b/test_regress/t/t_param_default_bad.out @@ -1,4 +1,4 @@ -%Error: t/t_param_default_bad.v:7:26: Parameter without initial value is never given value (IEEE 1800-2023 6.20.1): 'Foo' +%Error: t/t_param_default_bad.v:7:26: Parameter without default value is never given value (IEEE 1800-2023 6.20.1): 'Foo' : ... note: In instance 't.foo' 7 | module m #(parameter int Foo); | ^~~ diff --git a/test_regress/t/t_param_default_presv_bad.out b/test_regress/t/t_param_default_presv_bad.out index 60432957c..6a1db2f52 100644 --- a/test_regress/t/t_param_default_presv_bad.out +++ b/test_regress/t/t_param_default_presv_bad.out @@ -3,7 +3,7 @@ | ^~~ ... For warning description see https://verilator.org/warn/NEWERSTD?v=latest ... Use "/* verilator lint_off NEWERSTD */" and lint_on around source to disable this message. -%Error: t/t_param_default_bad.v:7:26: Parameter without initial value is never given value (IEEE 1800-2023 6.20.1): 'Foo' +%Error: t/t_param_default_bad.v:7:26: Parameter without default value is never given value (IEEE 1800-2023 6.20.1): 'Foo' : ... note: In instance 't.foo' 7 | module m #(parameter int Foo); | ^~~ diff --git a/test_regress/t/t_param_noval_bad.out b/test_regress/t/t_param_noval_bad.out index 432b48da8..14072fd52 100644 --- a/test_regress/t/t_param_noval_bad.out +++ b/test_regress/t/t_param_noval_bad.out @@ -1,7 +1,11 @@ -%Error: t/t_param_noval_bad.v:7:22: Parameter without initial value is never given value (IEEE 1800-2023 6.20.1): 'P' +%Error: t/t_param_noval_bad.v:7:22: Parameter without default value is never given value (IEEE 1800-2023 6.20.1): 'P' : ... note: In instance 't' - 7 | module t #(parameter P); + 7 | module t #(parameter P, parameter type T); | ^ +%Error: t/t_param_noval_bad.v:7:40: Parameter type without default value is never given value (IEEE 1800-2023 6.20.1): 'T' + : ... note: In instance 't' + 7 | module t #(parameter P, parameter type T); + | ^ %Warning-WIDTHTRUNC: t/t_param_noval_bad.v:10:7: Logical operator GENFOR expects 1 bit on the For Test Condition, but For Test Condition's VARREF 'P' generates 32 bits. : ... note: In instance 't' 10 | for (j=0; P; j++) diff --git a/test_regress/t/t_param_noval_bad.v b/test_regress/t/t_param_noval_bad.v index 3dde4948a..61248d8ef 100644 --- a/test_regress/t/t_param_noval_bad.v +++ b/test_regress/t/t_param_noval_bad.v @@ -4,7 +4,7 @@ // any use, without warranty, 2019 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 -module t #(parameter P); +module t #(parameter P, parameter type T); generate var j; for (j=0; P; j++) diff --git a/test_regress/t/t_param_pattern_init.py b/test_regress/t/t_param_pattern_init.py new file mode 100755 index 000000000..d4f986441 --- /dev/null +++ b/test_regress/t/t_param_pattern_init.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_param_pattern_init.v b/test_regress/t/t_param_pattern_init.v new file mode 100644 index 000000000..69fefffec --- /dev/null +++ b/test_regress/t/t_param_pattern_init.v @@ -0,0 +1,105 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2010 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +`define stop $stop +`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); + +package some_pkg; + localparam FOO = 5; + localparam BAR = 6; + + typedef enum int { + QUX = 7 + } pkg_enum_t; +endpackage + +module t (/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + int cyc = 0; + + localparam int unsigned SPI_INDEX = 0; + localparam int unsigned I2C_INDEX = 1; + localparam int unsigned TMR_INDEX = 4; + + localparam logic [31:0] AHB_ADDR[6] = '{ + SPI_INDEX: 32'h80001000, + I2C_INDEX: 32'h80002000, + TMR_INDEX: 32'h80003000, + default: '0}; + + initial begin + `checkh(AHB_ADDR[0], 32'h80001000); + `checkh(AHB_ADDR[1], 32'h80002000); + `checkh(AHB_ADDR[2], 32'h0); + `checkh(AHB_ADDR[3], 32'h0); + `checkh(AHB_ADDR[4], 32'h80003000); + `checkh(AHB_ADDR[5], 32'h0); + end + + genvar genvar_i; + for (genvar_i = 0; genvar_i < 2; genvar_i++) begin: the_gen + logic [31:0] gen_array [10]; + + always_comb gen_array = '{ + genvar_i: 32'habcd, + default: 0 + }; + + always_ff @(posedge clk) begin + `checkh(gen_array[genvar_i], 32'habcd); + end + end + + typedef enum int { + ENUM_A = 0, + ENUM_B, + ENUM_C + } enum_t; + + logic [31:0] enum_array [11]; + + always_comb enum_array = '{ + ENUM_A: 32'h1234, + ENUM_B: 32'h7777, + ENUM_C: 32'ha5a5, + default: 0 + }; + + always_ff @(posedge clk) begin + `checkh(enum_array[0], 32'h1234); + `checkh(enum_array[1], 32'h7777); + `checkh(enum_array[2], 32'ha5a5); + end + + logic [31:0] package_array [8]; + + import some_pkg::*; + always_comb package_array = '{ + FOO: 32'h9876, + BAR: 32'h1212, + QUX: 32'h5432, + default: 0 + }; + + always_ff @(posedge clk) begin + `checkh(package_array[5], 32'h9876); + `checkh(package_array[6], 32'h1212); + `checkh(package_array[7], 32'h5432); + end + + always_ff @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 2) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule diff --git a/test_regress/t/t_param_store_bad.out b/test_regress/t/t_param_store_bad.out new file mode 100644 index 000000000..8db0b471b --- /dev/null +++ b/test_regress/t/t_param_store_bad.out @@ -0,0 +1,4 @@ +%Error: t/t_param_store_bad.v:12:31: Storing to parameter variable 'S' in a context that is determined only at runtime + 12 | $value$plusargs("S=%s", S); + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_param_store_bad.py b/test_regress/t/t_param_store_bad.py new file mode 100755 index 000000000..31228c9a7 --- /dev/null +++ b/test_regress/t/t_param_store_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_param_store_bad.v b/test_regress/t/t_param_store_bad.v new file mode 100644 index 000000000..5f617d9d7 --- /dev/null +++ b/test_regress/t/t_param_store_bad.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, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t #( + string S = "" + ); + + initial begin + $value$plusargs("S=%s", S); // BAD assignment to S + #1; // Original bug got compile time error only with this line + $display("S=%s", S); + $finish; + end + +endmodule diff --git a/test_regress/t/t_param_type_bad.out b/test_regress/t/t_param_type_bad.out index 528bd8fc5..316eab2ba 100644 --- a/test_regress/t/t_param_type_bad.out +++ b/test_regress/t/t_param_type_bad.out @@ -1,4 +1,4 @@ -%Error: t/t_param_type_bad.v:9:27: syntax error, unexpected INTEGER NUMBER, expecting IDENTIFIER or TYPE-IDENTIFIER or randomize +%Error: t/t_param_type_bad.v:9:27: syntax error, unexpected INTEGER NUMBER, expecting IDENTIFIER or IDENTIFIER-for-cell or IDENTIFIER-for-type or randomize 9 | localparam type bad2 = 2; | ^ %Error: Exiting due to diff --git a/test_regress/t/t_pkg_identifier_bad.out b/test_regress/t/t_pkg_identifier_bad.out deleted file mode 100644 index b05993a11..000000000 --- a/test_regress/t/t_pkg_identifier_bad.out +++ /dev/null @@ -1,5 +0,0 @@ -%Error-PKGNODECL: t/t_pkg_identifier_bad.v:15:20: Package/class 'bar' not found, and needs to be predeclared (IEEE 1800-2023 26.3) - 15 | int baz = foo::bar::baz; - | ^~~ - ... For error description see https://verilator.org/warn/PKGNODECL?v=latest -%Error: Exiting due to diff --git a/test_regress/t/t_queue_assignment.py b/test_regress/t/t_queue_assignment.py new file mode 100755 index 000000000..d4f986441 --- /dev/null +++ b/test_regress/t/t_queue_assignment.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_queue_assignment.v b/test_regress/t/t_queue_assignment.v new file mode 100644 index 000000000..80f52ca52 --- /dev/null +++ b/test_regress/t/t_queue_assignment.v @@ -0,0 +1,41 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by PlanV GmbH. +// SPDX-License-Identifier: CC0-1.0 + +module t_queue_assignment; + typedef int T_QI[$]; + T_QI jagged_array[$]; // int jagged_array[$][$]; + initial begin + jagged_array = '{ {1}, T_QI'{2,3,4}, {5,6} }; + // jagged_array[0][0] = 1 -- jagged_array[0] is a queue of 1 int + // jagged_array[1][0] = 2 -- jagged_array[1] is a queue of 3 ints + // jagged_array[1][1] = 3 + // jagged_array[1][2] = 4 + // jagged_array[2][0] = 5 -- jagged_array[2] is a queue of 2 ints + // jagged_array[2][1] = 6 + jagged_array.push_back('{7}); + jagged_array.push_back('{8, 9, 10}); + jagged_array.push_front('{0, 1}); + print_and_check(); + + $write("*-* All Finished *-*\n"); + $finish; + end + + task automatic print_and_check(); + integer i, j; + int expected_values[][] = '{ '{0, 1}, '{1}, '{2, 3, 4}, '{5, 6}, '{7}, '{8, 9, 10} }; + + for (i = 0; i < jagged_array.size(); i++) begin + for (j = 0; j < jagged_array[i].size(); j++) begin + // $display("jagged_array[%0d][%0d] = %0d", i, j, jagged_array[i][j]); + if (jagged_array[i][j] !== expected_values[i][j]) begin + $stop; + end + end + end + endtask + +endmodule diff --git a/test_regress/t/t_randomize_array.v b/test_regress/t/t_randomize_array.v index 63747653c..f1a5abece 100755 --- a/test_regress/t/t_randomize_array.v +++ b/test_regress/t/t_randomize_array.v @@ -72,6 +72,7 @@ class unconstrained_dynamic_array_test; rand int dynamic_array_1d[]; rand int dynamic_array_2d[][]; rand Cls class_dynamic_array[]; + rand Cls class_dynamic_array_null[]; function new(); // Initialize 1D dynamic array @@ -94,6 +95,8 @@ class unconstrained_dynamic_array_test; class_dynamic_array[i] = new; end + class_dynamic_array_null = new[2]; + endfunction function void check_randomization(); @@ -108,6 +111,9 @@ class unconstrained_dynamic_array_test; foreach (class_dynamic_array[i]) begin `check_rand(this, class_dynamic_array[i].x) end + foreach (class_dynamic_array_null[i]) begin + if (class_dynamic_array_null[i] != null) $stop; + end endfunction endclass diff --git a/test_regress/t/t_randomize_extern.out b/test_regress/t/t_randomize_extern.out deleted file mode 100644 index a56aaa409..000000000 --- a/test_regress/t/t_randomize_extern.out +++ /dev/null @@ -1,11 +0,0 @@ -%Error-UNSUPPORTED: t/t_randomize_extern.v:8:4: Unsupported: pure constraint - 8 | pure constraint pur; - | ^~~~ - ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest -%Error-UNSUPPORTED: t/t_randomize_extern.v:17:4: Unsupported: extern constraint - 17 | extern constraint ex; - | ^~~~~~ -%Error-UNSUPPORTED: t/t_randomize_extern.v:21:1: Unsupported: extern constraint - 21 | constraint Packet::ex { header == 2; } - | ^~~~~~~~~~ -%Error: Exiting due to diff --git a/test_regress/t/t_randomize_extern.v b/test_regress/t/t_randomize_extern.v deleted file mode 100644 index cc74f0323..000000000 --- a/test_regress/t/t_randomize_extern.v +++ /dev/null @@ -1,42 +0,0 @@ -// DESCRIPTION: Verilator: Verilog Test module -// -// This file ONLY is placed under the Creative Commons Public Domain, for -// any use, without warranty, 2020 by Wilson Snyder. -// SPDX-License-Identifier: CC0-1.0 - -class Base; - pure constraint pur; -endclass - -class Packet extends Base; - rand int header; - rand int length; - - constraint pur { length == 3; } - - extern constraint ex; - -endclass - -constraint Packet::ex { header == 2; } - -module t (/*AUTOARG*/); - - Packet p; - - initial begin - - int v; - v = p.randomize(); - if (v != 1) $stop; - if (p.header != 2) $stop; - if (p.length != 3) $stop; - v = p.randomize(1); - if (v != 1) $stop; - if (p.header != 2) $stop; - if (p.length != 3) $stop; - - $write("*-* All Finished *-*\n"); - $finish; - end -endmodule diff --git a/test_regress/t/t_randomize_method_types_unsup.out b/test_regress/t/t_randomize_method_types_unsup.out index 2526171bc..4dd60a0a9 100644 --- a/test_regress/t/t_randomize_method_types_unsup.out +++ b/test_regress/t/t_randomize_method_types_unsup.out @@ -1,10 +1,20 @@ -%Warning-CONSTRAINTIGN: t/t_randomize_method_types_unsup.v:13:32: Unsupported: randomizing this expression, treating as state - 13 | constraint dynsize { dynarr.size < 20; } - | ^~~~ +%Warning-CONSTRAINTIGN: t/t_randomize_method_types_unsup.v:23:17: Unsupported: randomizing this expression, treating as state + 23 | dynarr[1].size < 10; + | ^~~~ ... For warning description see https://verilator.org/warn/CONSTRAINTIGN?v=latest ... Use "/* verilator lint_off CONSTRAINTIGN */" and lint_on around source to disable this message. -%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:10:13: Unsupported: random member variable with the type of the containing class +%Warning-CONSTRAINTIGN: t/t_randomize_method_types_unsup.v:27:9: Size constraint combined with element constraint may not work correctly + : ... note: In instance 't' + 27 | q.size < 5; + | ^~~~ +%Warning-CONSTRAINTIGN: t/t_randomize_method_types_unsup.v:31:10: Global constraints ignored (unsupported) + 31 | foo.x < y; + | ^ +%Error-UNSUPPORTED: t/t_randomize_method_types_unsup.v:15:13: Unsupported: random member variable with the type of the containing class : ... note: In instance 't' - 10 | rand Cls cls; + 15 | rand Cls cls; | ^~~ +%Warning-CONSTRAINTIGN: t/t_randomize_method_types_unsup.v:43:43: Unsupported: randomizing this expression, treating as state + 43 | res = obj.randomize() with { dynarr.size > 2; }; + | ^~~~ %Error: Exiting due to diff --git a/test_regress/t/t_randomize_method_types_unsup.v b/test_regress/t/t_randomize_method_types_unsup.v index 8fbb96f52..f100eeac9 100644 --- a/test_regress/t/t_randomize_method_types_unsup.v +++ b/test_regress/t/t_randomize_method_types_unsup.v @@ -4,14 +4,32 @@ // any use, without warranty, 2020 by Wilson Snyder. // SPDX-License-Identifier: CC0-1.0 +class Foo; + rand int x; +endclass + class Cls; rand int assocarr[string]; - rand int dynarr[]; + rand int dynarr[][]; + rand int q[$]; rand Cls cls; rand int i; + rand Foo foo; + rand int y; int st; - constraint dynsize { dynarr.size < 20; } + constraint dynsize { + dynarr.size < 20; + dynarr.size > 0; + dynarr[1].size < 10; + } constraint statedep { i < st + 2; } + constraint q_size_elem { + q.size < 5; + q[i] < 10; + } + constraint global_constraint { + foo.x < y; + } endclass module t (/*AUTOARG*/); @@ -20,6 +38,8 @@ module t (/*AUTOARG*/); initial begin obj = new; + obj.foo = new; res = obj.randomize(); + res = obj.randomize() with { dynarr.size > 2; }; end endmodule diff --git a/test_regress/t/t_randomize_param_with.py b/test_regress/t/t_randomize_param_with.py new file mode 100755 index 000000000..a2b131082 --- /dev/null +++ b/test_regress/t/t_randomize_param_with.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +if not test.have_solver: + test.skip("No constraint solver installed") + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_randomize_param_with.v b/test_regress/t/t_randomize_param_with.v new file mode 100644 index 000000000..3b7039436 --- /dev/null +++ b/test_regress/t/t_randomize_param_with.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, 2024 by Antmicro Ltd. +// SPDX-License-Identifier: CC0-1.0 + +`define check_rand(cl, field, constr, cond) \ +begin \ + longint prev_result; \ + int ok = 0; \ + if (!bit'(cl.randomize() with { constr; })) $stop; \ + prev_result = longint'(field); \ + if (!(cond)) $stop; \ + repeat(9) begin \ + longint result; \ + if (!bit'(cl.randomize() with { constr; })) $stop; \ + result = longint'(field); \ + if (!(cond)) $stop; \ + if (result != prev_result) ok = 1; \ + prev_result = result; \ + end \ + if (ok != 1) $stop; \ +end + +class Cls #(int LIMIT = 3); + rand int x; + int y = -100; + constraint x_limit { x <= LIMIT; }; +endclass + +module t; + initial begin + Cls#() cd = new; + Cls#(5) c5 = new; + + `check_rand(cd, cd.x, x > 0, cd.x > 0 && cd.x <= 3); + `check_rand(cd, cd.x, x > y, cd.x > -100 && cd.x <= 3); + if (cd.randomize() with {x > 3;} == 1) $stop; + + `check_rand(c5, c5.x, x > 0, c5.x > 0 && c5.x <= 5); + `check_rand(c5, c5.x, x > y, c5.x > -100 && c5.x <= 5); + if (c5.randomize() with {x >= 5;} == 0) $stop; + if (c5.x != 5) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_randomize_queue_size.py b/test_regress/t/t_randomize_queue_size.py new file mode 100755 index 000000000..a2b131082 --- /dev/null +++ b/test_regress/t/t_randomize_queue_size.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +if not test.have_solver: + test.skip("No constraint solver installed") + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_randomize_queue_size.v b/test_regress/t/t_randomize_queue_size.v new file mode 100755 index 000000000..f1429f642 --- /dev/null +++ b/test_regress/t/t_randomize_queue_size.v @@ -0,0 +1,85 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Antmicro Ltd. +// SPDX-License-Identifier: CC0-1.0 + +`define check_rand(cl, field, cond) \ +begin \ + longint prev_result; \ + int ok = 0; \ + if (!bit'(cl.randomize())) $stop; \ + prev_result = longint'(field); \ + if (!(cond)) $stop; \ + repeat(9) begin \ + longint result; \ + if (!bit'(cl.randomize())) $stop; \ + result = longint'(field); \ + if (!(cond)) $stop; \ + if (result != prev_result) ok = 1; \ + prev_result = result; \ + end \ + if (ok != 1) $stop; \ +end + +class Foo; + rand int q[$]; + rand int q2[$][$]; + int x = 1; + constraint c { + q.size() == 15; + q2.size() == 10; + } +endclass + +class Bar; + rand int q[$]; + rand int min_size; + rand int q2[$]; + constraint c { + min_size > 2; + q.size() >= min_size; + q.size() < 10; + }; + constraint c2 { + q2.size() < 7; + } +endclass + +class Baz; + rand Foo foo_arr[]; + constraint c_foo { + foo_arr.size == 7; + } +endclass + +module t; + initial begin + Foo foo = new; + Bar bar = new; + Baz baz = new; + + void'(foo.randomize()); + if (foo.q.size() != 15) $stop; + if (foo.q2.size() != 10) $stop; + + `check_rand(bar, bar.q.size(), bar.q.size() > 2 && bar.q.size() < 10); + `check_rand(bar, bar.q2.size(), bar.q2.size() < 7); + + baz.foo_arr = new[4]; + for (int i = 0; i < 4; i++) baz.foo_arr[i] = new; + baz.foo_arr[2].x = 2; + void'(baz.randomize()); + + if (baz.foo_arr.size() != 7) $stop; + for (int i = 0; i < 4; i++) + if (baz.foo_arr[i] == null) $stop; + for (int i = 4; i < 7; i++) + if (baz.foo_arr[i] != null) $stop; + if (baz.foo_arr[2].x != 2) $stop; + `check_rand(baz, baz.foo_arr[1].q[5], 1'b1); + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_savable_timing_bad.out b/test_regress/t/t_savable_timing_bad.out new file mode 100644 index 000000000..cef0f1ea3 --- /dev/null +++ b/test_regress/t/t_savable_timing_bad.out @@ -0,0 +1,2 @@ +%Error: Unsupported: --timing and --savable not supported together +%Error: Exiting due to diff --git a/test_regress/t/t_savable_timing_bad.py b/test_regress/t/t_savable_timing_bad.py new file mode 100755 index 000000000..31065f1eb --- /dev/null +++ b/test_regress/t/t_savable_timing_bad.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') +test.top_filename = "t/t_savable_coverage_bad.v" + +test.compile(v_flags2=["--savable --timing"], + save_time=500, + fails=True, + expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_vl_assign_sbw.cpp b/test_regress/t/t_sc_vl_assign_sbw.cpp similarity index 100% rename from test_regress/t/t_vl_assign_sbw.cpp rename to test_regress/t/t_sc_vl_assign_sbw.cpp diff --git a/test_regress/t/t_vl_assign_sbw.py b/test_regress/t/t_sc_vl_assign_sbw.py similarity index 100% rename from test_regress/t/t_vl_assign_sbw.py rename to test_regress/t/t_sc_vl_assign_sbw.py diff --git a/test_regress/t/t_vl_assign_sbw.v b/test_regress/t/t_sc_vl_assign_sbw.v similarity index 100% rename from test_regress/t/t_vl_assign_sbw.v rename to test_regress/t/t_sc_vl_assign_sbw.v diff --git a/test_regress/t/t_scoped_param_pattern_init_unsup.out b/test_regress/t/t_scoped_param_pattern_init_unsup.out new file mode 100644 index 000000000..377634d74 --- /dev/null +++ b/test_regress/t/t_scoped_param_pattern_init_unsup.out @@ -0,0 +1,4 @@ +%Error: t/t_scoped_param_pattern_init_unsup.v:30:22: syntax error, unexpected ':', expecting ',' or '}' + 30 | some_pkg::FOO: 32'h9876, + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_scoped_param_pattern_init_unsup.py b/test_regress/t/t_scoped_param_pattern_init_unsup.py new file mode 100755 index 000000000..efe8cc01c --- /dev/null +++ b/test_regress/t/t_scoped_param_pattern_init_unsup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.lint(fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_scoped_param_pattern_init_unsup.v b/test_regress/t/t_scoped_param_pattern_init_unsup.v new file mode 100644 index 000000000..ebaa9cd89 --- /dev/null +++ b/test_regress/t/t_scoped_param_pattern_init_unsup.v @@ -0,0 +1,50 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2010 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +`define stop $stop +`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); + +package some_pkg; + localparam FOO = 5; + localparam BAR = 6; + + typedef enum int { + QUX = 7 + } pkg_enum_t; +endpackage + +module t (/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + int cyc = 0; + + logic [31:0] package_array [8]; + + always_comb package_array = '{ + some_pkg::FOO: 32'h9876, + some_pkg::BAR: 32'h1212, + some_pkg::QUX: 32'h5432, + default: 0 + }; + + always_ff @(posedge clk) begin + `checkh(package_array[5], 32'h9876); + `checkh(package_array[6], 32'h1212); + `checkh(package_array[7], 32'h5432); + end + + always_ff @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 2) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule diff --git a/test_regress/t/t_std_identifier.py b/test_regress/t/t_std_identifier.py index 6938ef706..c312a43ce 100755 --- a/test_regress/t/t_std_identifier.py +++ b/test_regress/t/t_std_identifier.py @@ -11,6 +11,6 @@ import vltest_bootstrap test.scenarios('linter') -test.lint(verilator_flags2=["-DTEST_DECLARE_STD"]) +test.lint(verilator_flags2=["-DTEST_DECLARE_STD"], fails=test.vlt_all) # Issue #4705 due to :: test.passes() diff --git a/test_regress/t/t_std_waiver.py b/test_regress/t/t_std_waiver.py new file mode 100755 index 000000000..c2d985114 --- /dev/null +++ b/test_regress/t/t_std_waiver.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint() + +test.passes() diff --git a/test_regress/t/t_std_waiver.v b/test_regress/t/t_std_waiver.v new file mode 100644 index 000000000..08cf87957 --- /dev/null +++ b/test_regress/t/t_std_waiver.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, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +// Rather than look at waivers, just check we included it +`ifndef _VERILATED_STD_WAIVER_VLT_ +`error "Didn't include, no _VERILATED_STD_WAIVER_VLT_" +`endif + +module t; +endmodule diff --git a/test_regress/t/t_std_waiver_no.py b/test_regress/t/t_std_waiver_no.py new file mode 100755 index 000000000..2e67c6a6a --- /dev/null +++ b/test_regress/t/t_std_waiver_no.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(verilator_flags2=['-no-std-waiver']) + +test.passes() diff --git a/test_regress/t/t_std_waiver_no.v b/test_regress/t/t_std_waiver_no.v new file mode 100644 index 000000000..7cf201fb6 --- /dev/null +++ b/test_regress/t/t_std_waiver_no.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, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +// Rather than look at waivers, just check we included it +`ifdef _VERILATED_STD_WAIVER_VLT_ +`error "Shouldn't have included _VERILATED_STD_WAIVER_VLT_" +`endif + +module t; +endmodule diff --git a/test_regress/t/t_struct_array_assignment_delayed.py b/test_regress/t/t_struct_array_assignment_delayed.py new file mode 100755 index 000000000..3476171ff --- /dev/null +++ b/test_regress/t/t_struct_array_assignment_delayed.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile(timing_loop=True, verilator_flags2=["--timing"]) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_struct_array_assignment_delayed.v b/test_regress/t/t_struct_array_assignment_delayed.v new file mode 100644 index 000000000..1e4703c6c --- /dev/null +++ b/test_regress/t/t_struct_array_assignment_delayed.v @@ -0,0 +1,35 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by sumpster. +// SPDX-License-Identifier: CC0-1.0 + +module tb; + typedef struct { + logic a; + logic b; + } SimpleStruct; + + SimpleStruct s [1]; + + logic clock; + + always @(posedge clock) begin + for (int i = 0; i < 1; i++) begin + s[i].a <= 1; + s[i].b <= 0; + end + end + + initial begin + clock = 0; + s[0].a = 0; + s[0].b = 0; + + #1 clock = 1; + #1 if (s[0].a != 1) $stop; + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_struct_contents_bad.v b/test_regress/t/t_struct_contents_bad.v index e0981add9..b31734a07 100644 --- a/test_regress/t/t_struct_contents_bad.v +++ b/test_regress/t/t_struct_contents_bad.v @@ -30,6 +30,8 @@ endclass Cls c; // BAd } illegal_t; + illegal_t s; + initial begin $stop; end diff --git a/test_regress/t/t_timing_func_join.py b/test_regress/t/t_timing_func_join.py new file mode 100755 index 000000000..671072f97 --- /dev/null +++ b/test_regress/t/t_timing_func_join.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile(verilator_flags2=['--binary']) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_timing_func_join.v b/test_regress/t/t_timing_func_join.v new file mode 100644 index 000000000..e8b6b6816 --- /dev/null +++ b/test_regress/t/t_timing_func_join.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, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(/*AUTOARG*/); + function int fun(int val); + fork + $display("abc"); + $display("def"); + join_none // Although join is illegal, join_none legal (IEEE 1800-2023 13.4) + return val + 2; + endfunction + + task tsk(); + fork + $display("ghi"); + $display("jkl"); + join_none + endtask + + initial begin + $display("$d", fun(2)); + tsk(); + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_suspendable_deep.py b/test_regress/t/t_timing_suspendable_deep.py similarity index 100% rename from test_regress/t/t_suspendable_deep.py rename to test_regress/t/t_timing_suspendable_deep.py diff --git a/test_regress/t/t_suspendable_deep.v b/test_regress/t/t_timing_suspendable_deep.v similarity index 100% rename from test_regress/t/t_suspendable_deep.v rename to test_regress/t/t_timing_suspendable_deep.v diff --git a/test_regress/t/t_trace_public_sig_vlt.py b/test_regress/t/t_trace_public_sig_vlt.py index 743751fa9..5cb738257 100755 --- a/test_regress/t/t_trace_public_sig_vlt.py +++ b/test_regress/t/t_trace_public_sig_vlt.py @@ -26,7 +26,7 @@ test.compile(make_top_shell=False, if test.vlt_all: test.file_grep( out_filename, - r'{"type":"VAR","name":"GSR",.*"loc":"f,47:[^"]*",.*"origName":"GSR",.*"isSigPublic":true,.*"dtypeName":"logic",.*"isSigUserRdPublic":true.*"isSigUserRWPublic":true' + r'{"type":"VAR","name":"GSR",.*"loc":"\w,47:[^"]*",.*"origName":"GSR",.*"isSigPublic":true,.*"dtypeName":"logic",.*"isSigUserRdPublic":true.*"isSigUserRWPublic":true' ) test.execute() diff --git a/test_regress/t/t_tri_top_en_out.cpp b/test_regress/t/t_tri_top_en_out.cpp index 39735e8e0..9035ce61e 100644 --- a/test_regress/t/t_tri_top_en_out.cpp +++ b/test_regress/t/t_tri_top_en_out.cpp @@ -7,7 +7,7 @@ #include "verilated.h" #include "TestCheck.h" -#include "Vt_tri_top_en_out.h" +#include VM_PREFIX_INCLUDE #include @@ -18,7 +18,7 @@ int main(int argc, char** argv, char**) { const std::unique_ptr contextp{new VerilatedContext}; contextp->commandArgs(argc, argv); // Construct the Verilated model, from Vtop.h generated from Verilating - const std::unique_ptr topp{new Vt_tri_top_en_out{contextp.get()}}; + const std::unique_ptr topp{new VM_PREFIX{contextp.get()}}; // Initial input topp->drv_en = 0; diff --git a/test_regress/t/t_typedef_no_bad.out b/test_regress/t/t_typedef_no_bad.out index 1d17e5fc6..e1e4ceaf8 100644 --- a/test_regress/t/t_typedef_no_bad.out +++ b/test_regress/t/t_typedef_no_bad.out @@ -1,4 +1,4 @@ -%Error: t/t_typedef_no_bad.v:10:4: Can't find typedef: 'sometype' +%Error: t/t_typedef_no_bad.v:10:4: Can't find typedef/interface: 'sometype' 10 | sometype p; | ^~~~~~~~ %Error: Exiting due to diff --git a/test_regress/t/t_typename.out b/test_regress/t/t_typename.out index b95d23411..133f56582 100644 --- a/test_regress/t/t_typename.out +++ b/test_regress/t/t_typename.out @@ -14,6 +14,7 @@ "bit[2:0]" ==? "bit[2:0]" "int" ==? "int" "bit[9:1]" ==? "bit[9:1]" +"bit[9:1]" ==? "bit[9:1]" "string$[longint]" ==? "string$[longint]" "int$[$]" ==? "int$[$]" "int$[$:3]" ==? "int$[$:3]" diff --git a/test_regress/t/t_typename.v b/test_regress/t/t_typename.v index 624da2576..ea6c2d088 100644 --- a/test_regress/t/t_typename.v +++ b/test_regress/t/t_typename.v @@ -15,7 +15,8 @@ int signed Y; // "int" package A; enum {A,B,C=99} X; // "enum{A=32'sd0,B=32'sd1,C=32'sd99}A::e$1" - typedef bit [9:1'b1] word; // "A::bit[9:1]" + typedef bit [9:1'b1] word_t; // "A::bit[9:1]" + localparam type WORD_T = word_t; endpackage : A import A::*; @@ -31,6 +32,7 @@ module t(/*AUTOARG*/); real r; logic l; typedef bit mybit_t; + localparam type MYBIT_T = mybit_t; mybit_t [2:0] bitp20; mybit_t bitu32 [3:2]; mybit_t bitu31 [3:1][4:5]; @@ -69,7 +71,8 @@ module t(/*AUTOARG*/); `printtype(X, "bit[2:0]"); `printtype(Y, "int"); - `printtype(A::word, "bit[9:1]"); + `printtype(A::word_t, "bit[9:1]"); + `printtype(A::WORD_T, "bit[9:1]"); `printtype(assoc, "string$[longint]"); `printtype(q, "int$[$]"); `printtype(q3, "int$[$:3]"); // Some omit :3 - need it so != unbounded diff --git a/test_regress/t/t_unopt_combo_isolate.py b/test_regress/t/t_unopt_combo_isolate.py index c7f9f968d..641974899 100755 --- a/test_regress/t/t_unopt_combo_isolate.py +++ b/test_regress/t/t_unopt_combo_isolate.py @@ -20,23 +20,23 @@ if test.vlt_all: test.file_grep(test.stats, r'Optimizations, isolate_assignments blocks\s+3') test.file_grep( out_filename, - r'{"type":"VAR","name":"t.b",.*"loc":"e,23:[^"]*",.*"origName":"b",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' + r'{"type":"VAR","name":"t.b",.*"loc":"\w,23:[^"]*",.*"origName":"b",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"__Vfunc_t.file.get_31_16__0__Vfuncout",.*"loc":"e,99:[^"]*",.*"origName":"__Vfunc_t__DOT__file__DOT__get_31_16__0__Vfuncout",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' + r'{"type":"VAR","name":"__Vfunc_t.file.get_31_16__0__Vfuncout",.*"loc":"\w,99:[^"]*",.*"origName":"__Vfunc_t__DOT__file__DOT__get_31_16__0__Vfuncout",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"__Vfunc_t.file.get_31_16__0__t_crc",.*"loc":"e,100:[^"]*",.*"origName":"__Vfunc_t__DOT__file__DOT__get_31_16__0__t_crc",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' + r'{"type":"VAR","name":"__Vfunc_t.file.get_31_16__0__t_crc",.*"loc":"\w,100:[^"]*",.*"origName":"__Vfunc_t__DOT__file__DOT__get_31_16__0__t_crc",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"__Vtask_t.file.set_b_d__1__t_crc",.*"loc":"e,112:[^"]*",.*"origName":"__Vtask_t__DOT__file__DOT__set_b_d__1__t_crc",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' + r'{"type":"VAR","name":"__Vtask_t.file.set_b_d__1__t_crc",.*"loc":"\w,112:[^"]*",.*"origName":"__Vtask_t__DOT__file__DOT__set_b_d__1__t_crc",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"__Vtask_t.file.set_b_d__1__t_c",.*"loc":"e,113:[^"]*",.*"origName":"__Vtask_t__DOT__file__DOT__set_b_d__1__t_c",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' + r'{"type":"VAR","name":"__Vtask_t.file.set_b_d__1__t_c",.*"loc":"\w,113:[^"]*",.*"origName":"__Vtask_t__DOT__file__DOT__set_b_d__1__t_c",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' ) test.execute() diff --git a/test_regress/t/t_unopt_combo_isolate_vlt.py b/test_regress/t/t_unopt_combo_isolate_vlt.py index eab58591c..4f3a4988c 100755 --- a/test_regress/t/t_unopt_combo_isolate_vlt.py +++ b/test_regress/t/t_unopt_combo_isolate_vlt.py @@ -21,23 +21,23 @@ if test.vlt_all: test.file_grep(test.stats, r'Optimizations, isolate_assignments blocks\s+3') test.file_grep( out_filename, - r'{"type":"VAR","name":"t.b",.*"loc":"f,23:[^"]*",.*"origName":"b",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' + r'{"type":"VAR","name":"t.b",.*"loc":"\w,23:[^"]*",.*"origName":"b",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"__Vfunc_t.file.get_31_16__0__Vfuncout",.*"loc":"f,104:[^"]*",.*"origName":"__Vfunc_t__DOT__file__DOT__get_31_16__0__Vfuncout",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' + r'{"type":"VAR","name":"__Vfunc_t.file.get_31_16__0__Vfuncout",.*"loc":"\w,104:[^"]*",.*"origName":"__Vfunc_t__DOT__file__DOT__get_31_16__0__Vfuncout",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"__Vfunc_t.file.get_31_16__0__t_crc",.*"loc":"f,105:[^"]*",.*"origName":"__Vfunc_t__DOT__file__DOT__get_31_16__0__t_crc",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' + r'{"type":"VAR","name":"__Vfunc_t.file.get_31_16__0__t_crc",.*"loc":"\w,105:[^"]*",.*"origName":"__Vfunc_t__DOT__file__DOT__get_31_16__0__t_crc",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"__Vtask_t.file.set_b_d__1__t_crc",.*"loc":"f,115:[^"]*",.*"origName":"__Vtask_t__DOT__file__DOT__set_b_d__1__t_crc",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' + r'{"type":"VAR","name":"__Vtask_t.file.set_b_d__1__t_crc",.*"loc":"\w,115:[^"]*",.*"origName":"__Vtask_t__DOT__file__DOT__set_b_d__1__t_crc",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' ) test.file_grep( out_filename, - r'{"type":"VAR","name":"__Vtask_t.file.set_b_d__1__t_c",.*"loc":"f,116:[^"]*",.*"origName":"__Vtask_t__DOT__file__DOT__set_b_d__1__t_c",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' + r'{"type":"VAR","name":"__Vtask_t.file.set_b_d__1__t_c",.*"loc":"\w,116:[^"]*",.*"origName":"__Vtask_t__DOT__file__DOT__set_b_d__1__t_c",.*"attrIsolateAssign":true,.*"dtypeName":"logic"' ) test.execute() diff --git a/test_regress/t/t_unpacked_concat.v b/test_regress/t/t_unpacked_concat.v index 468518ab2..f1ca793b5 100644 --- a/test_regress/t/t_unpacked_concat.v +++ b/test_regress/t/t_unpacked_concat.v @@ -6,90 +6,90 @@ module t (/*AUTOARG*/); - typedef int AI3[1:3]; - AI3 A3; - int A9[1:9]; + typedef int ai3_t[1:3]; + ai3_t a3; + int a9[1:9]; logic [2:0] s0; logic [2:0] s1[1:3]; - logic [2:0] s2[3:1]; + logic [2:0] s1b[3:1]; logic [2:0] s3[2:8]; - logic [2:0] s4[8:2]; + logic [2:0] s3b[8:2]; initial begin s0 = 3'd1; s1[1] = 3'd2; s1[2] = 3'd3; s1[3] = 3'd4; - s2[1] = 3'd5; - s2[2] = 3'd6; - s2[3] = 3'd7; + s1b[1] = 3'd5; + s1b[2] = 3'd6; + s1b[3] = 3'd7; - A3 = '{1, 2, 3}; - A9 = {A3, 4, 5, A3, 6}; - if (A9[1] != 1) $stop; - if (A9[2] != 2) $stop; - if (A9[3] != 3) $stop; - if (A9[4] != 4) $stop; - if (A9[5] != 5) $stop; - if (A9[6] != 1) $stop; - if (A9[7] != 2) $stop; - if (A9[8] != 3) $stop; - if (A9[9] != 6) $stop; + a3 = '{1, 2, 3}; + a9 = {a3, 4, 5, a3, 6}; + if (a9[1] != 1) $stop; + if (a9[2] != 2) $stop; + if (a9[3] != 3) $stop; + if (a9[4] != 4) $stop; + if (a9[5] != 5) $stop; + if (a9[6] != 1) $stop; + if (a9[7] != 2) $stop; + if (a9[8] != 3) $stop; + if (a9[9] != 6) $stop; - s3 = {s0, s1, s2}; + s3 = {s0, s1, s1b}; if (s3[2] != s0) $stop; if (s3[3] != s1[1]) $stop; if (s3[4] != s1[2]) $stop; if (s3[5] != s1[3]) $stop; - if (s3[6] != s2[3]) $stop; - if (s3[7] != s2[2]) $stop; - if (s3[8] != s2[1]) $stop; + if (s3[6] != s1b[3]) $stop; + if (s3[7] != s1b[2]) $stop; + if (s3[8] != s1b[1]) $stop; - s3[2:8] = {s0, s1[1:2], s1[3], s2[3], s2[2:1]}; + s3[2:8] = {s0, s1[1:2], s1[3], s1b[3], s1b[2:1]}; if (s3[2] != s0) $stop; if (s3[3] != s1[1]) $stop; if (s3[4] != s1[2]) $stop; if (s3[5] != s1[3]) $stop; - if (s3[6] != s2[3]) $stop; - if (s3[7] != s2[2]) $stop; - if (s3[8] != s2[1]) $stop; + if (s3[6] != s1b[3]) $stop; + if (s3[7] != s1b[2]) $stop; + if (s3[8] != s1b[1]) $stop; - s3 = {s0, s1[1], s1[2:3], s2[3:2], s2[1]}; + s3 = {s0, s1[1], s1[2:3], s1b[3:2], s1b[1]}; if (s3[2] != s0) $stop; if (s3[3] != s1[1]) $stop; if (s3[4] != s1[2]) $stop; if (s3[5] != s1[3]) $stop; - if (s3[6] != s2[3]) $stop; - if (s3[7] != s2[2]) $stop; - if (s3[8] != s2[1]) $stop; + if (s3[6] != s1b[3]) $stop; + if (s3[7] != s1b[2]) $stop; + if (s3[8] != s1b[1]) $stop; - s4 = {s0, s1, s2}; - if (s4[8] != s0) $stop; - if (s4[7] != s1[1]) $stop; - if (s4[6] != s1[2]) $stop; - if (s4[5] != s1[3]) $stop; - if (s4[4] != s2[3]) $stop; - if (s4[3] != s2[2]) $stop; - if (s4[2] != s2[1]) $stop; + s3b = {s0, s1, s1b}; + if (s3b[8] != s0) $stop; + if (s3b[7] != s1[1]) $stop; + if (s3b[6] != s1[2]) $stop; + if (s3b[5] != s1[3]) $stop; + if (s3b[4] != s1b[3]) $stop; + if (s3b[3] != s1b[2]) $stop; + if (s3b[2] != s1b[1]) $stop; - s4[8:2] = {s0, s1[1:2], s1[3], s2[3], s2[2:1]}; - if (s4[8] != s0) $stop; - if (s4[7] != s1[1]) $stop; - if (s4[6] != s1[2]) $stop; - if (s4[5] != s1[3]) $stop; - if (s4[4] != s2[3]) $stop; - if (s4[3] != s2[2]) $stop; - if (s4[2] != s2[1]) $stop; + s3b[8:2] = {s0, s1[1:2], s1[3], s1b[3], s1b[2:1]}; + if (s3b[8] != s0) $stop; + if (s3b[7] != s1[1]) $stop; + if (s3b[6] != s1[2]) $stop; + if (s3b[5] != s1[3]) $stop; + if (s3b[4] != s1b[3]) $stop; + if (s3b[3] != s1b[2]) $stop; + if (s3b[2] != s1b[1]) $stop; - s4 = {s0, s1[1], s1[2:3], s2[3:2], s2[1]}; - if (s4[8] != s0) $stop; - if (s4[7] != s1[1]) $stop; - if (s4[6] != s1[2]) $stop; - if (s4[5] != s1[3]) $stop; - if (s4[4] != s2[3]) $stop; - if (s4[3] != s2[2]) $stop; - if (s4[2] != s2[1]) $stop; + s3b = {s0, s1[1], s1[2:3], s1b[3:2], s1b[1]}; + if (s3b[8] != s0) $stop; + if (s3b[7] != s1[1]) $stop; + if (s3b[6] != s1[2]) $stop; + if (s3b[5] != s1[3]) $stop; + if (s3b[4] != s1b[3]) $stop; + if (s3b[3] != s1b[2]) $stop; + if (s3b[2] != s1b[1]) $stop; $write("*-* All Finished *-*\n"); $finish; diff --git a/test_regress/t/t_unpacked_concat_bad.out b/test_regress/t/t_unpacked_concat_bad.out index 6b736d415..051187a46 100644 --- a/test_regress/t/t_unpacked_concat_bad.out +++ b/test_regress/t/t_unpacked_concat_bad.out @@ -3,4 +3,8 @@ 12 | localparam bit_int_t count_bits [1:0] = {2{$bits(count_t)}}; | ^ ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error: t/t_unpacked_concat_bad.v:12:46: Assignment pattern missed initializing elements: 0 + : ... note: In instance 't' + 12 | localparam bit_int_t count_bits [1:0] = {2{$bits(count_t)}}; + | ^ %Error: Exiting due to diff --git a/test_regress/t/t_unpacked_concat_bad3.out b/test_regress/t/t_unpacked_concat_bad3.out index 4bd30ce0c..f106250c0 100644 --- a/test_regress/t/t_unpacked_concat_bad3.out +++ b/test_regress/t/t_unpacked_concat_bad3.out @@ -1,4 +1,9 @@ -%Error: Internal Error: t/t_unpacked_concat_bad3.v:9:41: ../V3EmitCConstInit.h:#: Missing array init element +%Error: t/t_unpacked_concat_bad3.v:9:41: Assignment pattern missed initializing elements: 3 + : ... note: In instance 't' 9 | localparam logic [7:0] TOO_FEW [5] = '{0, 1, 2**8-1}; | ^~ - ... See the manual at https://verilator.org/verilator_doc.html for more assistance. +%Error: t/t_unpacked_concat_bad3.v:9:41: Assignment pattern missed initializing elements: 4 + : ... note: In instance 't' + 9 | localparam logic [7:0] TOO_FEW [5] = '{0, 1, 2**8-1}; + | ^~ +%Error: Exiting due to diff --git a/test_regress/t/t_unpacked_init.v b/test_regress/t/t_unpacked_init.v index ae7243ad1..e9d052a51 100644 --- a/test_regress/t/t_unpacked_init.v +++ b/test_regress/t/t_unpacked_init.v @@ -14,6 +14,8 @@ module t (/*AUTOARG*/); int a3[1] = '{16}; int a4[1] = {17}; + int a5[2][3] = '{'{10, 11, 12}, '{13, 14, 15}}; + initial begin `checkh(a1[0], 12); `checkh(a1[1], 13); @@ -25,6 +27,13 @@ module t (/*AUTOARG*/); `checkh(a4[0], 17); + `checkh(a5[0][0], 10); + `checkh(a5[0][1], 11); + `checkh(a5[0][2], 12); + `checkh(a5[1][0], 13); + `checkh(a5[1][1], 14); + `checkh(a5[1][2], 15); + $write("*-* All Finished *-*\n"); $finish; end diff --git a/test_regress/t/t_uvm_all.py b/test_regress/t/t_uvm_all.py index 790de6b74..ad9ecce9f 100755 --- a/test_regress/t/t_uvm_all.py +++ b/test_regress/t/t_uvm_all.py @@ -13,10 +13,7 @@ test.scenarios('vlt') test.compile( v_flags2=[ - "--binary --timing", # - "-Wno-PKGNODECL -Wno-IMPLICITSTATIC -Wno-MISINDENT", - "-Wno-CASEINCOMPLETE -Wno-CASTCONST -Wno-SYMRSVDWORD -Wno-WIDTHEXPAND -Wno-WIDTHTRUNC", - "-Wno-REALCVT", # TODO note mostly related to $realtime - could suppress or fix upstream + "--binary --timing +incdir+t/uvm", # "--error-limit 200 --debug-exit-uvm" ], verilator_make_gmake=False) diff --git a/test_regress/t/t_uvm_all.v b/test_regress/t/t_uvm_all.v index 594c95679..8ecaba7ed 100644 --- a/test_regress/t/t_uvm_all.v +++ b/test_regress/t/t_uvm_all.v @@ -6,7 +6,7 @@ `define UVM_NO_DPI -`include "t_uvm_pkg_all.vh" +`include "uvm_pkg_all.svh" module t(/*AUTOARG*/); diff --git a/test_regress/t/t_uvm_todo.py b/test_regress/t/t_uvm_todo.py index 91773036f..36429f86a 100755 --- a/test_regress/t/t_uvm_todo.py +++ b/test_regress/t/t_uvm_todo.py @@ -12,15 +12,9 @@ import multiprocessing test.scenarios('vlt') -test.compile( - v_flags2=[ - "--timing", # - "-Wno-PKGNODECL -Wno-IMPLICITSTATIC -Wno-MISINDENT", - "-Wno-CASEINCOMPLETE -Wno-CASTCONST -Wno-SYMRSVDWORD -Wno-WIDTHEXPAND -Wno-WIDTHTRUNC", - "-Wno-REALCVT" # TODO note mostly related to $realtime - could suppress or fix upstream - ], - make_flags=['-k -j ' + str(multiprocessing.cpu_count())], - verilator_make_gmake=False) +test.compile(v_flags2=["--timing", "+incdir+t/uvm", "t/t_uvm_todo.vlt"], + make_flags=['-k -j ' + str(multiprocessing.cpu_count())], + verilator_make_gmake=False) #test.execute() diff --git a/test_regress/t/t_uvm_todo.v b/test_regress/t/t_uvm_todo.v index c702f39f3..e77550344 100644 --- a/test_regress/t/t_uvm_todo.v +++ b/test_regress/t/t_uvm_todo.v @@ -6,7 +6,7 @@ `define UVM_NO_DPI -`include "t_uvm_pkg_todo.vh" +`include "uvm_pkg_todo.svh" module t(/*AUTOARG*/); diff --git a/test_regress/t/t_uvm_todo.vlt b/test_regress/t/t_uvm_todo.vlt new file mode 100644 index 000000000..d038688e3 --- /dev/null +++ b/test_regress/t/t_uvm_todo.vlt @@ -0,0 +1,7 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +`verilator_config diff --git a/test_regress/t/t_var_port_json_only.out b/test_regress/t/t_var_port_json_only.out index 0b45d1513..f136884c5 100644 --- a/test_regress/t/t_var_port_json_only.out +++ b/test_regress/t/t_var_port_json_only.out @@ -2,68 +2,68 @@ "modulesp": [ {"type":"MODULE","name":"mh2","addr":"(E)","loc":"d,18:8,18:11","origName":"mh2","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_inout_wire_integer","addr":"(F)","loc":"d,18:27,18:47","dtypep":"(G)","origName":"x_inout_wire_integer","isSc":false,"isPrimaryIO":false,"direction":"INOUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"integer","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_inout_wire_integer","addr":"(F)","loc":"d,18:27,18:47","dtypep":"(G)","origName":"x_inout_wire_integer","isSc":false,"isPrimaryIO":false,"direction":"INOUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"integer","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"activesp": []}, {"type":"MODULE","name":"mh5","addr":"(H)","loc":"d,24:8,24:11","origName":"mh5","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_input_wire_logic","addr":"(I)","loc":"d,24:19,24:37","dtypep":"(J)","origName":"x_input_wire_logic","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_input_wire_logic","addr":"(I)","loc":"d,24:19,24:37","dtypep":"(J)","origName":"x_input_wire_logic","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"activesp": []}, {"type":"MODULE","name":"mh6","addr":"(K)","loc":"d,26:8,26:11","origName":"mh6","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_input_var_logic","addr":"(L)","loc":"d,26:23,26:40","dtypep":"(J)","origName":"x_input_var_logic","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_input_var_logic","addr":"(L)","loc":"d,26:23,26:40","dtypep":"(J)","origName":"x_input_var_logic","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"activesp": []}, {"type":"MODULE","name":"mh7","addr":"(M)","loc":"d,28:8,28:11","origName":"mh7","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_input_var_integer","addr":"(N)","loc":"d,28:31,28:50","dtypep":"(G)","origName":"x_input_var_integer","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"integer","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_input_var_integer","addr":"(N)","loc":"d,28:31,28:50","dtypep":"(G)","origName":"x_input_var_integer","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"integer","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"activesp": []}, {"type":"MODULE","name":"mh8","addr":"(O)","loc":"d,30:8,30:11","origName":"mh8","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_output_wire_logic","addr":"(P)","loc":"d,30:20,30:39","dtypep":"(J)","origName":"x_output_wire_logic","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_output_wire_logic","addr":"(P)","loc":"d,30:20,30:39","dtypep":"(J)","origName":"x_output_wire_logic","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"activesp": []}, {"type":"MODULE","name":"mh9","addr":"(Q)","loc":"d,32:8,32:11","origName":"mh9","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_output_var_logic","addr":"(R)","loc":"d,32:24,32:42","dtypep":"(J)","origName":"x_output_var_logic","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_output_var_logic","addr":"(R)","loc":"d,32:24,32:42","dtypep":"(J)","origName":"x_output_var_logic","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"activesp": []}, {"type":"MODULE","name":"mh10","addr":"(S)","loc":"d,34:8,34:12","origName":"mh10","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_output_wire_logic_signed_p6","addr":"(T)","loc":"d,34:33,34:62","dtypep":"(U)","origName":"x_output_wire_logic_signed_p6","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_output_wire_logic_signed_p6","addr":"(T)","loc":"d,34:33,34:62","dtypep":"(U)","origName":"x_output_wire_logic_signed_p6","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"activesp": []}, {"type":"MODULE","name":"mh11","addr":"(V)","loc":"d,36:8,36:12","origName":"mh11","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_output_var_integer","addr":"(W)","loc":"d,36:28,36:48","dtypep":"(G)","origName":"x_output_var_integer","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"integer","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_output_var_integer","addr":"(W)","loc":"d,36:28,36:48","dtypep":"(G)","origName":"x_output_var_integer","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"integer","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"activesp": []}, {"type":"MODULE","name":"mh12","addr":"(X)","loc":"d,38:8,38:12","origName":"mh12","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_ref_logic_p6","addr":"(Y)","loc":"d,38:23,38:37","dtypep":"(Z)","origName":"x_ref_logic_p6","isSc":false,"isPrimaryIO":false,"direction":"REF","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_ref_logic_p6","addr":"(Y)","loc":"d,38:23,38:37","dtypep":"(Z)","origName":"x_ref_logic_p6","isSc":false,"isPrimaryIO":false,"direction":"REF","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"activesp": []}, {"type":"MODULE","name":"mh13","addr":"(AB)","loc":"d,40:8,40:12","origName":"mh13","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_ref_var_logic_u6","addr":"(BB)","loc":"d,40:17,40:35","dtypep":"(CB)","origName":"x_ref_var_logic_u6","isSc":false,"isPrimaryIO":false,"direction":"REF","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_ref_var_logic_u6","addr":"(BB)","loc":"d,40:17,40:35","dtypep":"(CB)","origName":"x_ref_var_logic_u6","isSc":false,"isPrimaryIO":false,"direction":"REF","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"activesp": []}, {"type":"MODULE","name":"mh17","addr":"(DB)","loc":"d,50:8,50:12","origName":"mh17","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_input_var_integer","addr":"(EB)","loc":"d,50:31,50:50","dtypep":"(G)","origName":"x_input_var_integer","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"integer","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"x_input_var_integer","addr":"(EB)","loc":"d,50:31,50:50","dtypep":"(G)","origName":"x_input_var_integer","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"integer","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, {"type":"VAR","name":"y_input_wire_logic","addr":"(FB)","loc":"d,50:57,50:75","dtypep":"(J)","origName":"y_input_wire_logic","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"WIRE","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"activesp": []}, {"type":"MODULE","name":"mh18","addr":"(GB)","loc":"d,52:8,52:12","origName":"mh18","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_output_var_logic","addr":"(HB)","loc":"d,52:24,52:42","dtypep":"(J)","origName":"x_output_var_logic","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"y_input_wire_logic","addr":"(IB)","loc":"d,52:50,52:68","dtypep":"(J)","origName":"y_input_wire_logic","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_output_var_logic","addr":"(HB)","loc":"d,52:24,52:42","dtypep":"(J)","origName":"x_output_var_logic","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"y_input_wire_logic","addr":"(IB)","loc":"d,52:50,52:68","dtypep":"(J)","origName":"y_input_wire_logic","isSc":false,"isPrimaryIO":false,"direction":"INPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"activesp": []}, {"type":"MODULE","name":"mh19","addr":"(JB)","loc":"d,54:8,54:12","origName":"mh19","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_output_wire_logic_signed_p6","addr":"(KB)","loc":"d,54:33,54:62","dtypep":"(U)","origName":"x_output_wire_logic_signed_p6","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"y_output_var_integer","addr":"(LB)","loc":"d,54:72,54:92","dtypep":"(G)","origName":"y_output_var_integer","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"integer","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_output_wire_logic_signed_p6","addr":"(KB)","loc":"d,54:33,54:62","dtypep":"(U)","origName":"x_output_wire_logic_signed_p6","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"y_output_var_integer","addr":"(LB)","loc":"d,54:72,54:92","dtypep":"(G)","origName":"y_output_var_integer","isSc":false,"isPrimaryIO":false,"direction":"OUTPUT","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"integer","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"activesp": []}, {"type":"MODULE","name":"mh20","addr":"(MB)","loc":"d,56:8,56:12","origName":"mh20","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"x_ref_var_logic_p6","addr":"(NB)","loc":"d,56:23,56:41","dtypep":"(Z)","origName":"x_ref_var_logic_p6","isSc":false,"isPrimaryIO":false,"direction":"REF","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"y_ref_var_logic_p6","addr":"(OB)","loc":"d,56:43,56:61","dtypep":"(Z)","origName":"y_ref_var_logic_p6","isSc":false,"isPrimaryIO":false,"direction":"REF","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"x_ref_var_logic_p6","addr":"(NB)","loc":"d,56:23,56:41","dtypep":"(Z)","origName":"x_ref_var_logic_p6","isSc":false,"isPrimaryIO":false,"direction":"REF","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"y_ref_var_logic_p6","addr":"(OB)","loc":"d,56:43,56:61","dtypep":"(Z)","origName":"y_ref_var_logic_p6","isSc":false,"isPrimaryIO":false,"direction":"REF","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"activesp": []}, {"type":"MODULE","name":"mh21","addr":"(PB)","loc":"d,58:8,58:12","origName":"mh21","level":0,"modPublic":false,"inLibrary":false,"dead":false,"recursiveClone":false,"recursive":false,"timeunit":"1ps","inlinesp": [], "stmtsp": [ - {"type":"VAR","name":"ref_var_logic_u6","addr":"(QB)","loc":"d,58:17,58:33","dtypep":"(RB)","origName":"ref_var_logic_u6","isSc":false,"isPrimaryIO":false,"direction":"REF","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, - {"type":"VAR","name":"y_ref_var_logic","addr":"(SB)","loc":"d,58:41,58:56","dtypep":"(J)","origName":"y_ref_var_logic","isSc":false,"isPrimaryIO":false,"direction":"REF","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"NONE","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} + {"type":"VAR","name":"ref_var_logic_u6","addr":"(QB)","loc":"d,58:17,58:33","dtypep":"(RB)","origName":"ref_var_logic_u6","isSc":false,"isPrimaryIO":false,"direction":"REF","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []}, + {"type":"VAR","name":"y_ref_var_logic","addr":"(SB)","loc":"d,58:41,58:56","dtypep":"(J)","origName":"y_ref_var_logic","isSc":false,"isPrimaryIO":false,"direction":"REF","isConst":false,"isPullup":false,"isPulldown":false,"isUsedClock":false,"isSigPublic":false,"isLatched":false,"isUsedLoopIdx":false,"noReset":false,"attrIsolateAssign":false,"attrFileDescr":false,"isDpiOpenArray":false,"isFuncReturn":false,"isFuncLocal":false,"attrClocker":"UNKNOWN","lifetime":"VSTATIC","varType":"PORT","dtypeName":"logic","isSigUserRdPublic":false,"isSigUserRWPublic":false,"isGParam":false,"isParam":false,"attrScBv":false,"attrSFormat":false,"sensIfacep":"UNLINKED","childDTypep": [],"delayp": [],"valuep": [],"attrsp": []} ],"activesp": []} ],"filesp": [], "miscsp": [ diff --git a/test_regress/t/t_var_static_assign_decl_bad.out b/test_regress/t/t_var_static_assign_decl_bad.out index 7ca2970b1..b296e1482 100644 --- a/test_regress/t/t_var_static_assign_decl_bad.out +++ b/test_regress/t/t_var_static_assign_decl_bad.out @@ -63,4 +63,8 @@ : is dependent on function/task I/O variable 49 | logic tmp = in; | ^~ +%Error-UNSUPPORTED: t/t_var_static_assign_decl_bad.v:72:17: Static variable initializer + : is dependent on function/task I/O variable + 72 | logic tmp = in; + | ^~ %Error: Exiting due to diff --git a/test_regress/t/t_varref_scope_in_interface.py b/test_regress/t/t_varref_scope_in_interface.py new file mode 100755 index 000000000..fbe7b466b --- /dev/null +++ b/test_regress/t/t_varref_scope_in_interface.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.lint(verilator_flags2=["--lint-only", "--timing"]) + +test.passes() diff --git a/test_regress/t/t_varref_scope_in_interface.v b/test_regress/t/t_varref_scope_in_interface.v new file mode 100755 index 000000000..d030b5c13 --- /dev/null +++ b/test_regress/t/t_varref_scope_in_interface.v @@ -0,0 +1,22 @@ +// 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 + +interface iface #(parameter DWIDTH = 32)(); + localparam TOTAL_PACKED_WIDTH = DWIDTH + 1; + modport Tx(output sop, data, import unpack); + logic sop; + logic [DWIDTH - 1:0] data = '0; + + task static unpack(input logic [TOTAL_PACKED_WIDTH-1:0] packed_in, input logic sop_i); + logic sop_nc; + {data, sop_nc} <= packed_in; + sop <= sop_i; + endtask +endinterface + +module t; +iface ifc(); +endmodule diff --git a/test_regress/t/t_vlprocess_missing.py b/test_regress/t/t_vlprocess_missing.py new file mode 100755 index 000000000..35076ad18 --- /dev/null +++ b/test_regress/t/t_vlprocess_missing.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('simulator') +test.top_filename = test.obj_dir + "/t_vlprocess_missing.v" + +# Number of tests to generate +NUM_TESTS = 200 + +# Testbench header template +HEADER = """\ +module Testbench; + + logic clk; + logic reset; + + // Clock driver + initial begin + clk = 0; + forever begin + #5 clk = ~clk; + end + end + + task automatic advance_clock(int n = 1); + repeat (n) @(posedge clk); + endtask + +""" + +# Test task template +TEST_TASK_TEMPLATE = """ + task automatic test_{num}(); + int counter = 0; + int expected_value = {num}; + + // Timeout wait + fork + begin + advance_clock(10000); + $error("Timeout"); + end + join_none + wait (counter == expected_value); + disable fork; + + while (counter < expected_value) begin + advance_clock(); + counter++; + end + endtask +""" + +# Testbench footer template +FOOTER = " initial begin" + +# Call template for invoking each test task +CALL_TEMPLATE = " test_{num}();\n" + +# Footer end +FOOTER_END = """ + $finish; + end + +endmodule +""" + + +def gen(filename, num_tests): + """ + Generates a SystemVerilog testbench with the specified number of tests. + + Args: + filename (str): The output file name for the generated testbench. + num_tests (int): The number of test tasks to generate. + """ + with open(filename, 'w', encoding="utf-8") as fh: + fh.write("// Generated by t_vlprocess_missing.py\n") + + # Write the header + fh.write(HEADER) + + # Generate the test tasks + for i in range(1, num_tests + 1): + fh.write(TEST_TASK_TEMPLATE.format(num=i)) + + # Write the initial block with test calls + fh.write(FOOTER) + for i in range(1, num_tests + 1): + fh.write(CALL_TEMPLATE.format(num=i)) + fh.write(FOOTER_END) + + +gen(test.top_filename, NUM_TESTS) + +test.compile(verilator_flags2=["--binary"]) + +test.passes() diff --git a/test_regress/t/t_vlt_match_contents.out b/test_regress/t/t_vlt_match_contents.out new file mode 100644 index 000000000..4867ea0bc --- /dev/null +++ b/test_regress/t/t_vlt_match_contents.out @@ -0,0 +1,7 @@ +%Warning-UNUSEDSIGNAL: t/t_vlt_match_contents.v:11:10: Signal is not driven, nor used: 'usignal_contents_mismatch' + : ... note: In instance 't' + 11 | logic usignal_contents_mismatch; + | ^~~~~~~~~~~~~~~~~~~~~~~~~ + ... For warning description see https://verilator.org/warn/UNUSEDSIGNAL?v=latest + ... Use "/* verilator lint_off UNUSEDSIGNAL */" and lint_on around source to disable this message. +%Error: Exiting due to diff --git a/test_regress/t/t_vlt_match_contents.py b/test_regress/t/t_vlt_match_contents.py new file mode 100755 index 000000000..3c4174c36 --- /dev/null +++ b/test_regress/t/t_vlt_match_contents.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('vlt') + +test.lint(verilator_flags2=["--lint-only -Wall t/t_vlt_match_contents.vlt"], + fails=True, + expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_vlt_match_contents.v b/test_regress/t/t_vlt_match_contents.v new file mode 100644 index 000000000..dc1c5d6fe --- /dev/null +++ b/test_regress/t/t_vlt_match_contents.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, 2024 by Ethan Sifferman. +// SPDX-License-Identifier: CC0-1.0 + +string MATCH_VERSION = "10.20"; + +module t; + logic usignal_contents_suppress; // Suppressed with -contents + logic usignal_contents_mismatch; // Doesn't match -contents +endmodule diff --git a/test_regress/t/t_vlt_match_contents.vlt b/test_regress/t/t_vlt_match_contents.vlt new file mode 100644 index 000000000..e568f5af0 --- /dev/null +++ b/test_regress/t/t_vlt_match_contents.vlt @@ -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, 2024 by Ethan Sifferman. +// SPDX-License-Identifier: CC0-1.0 + +`verilator_config + +lint_off -rule DECLFILENAME -file "*/t_vlt_match_contents.v" -contents "* MATCH_VERSION*" +lint_off -rule UNUSEDSIGNAL -file "*/t_vlt_match_contents.v" -contents "* MATCH_VERSION*" -match "*MATCH_VERSION*" +lint_off -rule UNUSEDSIGNAL -file "*/t_vlt_match_contents.v" -contents "* MATCH_VERSION*" -match "*usignal_contents_suppress*" +lint_off -rule UNUSEDSIGNAL -file "*/t_vlt_match_contents.v" -contents "* NOT_VERSION*" -match "*usignal_contents_mismatch*" diff --git a/test_regress/t/t_vpi_const_type.cpp b/test_regress/t/t_vpi_const_type.cpp index 6c4c25339..ac8ebd2db 100644 --- a/test_regress/t/t_vpi_const_type.cpp +++ b/test_regress/t/t_vpi_const_type.cpp @@ -35,38 +35,6 @@ #include "TestSimulator.h" #include "TestVpi.h" -// __FILE__ is too long -#define FILENM "t_vpi_const_type.cpp" - -#define DEBUG \ - if (0) printf - -#define CHECK_RESULT_NZ(got) \ - if (!(got)) { \ - printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM, __LINE__); \ - return __LINE__; \ - } - -#define CHECK_RESULT_Z(got) \ - if (got) { \ - printf("%%Error: %s:%d: GOT = !NULL EXP = NULL\n", FILENM, __LINE__); \ - return __LINE__; \ - } - -#define CHECK_RESULT(got, exp) \ - if ((got) != (exp)) { \ - std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << ": GOT = " << (got) \ - << " EXP = " << (exp) << std::endl; \ - return __LINE__; \ - } - -#define CHECK_RESULT_CSTR(got, exp) \ - if (std::strcmp((got), (exp))) { \ - printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \ - (got) ? (got) : "", (exp) ? (exp) : ""); \ - return __LINE__; \ - } - extern "C" { int mon_check() { #ifdef TEST_VERBOSE diff --git a/test_regress/t/t_vpi_escape.cpp b/test_regress/t/t_vpi_escape.cpp index 043a62a5d..73b7875fd 100644 --- a/test_regress/t/t_vpi_escape.cpp +++ b/test_regress/t/t_vpi_escape.cpp @@ -132,9 +132,19 @@ int _mon_check_iter() { TEST_CHECK_CSTR(p, "\\mod.with_dot "); if (TestSimulator::is_verilator()) { p = vpi_get_str(vpiDefName, vh2); - TEST_CHECK_CSTR(p, ""); // Unsupported + TEST_CHECK_CSTR(p, "sub"); } + TestVpiHandle vh_null_name = MY_VPI_HANDLE("___0_"); + TEST_CHECK_NZ(vh_null_name); + p = vpi_get_str(vpiName, vh_null_name); + TEST_CHECK_CSTR(p, "___0_"); + + TestVpiHandle vh_hex_name = MY_VPI_HANDLE("___0F_"); + TEST_CHECK_NZ(vh_hex_name); + p = vpi_get_str(vpiName, vh_hex_name); + TEST_CHECK_CSTR(p, "___0F_"); + TestVpiHandle vh10 = vpi_iterate(vpiReg, vh2); TEST_CHECK_NZ(vh10); TEST_CHECK_EQ(vpi_get(vpiType, vh10), vpiIterator); diff --git a/test_regress/t/t_vpi_escape.v b/test_regress/t/t_vpi_escape.v index b575dc199..a912c1096 100644 --- a/test_regress/t/t_vpi_escape.v +++ b/test_regress/t/t_vpi_escape.v @@ -63,6 +63,10 @@ extern "C" int mon_check(); sub \mod.with_dot (.cyc(cyc)); + // Check if scope names are not decoded twice + sub ___0F_ (.cyc(cyc)); + sub ___0_ (.cyc(cyc)); + initial begin `ifdef VERILATOR diff --git a/test_regress/t/t_vpi_get.cpp b/test_regress/t/t_vpi_get.cpp index 1d63845b4..021d761b6 100644 --- a/test_regress/t/t_vpi_get.cpp +++ b/test_regress/t/t_vpi_get.cpp @@ -35,50 +35,11 @@ #include "TestSimulator.h" #include "TestVpi.h" -// __FILE__ is too long -#define FILENM "t_vpi_get.cpp" - #define TEST_MSG \ if (0) printf //====================================================================== -#define CHECK_RESULT_VH(got, exp) \ - if ((got) != (exp)) { \ - printf("%%Error: %s:%d: GOT = %p EXP = %p\n", FILENM, __LINE__, (got), (exp)); \ - return __LINE__; \ - } - -#define CHECK_RESULT_NZ(got) \ - if (!(got)) { \ - printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM, __LINE__); \ - return __LINE__; \ - } - -// Use cout to avoid issues with %d/%lx etc -#define CHECK_RESULT(got, exp) \ - if ((got) != (exp)) { \ - std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << ": GOT = " << (got) \ - << " EXP = " << (exp) << std::endl; \ - return __LINE__; \ - } - -#define CHECK_RESULT_HEX(got, exp) \ - if ((got) != (exp)) { \ - std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << std::hex \ - << ": GOT = " << (got) << " EXP = " << (exp) << std::endl; \ - return __LINE__; \ - } - -#define CHECK_RESULT_CSTR(got, exp) \ - if (std::strcmp((got), (exp))) { \ - printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \ - (got) ? (got) : "", (exp) ? (exp) : ""); \ - return __LINE__; \ - } - -#define CHECK_RESULT_CSTR_STRIP(got, exp) CHECK_RESULT_CSTR(got + strspn(got, " "), exp) - static int _mon_check_props(TestVpiHandle& handle, int size, int direction, int scalar, int type) { s_vpi_value value; value.format = vpiIntVal; diff --git a/test_regress/t/t_vpi_memory.cpp b/test_regress/t/t_vpi_memory.cpp index 9ef3fbe97..e61cf737a 100644 --- a/test_regress/t/t_vpi_memory.cpp +++ b/test_regress/t/t_vpi_memory.cpp @@ -36,9 +36,6 @@ #include "TestSimulator.h" #include "TestVpi.h" -// __FILE__ is too long -#define FILENM "t_vpi_memory.cpp" - #define DEBUG \ if (0) printf diff --git a/test_regress/t/t_vpi_module.cpp b/test_regress/t/t_vpi_module.cpp index 955464d11..a0a3c030f 100644 --- a/test_regress/t/t_vpi_module.cpp +++ b/test_regress/t/t_vpi_module.cpp @@ -35,38 +35,9 @@ #include "TestSimulator.h" #include "TestVpi.h" -// __FILE__ is too long -#define FILENM "t_vpi_module.cpp" - #define DEBUG \ if (0) printf -#define CHECK_RESULT_NZ(got) \ - if (!(got)) { \ - printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM, __LINE__); \ - return __LINE__; \ - } - -#define CHECK_RESULT_Z(got) \ - if (got) { \ - printf("%%Error: %s:%d: GOT = !NULL EXP = NULL\n", FILENM, __LINE__); \ - return __LINE__; \ - } - -#define CHECK_RESULT(got, exp) \ - if ((got) != (exp)) { \ - std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << ": GOT = " << (got) \ - << " EXP = " << (exp) << std::endl; \ - return __LINE__; \ - } - -#define CHECK_RESULT_CSTR(got, exp) \ - if (std::strcmp((got), (exp))) { \ - printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \ - (got) ? (got) : "", (exp) ? (exp) : ""); \ - return __LINE__; \ - } - void modDump(const TestVpiHandle& it, int n) { while (TestVpiHandle hndl = vpi_scan(it)) { const char* nm = vpi_get_str(vpiName, hndl); diff --git a/test_regress/t/t_vpi_module_empty.cpp b/test_regress/t/t_vpi_module_empty.cpp index 139ff4cce..f08ebb27d 100644 --- a/test_regress/t/t_vpi_module_empty.cpp +++ b/test_regress/t/t_vpi_module_empty.cpp @@ -35,18 +35,6 @@ #include "TestSimulator.h" #include "TestVpi.h" -// __FILE__ is too long -#define FILENM "t_vpi_module_empty.cpp" - -#define DEBUG \ - if (0) printf - -#define CHECK_RESULT_NZ(got) \ - if (!(got)) { \ - printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM, __LINE__); \ - return __LINE__; \ - } - extern "C" { int mon_check() { #ifdef TEST_VERBOSE diff --git a/test_regress/t/t_vpi_onetime_cbs.cpp b/test_regress/t/t_vpi_onetime_cbs.cpp index dfd0106ed..4e4222967 100644 --- a/test_regress/t/t_vpi_onetime_cbs.cpp +++ b/test_regress/t/t_vpi_onetime_cbs.cpp @@ -54,22 +54,6 @@ bool verbose = true; 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 diff --git a/test_regress/t/t_vpi_package.cpp b/test_regress/t/t_vpi_package.cpp index 7d16c2283..4feb00a48 100644 --- a/test_regress/t/t_vpi_package.cpp +++ b/test_regress/t/t_vpi_package.cpp @@ -35,38 +35,6 @@ #include "TestSimulator.h" #include "TestVpi.h" -// __FILE__ is too long -#define FILENM "t_vpi_package.cpp" - -#define DEBUG \ - if (0) printf - -#define CHECK_RESULT_NZ(got) \ - if (!(got)) { \ - printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM, __LINE__); \ - return __LINE__; \ - } - -#define CHECK_RESULT_Z(got) \ - if (got) { \ - printf("%%Error: %s:%d: GOT = !NULL EXP = NULL\n", FILENM, __LINE__); \ - return __LINE__; \ - } - -#define CHECK_RESULT(got, exp) \ - if ((got) != (exp)) { \ - std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << ": GOT = " << (got) \ - << " EXP = " << (exp) << std::endl; \ - return __LINE__; \ - } - -#define CHECK_RESULT_CSTR(got, exp) \ - if (std::strcmp((got), (exp))) { \ - printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \ - (got) ? (got) : "", (exp) ? (exp) : ""); \ - return __LINE__; \ - } - extern "C" { int count_params(TestVpiHandle& handle, int expectedParams) { TestVpiHandle it = vpi_iterate(vpiParameter, handle); diff --git a/test_regress/t/t_vpi_param.cpp b/test_regress/t/t_vpi_param.cpp index 1f2c5d434..d5700b10a 100644 --- a/test_regress/t/t_vpi_param.cpp +++ b/test_regress/t/t_vpi_param.cpp @@ -42,50 +42,6 @@ #include "TestSimulator.h" #include "TestVpi.h" -// __FILE__ is too long -#define FILENM "t_vpi_param.cpp" - -#define DEBUG \ - if (0) printf - -//====================================================================== - -#define CHECK_RESULT_VH(got, exp) \ - if ((got) != (exp)) { \ - printf("%%Error: %s:%d: GOT = %p EXP = %p\n", FILENM, __LINE__, (got), (exp)); \ - return __LINE__; \ - } - -#define CHECK_RESULT_NZ(got) \ - if (!(got)) { \ - printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM, __LINE__); \ - return __LINE__; \ - } - -// Use cout to avoid issues with %d/%lx etc -#define CHECK_RESULT(got, exp) \ - if ((got) != (exp)) { \ - std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << ": GOT = " << (got) \ - << " EXP = " << (exp) << std::endl; \ - return __LINE__; \ - } - -#define CHECK_RESULT_HEX(got, exp) \ - if ((got) != (exp)) { \ - std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << std::hex \ - << ": GOT = " << (got) << " EXP = " << (exp) << std::endl; \ - return __LINE__; \ - } - -#define CHECK_RESULT_CSTR(got, exp) \ - if (std::strcmp((got), (exp))) { \ - printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \ - (got) ? (got) : "", (exp) ? (exp) : ""); \ - return __LINE__; \ - } - -#define CHECK_RESULT_CSTR_STRIP(got, exp) CHECK_RESULT_CSTR(got + strspn(got, " "), exp) - int check_param_int(std::string name, PLI_INT32 format, int exp_value, bool verbose) { int vpi_type; TestVpiHandle param_h; diff --git a/test_regress/t/t_vpi_public_depth.cpp b/test_regress/t/t_vpi_public_depth.cpp index ee1217bd4..cb4da699c 100644 --- a/test_regress/t/t_vpi_public_depth.cpp +++ b/test_regress/t/t_vpi_public_depth.cpp @@ -41,38 +41,6 @@ #include "TestSimulator.h" #include "TestVpi.h" -// __FILE__ is too long -#define FILENM "t_vpi_public_depth.cpp" - -#define DEBUG \ - if (0) printf - -#define CHECK_RESULT_NZ(got) \ - if (!(got)) { \ - printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM, __LINE__); \ - return __LINE__; \ - } - -#define CHECK_RESULT_Z(got) \ - if (got) { \ - printf("%%Error: %s:%d: GOT = !NULL EXP = NULL\n", FILENM, __LINE__); \ - return __LINE__; \ - } - -#define CHECK_RESULT(got, exp) \ - if ((got) != (exp)) { \ - std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << ": GOT = " << (got) \ - << " EXP = " << (exp) << std::endl; \ - return __LINE__; \ - } - -#define CHECK_RESULT_CSTR(got, exp) \ - if (std::strcmp((got), (exp))) { \ - printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \ - (got) ? (got) : "", (exp) ? (exp) : ""); \ - return __LINE__; \ - } - void modDump(const TestVpiHandle& it, int n) { while (TestVpiHandle hndl = vpi_scan(it)) { const char* nm = vpi_get_str(vpiName, hndl); diff --git a/test_regress/t/t_vpi_repetitive_cbs.cpp b/test_regress/t/t_vpi_repetitive_cbs.cpp index aa4c0c204..2cae4f7c5 100644 --- a/test_regress/t/t_vpi_repetitive_cbs.cpp +++ b/test_regress/t/t_vpi_repetitive_cbs.cpp @@ -71,22 +71,6 @@ bool verbose = false; #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; \ - END_TEST \ - } - -// 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; \ - END_TEST \ - } - #define STRINGIFY_CB_CASE(_cb) \ case _cb: return #_cb diff --git a/test_regress/t/t_vpi_unimpl.cpp b/test_regress/t/t_vpi_unimpl.cpp index 5b85a38e8..c6d73f324 100644 --- a/test_regress/t/t_vpi_unimpl.cpp +++ b/test_regress/t/t_vpi_unimpl.cpp @@ -22,58 +22,10 @@ // These require the above. Comment prevents clang-format moving them #include "TestVpi.h" -// __FILE__ is too long -#define FILENM "t_vpi_unimpl.cpp" - -#define DEBUG \ - if (0) printf - unsigned int callback_count = 0; //====================================================================== -#define CHECK_RESULT_VH(got, exp) \ - if ((got) != (exp)) { \ - printf("%%Error: %s:%d: GOT = %p EXP = %p\n", FILENM, __LINE__, (got), (exp)); \ - return __LINE__; \ - } - -#define CHECK_RESULT_NZ(got) \ - if (!(got)) { \ - printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM, __LINE__); \ - return __LINE__; \ - } - -#define CHECK_RESULT_Z(got) \ - if (got) { \ - printf("%%Error: %s:%d: GOT = !NULL EXP = NULL\n", FILENM, __LINE__); \ - return __LINE__; \ - } - -// Use cout to avoid issues with %d/%lx etc -#define CHECK_RESULT(got, exp) \ - if ((got) != (exp)) { \ - std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << ": GOT = " << (got) \ - << " EXP = " << (exp) << std::endl; \ - return __LINE__; \ - } - -#define CHECK_RESULT_HEX(got, exp) \ - if ((got) != (exp)) { \ - std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << std::hex \ - << ": GOT = " << (got) << " EXP = " << (exp) << std::endl; \ - return __LINE__; \ - } - -#define CHECK_RESULT_CSTR(got, exp) \ - if (std::strcmp((got), (exp))) { \ - printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \ - (got) ? (got) : "", (exp) ? (exp) : ""); \ - return __LINE__; \ - } - -#define CHECK_RESULT_CSTR_STRIP(got, exp) CHECK_RESULT_CSTR(got + strspn(got, " "), exp) - int _mon_check_unimpl(p_cb_data cb_data) { static TestVpiHandle cb, clk_h; vpiHandle handle; diff --git a/test_regress/t/t_vpi_var.cpp b/test_regress/t/t_vpi_var.cpp index 8f4189271..db721c306 100644 --- a/test_regress/t/t_vpi_var.cpp +++ b/test_regress/t/t_vpi_var.cpp @@ -34,6 +34,10 @@ #endif +#ifdef VERILATOR +#include "verilated.h" +#endif + #include #include #include @@ -46,8 +50,6 @@ #include "TestVpi.h" int errors = 0; -// __FILE__ is too long -#define FILENM "t_vpi_var.cpp" #define TEST_MSG \ if (0) printf @@ -61,48 +63,6 @@ unsigned int callback_count_strs_max = 500; //====================================================================== -#define CHECK_RESULT_VH(got, exp) \ - if ((got) != (exp)) { \ - printf("%%Error: %s:%d: GOT = %p EXP = %p\n", FILENM, __LINE__, (got), (exp)); \ - return __LINE__; \ - } - -#define CHECK_RESULT_NZ(got) \ - if (!(got)) { \ - printf("%%Error: %s:%d: GOT = NULL EXP = !NULL\n", FILENM, __LINE__); \ - return __LINE__; \ - } - -#define CHECK_RESULT_Z(got) \ - if ((got)) { \ - printf("%%Error: %s:%d: GOT = !NULL EXP = NULL\n", FILENM, __LINE__); \ - return __LINE__; \ - } - -// Use cout to avoid issues with %d/%lx etc -#define CHECK_RESULT(got, exp) \ - if ((got) != (exp)) { \ - std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << ": GOT = " << (got) \ - << " EXP = " << (exp) << std::endl; \ - return __LINE__; \ - } - -#define CHECK_RESULT_HEX(got, exp) \ - if ((got) != (exp)) { \ - std::cout << std::dec << "%Error: " << FILENM << ":" << __LINE__ << std::hex \ - << ": GOT = " << (got) << " EXP = " << (exp) << std::endl; \ - return __LINE__; \ - } - -#define CHECK_RESULT_CSTR(got, exp) \ - if (std::strcmp((got), (exp))) { \ - printf("%%Error: %s:%d: GOT = '%s' EXP = '%s'\n", FILENM, __LINE__, \ - ((got) != NULL) ? (got) : "", ((exp) != NULL) ? (exp) : ""); \ - return __LINE__; \ - } - -#define CHECK_RESULT_CSTR_STRIP(got, exp) CHECK_RESULT_CSTR(got + strspn(got, " "), exp) - // We cannot replace those with VL_STRINGIFY, not available when PLI is build #define STRINGIFY(x) STRINGIFY2(x) #define STRINGIFY2(x) #x @@ -253,6 +213,29 @@ int _mon_check_value_callbacks() { return 0; } +int _mon_check_too_big() { +#ifdef VERILATOR + s_vpi_value v; + v.format = vpiVectorVal; + + TestVpiHandle h = VPI_HANDLE("too_big"); + CHECK_RESULT_NZ(h); + + Verilated::fatalOnVpiError(false); + vpi_get_value(h, &v); + Verilated::fatalOnVpiError(true); + s_vpi_error_info info; + CHECK_RESULT_NZ(vpi_chk_error(&info)); + + v.format = vpiStringVal; + vpi_get_value(h, &v); + CHECK_RESULT_Z(vpi_chk_error(nullptr)); + CHECK_RESULT_CSTR_STRIP(v.value.str, "some text"); +#endif + + return 0; +} + int _mon_check_var() { TestVpiHandle vh1 = VPI_HANDLE("onebit"); CHECK_RESULT_NZ(vh1); @@ -378,6 +361,16 @@ int _mon_check_var() { CHECK_RESULT_CSTR(p, "vpiConstant"); } + // C++ keyword collision + { + TestVpiHandle vh10 = VPI_HANDLE("nullptr"); + CHECK_RESULT_NZ(vh10); + vpi_get_value(vh10, &tmpValue); + CHECK_RESULT(tmpValue.value.integer, 123); + p = vpi_get_str(vpiType, vh10); + CHECK_RESULT_CSTR(p, "vpiParameter"); + } + // non-integer variables tmpValue.format = vpiRealVal; { @@ -416,7 +409,7 @@ int _mon_check_varlist() { CHECK_RESULT_CSTR(p, "sub"); if (TestSimulator::is_verilator()) { p = vpi_get_str(vpiDefName, vh2); - CHECK_RESULT_CSTR(p, ""); // Unsupported + CHECK_RESULT_CSTR(p, "sub"); } TestVpiHandle vh10 = vpi_iterate(vpiReg, vh2); @@ -935,6 +928,7 @@ extern "C" int mon_check() { if (int status = _mon_check_putget_str(NULL)) return status; if (int status = _mon_check_vlog_info()) return status; if (int status = _mon_check_delayed()) return status; + if (int status = _mon_check_too_big()) return status; #ifndef IS_VPI VerilatedVpi::selfTest(); #endif diff --git a/test_regress/t/t_vpi_var.py b/test_regress/t/t_vpi_var.py index 14985718b..610e7454d 100755 --- a/test_regress/t/t_vpi_var.py +++ b/test_regress/t/t_vpi_var.py @@ -17,7 +17,7 @@ test.compile(make_top_shell=False, sim_time=2100, iv_flags2=["-g2005-sv -D USE_VPI_NOT_DPI -DWAVES"], v_flags2=["+define+USE_VPI_NOT_DPI"], - verilator_flags2=["--exe --vpi --no-l2name", test.pli_filename]) + verilator_flags2=["-Wno-SYMRSVDWORD --exe --vpi --no-l2name", test.pli_filename]) test.execute(use_libvpi=True, all_run_flags=['+PLUS +INT=1234 +STRSTR']) diff --git a/test_regress/t/t_vpi_var.v b/test_regress/t/t_vpi_var.v index 8828b1776..d93196cc9 100644 --- a/test_regress/t/t_vpi_var.v +++ b/test_regress/t/t_vpi_var.v @@ -49,11 +49,15 @@ extern "C" int mon_check(); reg [31:0] text_word /*verilator public_flat_rw @(posedge clk) */; reg [63:0] text_long /*verilator public_flat_rw @(posedge clk) */; reg [511:0] text /*verilator public_flat_rw @(posedge clk) */; + reg [2047:0] too_big /*verilator public_flat_rw @(posedge clk) */; integer status; real real1 /*verilator public_flat_rw */; string str1 /*verilator public_flat_rw */; + // specifically public and not public_flat_rw here so as to induce the C++ + // keyword collision + localparam int nullptr /*verilator public */ = 123; sub sub(); @@ -68,6 +72,7 @@ extern "C" int mon_check(); text_word = "Word"; text_long = "Long64b"; text = "Verilog Test module"; + too_big = "some text"; real1 = 1.0; str1 = "hello"; diff --git a/test_regress/t/t_vpi_var2.py b/test_regress/t/t_vpi_var2.py index 478afcebb..62511e4cb 100755 --- a/test_regress/t/t_vpi_var2.py +++ b/test_regress/t/t_vpi_var2.py @@ -18,7 +18,7 @@ test.compile(make_top_shell=False, sim_time=2100, iv_flags2=["-g2005-sv -D USE_VPI_NOT_DPI -DWAVES -DT_VPI_VAR2"], v_flags2=["+define+USE_VPI_NOT_DPI"], - verilator_flags2=["--exe --vpi --no-l2name", test.pli_filename]) + verilator_flags2=["-Wno-SYMRSVDWORD --exe --vpi --no-l2name", test.pli_filename]) test.execute(use_libvpi=True, all_run_flags=['+PLUS +INT=1234 +STRSTR']) diff --git a/test_regress/t/t_vpi_var2.v b/test_regress/t/t_vpi_var2.v index 85b015766..0c0019ddf 100644 --- a/test_regress/t/t_vpi_var2.v +++ b/test_regress/t/t_vpi_var2.v @@ -67,12 +67,14 @@ extern "C" int mon_check(); reg [31:0] text_word; reg [63:0] text_long; reg [511:0] text; + reg [2047:0] too_big; /*verilator public_off*/ integer status; /*verilator public_flat_rw_on*/ real real1; string str1; + localparam int nullptr = 123; /*verilator public_off*/ sub sub(); @@ -88,6 +90,7 @@ extern "C" int mon_check(); text_word = "Word"; text_long = "Long64b"; text = "Verilog Test module"; + too_big = "some text"; real1 = 1.0; str1 = "hello"; diff --git a/test_regress/t/t_vpi_var3.v b/test_regress/t/t_vpi_var3.v index 6e62d5c66..a6422b8c2 100644 --- a/test_regress/t/t_vpi_var3.v +++ b/test_regress/t/t_vpi_var3.v @@ -49,11 +49,13 @@ extern "C" int mon_check(); reg [31:0] text_word; reg [63:0] text_long; reg [511:0] text; + reg [2047:0] too_big; integer status; real real1; string str1; + localparam int nullptr = 123; sub sub(); @@ -68,6 +70,7 @@ extern "C" int mon_check(); text_word = "Word"; text_long = "Long64b"; text = "Verilog Test module"; + too_big = "some text"; real1 = 1.0; str1 = "hello"; diff --git a/test_regress/t/t_wait_no_triggered_bad.out b/test_regress/t/t_wait_no_triggered_bad.out new file mode 100755 index 000000000..2b4628408 --- /dev/null +++ b/test_regress/t/t_wait_no_triggered_bad.out @@ -0,0 +1,6 @@ +%Error: t/t_wait_no_triggered_bad.v:15:12: Wait statement conditions do not take raw events (IEEE 1800-2023 15.5.3) + : ... note: In instance 't' + : ... Suggest use 'e_my_event.triggered' + 15 | wait(e_my_event); + | ^~~~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_wait_no_triggered_bad.py b/test_regress/t/t_wait_no_triggered_bad.py new file mode 100755 index 000000000..5df24a780 --- /dev/null +++ b/test_regress/t/t_wait_no_triggered_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/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 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(verilator_flags2=['--timing'], fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_wait_no_triggered_bad.v b/test_regress/t/t_wait_no_triggered_bad.v new file mode 100644 index 000000000..0d827874d --- /dev/null +++ b/test_regress/t/t_wait_no_triggered_bad.v @@ -0,0 +1,21 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t; + + event e_my_event; + + initial begin + #(1us); + wait(e_my_event.triggered); // Ok + #(1us); + wait(e_my_event); // Bad + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_waiveroutput.out b/test_regress/t/t_waiveroutput.out index 673c0445a..e111709f1 100644 --- a/test_regress/t/t_waiveroutput.out +++ b/test_regress/t/t_waiveroutput.out @@ -2,9 +2,10 @@ `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 +// Below are suggested waivers. You have three options: +// 1. Fix the reason for the linter warning in the Verilog sources +// 2. Keep the waiver permanently if you are sure it is okay // 3. Keep the waiver temporarily to suppress the output -// No waivers needed - great! +// lint_off -rule UNUSEDSIGNAL -file "*t/t_waiveroutput.v" -match "Signal is not used: 'width_warn'*" + diff --git a/test_regress/t/t_waiveroutput.py b/test_regress/t/t_waiveroutput.py index 67b6355da..df3799f05 100755 --- a/test_regress/t/t_waiveroutput.py +++ b/test_regress/t/t_waiveroutput.py @@ -15,7 +15,7 @@ test.top_filename = "t/t_waiveroutput.v" out_filename = test.obj_dir + "/" + test.name + ".waiver_gen.out" waiver_filename = "t/" + test.name + ".vlt" -test.compile(v_flags2=[waiver_filename, '--waiver-output', out_filename]) +test.lint(v_flags2=[waiver_filename, '-Wall', '-Wno-fatal', '--waiver-output', out_filename]) test.files_identical(out_filename, test.golden_filename) diff --git a/test_regress/t/t_waiveroutput_allgood.out b/test_regress/t/t_waiveroutput_allgood.out index 673c0445a..6cba8ab6b 100644 --- a/test_regress/t/t_waiveroutput_allgood.out +++ b/test_regress/t/t_waiveroutput_allgood.out @@ -2,9 +2,9 @@ `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 +// Below are suggested waivers. You have three options: +// 1. Fix the reason for the linter warning in the Verilog sources +// 2. Keep the waiver permanently if you are sure it is okay // 3. Keep the waiver temporarily to suppress the output // No waivers needed - great! diff --git a/test_regress/t/t_waiveroutput_allgood.py b/test_regress/t/t_waiveroutput_allgood.py index fd20a2c37..502abc15b 100755 --- a/test_regress/t/t_waiveroutput_allgood.py +++ b/test_regress/t/t_waiveroutput_allgood.py @@ -13,9 +13,9 @@ test.scenarios('vlt') test.top_filename = "t/t_waiveroutput.v" out_filename = test.obj_dir + "/" + test.name + ".waiver_gen.vlt" -waiver_filename = "t/" + test.name + ".vlt" -test.compile(v_flags2=[waiver_filename, '--waiver-output', out_filename]) +# Note no Wall +test.lint(v_flags2=['-Wno-WIDTH', '--waiver-output', out_filename]) test.files_identical(out_filename, test.golden_filename) diff --git a/test_regress/t/t_waiveroutput_allgood.vlt b/test_regress/t/t_waiveroutput_allgood.vlt deleted file mode 100644 index 54c5798f2..000000000 --- a/test_regress/t/t_waiveroutput_allgood.vlt +++ /dev/null @@ -1,11 +0,0 @@ -// 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 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_waiveroutput_multiline.out b/test_regress/t/t_waiveroutput_multiline.out new file mode 100644 index 000000000..ecfc68bf5 --- /dev/null +++ b/test_regress/t/t_waiveroutput_multiline.out @@ -0,0 +1,11 @@ +// DESCRIPTION: Verilator output: Waivers generated with --waiver-output + +`verilator_config + +// Below are suggested waivers. You have three options: +// 1. Fix the reason for the linter warning in the Verilog sources +// 2. Keep the waiver permanently if you are sure it is okay +// 3. Keep the waiver temporarily to suppress the output + +// lint_off -rule UNUSEDSIGNAL -file "*t/t_waiveroutput.v" -match "Signal is not used: 'width_warn'*reg width_warn = 2'b11;*" + diff --git a/test_regress/t/t_waiveroutput_wall.py b/test_regress/t/t_waiveroutput_multiline.py similarity index 78% rename from test_regress/t/t_waiveroutput_wall.py rename to test_regress/t/t_waiveroutput_multiline.py index 9128c7d89..ddbe93341 100755 --- a/test_regress/t/t_waiveroutput_wall.py +++ b/test_regress/t/t_waiveroutput_multiline.py @@ -13,9 +13,11 @@ test.scenarios('vlt') test.top_filename = "t/t_waiveroutput.v" out_filename = test.obj_dir + "/" + test.name + ".waiver_gen.out" -waiver_filename = "t/" + test.name + ".vlt" +waiver_filename = "t/t_waiveroutput.vlt" -test.compile(v_flags2=['-Wall', waiver_filename, '--waiver-output', out_filename]) +test.lint(v_flags2=[ + waiver_filename, '-Wall', '-Wno-fatal', '--waiver-multiline', '--waiver-output', out_filename +]) test.files_identical(out_filename, test.golden_filename) diff --git a/test_regress/t/t_multiline_waivers.py b/test_regress/t/t_waiveroutput_roundtrip.py similarity index 77% rename from test_regress/t/t_multiline_waivers.py rename to test_regress/t/t_waiveroutput_roundtrip.py index 3f3414f68..39834358b 100755 --- a/test_regress/t/t_multiline_waivers.py +++ b/test_regress/t/t_waiveroutput_roundtrip.py @@ -11,14 +11,14 @@ import vltest_bootstrap test.scenarios('vlt') -out_filename = test.obj_dir + "/" + test.name + "_waiver_gen.vlt" +out_filename = test.obj_dir + "/" + test.name + ".waiver_gen.out" waiver_filename = test.obj_dir + "/" + test.name + "_waiver.vlt" -test.compile(v_flags2=['--waiver-output', out_filename], fails=True) +test.lint(v_flags2=['-Wall', '-Wno-fatal', '--waiver-output', out_filename]) test.file_sed(out_filename, waiver_filename, lambda line: re.sub(r'\/\/ lint_off', 'lint_off', line)) -test.compile(v_flags2=[waiver_filename]) +test.lint(v_flags2=[waiver_filename]) test.passes() diff --git a/test_regress/t/t_multiline_waivers.v b/test_regress/t/t_waiveroutput_roundtrip.v similarity index 100% rename from test_regress/t/t_multiline_waivers.v rename to test_regress/t/t_waiveroutput_roundtrip.v diff --git a/test_regress/t/t_waiveroutput_wall.out b/test_regress/t/t_waiveroutput_wall.out deleted file mode 100644 index 673c0445a..000000000 --- a/test_regress/t/t_waiveroutput_wall.out +++ /dev/null @@ -1,10 +0,0 @@ -// DESCRIPTION: Verilator output: Waivers generated with --waiver-output - -`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 - -// No waivers needed - great! diff --git a/test_regress/t/t_waiveroutput_wall.vlt b/test_regress/t/t_waiveroutput_wall.vlt deleted file mode 100644 index 54c5798f2..000000000 --- a/test_regress/t/t_waiveroutput_wall.vlt +++ /dev/null @@ -1,11 +0,0 @@ -// 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 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_width_docs_bad.v b/test_regress/t/t_width_docs_bad.v deleted file mode 100644 index 13ed51756..000000000 --- a/test_regress/t/t_width_docs_bad.v +++ /dev/null @@ -1,19 +0,0 @@ -// DESCRIPTION: Verilator: Verilog Test module -// -// This file ONLY is placed under the Creative Commons Public Domain, for -// any use, without warranty, 2009 by Wilson Snyder. -// SPDX-License-Identifier: CC0-1.0 - -module t; - int array[5]; - bit [1:0] rd_addr; - wire int rd_value = read_array[rd_addr]; //<--- Warning - - ok ok(); -endmodule - -module ok; - int array[5]; - bit [1:0] rd_addr; - wire int rd_value = read_array[{1'b0, rd_addr}]; //<--- Fixed -endmodule; diff --git a/test_regress/t/t_uvm_pkg_all.vh b/test_regress/t/uvm/uvm_pkg_all.svh similarity index 100% rename from test_regress/t/t_uvm_pkg_all.vh rename to test_regress/t/uvm/uvm_pkg_all.svh diff --git a/test_regress/t/t_uvm_pkg_todo.vh b/test_regress/t/uvm/uvm_pkg_todo.svh similarity index 99% rename from test_regress/t/t_uvm_pkg_todo.vh rename to test_regress/t/uvm/uvm_pkg_todo.svh index 888258fa2..65c2d0b3d 100644 --- a/test_regress/t/t_uvm_pkg_todo.vh +++ b/test_regress/t/uvm/uvm_pkg_todo.svh @@ -22444,9 +22444,7 @@ class uvm_reg_item extends uvm_sequence_item; uvm_elem_kind_e element_kind; uvm_object element; rand uvm_access_e kind; - //TODO issue-4625 - Rand fields of dynamic array types - //TODO %Error-UNSUPPORTED: t/t_uvm_pkg_todo.vh:21081:35: Unsupported: random member variable with type 'bit[]' - /*rand*/ uvm_reg_data_t value[]; + rand uvm_reg_data_t value[]; constraint max_values { value.size() > 0 && value.size() < 1000; } rand uvm_reg_addr_t offset; uvm_status_e status; @@ -26866,9 +26864,7 @@ class uvm_reg_fifo extends uvm_reg; local uvm_reg_field value; local int m_set_cnt; local int unsigned m_size; - //TODO issue-4625 - Rand fields of dynamic array types - //TODO %Error-UNSUPPORTED: t/t_uvm_pkg_todo.vh:21081:35: Unsupported: random member variable with type 'bit[$]' - /*rand*/ uvm_reg_data_t fifo[$]; + rand uvm_reg_data_t fifo[$]; constraint valid_fifo_size { fifo.size() <= m_size; } diff --git a/verilator-config-version.cmake.in b/verilator-config-version.cmake.in index 92160d8fc..1624ae0ca 100644 --- a/verilator-config-version.cmake.in +++ b/verilator-config-version.cmake.in @@ -7,7 +7,7 @@ # # find_package(verilator 4.0) # -# Copyright 2003-2024 by Wilson Snyder. This program is free software; you +# Copyright 2003-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it 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 3c00e1d86..33dcc4406 100644 --- a/verilator-config.cmake.in +++ b/verilator-config.cmake.in @@ -11,7 +11,7 @@ # add_executable(simulator ) # verilate(simulator SOURCES ) # -# Copyright 2003-2024 by Wilson Snyder. This program is free software; you +# Copyright 2003-2025 by Wilson Snyder. This program is free software; you # can redistribute it and/or modify it under the terms of either the GNU # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0.