Merge from master for release.
This commit is contained in:
commit
04fff7ebd8
|
|
@ -11,7 +11,7 @@ on:
|
|||
jobs:
|
||||
Test:
|
||||
name: "'docs/CONTRIBUTORS' was signed"
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: test_regress/t/t_dist_contributors.pl
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ on:
|
|||
|
||||
jobs:
|
||||
format:
|
||||
runs-on: ubuntu-20.04
|
||||
name: Ubuntu 20.04 | format
|
||||
runs-on: ubuntu-22.04
|
||||
name: Ubuntu 22.04 | format
|
||||
env:
|
||||
CI_OS_NAME: linux
|
||||
CI_RUNS_ON: ubuntu-20.04
|
||||
CI_RUNS_ON: ubuntu-22.04
|
||||
CI_COMMIT: ${{ github.sha }}
|
||||
CI_M32: 0
|
||||
steps:
|
||||
|
|
@ -27,14 +27,14 @@ jobs:
|
|||
CI_BUILD_STAGE_NAME: build
|
||||
run: |
|
||||
bash ci/ci-install.bash &&
|
||||
sudo apt-get install clang-format-11 yapf3 &&
|
||||
sudo apt-get install clang-format-14 yapf3 &&
|
||||
git config --global user.email "action@example.com" &&
|
||||
git config --global user.name "github action"
|
||||
- name: Format code
|
||||
run: |
|
||||
autoconf &&
|
||||
./configure &&
|
||||
make -j 2 format CLANGFORMAT=clang-format-11 &&
|
||||
make -j 2 format CLANGFORMAT=clang-format-14 &&
|
||||
git status
|
||||
- name: Push
|
||||
run: |
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
\#*
|
||||
.#*
|
||||
.gdb_history
|
||||
.nfs*
|
||||
*~
|
||||
*.tidy
|
||||
|
|
|
|||
30
Changes
30
Changes
|
|
@ -8,6 +8,31 @@ The changes in each Verilator version are described below. The
|
|||
contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
|
||||
Verilator 4.228 2022-10-01
|
||||
==========================
|
||||
|
||||
**Announcement:**
|
||||
|
||||
* The next release is anticipated primere Verilator Version 5. Please
|
||||
consider beta-testing the github 'develop-v5' branch, which will soon
|
||||
merge into the github 'master' branch (#3383).
|
||||
|
||||
**Minor:**
|
||||
|
||||
* Support some IEEE signal strengths (#3601) (#3629). [Ryszard Rozak/Antmicro]
|
||||
* Add --main to generate main() C++ (previously was experimental only).
|
||||
* Add --build-jobs, and rework arguments for -j (#3623). [Kamil Rakoczy]
|
||||
* Rename --bin to --build-dep-bin.
|
||||
* Rename debug flags --dumpi-tree, --dumpi-graph, etc. [Geza Lore]
|
||||
* Fix thread saftey in SystemC VL_ASSIGN_SBW/WSB (#3494) (#3513). [Mladen Slijepcevic]
|
||||
* Fix crash in gate optimization of circular logic (#3543). [Bill Flynn]
|
||||
* Fix arguments in non-static method call (#3547) (#3582). [Gustav Svensk]
|
||||
* Fix default --mod-prefix when --prefix is repeated (#3603). [Geza Lore]
|
||||
* Fix calling trace() after open() segfault (#3610) (#3627). [Yu-Sheng Lin]
|
||||
* Fix typedef'ed class conversion to boolean (#3616). [Aleksander Kiryk]
|
||||
* Fix Verilation speed when disabled warnings (#3632). [Kamil Rakoczy/Antmicro]
|
||||
|
||||
|
||||
Verilator 4.226 2022-08-31
|
||||
==========================
|
||||
|
||||
|
|
@ -20,12 +45,13 @@ Verilator 4.226 2022-08-31
|
|||
* Support $test$plusargs(expr) (#3489).
|
||||
* Rename trace rolloverSize() (#3570).
|
||||
* Improve Verilation speed with --threads on large designs. [Geza Lore]
|
||||
* Improve Verilation memory by reducing V3Number (#3521). [Mariusz Glebocki/Antmicro]
|
||||
* Fix struct pattern assignment (#2328) (#3517). [Mostafa Gamal]
|
||||
* Fix public combo propagation issues (#2905). [Todd Strader]
|
||||
* Fix incorrect tristate logic (#3399) [shareefj, Vighnesh Iyer]
|
||||
* Fix incorrect bit op tree optimization (#3470). [algrobman]
|
||||
* Fix bisonpre for MSYS2 (#3471).
|
||||
* Fix max memory usage (#3483). [Kamil Rakoczy]
|
||||
* Fix max memory usage (#3483). [Kamil Rakoczy/Antmicro]
|
||||
* Fix empty string arguments to display (#3484). [Grulfen]
|
||||
* Fix table misoptimizing away display (#3488). [Stefan Post]
|
||||
* Fix unique_ptr memory header for MinGW64 (#3493).
|
||||
|
|
@ -36,7 +62,7 @@ Verilator 4.226 2022-08-31
|
|||
* Fix segfault exporting non-existant package (#3535).
|
||||
* Fix void-cast queue pop_front or pop_back (#3542) (#3364). [Drew Ranck]
|
||||
* Fix case statement comparing string literal (#3544). [Gustav Svensk]
|
||||
* Fix === with some tristate constants (#3551). [Ryszard Rozak]
|
||||
* Fix === with some tristate constants (#3551). [Ryszard Rozak/Antmicro]
|
||||
* Fix converting subclasses to string (#3552). [Arkadiusz Kozdra/Antmicro]
|
||||
* Fix --hierarchical with order-based pin connections (#3583) (#3585). [Kelin9298]
|
||||
|
||||
|
|
|
|||
10
Makefile.in
10
Makefile.in
|
|
@ -346,13 +346,13 @@ analyzer-include:
|
|||
|
||||
format: clang-format yapf format-pl-exec
|
||||
|
||||
CLANGFORMAT = clang-format-11
|
||||
CLANGFORMAT = clang-format-14
|
||||
CLANGFORMAT_FLAGS = -i
|
||||
CLANGFORMAT_FILES = $(CPPCHECK_CPP) $(CPPCHECK_H) $(CPPCHECK_YL) test_regress/t/*.c* test_regress/t/*.h
|
||||
|
||||
clang-format:
|
||||
@$(CLANGFORMAT) --version | egrep 11.0 > /dev/null \
|
||||
|| echo "*** You are not using clang-format 11.0, indents may differ from master's ***"
|
||||
@$(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)
|
||||
|
||||
PY_PROGRAMS = \
|
||||
|
|
@ -391,10 +391,10 @@ yapf:
|
|||
FLAKE8 = flake8
|
||||
FLAKE8_FLAGS = \
|
||||
--extend-exclude=fastcov.py \
|
||||
--ignore=E123,E129,E251,E501,W503,W504,E701
|
||||
--ignore=E123,E129,E251,E402,E501,W503,W504,E701
|
||||
|
||||
PYLINT = pylint
|
||||
PYLINT_FLAGS = --disable=R0801
|
||||
PYLINT_FLAGS = --score=n --disable=R0801
|
||||
|
||||
lint-py:
|
||||
-$(FLAKE8) $(FLAKE8_FLAGS) $(PY_PROGRAMS)
|
||||
|
|
|
|||
33
README.rst
33
README.rst
|
|
@ -28,7 +28,7 @@ Welcome to Verilator
|
|||
- |Logo|
|
||||
* - |verilator multithreaded performance|
|
||||
- **Fast**
|
||||
* Outperforms many commercial simulators
|
||||
* Outperforms many closed-source commercial simulators
|
||||
* Single- and multi-threaded output models
|
||||
* - **Widely Used**
|
||||
* Wide industry and academic deployment
|
||||
|
|
@ -55,20 +55,19 @@ performing lint checks, and optionally inserting assertion checks and
|
|||
coverage-analysis points. It outputs single- or multi-threaded .cpp and .h
|
||||
files, the "Verilated" code.
|
||||
|
||||
The user writes a little C++/SystemC wrapper file, which instantiates the
|
||||
"Verilated" model of the user's top level module. These C++/SystemC files
|
||||
are then compiled by a C++ compiler (gcc/clang/MSVC++). Executing the
|
||||
resulting executable performs the design simulation. Verilator also
|
||||
supports linking Verilated generated libraries, optionally encrypted, into
|
||||
other simulators.
|
||||
These Verilated C++/SystemC files are then compiled by a C++ compiler
|
||||
(gcc/clang/MSVC++), optionally along with a user's own C++/SystemC wrapper
|
||||
file to instantiate the Verilated model. Executing the resulting executable
|
||||
performs the design simulation. Verilator also supports linking Verilated
|
||||
generated libraries, optionally encrypted, into other simulators.
|
||||
|
||||
Verilator may not be the best choice if you are expecting a full featured
|
||||
replacement for Incisive, ModelSim/Questa, VCS or another commercial
|
||||
Verilog simulator, or if you are looking for a behavioral Verilog simulator
|
||||
e.g. for a quick class project (we recommend `Icarus Verilog`_ for this.)
|
||||
However, if you are looking for a path to migrate SystemVerilog to C++ or
|
||||
SystemC, or your team is comfortable writing just a touch of C++ code,
|
||||
Verilator is the tool for you.
|
||||
replacement for a closed-source Verilog simulator, need SDF annotation,
|
||||
mixed-signal simulation, or are doing a quick class project (we recommend
|
||||
`Icarus Verilog`_ for classwork.) However, if you are looking for a path
|
||||
to migrate SystemVerilog to C++/SystemC, or want high speed simulation of
|
||||
synthesizable designs containing limited verification constructs, Verilator
|
||||
is the tool for you.
|
||||
|
||||
|
||||
Performance
|
||||
|
|
@ -85,9 +84,11 @@ multithreading (yielding 200-1000x total over interpreted simulators).
|
|||
|
||||
Verilator has typically similar or better performance versus the
|
||||
closed-source Verilog simulators (Carbon Design Systems Carbonator,
|
||||
Modelsim, Cadence Incisive/NC-Verilog, Synopsys VCS, VTOC, and Pragmatic
|
||||
CVer/CVC). But, Verilator is open-sourced, so you can spend on computes
|
||||
rather than licenses. Thus Verilator gives you the best cycles/dollar.
|
||||
Modelsim/Questa, Cadence Incisive/NC-Verilog, Synopsys VCS, VTOC, and
|
||||
Pragmatic CVer/CVC). But, Verilator is open-sourced, so you can spend on
|
||||
computes rather than licenses. Thus Verilator gives you the best
|
||||
cycles/dollar.
|
||||
|
||||
|
||||
Installation & Documentation
|
||||
============================
|
||||
|
|
|
|||
|
|
@ -282,8 +282,9 @@ detailed descriptions of these arguments.
|
|||
--autoflush Flush streams after all $displays
|
||||
--bbox-sys Blackbox unknown $system calls
|
||||
--bbox-unsup Blackbox unsupported language features
|
||||
--bin <filename> Override Verilator binary
|
||||
--build Build model executable/library after Verilation
|
||||
--build-dep-bin <filename> Override build dependency Verilator binary
|
||||
--build-jobs <jobs> Parallelism for --build
|
||||
--cc Create C++ output
|
||||
--cdc Clock domain crossing analysis
|
||||
-CFLAGS <flags> C++ compiler arguments for makefile
|
||||
|
|
@ -308,10 +309,13 @@ detailed descriptions of these arguments.
|
|||
+define+<var>=<value> Set preprocessor define
|
||||
--dpi-hdr-only Only produce the DPI header file
|
||||
--dump-defines Show preprocessor defines with -E
|
||||
--dump-tree Enable dumping .tree files
|
||||
--dump-graph Enable dumping V3Graphs to .dot
|
||||
--dump-tree Enable dumping Ast .tree files
|
||||
--dump-tree-addrids Use short identifiers instead of addresses
|
||||
--dump-treei <level> Enable dumping .tree files at a level
|
||||
--dump-treei-<srcfile> <level> Enable dumping .tree file at a source file at a level
|
||||
--dump-<srcfile> Enable dumping everything in source file
|
||||
--dumpi-graph <level> Enable dumping V3Graphs to .dot files at level
|
||||
--dumpi-tree <level> Enable dumping Ast .tree files at level
|
||||
--dumpi-<srcfile> <level> Enable dumping everything in source file at level
|
||||
-E Preprocess, but do not compile
|
||||
--error-limit <value> Abort after this number of errors
|
||||
--exe Link to create executable
|
||||
|
|
@ -334,7 +338,7 @@ detailed descriptions of these arguments.
|
|||
+incdir+<dir> Directory to search for includes
|
||||
--inline-mult <value> Tune module inlining
|
||||
--instr-count-dpi <value> Assumed dynamic instruction count of DPI imports
|
||||
-j <jobs> Parallelism for --build
|
||||
-j <jobs> Parallelism for --build (alias to --build-jobs)
|
||||
--l2-name <value> Verilog scope name of the top module
|
||||
--language <lang> Default language standard to parse
|
||||
-LDFLAGS <flags> Linker pre-object arguments for makefile
|
||||
|
|
@ -343,6 +347,7 @@ detailed descriptions of these arguments.
|
|||
--lint-only Lint, but do not make output
|
||||
--make <build-tool> Generate scripts for specified build tool
|
||||
-MAKEFLAGS <flags> Arguments to pass to make during --build
|
||||
--main Generate C++ main() file
|
||||
--max-num-width <value> Maximum number width (default: 64K)
|
||||
--Mdir <directory> Name of output object directory
|
||||
--MMD Create .d dependency files
|
||||
|
|
@ -354,6 +359,7 @@ detailed descriptions of these arguments.
|
|||
-O<optimization-letter> Selectable optimizations
|
||||
-o <executable> Name of final executable
|
||||
--no-order-clock-delay Disable ordering clock enable assignments
|
||||
--no-verilate Skip Verilation, only compile previously Verilated code
|
||||
--output-split <statements> Split .cpp files into pieces
|
||||
--output-split-cfuncs <statements> Split model functions
|
||||
--output-split-ctrace <statements> Split tracing functions
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ def diff_dir(a, b):
|
|||
|
||||
anyfile = False
|
||||
for base in sorted(files.keys()):
|
||||
if (not 'a' in files[base]) or (not 'b' in files[base]):
|
||||
if ('a' not in files[base]) or ('b' not in files[base]):
|
||||
continue
|
||||
a = files[base]['a']
|
||||
b = files[base]['b']
|
||||
|
|
|
|||
|
|
@ -149,7 +149,8 @@ def report():
|
|||
for thread in Threads:
|
||||
# Make potentially multiple characters per column
|
||||
for start in Threads[thread]:
|
||||
if not Threads[thread][start]: continue
|
||||
if not Threads[thread][start]:
|
||||
continue
|
||||
cpu = Threads[thread][start]['cpu']
|
||||
elapsed = Threads[thread][start]['end'] - start
|
||||
if cpu not in Global['cpus']:
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ set -x
|
|||
|
||||
cd $(dirname "$0")/..
|
||||
|
||||
# Avoid occasional cpan failures "Issued certificate has expired."
|
||||
export PERL_LWP_SSL_VERIFY_HOSTNAME=0
|
||||
echo "check_certificate = off" >> ~/.wgetrc
|
||||
|
||||
fatal() {
|
||||
echo "ERROR: $(basename "$0"): $1" >&2; exit 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
FROM ubuntu:20.04
|
||||
FROM ubuntu:22.04
|
||||
|
||||
RUN apt-get update \
|
||||
&& DEBIAN_FRONTEND=noninteractive \
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Verilator build. It uses the following parameters:
|
|||
|
||||
- Source revision (default: master)
|
||||
|
||||
- Compiler (GCC 9.3.0, clang 10.0.0, default: 9.3.0)
|
||||
- Compiler (GCC 10.3.0, clang 10.0.0, default: 10.3.0)
|
||||
|
||||
The container is published as ``verilator/verilator-buildenv`` on `docker
|
||||
hub
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
FROM ubuntu:20.04
|
||||
FROM ubuntu:22.04
|
||||
|
||||
RUN apt-get update \
|
||||
&& DEBIAN_FRONTEND=noninteractive \
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
# Then 'make maintainer-dist'
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[4.226 2022-08-31],
|
||||
AC_INIT([Verilator],[4.228 2022-10-01],
|
||||
[https://verilator.org],
|
||||
[verilator],[https://verilator.org])
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ HyungKi Jeong
|
|||
Iru Cai
|
||||
Ivan Vnučec
|
||||
Iztok Jeras
|
||||
Jake Merdich
|
||||
James Hanlon
|
||||
James Hutchinson
|
||||
James Pallister
|
||||
|
|
@ -82,6 +83,7 @@ Michael Killough
|
|||
Michaël Lefebvre
|
||||
Mike Popoloski
|
||||
Miodrag Milanović
|
||||
Mladen Slijepcevic
|
||||
Morten Borup Petersen
|
||||
Mostafa Gamal
|
||||
Nandu Raj
|
||||
|
|
@ -89,6 +91,7 @@ Nathan Kohagen
|
|||
Nathan Myers
|
||||
Patrick Stewart
|
||||
Paul Wright
|
||||
Pawel Sagan
|
||||
Peter Horvath
|
||||
Peter Monsson
|
||||
Philipp Wagner
|
||||
|
|
@ -128,5 +131,6 @@ Yoda Lee
|
|||
Yossi Nivin
|
||||
Yuri Victorovich
|
||||
Yutetsu TAKATSUKASA
|
||||
Yu-Sheng Lin
|
||||
Yves Mathieu
|
||||
Zhanglei Wang
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ from datetime import datetime
|
|||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.abspath('./_ext'))
|
||||
|
||||
import sphinx_rtd_theme # pylint: disable=wrong-import-position,
|
||||
|
|
|
|||
|
|
@ -115,13 +115,6 @@ Summary:
|
|||
|
||||
Using this argument will likely cause incorrect simulation.
|
||||
|
||||
.. option:: --bin <filename>
|
||||
|
||||
Rarely needed. Override the default filename for Verilator itself.
|
||||
When a dependency (.d) file is created, this filename will become a
|
||||
source dependency, such that a change in this binary will have make
|
||||
rebuild the output files.
|
||||
|
||||
.. option:: --build
|
||||
|
||||
After generating the SystemC/C++ code, Verilator will invoke the
|
||||
|
|
@ -129,6 +122,24 @@ Summary:
|
|||
is also used). Verilator manages the build itself, and for this --build
|
||||
requires GNU Make to be available on the platform.
|
||||
|
||||
.. option:: --build-dep-bin <filename>
|
||||
|
||||
Rarely needed. When a dependency (.d) file is created, this filename
|
||||
will become a source dependency, such that a change in this binary will
|
||||
have make rebuild the output files. Defaults to the full path to the
|
||||
Verilator binary.
|
||||
|
||||
This option was named `--bin` prior to version 4.228.
|
||||
|
||||
.. option:: --build-jobs [<value>]
|
||||
|
||||
Specify the level of parallelism for :vlopt:`--build`. If zero, uses the
|
||||
number of threads in the current hardware. Otherwise, the <value> must
|
||||
be a positive integer specifying the maximum number of parallel build
|
||||
jobs.
|
||||
|
||||
See also :vlopt:`-j`.
|
||||
|
||||
.. option:: --cc
|
||||
|
||||
Specifies C++ without SystemC output mode; see also :vlopt:`--sc`
|
||||
|
|
@ -255,8 +266,8 @@ Summary:
|
|||
generally is a less-optimized binary with symbols present (so GDB can be used on it).
|
||||
* Enable debugging messages (equivalent to :vlopt:`--debugi 3 <--debugi>`).
|
||||
* Enable internal assertions (equivalent to :vlopt:`--debug-check`).
|
||||
* Enable intermediate form dump files (equivalent to :vlopt:`--dump-treei 3
|
||||
<--dump-treei>`).
|
||||
* Enable intermediate form dump files (equivalent to :vlopt:`--dumpi-tree 3
|
||||
<--dumpi-tree>`).
|
||||
* Leak to make node numbers unique (equivalent to :vlopt:`--debug-leak
|
||||
<--no-debug-leak>`.
|
||||
* Call abort() instead of exit() if there are any errors (so GDB can see
|
||||
|
|
@ -347,26 +358,21 @@ Summary:
|
|||
|
||||
touch foo.v ; verilator -E --dump-defines foo.v
|
||||
|
||||
.. option:: --dump-graph
|
||||
|
||||
Rarely needed. Enable dumping V3Graph .dot debug files with dumping
|
||||
level 3. Before Verilator 4.228, :vlopt:`--dump-tree` used
|
||||
to include this option.
|
||||
|
||||
.. option:: --dump-tree
|
||||
|
||||
Rarely needed. Enable writing .tree debug files with dumping level 3,
|
||||
Rarely needed. Enable dumping Ast .tree debug files with dumping level 3,
|
||||
which dumps the standard critical stages. For details on the format see
|
||||
the Verilator Internals manual. :vlopt:`--dump-tree` is enabled
|
||||
automatically with :vlopt:`--debug`, so :vlopt:`--debug --no-dump-tree
|
||||
<--dump-tree>` may be useful if the dump files are large and not
|
||||
desired.
|
||||
|
||||
.. option:: --dump-treei <level>
|
||||
|
||||
.. option:: --dump-treei-<srcfile> <level>
|
||||
|
||||
Rarely needed - for developer use. Set internal tree dumping level
|
||||
globally to a specific dumping level or set the specified Verilator
|
||||
source file to the specified tree dumping level (e.g.
|
||||
:vlopt:`--dump-treei-V3Order 9 <--dump-treei>`). Level 0 disables dumps
|
||||
and is equivalent to :vlopt:`--no-dump-tree <--dump-tree>`. Level 9
|
||||
enables dumping of every stage.
|
||||
|
||||
.. option:: --dump-tree-addrids
|
||||
|
||||
Rarely needed - for developer use. Replace AST node addresses with
|
||||
|
|
@ -376,6 +382,28 @@ Summary:
|
|||
by a newly allocated node after a node with the same address has been
|
||||
dumped then freed.
|
||||
|
||||
.. option:: --dump-<srcfile>
|
||||
|
||||
Rarely needed - for developer use. Enable all dumping in the given
|
||||
source file at level 3.
|
||||
|
||||
.. option:: --dumpi-graph <level>
|
||||
|
||||
Rarely needed - for developer use. Set internal V3Graph dumping level
|
||||
globally to the specified value.
|
||||
|
||||
.. option:: --dumpi-tree <level>
|
||||
|
||||
Rarely needed - for developer use. Set internal Ast dumping level
|
||||
globally to the specified value.
|
||||
|
||||
.. option:: --dumpi-<srcfile> <level>
|
||||
|
||||
Rarely needed - for developer use. Set the dumping level in the
|
||||
specified Verilator source file to the specified value (e.g.
|
||||
:vlopt:`--dumpi-V3Order 9`). Level 0 disables dumps and is equivalent
|
||||
to :vlopt:`--no-dump-<srcfile>`. Level 9 enables dumping of everything.
|
||||
|
||||
.. option:: -E
|
||||
|
||||
Preprocess the source code, but do not compile, similar to C++
|
||||
|
|
@ -615,11 +643,10 @@ Summary:
|
|||
|
||||
.. option:: -j [<value>]
|
||||
|
||||
Specify the level of parallelism for :vlopt:`--build`. The <value> must
|
||||
be a positive integer specifying the maximum number of parallel build
|
||||
jobs, or can be omitted. When <value> is omitted, the build will not try
|
||||
to limit the number of parallel build jobs but attempt to execute all
|
||||
independent build steps in parallel.
|
||||
Specify the level of parallelism for :vlopt:`--build` if
|
||||
:vlopt:`--build-jobs` isn't provided. If zero, uses the number of threads
|
||||
in the current hardware. Otherwise, the <value> must be a positive
|
||||
integer specifying the maximum number of parallel build jobs.
|
||||
|
||||
.. option:: --l2-name <value>
|
||||
|
||||
|
|
@ -709,6 +736,15 @@ Summary:
|
|||
(e.g. ``-MAKEFLAGS -l -MAKEFLAGS -k``). Use of this option should not be
|
||||
required for simple builds using the host toolchain.
|
||||
|
||||
.. option:: --main
|
||||
|
||||
Generates a top-level C++ main() file that supports parsing arguments,
|
||||
but does not drive any inputs. This is sufficient to use for top-level
|
||||
SystemVerilog designs that has no inputs, and does not need the C++ to
|
||||
do any time advancement.
|
||||
|
||||
Implies :vlopt:`--cc` if no other output mode was provided.
|
||||
|
||||
.. option:: --max-num-width <value>
|
||||
|
||||
Set the maximum number literal width (e.g. in 1024'd22 this it the
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ Those developing Verilator itself may also want these (see internals.rst):
|
|||
|
||||
::
|
||||
|
||||
sudo apt-get install gdb graphviz cmake clang clang-format-11 gprof lcov
|
||||
sudo apt-get install gdb graphviz cmake clang clang-format-14 gprof lcov
|
||||
sudo apt-get install yapf3
|
||||
sudo pip3 install sphinx sphinx_rtd_theme sphinxcontrib-spelling breathe
|
||||
cpan install Pod::Perldoc
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@
|
|||
Simulating (Verilated-Model Runtime)
|
||||
************************************
|
||||
|
||||
This section describes items related to simulating, that using a Verilated
|
||||
model's executable. For the runtime arguments to a simulated model, see
|
||||
:ref:`Simulation Runtime Arguments`.
|
||||
This section describes items related to simulating, that is, the use of a
|
||||
Verilated model's executable. For the runtime arguments to a simulated
|
||||
model, see :ref:`Simulation Runtime Arguments`.
|
||||
|
||||
|
||||
.. _Benchmarking & Optimization:
|
||||
|
|
|
|||
|
|
@ -96,10 +96,11 @@ this.
|
|||
Each ``AstNode`` has pointers to up to four children, accessed by the
|
||||
``op1p`` through ``op4p`` methods. These methods are then abstracted in a
|
||||
specific Ast\* node class to a more specific name. For example with the
|
||||
``AstIf`` node (for ``if`` statements), ``ifsp`` calls ``op2p`` to give the
|
||||
``AstIf`` node (for ``if`` statements), ``thensp`` calls ``op2p`` to give the
|
||||
pointer to the AST for the "then" block, while ``elsesp`` calls ``op3p`` to
|
||||
give the pointer to the AST for the "else" block, or NULL if there is not
|
||||
one.
|
||||
one. These accessors are automatically generated by ``astgen`` after
|
||||
parsing the ``@astgen`` directives in the specific ``AstNode`` subclasses.
|
||||
|
||||
``AstNode`` has the concept of a next and previous AST - for example the
|
||||
next and previous statements in a block. Pointers to the AST for these
|
||||
|
|
@ -501,22 +502,99 @@ code:
|
|||
The ``astgen`` Script
|
||||
---------------------
|
||||
|
||||
Some of the code implementing passes is extremely repetitive, and must be
|
||||
implemented for each sub-class of ``AstNode``. However, while repetitive,
|
||||
there is more variability than can be handled in C++ macros.
|
||||
The ``astgen`` script is used to generate some of the repetitive C++ code
|
||||
related to the ``AstNode`` type hierarchy. An example is the abstract ``visit``
|
||||
methods in ``VNVisitor``. There are other uses, please see the ``*__gen*``
|
||||
files in the bulid directories and the ``astgen`` script itself for details. A
|
||||
description of the more advanced features of ``astgen`` are provided here.
|
||||
|
||||
In Verilator this is implemented by using a script, ``astgen`` to
|
||||
pre-process the C++ code. For example in ``V3Const.cpp`` this is used to
|
||||
implement the ``visit()`` functions for each binary operation using the
|
||||
``TREEOP`` macro.
|
||||
|
||||
The original C source code is transformed into C code in the ``obj_opt``
|
||||
Generating ``AstNode`` members
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Some of the member s of ``AstNode`` sub-classes are generated by ``astgen``.
|
||||
These are emitted as pre-processor macro definitions, which then need to be
|
||||
added to the ``AstNode`` sub-classes they correspond to. Specifically ``class
|
||||
AstFoo`` should contain an instance of ``ASTGEN_MEMBERS_Foo;`` at class scope.
|
||||
The ``astgen`` script checks and errors if this is not present. The method
|
||||
generated depends on whether the class is a concrete final class, or an
|
||||
abstract ``AstNode*`` base-class, and on ``@astgen`` directives present in
|
||||
comment sections in the body of the ``AstNode`` sub-class definitions.
|
||||
|
||||
|
||||
List of ``@astgen`` directives
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
``@astgen`` directives in comments contained in the body of ``AstNode``
|
||||
sub-class definitions are parsed and contribute to the code generated by
|
||||
``astgen``. The general syntax is ``@astgen <keywords> := <description>``,
|
||||
where ``<keywords>`` determines what is being defined, and ``<description>`` is
|
||||
a ``<keywords>`` dependent description of the definition. The list of
|
||||
``@astgen`` directives is as follows:
|
||||
|
||||
|
||||
``op<N>`` operand directives
|
||||
"""""""""""""""""""""""""""""
|
||||
|
||||
The ``op1``, ``op2``, ``op3`` and ``op4`` directives are used to describe the
|
||||
name and type of the up to 4 child operands of a node. The syntax of the
|
||||
``<description>`` field is ``<identifier> : <type>``, where ``<identifier>``
|
||||
will be used as the base name of the generated operand accessors, and
|
||||
``<type>`` is one of:
|
||||
|
||||
1. An ``AstNode`` sub-class, defining the operand to be of that type, always
|
||||
no-null, and with an always null ``nextp()``. That is, the child node is
|
||||
always present, and is a single ``AstNode`` (as opposed to a list).
|
||||
|
||||
2. ``Optional[<AstNode sub-class>]``. This is just like in point 1 above, but
|
||||
defines the child node to be optional, meaning it may be null.
|
||||
|
||||
3. ``List[AstNode sub-class]`` describes a list operand, which means the child
|
||||
node may have a non-null ``nextp()`` and in addition the child itself may be
|
||||
null, representing an empty list.
|
||||
|
||||
|
||||
An example of the full syntax of the directive is
|
||||
``@astgen op1 := lhsp : AstNodeMath``.
|
||||
|
||||
``astnode`` generates accessors for the child nodes based on these directives.
|
||||
For non-list children, the names of the getter and setter both are that of the
|
||||
given ``<identifier>``. For list type children, the getter is ``<identifier>``,
|
||||
and instead of the setter, there an ``add<Identifier>`` method is generated
|
||||
that appends new nodes (or lists of nodes) to the child list.
|
||||
|
||||
``alias op<N>`` operand alias directives
|
||||
""""""""""""""""""""""""""""""""""""""""
|
||||
|
||||
If a super-class already defined a name and type for a child node using the
|
||||
``op<N>`` directive, but a more appropriate name exists in the context of a
|
||||
sub-class, then the alias directive can be used to introduce an additional name
|
||||
for the child node. The is ``alias op<N> := <identifier>`` where
|
||||
``<identifier>`` is the new name. ``op<N>`` must have been defined in some
|
||||
super-class of the current node.
|
||||
|
||||
Example: ``@astgen alias op1 := condp``
|
||||
|
||||
|
||||
Additional features of ``astgen``
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In addition to generating ``AstNode`` members as described above,
|
||||
``astgen`` is also use to handle some of the repetitive implementation code
|
||||
that is still variable enough not to be handled in C++ macros.
|
||||
|
||||
In particular, ``astgen`` is used to pre-process some of the C++ source
|
||||
files. For example in ``V3Const.cpp``, it is used to implement the
|
||||
``visit()`` functions for each binary operation using the ``TREEOP`` macro.
|
||||
|
||||
The original C++ source code is transformed into C++ code in the ``obj_opt``
|
||||
and ``obj_dbg`` sub-directories (the former for the optimized version of
|
||||
Verilator, the latter for the debug version). So for example
|
||||
``V3Const.cpp`` into ``V3Const__gen.cpp``.
|
||||
|
||||
|
||||
Visitor Functions -----------------
|
||||
Visitor Functions
|
||||
-----------------
|
||||
|
||||
Verilator uses the "Visitor" design pattern to implement its refinement and
|
||||
optimization passes. This allows separation of the pass algorithm from the
|
||||
|
|
@ -1153,8 +1231,9 @@ Generally what would you do to add a new feature?
|
|||
language and has a lot of back-and-forth with Verilator's grammar. Copy
|
||||
the appropriate rules to src/verilog.y and modify the productions.
|
||||
|
||||
4. If a new Ast type is needed, add it to V3AstNodes.h. Follow the
|
||||
convention described above about the AstNode type hierarchy.
|
||||
4. If a new Ast type is needed, add it to the appropriate V3AstNode*.h.
|
||||
Follow the convention described above about the AstNode type hierarchy.
|
||||
Ordering of definitions is enforced by ``astgen``.
|
||||
|
||||
5. Now you can run "test_regress/t/t_<newtestcase>.pl --debug" and it'll
|
||||
probably fail but you'll see a
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ int main(int argc, char** argv, char** env) {
|
|||
// When tracing, the contents of the secret module will not be seen
|
||||
VerilatedVcdC* tfp = nullptr;
|
||||
const char* flag = contextp->commandArgsPlusMatch("trace");
|
||||
if (flag && 0 == strcmp(flag, "+trace")) {
|
||||
if (flag && 0 == std::strcmp(flag, "+trace")) {
|
||||
contextp->traceEverOn(true);
|
||||
VL_PRINTF("Enabling waves into logs/vlt_dump.vcd...\n");
|
||||
tfp = new VerilatedVcdC;
|
||||
|
|
|
|||
|
|
@ -82,14 +82,14 @@ int sc_main(int argc, char* argv[]) {
|
|||
|
||||
// You must do one evaluation before enabling waves, in order to allow
|
||||
// SystemC to interconnect everything for testing.
|
||||
sc_start(1, SC_NS);
|
||||
sc_start(SC_ZERO_TIME);
|
||||
|
||||
#if VM_TRACE
|
||||
// If verilator was invoked with --trace argument,
|
||||
// and if at run time passed the +trace argument, turn on tracing
|
||||
VerilatedVcdSc* tfp = nullptr;
|
||||
const char* flag = Verilated::commandArgsPlusMatch("trace");
|
||||
if (flag && 0 == strcmp(flag, "+trace")) {
|
||||
if (flag && 0 == std::strcmp(flag, "+trace")) {
|
||||
cout << "Enabling waves into logs/vlt_dump.vcd...\n";
|
||||
tfp = new VerilatedVcdSc;
|
||||
top->trace(tfp, 99); // Trace 99 levels of hierarchy
|
||||
|
|
|
|||
|
|
@ -16,12 +16,13 @@ from shutil import copy2
|
|||
|
||||
|
||||
class VlFileCopy:
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
verilator_args, # presently all verilator options are passed-thru
|
||||
# ideally this script would check against options mentioned in help
|
||||
self,
|
||||
verilator_args, # presently all verilator options are passed-thru
|
||||
# ideally this script would check against options mentioned in help
|
||||
debug=0,
|
||||
output_dir='copied'): # directory name we output file uses
|
||||
output_dir='copied'): # directory name we output file uses
|
||||
|
||||
self.debug = debug
|
||||
|
||||
|
|
|
|||
|
|
@ -14,12 +14,13 @@ import xml.etree.ElementTree as ET
|
|||
|
||||
|
||||
class VlHierGraph:
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
verilator_args, # presently all verilator options are passed-thru
|
||||
# ideally this script would check against options mentioned in help
|
||||
self,
|
||||
verilator_args, # presently all verilator options are passed-thru
|
||||
# ideally this script would check against options mentioned in help
|
||||
debug=0,
|
||||
output_filename='graph.dot'): # output filename
|
||||
output_filename='graph.dot'): # output filename
|
||||
self.debug = debug
|
||||
self.next_vertex_number = 0
|
||||
self.name_to_number = {}
|
||||
|
|
|
|||
|
|
@ -1003,22 +1003,22 @@ void _vl_vsformat(std::string& output, const char* formatp, va_list ap) VL_MT_SA
|
|||
}
|
||||
}
|
||||
|
||||
static inline bool _vl_vsss_eof(FILE* fp, int floc) VL_MT_SAFE {
|
||||
static bool _vl_vsss_eof(FILE* fp, int floc) VL_MT_SAFE {
|
||||
if (VL_LIKELY(fp)) {
|
||||
return std::feof(fp) ? true : false; // true : false to prevent MSVC++ warning
|
||||
} else {
|
||||
return floc < 0;
|
||||
}
|
||||
}
|
||||
static inline void _vl_vsss_advance(FILE* fp, int& floc) VL_MT_SAFE {
|
||||
static void _vl_vsss_advance(FILE* fp, int& floc) VL_MT_SAFE {
|
||||
if (VL_LIKELY(fp)) {
|
||||
std::fgetc(fp);
|
||||
} else {
|
||||
floc -= 8;
|
||||
}
|
||||
}
|
||||
static inline int _vl_vsss_peek(FILE* fp, int& floc, const WDataInP fromp,
|
||||
const std::string& fstr) VL_MT_SAFE {
|
||||
static int _vl_vsss_peek(FILE* fp, int& floc, const WDataInP fromp,
|
||||
const std::string& fstr) VL_MT_SAFE {
|
||||
// Get a character without advancing
|
||||
if (VL_LIKELY(fp)) {
|
||||
const int data = std::fgetc(fp);
|
||||
|
|
@ -1035,17 +1035,16 @@ static inline int _vl_vsss_peek(FILE* fp, int& floc, const WDataInP fromp,
|
|||
}
|
||||
}
|
||||
}
|
||||
static inline void _vl_vsss_skipspace(FILE* fp, int& floc, const WDataInP fromp,
|
||||
const std::string& fstr) VL_MT_SAFE {
|
||||
static void _vl_vsss_skipspace(FILE* fp, int& floc, const WDataInP fromp,
|
||||
const std::string& fstr) VL_MT_SAFE {
|
||||
while (true) {
|
||||
const int c = _vl_vsss_peek(fp, floc, fromp, fstr);
|
||||
if (c == EOF || !std::isspace(c)) return;
|
||||
_vl_vsss_advance(fp, floc);
|
||||
}
|
||||
}
|
||||
static inline void _vl_vsss_read_str(FILE* fp, int& floc, const WDataInP fromp,
|
||||
const std::string& fstr, char* tmpp,
|
||||
const char* acceptp) VL_MT_SAFE {
|
||||
static void _vl_vsss_read_str(FILE* fp, int& floc, const WDataInP fromp, const std::string& fstr,
|
||||
char* tmpp, const char* acceptp) VL_MT_SAFE {
|
||||
// Read into tmp, consisting of characters from acceptp list
|
||||
char* cp = tmpp;
|
||||
while (true) {
|
||||
|
|
@ -1059,9 +1058,8 @@ static inline void _vl_vsss_read_str(FILE* fp, int& floc, const WDataInP fromp,
|
|||
*cp++ = '\0';
|
||||
// VL_DBG_MSGF(" _read got='"<<tmpp<<"'\n");
|
||||
}
|
||||
static inline char* _vl_vsss_read_bin(FILE* fp, int& floc, const WDataInP fromp,
|
||||
const std::string& fstr, char* beginp, std::size_t n,
|
||||
const bool inhibit = false) {
|
||||
static char* _vl_vsss_read_bin(FILE* fp, int& floc, const WDataInP fromp, const std::string& fstr,
|
||||
char* beginp, std::size_t n, const bool inhibit = false) {
|
||||
// Variant of _vl_vsss_read_str using the same underlying I/O functions but optimized
|
||||
// specifically for block reads of N bytes (read operations are not demarcated by
|
||||
// whitespace). In the fp case, except descriptor to have been opened in binary mode.
|
||||
|
|
@ -1073,12 +1071,11 @@ static inline char* _vl_vsss_read_bin(FILE* fp, int& floc, const WDataInP fromp,
|
|||
}
|
||||
return beginp;
|
||||
}
|
||||
static inline void _vl_vsss_setbit(WDataOutP owp, int obits, int lsb, int nbits,
|
||||
IData ld) VL_MT_SAFE {
|
||||
static void _vl_vsss_setbit(WDataOutP owp, int obits, int lsb, int nbits, IData ld) VL_MT_SAFE {
|
||||
for (; nbits && lsb < obits; nbits--, lsb++, ld >>= 1) { VL_ASSIGNBIT_WI(lsb, owp, ld & 1); }
|
||||
}
|
||||
static inline void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const char* strp,
|
||||
size_t posstart, size_t posend) VL_MT_SAFE {
|
||||
static void _vl_vsss_based(WDataOutP owp, int obits, int baseLog2, const char* strp,
|
||||
size_t posstart, size_t posend) VL_MT_SAFE {
|
||||
// Read in base "2^^baseLog2" digits from strp[posstart..posend-1] into owp of size obits.
|
||||
int lsb = 0;
|
||||
for (int i = 0, pos = static_cast<int>(posend) - 1;
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ protected:
|
|||
public:
|
||||
/// Returns the VerilatedContext this model is instantiated under
|
||||
/// Used to get to e.g. simulation time via contextp()->time()
|
||||
inline VerilatedContext* contextp() const { return &m_context; }
|
||||
VerilatedContext* contextp() const { return &m_context; }
|
||||
/// Returns the hierarchical name of this module instance.
|
||||
virtual const char* hierName() const = 0;
|
||||
/// Returns the name of this model (the name of the generated model class).
|
||||
|
|
@ -457,9 +457,9 @@ public:
|
|||
VerilatedCovContext* coveragep() VL_MT_SAFE;
|
||||
/// Set debug level
|
||||
/// Debug is currently global, but for forward compatibility have a per-context method
|
||||
static void debug(int val) VL_MT_SAFE;
|
||||
static inline void debug(int val) VL_MT_SAFE;
|
||||
/// Return debug level
|
||||
static int debug() VL_MT_SAFE;
|
||||
static inline int debug() VL_MT_SAFE;
|
||||
/// Set current number of errors/assertions
|
||||
void errorCount(int val) VL_MT_SAFE;
|
||||
/// Increment current number of errors/assertions
|
||||
|
|
@ -521,7 +521,7 @@ public:
|
|||
///
|
||||
/// * Else, time comes from the legacy 'double sc_time_stamp()' which
|
||||
/// must be a function defined by the user's wrapper.
|
||||
uint64_t time() const VL_MT_SAFE;
|
||||
inline uint64_t time() const VL_MT_SAFE;
|
||||
/// Set current simulation time. See time() for side effect details
|
||||
void time(uint64_t value) VL_MT_SAFE { m_s.m_time = value; }
|
||||
/// Advance current simulation time. See time() for side effect details
|
||||
|
|
@ -652,13 +652,13 @@ public: // But internals only - called from VerilatedModule's
|
|||
const char* name() const { return m_namep; }
|
||||
const char* identifier() const { return m_identifierp; }
|
||||
int8_t timeunit() const { return m_timeunit; }
|
||||
inline VerilatedSyms* symsp() const { return m_symsp; }
|
||||
VerilatedSyms* symsp() const { return m_symsp; }
|
||||
VerilatedVar* varFind(const char* namep) const VL_MT_SAFE_POSTINIT;
|
||||
VerilatedVarNameMap* varsp() const VL_MT_SAFE_POSTINIT { return m_varsp; }
|
||||
void scopeDump() const;
|
||||
void* exportFindError(int funcnum) const;
|
||||
static void* exportFindNullError(int funcnum) VL_MT_SAFE;
|
||||
static inline void* exportFind(const VerilatedScope* scopep, int funcnum) VL_MT_SAFE {
|
||||
static void* exportFind(const VerilatedScope* scopep, int funcnum) VL_MT_SAFE {
|
||||
if (VL_UNLIKELY(!scopep)) return exportFindNullError(funcnum);
|
||||
if (VL_LIKELY(funcnum < scopep->m_funcnumMax)) {
|
||||
// m_callbacksp must be declared, as Max'es are > 0
|
||||
|
|
@ -727,7 +727,7 @@ public:
|
|||
/// Return debug level
|
||||
/// When multithreaded this may not immediately react to another thread
|
||||
/// changing the level (no mutex)
|
||||
static inline int debug() VL_MT_SAFE { return s_debug; }
|
||||
static int debug() VL_MT_SAFE { return s_debug; }
|
||||
#else
|
||||
/// Return constant 0 debug level, so C++'s optimizer rips up
|
||||
static constexpr int debug() VL_PURE { return 0; }
|
||||
|
|
@ -933,8 +933,8 @@ private:
|
|||
#endif
|
||||
};
|
||||
|
||||
inline void VerilatedContext::debug(int val) VL_MT_SAFE { Verilated::debug(val); }
|
||||
inline int VerilatedContext::debug() VL_MT_SAFE { return Verilated::debug(); }
|
||||
void VerilatedContext::debug(int val) VL_MT_SAFE { Verilated::debug(val); }
|
||||
int VerilatedContext::debug() VL_MT_SAFE { return Verilated::debug(); }
|
||||
|
||||
//=========================================================================
|
||||
// Data Types
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ void svPutPartselLogic(svLogicVecVal* dp, const svLogicVecVal s, int lbit, int w
|
|||
//======================================================================
|
||||
// Open array internals
|
||||
|
||||
static inline const VerilatedDpiOpenVar* _vl_openhandle_varp(const svOpenArrayHandle h) {
|
||||
static const VerilatedDpiOpenVar* _vl_openhandle_varp(const svOpenArrayHandle h) {
|
||||
if (VL_UNLIKELY(!h)) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "",
|
||||
"%%Error: DPI svOpenArrayHandle function called with nullptr handle");
|
||||
|
|
|
|||
|
|
@ -161,13 +161,13 @@ class VerilatedFstBuffer VL_NOT_FINAL {
|
|||
|
||||
// Implementations of duck-typed methods for VerilatedTraceBuffer. These are
|
||||
// called from only one place (the full* methods), so always inline them.
|
||||
VL_ATTR_ALWINLINE inline void emitBit(uint32_t code, CData newval);
|
||||
VL_ATTR_ALWINLINE inline void emitCData(uint32_t code, CData newval, int bits);
|
||||
VL_ATTR_ALWINLINE inline void emitSData(uint32_t code, SData newval, int bits);
|
||||
VL_ATTR_ALWINLINE inline void emitIData(uint32_t code, IData newval, int bits);
|
||||
VL_ATTR_ALWINLINE inline void emitQData(uint32_t code, QData newval, int bits);
|
||||
VL_ATTR_ALWINLINE inline void emitWData(uint32_t code, const WData* newvalp, int bits);
|
||||
VL_ATTR_ALWINLINE inline void emitDouble(uint32_t code, double newval);
|
||||
VL_ATTR_ALWINLINE void emitBit(uint32_t code, CData newval);
|
||||
VL_ATTR_ALWINLINE void emitCData(uint32_t code, CData newval, int bits);
|
||||
VL_ATTR_ALWINLINE void emitSData(uint32_t code, SData newval, int bits);
|
||||
VL_ATTR_ALWINLINE void emitIData(uint32_t code, IData newval, int bits);
|
||||
VL_ATTR_ALWINLINE void emitQData(uint32_t code, QData newval, int bits);
|
||||
VL_ATTR_ALWINLINE void emitWData(uint32_t code, const WData* newvalp, int bits);
|
||||
VL_ATTR_ALWINLINE void emitDouble(uint32_t code, double newval);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
|
|
@ -232,7 +232,7 @@ public:
|
|||
}
|
||||
|
||||
// Internal class access
|
||||
inline VerilatedFst* spTrace() { return &m_sptrace; }
|
||||
VerilatedFst* spTrace() { return &m_sptrace; }
|
||||
};
|
||||
|
||||
#endif // guard
|
||||
|
|
|
|||
|
|
@ -52,35 +52,35 @@ public:
|
|||
}
|
||||
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
|
||||
}
|
||||
virtual ~VerilatedFstSc() /*override*/ { close(); }
|
||||
~VerilatedFstSc() override { close(); }
|
||||
|
||||
// METHODS
|
||||
/// Called by SystemC simulate()
|
||||
virtual void cycle(bool delta_cycle) {
|
||||
void cycle(bool delta_cycle) override {
|
||||
if (!delta_cycle) { this->dump(sc_time_stamp().to_double()); }
|
||||
}
|
||||
|
||||
// Override VerilatedFstC. Must be called after starting simulation.
|
||||
// cppcheck-suppress missingOverride // GCC won't accept override
|
||||
virtual void open(const char* filename) /*override*/ VL_MT_SAFE;
|
||||
// Note: this is not a virtual function in the base class, so no 'override'
|
||||
virtual void open(const char* filename) VL_MT_SAFE;
|
||||
|
||||
private:
|
||||
/// Fake outs for linker
|
||||
|
||||
#ifdef NC_SYSTEMC
|
||||
// Cadence Incisive has these as abstract functions so we must create them
|
||||
virtual void set_time_unit(int exponent10_seconds) {} // deprecated
|
||||
void set_time_unit(int exponent10_seconds) override {} // deprecated
|
||||
#endif
|
||||
virtual void set_time_unit(double v, sc_time_unit tu) {} // LCOV_EXCL_LINE
|
||||
void set_time_unit(double v, sc_time_unit tu) override {} // LCOV_EXCL_LINE
|
||||
|
||||
//--------------------------------------------------
|
||||
// SystemC 2.1.v1
|
||||
#define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const std::string& name);
|
||||
#define DECL_TRACE_METHOD_A(tp) void trace(const tp& object, const std::string& name) override;
|
||||
#define DECL_TRACE_METHOD_B(tp) \
|
||||
virtual void trace(const tp& object, const std::string& name, int width);
|
||||
void trace(const tp& object, const std::string& name, int width) override;
|
||||
|
||||
virtual void write_comment(const std::string&);
|
||||
virtual void trace(const unsigned int&, const std::string&, const char**);
|
||||
void write_comment(const std::string&) override;
|
||||
void trace(const unsigned int&, const std::string&, const char**) override;
|
||||
|
||||
// clang-format off
|
||||
// Formatting matches that of sc_trace.h
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ inline uint64_t vl_time_stamp64() {
|
|||
# endif
|
||||
#endif
|
||||
|
||||
inline uint64_t VerilatedContext::time() const VL_MT_SAFE {
|
||||
uint64_t VerilatedContext::time() const VL_MT_SAFE {
|
||||
// When using non-default context, fastest path is return time
|
||||
if (VL_LIKELY(m_s.m_time)) return m_s.m_time;
|
||||
#if defined(SYSTEMC_VERSION) || (!defined(VL_TIME_CONTEXT) && !defined(VL_NO_LEGACY))
|
||||
|
|
@ -448,10 +448,17 @@ static inline void VL_ASSIGNBIT_WO(int bit, WDataOutP owp) VL_MT_SAFE {
|
|||
{ \
|
||||
const int words = VL_WORDS_I(obits); \
|
||||
sc_biguint<(obits)> _butemp = (svar).read(); \
|
||||
for (int i = 0; i < words; ++i) { \
|
||||
int msb = ((i + 1) * VL_IDATASIZE) - 1; \
|
||||
msb = (msb >= (obits)) ? ((obits)-1) : msb; \
|
||||
(owp)[i] = _butemp.range(msb, i * VL_IDATASIZE).to_uint(); \
|
||||
uint32_t* chunk = _butemp.get_raw(); \
|
||||
int32_t lsb = 0; \
|
||||
while (lsb < obits - BITS_PER_DIGIT) { \
|
||||
const uint32_t data = *chunk; \
|
||||
++chunk; \
|
||||
_vl_insert_WI(owp.data(), data, lsb + BITS_PER_DIGIT - 1, lsb); \
|
||||
lsb += BITS_PER_DIGIT; \
|
||||
} \
|
||||
if (lsb < obits) { \
|
||||
const uint32_t msb_data = *chunk; \
|
||||
_vl_insert_WI(owp.data(), msb_data, obits - 1, lsb); \
|
||||
} \
|
||||
(owp)[words - 1] &= VL_MASK_E(obits); \
|
||||
}
|
||||
|
|
@ -492,13 +499,23 @@ static inline void VL_ASSIGNBIT_WO(int bit, WDataOutP owp) VL_MT_SAFE {
|
|||
{ (svar).write(rd); }
|
||||
#define VL_ASSIGN_SBQ(obits, svar, rd) \
|
||||
{ (svar).write(rd); }
|
||||
#define VL_SC_BITS_PER_DIGIT 30 // This comes from sc_nbdefs.h BITS_PER_DIGIT
|
||||
#define VL_ASSIGN_SBW(obits, svar, rwp) \
|
||||
{ \
|
||||
sc_biguint<(obits)> _butemp; \
|
||||
for (int i = 0; i < VL_WORDS_I(obits); ++i) { \
|
||||
int msb = ((i + 1) * VL_IDATASIZE) - 1; \
|
||||
msb = (msb >= (obits)) ? ((obits)-1) : msb; \
|
||||
_butemp.range(msb, i* VL_IDATASIZE) = (rwp)[i]; \
|
||||
int32_t lsb = 0; \
|
||||
uint32_t* chunk = _butemp.get_raw(); \
|
||||
while (lsb + VL_SC_BITS_PER_DIGIT < (obits)) { \
|
||||
static_assert(std::is_same<IData, EData>::value, "IData and EData missmatch"); \
|
||||
const uint32_t data = VL_SEL_IWII(lsb + VL_SC_BITS_PER_DIGIT + 1, (rwp).data(), lsb, \
|
||||
VL_SC_BITS_PER_DIGIT); \
|
||||
*chunk = data & VL_MASK_E(VL_SC_BITS_PER_DIGIT); \
|
||||
++chunk; \
|
||||
lsb += VL_SC_BITS_PER_DIGIT; \
|
||||
} \
|
||||
if (lsb < (obits)) { \
|
||||
const uint32_t msb_data = VL_SEL_IWII((obits) + 1, (rwp).data(), lsb, (obits)-lsb); \
|
||||
*chunk = msb_data & VL_MASK_E((obits)-lsb); \
|
||||
} \
|
||||
(svar).write(_butemp); \
|
||||
}
|
||||
|
|
|
|||
|
|
@ -356,7 +356,7 @@ public: // But only for verilated*.cpp
|
|||
}
|
||||
}
|
||||
}
|
||||
inline FILE* fdToFp(IData fdi) VL_MT_SAFE_EXCLUDES(m_fdMutex) {
|
||||
FILE* fdToFp(IData fdi) VL_MT_SAFE_EXCLUDES(m_fdMutex) {
|
||||
const VerilatedLockGuard lock{m_fdMutex};
|
||||
const VerilatedFpList fdlist = fdToFpList(fdi);
|
||||
if (VL_UNLIKELY(fdlist.size() != 1)) return nullptr;
|
||||
|
|
@ -466,7 +466,7 @@ public:
|
|||
// There's often many more scopes than userdata's and thus having a ~48byte
|
||||
// per map overhead * N scopes would take much more space and cache thrashing.
|
||||
// As scopep's are pointers, this implicitly handles multiple Context's
|
||||
static inline void userInsert(const void* scopep, void* userKey, void* userData) VL_MT_SAFE {
|
||||
static void userInsert(const void* scopep, void* userKey, void* userData) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock{s().m_userMapMutex};
|
||||
const auto it = s().m_userMap.find(std::make_pair(scopep, userKey));
|
||||
if (it != s().m_userMap.end()) {
|
||||
|
|
@ -475,7 +475,7 @@ public:
|
|||
s().m_userMap.emplace(std::make_pair(scopep, userKey), userData);
|
||||
}
|
||||
}
|
||||
static inline void* userFind(const void* scopep, void* userKey) VL_MT_SAFE {
|
||||
static void* userFind(const void* scopep, void* userKey) VL_MT_SAFE {
|
||||
const VerilatedLockGuard lock{s().m_userMapMutex};
|
||||
const auto& it = vlstd::as_const(s().m_userMap).find(std::make_pair(scopep, userKey));
|
||||
if (VL_UNLIKELY(it == s().m_userMap.end())) return nullptr;
|
||||
|
|
|
|||
|
|
@ -45,8 +45,7 @@ class VlThreadPool;
|
|||
|
||||
//=============================================================================
|
||||
// Return high-precision counter for profiling, or 0x0 if not available
|
||||
VL_ATTR_ALWINLINE
|
||||
inline QData VL_CPU_TICK() {
|
||||
VL_ATTR_ALWINLINE QData VL_CPU_TICK() {
|
||||
uint64_t val;
|
||||
VL_GET_CPU_TICK(val);
|
||||
return val;
|
||||
|
|
@ -171,9 +170,9 @@ public:
|
|||
// METHODS
|
||||
|
||||
// Is profiling enabled
|
||||
inline bool enabled() const { return m_enabled; }
|
||||
bool enabled() const { return m_enabled; }
|
||||
// Append a trace record to the trace buffer of the current thread
|
||||
static inline VlExecutionRecord& addRecord() {
|
||||
static VlExecutionRecord& addRecord() {
|
||||
t_trace.emplace_back();
|
||||
return t_trace.back();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ public:
|
|||
// Upstream mtasks must call this when they complete.
|
||||
// Returns true when the current MTaskVertex becomes ready to execute,
|
||||
// false while it's still waiting on more dependencies.
|
||||
inline bool signalUpstreamDone(bool evenCycle) {
|
||||
bool signalUpstreamDone(bool evenCycle) {
|
||||
if (evenCycle) {
|
||||
const uint32_t upstreamDepsDone
|
||||
= 1 + m_upstreamDepsDone.fetch_add(1, std::memory_order_release);
|
||||
|
|
@ -116,11 +116,11 @@ public:
|
|||
return (upstreamDepsDone_prev == 1);
|
||||
}
|
||||
}
|
||||
inline bool areUpstreamDepsDone(bool evenCycle) const {
|
||||
bool areUpstreamDepsDone(bool evenCycle) const {
|
||||
const uint32_t target = evenCycle ? m_upstreamDepCount : 0;
|
||||
return m_upstreamDepsDone.load(std::memory_order_acquire) == target;
|
||||
}
|
||||
inline void waitUntilUpstreamDone(bool evenCycle) const {
|
||||
void waitUntilUpstreamDone(bool evenCycle) const {
|
||||
unsigned ct = 0;
|
||||
while (VL_UNLIKELY(!areUpstreamDepsDone(evenCycle))) {
|
||||
VL_CPU_RELAX();
|
||||
|
|
@ -171,7 +171,7 @@ public:
|
|||
|
||||
// METHODS
|
||||
template <bool SpinWait>
|
||||
inline void dequeWork(ExecRec* workp) VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
void dequeWork(ExecRec* workp) VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
// Spin for a while, waiting for new data
|
||||
if VL_CONSTEXPR_CXX17 (SpinWait) {
|
||||
for (unsigned i = 0; i < VL_LOCK_SPINS; ++i) {
|
||||
|
|
@ -191,7 +191,7 @@ public:
|
|||
m_ready.erase(m_ready.begin());
|
||||
m_ready_size.fetch_sub(1, std::memory_order_relaxed);
|
||||
}
|
||||
inline void addTask(VlExecFnp fnp, VlSelfP selfp, bool evenCycle = false)
|
||||
void addTask(VlExecFnp fnp, VlSelfP selfp, bool evenCycle = false)
|
||||
VL_MT_SAFE_EXCLUDES(m_mutex) {
|
||||
bool notify;
|
||||
{
|
||||
|
|
@ -223,8 +223,8 @@ public:
|
|||
~VlThreadPool() override;
|
||||
|
||||
// METHODS
|
||||
inline int numThreads() const { return m_workers.size(); }
|
||||
inline VlWorkerThread* workerp(int index) {
|
||||
int numThreads() const { return m_workers.size(); }
|
||||
VlWorkerThread* workerp(int index) {
|
||||
assert(index >= 0);
|
||||
assert(index < m_workers.size());
|
||||
return m_workers[index];
|
||||
|
|
|
|||
|
|
@ -318,8 +318,8 @@ protected:
|
|||
void flushBase();
|
||||
|
||||
#ifdef VL_THREADED
|
||||
inline bool offload() const { return m_offload; }
|
||||
inline bool parallel() const { return m_parallel; }
|
||||
bool offload() const { return m_offload; }
|
||||
bool parallel() const { return m_parallel; }
|
||||
#else
|
||||
static constexpr bool offload() { return false; }
|
||||
static constexpr bool parallel() { return false; }
|
||||
|
|
@ -425,7 +425,7 @@ public:
|
|||
// duck-typed void emitWData(uint32_t code, const WData* newvalp, int bits) = 0;
|
||||
// duck-typed void emitDouble(uint32_t code, double newval) = 0;
|
||||
|
||||
VL_ATTR_ALWINLINE inline uint32_t* oldp(uint32_t code) { return m_sigs_oldvalp + code; }
|
||||
VL_ATTR_ALWINLINE uint32_t* oldp(uint32_t code) { return m_sigs_oldvalp + code; }
|
||||
|
||||
// Write to previous value buffer value and emit trace entry.
|
||||
void fullBit(uint32_t* oldp, CData newval);
|
||||
|
|
@ -441,27 +441,27 @@ public:
|
|||
// thread and are called chg*Impl
|
||||
|
||||
// Check previous dumped value of signal. If changed, then emit trace entry
|
||||
VL_ATTR_ALWINLINE inline void chgBit(uint32_t* oldp, CData newval) {
|
||||
VL_ATTR_ALWINLINE void chgBit(uint32_t* oldp, CData newval) {
|
||||
const uint32_t diff = *oldp ^ newval;
|
||||
if (VL_UNLIKELY(diff)) fullBit(oldp, newval);
|
||||
}
|
||||
VL_ATTR_ALWINLINE inline void chgCData(uint32_t* oldp, CData newval, int bits) {
|
||||
VL_ATTR_ALWINLINE void chgCData(uint32_t* oldp, CData newval, int bits) {
|
||||
const uint32_t diff = *oldp ^ newval;
|
||||
if (VL_UNLIKELY(diff)) fullCData(oldp, newval, bits);
|
||||
}
|
||||
VL_ATTR_ALWINLINE inline void chgSData(uint32_t* oldp, SData newval, int bits) {
|
||||
VL_ATTR_ALWINLINE void chgSData(uint32_t* oldp, SData newval, int bits) {
|
||||
const uint32_t diff = *oldp ^ newval;
|
||||
if (VL_UNLIKELY(diff)) fullSData(oldp, newval, bits);
|
||||
}
|
||||
VL_ATTR_ALWINLINE inline void chgIData(uint32_t* oldp, IData newval, int bits) {
|
||||
VL_ATTR_ALWINLINE void chgIData(uint32_t* oldp, IData newval, int bits) {
|
||||
const uint32_t diff = *oldp ^ newval;
|
||||
if (VL_UNLIKELY(diff)) fullIData(oldp, newval, bits);
|
||||
}
|
||||
VL_ATTR_ALWINLINE inline void chgQData(uint32_t* oldp, QData newval, int bits) {
|
||||
VL_ATTR_ALWINLINE void chgQData(uint32_t* oldp, QData newval, int bits) {
|
||||
const uint64_t diff = *reinterpret_cast<QData*>(oldp) ^ newval;
|
||||
if (VL_UNLIKELY(diff)) fullQData(oldp, newval, bits);
|
||||
}
|
||||
VL_ATTR_ALWINLINE inline void chgWData(uint32_t* oldp, const WData* newvalp, int bits) {
|
||||
VL_ATTR_ALWINLINE void chgWData(uint32_t* oldp, const WData* newvalp, int bits) {
|
||||
for (int i = 0; i < (bits + 31) / 32; ++i) {
|
||||
if (VL_UNLIKELY(oldp[i] ^ newvalp[i])) {
|
||||
fullWData(oldp, newvalp, bits);
|
||||
|
|
@ -469,7 +469,7 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
VL_ATTR_ALWINLINE inline void chgDouble(uint32_t* oldp, double newval) {
|
||||
VL_ATTR_ALWINLINE void chgDouble(uint32_t* oldp, double newval) {
|
||||
// cppcheck-suppress invalidPointerCast
|
||||
if (VL_UNLIKELY(*reinterpret_cast<double*>(oldp) != newval)) fullDouble(oldp, newval);
|
||||
}
|
||||
|
|
@ -498,48 +498,48 @@ public:
|
|||
// Hot path internal interface to Verilator generated code
|
||||
|
||||
// Offloaded tracing. Just dump everything in the offload buffer
|
||||
inline void chgBit(uint32_t code, CData newval) {
|
||||
void chgBit(uint32_t code, CData newval) {
|
||||
m_offloadBufferWritep[0] = VerilatedTraceOffloadCommand::CHG_BIT_0 | newval;
|
||||
m_offloadBufferWritep[1] = code;
|
||||
m_offloadBufferWritep += 2;
|
||||
VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp););
|
||||
}
|
||||
inline void chgCData(uint32_t code, CData newval, int bits) {
|
||||
void chgCData(uint32_t code, CData newval, int bits) {
|
||||
m_offloadBufferWritep[0] = (bits << 4) | VerilatedTraceOffloadCommand::CHG_CDATA;
|
||||
m_offloadBufferWritep[1] = code;
|
||||
m_offloadBufferWritep[2] = newval;
|
||||
m_offloadBufferWritep += 3;
|
||||
VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp););
|
||||
}
|
||||
inline void chgSData(uint32_t code, SData newval, int bits) {
|
||||
void chgSData(uint32_t code, SData newval, int bits) {
|
||||
m_offloadBufferWritep[0] = (bits << 4) | VerilatedTraceOffloadCommand::CHG_SDATA;
|
||||
m_offloadBufferWritep[1] = code;
|
||||
m_offloadBufferWritep[2] = newval;
|
||||
m_offloadBufferWritep += 3;
|
||||
VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp););
|
||||
}
|
||||
inline void chgIData(uint32_t code, IData newval, int bits) {
|
||||
void chgIData(uint32_t code, IData newval, int bits) {
|
||||
m_offloadBufferWritep[0] = (bits << 4) | VerilatedTraceOffloadCommand::CHG_IDATA;
|
||||
m_offloadBufferWritep[1] = code;
|
||||
m_offloadBufferWritep[2] = newval;
|
||||
m_offloadBufferWritep += 3;
|
||||
VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp););
|
||||
}
|
||||
inline void chgQData(uint32_t code, QData newval, int bits) {
|
||||
void chgQData(uint32_t code, QData newval, int bits) {
|
||||
m_offloadBufferWritep[0] = (bits << 4) | VerilatedTraceOffloadCommand::CHG_QDATA;
|
||||
m_offloadBufferWritep[1] = code;
|
||||
*reinterpret_cast<QData*>(m_offloadBufferWritep + 2) = newval;
|
||||
m_offloadBufferWritep += 4;
|
||||
VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp););
|
||||
}
|
||||
inline void chgWData(uint32_t code, const WData* newvalp, int bits) {
|
||||
void chgWData(uint32_t code, const WData* newvalp, int bits) {
|
||||
m_offloadBufferWritep[0] = (bits << 4) | VerilatedTraceOffloadCommand::CHG_WDATA;
|
||||
m_offloadBufferWritep[1] = code;
|
||||
m_offloadBufferWritep += 2;
|
||||
for (int i = 0; i < (bits + 31) / 32; ++i) { *m_offloadBufferWritep++ = newvalp[i]; }
|
||||
VL_DEBUG_IF(assert(m_offloadBufferWritep <= m_offloadBufferEndp););
|
||||
}
|
||||
inline void chgDouble(uint32_t code, double newval) {
|
||||
void chgDouble(uint32_t code, double newval) {
|
||||
m_offloadBufferWritep[0] = VerilatedTraceOffloadCommand::CHG_DOUBLE;
|
||||
m_offloadBufferWritep[1] = code;
|
||||
// cppcheck-suppress invalidPointerCast
|
||||
|
|
|
|||
|
|
@ -551,15 +551,15 @@ template <>
|
|||
void VerilatedTrace<VL_SUB_T, VL_BUF_T>::runOffloadedCallbacks(
|
||||
const std::vector<CallbackRecord>& cbVec) {
|
||||
// Fall back on sequential execution
|
||||
for (const CallbackRecord& cbr : cbVec) {
|
||||
#ifdef VL_THREADED
|
||||
for (const CallbackRecord& cbr : cbVec) {
|
||||
Buffer* traceBufferp = getTraceBuffer();
|
||||
cbr.m_dumpOffloadCb(cbr.m_userp, static_cast<OffloadBuffer*>(traceBufferp));
|
||||
commitTraceBuffer(traceBufferp);
|
||||
#else
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "", "Unreachable");
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
if (!cbVec.empty()) VL_FATAL_MT(__FILE__, __LINE__, "", "Unreachable");
|
||||
#endif
|
||||
}
|
||||
|
||||
template <>
|
||||
|
|
@ -586,7 +586,9 @@ void VerilatedTrace<VL_SUB_T, VL_BUF_T>::dump(uint64_t timeui) VL_MT_SAFE_EXCLUD
|
|||
if (!preChangeDump()) return;
|
||||
}
|
||||
|
||||
#ifdef VL_THREADED
|
||||
uint32_t* bufferp = nullptr;
|
||||
#endif
|
||||
if (offload()) {
|
||||
#ifdef VL_THREADED
|
||||
// Currently only incremental dumps run on the worker thread
|
||||
|
|
|
|||
|
|
@ -632,10 +632,10 @@ void VerilatedVcd::commitTraceBuffer(VerilatedVcd::Buffer* bufp) {
|
|||
//=============================================================================
|
||||
// Trace rendering primitives
|
||||
|
||||
static inline void
|
||||
VerilatedVcdCCopyAndAppendNewLine(char* writep, const char* suffixp) VL_ATTR_NO_SANITIZE_ALIGN;
|
||||
static void VerilatedVcdCCopyAndAppendNewLine(char* writep,
|
||||
const char* suffixp) VL_ATTR_NO_SANITIZE_ALIGN;
|
||||
|
||||
static inline void VerilatedVcdCCopyAndAppendNewLine(char* writep, const char* suffixp) {
|
||||
static void VerilatedVcdCCopyAndAppendNewLine(char* writep, const char* suffixp) {
|
||||
// Copy the whole suffix (this avoid having hard to predict branches which
|
||||
// helps a lot). Note: The maximum length of the suffix is
|
||||
// VL_TRACE_MAX_VCD_CODE_SIZE + 2 == 7, but we unroll this here for speed.
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ private:
|
|||
|
||||
void bufferResize(size_t minsize);
|
||||
void bufferFlush() VL_MT_UNSAFE_ONE;
|
||||
inline void bufferCheck() {
|
||||
void bufferCheck() {
|
||||
// Flush the write buffer if there's not enough space left for new information
|
||||
// We only call this once per vector, so we need enough slop for a very wide "b###" line
|
||||
if (VL_UNLIKELY(m_writep > m_wrFlushp)) bufferFlush();
|
||||
|
|
@ -210,13 +210,13 @@ class VerilatedVcdBuffer VL_NOT_FINAL {
|
|||
// Implementation of VerilatedTraceBuffer interface
|
||||
// Implementations of duck-typed methods for VerilatedTraceBuffer. These are
|
||||
// called from only one place (the full* methods), so always inline them.
|
||||
VL_ATTR_ALWINLINE inline void emitBit(uint32_t code, CData newval);
|
||||
VL_ATTR_ALWINLINE inline void emitCData(uint32_t code, CData newval, int bits);
|
||||
VL_ATTR_ALWINLINE inline void emitSData(uint32_t code, SData newval, int bits);
|
||||
VL_ATTR_ALWINLINE inline void emitIData(uint32_t code, IData newval, int bits);
|
||||
VL_ATTR_ALWINLINE inline void emitQData(uint32_t code, QData newval, int bits);
|
||||
VL_ATTR_ALWINLINE inline void emitWData(uint32_t code, const WData* newvalp, int bits);
|
||||
VL_ATTR_ALWINLINE inline void emitDouble(uint32_t code, double newval);
|
||||
VL_ATTR_ALWINLINE void emitBit(uint32_t code, CData newval);
|
||||
VL_ATTR_ALWINLINE void emitCData(uint32_t code, CData newval, int bits);
|
||||
VL_ATTR_ALWINLINE void emitSData(uint32_t code, SData newval, int bits);
|
||||
VL_ATTR_ALWINLINE void emitIData(uint32_t code, IData newval, int bits);
|
||||
VL_ATTR_ALWINLINE void emitQData(uint32_t code, QData newval, int bits);
|
||||
VL_ATTR_ALWINLINE void emitWData(uint32_t code, const WData* newvalp, int bits);
|
||||
VL_ATTR_ALWINLINE void emitDouble(uint32_t code, double newval);
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
|
|
@ -313,7 +313,7 @@ public:
|
|||
}
|
||||
|
||||
// Internal class access
|
||||
inline VerilatedVcd* spTrace() { return &m_sptrace; }
|
||||
VerilatedVcd* spTrace() { return &m_sptrace; }
|
||||
};
|
||||
|
||||
#endif // guard
|
||||
|
|
|
|||
|
|
@ -55,35 +55,34 @@ public:
|
|||
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
|
||||
}
|
||||
/// Destruct, flush, and close the dump
|
||||
virtual ~VerilatedVcdSc() /*override*/ { close(); }
|
||||
~VerilatedVcdSc() override { close(); }
|
||||
|
||||
// METHODS - for SC kernel
|
||||
// Called by SystemC simulate()
|
||||
virtual void cycle(bool delta_cycle) {
|
||||
void cycle(bool delta_cycle) override {
|
||||
if (!delta_cycle) this->dump(sc_time_stamp().to_double());
|
||||
}
|
||||
|
||||
// Override VerilatedVcdC. Must be called after starting simulation.
|
||||
// cppcheck-suppress missingOverride // GCC won't accept override
|
||||
virtual void open(const char* filename) /*override*/ VL_MT_SAFE;
|
||||
void open(const char* filename) override VL_MT_SAFE;
|
||||
|
||||
private:
|
||||
// METHODS - Fake outs for linker
|
||||
|
||||
#ifdef NC_SYSTEMC
|
||||
// Cadence Incisive has these as abstract functions so we must create them
|
||||
virtual void set_time_unit(int exponent10_seconds) {} // deprecated
|
||||
void set_time_unit(int exponent10_seconds) override {} // deprecated
|
||||
#endif
|
||||
virtual void set_time_unit(double v, sc_time_unit tu) {} // LCOV_EXCL_LINE
|
||||
void set_time_unit(double v, sc_time_unit tu) override {} // LCOV_EXCL_LINE
|
||||
|
||||
//--------------------------------------------------
|
||||
// SystemC 2.1.v1
|
||||
#define DECL_TRACE_METHOD_A(tp) virtual void trace(const tp& object, const std::string& name);
|
||||
#define DECL_TRACE_METHOD_A(tp) void trace(const tp& object, const std::string& name) override;
|
||||
#define DECL_TRACE_METHOD_B(tp) \
|
||||
virtual void trace(const tp& object, const std::string& name, int width);
|
||||
void trace(const tp& object, const std::string& name, int width) override;
|
||||
|
||||
virtual void write_comment(const std::string&);
|
||||
virtual void trace(const unsigned int&, const std::string&, const char**);
|
||||
void write_comment(const std::string&) override;
|
||||
void trace(const unsigned int&, const std::string&, const char**) override;
|
||||
|
||||
// clang-format off
|
||||
// Formatting matches that of sc_trace.h
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ public:
|
|||
*(reinterpret_cast<uint32_t*>(newp)) = activeMagic();
|
||||
return newp + 8;
|
||||
}
|
||||
static void operator delete(void* obj, size_t /*size*/)VL_MT_SAFE {
|
||||
static void operator delete(void* obj, size_t /*size*/) VL_MT_SAFE {
|
||||
uint8_t* const oldp = (static_cast<uint8_t*>(obj)) - 8;
|
||||
if (VL_UNLIKELY(*(reinterpret_cast<uint32_t*>(oldp)) != activeMagic())) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "",
|
||||
|
|
@ -114,7 +114,7 @@ public:
|
|||
static VerilatedVpio* castp(vpiHandle h) {
|
||||
return dynamic_cast<VerilatedVpio*>(reinterpret_cast<VerilatedVpio*>(h));
|
||||
}
|
||||
inline vpiHandle castVpiHandle() { return reinterpret_cast<vpiHandle>(this); }
|
||||
vpiHandle castVpiHandle() { return reinterpret_cast<vpiHandle>(this); }
|
||||
// ACCESSORS
|
||||
virtual const char* name() const { return "<null>"; }
|
||||
virtual const char* fullname() const { return "<null>"; }
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
#ifdef __GNUC__
|
||||
# define VL_ATTR_ALIGNED(alignment) __attribute__((aligned(alignment)))
|
||||
# define VL_ATTR_ALWINLINE __attribute__((always_inline))
|
||||
# define VL_ATTR_ALWINLINE __attribute__((always_inline)) inline
|
||||
# define VL_ATTR_NOINLINE __attribute__((noinline))
|
||||
# define VL_ATTR_COLD __attribute__((cold))
|
||||
# define VL_ATTR_HOT __attribute__((hot))
|
||||
|
|
@ -548,8 +548,8 @@ struct reverse_wrapper {
|
|||
|
||||
explicit reverse_wrapper(const T& a_v)
|
||||
: m_v(a_v) {}
|
||||
inline auto begin() -> decltype(m_v.rbegin()) { return m_v.rbegin(); }
|
||||
inline auto end() -> decltype(m_v.rend()) { return m_v.rend(); }
|
||||
auto begin() -> decltype(m_v.rbegin()) { return m_v.rbegin(); }
|
||||
auto end() -> decltype(m_v.rend()) { return m_v.rend(); }
|
||||
};
|
||||
|
||||
// C++20's std::ranges::reverse_view
|
||||
|
|
@ -563,6 +563,7 @@ template <class T>
|
|||
T const& as_const(T& v) {
|
||||
return v;
|
||||
}
|
||||
|
||||
}; // namespace vlstd
|
||||
|
||||
//=========================================================================
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ exclude_line_regexp(r'\bNUM_ASSERT')
|
|||
exclude_line_regexp(r'\bERROR_RSVD_WORD')
|
||||
exclude_line_regexp(r'\bV3ERROR_NA')
|
||||
exclude_line_regexp(r'\bUINFO\b')
|
||||
exclude_line_regexp(r'\bVL_DEFINE_DEBUG_FUNCTIONS\b')
|
||||
|
||||
# Exclude for branch coverage only
|
||||
exclude_branch_regexp(r'\bdebug\(\)')
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ ifeq ($(VL_NOOPT),1)
|
|||
CPPFLAGS += -O0
|
||||
else ifeq ($(VL_DEBUG),)
|
||||
# Optimize
|
||||
CPPFLAGS += -O2
|
||||
CPPFLAGS += -O3
|
||||
else
|
||||
# Debug
|
||||
CPPFLAGS += @CFG_CXXFLAGS_DEBUG@ -DVL_DEBUG -D_GLIBCXX_DEBUG
|
||||
|
|
@ -276,9 +276,16 @@ VLCOV_OBJS = \
|
|||
|
||||
NON_STANDALONE_HEADERS = \
|
||||
V3AstInlines.h \
|
||||
V3AstNodes.h \
|
||||
V3AstNodeDType.h \
|
||||
V3AstNodeMath.h \
|
||||
V3AstNodeOther.h \
|
||||
V3WidthCommit.h \
|
||||
|
||||
AST_DEFS := \
|
||||
V3AstNodeDType.h \
|
||||
V3AstNodeMath.h \
|
||||
V3AstNodeOther.h \
|
||||
|
||||
#### Linking
|
||||
|
||||
ifeq ($(VL_VLCOV),)
|
||||
|
|
@ -301,8 +308,8 @@ V3Number_test: V3Number_test.o
|
|||
|
||||
#### Modules
|
||||
|
||||
%__gen.cpp: %.cpp $(ASTGEN) V3Ast.h V3AstNodes.h
|
||||
$(PYTHON3) $(ASTGEN) -I $(srcdir) $*.cpp
|
||||
%__gen.cpp: %.cpp $(ASTGEN) $(AST_DEFS)
|
||||
$(PYTHON3) $(ASTGEN) -I $(srcdir) $(foreach f,$(AST_DEFS),--astdef $f) $*.cpp
|
||||
|
||||
%.o: %.cpp
|
||||
$(OBJCACHE) ${CXX} ${CXXFLAGS} ${CPPFLAGSWALL} -c $< -o $@
|
||||
|
|
@ -332,8 +339,8 @@ vlcovgen.d: $(VLCOVGEN) $(srcdir)/../include/verilated_cov_key.h
|
|||
$(PYTHON3) $(VLCOVGEN) --srcdir $(srcdir)
|
||||
touch $@
|
||||
|
||||
V3Ast__gen_classes.h : $(ASTGEN) V3Ast.h V3AstNodes.h
|
||||
$(PYTHON3) $(ASTGEN) -I $(srcdir) --classes
|
||||
V3Ast__gen_classes.h : $(ASTGEN) $(AST_DEFS)
|
||||
$(PYTHON3) $(ASTGEN) -I $(srcdir) $(foreach f,$(AST_DEFS),--astdef $f) --classes
|
||||
|
||||
V3ParseBison.h: V3ParseBison.c
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@
|
|||
|
||||
#include <unordered_map>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//***** See below for main transformation engine
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -66,8 +68,8 @@ public:
|
|||
: V3GraphVertex{graphp}
|
||||
, m_name{name}
|
||||
, m_type{type} {}
|
||||
virtual string name() const override { return m_name + " " + typestr(); }
|
||||
virtual string dotColor() const override { return user() ? "green" : "black"; }
|
||||
string name() const override { return m_name + " " + typestr(); }
|
||||
string dotColor() const override { return user() ? "green" : "black"; }
|
||||
virtual int type() const { return m_type; }
|
||||
};
|
||||
|
||||
|
|
@ -79,8 +81,6 @@ protected:
|
|||
LatchDetectGraphVertex* m_curVertexp = nullptr; // Current latch detection graph vertex
|
||||
std::vector<AstVarRef*> m_outputs; // Vector of lvalues encountered on this pass
|
||||
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
static LatchDetectGraphVertex* castVertexp(void* vertexp) {
|
||||
return reinterpret_cast<LatchDetectGraphVertex*>(vertexp);
|
||||
}
|
||||
|
|
@ -120,7 +120,7 @@ protected:
|
|||
|
||||
public:
|
||||
LatchDetectGraph() { clear(); }
|
||||
virtual ~LatchDetectGraph() override { clear(); }
|
||||
~LatchDetectGraph() override { clear(); }
|
||||
// ACCESSORS
|
||||
LatchDetectGraphVertex* currentp() { return m_curVertexp; }
|
||||
void currentp(LatchDetectGraphVertex* vertex) { m_curVertexp = vertex; }
|
||||
|
|
@ -183,7 +183,7 @@ public:
|
|||
<< " (not all control paths of combinational always assign a value)\n"
|
||||
<< nodep->warnMore()
|
||||
<< "... Suggest use of always_latch for intentional latches");
|
||||
if (debug() >= 9) dumpDotFilePrefixed("latch_" + vrp->name());
|
||||
if (dumpGraph() >= 9) dumpDotFilePrefixed("latch_" + vrp->name());
|
||||
}
|
||||
vertp->user(false); // Clear again (see above)
|
||||
vrp->varp()->isLatched(latch_detected);
|
||||
|
|
@ -198,12 +198,7 @@ public:
|
|||
//######################################################################
|
||||
// Collect existing active names
|
||||
|
||||
class ActiveBaseVisitor VL_NOT_FINAL : public VNVisitor {
|
||||
protected:
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
};
|
||||
|
||||
class ActiveNamer final : public ActiveBaseVisitor {
|
||||
class ActiveNamer final : public VNVisitor {
|
||||
private:
|
||||
// STATE
|
||||
AstScope* m_scopep = nullptr; // Current scope to add statement to
|
||||
|
|
@ -216,10 +211,10 @@ private:
|
|||
// METHODS
|
||||
void addActive(AstActive* nodep) {
|
||||
UASSERT_OBJ(m_scopep, nodep, "nullptr scope");
|
||||
m_scopep->addActivep(nodep);
|
||||
m_scopep->addBlocksp(nodep);
|
||||
}
|
||||
// VISITORS
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
void visit(AstScope* nodep) override {
|
||||
m_scopep = nodep;
|
||||
m_iActivep = nullptr;
|
||||
m_cActivep = nullptr;
|
||||
|
|
@ -227,13 +222,13 @@ private:
|
|||
iterateChildren(nodep);
|
||||
// Don't clear scopep, the namer persists beyond this visit
|
||||
}
|
||||
virtual void visit(AstSenTree* nodep) override {
|
||||
void visit(AstSenTree* nodep) override {
|
||||
// Simplify sensitivity list
|
||||
VL_DO_DANGLING(V3Const::constifyExpensiveEdit(nodep), nodep);
|
||||
}
|
||||
//--------------------
|
||||
virtual void visit(AstNodeStmt*) override {} // Accelerate
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNodeStmt*) override {} // Accelerate
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// METHODS
|
||||
|
|
@ -275,14 +270,14 @@ public:
|
|||
|
||||
// CONSTRUCTORS
|
||||
ActiveNamer() = default;
|
||||
virtual ~ActiveNamer() override = default;
|
||||
~ActiveNamer() override = default;
|
||||
void main(AstScope* nodep) { iterate(nodep); }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Latch checking visitor
|
||||
|
||||
class ActiveLatchCheckVisitor final : public ActiveBaseVisitor {
|
||||
class ActiveLatchCheckVisitor final : public VNVisitor {
|
||||
private:
|
||||
// NODE STATE
|
||||
// Input:
|
||||
|
|
@ -291,25 +286,25 @@ private:
|
|||
// STATE
|
||||
LatchDetectGraph m_graph; // Graph used to detect latches in combo always
|
||||
// VISITORS
|
||||
virtual void visit(AstVarRef* nodep) override {
|
||||
void visit(AstVarRef* nodep) override {
|
||||
const AstVar* const varp = nodep->varp();
|
||||
if (nodep->access().isWriteOrRW() && varp->isSignal() && !varp->isUsedLoopIdx()) {
|
||||
m_graph.addAssignment(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeIf* nodep) override {
|
||||
void visit(AstNodeIf* nodep) override {
|
||||
if (!nodep->isBoundsCheck()) {
|
||||
LatchDetectGraphVertex* const parentp = m_graph.currentp();
|
||||
LatchDetectGraphVertex* const branchp = m_graph.addPathVertex(parentp, "BRANCH", true);
|
||||
m_graph.addPathVertex(branchp, "IF");
|
||||
iterateAndNextNull(nodep->ifsp());
|
||||
iterateAndNextNull(nodep->thensp());
|
||||
m_graph.addPathVertex(branchp, "ELSE");
|
||||
iterateAndNextNull(nodep->elsesp());
|
||||
m_graph.currentp(parentp);
|
||||
}
|
||||
}
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
|
|
@ -324,7 +319,7 @@ public:
|
|||
//######################################################################
|
||||
// Replace unsupported non-blocking assignments with blocking assignments
|
||||
|
||||
class ActiveDlyVisitor final : public ActiveBaseVisitor {
|
||||
class ActiveDlyVisitor final : public VNVisitor {
|
||||
public:
|
||||
enum CheckType : uint8_t { CT_SEQ, CT_COMB, CT_INITIAL };
|
||||
|
||||
|
|
@ -333,7 +328,7 @@ private:
|
|||
const CheckType m_check; // Process type we are checking
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstAssignDly* nodep) override {
|
||||
void visit(AstAssignDly* nodep) override {
|
||||
// Non-blocking assignments are OK in sequential processes
|
||||
if (m_check == CT_SEQ) return;
|
||||
|
||||
|
|
@ -357,7 +352,7 @@ private:
|
|||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstAssign* nodep) override {
|
||||
void visit(AstAssign* nodep) override {
|
||||
// Blocking assignments are always OK in combinational (and initial/final) processes
|
||||
if (m_check != CT_SEQ) return;
|
||||
|
||||
|
|
@ -380,7 +375,7 @@ private:
|
|||
}
|
||||
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
|
|
@ -394,7 +389,7 @@ public:
|
|||
//######################################################################
|
||||
// Active class functions
|
||||
|
||||
class ActiveVisitor final : public ActiveBaseVisitor {
|
||||
class ActiveVisitor final : public VNVisitor {
|
||||
private:
|
||||
// NODE STATE
|
||||
// Each call to V3Const::constify
|
||||
|
|
@ -407,7 +402,7 @@ private:
|
|||
bool m_itemSequent = false; // Found a SenItem sequential
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
void visit(AstScope* nodep) override {
|
||||
// Create required actives and add to scope
|
||||
UINFO(4, " SCOPE " << nodep << endl);
|
||||
// Clear last scope's names, and collect this scope's existing names
|
||||
|
|
@ -415,10 +410,10 @@ private:
|
|||
m_scopeFinalp = nullptr;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstActive* nodep) override {
|
||||
void visit(AstActive* nodep) override {
|
||||
// Actives are being formed, so we can ignore any already made
|
||||
}
|
||||
virtual void visit(AstInitialStatic* nodep) override {
|
||||
void visit(AstInitialStatic* nodep) override {
|
||||
// Relink to IACTIVE, unless already under it
|
||||
UINFO(4, " INITIAL " << nodep << endl);
|
||||
const ActiveDlyVisitor dlyvisitor{nodep, ActiveDlyVisitor::CT_INITIAL};
|
||||
|
|
@ -426,7 +421,7 @@ private:
|
|||
nodep->unlinkFrBack();
|
||||
wantactivep->addStmtsp(nodep);
|
||||
}
|
||||
virtual void visit(AstInitial* nodep) override {
|
||||
void visit(AstInitial* nodep) override {
|
||||
// Relink to IACTIVE, unless already under it
|
||||
UINFO(4, " INITIAL " << nodep << endl);
|
||||
const ActiveDlyVisitor dlyvisitor{nodep, ActiveDlyVisitor::CT_INITIAL};
|
||||
|
|
@ -434,31 +429,31 @@ private:
|
|||
nodep->unlinkFrBack();
|
||||
wantactivep->addStmtsp(nodep);
|
||||
}
|
||||
virtual void visit(AstAssignAlias* nodep) override {
|
||||
void visit(AstAssignAlias* nodep) override {
|
||||
// Relink to CACTIVE, unless already under it
|
||||
UINFO(4, " ASSIGNW " << nodep << endl);
|
||||
AstActive* const wantactivep = m_namer.getCActive(nodep->fileline());
|
||||
nodep->unlinkFrBack();
|
||||
wantactivep->addStmtsp(nodep);
|
||||
}
|
||||
virtual void visit(AstAssignW* nodep) override {
|
||||
void visit(AstAssignW* nodep) override {
|
||||
// Relink to CACTIVE, unless already under it
|
||||
UINFO(4, " ASSIGNW " << nodep << endl);
|
||||
AstActive* const wantactivep = m_namer.getCActive(nodep->fileline());
|
||||
nodep->unlinkFrBack();
|
||||
wantactivep->addStmtsp(nodep);
|
||||
}
|
||||
virtual void visit(AstCoverToggle* nodep) override {
|
||||
void visit(AstCoverToggle* nodep) override {
|
||||
// Relink to CACTIVE, unless already under it
|
||||
UINFO(4, " COVERTOGGLE " << nodep << endl);
|
||||
AstActive* const wantactivep = m_namer.getCActive(nodep->fileline());
|
||||
nodep->unlinkFrBack();
|
||||
wantactivep->addStmtsp(nodep);
|
||||
}
|
||||
virtual void visit(AstFinal* nodep) override {
|
||||
void visit(AstFinal* nodep) override {
|
||||
// Relink to CFUNC for the final
|
||||
UINFO(4, " FINAL " << nodep << endl);
|
||||
if (!nodep->bodysp()) { // Empty, Kill it.
|
||||
if (!nodep->stmtsp()) { // Empty, Kill it.
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
return;
|
||||
}
|
||||
|
|
@ -471,10 +466,10 @@ private:
|
|||
m_scopeFinalp->isStatic(false);
|
||||
m_scopeFinalp->isLoose(true);
|
||||
m_scopeFinalp->slow(true);
|
||||
m_namer.scopep()->addActivep(m_scopeFinalp);
|
||||
m_namer.scopep()->addBlocksp(m_scopeFinalp);
|
||||
}
|
||||
nodep->unlinkFrBack();
|
||||
m_scopeFinalp->addStmtsp(nodep->bodysp()->unlinkFrBackWithNext());
|
||||
m_scopeFinalp->addStmtsp(nodep->stmtsp()->unlinkFrBackWithNext());
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
|
||||
|
|
@ -537,33 +532,33 @@ private:
|
|||
ActiveDlyVisitor{nodep, ActiveDlyVisitor::CT_SEQ};
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAlways* nodep) override {
|
||||
void visit(AstAlways* nodep) override {
|
||||
// Move always to appropriate ACTIVE based on its sense list
|
||||
UINFO(4, " ALW " << nodep << endl);
|
||||
// if (debug() >= 9) nodep->dumpTree(cout, " Alw: ");
|
||||
|
||||
if (!nodep->bodysp()) {
|
||||
if (!nodep->stmtsp()) {
|
||||
// Empty always. Kill it.
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
return;
|
||||
}
|
||||
visitAlways(nodep, nodep->sensesp(), nodep->keyword());
|
||||
}
|
||||
virtual void visit(AstAlwaysPostponed* nodep) override {
|
||||
void visit(AstAlwaysPostponed* nodep) override {
|
||||
UINFO(4, " ALW " << nodep << endl);
|
||||
if (!nodep->bodysp()) {
|
||||
if (!nodep->stmtsp()) {
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
return;
|
||||
}
|
||||
visitAlways(nodep, nullptr, VAlwaysKwd::ALWAYS);
|
||||
}
|
||||
virtual void visit(AstAlwaysPublic* nodep) override {
|
||||
void visit(AstAlwaysPublic* nodep) override {
|
||||
// Move always to appropriate ACTIVE based on its sense list
|
||||
UINFO(4, " ALWPub " << nodep << endl);
|
||||
// if (debug() >= 9) nodep->dumpTree(cout, " Alw: ");
|
||||
visitAlways(nodep, nodep->sensesp(), VAlwaysKwd::ALWAYS);
|
||||
}
|
||||
virtual void visit(AstSenItem* nodep) override {
|
||||
void visit(AstSenItem* nodep) override {
|
||||
if (nodep->varrefp()) {
|
||||
if (const AstBasicDType* const basicp = nodep->varrefp()->dtypep()->basicp()) {
|
||||
if (basicp->isEventValue()) {
|
||||
|
|
@ -592,9 +587,9 @@ private:
|
|||
}
|
||||
|
||||
//--------------------
|
||||
virtual void visit(AstNodeMath*) override {} // Accelerate
|
||||
virtual void visit(AstVarScope*) override {} // Accelerate
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNodeMath*) override {} // Accelerate
|
||||
void visit(AstVarScope*) override {} // Accelerate
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
|
|
@ -608,5 +603,5 @@ public:
|
|||
void V3Active::activeAll(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ ActiveVisitor{nodep}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("active", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("active", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
#include "V3Global.h"
|
||||
#include "V3SenTree.h"
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Active class functions
|
||||
|
||||
|
|
@ -49,16 +51,15 @@ private:
|
|||
SenTreeFinder m_finder; // Find global sentree's / add them under the AstTopScope
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
// Create required actives and add to module
|
||||
// We can start ordering at a module, or a scope
|
||||
UINFO(4, " MOD " << nodep << endl);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstActive* nodep) override {
|
||||
void visit(AstActive* nodep) override {
|
||||
UINFO(4, " ACTIVE " << nodep << endl);
|
||||
// Remove duplicate clocks and such; sensesp() may change!
|
||||
V3Const::constifyExpensiveEdit(nodep);
|
||||
|
|
@ -101,27 +102,27 @@ private:
|
|||
// No need to do statements under it, they're already moved.
|
||||
// iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeProcedure* nodep) override { // LCOV_EXCL_LINE
|
||||
void visit(AstNodeProcedure* nodep) override { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
}
|
||||
virtual void visit(AstAssignAlias* nodep) override { // LCOV_EXCL_LINE
|
||||
void visit(AstAssignAlias* nodep) override { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
}
|
||||
virtual void visit(AstAssignW* nodep) override { // LCOV_EXCL_LINE
|
||||
void visit(AstAssignW* nodep) override { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
}
|
||||
virtual void visit(AstAlwaysPublic* nodep) override { // LCOV_EXCL_LINE
|
||||
void visit(AstAlwaysPublic* nodep) override { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
}
|
||||
//--------------------
|
||||
virtual void visit(AstNodeMath*) override {} // Accelerate
|
||||
virtual void visit(AstVarScope*) override {} // Accelerate
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNodeMath*) override {} // Accelerate
|
||||
void visit(AstVarScope*) override {} // Accelerate
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit ActiveTopVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~ActiveTopVisitor() override = default;
|
||||
~ActiveTopVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -130,5 +131,5 @@ public:
|
|||
void V3ActiveTop::activeTopAll(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ ActiveTopVisitor{nodep}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("activetop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("activetop", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
#include "V3Global.h"
|
||||
#include "V3Stats.h"
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Assert class functions
|
||||
|
||||
|
|
@ -70,7 +72,7 @@ private:
|
|||
if (!m_monitorNumVarp) {
|
||||
m_monitorNumVarp = new AstVar{nodep->fileline(), VVarType::MODULETEMP, "__VmonitorNum",
|
||||
nodep->findUInt64DType()};
|
||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(m_monitorNumVarp);
|
||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(m_monitorNumVarp);
|
||||
}
|
||||
const auto varrefp = new AstVarRef(nodep->fileline(), m_monitorNumVarp, access);
|
||||
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||
|
|
@ -80,7 +82,7 @@ private:
|
|||
if (!m_monitorOffVarp) {
|
||||
m_monitorOffVarp = new AstVar{nodep->fileline(), VVarType::MODULETEMP, "__VmonitorOff",
|
||||
nodep->findBitDType()};
|
||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtp(m_monitorOffVarp);
|
||||
v3Global.rootp()->dollarUnitPkgAddp()->addStmtsp(m_monitorOffVarp);
|
||||
}
|
||||
const auto varrefp = new AstVarRef(nodep->fileline(), m_monitorOffVarp, access);
|
||||
varrefp->classOrPackagep(v3Global.rootp()->dollarUnitPkgAddp());
|
||||
|
|
@ -147,7 +149,7 @@ private:
|
|||
selfDestruct = true;
|
||||
} else {
|
||||
// V3Coverage assigned us a bucket to increment.
|
||||
AstCoverInc* const covincp = VN_AS(snodep->coverincp(), CoverInc);
|
||||
AstCoverInc* const covincp = VN_AS(snodep->coverincsp(), CoverInc);
|
||||
UASSERT_OBJ(covincp, snodep, "Missing AstCoverInc under assertion");
|
||||
covincp->unlinkFrBackWithNext(); // next() might have AstAssign for trace
|
||||
if (message != "") covincp->declp()->comment(message);
|
||||
|
|
@ -196,7 +198,7 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstIf* nodep) override {
|
||||
void visit(AstIf* nodep) override {
|
||||
if (nodep->user1SetOnce()) return;
|
||||
if (nodep->uniquePragma() || nodep->unique0Pragma()) {
|
||||
const AstNodeIf* ifp = nodep;
|
||||
|
|
@ -209,7 +211,7 @@ private:
|
|||
iterateAndNextNull(ifp->condp());
|
||||
|
||||
// Recurse into the true case.
|
||||
iterateAndNextNull(ifp->ifsp());
|
||||
iterateAndNextNull(ifp->thensp());
|
||||
|
||||
// If the last else is not an else if, recurse into that too.
|
||||
if (ifp->elsesp() && !nextifp) { //
|
||||
|
|
@ -254,7 +256,7 @@ private:
|
|||
}
|
||||
|
||||
//========== Case assertions
|
||||
virtual void visit(AstCase* nodep) override {
|
||||
void visit(AstCase* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (!nodep->user1SetOnce()) {
|
||||
bool has_default = false;
|
||||
|
|
@ -323,7 +325,7 @@ private:
|
|||
}
|
||||
|
||||
//========== Past
|
||||
virtual void visit(AstPast* nodep) override {
|
||||
void visit(AstPast* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
uint32_t ticks = 1;
|
||||
if (nodep->ticksp()) {
|
||||
|
|
@ -338,28 +340,28 @@ private:
|
|||
sentreep->unlinkFrBack();
|
||||
AstAlways* const alwaysp
|
||||
= new AstAlways(nodep->fileline(), VAlwaysKwd::ALWAYS, sentreep, nullptr);
|
||||
m_modp->addStmtp(alwaysp);
|
||||
m_modp->addStmtsp(alwaysp);
|
||||
for (uint32_t i = 0; i < ticks; ++i) {
|
||||
AstVar* const outvarp = new AstVar(
|
||||
nodep->fileline(), VVarType::MODULETEMP,
|
||||
"_Vpast_" + cvtToStr(m_modPastNum++) + "_" + cvtToStr(i), inp->dtypep());
|
||||
m_modp->addStmtp(outvarp);
|
||||
m_modp->addStmtsp(outvarp);
|
||||
AstNode* const assp = new AstAssignDly(
|
||||
nodep->fileline(), new AstVarRef(nodep->fileline(), outvarp, VAccess::WRITE), inp);
|
||||
alwaysp->addStmtp(assp);
|
||||
alwaysp->addStmtsp(assp);
|
||||
// if (debug() >= 9) assp->dumpTree(cout, "-ass: ");
|
||||
invarp = outvarp;
|
||||
inp = new AstVarRef(nodep->fileline(), invarp, VAccess::READ);
|
||||
}
|
||||
nodep->replaceWith(inp);
|
||||
}
|
||||
virtual void visit(AstSampled* nodep) override {
|
||||
void visit(AstSampled* nodep) override {
|
||||
nodep->replaceWith(nodep->exprp()->unlinkFrBack());
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
|
||||
//========== Statements
|
||||
virtual void visit(AstDisplay* nodep) override {
|
||||
void visit(AstDisplay* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
// Replace the special types with standard text
|
||||
if (nodep->displayType() == VDisplayType::DT_INFO) {
|
||||
|
|
@ -387,7 +389,7 @@ private:
|
|||
stmtsp};
|
||||
ifp->branchPred(VBranchPred::BP_UNLIKELY);
|
||||
AstNode* const newp = new AstAlwaysPostponed{fl, ifp};
|
||||
m_modp->addStmtp(newp);
|
||||
m_modp->addStmtsp(newp);
|
||||
} else if (nodep->displayType() == VDisplayType::DT_STROBE) {
|
||||
nodep->displayType(VDisplayType::DT_DISPLAY);
|
||||
// Need one-shot
|
||||
|
|
@ -395,7 +397,7 @@ private:
|
|||
const auto varp
|
||||
= new AstVar{fl, VVarType::MODULETEMP, "__Vstrobe" + cvtToStr(m_modStrobeNum++),
|
||||
nodep->findBitDType()};
|
||||
m_modp->addStmtp(varp);
|
||||
m_modp->addStmtsp(varp);
|
||||
// Where $strobe was we do "__Vstrobe = '1;"
|
||||
const auto newsetp = new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE},
|
||||
new AstConst{fl, AstConst::BitTrue{}}};
|
||||
|
|
@ -407,35 +409,35 @@ private:
|
|||
AstNode* const newp = new AstAlwaysPostponed{fl, ifp};
|
||||
stmtsp->addNext(new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE},
|
||||
new AstConst{fl, AstConst::BitFalse{}}});
|
||||
m_modp->addStmtp(newp);
|
||||
m_modp->addStmtsp(newp);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstMonitorOff* nodep) override {
|
||||
void visit(AstMonitorOff* nodep) override {
|
||||
const auto newp
|
||||
= new AstAssign(nodep->fileline(), newMonitorOffVarRefp(nodep, VAccess::WRITE),
|
||||
new AstConst(nodep->fileline(), AstConst::BitTrue{}, nodep->off()));
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
virtual void visit(AstAssert* nodep) override {
|
||||
void visit(AstAssert* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
newPslAssertion(nodep, nodep->failsp());
|
||||
}
|
||||
virtual void visit(AstAssertIntrinsic* nodep) override {
|
||||
void visit(AstAssertIntrinsic* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
newPslAssertion(nodep, nodep->failsp());
|
||||
}
|
||||
virtual void visit(AstCover* nodep) override {
|
||||
void visit(AstCover* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
newPslAssertion(nodep, nullptr);
|
||||
}
|
||||
virtual void visit(AstRestrict* nodep) override {
|
||||
void visit(AstRestrict* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
// IEEE says simulator ignores these
|
||||
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
VL_RESTORER(m_modPastNum);
|
||||
VL_RESTORER(m_modStrobeNum);
|
||||
|
|
@ -446,7 +448,7 @@ private:
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstBegin* nodep) override {
|
||||
void visit(AstBegin* nodep) override {
|
||||
// This code is needed rather than a visitor in V3Begin,
|
||||
// because V3Assert is called before V3Begin
|
||||
VL_RESTORER(m_beginp);
|
||||
|
|
@ -456,12 +458,12 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit AssertVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~AssertVisitor() override {
|
||||
~AssertVisitor() override {
|
||||
V3Stats::addStat("Assertions, assert non-immediate statements", m_statAsNotImm);
|
||||
V3Stats::addStat("Assertions, assert immediate statements", m_statAsImm);
|
||||
V3Stats::addStat("Assertions, cover statements", m_statCover);
|
||||
|
|
@ -475,5 +477,5 @@ public:
|
|||
void V3Assert::assertAll(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ AssertVisitor{nodep}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("assert", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("assert", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
#include "V3Ast.h"
|
||||
#include "V3Global.h"
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Assert class functions
|
||||
|
||||
|
|
@ -45,7 +47,6 @@ private:
|
|||
AstNode* m_disablep = nullptr; // Last disable
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
AstSenTree* newSenTree(AstNode* nodep) {
|
||||
// Create sentree based on clocked or default clock
|
||||
|
|
@ -69,7 +70,7 @@ private:
|
|||
|
||||
// VISITORS
|
||||
//========== Statements
|
||||
virtual void visit(AstClocking* nodep) override {
|
||||
void visit(AstClocking* nodep) override {
|
||||
UINFO(8, " CLOCKING" << nodep << endl);
|
||||
// Store the new default clock, reset on new module
|
||||
m_seniDefaultp = nodep->sensesp();
|
||||
|
|
@ -81,14 +82,14 @@ private:
|
|||
}
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
virtual void visit(AstAlways* nodep) override {
|
||||
void visit(AstAlways* nodep) override {
|
||||
iterateAndNextNull(nodep->sensesp());
|
||||
if (nodep->sensesp()) m_seniAlwaysp = nodep->sensesp()->sensesp();
|
||||
iterateAndNextNull(nodep->bodysp());
|
||||
iterateAndNextNull(nodep->stmtsp());
|
||||
m_seniAlwaysp = nullptr;
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeCoverOrAssert* nodep) override {
|
||||
void visit(AstNodeCoverOrAssert* nodep) override {
|
||||
if (nodep->sentreep()) return; // Already processed
|
||||
clearAssertInfo();
|
||||
// Find Clocking's buried under nodep->exprsp
|
||||
|
|
@ -96,7 +97,7 @@ private:
|
|||
if (!nodep->immediate()) nodep->sentreep(newSenTree(nodep));
|
||||
clearAssertInfo();
|
||||
}
|
||||
virtual void visit(AstFell* nodep) override {
|
||||
void visit(AstFell* nodep) override {
|
||||
if (nodep->sentreep()) return; // Already processed
|
||||
iterateChildren(nodep);
|
||||
FileLine* const fl = nodep->fileline();
|
||||
|
|
@ -110,12 +111,12 @@ private:
|
|||
nodep->sentreep(newSenTree(nodep));
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
virtual void visit(AstPast* nodep) override {
|
||||
void visit(AstPast* nodep) override {
|
||||
if (nodep->sentreep()) return; // Already processed
|
||||
iterateChildren(nodep);
|
||||
nodep->sentreep(newSenTree(nodep));
|
||||
}
|
||||
virtual void visit(AstRose* nodep) override {
|
||||
void visit(AstRose* nodep) override {
|
||||
if (nodep->sentreep()) return; // Already processed
|
||||
iterateChildren(nodep);
|
||||
FileLine* const fl = nodep->fileline();
|
||||
|
|
@ -129,7 +130,7 @@ private:
|
|||
nodep->sentreep(newSenTree(nodep));
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
virtual void visit(AstStable* nodep) override {
|
||||
void visit(AstStable* nodep) override {
|
||||
if (nodep->sentreep()) return; // Already processed
|
||||
iterateChildren(nodep);
|
||||
FileLine* const fl = nodep->fileline();
|
||||
|
|
@ -143,7 +144,7 @@ private:
|
|||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstImplication* nodep) override {
|
||||
void visit(AstImplication* nodep) override {
|
||||
if (nodep->sentreep()) return; // Already processed
|
||||
|
||||
FileLine* const fl = nodep->fileline();
|
||||
|
|
@ -161,7 +162,7 @@ private:
|
|||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstPropClocked* nodep) override {
|
||||
void visit(AstPropClocked* nodep) override {
|
||||
// No need to iterate the body, once replace will get iterated
|
||||
iterateAndNextNull(nodep->sensesp());
|
||||
if (m_senip)
|
||||
|
|
@ -183,12 +184,12 @@ private:
|
|||
nodep->replaceWith(blockp);
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
// Reset defaults
|
||||
m_seniDefaultp = nullptr;
|
||||
}
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
|
|
@ -197,7 +198,7 @@ public:
|
|||
// Process
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~AssertPreVisitor() override = default;
|
||||
~AssertPreVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -206,5 +207,5 @@ public:
|
|||
void V3AssertPre::assertPreAll(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ AssertPreVisitor{nodep}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("assertpre", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("assertpre", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include <iomanip>
|
||||
#include <memory>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//======================================================================
|
||||
// Statics
|
||||
|
||||
|
|
@ -165,22 +167,22 @@ string AstNode::prettyName(const string& namein) {
|
|||
continue;
|
||||
}
|
||||
if (pos[0] == '_' && pos[1] == '_') { // Short-circuit
|
||||
if (0 == strncmp(pos, "__BRA__", 7)) {
|
||||
if (0 == std::strncmp(pos, "__BRA__", 7)) {
|
||||
pretty += "[";
|
||||
pos += 7;
|
||||
continue;
|
||||
}
|
||||
if (0 == strncmp(pos, "__KET__", 7)) {
|
||||
if (0 == std::strncmp(pos, "__KET__", 7)) {
|
||||
pretty += "]";
|
||||
pos += 7;
|
||||
continue;
|
||||
}
|
||||
if (0 == strncmp(pos, "__DOT__", 7)) {
|
||||
if (0 == std::strncmp(pos, "__DOT__", 7)) {
|
||||
pretty += ".";
|
||||
pos += 7;
|
||||
continue;
|
||||
}
|
||||
if (0 == strncmp(pos, "__PVT__", 7)) {
|
||||
if (0 == std::strncmp(pos, "__PVT__", 7)) {
|
||||
pretty += "";
|
||||
pos += 7;
|
||||
continue;
|
||||
|
|
@ -212,8 +214,7 @@ string AstNode::prettyTypeName() const {
|
|||
//######################################################################
|
||||
// Insertion
|
||||
|
||||
inline void AstNode::debugTreeChange(const AstNode* nodep, const char* prefix, int lineno,
|
||||
bool next){
|
||||
void AstNode::debugTreeChange(const AstNode* nodep, const char* prefix, int lineno, bool next) {
|
||||
#ifdef VL_DEBUG
|
||||
// Called on all major tree changers.
|
||||
// Only for use for those really nasty bugs relating to internals
|
||||
|
|
@ -234,7 +235,8 @@ inline void AstNode::debugTreeChange(const AstNode* nodep, const char* prefix, i
|
|||
#endif
|
||||
}
|
||||
|
||||
AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp) {
|
||||
template <>
|
||||
AstNode* AstNode::addNext<AstNode, AstNode>(AstNode* nodep, AstNode* newp) {
|
||||
// Add to m_nextp, returns this
|
||||
UDEBUGONLY(UASSERT_OBJ(newp, nodep, "Null item passed to addNext"););
|
||||
debugTreeChange(nodep, "-addNextThs: ", __LINE__, false);
|
||||
|
|
@ -272,11 +274,6 @@ AstNode* AstNode::addNext(AstNode* nodep, AstNode* newp) {
|
|||
return nodep;
|
||||
}
|
||||
|
||||
AstNode* AstNode::addNextNull(AstNode* nodep, AstNode* newp) {
|
||||
if (!newp) return nodep;
|
||||
return addNext(nodep, newp);
|
||||
}
|
||||
|
||||
void AstNode::addNextHere(AstNode* newp) {
|
||||
// Add to m_nextp on exact node passed, not at the end.
|
||||
// This could be at head, tail, or both (single)
|
||||
|
|
@ -925,7 +922,7 @@ AstNode* AstNode::iterateSubtreeReturnEdits(VNVisitor& v) {
|
|||
} else if (!nodep->backp()) {
|
||||
// Calling on standalone tree; insert a shim node so we can keep
|
||||
// track, then delete it on completion
|
||||
AstBegin* const tempp = new AstBegin(nodep->fileline(), "[EditWrapper]", nodep);
|
||||
AstBegin* const tempp = new AstBegin{nodep->fileline(), "[EditWrapper]", nodep};
|
||||
{
|
||||
VL_DO_DANGLING(tempp->stmtsp()->accept(v),
|
||||
nodep); // nodep to null as may be replaced
|
||||
|
|
@ -1004,43 +1001,12 @@ bool AstNode::sameTreeIter(const AstNode* node1p, const AstNode* node2p, bool ig
|
|||
//======================================================================
|
||||
// Debugging
|
||||
|
||||
void AstNode::checkTreeIter(AstNode* backp) {
|
||||
void AstNode::checkTreeIter(const AstNode* backp) const {
|
||||
// private: Check a tree and children
|
||||
UASSERT_OBJ(backp == this->backp(), this, "Back node inconsistent");
|
||||
if (VN_IS(this, NodeTermop) || VN_IS(this, NodeVarRef)) {
|
||||
// Termops have a short-circuited iterateChildren, so check usage
|
||||
UASSERT_OBJ(!(op1p() || op2p() || op3p() || op4p()), this,
|
||||
"Terminal operation with non-terminals");
|
||||
}
|
||||
if (m_op1p) m_op1p->checkTreeIterList(this);
|
||||
if (m_op2p) m_op2p->checkTreeIterList(this);
|
||||
if (m_op3p) m_op3p->checkTreeIterList(this);
|
||||
if (m_op4p) m_op4p->checkTreeIterList(this);
|
||||
}
|
||||
|
||||
void AstNode::checkTreeIterList(AstNode* backp) {
|
||||
// private: Check a (possible) list of nodes, this is always the head of the list
|
||||
// Audited to make sure this is never nullptr
|
||||
AstNode* const headp = this;
|
||||
const AstNode* tailp = this;
|
||||
for (AstNode* nodep = headp; nodep; nodep = nodep->nextp()) {
|
||||
nodep->checkTreeIter(backp);
|
||||
UASSERT_OBJ(headp == this || !nextp(), this,
|
||||
"Headtailp should be null in middle of lists");
|
||||
tailp = nodep;
|
||||
backp = nodep;
|
||||
}
|
||||
UASSERT_OBJ(headp->m_headtailp == tailp, headp, "Tail in headtailp is inconsistent");
|
||||
UASSERT_OBJ(tailp->m_headtailp == headp, tailp, "Head in headtailp is inconsistent");
|
||||
}
|
||||
|
||||
void AstNode::checkTree() {
|
||||
if (!debug()) return;
|
||||
if (this->backp()) {
|
||||
// Linked tree- check only the passed node
|
||||
this->checkTreeIter(this->backp());
|
||||
} else {
|
||||
this->checkTreeIterList(this->backp());
|
||||
switch (this->type()) {
|
||||
#include "V3Ast__gen_op_checks.h"
|
||||
default: VL_UNREACHABLE; // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1156,7 +1122,7 @@ void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump, boo
|
|||
if (logsp->fail()) v3fatal("Can't write " << filename);
|
||||
*logsp << "Verilator Tree Dump (format 0x3900) from <e" << std::dec << editCountLast();
|
||||
*logsp << "> to <e" << std::dec << editCountGbl() << ">\n";
|
||||
if (editCountGbl() == editCountLast() && !(v3Global.opt.dumpTree() >= 9)) {
|
||||
if (editCountGbl() == editCountLast() && ::dumpTree() < 9) {
|
||||
*logsp << '\n';
|
||||
*logsp << "No changes since last dump!\n";
|
||||
} else {
|
||||
|
|
@ -1166,7 +1132,7 @@ void AstNode::dumpTreeFile(const string& filename, bool append, bool doDump, boo
|
|||
}
|
||||
}
|
||||
if (doDump && v3Global.opt.debugEmitV()) V3EmitV::debugEmitV(filename + ".v");
|
||||
if (doCheck && (v3Global.opt.debugCheck() || v3Global.opt.dumpTree())) {
|
||||
if (doCheck && (v3Global.opt.debugCheck() || ::dumpTree())) {
|
||||
// Error check
|
||||
checkTree();
|
||||
// Broken isn't part of check tree because it can munge iterp's
|
||||
|
|
@ -1217,7 +1183,11 @@ void AstNode::v3errorEnd(std::ostringstream& str) const {
|
|||
const_cast<AstNode*>(this)->dump(nsstr);
|
||||
nsstr << endl;
|
||||
}
|
||||
m_fileline->v3errorEnd(nsstr, instanceStr());
|
||||
// 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::errorCode()) ? "" : instanceStr());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
1651
src/V3Ast.h
1651
src/V3Ast.h
File diff suppressed because it is too large
Load Diff
|
|
@ -17,71 +17,175 @@
|
|||
#ifndef VERILATOR_V3ASTINLINES_H_
|
||||
#define VERILATOR_V3ASTINLINES_H_
|
||||
|
||||
#ifndef VERILATOR_V3ASTNODES_H_
|
||||
#ifndef VERILATOR_V3AST_H_
|
||||
#error "Use V3Ast.h as the include"
|
||||
#include "V3AstNodes.h" // This helps code analysis tools pick up symbols in V3Ast.h and V3AstNodes.h
|
||||
#include "V3Ast.h" // This helps code analysis tools pick up symbols in V3Ast.h and relaed
|
||||
#endif
|
||||
|
||||
//######################################################################
|
||||
// Inline ACCESSORS
|
||||
// Inline METHODS
|
||||
|
||||
inline int AstNode::width() const { return dtypep() ? dtypep()->width() : 0; }
|
||||
inline int AstNode::widthMin() const { return dtypep() ? dtypep()->widthMin() : 0; }
|
||||
inline bool AstNode::width1() const { // V3Const uses to know it can optimize
|
||||
int AstNode::width() const { return dtypep() ? dtypep()->width() : 0; }
|
||||
int AstNode::widthMin() const { return dtypep() ? dtypep()->widthMin() : 0; }
|
||||
bool AstNode::width1() const { // V3Const uses to know it can optimize
|
||||
return dtypep() && dtypep()->width() == 1;
|
||||
}
|
||||
inline int AstNode::widthInstrs() const {
|
||||
int AstNode::widthInstrs() const {
|
||||
return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1));
|
||||
}
|
||||
inline bool AstNode::isDouble() const {
|
||||
bool AstNode::isDouble() const {
|
||||
return dtypep() && VN_IS(dtypep(), BasicDType) && VN_AS(dtypep(), BasicDType)->isDouble();
|
||||
}
|
||||
inline bool AstNode::isString() const {
|
||||
bool AstNode::isString() const {
|
||||
return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString();
|
||||
}
|
||||
inline bool AstNode::isSigned() const { return dtypep() && dtypep()->isSigned(); }
|
||||
bool AstNode::isSigned() const { return dtypep() && dtypep()->isSigned(); }
|
||||
|
||||
inline bool AstNode::isZero() const {
|
||||
bool AstNode::isZero() const {
|
||||
return (VN_IS(this, Const) && VN_AS(this, Const)->num().isEqZero());
|
||||
}
|
||||
inline bool AstNode::isNeqZero() const {
|
||||
bool AstNode::isNeqZero() const {
|
||||
return (VN_IS(this, Const) && VN_AS(this, Const)->num().isNeqZero());
|
||||
}
|
||||
inline bool AstNode::isOne() const {
|
||||
return (VN_IS(this, Const) && VN_AS(this, Const)->num().isEqOne());
|
||||
}
|
||||
inline bool AstNode::isAllOnes() const {
|
||||
bool AstNode::isOne() const { return (VN_IS(this, Const) && VN_AS(this, Const)->num().isEqOne()); }
|
||||
bool AstNode::isAllOnes() const {
|
||||
return (VN_IS(this, Const) && VN_AS(this, Const)->isEqAllOnes());
|
||||
}
|
||||
inline bool AstNode::isAllOnesV() const {
|
||||
bool AstNode::isAllOnesV() const {
|
||||
return (VN_IS(this, Const) && VN_AS(this, Const)->isEqAllOnesV());
|
||||
}
|
||||
inline bool AstNode::sameTree(const AstNode* node2p) const {
|
||||
bool AstNode::sameTree(const AstNode* node2p) const {
|
||||
return sameTreeIter(this, node2p, true, false);
|
||||
}
|
||||
inline bool AstNode::sameGateTree(const AstNode* node2p) const {
|
||||
bool AstNode::sameGateTree(const AstNode* node2p) const {
|
||||
return sameTreeIter(this, node2p, true, true);
|
||||
}
|
||||
|
||||
inline void AstNodeVarRef::varp(AstVar* varp) {
|
||||
m_varp = varp;
|
||||
int AstNodeArrayDType::left() const { return rangep()->leftConst(); }
|
||||
int AstNodeArrayDType::right() const { return rangep()->rightConst(); }
|
||||
int AstNodeArrayDType::hi() const { return rangep()->hiConst(); }
|
||||
int AstNodeArrayDType::lo() const { return rangep()->loConst(); }
|
||||
int AstNodeArrayDType::elementsConst() const { return rangep()->elementsConst(); }
|
||||
VNumRange AstNodeArrayDType::declRange() const { return VNumRange{left(), right()}; }
|
||||
|
||||
AstRange::AstRange(FileLine* fl, int left, int right)
|
||||
: ASTGEN_SUPER_Range(fl) {
|
||||
leftp(new AstConst{fl, static_cast<uint32_t>(left)});
|
||||
rightp(new AstConst{fl, static_cast<uint32_t>(right)});
|
||||
}
|
||||
AstRange::AstRange(FileLine* fl, const VNumRange& range)
|
||||
: ASTGEN_SUPER_Range(fl) {
|
||||
leftp(new AstConst{fl, static_cast<uint32_t>(range.left())});
|
||||
rightp(new AstConst{fl, static_cast<uint32_t>(range.right())});
|
||||
}
|
||||
int AstRange::leftConst() const {
|
||||
AstConst* const constp = VN_CAST(leftp(), Const);
|
||||
return (constp ? constp->toSInt() : 0);
|
||||
}
|
||||
int AstRange::rightConst() const {
|
||||
AstConst* const constp = VN_CAST(rightp(), Const);
|
||||
return (constp ? constp->toSInt() : 0);
|
||||
}
|
||||
|
||||
int AstQueueDType::boundConst() const {
|
||||
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}
|
||||
, m_name{varname->name()} {
|
||||
this->exprp(exprp);
|
||||
}
|
||||
|
||||
AstDpiExportUpdated::AstDpiExportUpdated(FileLine* fl, AstVarScope* varScopep)
|
||||
: ASTGEN_SUPER_DpiExportUpdated(fl) {
|
||||
this->varRefp(new AstVarRef{fl, varScopep, VAccess::WRITE});
|
||||
}
|
||||
|
||||
AstVarScope* AstDpiExportUpdated::varScopep() const { return varRefp()->varScopep(); }
|
||||
|
||||
AstPackArrayDType::AstPackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp,
|
||||
AstRange* rangep)
|
||||
: ASTGEN_SUPER_PackArrayDType(fl) {
|
||||
childDTypep(dtp); // Only for parser
|
||||
refDTypep(nullptr);
|
||||
this->rangep(rangep);
|
||||
dtypep(nullptr); // V3Width will resolve
|
||||
const int width = subDTypep()->width() * rangep->elementsConst();
|
||||
widthForce(width, width);
|
||||
}
|
||||
AstPackArrayDType::AstPackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep)
|
||||
: ASTGEN_SUPER_PackArrayDType(fl) {
|
||||
refDTypep(dtp);
|
||||
this->rangep(rangep);
|
||||
dtypep(this);
|
||||
const int width = subDTypep()->width() * rangep->elementsConst();
|
||||
widthForce(width, width);
|
||||
}
|
||||
|
||||
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 {
|
||||
return (rangep() ? rangep()->elementsConst() : m.m_nrange.elements());
|
||||
}
|
||||
bool AstBasicDType::littleEndian() const {
|
||||
return (rangep() ? rangep()->littleEndian() : m.m_nrange.littleEndian());
|
||||
}
|
||||
|
||||
bool AstActive::hasInitial() const { return m_sensesp->hasInitial(); }
|
||||
bool AstActive::hasSettle() const { return m_sensesp->hasSettle(); }
|
||||
bool AstActive::hasClocked() const { return m_sensesp->hasClocked(); }
|
||||
|
||||
AstElabDisplay::AstElabDisplay(FileLine* fl, VDisplayType dispType, AstNode* exprsp)
|
||||
: ASTGEN_SUPER_ElabDisplay(fl) {
|
||||
addFmtp(new AstSFormatF{fl, AstSFormatF::NoFormat(), exprsp});
|
||||
m_displayType = dispType;
|
||||
}
|
||||
|
||||
AstCStmt::AstCStmt(FileLine* fl, const string& textStmt)
|
||||
: ASTGEN_SUPER_CStmt(fl) {
|
||||
addExprsp(new AstText{fl, textStmt, true});
|
||||
}
|
||||
|
||||
AstCMath::AstCMath(FileLine* fl, const string& textStmt, int setwidth, bool cleanOut)
|
||||
: ASTGEN_SUPER_CMath(fl)
|
||||
, m_cleanOut{cleanOut}
|
||||
, m_pure{true} {
|
||||
addExprsp(new AstText{fl, textStmt, true});
|
||||
if (setwidth) dtypeSetLogicSized(setwidth, VSigning::UNSIGNED);
|
||||
}
|
||||
|
||||
AstVarRef::AstVarRef(FileLine* fl, AstVar* varp, const VAccess& access)
|
||||
: ASTGEN_SUPER_VarRef(fl, varp->name(), varp, access) {}
|
||||
// This form only allowed post-link (see above)
|
||||
AstVarRef::AstVarRef(FileLine* fl, AstVarScope* varscp, const VAccess& access)
|
||||
: ASTGEN_SUPER_VarRef(fl, varscp->varp()->name(), varscp->varp(), access) {
|
||||
varScopep(varscp);
|
||||
}
|
||||
bool AstVarRef::same(const AstVarRef* samep) const {
|
||||
if (varScopep()) {
|
||||
return (varScopep() == samep->varScopep() && access() == samep->access());
|
||||
} else {
|
||||
return (selfPointer() == samep->selfPointer() && varp()->name() == samep->varp()->name()
|
||||
&& access() == samep->access());
|
||||
}
|
||||
}
|
||||
bool AstVarRef::sameNoLvalue(AstVarRef* samep) const {
|
||||
if (varScopep()) {
|
||||
return (varScopep() == samep->varScopep());
|
||||
} else {
|
||||
return (selfPointer() == samep->selfPointer()
|
||||
&& (!selfPointer().empty() || !samep->selfPointer().empty())
|
||||
&& varp()->name() == samep->varp()->name());
|
||||
}
|
||||
}
|
||||
|
||||
AstVarXRef::AstVarXRef(FileLine* fl, AstVar* varp, const string& dotted, const VAccess& access)
|
||||
: ASTGEN_SUPER_VarXRef(fl, varp->name(), varp, access)
|
||||
, m_dotted{dotted} {
|
||||
dtypeFrom(varp);
|
||||
}
|
||||
|
||||
inline bool AstNodeDType::isFourstate() const { return basicp()->isFourstate(); }
|
||||
|
||||
inline void AstNodeArrayDType::rangep(AstRange* nodep) { setOp2p(nodep); }
|
||||
inline int AstNodeArrayDType::left() const { return rangep()->leftConst(); }
|
||||
inline int AstNodeArrayDType::right() const { return rangep()->rightConst(); }
|
||||
inline int AstNodeArrayDType::hi() const { return rangep()->hiConst(); }
|
||||
inline int AstNodeArrayDType::lo() const { return rangep()->loConst(); }
|
||||
inline int AstNodeArrayDType::elementsConst() const { return rangep()->elementsConst(); }
|
||||
inline VNumRange AstNodeArrayDType::declRange() const { return VNumRange{left(), right()}; }
|
||||
|
||||
inline void AstIfaceRefDType::cloneRelink() {
|
||||
if (m_cellp && m_cellp->clonep()) m_cellp = m_cellp->clonep();
|
||||
if (m_ifacep && m_ifacep->clonep()) m_ifacep = m_ifacep->clonep();
|
||||
if (m_modportp && m_modportp->clonep()) m_modportp = m_modportp->clonep();
|
||||
}
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -26,7 +26,7 @@
|
|||
#include "V3PartitionGraph.h" // Just for mtask dumping
|
||||
#include "V3String.h"
|
||||
|
||||
#include "V3AstNodes__gen_macros.h" // Generated by 'astgen'
|
||||
#include "V3Ast__gen_macros.h" // Generated by 'astgen'
|
||||
|
||||
#include <iomanip>
|
||||
#include <iterator>
|
||||
|
|
@ -155,6 +155,51 @@ void AstNodeCond::numberOperate(V3Number& out, const V3Number& lhs, const V3Numb
|
|||
}
|
||||
}
|
||||
|
||||
void AstBasicDType::init(VBasicDTypeKwd kwd, VSigning numer, int wantwidth, int wantwidthmin,
|
||||
AstRange* rangep) {
|
||||
// wantwidth=0 means figure it out, but if a widthmin is >=0
|
||||
// we allow width 0 so that {{0{x}},y} works properly
|
||||
// wantwidthmin=-1: default, use wantwidth if it is non zero
|
||||
m.m_keyword = kwd;
|
||||
// Implicitness: // "parameter X" is implicit and sized from initial
|
||||
// value, "parameter reg x" not
|
||||
if (keyword() == VBasicDTypeKwd::LOGIC_IMPLICIT) {
|
||||
if (rangep || wantwidth) m.m_keyword = VBasicDTypeKwd::LOGIC;
|
||||
}
|
||||
if (numer == VSigning::NOSIGN) {
|
||||
if (keyword().isSigned()) {
|
||||
numer = VSigning::SIGNED;
|
||||
} else if (keyword().isUnsigned()) {
|
||||
numer = VSigning::UNSIGNED;
|
||||
}
|
||||
}
|
||||
numeric(numer);
|
||||
if (!rangep && (wantwidth || wantwidthmin >= 0)) { // Constant width
|
||||
if (wantwidth > 1) m.m_nrange.init(wantwidth - 1, 0, false);
|
||||
const int wmin = wantwidthmin >= 0 ? wantwidthmin : wantwidth;
|
||||
widthForce(wantwidth, wmin);
|
||||
} else if (!rangep) { // Set based on keyword properties
|
||||
// V3Width will pull from this width
|
||||
if (keyword().width() > 1 && !isOpaque()) {
|
||||
m.m_nrange.init(keyword().width() - 1, 0, false);
|
||||
}
|
||||
widthForce(keyword().width(), keyword().width());
|
||||
} else {
|
||||
widthForce(rangep->elementsConst(),
|
||||
rangep->elementsConst()); // Maybe unknown if parameters underneath it
|
||||
}
|
||||
this->rangep(rangep);
|
||||
this->dtypep(this);
|
||||
}
|
||||
|
||||
void AstBasicDType::cvtRangeConst() {
|
||||
if (rangep() && VN_IS(rangep()->leftp(), Const) && VN_IS(rangep()->rightp(), Const)) {
|
||||
m.m_nrange = VNumRange{rangep()->leftConst(), rangep()->rightConst()};
|
||||
rangep()->unlinkFrBackWithNext()->deleteTree();
|
||||
rangep(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
int AstBasicDType::widthAlignBytes() const {
|
||||
if (width() <= 8) {
|
||||
return 1;
|
||||
|
|
@ -519,11 +564,11 @@ string AstVar::dpiArgType(bool named, bool forReturn) const {
|
|||
return dpiTypesToStringConverter{}.convert(this);
|
||||
} else {
|
||||
class converter final : public dpiTypesToStringConverter {
|
||||
virtual string bitLogicVector(const AstVar* varp, bool isBit) const override {
|
||||
string bitLogicVector(const AstVar* varp, bool isBit) const override {
|
||||
return string(varp->isReadOnly() ? "const " : "")
|
||||
+ dpiTypesToStringConverter::bitLogicVector(varp, isBit) + '*';
|
||||
}
|
||||
virtual string primitive(const AstVar* varp) const override {
|
||||
string primitive(const AstVar* varp) const override {
|
||||
string type = dpiTypesToStringConverter::primitive(varp);
|
||||
if (varp->isWritable() || VN_IS(varp->dtypep()->skipRefp(), UnpackArrayDType)) {
|
||||
if (!varp->isWritable() && varp->basicp()->keyword() != VBasicDTypeKwd::STRING)
|
||||
|
|
@ -555,16 +600,16 @@ string AstVar::dpiTmpVarType(const string& varName) const {
|
|||
return "";
|
||||
}
|
||||
}
|
||||
virtual string openArray(const AstVar* varp) const override {
|
||||
string openArray(const AstVar* varp) const override {
|
||||
return dpiTypesToStringConverter::openArray(varp) + ' ' + m_name
|
||||
+ arraySuffix(varp, 0);
|
||||
}
|
||||
virtual string bitLogicVector(const AstVar* varp, bool isBit) const override {
|
||||
string bitLogicVector(const AstVar* varp, bool isBit) const override {
|
||||
string type = dpiTypesToStringConverter::bitLogicVector(varp, isBit);
|
||||
type += ' ' + m_name + arraySuffix(varp, varp->widthWords());
|
||||
return type;
|
||||
}
|
||||
virtual string primitive(const AstVar* varp) const override {
|
||||
string primitive(const AstVar* varp) const override {
|
||||
string type = dpiTypesToStringConverter::primitive(varp);
|
||||
if (varp->isWritable() || VN_IS(varp->dtypep()->skipRefp(), UnpackArrayDType)) {
|
||||
if (!varp->isWritable() && varp->basicp()->keyword() == VBasicDTypeKwd::CHANDLE)
|
||||
|
|
@ -615,29 +660,21 @@ AstVar* AstVar::scVarRecurse(AstNode* nodep) {
|
|||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
} else if (VN_IS(nodep, VarRef)) {
|
||||
if (VN_AS(nodep, VarRef)->varp()->isSc()) {
|
||||
return VN_AS(nodep, VarRef)->varp();
|
||||
} else if (AstVarRef* const vrefp = VN_CAST(nodep, VarRef)) {
|
||||
if (vrefp->varp()->isSc()) {
|
||||
return vrefp->varp();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
} else if (VN_IS(nodep, ArraySel)) {
|
||||
if (nodep->op1p()) {
|
||||
if (AstVar* p = scVarRecurse(nodep->op1p())) return p;
|
||||
}
|
||||
if (nodep->op2p()) {
|
||||
if (AstVar* p = scVarRecurse(nodep->op2p())) return p;
|
||||
}
|
||||
if (nodep->op3p()) {
|
||||
if (AstVar* p = scVarRecurse(nodep->op3p())) return p;
|
||||
}
|
||||
if (nodep->op4p()) {
|
||||
if (AstVar* p = scVarRecurse(nodep->op4p())) return p;
|
||||
}
|
||||
} else if (AstArraySel* const arraySelp = VN_CAST(nodep, ArraySel)) {
|
||||
if (AstVar* const p = scVarRecurse(arraySelp->fromp())) return p;
|
||||
if (AstVar* const p = scVarRecurse(arraySelp->bitp())) return p;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool AstNodeDType::isFourstate() const { return basicp()->isFourstate(); }
|
||||
|
||||
class AstNodeDType::CTypeRecursed final {
|
||||
public:
|
||||
string m_type; // The base type, e.g.: "Foo_t"s
|
||||
|
|
@ -1023,8 +1060,13 @@ AstConstPool::AstConstPool(FileLine* fl)
|
|||
: ASTGEN_SUPER_ConstPool(fl)
|
||||
, m_modp{new AstModule(fl, "@CONST-POOL@")}
|
||||
, m_scopep{new AstScope(fl, m_modp, "@CONST-POOL@", nullptr, nullptr)} {
|
||||
addOp1p(m_modp);
|
||||
m_modp->addStmtp(m_scopep);
|
||||
this->modulep(m_modp);
|
||||
m_modp->addStmtsp(m_scopep);
|
||||
}
|
||||
const char* AstConstPool::broken() const {
|
||||
BROKEN_RTN(m_modp && !m_modp->brokeExists());
|
||||
BROKEN_RTN(m_scopep && !m_scopep->brokeExists());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AstVarScope* AstConstPool::createNewEntry(const string& name, AstNode* initp) {
|
||||
|
|
@ -1033,9 +1075,9 @@ AstVarScope* AstConstPool::createNewEntry(const string& name, AstNode* initp) {
|
|||
varp->isConst(true);
|
||||
varp->isStatic(true);
|
||||
varp->valuep(initp->cloneTree(false));
|
||||
m_modp->addStmtp(varp);
|
||||
m_modp->addStmtsp(varp);
|
||||
AstVarScope* const varScopep = new AstVarScope(fl, m_scopep, varp);
|
||||
m_scopep->addVarp(varScopep);
|
||||
m_scopep->addVarsp(varScopep);
|
||||
return varScopep;
|
||||
}
|
||||
|
||||
|
|
@ -1181,7 +1223,7 @@ void AstWhile::addBeforeStmt(AstNode* newp, AstNode* belowp) {
|
|||
} else if (belowp == condp()) {
|
||||
// Goes before condition, IE in preconditions
|
||||
addPrecondsp(newp);
|
||||
} else if (belowp == bodysp()) {
|
||||
} else if (belowp == stmtsp()) {
|
||||
// Was first statement in body, so new front
|
||||
belowp->addHereThisAsNext(newp);
|
||||
} else {
|
||||
|
|
@ -1198,12 +1240,12 @@ void AstWhile::addNextStmt(AstNode* newp, AstNode* belowp) {
|
|||
belowp->addNextHere(newp);
|
||||
} else if (belowp == condp()) {
|
||||
// Becomes first statement in body, body may have been empty
|
||||
if (bodysp()) {
|
||||
bodysp()->addHereThisAsNext(newp);
|
||||
if (stmtsp()) {
|
||||
stmtsp()->addHereThisAsNext(newp);
|
||||
} else {
|
||||
addBodysp(newp);
|
||||
addStmtsp(newp);
|
||||
}
|
||||
} else if (belowp == bodysp()) {
|
||||
} else if (belowp == stmtsp()) {
|
||||
// Next statement in body
|
||||
belowp->addNextHere(newp);
|
||||
} else {
|
||||
|
|
@ -1224,10 +1266,10 @@ static std::string nodeAddr(const AstNode* nodep) {
|
|||
}
|
||||
|
||||
void AstNode::dump(std::ostream& str) const {
|
||||
str << typeName() << " "
|
||||
<< nodeAddr(this)
|
||||
//<< " " << nodeAddr(m_backp)
|
||||
str << typeName() << " " << nodeAddr(this)
|
||||
#ifdef VL_DEBUG
|
||||
<< " <e" << std::dec << editCount() << ((editCount() >= editCountLast()) ? "#>" : ">")
|
||||
#endif
|
||||
<< " {" << fileline()->filenameLetters() << std::dec << fileline()->lastLineno()
|
||||
<< fileline()->firstColumnLetters() << "}";
|
||||
if (user1p()) str << " u1=" << nodeAddr(user1p());
|
||||
|
|
@ -1297,11 +1339,19 @@ void AstCell::dump(std::ostream& str) const {
|
|||
str << " ->UNLINKED:" << modName();
|
||||
}
|
||||
}
|
||||
const char* AstCell::broken() const {
|
||||
BROKEN_RTN(m_modp && !m_modp->brokeExists());
|
||||
return nullptr;
|
||||
}
|
||||
void AstCellInline::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " -> " << origModName();
|
||||
str << " [scopep=" << reinterpret_cast<const void*>(scopep()) << "]";
|
||||
}
|
||||
const char* AstCellInline::broken() const {
|
||||
BROKEN_RTN(m_scopep && !m_scopep->brokeExists());
|
||||
return nullptr;
|
||||
}
|
||||
const char* AstClassPackage::broken() const {
|
||||
BROKEN_BASE_RTN(AstNodeModule::broken());
|
||||
BROKEN_RTN(m_classp && !m_classp->brokeExists());
|
||||
|
|
@ -1346,6 +1396,17 @@ void AstClass::dump(std::ostream& str) const {
|
|||
if (isExtended()) str << " [EXT]";
|
||||
if (isVirtual()) str << " [VIRT]";
|
||||
}
|
||||
const char* AstClass::broken() const {
|
||||
BROKEN_BASE_RTN(AstNodeModule::broken());
|
||||
BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists());
|
||||
return nullptr;
|
||||
}
|
||||
void AstClass::cloneRelink() {
|
||||
AstNodeModule::cloneRelink();
|
||||
if (m_classOrPackagep && m_classOrPackagep->clonep()) {
|
||||
m_classOrPackagep = m_classOrPackagep->clonep();
|
||||
}
|
||||
}
|
||||
AstClass* AstClassExtends::classp() const {
|
||||
const AstClassRefDType* refp = VN_CAST(dtypep(), ClassRefDType);
|
||||
if (VL_UNLIKELY(!refp)) { // LinkDot uses this for 'super.'
|
||||
|
|
@ -1368,6 +1429,18 @@ void AstClassRefDType::dumpSmall(std::ostream& str) const {
|
|||
this->AstNodeDType::dumpSmall(str);
|
||||
str << "class:" << name();
|
||||
}
|
||||
const char* AstClassRefDType::broken() const {
|
||||
BROKEN_RTN(m_classp && !m_classp->brokeExists());
|
||||
BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists());
|
||||
return nullptr;
|
||||
}
|
||||
void AstClassRefDType::cloneRelink() {
|
||||
if (m_classp && m_classp->clonep()) m_classp = m_classp->clonep();
|
||||
if (m_classOrPackagep && m_classOrPackagep->clonep()) {
|
||||
m_classOrPackagep = m_classOrPackagep->clonep();
|
||||
}
|
||||
}
|
||||
string AstClassRefDType::name() const { return classp() ? classp()->name() : "<unlinked>"; }
|
||||
void AstNodeCoverOrAssert::dump(std::ostream& str) const {
|
||||
this->AstNodeStmt::dump(str);
|
||||
if (immediate()) str << " [IMMEDIATE]";
|
||||
|
|
@ -1385,6 +1458,11 @@ void AstEnumItemRef::dump(std::ostream& str) const {
|
|||
str << "UNLINKED";
|
||||
}
|
||||
}
|
||||
const char* AstEnumItemRef::broken() const {
|
||||
BROKEN_RTN(m_itemp && !m_itemp->brokeExists());
|
||||
BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists());
|
||||
return nullptr;
|
||||
}
|
||||
void AstIfaceRefDType::dump(std::ostream& str) const {
|
||||
this->AstNodeDType::dump(str);
|
||||
if (cellName() != "") str << " cell=" << cellName();
|
||||
|
|
@ -1404,6 +1482,11 @@ void AstIfaceRefDType::dumpSmall(std::ostream& str) const {
|
|||
this->AstNodeDType::dumpSmall(str);
|
||||
str << "iface";
|
||||
}
|
||||
void AstIfaceRefDType::cloneRelink() {
|
||||
if (m_cellp && m_cellp->clonep()) m_cellp = m_cellp->clonep();
|
||||
if (m_ifacep && m_ifacep->clonep()) m_ifacep = m_ifacep->clonep();
|
||||
if (m_modportp && m_modportp->clonep()) m_modportp = m_modportp->clonep();
|
||||
}
|
||||
void AstInitArray::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
int n = 0;
|
||||
|
|
@ -1416,6 +1499,42 @@ void AstInitArray::dump(std::ostream& str) const {
|
|||
str << " [" << itr.first << "]=" << reinterpret_cast<const void*>(itr.second);
|
||||
}
|
||||
}
|
||||
const char* AstInitArray::broken() const {
|
||||
for (KeyItemMap::const_iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||
BROKEN_RTN(!it->second);
|
||||
BROKEN_RTN(!it->second->brokeExists());
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
void AstInitArray::cloneRelink() {
|
||||
for (KeyItemMap::iterator it = m_map.begin(); it != m_map.end(); ++it) {
|
||||
if (it->second->clonep()) it->second = it->second->clonep();
|
||||
}
|
||||
}
|
||||
void AstInitArray::addIndexValuep(uint64_t index, AstNode* newp) {
|
||||
const auto it = m_map.find(index);
|
||||
if (it != m_map.end()) {
|
||||
it->second->valuep(newp);
|
||||
} else {
|
||||
AstInitItem* const itemp = new AstInitItem(fileline(), newp);
|
||||
m_map.emplace(index, itemp);
|
||||
addInitsp(itemp);
|
||||
}
|
||||
}
|
||||
AstNode* AstInitArray::getIndexValuep(uint64_t index) const {
|
||||
const auto it = m_map.find(index);
|
||||
if (it == m_map.end()) {
|
||||
return nullptr;
|
||||
} else {
|
||||
return it->second->valuep();
|
||||
}
|
||||
}
|
||||
AstNode* AstInitArray::getIndexDefaultedValuep(uint64_t index) const {
|
||||
AstNode* valuep = getIndexValuep(index);
|
||||
if (!valuep) valuep = defaultp();
|
||||
return valuep;
|
||||
}
|
||||
|
||||
void AstJumpGo::dump(std::ostream& str) const {
|
||||
this->AstNodeStmt::dump(str);
|
||||
str << " -> ";
|
||||
|
|
@ -1425,6 +1544,13 @@ void AstJumpGo::dump(std::ostream& str) const {
|
|||
str << "%Error:UNLINKED";
|
||||
}
|
||||
}
|
||||
const char* AstJumpGo::broken() const {
|
||||
BROKEN_RTN(!labelp()->brokeExistsBelow());
|
||||
return nullptr;
|
||||
}
|
||||
void AstJumpGo::cloneRelink() {
|
||||
if (m_labelp->clonep()) m_labelp = m_labelp->clonep();
|
||||
}
|
||||
void AstJumpLabel::dump(std::ostream& str) const {
|
||||
this->AstNodeStmt::dump(str);
|
||||
str << " -> ";
|
||||
|
|
@ -1447,6 +1573,13 @@ void AstMemberSel::dump(std::ostream& str) const {
|
|||
str << "%Error:UNLINKED";
|
||||
}
|
||||
}
|
||||
void AstMemberSel::cloneRelink() {
|
||||
if (m_varp && m_varp->clonep()) m_varp = m_varp->clonep();
|
||||
}
|
||||
const char* AstMemberSel::broken() const {
|
||||
BROKEN_RTN(m_varp && !m_varp->brokeExists());
|
||||
return nullptr;
|
||||
}
|
||||
void AstMethodCall::dump(std::ostream& str) const {
|
||||
this->AstNodeFTaskRef::dump(str);
|
||||
if (isStatement()) str << " [STMT]";
|
||||
|
|
@ -1468,6 +1601,13 @@ void AstModportFTaskRef::dump(std::ostream& str) const {
|
|||
str << " -> UNLINKED";
|
||||
}
|
||||
}
|
||||
const char* AstModportFTaskRef::broken() const {
|
||||
BROKEN_RTN(m_ftaskp && !m_ftaskp->brokeExists());
|
||||
return nullptr;
|
||||
}
|
||||
void AstModportFTaskRef::cloneRelink() {
|
||||
if (m_ftaskp && m_ftaskp->clonep()) m_ftaskp = m_ftaskp->clonep();
|
||||
}
|
||||
void AstModportVarRef::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
if (direction().isAny()) str << " " << direction();
|
||||
|
|
@ -1478,6 +1618,13 @@ void AstModportVarRef::dump(std::ostream& str) const {
|
|||
str << " -> UNLINKED";
|
||||
}
|
||||
}
|
||||
const char* AstModportVarRef::broken() const {
|
||||
BROKEN_RTN(m_varp && !m_varp->brokeExists());
|
||||
return nullptr;
|
||||
}
|
||||
void AstModportVarRef::cloneRelink() {
|
||||
if (m_varp && m_varp->clonep()) m_varp = m_varp->clonep();
|
||||
}
|
||||
void AstPin::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
if (modVarp()) {
|
||||
|
|
@ -1488,6 +1635,17 @@ void AstPin::dump(std::ostream& str) const {
|
|||
}
|
||||
if (svImplicit()) str << " [.SV]";
|
||||
}
|
||||
const char* AstPin::broken() const {
|
||||
BROKEN_RTN(m_modVarp && !m_modVarp->brokeExists());
|
||||
BROKEN_RTN(m_modPTypep && !m_modPTypep->brokeExists());
|
||||
return nullptr;
|
||||
}
|
||||
string AstPin::prettyOperatorName() const {
|
||||
return modVarp()
|
||||
? ((modVarp()->direction().isAny() ? modVarp()->direction().prettyName() + " " : "")
|
||||
+ "port connection " + modVarp()->prettyNameQ())
|
||||
: "port connection";
|
||||
}
|
||||
void AstPrintTimeScale::dump(std::ostream& str) const {
|
||||
this->AstNodeStmt::dump(str);
|
||||
str << " " << timeunit();
|
||||
|
|
@ -1533,6 +1691,23 @@ void AstRefDType::dump(std::ostream& str) const {
|
|||
str << " -> UNLINKED";
|
||||
}
|
||||
}
|
||||
const char* AstRefDType::broken() const {
|
||||
BROKEN_RTN(m_typedefp && !m_typedefp->brokeExists());
|
||||
BROKEN_RTN(m_refDTypep && !m_refDTypep->brokeExists());
|
||||
BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists());
|
||||
return nullptr;
|
||||
}
|
||||
void AstRefDType::cloneRelink() {
|
||||
if (m_typedefp && m_typedefp->clonep()) m_typedefp = m_typedefp->clonep();
|
||||
if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep();
|
||||
if (m_classOrPackagep && m_classOrPackagep->clonep()) {
|
||||
m_classOrPackagep = m_classOrPackagep->clonep();
|
||||
}
|
||||
}
|
||||
AstNodeDType* AstRefDType::subDTypep() const {
|
||||
if (typedefp()) return typedefp()->subDTypep();
|
||||
return refDTypep(); // Maybe nullptr
|
||||
}
|
||||
void AstNodeUOrStructDType::dump(std::ostream& str) const {
|
||||
this->AstNodeDType::dump(str);
|
||||
if (packed()) str << " [PACKED]";
|
||||
|
|
@ -1603,6 +1778,32 @@ void AstNetlist::dump(std::ostream& str) const {
|
|||
this->AstNode::dump(str);
|
||||
str << " [" << timeunit() << "/" << timeprecision() << "]";
|
||||
}
|
||||
const char* AstNetlist::broken() const {
|
||||
BROKEN_RTN(m_typeTablep && !m_typeTablep->brokeExists());
|
||||
BROKEN_RTN(m_constPoolp && !m_constPoolp->brokeExists());
|
||||
BROKEN_RTN(m_dollarUnitPkgp && !m_dollarUnitPkgp->brokeExists());
|
||||
BROKEN_RTN(m_evalp && !m_evalp->brokeExists());
|
||||
BROKEN_RTN(m_dpiExportTriggerp && !m_dpiExportTriggerp->brokeExists());
|
||||
BROKEN_RTN(m_topScopep && !m_topScopep->brokeExists());
|
||||
return nullptr;
|
||||
}
|
||||
AstPackage* AstNetlist::dollarUnitPkgAddp() {
|
||||
if (!m_dollarUnitPkgp) {
|
||||
m_dollarUnitPkgp = new AstPackage(fileline(), AstPackage::dollarUnitName());
|
||||
// packages are always libraries; don't want to make them a "top"
|
||||
m_dollarUnitPkgp->inLibrary(true);
|
||||
m_dollarUnitPkgp->modTrace(false); // may reconsider later
|
||||
m_dollarUnitPkgp->internal(true);
|
||||
addModulesp(m_dollarUnitPkgp);
|
||||
}
|
||||
return m_dollarUnitPkgp;
|
||||
}
|
||||
void AstNetlist::createTopScope(AstScope* scopep) {
|
||||
UASSERT(scopep, "Must not be nullptr");
|
||||
UASSERT_OBJ(!m_topScopep, scopep, "TopScope already exits");
|
||||
m_topScopep = new AstTopScope{scopep->modp()->fileline(), scopep};
|
||||
scopep->modp()->addStmtsp(v3Global.rootp()->topScopep());
|
||||
}
|
||||
void AstNodeModule::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " L" << level();
|
||||
|
|
@ -1620,10 +1821,24 @@ void AstPackageExport::dump(std::ostream& str) const {
|
|||
this->AstNode::dump(str);
|
||||
str << " -> " << packagep();
|
||||
}
|
||||
const char* AstPackageExport ::broken() const {
|
||||
BROKEN_RTN(!m_packagep || !m_packagep->brokeExists());
|
||||
return nullptr;
|
||||
}
|
||||
void AstPackageExport::cloneRelink() {
|
||||
if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep();
|
||||
}
|
||||
void AstPackageImport::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " -> " << packagep();
|
||||
}
|
||||
const char* AstPackageImport::broken() const {
|
||||
BROKEN_RTN(!m_packagep || !m_packagep->brokeExists());
|
||||
return nullptr;
|
||||
}
|
||||
void AstPackageImport::cloneRelink() {
|
||||
if (m_packagep && m_packagep->clonep()) m_packagep = m_packagep->clonep();
|
||||
}
|
||||
void AstPatMember::dump(std::ostream& str) const {
|
||||
this->AstNodeMath::dump(str);
|
||||
if (isDefault()) str << " [DEFAULT]";
|
||||
|
|
@ -1650,7 +1865,7 @@ void AstTypeTable::dump(std::ostream& str) const {
|
|||
for (int i = 0; i < static_cast<int>(VBasicDTypeKwd::_ENUM_MAX); ++i) {
|
||||
if (AstBasicDType* const subnodep = m_basicps[i]) {
|
||||
str << '\n'; // Newline from caller, so newline first
|
||||
str << "\t\t" << std::setw(8) << VBasicDTypeKwd(i).ascii();
|
||||
str << "\t\t" << std::setw(8) << VBasicDTypeKwd{i}.ascii();
|
||||
str << " -> ";
|
||||
subnodep->dump(str);
|
||||
}
|
||||
|
|
@ -1691,10 +1906,30 @@ void AstWildcardArrayDType::dumpSmall(std::ostream& str) const {
|
|||
this->AstNodeDType::dumpSmall(str);
|
||||
str << "[*]";
|
||||
}
|
||||
bool AstWildcardArrayDType::same(const AstNode* samep) const {
|
||||
const AstNodeArrayDType* const asamep = static_cast<const AstNodeArrayDType*>(samep);
|
||||
if (!asamep->subDTypep()) return false;
|
||||
return (subDTypep() == asamep->subDTypep());
|
||||
}
|
||||
bool AstWildcardArrayDType::similarDType(AstNodeDType* samep) const {
|
||||
const AstNodeArrayDType* const asamep = static_cast<const AstNodeArrayDType*>(samep);
|
||||
return type() == samep->type() && asamep->subDTypep()
|
||||
&& subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp());
|
||||
}
|
||||
void AstUnsizedArrayDType::dumpSmall(std::ostream& str) const {
|
||||
this->AstNodeDType::dumpSmall(str);
|
||||
str << "[]";
|
||||
}
|
||||
bool AstUnsizedArrayDType::same(const AstNode* samep) const {
|
||||
const AstNodeArrayDType* const asamep = static_cast<const AstNodeArrayDType*>(samep);
|
||||
if (!asamep->subDTypep()) return false;
|
||||
return (subDTypep() == asamep->subDTypep());
|
||||
}
|
||||
bool AstUnsizedArrayDType::similarDType(AstNodeDType* samep) const {
|
||||
const AstNodeArrayDType* const asamep = static_cast<const AstNodeArrayDType*>(samep);
|
||||
return type() == samep->type() && asamep->subDTypep()
|
||||
&& subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp());
|
||||
}
|
||||
void AstEmptyQueueDType::dumpSmall(std::ostream& str) const {
|
||||
this->AstNodeDType::dumpSmall(str);
|
||||
str << "emptyq";
|
||||
|
|
@ -1742,6 +1977,9 @@ void AstVarRef::dump(std::ostream& str) const {
|
|||
str << "UNLINKED";
|
||||
}
|
||||
}
|
||||
bool AstVarRef::same(const AstNode* samep) const {
|
||||
return same(static_cast<const AstVarRef*>(samep));
|
||||
}
|
||||
void AstVar::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
if (isSc()) str << " [SC]";
|
||||
|
|
@ -1786,6 +2024,10 @@ void AstSenItem::dump(std::ostream& str) const {
|
|||
this->AstNode::dump(str);
|
||||
str << " [" << edgeType().ascii() << "]";
|
||||
}
|
||||
void AstStrengthSpec::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " (" << m_s0.ascii() << ", " << m_s1.ascii() << ")";
|
||||
}
|
||||
void AstParseRef::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " [" << expect().ascii() << "]";
|
||||
|
|
@ -1800,6 +2042,13 @@ void AstClassOrPackageRef::dump(std::ostream& str) const {
|
|||
str << "UNLINKED";
|
||||
}
|
||||
}
|
||||
AstNodeModule* AstClassOrPackageRef::classOrPackagep() const {
|
||||
AstNode* foundp = m_classOrPackageNodep;
|
||||
while (auto* const anodep = VN_CAST(foundp, Typedef)) foundp = anodep->subDTypep();
|
||||
if (auto* const anodep = VN_CAST(foundp, ClassRefDType)) foundp = anodep->classp();
|
||||
return VN_CAST(foundp, NodeModule);
|
||||
}
|
||||
|
||||
void AstDot::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
if (colon()) str << " [::]";
|
||||
|
|
@ -1813,6 +2062,16 @@ void AstActive::dump(std::ostream& str) const {
|
|||
str << "UNLINKED";
|
||||
}
|
||||
}
|
||||
const char* AstActive::broken() const {
|
||||
BROKEN_RTN(m_sensesp && !m_sensesp->brokeExists());
|
||||
return nullptr;
|
||||
}
|
||||
void AstActive::cloneRelink() {
|
||||
if (m_sensesp->clonep()) {
|
||||
m_sensesp = m_sensesp->clonep();
|
||||
UASSERT(m_sensesp, "Bad clone cross link: " << this);
|
||||
}
|
||||
}
|
||||
void AstNodeFTaskRef::dump(std::ostream& str) const {
|
||||
this->AstNodeStmt::dump(str);
|
||||
if (classOrPackagep()) str << " pkg=" << nodeAddr(classOrPackagep());
|
||||
|
|
@ -1916,6 +2175,14 @@ void AstCFunc::dump(std::ostream& str) const {
|
|||
if (isDestructor()) str << " [DTOR]";
|
||||
if (isVirtual()) str << " [VIRT]";
|
||||
}
|
||||
const char* AstCFunc::broken() const {
|
||||
BROKEN_RTN((m_scopep && !m_scopep->brokeExists()));
|
||||
return nullptr;
|
||||
}
|
||||
void AstCFunc::cloneRelink() {
|
||||
if (m_scopep && m_scopep->clonep()) m_scopep = m_scopep->clonep();
|
||||
}
|
||||
|
||||
void AstCUse::dump(std::ostream& str) const {
|
||||
this->AstNode::dump(str);
|
||||
str << " [" << useType() << "]";
|
||||
|
|
|
|||
9571
src/V3AstNodes.h
9571
src/V3AstNodes.h
File diff suppressed because it is too large
Load Diff
|
|
@ -35,7 +35,7 @@ class AstUserAllocatorBase VL_NOT_FINAL {
|
|||
private:
|
||||
std::vector<T_Data*> m_allocated;
|
||||
|
||||
inline T_Data* getUserp(const T_Node* nodep) const {
|
||||
T_Data* getUserp(const T_Node* nodep) const {
|
||||
if VL_CONSTEXPR_CXX17 (T_UserN == 1) {
|
||||
const VNUser user = nodep->user1u();
|
||||
return user.to<T_Data*>();
|
||||
|
|
@ -54,17 +54,17 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
inline void setUserp(T_Node* nodep, T_Data* userp) const {
|
||||
void setUserp(T_Node* nodep, T_Data* userp) const {
|
||||
if VL_CONSTEXPR_CXX17 (T_UserN == 1) {
|
||||
nodep->user1u(VNUser(userp));
|
||||
nodep->user1u(VNUser{userp});
|
||||
} else if VL_CONSTEXPR_CXX17 (T_UserN == 2) {
|
||||
nodep->user2u(VNUser(userp));
|
||||
nodep->user2u(VNUser{userp});
|
||||
} else if VL_CONSTEXPR_CXX17 (T_UserN == 3) {
|
||||
nodep->user3u(VNUser(userp));
|
||||
nodep->user3u(VNUser{userp});
|
||||
} else if VL_CONSTEXPR_CXX17 (T_UserN == 4) {
|
||||
nodep->user4u(VNUser(userp));
|
||||
nodep->user4u(VNUser{userp});
|
||||
} else {
|
||||
nodep->user5u(VNUser(userp));
|
||||
nodep->user5u(VNUser{userp});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
|
||||
class BeginState final {
|
||||
|
|
@ -70,7 +72,6 @@ private:
|
|||
int m_ifDepth = 0; // Current if depth
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
string dot(const string& a, const string& b) {
|
||||
if (a == "") return b;
|
||||
|
|
@ -85,7 +86,7 @@ private:
|
|||
string::size_type pos;
|
||||
while ((pos = dottedname.find("__DOT__")) != string::npos) {
|
||||
const string ident = dottedname.substr(0, pos);
|
||||
dottedname = dottedname.substr(pos + strlen("__DOT__"));
|
||||
dottedname = dottedname.substr(pos + std::strlen("__DOT__"));
|
||||
if (nodep->name() != "") {
|
||||
m_displayScope = dot(m_displayScope, ident);
|
||||
m_namedScope = dot(m_namedScope, ident);
|
||||
|
|
@ -115,19 +116,19 @@ private:
|
|||
}
|
||||
} else {
|
||||
// Move to module
|
||||
m_modp->addStmtp(nodep);
|
||||
m_modp->addStmtsp(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
m_modp = nodep;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeFTask* nodep) override {
|
||||
void visit(AstNodeFTask* nodep) override {
|
||||
UINFO(8, " " << nodep << endl);
|
||||
// Rename it
|
||||
if (m_unnamedScope != "") {
|
||||
|
|
@ -162,7 +163,7 @@ private:
|
|||
m_ftaskp = nullptr;
|
||||
}
|
||||
}
|
||||
virtual void visit(AstBegin* nodep) override {
|
||||
void visit(AstBegin* nodep) override {
|
||||
// Begin blocks were only useful in variable creation, change names and delete
|
||||
UINFO(8, " " << nodep << endl);
|
||||
VL_RESTORER(m_displayScope);
|
||||
|
|
@ -177,11 +178,7 @@ private:
|
|||
AstNode* addsp = nullptr;
|
||||
if (AstNode* const stmtsp = nodep->stmtsp()) {
|
||||
stmtsp->unlinkFrBackWithNext();
|
||||
if (addsp) {
|
||||
addsp = addsp->addNextNull(stmtsp);
|
||||
} else {
|
||||
addsp = stmtsp;
|
||||
}
|
||||
addsp = AstNode::addNext(addsp, stmtsp);
|
||||
}
|
||||
if (addsp) {
|
||||
nodep->replaceWith(addsp);
|
||||
|
|
@ -191,7 +188,7 @@ private:
|
|||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVar* nodep) override {
|
||||
void visit(AstVar* nodep) override {
|
||||
if (m_unnamedScope != "") {
|
||||
// Rename it
|
||||
nodep->name(dot(m_unnamedScope, nodep->name()));
|
||||
|
|
@ -200,7 +197,7 @@ private:
|
|||
liftNode(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstTypedef* nodep) override {
|
||||
void visit(AstTypedef* nodep) override {
|
||||
if (m_unnamedScope != "") {
|
||||
// Rename it
|
||||
nodep->name(dot(m_unnamedScope, nodep->name()));
|
||||
|
|
@ -209,7 +206,7 @@ private:
|
|||
liftNode(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCell* nodep) override {
|
||||
void visit(AstCell* nodep) override {
|
||||
UINFO(8, " CELL " << nodep << endl);
|
||||
if (m_namedScope != "") {
|
||||
m_statep->userMarkChanged(nodep);
|
||||
|
|
@ -218,18 +215,18 @@ private:
|
|||
UINFO(8, " rename to " << nodep->name() << endl);
|
||||
// Move to module
|
||||
nodep->unlinkFrBack();
|
||||
m_modp->addStmtp(nodep);
|
||||
m_modp->addStmtsp(nodep);
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstVarXRef* nodep) override {
|
||||
void visit(AstVarXRef* nodep) override {
|
||||
UINFO(9, " VARXREF " << nodep << endl);
|
||||
if (m_namedScope != "" && nodep->inlinedDots() == "" && !m_ftaskp) {
|
||||
nodep->inlinedDots(m_namedScope);
|
||||
UINFO(9, " rescope to " << nodep << endl);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstScopeName* nodep) override {
|
||||
void visit(AstScopeName* nodep) override {
|
||||
// If there's a %m in the display text, we add a special node that will contain the name()
|
||||
// Similar code in V3Inline
|
||||
if (nodep->user1SetOnce()) return; // Don't double-add text's
|
||||
|
|
@ -237,20 +234,20 @@ private:
|
|||
const string scname = nodep->forFormat() ? m_displayScope : m_namedScope;
|
||||
if (!scname.empty()) {
|
||||
// To keep correct visual order, must add before other Text's
|
||||
AstNode* const afterp = nodep->scopeAttrp();
|
||||
AstText* const afterp = nodep->scopeAttrp();
|
||||
if (afterp) afterp->unlinkFrBackWithNext();
|
||||
nodep->scopeAttrp(new AstText{nodep->fileline(), string("__DOT__") + scname});
|
||||
if (afterp) nodep->scopeAttrp(afterp);
|
||||
nodep->addScopeAttrp(new AstText{nodep->fileline(), string("__DOT__") + scname});
|
||||
if (afterp) nodep->addScopeAttrp(afterp);
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstCoverDecl* nodep) override {
|
||||
void visit(AstCoverDecl* nodep) override {
|
||||
// Don't need to fix path in coverage statements, they're not under
|
||||
// any BEGINs, but V3Coverage adds them all under the module itself.
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
// VISITORS - LINT CHECK
|
||||
virtual void visit(AstIf* nodep) override { // not AstNodeIf; other types not covered
|
||||
void visit(AstIf* nodep) override { // not AstNodeIf; other types not covered
|
||||
// Check IFDEPTH warning - could be in other transform files if desire
|
||||
VL_RESTORER(m_ifDepth);
|
||||
if (m_ifDepth == -1 || v3Global.opt.ifDepth() < 1) { // Turned off
|
||||
|
|
@ -264,7 +261,7 @@ private:
|
|||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
|
|
@ -272,7 +269,7 @@ public:
|
|||
: m_statep{statep} {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~BeginVisitor() override = default;
|
||||
~BeginVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -285,21 +282,21 @@ private:
|
|||
// AstNodeFTask::user1p // Node replaced, rename it
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeFTaskRef* nodep) override {
|
||||
void visit(AstNodeFTaskRef* nodep) override {
|
||||
if (nodep->taskp()->user1()) { // It was converted
|
||||
UINFO(9, " relinkFTask " << nodep << endl);
|
||||
nodep->name(nodep->taskp()->name());
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep) override {
|
||||
void visit(AstVarRef* nodep) override {
|
||||
if (nodep->varp()->user1()) { // It was converted
|
||||
UINFO(9, " relinVarRef " << nodep << endl);
|
||||
nodep->name(nodep->varp()->name());
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstIfaceRefDType* nodep) override {
|
||||
void visit(AstIfaceRefDType* nodep) override {
|
||||
// May have changed cell names
|
||||
// TypeTable is always after all modules, so names are stable
|
||||
UINFO(8, " IFACEREFDTYPE " << nodep << endl);
|
||||
|
|
@ -308,12 +305,12 @@ private:
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
BeginRelinkVisitor(AstNetlist* nodep, BeginState*) { iterate(nodep); }
|
||||
virtual ~BeginRelinkVisitor() override = default;
|
||||
~BeginRelinkVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -326,5 +323,5 @@ void V3Begin::debeginAll(AstNetlist* nodep) {
|
|||
{ BeginVisitor{nodep, &state}; }
|
||||
if (state.anyFuncInBegin()) { BeginRelinkVisitor{nodep, &state}; }
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("begin", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("begin", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
|
||||
#include <map>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Branch state, as a visitor of each AstNode
|
||||
|
||||
|
|
@ -49,7 +51,6 @@ private:
|
|||
std::vector<AstCFunc*> m_cfuncsp; // List of all tasks
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
void reset() {
|
||||
m_likely = false;
|
||||
|
|
@ -63,14 +64,14 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeIf* nodep) override {
|
||||
void visit(AstNodeIf* nodep) override {
|
||||
UINFO(4, " IF: " << nodep << endl);
|
||||
VL_RESTORER(m_likely);
|
||||
VL_RESTORER(m_unlikely);
|
||||
{
|
||||
// Do if
|
||||
reset();
|
||||
iterateAndNextNull(nodep->ifsp());
|
||||
iterateAndNextNull(nodep->thensp());
|
||||
const int ifLikely = m_likely;
|
||||
const int ifUnlikely = m_unlikely;
|
||||
// Do else
|
||||
|
|
@ -87,17 +88,17 @@ private:
|
|||
} // else leave unknown
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeCCall* nodep) override {
|
||||
void visit(AstNodeCCall* nodep) override {
|
||||
checkUnlikely(nodep);
|
||||
nodep->funcp()->user1Inc();
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
void visit(AstCFunc* nodep) override {
|
||||
checkUnlikely(nodep);
|
||||
m_cfuncsp.push_back(nodep);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
void visit(AstNode* nodep) override {
|
||||
checkUnlikely(nodep);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
|
@ -116,7 +117,7 @@ public:
|
|||
iterateChildren(nodep);
|
||||
calc_tasks();
|
||||
}
|
||||
virtual ~BranchVisitor() override = default;
|
||||
~BranchVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@
|
|||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Generation counter for AstNode::m_brokenState
|
||||
|
||||
|
|
@ -132,8 +134,8 @@ private:
|
|||
public:
|
||||
// METHODS
|
||||
void clear() { m_linkable.clear(); }
|
||||
inline void addLinkable(const AstNode* nodep) { m_linkable.emplace(nodep); }
|
||||
inline bool isLinkable(const AstNode* nodep) const { return m_linkable.count(nodep) != 0; }
|
||||
void addLinkable(const AstNode* nodep) { m_linkable.emplace(nodep); }
|
||||
bool isLinkable(const AstNode* nodep) const { return m_linkable.count(nodep) != 0; }
|
||||
} s_linkableTable;
|
||||
|
||||
bool V3Broken::isLinkable(const AstNode* nodep) { return s_linkableTable.isLinkable(nodep); }
|
||||
|
|
@ -214,27 +216,27 @@ private:
|
|||
}
|
||||
return false;
|
||||
}
|
||||
virtual void visit(AstNodeAssign* nodep) override {
|
||||
void visit(AstNodeAssign* nodep) override {
|
||||
processAndIterate(nodep);
|
||||
UASSERT_OBJ(!(v3Global.assertDTypesResolved() && nodep->brokeLhsMustBeLvalue()
|
||||
&& VN_IS(nodep->lhsp(), NodeVarRef)
|
||||
&& !VN_AS(nodep->lhsp(), NodeVarRef)->access().isWriteOrRW()),
|
||||
nodep, "Assignment LHS is not an lvalue");
|
||||
}
|
||||
virtual void visit(AstRelease* nodep) override {
|
||||
void visit(AstRelease* nodep) override {
|
||||
processAndIterate(nodep);
|
||||
UASSERT_OBJ(!(v3Global.assertDTypesResolved() && VN_IS(nodep->lhsp(), NodeVarRef)
|
||||
&& !VN_AS(nodep->lhsp(), NodeVarRef)->access().isWriteOrRW()),
|
||||
nodep, "Release LHS is not an lvalue");
|
||||
}
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
void visit(AstScope* nodep) override {
|
||||
VL_RESTORER(m_inScope);
|
||||
{
|
||||
m_inScope = true;
|
||||
processAndIterate(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeVarRef* nodep) override {
|
||||
void visit(AstNodeVarRef* nodep) override {
|
||||
processAndIterate(nodep);
|
||||
// m_inScope because some Vars have initial variable references without scopes
|
||||
// This might false fire with some debug flags, as not certain we don't have temporary
|
||||
|
|
@ -252,7 +254,7 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
void visit(AstCFunc* nodep) override {
|
||||
UASSERT_OBJ(!m_cfuncp, nodep, "Nested AstCFunc");
|
||||
m_cfuncp = nodep;
|
||||
m_localVars.clear();
|
||||
|
|
@ -270,14 +272,14 @@ private:
|
|||
|
||||
m_cfuncp = nullptr;
|
||||
}
|
||||
virtual void visit(AstNodeIf* nodep) override {
|
||||
void visit(AstNodeIf* nodep) override {
|
||||
// Each branch is a separate local variable scope
|
||||
pushLocalScope();
|
||||
processEnter(nodep);
|
||||
processAndIterate(nodep->condp());
|
||||
if (AstNode* const ifsp = nodep->ifsp()) {
|
||||
if (AstNode* const thensp = nodep->thensp()) {
|
||||
pushLocalScope();
|
||||
processAndIterateList(ifsp);
|
||||
processAndIterateList(thensp);
|
||||
popLocalScope();
|
||||
}
|
||||
if (AstNode* const elsesp = nodep->elsesp()) {
|
||||
|
|
@ -288,21 +290,21 @@ private:
|
|||
processExit(nodep);
|
||||
popLocalScope();
|
||||
}
|
||||
virtual void visit(AstNodeStmt* nodep) override {
|
||||
void visit(AstNodeStmt* nodep) override {
|
||||
// For local variable checking act as if any statement introduces a new scope.
|
||||
// This is aggressive but conservatively correct.
|
||||
pushLocalScope();
|
||||
processAndIterate(nodep);
|
||||
popLocalScope();
|
||||
}
|
||||
virtual void visit(AstVar* nodep) override {
|
||||
void visit(AstVar* nodep) override {
|
||||
processAndIterate(nodep);
|
||||
if (m_cfuncp) {
|
||||
m_localVars.insert(nodep);
|
||||
m_localsStack.back().insert(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
void visit(AstNode* nodep) override {
|
||||
// Process not just iterate
|
||||
processAndIterate(nodep);
|
||||
}
|
||||
|
|
@ -310,7 +312,7 @@ private:
|
|||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit BrokenCheckVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~BrokenCheckVisitor() override = default;
|
||||
~BrokenCheckVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@
|
|||
#include <algorithm>
|
||||
#include <list>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
class VCtorType final {
|
||||
public:
|
||||
enum en : uint8_t { MODULE, CLASS, COVERAGE };
|
||||
|
|
@ -44,7 +46,7 @@ private:
|
|||
|
||||
public:
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline VCtorType(en _e)
|
||||
constexpr VCtorType(en _e)
|
||||
: m_e{_e} {}
|
||||
bool isClass() const { return m_e == CLASS; }
|
||||
bool isCoverage() const { return m_e == COVERAGE; }
|
||||
|
|
@ -77,7 +79,7 @@ private:
|
|||
if (!preventUnusedStmt.empty()) {
|
||||
funcp->addStmtsp(new AstCStmt{m_modp->fileline(), preventUnusedStmt});
|
||||
}
|
||||
m_modp->addStmtp(funcp);
|
||||
m_modp->addStmtsp(funcp);
|
||||
m_numStmts = 0;
|
||||
return funcp;
|
||||
}
|
||||
|
|
@ -136,7 +138,7 @@ void V3CCtors::evalAsserts() {
|
|||
funcp->isLoose(true);
|
||||
funcp->slow(false);
|
||||
funcp->ifdef("VL_DEBUG");
|
||||
modp->addStmtp(funcp);
|
||||
modp->addStmtsp(funcp);
|
||||
for (AstNode* np = modp->stmtsp(); np; np = np->nextp()) {
|
||||
if (AstVar* const varp = VN_CAST(np, Var)) {
|
||||
if (varp->isPrimaryInish() && !varp->isSc()) {
|
||||
|
|
@ -209,7 +211,7 @@ void V3CCtors::cctorsAll() {
|
|||
// If can be referred to by base pointer, need virtual delete
|
||||
funcp->isVirtual(classp->isExtended());
|
||||
funcp->slow(false);
|
||||
modp->addStmtp(funcp);
|
||||
modp->addStmtsp(funcp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@
|
|||
|
||||
#include <set>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
|
||||
// Visit within a module all nodes and data types they reference, finding
|
||||
|
|
@ -51,13 +53,13 @@ class CUseVisitor final : public VNVisitor {
|
|||
void addNewUse(AstNode* nodep, VUseType useType, const string& name) {
|
||||
if (m_didUse.emplace(useType, name).second) {
|
||||
AstCUse* const newp = new AstCUse{nodep->fileline(), useType, name};
|
||||
m_modp->addStmtp(newp);
|
||||
m_modp->addStmtsp(newp);
|
||||
UINFO(8, "Insert " << newp << endl);
|
||||
}
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstClassRefDType* nodep) override {
|
||||
void visit(AstClassRefDType* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
if (!m_impOnly) addNewUse(nodep, VUseType::INT_FWD_CLASS, nodep->classp()->name());
|
||||
// Need to include extends() when we implement, but no need for pointers to know
|
||||
|
|
@ -67,17 +69,17 @@ class CUseVisitor final : public VNVisitor {
|
|||
iterateChildren(nodep->classp()); // This also gets all extend classes
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeDType* nodep) override {
|
||||
void visit(AstNodeDType* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
if (nodep->virtRefDTypep()) iterate(nodep->virtRefDTypep());
|
||||
if (nodep->virtRefDType2p()) iterate(nodep->virtRefDType2p());
|
||||
}
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
void visit(AstNode* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
if (nodep->dtypep() && !nodep->dtypep()->user1()) iterate(nodep->dtypep());
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstCell* nodep) override {
|
||||
void visit(AstCell* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
// Currently no IMP_INCLUDE because we include __Syms which has them all
|
||||
addNewUse(nodep, VUseType::INT_FWD_CLASS, nodep->modp()->name());
|
||||
|
|
@ -90,7 +92,7 @@ public:
|
|||
: m_modp(modp) {
|
||||
iterate(modp);
|
||||
}
|
||||
virtual ~CUseVisitor() override = default;
|
||||
~CUseVisitor() override = default;
|
||||
VL_UNCOPYABLE(CUseVisitor);
|
||||
};
|
||||
|
||||
|
|
@ -106,5 +108,5 @@ void V3CUse::cUseAll() {
|
|||
// for each output file and put under that
|
||||
CUseVisitor{modp};
|
||||
}
|
||||
V3Global::dumpCheckGlobalTree("cuse", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("cuse", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
#define CASE_OVERLAP_WIDTH 16 // Maximum width we can check for overlaps in
|
||||
#define CASE_BARF 999999 // Magic width when non-constant
|
||||
#define CASE_ENCODER_GROUP_DEPTH 8 // Levels of priority to be ORed together in top IF tree
|
||||
|
|
@ -57,9 +59,8 @@ private:
|
|||
= nullptr; // Under a CASE value node, if so the relevant case statement
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
virtual void visit(AstNodeCase* nodep) override {
|
||||
void visit(AstNodeCase* nodep) override {
|
||||
if (VN_IS(nodep, Case) && VN_AS(nodep, Case)->casex()) {
|
||||
nodep->v3warn(CASEX, "Suggest casez (with ?'s) in place of casex (with X's)");
|
||||
}
|
||||
|
|
@ -86,7 +87,7 @@ private:
|
|||
m_caseExprp = nullptr;
|
||||
}
|
||||
}
|
||||
virtual void visit(AstConst* nodep) override {
|
||||
void visit(AstConst* nodep) override {
|
||||
// See also neverItem
|
||||
if (m_caseExprp && nodep->num().isFourState()) {
|
||||
if (VN_IS(m_caseExprp, GenCase)) {
|
||||
|
|
@ -107,12 +108,12 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CaseLintVisitor(AstNodeCase* nodep) { iterate(nodep); }
|
||||
virtual ~CaseLintVisitor() override = default;
|
||||
~CaseLintVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -138,7 +139,6 @@ private:
|
|||
std::array<AstNode*, 1 << CASE_OVERLAP_WIDTH> m_valueItem;
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
bool isCaseTreeFast(AstCase* nodep) {
|
||||
int width = 0;
|
||||
|
|
@ -245,7 +245,7 @@ private:
|
|||
// Convert valueItem from AstCaseItem* to the expression
|
||||
// Not done earlier, as we may now have a nullptr because it's just a ";" NOP branch
|
||||
for (uint32_t i = 0; i < numCases; ++i) {
|
||||
m_valueItem[i] = VN_AS(m_valueItem[i], CaseItem)->bodysp();
|
||||
m_valueItem[i] = VN_AS(m_valueItem[i], CaseItem)->stmtsp();
|
||||
}
|
||||
return true; // All is fine
|
||||
}
|
||||
|
|
@ -346,7 +346,7 @@ private:
|
|||
itemp = VN_AS(itemp->nextp(), CaseItem)) {
|
||||
if (!itemp->condsp()) {
|
||||
// Default clause. Just make true, we'll optimize it away later
|
||||
itemp->condsp(new AstConst(itemp->fileline(), AstConst::BitTrue()));
|
||||
itemp->addCondsp(new AstConst(itemp->fileline(), AstConst::BitTrue()));
|
||||
hadDefault = true;
|
||||
} else {
|
||||
// Expressioned clause
|
||||
|
|
@ -397,7 +397,7 @@ private:
|
|||
}
|
||||
}
|
||||
// Replace expression in tree
|
||||
itemp->condsp(ifexprp);
|
||||
itemp->addCondsp(ifexprp);
|
||||
}
|
||||
}
|
||||
VL_DO_DANGLING(cexprp->deleteTree(), cexprp);
|
||||
|
|
@ -420,7 +420,7 @@ private:
|
|||
AstIf* itemnextp = nullptr;
|
||||
for (AstCaseItem* itemp = nodep->itemsp(); itemp;
|
||||
itemp = VN_AS(itemp->nextp(), CaseItem)) {
|
||||
AstNode* const istmtsp = itemp->bodysp(); // Maybe null -- no action.
|
||||
AstNode* const istmtsp = itemp->stmtsp(); // Maybe null -- no action.
|
||||
if (istmtsp) istmtsp->unlinkFrBackWithNext();
|
||||
// Expressioned clause
|
||||
AstNode* const ifexprp = itemp->condsp()->unlinkFrBack();
|
||||
|
|
@ -452,7 +452,7 @@ private:
|
|||
if (itemnextp) {
|
||||
itemnextp->addElsesp(newp);
|
||||
} else {
|
||||
groupnextp->addIfsp(newp); // First in a new group
|
||||
groupnextp->addThensp(newp); // First in a new group
|
||||
}
|
||||
itemnextp = newp;
|
||||
}
|
||||
|
|
@ -493,7 +493,7 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstCase* nodep) override {
|
||||
void visit(AstCase* nodep) override {
|
||||
V3Case::caseLint(nodep);
|
||||
iterateChildren(nodep);
|
||||
if (debug() >= 9) nodep->dumpTree(cout, " case_old: ");
|
||||
|
|
@ -510,7 +510,7 @@ private:
|
|||
}
|
||||
}
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
void visit(AstNode* nodep) override {
|
||||
if (VN_IS(nodep, Always)) m_alwaysp = nodep;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
|
@ -521,7 +521,7 @@ public:
|
|||
for (auto& itr : m_valueItem) itr = nullptr;
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~CaseVisitor() override {
|
||||
~CaseVisitor() override {
|
||||
V3Stats::addStat("Optimizations, Cases parallelized", m_statCaseFast);
|
||||
V3Stats::addStat("Optimizations, Cases complex", m_statCaseSlow);
|
||||
}
|
||||
|
|
@ -533,7 +533,7 @@ public:
|
|||
void V3Case::caseAll(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ CaseVisitor{nodep}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("case", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("case", 0, dumpTree() >= 3);
|
||||
}
|
||||
void V3Case::caseLint(AstNodeCase* nodep) {
|
||||
UINFO(4, __FUNCTION__ << ": " << endl);
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Cast state, as a visitor of each AstNode
|
||||
|
||||
|
|
@ -60,7 +62,6 @@ private:
|
|||
// STATE
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
void insertCast(AstNode* nodep, int needsize) { // We'll insert ABOVE passed node
|
||||
UINFO(4, " NeedCast " << nodep << endl);
|
||||
|
|
@ -111,25 +112,25 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeUniop* nodep) override {
|
||||
void visit(AstNodeUniop* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
nodep->user1(nodep->lhsp()->user1());
|
||||
if (nodep->sizeMattersLhs()) ensureCast(nodep->lhsp());
|
||||
}
|
||||
virtual void visit(AstNodeBiop* nodep) override {
|
||||
void visit(AstNodeBiop* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
nodep->user1(nodep->lhsp()->user1() | nodep->rhsp()->user1());
|
||||
if (nodep->sizeMattersLhs()) ensureCast(nodep->lhsp());
|
||||
if (nodep->sizeMattersRhs()) ensureCast(nodep->rhsp());
|
||||
}
|
||||
virtual void visit(AstNodeTriop* nodep) override {
|
||||
void visit(AstNodeTriop* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
nodep->user1(nodep->lhsp()->user1() | nodep->rhsp()->user1() | nodep->thsp()->user1());
|
||||
if (nodep->sizeMattersLhs()) ensureCast(nodep->lhsp());
|
||||
if (nodep->sizeMattersRhs()) ensureCast(nodep->rhsp());
|
||||
if (nodep->sizeMattersThs()) ensureCast(nodep->thsp());
|
||||
}
|
||||
virtual void visit(AstNodeQuadop* nodep) override {
|
||||
void visit(AstNodeQuadop* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
nodep->user1(nodep->lhsp()->user1() | nodep->rhsp()->user1() | nodep->thsp()->user1()
|
||||
| nodep->fhsp()->user1());
|
||||
|
|
@ -138,12 +139,12 @@ private:
|
|||
if (nodep->sizeMattersThs()) ensureCast(nodep->thsp());
|
||||
if (nodep->sizeMattersFhs()) ensureCast(nodep->fhsp());
|
||||
}
|
||||
virtual void visit(AstCCast* nodep) override {
|
||||
void visit(AstCCast* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureLower32Cast(nodep);
|
||||
nodep->user1(1);
|
||||
}
|
||||
virtual void visit(AstNegate* nodep) override {
|
||||
void visit(AstNegate* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
nodep->user1(nodep->lhsp()->user1());
|
||||
if (nodep->lhsp()->widthMin() == 1) {
|
||||
|
|
@ -155,7 +156,7 @@ private:
|
|||
ensureCast(nodep->lhsp());
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep) override {
|
||||
void visit(AstVarRef* nodep) override {
|
||||
const AstNode* const backp = nodep->backp();
|
||||
if (nodep->access().isReadOnly() && !VN_IS(backp, CCast) && VN_IS(backp, NodeMath)
|
||||
&& !VN_IS(backp, ArraySel) && !VN_IS(backp, RedXor) && backp->width()
|
||||
|
|
@ -166,7 +167,7 @@ private:
|
|||
}
|
||||
nodep->user1(1);
|
||||
}
|
||||
virtual void visit(AstConst* nodep) override {
|
||||
void visit(AstConst* nodep) override {
|
||||
// Constants are of unknown size if smaller than 33 bits, because
|
||||
// we're too lazy to wrap every constant in the universe in
|
||||
// ((IData)#).
|
||||
|
|
@ -174,29 +175,29 @@ private:
|
|||
}
|
||||
|
||||
// Null dereference protection
|
||||
virtual void visit(AstNullCheck* nodep) override {
|
||||
void visit(AstNullCheck* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
nodep->user1(nodep->lhsp()->user1());
|
||||
}
|
||||
virtual void visit(AstCMethodCall* nodep) override {
|
||||
void visit(AstCMethodCall* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureNullChecked(nodep->fromp());
|
||||
}
|
||||
virtual void visit(AstMemberSel* nodep) override {
|
||||
void visit(AstMemberSel* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureNullChecked(nodep->fromp());
|
||||
}
|
||||
|
||||
// NOPs
|
||||
virtual void visit(AstVar*) override {}
|
||||
void visit(AstVar*) override {}
|
||||
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CastVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~CastVisitor() override = default;
|
||||
~CastVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -205,5 +206,5 @@ public:
|
|||
void V3Cast::castAll(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ CastVisitor{nodep}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("cast", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("cast", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,13 +38,14 @@
|
|||
#include <iomanip>
|
||||
#include <memory>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
constexpr int CDC_WEIGHT_ASYNC = 0x1000; // Weight for edges that feed async logic
|
||||
|
||||
//######################################################################
|
||||
|
||||
class CdcBaseVisitor VL_NOT_FINAL : public VNVisitor {
|
||||
public:
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -67,9 +68,9 @@ public:
|
|||
, m_srcDomainSet{false}
|
||||
, m_dstDomainSet{false}
|
||||
, m_asyncPath{false} {}
|
||||
virtual ~CdcEitherVertex() override = default;
|
||||
~CdcEitherVertex() override = default;
|
||||
// ACCESSORS
|
||||
virtual FileLine* fileline() const override { return nodep()->fileline(); }
|
||||
FileLine* fileline() const override { return nodep()->fileline(); }
|
||||
AstScope* scopep() const { return m_scopep; }
|
||||
AstNode* nodep() const { return m_nodep; }
|
||||
AstSenTree* srcDomainp() const { return m_srcDomainp; }
|
||||
|
|
@ -93,11 +94,11 @@ public:
|
|||
CdcVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
|
||||
: CdcEitherVertex{graphp, scopep, varScp}
|
||||
, m_varScp{varScp} {}
|
||||
virtual ~CdcVarVertex() override = default;
|
||||
~CdcVarVertex() override = default;
|
||||
// ACCESSORS
|
||||
AstVarScope* varScp() const { return m_varScp; }
|
||||
virtual string name() const override { return (cvtToHex(m_varScp) + " " + varScp()->name()); }
|
||||
virtual string dotColor() const override {
|
||||
string name() const override { return (cvtToHex(m_varScp) + " " + varScp()->name()); }
|
||||
string dotColor() const override {
|
||||
return fromFlop() ? "green" : cntAsyncRst() ? "red" : "blue";
|
||||
}
|
||||
int cntAsyncRst() const { return m_cntAsyncRst; }
|
||||
|
|
@ -118,12 +119,10 @@ public:
|
|||
srcDomainp(sensenodep);
|
||||
dstDomainp(sensenodep);
|
||||
}
|
||||
virtual ~CdcLogicVertex() override = default;
|
||||
~CdcLogicVertex() override = default;
|
||||
// ACCESSORS
|
||||
virtual string name() const override {
|
||||
return (cvtToHex(nodep()) + "@" + scopep()->prettyName());
|
||||
}
|
||||
virtual string dotColor() const override { return hazard() ? "black" : "yellow"; }
|
||||
string name() const override { return (cvtToHex(nodep()) + "@" + scopep()->prettyName()); }
|
||||
string dotColor() const override { return hazard() ? "black" : "yellow"; }
|
||||
bool hazard() const { return m_hazard; }
|
||||
void setHazard(AstNode* nodep) {
|
||||
m_hazard = true;
|
||||
|
|
@ -144,7 +143,7 @@ private:
|
|||
std::ofstream* const m_ofp = nullptr; // Output file
|
||||
string m_prefix;
|
||||
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
void visit(AstNode* nodep) override {
|
||||
*m_ofp << m_prefix;
|
||||
if (nodep->user3()) {
|
||||
*m_ofp << " %%";
|
||||
|
|
@ -171,7 +170,7 @@ public:
|
|||
, m_prefix{prefix} {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~CdcDumpVisitor() override = default;
|
||||
~CdcDumpVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -181,7 +180,7 @@ private:
|
|||
int m_maxLineno = 0;
|
||||
size_t m_maxFilenameLen = 0;
|
||||
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
void visit(AstNode* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
// Keeping line+filename lengths separate is much faster than calling ascii().length()
|
||||
if (nodep->fileline()->lineno() >= m_maxLineno) {
|
||||
|
|
@ -195,7 +194,7 @@ private:
|
|||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CdcWidthVisitor(AstNode* nodep) { iterate(nodep); }
|
||||
virtual ~CdcWidthVisitor() override = default;
|
||||
~CdcWidthVisitor() override = default;
|
||||
// ACCESSORS
|
||||
int maxWidth() const {
|
||||
size_t width = 1;
|
||||
|
|
@ -325,13 +324,11 @@ private:
|
|||
|
||||
void analyze() {
|
||||
UINFO(3, __FUNCTION__ << ": " << endl);
|
||||
// if (debug() > 6) m_graph.dump();
|
||||
if (debug() > 6) m_graph.dumpDotFilePrefixed("cdc_pre");
|
||||
if (dumpGraph() > 6) m_graph.dumpDotFilePrefixed("cdc_pre");
|
||||
// This will MAX across edge weights
|
||||
m_graph.removeRedundantEdges(&V3GraphEdge::followAlwaysTrue);
|
||||
//
|
||||
m_graph.removeRedundantEdges(
|
||||
&V3GraphEdge::followAlwaysTrue); // This will MAX across edge weights
|
||||
//
|
||||
m_graph.dumpDotFilePrefixed("cdc_simp");
|
||||
if (dumpGraph() >= 3) m_graph.dumpDotFilePrefixed("cdc_simp");
|
||||
//
|
||||
analyzeReset();
|
||||
}
|
||||
|
|
@ -628,21 +625,21 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
m_modp = nodep;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
void visit(AstScope* nodep) override {
|
||||
UINFO(4, " SCOPE " << nodep << endl);
|
||||
m_scopep = nodep;
|
||||
m_logicVertexp = nullptr;
|
||||
iterateChildren(nodep);
|
||||
m_scopep = nullptr;
|
||||
}
|
||||
virtual void visit(AstActive* nodep) override {
|
||||
void visit(AstActive* nodep) override {
|
||||
// Create required blocks and add to module
|
||||
UINFO(4, " BLOCK " << nodep << endl);
|
||||
AstNode::user2ClearTree();
|
||||
|
|
@ -654,7 +651,7 @@ private:
|
|||
m_domainp = nullptr;
|
||||
AstNode::user2ClearTree();
|
||||
}
|
||||
virtual void visit(AstNodeVarRef* nodep) override {
|
||||
void visit(AstNodeVarRef* nodep) override {
|
||||
if (m_scopep) {
|
||||
UASSERT_OBJ(m_logicVertexp, nodep, "Var ref not under a logic block");
|
||||
AstVarScope* const varscp = nodep->varScopep();
|
||||
|
|
@ -682,53 +679,53 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAssignDly* nodep) override {
|
||||
void visit(AstAssignDly* nodep) override {
|
||||
m_inDly = true;
|
||||
iterateChildren(nodep);
|
||||
m_inDly = false;
|
||||
}
|
||||
virtual void visit(AstSenItem* nodep) override {
|
||||
void visit(AstSenItem* nodep) override {
|
||||
m_inSenItem = true;
|
||||
iterateChildren(nodep);
|
||||
m_inSenItem = false;
|
||||
}
|
||||
virtual void visit(AstAlways* nodep) override { iterateNewStmt(nodep); }
|
||||
virtual void visit(AstAlwaysPublic* nodep) override {
|
||||
void visit(AstAlways* nodep) override { iterateNewStmt(nodep); }
|
||||
void visit(AstAlwaysPublic* nodep) override {
|
||||
// CDC doesn't care about public variables
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) override { iterateNewStmt(nodep); }
|
||||
virtual void visit(AstAssignAlias* nodep) override { iterateNewStmt(nodep); }
|
||||
virtual void visit(AstAssignW* nodep) override { iterateNewStmt(nodep); }
|
||||
void visit(AstCFunc* nodep) override { iterateNewStmt(nodep); }
|
||||
void visit(AstAssignAlias* nodep) override { iterateNewStmt(nodep); }
|
||||
void visit(AstAssignW* nodep) override { iterateNewStmt(nodep); }
|
||||
|
||||
// Math that shouldn't cause us to clear hazard
|
||||
virtual void visit(AstConst*) override {}
|
||||
virtual void visit(AstReplicate* nodep) override { iterateChildren(nodep); }
|
||||
virtual void visit(AstConcat* nodep) override { iterateChildren(nodep); }
|
||||
virtual void visit(AstNot* nodep) override { iterateChildren(nodep); }
|
||||
virtual void visit(AstSel* nodep) override {
|
||||
void visit(AstConst*) override {}
|
||||
void visit(AstReplicate* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstConcat* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNot* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstSel* nodep) override {
|
||||
if (!VN_IS(nodep->lsbp(), Const)) setNodeHazard(nodep);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeSel* nodep) override {
|
||||
void visit(AstNodeSel* nodep) override {
|
||||
if (!VN_IS(nodep->bitp(), Const)) setNodeHazard(nodep);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
// Ignores
|
||||
virtual void visit(AstInitial*) override {}
|
||||
virtual void visit(AstInitialAutomatic*) override {}
|
||||
virtual void visit(AstInitialStatic*) override {}
|
||||
virtual void visit(AstTraceDecl*) override {}
|
||||
virtual void visit(AstCoverToggle*) override {}
|
||||
virtual void visit(AstNodeDType*) override {}
|
||||
void visit(AstInitial*) override {}
|
||||
void visit(AstInitialAutomatic*) override {}
|
||||
void visit(AstInitialStatic*) override {}
|
||||
void visit(AstTraceDecl*) override {}
|
||||
void visit(AstCoverToggle*) override {}
|
||||
void visit(AstNodeDType*) override {}
|
||||
|
||||
//--------------------
|
||||
// Default
|
||||
virtual void visit(AstNodeMath* nodep) override {
|
||||
void visit(AstNodeMath* nodep) override {
|
||||
setNodeHazard(nodep);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
|
|
@ -754,7 +751,7 @@ public:
|
|||
*m_ofp << '\n';
|
||||
}
|
||||
}
|
||||
virtual ~CdcVisitor() override {
|
||||
~CdcVisitor() override {
|
||||
if (m_ofp) VL_DO_CLEAR(delete m_ofp, m_ofp = nullptr);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
|
||||
class ChangedState final {
|
||||
|
|
@ -67,7 +69,7 @@ public:
|
|||
m_tlChgFuncp->isStatic(false);
|
||||
m_tlChgFuncp->isLoose(true);
|
||||
m_tlChgFuncp->declPrivate(true);
|
||||
m_scopetopp->addActivep(m_tlChgFuncp);
|
||||
m_scopetopp->addBlocksp(m_tlChgFuncp);
|
||||
// Each change detection function needs at least one AstChangeDet
|
||||
// to ensure that V3EmitC outputs the necessary code.
|
||||
maybeCreateMidChg();
|
||||
|
|
@ -86,7 +88,7 @@ public:
|
|||
m_chgFuncp->isStatic(false);
|
||||
m_chgFuncp->isLoose(true);
|
||||
m_chgFuncp->declPrivate(true);
|
||||
m_scopetopp->addActivep(m_chgFuncp);
|
||||
m_scopetopp->addBlocksp(m_chgFuncp);
|
||||
|
||||
// Add a top call to it
|
||||
AstCCall* const callp = new AstCCall{m_scopetopp->fileline(), m_chgFuncp};
|
||||
|
|
@ -155,13 +157,13 @@ private:
|
|||
m_state.m_numStmts += initp->nodeCount() + m_varEqnp->widthWords();
|
||||
}
|
||||
|
||||
virtual void visit(AstBasicDType*) override { //
|
||||
void visit(AstBasicDType*) override { //
|
||||
newChangeDet();
|
||||
}
|
||||
virtual void visit(AstPackArrayDType*) override { //
|
||||
void visit(AstPackArrayDType*) override { //
|
||||
newChangeDet();
|
||||
}
|
||||
virtual void visit(AstUnpackArrayDType* nodep) override {
|
||||
void visit(AstUnpackArrayDType* nodep) override {
|
||||
for (int index = 0; index < nodep->elementsConst(); ++index) {
|
||||
VL_RESTORER(m_varEqnp);
|
||||
VL_RESTORER(m_newLvEqnp);
|
||||
|
|
@ -181,7 +183,7 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeUOrStructDType* nodep) override {
|
||||
void visit(AstNodeUOrStructDType* nodep) override {
|
||||
if (nodep->packedUnsup()) {
|
||||
newChangeDet();
|
||||
} else {
|
||||
|
|
@ -191,7 +193,7 @@ private:
|
|||
<< m_vscp->varp()->prettyNameQ());
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
void visit(AstNode* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (debug()) nodep->dumpTree(cout, "-DETECTARRAY-general-");
|
||||
m_vscp->v3warn(E_DETECTARRAY, "Unsupported: Can't detect changes on complex variable"
|
||||
|
|
@ -218,9 +220,9 @@ public:
|
|||
// CHANGEDET(VARREF(_last), VARREF(var))
|
||||
AstVar* const newvarp
|
||||
= new AstVar{varp->fileline(), VVarType::MODULETEMP, newvarname, varp};
|
||||
m_state.m_topModp->addStmtp(newvarp);
|
||||
m_state.m_topModp->addStmtsp(newvarp);
|
||||
m_newvscp = new AstVarScope{m_vscp->fileline(), m_state.m_scopetopp, newvarp};
|
||||
m_state.m_scopetopp->addVarp(m_newvscp);
|
||||
m_state.m_scopetopp->addVarsp(m_newvscp);
|
||||
|
||||
m_varEqnp = new AstVarRef{m_vscp->fileline(), m_vscp, VAccess::READ};
|
||||
m_newLvEqnp = new AstVarRef{m_vscp->fileline(), m_newvscp, VAccess::WRITE};
|
||||
|
|
@ -231,7 +233,7 @@ public:
|
|||
m_newLvEqnp->deleteTree();
|
||||
m_newRvEqnp->deleteTree();
|
||||
}
|
||||
virtual ~ChangedInsertVisitor() override = default;
|
||||
~ChangedInsertVisitor() override = default;
|
||||
VL_UNCOPYABLE(ChangedInsertVisitor);
|
||||
};
|
||||
|
||||
|
|
@ -252,5 +254,5 @@ void V3Changed::changedAll(AstNetlist* nodep) {
|
|||
}
|
||||
});
|
||||
|
||||
V3Global::dumpCheckGlobalTree("changed", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("changed", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include "V3Ast.h"
|
||||
#include "V3Global.h"
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
|
||||
class ClassVisitor final : public VNVisitor {
|
||||
|
|
@ -47,14 +49,13 @@ private:
|
|||
std::vector<std::pair<AstNode*, AstNodeModule*>> m_toPackageMoves;
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
virtual void visit(AstClass* nodep) override {
|
||||
void visit(AstClass* nodep) override {
|
||||
if (nodep->user1SetOnce()) return;
|
||||
// Move this class
|
||||
nodep->name(m_prefix + nodep->name());
|
||||
nodep->unlinkFrBack();
|
||||
v3Global.rootp()->addModulep(nodep);
|
||||
v3Global.rootp()->addModulesp(nodep);
|
||||
// Make containing package
|
||||
// Note origName is the same as the class origName so errors look correct
|
||||
AstClassPackage* const packagep
|
||||
|
|
@ -62,7 +63,7 @@ private:
|
|||
packagep->name(nodep->name() + "__Vclpkg");
|
||||
nodep->classOrPackagep(packagep);
|
||||
packagep->classp(nodep);
|
||||
v3Global.rootp()->addModulep(packagep);
|
||||
v3Global.rootp()->addModulesp(packagep);
|
||||
// Add package to hierarchy
|
||||
AstCell* const cellp = new AstCell{packagep->fileline(),
|
||||
packagep->fileline(),
|
||||
|
|
@ -72,7 +73,7 @@ private:
|
|||
nullptr,
|
||||
nullptr};
|
||||
cellp->modp(packagep);
|
||||
v3Global.rootp()->topModulep()->addStmtp(cellp);
|
||||
v3Global.rootp()->topModulep()->addStmtsp(cellp);
|
||||
// Find class's scope
|
||||
// Alternative would be to move this and related to V3Scope
|
||||
const AstScope* classScopep = nullptr;
|
||||
|
|
@ -85,7 +86,7 @@ private:
|
|||
AstScope* const scopep
|
||||
= new AstScope{nodep->fileline(), packagep, classScopep->name(),
|
||||
classScopep->aboveScopep(), classScopep->aboveCellp()};
|
||||
packagep->addStmtp(scopep);
|
||||
packagep->addStmtsp(scopep);
|
||||
// Iterate
|
||||
VL_RESTORER(m_prefix);
|
||||
VL_RESTORER(m_classPackagep);
|
||||
|
|
@ -100,7 +101,7 @@ private:
|
|||
}
|
||||
nodep->repairCache();
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
// Visit for NodeModules that are not AstClass (AstClass is-a AstNodeModule)
|
||||
VL_RESTORER(m_prefix);
|
||||
{
|
||||
|
|
@ -109,7 +110,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstVar* nodep) override {
|
||||
void visit(AstVar* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_packageScopep) {
|
||||
if (m_ftaskp && m_ftaskp->lifetime().isStatic()) {
|
||||
|
|
@ -127,12 +128,12 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstVarScope* nodep) override {
|
||||
void visit(AstVarScope* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
nodep->varp()->user1p(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeFTask* nodep) override {
|
||||
void visit(AstNodeFTask* nodep) override {
|
||||
VL_RESTORER(m_ftaskp);
|
||||
{
|
||||
m_ftaskp = nodep;
|
||||
|
|
@ -142,7 +143,7 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
void visit(AstCFunc* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
// Don't move now, or wouldn't keep interating the class
|
||||
// TODO move function statics only
|
||||
|
|
@ -150,14 +151,14 @@ private:
|
|||
// m_toScopeMoves.push_back(std::make_pair(nodep, m_classScopep));
|
||||
//}
|
||||
}
|
||||
virtual void visit(AstInitial* nodep) override {
|
||||
void visit(AstInitial* nodep) override {
|
||||
// But not AstInitialAutomatic, which remains under the class
|
||||
iterateChildren(nodep);
|
||||
if (m_packageScopep) {
|
||||
m_toScopeMoves.emplace_back(std::make_pair(nodep, m_packageScopep));
|
||||
}
|
||||
}
|
||||
virtual void visit(AstInitialStatic* nodep) override {
|
||||
void visit(AstInitialStatic* nodep) override {
|
||||
// But not AstInitialAutomatic, which remains under the class
|
||||
iterateChildren(nodep);
|
||||
if (m_packageScopep) {
|
||||
|
|
@ -165,28 +166,28 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeMath* nodep) override {} // Short circuit
|
||||
virtual void visit(AstNodeStmt* nodep) override {} // Short circuit
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNodeMath* nodep) override {} // Short circuit
|
||||
void visit(AstNodeStmt* nodep) override {} // Short circuit
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit ClassVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~ClassVisitor() override {
|
||||
~ClassVisitor() override {
|
||||
for (auto moved : m_toScopeMoves) {
|
||||
AstNode* const nodep = moved.first;
|
||||
AstScope* const scopep = moved.second;
|
||||
UINFO(9, "moving " << nodep << " to " << scopep << endl);
|
||||
if (VN_IS(nodep, NodeFTask)) {
|
||||
scopep->addActivep(nodep->unlinkFrBack());
|
||||
scopep->addBlocksp(nodep->unlinkFrBack());
|
||||
} else if (VN_IS(nodep, Var)) {
|
||||
AstVarScope* const vscp = VN_AS(nodep->user1p(), VarScope);
|
||||
vscp->scopep(scopep);
|
||||
vscp->unlinkFrBack();
|
||||
scopep->addVarp(vscp);
|
||||
scopep->addVarsp(vscp);
|
||||
} else if (VN_IS(nodep, Initial) || VN_IS(nodep, InitialStatic)) {
|
||||
nodep->unlinkFrBack();
|
||||
scopep->addActivep(nodep);
|
||||
scopep->addBlocksp(nodep);
|
||||
} else {
|
||||
nodep->v3fatalSrc("Bad case");
|
||||
}
|
||||
|
|
@ -196,7 +197,7 @@ public:
|
|||
AstNodeModule* const modp = moved.second;
|
||||
UINFO(9, "moving " << nodep << " to " << modp << endl);
|
||||
nodep->unlinkFrBack();
|
||||
modp->addStmtp(nodep);
|
||||
modp->addStmtsp(nodep);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -207,5 +208,5 @@ public:
|
|||
void V3Class::classAll(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ ClassVisitor{nodep}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("class", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("class", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Clean state, as a visitor of each AstNode
|
||||
|
||||
|
|
@ -54,7 +56,6 @@ private:
|
|||
const AstNodeModule* m_modp = nullptr;
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
// Width resetting
|
||||
int cppWidth(AstNode* nodep) {
|
||||
|
|
@ -173,134 +174,134 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
m_modp = nodep;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeUniop* nodep) override {
|
||||
void visit(AstNodeUniop* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
computeCppWidth(nodep);
|
||||
if (nodep->cleanLhs()) ensureClean(nodep->lhsp());
|
||||
setClean(nodep, nodep->cleanOut());
|
||||
}
|
||||
virtual void visit(AstNodeBiop* nodep) override {
|
||||
void visit(AstNodeBiop* nodep) override {
|
||||
operandBiop(nodep);
|
||||
setClean(nodep, nodep->cleanOut());
|
||||
}
|
||||
virtual void visit(AstAnd* nodep) override {
|
||||
void visit(AstAnd* nodep) override {
|
||||
operandBiop(nodep);
|
||||
setClean(nodep, isClean(nodep->lhsp()) || isClean(nodep->rhsp()));
|
||||
}
|
||||
virtual void visit(AstXor* nodep) override {
|
||||
void visit(AstXor* nodep) override {
|
||||
operandBiop(nodep);
|
||||
setClean(nodep, isClean(nodep->lhsp()) && isClean(nodep->rhsp()));
|
||||
}
|
||||
virtual void visit(AstOr* nodep) override {
|
||||
void visit(AstOr* nodep) override {
|
||||
operandBiop(nodep);
|
||||
setClean(nodep, isClean(nodep->lhsp()) && isClean(nodep->rhsp()));
|
||||
}
|
||||
virtual void visit(AstNodeQuadop* nodep) override {
|
||||
void visit(AstNodeQuadop* nodep) override {
|
||||
operandQuadop(nodep);
|
||||
setClean(nodep, nodep->cleanOut());
|
||||
}
|
||||
virtual void visit(AstNodeMath* nodep) override {
|
||||
void visit(AstNodeMath* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
computeCppWidth(nodep);
|
||||
setClean(nodep, nodep->cleanOut());
|
||||
}
|
||||
virtual void visit(AstNodeAssign* nodep) override {
|
||||
void visit(AstNodeAssign* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
computeCppWidth(nodep);
|
||||
if (nodep->cleanRhs()) ensureClean(nodep->rhsp());
|
||||
}
|
||||
virtual void visit(AstText* nodep) override { //
|
||||
void visit(AstText* nodep) override { //
|
||||
setClean(nodep, true);
|
||||
}
|
||||
virtual void visit(AstScopeName* nodep) override { //
|
||||
void visit(AstScopeName* nodep) override { //
|
||||
setClean(nodep, true);
|
||||
}
|
||||
virtual void visit(AstCNew* nodep) override {
|
||||
void visit(AstCNew* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
setClean(nodep, true);
|
||||
}
|
||||
virtual void visit(AstSel* nodep) override {
|
||||
void visit(AstSel* nodep) override {
|
||||
operandTriop(nodep);
|
||||
setClean(nodep, nodep->cleanOut());
|
||||
}
|
||||
virtual void visit(AstUCFunc* nodep) override {
|
||||
void visit(AstUCFunc* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
computeCppWidth(nodep);
|
||||
setClean(nodep, false);
|
||||
// We always clean, as we don't trust those pesky users.
|
||||
if (!VN_IS(nodep->backp(), And)) insertClean(nodep);
|
||||
ensureCleanAndNext(nodep->bodysp());
|
||||
ensureCleanAndNext(nodep->exprsp());
|
||||
}
|
||||
virtual void visit(AstTraceDecl* nodep) override {
|
||||
void visit(AstTraceDecl* nodep) override {
|
||||
// No cleaning, or would loose pointer to enum
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstTraceInc* nodep) override {
|
||||
void visit(AstTraceInc* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureCleanAndNext(nodep->valuep());
|
||||
}
|
||||
virtual void visit(AstTypedef* nodep) override {
|
||||
void visit(AstTypedef* nodep) override {
|
||||
// No cleaning, or would loose pointer to enum
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstParamTypeDType* nodep) override {
|
||||
void visit(AstParamTypeDType* nodep) override {
|
||||
// No cleaning, or would loose pointer to enum
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
// Control flow operators
|
||||
virtual void visit(AstNodeCond* nodep) override {
|
||||
void visit(AstNodeCond* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureClean(nodep->condp());
|
||||
setClean(nodep, isClean(nodep->expr1p()) && isClean(nodep->expr2p()));
|
||||
setClean(nodep, isClean(nodep->thenp()) && isClean(nodep->elsep()));
|
||||
}
|
||||
virtual void visit(AstWhile* nodep) override {
|
||||
void visit(AstWhile* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureClean(nodep->condp());
|
||||
}
|
||||
virtual void visit(AstNodeIf* nodep) override {
|
||||
void visit(AstNodeIf* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureClean(nodep->condp());
|
||||
}
|
||||
virtual void visit(AstSFormatF* nodep) override {
|
||||
void visit(AstSFormatF* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureCleanAndNext(nodep->exprsp());
|
||||
setClean(nodep, true); // generates a string, so not relevant
|
||||
}
|
||||
virtual void visit(AstUCStmt* nodep) override {
|
||||
void visit(AstUCStmt* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureCleanAndNext(nodep->bodysp());
|
||||
ensureCleanAndNext(nodep->exprsp());
|
||||
}
|
||||
virtual void visit(AstNodeCCall* nodep) override {
|
||||
void visit(AstNodeCCall* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureCleanAndNext(nodep->argsp());
|
||||
setClean(nodep, true);
|
||||
}
|
||||
virtual void visit(AstCMethodHard* nodep) override {
|
||||
void visit(AstCMethodHard* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureCleanAndNext(nodep->pinsp());
|
||||
setClean(nodep, true);
|
||||
}
|
||||
virtual void visit(AstWith* nodep) override {
|
||||
void visit(AstWith* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
ensureCleanAndNext(nodep->exprp());
|
||||
setClean(nodep, true);
|
||||
}
|
||||
virtual void visit(AstIntfRef* nodep) override {
|
||||
void visit(AstIntfRef* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
setClean(nodep, true); // generates a string, so not relevant
|
||||
}
|
||||
|
||||
//--------------------
|
||||
// Default: Just iterate
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
void visit(AstNode* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
computeCppWidth(nodep);
|
||||
}
|
||||
|
|
@ -308,7 +309,7 @@ private:
|
|||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CleanVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~CleanVisitor() override = default;
|
||||
~CleanVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -317,5 +318,5 @@ public:
|
|||
void V3Clean::cleanAll(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ CleanVisitor{nodep}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("clean", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("clean", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Convert every WRITE AstVarRef to a READ ref
|
||||
|
||||
|
|
@ -88,7 +90,6 @@ private:
|
|||
AstMTaskBody* m_mtaskBodyp = nullptr; // Current mtask body
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
AstVarScope* getCreateLastClk(AstVarScope* vscp) {
|
||||
if (vscp->user1p()) return static_cast<AstVarScope*>(vscp->user1p());
|
||||
|
|
@ -100,12 +101,12 @@ private:
|
|||
const string newvarname
|
||||
= (string("__Vclklast__") + vscp->scopep()->nameDotless() + "__" + varp->name());
|
||||
AstVar* const newvarp = new AstVar(vscp->fileline(), VVarType::MODULETEMP, newvarname,
|
||||
VFlagLogicPacked(), 1);
|
||||
VFlagLogicPacked{}, 1);
|
||||
newvarp->noReset(true); // Reset by below assign
|
||||
m_modp->addStmtp(newvarp);
|
||||
m_modp->addStmtsp(newvarp);
|
||||
AstVarScope* const newvscp = new AstVarScope(vscp->fileline(), m_scopep, newvarp);
|
||||
vscp->user1p(newvscp);
|
||||
m_scopep->addVarp(newvscp);
|
||||
m_scopep->addVarsp(newvscp);
|
||||
// Add init
|
||||
AstNode* fromp = new AstVarRef(newvarp->fileline(), vscp, VAccess::READ);
|
||||
if (v3Global.opt.xInitialEdge()) fromp = new AstNot(fromp->fileline(), fromp);
|
||||
|
|
@ -202,7 +203,7 @@ private:
|
|||
funcp->slow(slow);
|
||||
funcp->isConst(false);
|
||||
funcp->declPrivate(true);
|
||||
m_topScopep->scopep()->addActivep(funcp);
|
||||
m_topScopep->scopep()->addBlocksp(funcp);
|
||||
return funcp;
|
||||
}
|
||||
void splitCheck(AstCFunc* ofuncp) {
|
||||
|
|
@ -229,7 +230,7 @@ private:
|
|||
funcp->isStatic(false);
|
||||
funcp->isLoose(true);
|
||||
funcp->slow(ofuncp->slow());
|
||||
m_topScopep->scopep()->addActivep(funcp);
|
||||
m_topScopep->scopep()->addBlocksp(funcp);
|
||||
//
|
||||
AstCCall* const callp = new AstCCall{funcp->fileline(), funcp};
|
||||
ofuncp->addStmtsp(callp);
|
||||
|
|
@ -242,7 +243,7 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstTopScope* nodep) override {
|
||||
void visit(AstTopScope* nodep) override {
|
||||
UINFO(4, " TOPSCOPE " << nodep << endl);
|
||||
m_topScopep = nodep;
|
||||
m_scopep = nodep->scopep();
|
||||
|
|
@ -277,7 +278,7 @@ private:
|
|||
m_topScopep = nullptr;
|
||||
m_scopep = nullptr;
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
// UINFO(4, " MOD " << nodep << endl);
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
|
|
@ -285,7 +286,7 @@ private:
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
void visit(AstScope* nodep) override {
|
||||
// UINFO(4, " SCOPE " << nodep << endl);
|
||||
m_scopep = nodep;
|
||||
iterateChildren(nodep);
|
||||
|
|
@ -296,14 +297,14 @@ private:
|
|||
}
|
||||
m_scopep = nullptr;
|
||||
}
|
||||
virtual void visit(AstNodeProcedure* nodep) override {
|
||||
if (AstNode* const stmtsp = nodep->bodysp()) {
|
||||
void visit(AstNodeProcedure* nodep) override {
|
||||
if (AstNode* const stmtsp = nodep->stmtsp()) {
|
||||
stmtsp->unlinkFrBackWithNext();
|
||||
nodep->addNextHere(stmtsp);
|
||||
}
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
}
|
||||
virtual void visit(AstCoverToggle* nodep) override {
|
||||
void visit(AstCoverToggle* nodep) override {
|
||||
// nodep->dumpTree(cout, "ct:");
|
||||
// COVERTOGGLE(INC, ORIG, CHANGE) ->
|
||||
// IF(ORIG ^ CHANGE) { INC; CHANGE = ORIG; }
|
||||
|
|
@ -316,11 +317,11 @@ private:
|
|||
// We could add another IF to detect posedges, and only increment if so.
|
||||
// It's another whole branch though versus a potential memory miss.
|
||||
// We'll go with the miss.
|
||||
newp->addIfsp(new AstAssign(nodep->fileline(), changeWrp, origp->cloneTree(false)));
|
||||
newp->addThensp(new AstAssign(nodep->fileline(), changeWrp, origp->cloneTree(false)));
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
void visit(AstCFunc* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
// Link to global function
|
||||
if (nodep->isFinal()) {
|
||||
|
|
@ -329,7 +330,7 @@ private:
|
|||
m_finalFuncp->addStmtsp(callp);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstSenTree* nodep) override {
|
||||
void visit(AstSenTree* nodep) override {
|
||||
// Delete it later; Actives still pointing to it
|
||||
nodep->unlinkFrBack();
|
||||
pushDeletep(nodep);
|
||||
|
|
@ -343,7 +344,7 @@ private:
|
|||
void addToInitial(AstNode* stmtsp) {
|
||||
m_initFuncp->addStmtsp(stmtsp); // add to top level function
|
||||
}
|
||||
virtual void visit(AstActive* nodep) override {
|
||||
void visit(AstActive* nodep) override {
|
||||
// Careful if adding variables here, ACTIVES can be under other ACTIVES
|
||||
// Need to save and restore any member state in AstUntilStable block
|
||||
if (!m_topScopep || !nodep->stmtsp()) {
|
||||
|
|
@ -367,7 +368,7 @@ private:
|
|||
m_mtaskBodyp->addStmtsp(m_lastIfp);
|
||||
}
|
||||
// Move statements to if
|
||||
m_lastIfp->addIfsp(stmtsp);
|
||||
m_lastIfp->addThensp(stmtsp);
|
||||
} else if (nodep->hasInitial() || nodep->hasSettle()) {
|
||||
nodep->v3fatalSrc("MTask should not include initial/settle logic.");
|
||||
} else {
|
||||
|
|
@ -393,7 +394,7 @@ private:
|
|||
addToEvalLoop(m_lastIfp);
|
||||
}
|
||||
// Move statements to if
|
||||
m_lastIfp->addIfsp(stmtsp);
|
||||
m_lastIfp->addThensp(stmtsp);
|
||||
} else if (nodep->hasInitial()) {
|
||||
// Don't need to: clearLastSen();, as we're adding it to different cfunc
|
||||
// Move statements to function
|
||||
|
|
@ -411,7 +412,7 @@ private:
|
|||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstExecGraph* nodep) override {
|
||||
void visit(AstExecGraph* nodep) override {
|
||||
VL_RESTORER(m_mtaskBodyp);
|
||||
for (m_mtaskBodyp = nodep->mTaskBodiesp(); m_mtaskBodyp;
|
||||
m_mtaskBodyp = VN_AS(m_mtaskBodyp->nextp(), MTaskBody)) {
|
||||
|
|
@ -427,7 +428,7 @@ private:
|
|||
}
|
||||
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
|
|
@ -437,7 +438,7 @@ public:
|
|||
// easily without iterating through the tree.
|
||||
nodep->evalp(m_evalFuncp);
|
||||
}
|
||||
virtual ~ClockVisitor() override = default;
|
||||
~ClockVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -446,5 +447,5 @@ public:
|
|||
void V3Clock::clockAll(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ ClockVisitor{nodep}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("clock", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("clock", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
class CombineVisitor final : VNVisitor {
|
||||
// NODE STATE
|
||||
// AstNodeModule::user1() List of AstCFuncs in this module (via m_cfuncs)
|
||||
|
|
@ -57,7 +59,6 @@ class CombineVisitor final : VNVisitor {
|
|||
VDouble0 m_cfuncsCombined; // Statistic tracking
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
void removeEmptyFunctions(std::list<AstCFunc*>& funcps) {
|
||||
for (funcit_t it = funcps.begin(), nit; it != funcps.end(); it = nit) {
|
||||
|
|
@ -180,32 +181,32 @@ class CombineVisitor final : VNVisitor {
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNetlist* nodep) override {
|
||||
void visit(AstNetlist* nodep) override {
|
||||
// Gather functions and references
|
||||
iterateChildrenConst(nodep);
|
||||
// Combine functions
|
||||
process(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
UASSERT_OBJ(!m_modp, nodep, "Should not nest");
|
||||
m_modp = nodep;
|
||||
iterateChildrenConst(nodep);
|
||||
m_modp = nullptr;
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
void visit(AstCFunc* nodep) override {
|
||||
iterateChildrenConst(nodep);
|
||||
if (nodep->dontCombine()) return;
|
||||
auto& coll = nodep->slow() ? m_cfuncs(m_modp).m_slow : m_cfuncs(m_modp).m_fast;
|
||||
coll.emplace_back(nodep);
|
||||
}
|
||||
virtual void visit(AstCCall* nodep) override {
|
||||
void visit(AstCCall* nodep) override {
|
||||
iterateChildrenConst(nodep);
|
||||
AstCFunc* const funcp = nodep->funcp();
|
||||
if (funcp->dontCombine()) return;
|
||||
m_callSites(funcp).emplace_back(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstAddrOfCFunc* nodep) override {
|
||||
void visit(AstAddrOfCFunc* nodep) override {
|
||||
iterateChildrenConst(nodep);
|
||||
if (nodep->funcp()->dontCombine()) return;
|
||||
// LCOV_EXCL_START
|
||||
|
|
@ -217,7 +218,7 @@ class CombineVisitor final : VNVisitor {
|
|||
}
|
||||
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) override { iterateChildrenConst(nodep); }
|
||||
void visit(AstNode* nodep) override { iterateChildrenConst(nodep); }
|
||||
|
||||
// CONSTRUCTORS
|
||||
explicit CombineVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
|
|
@ -235,5 +236,5 @@ public:
|
|||
void V3Combine::combineAll(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
CombineVisitor::apply(nodep);
|
||||
V3Global::dumpCheckGlobalTree("combine", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("combine", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@
|
|||
#include "V3EmitCBase.h"
|
||||
#include "V3Global.h"
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Common component builders
|
||||
|
||||
|
|
@ -43,7 +45,7 @@ static void makeVlToString(AstClass* nodep) {
|
|||
AstNode* const exprp = new AstCMath{nodep->fileline(), "obj ? obj->to_string() : \"null\"", 0};
|
||||
exprp->dtypeSetString();
|
||||
funcp->addStmtsp(new AstCReturn{nodep->fileline(), exprp});
|
||||
nodep->addStmtp(funcp);
|
||||
nodep->addStmtsp(funcp);
|
||||
}
|
||||
static void makeToString(AstClass* nodep) {
|
||||
AstCFunc* const funcp = new AstCFunc{nodep->fileline(), "to_string", nullptr, "std::string"};
|
||||
|
|
@ -54,7 +56,7 @@ static void makeToString(AstClass* nodep) {
|
|||
= new AstCMath{nodep->fileline(), R"(std::string{"'{"} + to_string_middle() + "}")", 0};
|
||||
exprp->dtypeSetString();
|
||||
funcp->addStmtsp(new AstCReturn{nodep->fileline(), exprp});
|
||||
nodep->addStmtp(funcp);
|
||||
nodep->addStmtsp(funcp);
|
||||
}
|
||||
static void makeToStringMiddle(AstClass* nodep) {
|
||||
AstCFunc* const funcp
|
||||
|
|
@ -96,7 +98,7 @@ static void makeToStringMiddle(AstClass* nodep) {
|
|||
funcp->addStmtsp(new AstCStmt{nodep->fileline(), stmt});
|
||||
}
|
||||
funcp->addStmtsp(new AstCStmt{nodep->fileline(), "return out;\n"});
|
||||
nodep->addStmtp(funcp);
|
||||
nodep->addStmtsp(funcp);
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -117,5 +119,5 @@ void V3Common::commonAll() {
|
|||
makeToStringMiddle(classp);
|
||||
}
|
||||
}
|
||||
V3Global::dumpCheckGlobalTree("common", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("common", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Resolve wildcards in files, modules, ftasks or variables
|
||||
|
||||
|
|
@ -193,11 +195,11 @@ public:
|
|||
const VPragmaType type
|
||||
= m_inlineValue ? VPragmaType::INLINE_MODULE : VPragmaType::NO_INLINE_MODULE;
|
||||
AstNode* const nodep = new AstPragma(modp->fileline(), type);
|
||||
modp->addStmtp(nodep);
|
||||
modp->addStmtsp(nodep);
|
||||
}
|
||||
for (const auto& itr : m_modPragmas) {
|
||||
AstNode* const nodep = new AstPragma{modp->fileline(), itr};
|
||||
modp->addStmtp(nodep);
|
||||
modp->addStmtsp(nodep);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -309,7 +311,7 @@ public:
|
|||
if (lineMatch(lineno, VPragmaType::FULL_CASE)) nodep->fullPragma(true);
|
||||
if (lineMatch(lineno, VPragmaType::PARALLEL_CASE)) nodep->parallelPragma(true);
|
||||
}
|
||||
inline void applyIgnores(FileLine* filelinep) {
|
||||
void applyIgnores(FileLine* filelinep) {
|
||||
// HOT routine, called each parsed token line of this filename
|
||||
if (m_lastIgnore.lineno != filelinep->lineno()) {
|
||||
// UINFO(9, " ApplyIgnores for " << filelinep->ascii() << endl);
|
||||
|
|
|
|||
214
src/V3Const.cpp
214
src/V3Const.cpp
|
|
@ -37,6 +37,8 @@
|
|||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Utilities
|
||||
|
||||
|
|
@ -350,7 +352,6 @@ class ConstBitOpTreeVisitor final : public VNVisitor {
|
|||
std::vector<std::unique_ptr<VarInfo>> m_varInfos; // VarInfo for each variable, [0] is nullptr
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
bool isAndTree() const { return VN_IS(m_rootp, And); }
|
||||
bool isOrTree() const { return VN_IS(m_rootp, Or); }
|
||||
|
|
@ -417,14 +418,12 @@ class ConstBitOpTreeVisitor final : public VNVisitor {
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
CONST_BITOP_SET_FAILED("Hit unexpected op", nodep);
|
||||
}
|
||||
virtual void visit(AstCCast* nodep) override {
|
||||
void visit(AstNode* nodep) override { CONST_BITOP_SET_FAILED("Hit unexpected op", nodep); }
|
||||
void visit(AstCCast* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_leafp) m_leafp->updateBitRange(nodep);
|
||||
}
|
||||
virtual void visit(AstShiftR* nodep) override {
|
||||
void visit(AstShiftR* nodep) override {
|
||||
CONST_BITOP_RETURN_IF(!m_leafp, nodep);
|
||||
AstConst* const constp = VN_CAST(nodep->rhsp(), Const);
|
||||
CONST_BITOP_RETURN_IF(!constp, nodep->rhsp());
|
||||
|
|
@ -434,7 +433,7 @@ class ConstBitOpTreeVisitor final : public VNVisitor {
|
|||
m_leafp->updateBitRange(nodep);
|
||||
m_lsb -= constp->toUInt();
|
||||
}
|
||||
virtual void visit(AstNot* nodep) override {
|
||||
void visit(AstNot* nodep) override {
|
||||
CONST_BITOP_RETURN_IF(nodep->widthMin() != 1, nodep);
|
||||
AstNode* lhsp = nodep->lhsp();
|
||||
AstCCast* const castp = VN_CAST(lhsp, CCast);
|
||||
|
|
@ -449,7 +448,7 @@ class ConstBitOpTreeVisitor final : public VNVisitor {
|
|||
if (!isXorTree()) m_polarity = !m_polarity;
|
||||
if (m_leafp && castp) m_leafp->updateBitRange(castp);
|
||||
}
|
||||
virtual void visit(AstWordSel* nodep) override {
|
||||
void visit(AstWordSel* nodep) override {
|
||||
CONST_BITOP_RETURN_IF(!m_leafp, nodep);
|
||||
AstConst* const constp = VN_CAST(nodep->bitp(), Const);
|
||||
CONST_BITOP_RETURN_IF(!constp, nodep->rhsp());
|
||||
|
|
@ -457,17 +456,17 @@ class ConstBitOpTreeVisitor final : public VNVisitor {
|
|||
m_leafp->wordIdx(constp->toSInt());
|
||||
iterate(nodep->fromp());
|
||||
}
|
||||
virtual void visit(AstVarRef* nodep) override {
|
||||
void visit(AstVarRef* nodep) override {
|
||||
CONST_BITOP_RETURN_IF(!m_leafp, nodep);
|
||||
m_leafp->setLeaf(nodep);
|
||||
m_leafp->polarity(m_polarity);
|
||||
}
|
||||
virtual void visit(AstConst* nodep) override {
|
||||
void visit(AstConst* nodep) override {
|
||||
CONST_BITOP_RETURN_IF(!m_leafp, nodep);
|
||||
m_leafp->setLeaf(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstRedXor* nodep) override {
|
||||
void visit(AstRedXor* nodep) override {
|
||||
Restorer restorer{*this};
|
||||
CONST_BITOP_RETURN_IF(!VN_IS(m_rootp, Xor), nodep);
|
||||
AstNode* lhsp = nodep->lhsp();
|
||||
|
|
@ -514,7 +513,7 @@ class ConstBitOpTreeVisitor final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeBiop* nodep) override {
|
||||
void visit(AstNodeBiop* nodep) override {
|
||||
if (VN_IS(nodep, And) && isConst(nodep->lhsp(), 1)) { // 1 & _
|
||||
// Always reach past a plain making AND
|
||||
Restorer restorer{*this};
|
||||
|
|
@ -895,7 +894,6 @@ private:
|
|||
V3UniqueNames m_concswapNames; // For generating unique temporary variable names
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
bool operandConst(AstNode* nodep) { return VN_IS(nodep, Const); }
|
||||
bool operandAsvConst(const AstNode* nodep) {
|
||||
|
|
@ -1044,20 +1042,19 @@ private:
|
|||
// as high as possible, which is usally the right choice, except for this.
|
||||
AstNodeCond* const condp = VN_CAST(nodep->rhsp(), NodeCond);
|
||||
if (!condp) return false;
|
||||
if (!VN_IS(condp->expr1p(), Const) && !VN_IS(condp->expr2p(), Const)) return false;
|
||||
if (!VN_IS(condp->thenp(), Const) && !VN_IS(condp->elsep(), Const)) return false;
|
||||
AstConst* const maskp = VN_CAST(nodep->lhsp(), Const);
|
||||
if (!maskp) return false;
|
||||
UINFO(4, "AND(CONSTm, CONDcond(c, i, e))->CONDcond(c, AND(m,i), AND(m, e)) " << nodep
|
||||
<< endl);
|
||||
AstNodeCond* const newp = static_cast<AstNodeCond*>(
|
||||
condp->cloneType(condp->condp()->unlinkFrBack(),
|
||||
new AstAnd(nodep->fileline(), maskp->cloneTree(false),
|
||||
condp->expr1p()->unlinkFrBack()),
|
||||
new AstAnd(nodep->fileline(), maskp->cloneTree(false),
|
||||
condp->expr2p()->unlinkFrBack())));
|
||||
AstNodeCond* const newp = static_cast<AstNodeCond*>(condp->cloneType(
|
||||
condp->condp()->unlinkFrBack(),
|
||||
new AstAnd(nodep->fileline(), maskp->cloneTree(false), condp->thenp()->unlinkFrBack()),
|
||||
new AstAnd(nodep->fileline(), maskp->cloneTree(false),
|
||||
condp->elsep()->unlinkFrBack())));
|
||||
newp->dtypeFrom(nodep);
|
||||
newp->expr1p()->dtypeFrom(nodep); // As And might have been to change widths
|
||||
newp->expr2p()->dtypeFrom(nodep);
|
||||
newp->thenp()->dtypeFrom(nodep); // As And might have been to change widths
|
||||
newp->elsep()->dtypeFrom(nodep);
|
||||
nodep->replaceWith(newp);
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
return true;
|
||||
|
|
@ -1445,19 +1442,19 @@ private:
|
|||
}
|
||||
}
|
||||
bool ifSameAssign(const AstNodeIf* nodep) {
|
||||
const AstNodeAssign* const ifp = VN_CAST(nodep->ifsp(), NodeAssign);
|
||||
const AstNodeAssign* const elsep = VN_CAST(nodep->elsesp(), NodeAssign);
|
||||
if (!ifp || ifp->nextp()) return false; // Must be SINGLE statement
|
||||
if (!elsep || elsep->nextp()) return false;
|
||||
if (ifp->type() != elsep->type()) return false; // Can't mix an assigndly and an assign
|
||||
if (!ifp->lhsp()->sameGateTree(elsep->lhsp())) return false;
|
||||
if (!ifp->rhsp()->gateTree()) return false;
|
||||
if (!elsep->rhsp()->gateTree()) return false;
|
||||
const AstNodeAssign* const thensp = VN_CAST(nodep->thensp(), NodeAssign);
|
||||
const AstNodeAssign* const elsesp = VN_CAST(nodep->elsesp(), NodeAssign);
|
||||
if (!thensp || thensp->nextp()) return false; // Must be SINGLE statement
|
||||
if (!elsesp || elsesp->nextp()) return false;
|
||||
if (thensp->type() != elsesp->type()) return false; // Can't mix an assigndly with assign
|
||||
if (!thensp->lhsp()->sameGateTree(elsesp->lhsp())) return false;
|
||||
if (!thensp->rhsp()->gateTree()) return false;
|
||||
if (!elsesp->rhsp()->gateTree()) return false;
|
||||
return true;
|
||||
}
|
||||
bool operandIfIf(const AstNodeIf* nodep) {
|
||||
if (nodep->elsesp()) return false;
|
||||
const AstNodeIf* const lowerIfp = VN_CAST(nodep->ifsp(), NodeIf);
|
||||
const AstNodeIf* const lowerIfp = VN_CAST(nodep->thensp(), NodeIf);
|
||||
if (!lowerIfp || lowerIfp->nextp()) return false;
|
||||
if (nodep->type() != lowerIfp->type()) return false;
|
||||
if (afterComment(lowerIfp->elsesp())) return false;
|
||||
|
|
@ -2079,7 +2076,7 @@ private:
|
|||
AstSel* const sel2p = new AstSel(conp->fileline(), rhs2p, lsb2, msb2 - lsb2 + 1);
|
||||
// Make new assigns of same flavor as old one
|
||||
//*** Not cloneTree; just one node.
|
||||
AstNode* newp = nullptr;
|
||||
AstNodeAssign* newp = nullptr;
|
||||
if (!need_temp) {
|
||||
AstNodeAssign* const asn1ap = VN_AS(nodep->cloneType(lc1p, sel1p), NodeAssign);
|
||||
AstNodeAssign* const asn2ap = VN_AS(nodep->cloneType(lc2p, sel2p), NodeAssign);
|
||||
|
|
@ -2099,8 +2096,8 @@ private:
|
|||
AstVar* const temp2p
|
||||
= new AstVar(sel2p->fileline(), VVarType::BLOCKTEMP,
|
||||
m_concswapNames.get(sel2p), VFlagLogicPacked(), msb2 - lsb2 + 1);
|
||||
m_modp->addStmtp(temp1p);
|
||||
m_modp->addStmtp(temp2p);
|
||||
m_modp->addStmtsp(temp1p);
|
||||
m_modp->addStmtsp(temp2p);
|
||||
AstNodeAssign* const asn1ap
|
||||
= VN_AS(nodep->cloneType(
|
||||
new AstVarRef(sel1p->fileline(), temp1p, VAccess::WRITE), sel1p),
|
||||
|
|
@ -2252,11 +2249,11 @@ private:
|
|||
//----------------------------------------
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNetlist* nodep) override {
|
||||
void visit(AstNetlist* nodep) override {
|
||||
// Iterate modules backwards, in bottom-up order. That's faster
|
||||
iterateChildrenBackwards(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
m_modp = nodep;
|
||||
|
|
@ -2264,7 +2261,7 @@ private:
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
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);
|
||||
|
|
@ -2273,7 +2270,7 @@ private:
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
void visit(AstScope* nodep) override {
|
||||
// No ASSIGNW removals under scope, we've long eliminated INITIALs
|
||||
VL_RESTORER(m_wremove);
|
||||
VL_RESTORER(m_scopep);
|
||||
|
|
@ -2370,17 +2367,17 @@ private:
|
|||
}
|
||||
|
||||
// Special cases
|
||||
virtual void visit(AstConst*) override {} // Already constant
|
||||
void visit(AstConst*) override {} // Already constant
|
||||
|
||||
virtual void visit(AstCell* nodep) override {
|
||||
void visit(AstCell* nodep) override {
|
||||
if (m_params) {
|
||||
iterateAndNextNull(nodep->paramsp());
|
||||
} else {
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstClassOrPackageRef* nodep) override { iterateChildren(nodep); }
|
||||
virtual void visit(AstPin* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstClassOrPackageRef* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstPin* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
void replaceLogEq(AstLogEq* nodep) {
|
||||
// LOGEQ(a,b) => AstLogAnd{AstLogOr{AstLogNot{a},b},AstLogOr{AstLogNot{b},a}}
|
||||
|
|
@ -2562,7 +2559,7 @@ private:
|
|||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstAttrOf* nodep) override {
|
||||
void visit(AstAttrOf* nodep) override {
|
||||
VL_RESTORER(m_attrp);
|
||||
{
|
||||
m_attrp = nodep;
|
||||
|
|
@ -2570,7 +2567,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstArraySel* nodep) override {
|
||||
void visit(AstArraySel* nodep) override {
|
||||
iterateAndNextNull(nodep->bitp());
|
||||
if (VN_IS(nodep->bitp(), Const)
|
||||
&& VN_IS(nodep->fromp(), VarRef)
|
||||
|
|
@ -2596,7 +2593,7 @@ private:
|
|||
}
|
||||
m_selp = nullptr;
|
||||
}
|
||||
virtual void visit(AstNodeVarRef* nodep) override {
|
||||
void visit(AstNodeVarRef* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
UASSERT_OBJ(nodep->varp(), nodep, "Not linked");
|
||||
bool did = false;
|
||||
|
|
@ -2650,7 +2647,7 @@ private:
|
|||
<< nodep->varp()->prettyNameQ());
|
||||
}
|
||||
}
|
||||
virtual void visit(AstEnumItemRef* nodep) override {
|
||||
void visit(AstEnumItemRef* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
UASSERT_OBJ(nodep->itemp(), nodep, "Not linked");
|
||||
bool did = false;
|
||||
|
|
@ -2675,7 +2672,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
// virtual void visit(AstCvtPackString* nodep) override {
|
||||
// void visit(AstCvtPackString* nodep) override {
|
||||
// Not constant propagated (for today) because AstNodeMath::isOpaque is set
|
||||
// Someday if lower is constant, convert to quoted "string".
|
||||
|
||||
|
|
@ -2683,7 +2680,7 @@ private:
|
|||
// Only one if it's not in a list
|
||||
return (!nodep->nextp() && nodep->backp()->nextp() != nodep);
|
||||
}
|
||||
virtual void visit(AstSenItem* nodep) override {
|
||||
void visit(AstSenItem* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_doNConst
|
||||
&& (VN_IS(nodep->sensp(), Const) || VN_IS(nodep->sensp(), EnumItemRef)
|
||||
|
|
@ -2750,7 +2747,7 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
virtual void visit(AstSenTree* nodep) override {
|
||||
void visit(AstSenTree* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_doExpensive) {
|
||||
// cout<<endl; nodep->dumpTree(cout, "ssin: ");
|
||||
|
|
@ -2834,17 +2831,17 @@ private:
|
|||
|
||||
//-----
|
||||
// Zero elimination
|
||||
virtual void visit(AstNodeAssign* nodep) override {
|
||||
void visit(AstNodeAssign* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_doNConst && replaceNodeAssign(nodep)) return;
|
||||
}
|
||||
virtual void visit(AstAssignAlias* nodep) override {
|
||||
void visit(AstAssignAlias* nodep) override {
|
||||
// Don't perform any optimizations, keep the alias around
|
||||
}
|
||||
virtual void visit(AstAssignVarScope* nodep) override {
|
||||
void visit(AstAssignVarScope* nodep) override {
|
||||
// Don't perform any optimizations, the node won't be linked yet
|
||||
}
|
||||
virtual void visit(AstAssignW* nodep) override {
|
||||
void visit(AstAssignW* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_doNConst && replaceNodeAssign(nodep)) return;
|
||||
AstNodeVarRef* const varrefp = VN_CAST(
|
||||
|
|
@ -2853,6 +2850,7 @@ private:
|
|||
if (m_wremove && !m_params && m_doNConst && m_modp && operandConst(nodep->rhsp())
|
||||
&& !VN_AS(nodep->rhsp(), Const)->num().isFourState()
|
||||
&& varrefp // Don't do messes with BITREFs/ARRAYREFs
|
||||
&& !varrefp->varp()->hasStrengthAssignment() // Strengths are resolved in V3Tristate
|
||||
&& !varrefp->varp()->valuep() // Not already constified
|
||||
&& !varrefp->varScopep()) { // Not scoped (or each scope may have different initial
|
||||
// value)
|
||||
|
|
@ -2863,14 +2861,14 @@ private:
|
|||
varrefp->unlinkFrBack();
|
||||
AstInitial* const newinitp = new AstInitial(
|
||||
nodep->fileline(), new AstAssign(nodep->fileline(), varrefp, exprp));
|
||||
m_modp->addStmtp(newinitp);
|
||||
m_modp->addStmtsp(newinitp);
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
// Set the initial value right in the variable so we can constant propagate
|
||||
AstNode* const initvaluep = exprp->cloneTree(false);
|
||||
varrefp->varp()->valuep(initvaluep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstRelease* nodep) override {
|
||||
void visit(AstRelease* nodep) override {
|
||||
if (AstConcat* const concatp = VN_CAST(nodep->lhsp(), Concat)) {
|
||||
FileLine* const flp = nodep->fileline();
|
||||
AstRelease* const newLp = new AstRelease{flp, concatp->lhsp()->unlinkFrBack()};
|
||||
|
|
@ -2883,7 +2881,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeIf* nodep) override {
|
||||
void visit(AstNodeIf* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_doNConst) {
|
||||
if (const AstConst* const constp = VN_CAST(nodep->condp(), Const)) {
|
||||
|
|
@ -2893,7 +2891,7 @@ private:
|
|||
keepp = nodep->elsesp();
|
||||
} else if (!m_doV || constp->isNeqZero()) { // Might be X in Verilog
|
||||
UINFO(4, "IF(!0,{x},{any}) => {x}: " << nodep << endl);
|
||||
keepp = nodep->ifsp();
|
||||
keepp = nodep->thensp();
|
||||
} else {
|
||||
UINFO(4, "IF condition is X, retaining: " << nodep << endl);
|
||||
return;
|
||||
|
|
@ -2905,7 +2903,7 @@ private:
|
|||
nodep->unlinkFrBack();
|
||||
}
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
} else if (!afterComment(nodep->ifsp()) && !afterComment(nodep->elsesp())) {
|
||||
} else if (!afterComment(nodep->thensp()) && !afterComment(nodep->elsesp())) {
|
||||
if (!isTreePureRecurse(nodep->condp())) {
|
||||
// Condition has side effect - leave - perhaps in
|
||||
// future simplify to remove all but side effect terms
|
||||
|
|
@ -2913,27 +2911,27 @@ private:
|
|||
// Empty block, remove it
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
}
|
||||
} else if (!afterComment(nodep->ifsp())) {
|
||||
} else if (!afterComment(nodep->thensp())) {
|
||||
UINFO(4, "IF({x}) nullptr {...} => IF(NOT{x}}: " << nodep << endl);
|
||||
AstNode* const condp = nodep->condp();
|
||||
AstNode* const elsesp = nodep->elsesp();
|
||||
condp->unlinkFrBackWithNext();
|
||||
elsesp->unlinkFrBackWithNext();
|
||||
if (nodep->ifsp()) { // Must have been comment
|
||||
nodep->ifsp()->unlinkFrBackWithNext()->deleteTree();
|
||||
if (nodep->thensp()) { // Must have been comment
|
||||
nodep->thensp()->unlinkFrBackWithNext()->deleteTree();
|
||||
}
|
||||
nodep->condp(new AstLogNot(condp->fileline(),
|
||||
condp)); // LogNot, as C++ optimization also possible
|
||||
nodep->addIfsp(elsesp);
|
||||
nodep->addThensp(elsesp);
|
||||
} else if (((VN_IS(nodep->condp(), Not) && nodep->condp()->width() == 1)
|
||||
|| VN_IS(nodep->condp(), LogNot))
|
||||
&& nodep->ifsp() && nodep->elsesp()) {
|
||||
&& nodep->thensp() && nodep->elsesp()) {
|
||||
UINFO(4, "IF(NOT {x}) => IF(x) swapped if/else" << nodep << endl);
|
||||
AstNode* const condp
|
||||
= VN_AS(nodep->condp(), NodeUniop)->lhsp()->unlinkFrBackWithNext();
|
||||
AstNode* const ifsp = nodep->ifsp()->unlinkFrBackWithNext();
|
||||
AstNode* const thensp = nodep->thensp()->unlinkFrBackWithNext();
|
||||
AstNode* const elsesp = nodep->elsesp()->unlinkFrBackWithNext();
|
||||
AstIf* const ifp = new AstIf(nodep->fileline(), condp, elsesp, ifsp);
|
||||
AstIf* const ifp = new AstIf(nodep->fileline(), condp, elsesp, thensp);
|
||||
ifp->branchPred(nodep->branchPred().invert());
|
||||
nodep->replaceWith(ifp);
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
|
|
@ -2941,25 +2939,25 @@ private:
|
|||
UINFO(
|
||||
4,
|
||||
"IF({a}) ASSIGN({b},{c}) else ASSIGN({b},{d}) => ASSIGN({b}, {a}?{c}:{d})\n");
|
||||
AstNodeAssign* const ifp = VN_AS(nodep->ifsp(), NodeAssign);
|
||||
AstNodeAssign* const elsep = VN_AS(nodep->elsesp(), NodeAssign);
|
||||
ifp->unlinkFrBack();
|
||||
AstNodeAssign* const thensp = VN_AS(nodep->thensp(), NodeAssign);
|
||||
AstNodeAssign* const elsesp = VN_AS(nodep->elsesp(), NodeAssign);
|
||||
thensp->unlinkFrBack();
|
||||
AstNode* const condp = nodep->condp()->unlinkFrBack();
|
||||
AstNode* const truep = ifp->rhsp()->unlinkFrBack();
|
||||
AstNode* const falsep = elsep->rhsp()->unlinkFrBack();
|
||||
ifp->rhsp(new AstCond(truep->fileline(), condp, truep, falsep));
|
||||
nodep->replaceWith(ifp);
|
||||
AstNode* const truep = thensp->rhsp()->unlinkFrBack();
|
||||
AstNode* const falsep = elsesp->rhsp()->unlinkFrBack();
|
||||
thensp->rhsp(new AstCond(truep->fileline(), condp, truep, falsep));
|
||||
nodep->replaceWith(thensp);
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
} else if (false // Disabled, as vpm assertions are faster
|
||||
// without due to short-circuiting
|
||||
&& operandIfIf(nodep)) {
|
||||
UINFO(9, "IF({a}) IF({b}) => IF({a} && {b})" << endl);
|
||||
AstNodeIf* const lowerIfp = VN_AS(nodep->ifsp(), NodeIf);
|
||||
AstNodeIf* const lowerIfp = VN_AS(nodep->thensp(), NodeIf);
|
||||
AstNode* const condp = nodep->condp()->unlinkFrBack();
|
||||
AstNode* const lowerIfsp = lowerIfp->ifsp()->unlinkFrBackWithNext();
|
||||
AstNode* const lowerThensp = lowerIfp->thensp()->unlinkFrBackWithNext();
|
||||
AstNode* const lowerCondp = lowerIfp->condp()->unlinkFrBackWithNext();
|
||||
nodep->condp(new AstLogAnd(lowerIfp->fileline(), condp, lowerCondp));
|
||||
lowerIfp->replaceWith(lowerIfsp);
|
||||
lowerIfp->replaceWith(lowerThensp);
|
||||
VL_DO_DANGLING(lowerIfp->deleteTree(), lowerIfp);
|
||||
} else if (operandBoolShift(nodep->condp())) {
|
||||
replaceBoolShift(nodep->condp());
|
||||
|
|
@ -2967,7 +2965,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstDisplay* nodep) override {
|
||||
void visit(AstDisplay* nodep) override {
|
||||
// DISPLAY(SFORMAT(text1)),DISPLAY(SFORMAT(text2)) -> DISPLAY(SFORMAT(text1+text2))
|
||||
iterateChildren(nodep);
|
||||
if (stmtDisplayDisplay(nodep)) return;
|
||||
|
|
@ -3016,12 +3014,14 @@ private:
|
|||
pformatp->text(pformatp->text() + nformatp->text());
|
||||
if (!prevp->addNewline() && nodep->addNewline()) pformatp->text(pformatp->text() + "\n");
|
||||
if (nformatp->exprsp()) pformatp->addExprsp(nformatp->exprsp()->unlinkFrBackWithNext());
|
||||
if (nformatp->scopeNamep())
|
||||
pformatp->scopeNamep(nformatp->scopeNamep()->unlinkFrBackWithNext());
|
||||
if (AstScopeName* const scopeNamep = nformatp->scopeNamep()) {
|
||||
scopeNamep->unlinkFrBackWithNext();
|
||||
pformatp->scopeNamep(scopeNamep);
|
||||
}
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
return true;
|
||||
}
|
||||
virtual void visit(AstSFormatF* nodep) override {
|
||||
void visit(AstSFormatF* nodep) override {
|
||||
// Substitute constants into displays. The main point of this is to
|
||||
// simplify assertion methodologies which call functions with display's.
|
||||
// This eliminates a pile of wide temps, and makes the C a whole lot more readable.
|
||||
|
|
@ -3088,17 +3088,17 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstFuncRef* nodep) override {
|
||||
void visit(AstFuncRef* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_params) { // Only parameters force us to do constant function call propagation
|
||||
replaceWithSimulation(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstArg* nodep) override {
|
||||
void visit(AstArg* nodep) override {
|
||||
// replaceWithSimulation on the Arg's parent FuncRef replaces these
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstWhile* nodep) override {
|
||||
void visit(AstWhile* nodep) override {
|
||||
const bool oldHasJumpDelay = m_hasJumpDelay;
|
||||
m_hasJumpDelay = false;
|
||||
{ iterateChildren(nodep); }
|
||||
|
|
@ -3124,22 +3124,22 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstInitArray* nodep) override { iterateChildren(nodep); }
|
||||
virtual void visit(AstInitItem* nodep) override { iterateChildren(nodep); }
|
||||
virtual void visit(AstUnbounded* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstInitArray* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstInitItem* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstUnbounded* nodep) override { iterateChildren(nodep); }
|
||||
// These are converted by V3Param. Don't constify as we don't want the
|
||||
// from() VARREF to disappear, if any.
|
||||
// If output of a presel didn't get consted, chances are V3Param didn't visit properly
|
||||
virtual void visit(AstNodePreSel*) override {}
|
||||
void visit(AstNodePreSel*) override {}
|
||||
|
||||
// Ignored, can eliminate early
|
||||
virtual void visit(AstSysIgnore* nodep) override {
|
||||
void visit(AstSysIgnore* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_doNConst) VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
}
|
||||
|
||||
// Simplify
|
||||
virtual void visit(AstBasicDType* nodep) override {
|
||||
void visit(AstBasicDType* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
nodep->cvtRangeConst();
|
||||
}
|
||||
|
|
@ -3147,11 +3147,11 @@ private:
|
|||
//-----
|
||||
// Jump elimination
|
||||
|
||||
virtual void visit(AstDelay* nodep) override {
|
||||
void visit(AstDelay* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
m_hasJumpDelay = true;
|
||||
}
|
||||
virtual void visit(AstJumpGo* nodep) override {
|
||||
void visit(AstJumpGo* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
// Jump to label where label immediately follows label is not useful
|
||||
if (nodep->labelp() == VN_CAST(nodep->nextp(), JumpLabel)) {
|
||||
|
|
@ -3182,7 +3182,7 @@ private:
|
|||
m_hasJumpDelay = true;
|
||||
}
|
||||
|
||||
virtual void visit(AstJumpBlock* nodep) override {
|
||||
void visit(AstJumpBlock* nodep) override {
|
||||
// Because JumpLabels disable many optimizations,
|
||||
// remove JumpLabels that are not pointed to by any AstJumpGos
|
||||
// Note this assumes all AstJumpGos are underneath the given label; V3Broken asserts this
|
||||
|
|
@ -3301,19 +3301,19 @@ private:
|
|||
TREEOPC("AstAnd {$lhsp.isOne, matchRedundantClean(nodep)}", "DONE") // 1 & (a == b) -> (IData)(a == b)
|
||||
// Trinary ops
|
||||
// Note V3Case::Sel requires Cond to always be conditionally executed in C to prevent core dump!
|
||||
TREEOP ("AstNodeCond{$condp.isZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr2p)");
|
||||
TREEOP ("AstNodeCond{$condp.isNeqZero, $expr1p, $expr2p}", "replaceWChild(nodep,$expr1p)");
|
||||
TREEOPA("AstNodeCond{$condp.isZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr2p)");
|
||||
TREEOPA("AstNodeCond{$condp.isNeqZero, $expr1p.castConst, $expr2p.castConst}", "replaceWChild(nodep,$expr1p)");
|
||||
TREEOP ("AstNodeCond{$condp, operandsSame($expr1p,,$expr2p)}","replaceWChild(nodep,$expr1p)");
|
||||
TREEOP ("AstNodeCond{$condp.isZero, $thenp, $elsep}", "replaceWChild(nodep,$elsep)");
|
||||
TREEOP ("AstNodeCond{$condp.isNeqZero, $thenp, $elsep}", "replaceWChild(nodep,$thenp)");
|
||||
TREEOPA("AstNodeCond{$condp.isZero, $thenp.castConst, $elsep.castConst}", "replaceWChild(nodep,$elsep)");
|
||||
TREEOPA("AstNodeCond{$condp.isNeqZero, $thenp.castConst, $elsep.castConst}", "replaceWChild(nodep,$thenp)");
|
||||
TREEOP ("AstNodeCond{$condp, operandsSame($thenp,,$elsep)}","replaceWChild(nodep,$thenp)");
|
||||
// This visit function here must allow for short-circuiting.
|
||||
TREEOPS("AstCond {$lhsp.isZero}", "replaceWIteratedThs(nodep)");
|
||||
TREEOPS("AstCond {$lhsp.isNeqZero}", "replaceWIteratedRhs(nodep)");
|
||||
TREEOP ("AstCond{$condp.castNot, $expr1p, $expr2p}", "AstCond{$condp->op1p(), $expr2p, $expr1p}");
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isAllOnes, $expr2p}", "AstLogOr {$condp, $expr2p}"); // a?1:b == a||b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isZero}", "AstLogAnd{$condp, $expr1p}"); // a?b:0 == a&&b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p, $expr2p.isAllOnes}", "AstLogOr {AstNot{$condp}, $expr1p}"); // a?b:1 == ~a||b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $expr1p.width1, $expr1p.isZero, $expr2p}", "AstLogAnd{AstNot{$condp}, $expr2p}"); // a?0:b == ~a&&b
|
||||
TREEOP ("AstCond{$condp.castNot, $thenp, $elsep}", "AstCond{$condp->op1p(), $elsep, $thenp}");
|
||||
TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp.isAllOnes, $elsep}", "AstLogOr {$condp, $elsep}"); // a?1:b == a||b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp, $elsep.isZero}", "AstLogAnd{$condp, $thenp}"); // a?b:0 == a&&b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp, $elsep.isAllOnes}", "AstLogOr {AstNot{$condp}, $thenp}"); // a?b:1 == ~a||b
|
||||
TREEOP ("AstNodeCond{$condp.width1, $thenp.width1, $thenp.isZero, $elsep}", "AstLogAnd{AstNot{$condp}, $elsep}"); // a?0:b == ~a&&b
|
||||
TREEOP ("AstNodeCond{!$condp.width1, operandBoolShift(nodep->condp())}", "replaceBoolShift(nodep->condp())");
|
||||
// Prefer constants on left, since that often needs a shift, it lets
|
||||
// constant red remove the shift
|
||||
|
|
@ -3536,7 +3536,7 @@ private:
|
|||
// Note we can't convert EqCase/NeqCase to Eq/Neq here because that would break 3'b1x1==3'b101
|
||||
|
||||
//-----
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
void visit(AstNode* nodep) override {
|
||||
// Default: Just iterate
|
||||
if (m_required) {
|
||||
if (VN_IS(nodep, NodeDType) || VN_IS(nodep, Range) || VN_IS(nodep, SliceSel)) {
|
||||
|
|
@ -3583,7 +3583,7 @@ public:
|
|||
}
|
||||
// clang-format on
|
||||
}
|
||||
virtual ~ConstVisitor() override {
|
||||
~ConstVisitor() override {
|
||||
if (m_doCpp) {
|
||||
if (m_globalPass) {
|
||||
V3Stats::addStat("Optimizations, Const bit op reduction", m_statBitOpReduction);
|
||||
|
|
@ -3664,7 +3664,7 @@ void V3Const::constifyAllLint(AstNetlist* nodep) {
|
|||
ConstVisitor visitor{ConstVisitor::PROC_V_WARN, /* globalPass: */ true};
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("const", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("const", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
||||
void V3Const::constifyCpp(AstNetlist* nodep) {
|
||||
|
|
@ -3673,7 +3673,7 @@ void V3Const::constifyCpp(AstNetlist* nodep) {
|
|||
ConstVisitor visitor{ConstVisitor::PROC_CPP, /* globalPass: */ true};
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("const_cpp", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("const_cpp", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
||||
AstNode* V3Const::constifyEdit(AstNode* nodep) {
|
||||
|
|
@ -3697,7 +3697,7 @@ void V3Const::constifyAllLive(AstNetlist* nodep) {
|
|||
ConstVisitor visitor{ConstVisitor::PROC_LIVE, /* globalPass: */ true};
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("const", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("const", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
||||
void V3Const::constifyAll(AstNetlist* nodep) {
|
||||
|
|
@ -3707,7 +3707,7 @@ void V3Const::constifyAll(AstNetlist* nodep) {
|
|||
ConstVisitor visitor{ConstVisitor::PROC_V_EXPENSIVE, /* globalPass: */ true};
|
||||
(void)visitor.mainAcceptEdit(nodep);
|
||||
} // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("const", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("const", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
||||
AstNode* V3Const::constifyExpensiveEdit(AstNode* nodep) {
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@
|
|||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Coverage state, as a visitor of each AstNode
|
||||
|
||||
|
|
@ -86,7 +88,6 @@ private:
|
|||
m_handleLines; // All line numbers for a given m_stateHandle
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
const char* varIgnoreToggle(AstVar* nodep) {
|
||||
// Return true if this shouldn't be traced
|
||||
|
|
@ -119,7 +120,7 @@ private:
|
|||
|
||||
AstCoverDecl* const declp = new AstCoverDecl(fl, page, comment, linescov, offset);
|
||||
declp->hier(hier);
|
||||
m_modp->addStmtp(declp);
|
||||
m_modp->addStmtsp(declp);
|
||||
UINFO(9, "new " << declp << endl);
|
||||
|
||||
AstCoverInc* const incp = new AstCoverInc(fl, declp);
|
||||
|
|
@ -128,13 +129,13 @@ private:
|
|||
incp->findUInt32DType());
|
||||
varp->trace(true);
|
||||
varp->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true);
|
||||
m_modp->addStmtp(varp);
|
||||
m_modp->addStmtsp(varp);
|
||||
UINFO(5, "New coverage trace: " << varp << endl);
|
||||
AstAssign* const assp = new AstAssign(
|
||||
incp->fileline(), new AstVarRef(incp->fileline(), varp, VAccess::WRITE),
|
||||
new AstAdd(incp->fileline(), new AstVarRef(incp->fileline(), varp, VAccess::READ),
|
||||
new AstConst(incp->fileline(), AstConst::WidthedValue(), 32, 1)));
|
||||
incp->addNext(assp);
|
||||
AstNode::addNext<AstNode, AstNode>(incp, assp);
|
||||
}
|
||||
return incp;
|
||||
}
|
||||
|
|
@ -209,7 +210,7 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS - BOTH
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
const AstNodeModule* const origModp = m_modp;
|
||||
VL_RESTORER(m_modp);
|
||||
VL_RESTORER(m_state);
|
||||
|
|
@ -227,9 +228,9 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeProcedure* nodep) override { iterateProcedure(nodep); }
|
||||
virtual void visit(AstWhile* nodep) override { iterateProcedure(nodep); }
|
||||
virtual void visit(AstNodeFTask* nodep) override {
|
||||
void visit(AstNodeProcedure* nodep) override { iterateProcedure(nodep); }
|
||||
void visit(AstWhile* nodep) override { iterateProcedure(nodep); }
|
||||
void visit(AstNodeFTask* nodep) override {
|
||||
if (!nodep->dpiImport()) iterateProcedure(nodep);
|
||||
}
|
||||
void iterateProcedure(AstNode* nodep) {
|
||||
|
|
@ -245,11 +246,11 @@ private:
|
|||
= newCoverInc(nodep->fileline(), "", "v_line", "block",
|
||||
linesCov(m_state, nodep), 0, traceNameForLine(nodep, "block"));
|
||||
if (AstNodeProcedure* const itemp = VN_CAST(nodep, NodeProcedure)) {
|
||||
itemp->addStmtp(newp);
|
||||
itemp->addStmtsp(newp);
|
||||
} else if (AstNodeFTask* const itemp = VN_CAST(nodep, NodeFTask)) {
|
||||
itemp->addStmtsp(newp);
|
||||
} else if (AstWhile* const itemp = VN_CAST(nodep, While)) {
|
||||
itemp->addBodysp(newp);
|
||||
itemp->addStmtsp(newp);
|
||||
} else {
|
||||
nodep->v3fatalSrc("Bad node type");
|
||||
}
|
||||
|
|
@ -258,7 +259,7 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS - TOGGLE COVERAGE
|
||||
virtual void visit(AstVar* nodep) override {
|
||||
void visit(AstVar* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_modp && !m_inToggleOff && !m_state.m_inModOff && nodep->fileline()->coverageOn()
|
||||
&& v3Global.opt.coverageToggle()) {
|
||||
|
|
@ -283,7 +284,7 @@ private:
|
|||
AstVar* const chgVarp
|
||||
= new AstVar(nodep->fileline(), VVarType::MODULETEMP, newvarname, nodep);
|
||||
chgVarp->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true);
|
||||
m_modp->addStmtp(chgVarp);
|
||||
m_modp->addStmtsp(chgVarp);
|
||||
|
||||
// Create bucket for each dimension * bit.
|
||||
// This is necessarily an O(n^2) expansion, which is why
|
||||
|
|
@ -304,7 +305,7 @@ private:
|
|||
newCoverInc(varp->fileline(), "", "v_toggle", varp->name() + above.m_comment, "", 0,
|
||||
""),
|
||||
above.m_varRefp->cloneTree(true), above.m_chgRefp->cloneTree(true));
|
||||
m_modp->addStmtp(newp);
|
||||
m_modp->addStmtsp(newp);
|
||||
}
|
||||
|
||||
void toggleVarRecurse(AstNodeDType* dtypep, int depth, // per-iteration
|
||||
|
|
@ -383,12 +384,12 @@ private:
|
|||
|
||||
// VISITORS - LINE COVERAGE
|
||||
// Note not AstNodeIf; other types don't get covered
|
||||
virtual void visit(AstIf* nodep) override {
|
||||
void visit(AstIf* nodep) override {
|
||||
UINFO(4, " IF: " << nodep << endl);
|
||||
if (m_state.m_on) {
|
||||
// An else-if. When we iterate the if, use "elsif" marking
|
||||
const bool elsif
|
||||
= nodep->ifsp() && VN_IS(nodep->elsesp(), If) && !nodep->elsesp()->nextp();
|
||||
= nodep->thensp() && VN_IS(nodep->elsesp(), If) && !nodep->elsesp()->nextp();
|
||||
if (elsif) VN_AS(nodep->elsesp(), If)->user1(true);
|
||||
const bool first_elsif = !nodep->user1() && elsif;
|
||||
const bool cont_elsif = nodep->user1() && elsif;
|
||||
|
|
@ -403,7 +404,7 @@ private:
|
|||
CheckState elseState;
|
||||
{
|
||||
createHandle(nodep);
|
||||
iterateAndNextNull(nodep->ifsp());
|
||||
iterateAndNextNull(nodep->thensp());
|
||||
lineTrack(nodep);
|
||||
ifState = m_state;
|
||||
}
|
||||
|
|
@ -422,9 +423,9 @@ private:
|
|||
// Normal if. Linecov shows what's inside the if (not condition that is
|
||||
// always executed)
|
||||
UINFO(4, " COVER-branch: " << nodep << endl);
|
||||
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_branch", "if",
|
||||
linesCov(ifState, nodep), 0,
|
||||
traceNameForLine(nodep, "if")));
|
||||
nodep->addThensp(newCoverInc(nodep->fileline(), "", "v_branch", "if",
|
||||
linesCov(ifState, nodep), 0,
|
||||
traceNameForLine(nodep, "if")));
|
||||
// The else has a column offset of 1 to uniquify it relative to the if
|
||||
// As "if" and "else" are more than one character wide, this won't overlap
|
||||
// another token
|
||||
|
|
@ -436,18 +437,18 @@ private:
|
|||
else if (first_elsif || cont_elsif) {
|
||||
UINFO(4, " COVER-elsif: " << nodep << endl);
|
||||
if (ifState.lineCoverageOn(nodep)) {
|
||||
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "elsif",
|
||||
linesCov(ifState, nodep), 0,
|
||||
traceNameForLine(nodep, "elsif")));
|
||||
nodep->addThensp(newCoverInc(nodep->fileline(), "", "v_line", "elsif",
|
||||
linesCov(ifState, nodep), 0,
|
||||
traceNameForLine(nodep, "elsif")));
|
||||
}
|
||||
// and we don't insert the else as the child if-else will do so
|
||||
} else {
|
||||
// Cover as separate blocks (not a branch as is not two-legged)
|
||||
if (ifState.lineCoverageOn(nodep)) {
|
||||
UINFO(4, " COVER-half-if: " << nodep << endl);
|
||||
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "if",
|
||||
linesCov(ifState, nodep), 0,
|
||||
traceNameForLine(nodep, "if")));
|
||||
nodep->addThensp(newCoverInc(nodep->fileline(), "", "v_line", "if",
|
||||
linesCov(ifState, nodep), 0,
|
||||
traceNameForLine(nodep, "if")));
|
||||
}
|
||||
if (elseState.lineCoverageOn(nodep)) {
|
||||
UINFO(4, " COVER-half-el: " << nodep << endl);
|
||||
|
|
@ -460,7 +461,7 @@ private:
|
|||
}
|
||||
UINFO(9, " done HANDLE " << m_state.m_handle << " for " << nodep << endl);
|
||||
}
|
||||
virtual void visit(AstCaseItem* nodep) override {
|
||||
void visit(AstCaseItem* nodep) override {
|
||||
// We don't add an explicit "default" coverage if not provided,
|
||||
// as we already have a warning when there is no default.
|
||||
UINFO(4, " CASEI: " << nodep << endl);
|
||||
|
|
@ -468,38 +469,38 @@ private:
|
|||
VL_RESTORER(m_state);
|
||||
{
|
||||
createHandle(nodep);
|
||||
iterateAndNextNull(nodep->bodysp());
|
||||
iterateAndNextNull(nodep->stmtsp());
|
||||
if (m_state.lineCoverageOn(nodep)) { // if the case body didn't disable it
|
||||
lineTrack(nodep);
|
||||
UINFO(4, " COVER: " << nodep << endl);
|
||||
nodep->addBodysp(newCoverInc(nodep->fileline(), "", "v_line", "case",
|
||||
nodep->addStmtsp(newCoverInc(nodep->fileline(), "", "v_line", "case",
|
||||
linesCov(m_state, nodep), 0,
|
||||
traceNameForLine(nodep, "case")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCover* nodep) override {
|
||||
void visit(AstCover* nodep) override {
|
||||
UINFO(4, " COVER: " << nodep << endl);
|
||||
VL_RESTORER(m_state);
|
||||
{
|
||||
m_state.m_on = true; // Always do cover blocks, even if there's a $stop
|
||||
createHandle(nodep);
|
||||
iterateChildren(nodep);
|
||||
if (!nodep->coverincp() && v3Global.opt.coverageUser()) {
|
||||
if (!nodep->coverincsp() && v3Global.opt.coverageUser()) {
|
||||
// Note the name may be overridden by V3Assert processing
|
||||
lineTrack(nodep);
|
||||
nodep->coverincp(newCoverInc(nodep->fileline(), m_beginHier, "v_user", "cover",
|
||||
linesCov(m_state, nodep), 0,
|
||||
m_beginHier + "_vlCoverageUserTrace"));
|
||||
nodep->addCoverincsp(newCoverInc(nodep->fileline(), m_beginHier, "v_user", "cover",
|
||||
linesCov(m_state, nodep), 0,
|
||||
m_beginHier + "_vlCoverageUserTrace"));
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstStop* nodep) override {
|
||||
void visit(AstStop* nodep) override {
|
||||
UINFO(4, " STOP: " << nodep << endl);
|
||||
m_state.m_on = false;
|
||||
}
|
||||
virtual void visit(AstPragma* nodep) override {
|
||||
void visit(AstPragma* nodep) override {
|
||||
if (nodep->pragType() == VPragmaType::COVERAGE_BLOCK_OFF) {
|
||||
// Skip all NEXT nodes under this block, and skip this if/case branch
|
||||
UINFO(4, " OFF: h" << m_state.m_handle << " " << nodep << endl);
|
||||
|
|
@ -510,7 +511,7 @@ private:
|
|||
lineTrack(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstBegin* nodep) override {
|
||||
void visit(AstBegin* nodep) override {
|
||||
// Record the hierarchy of any named begins, so we can apply to user
|
||||
// coverage points. This is because there may be cov points inside
|
||||
// generate blocks; each point should get separate consideration.
|
||||
|
|
@ -529,7 +530,7 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS - BOTH
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
void visit(AstNode* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
lineTrack(nodep);
|
||||
}
|
||||
|
|
@ -537,7 +538,7 @@ private:
|
|||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CoverageVisitor(AstNetlist* rootp) { iterateChildren(rootp); }
|
||||
virtual ~CoverageVisitor() override = default;
|
||||
~CoverageVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -546,5 +547,5 @@ public:
|
|||
void V3Coverage::coverage(AstNetlist* rootp) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ CoverageVisitor{rootp}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("coverage", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("coverage", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
#include <vector>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// CoverageJoin state, as a visitor of each AstNode
|
||||
|
||||
|
|
@ -42,7 +44,6 @@ private:
|
|||
VDouble0 m_statToggleJoins; // Statistic tracking
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
void detectDuplicates() {
|
||||
UINFO(9, "Finding duplicates\n");
|
||||
|
|
@ -88,24 +89,24 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNetlist* nodep) override {
|
||||
void visit(AstNetlist* nodep) override {
|
||||
// Find all Coverage's
|
||||
iterateChildren(nodep);
|
||||
// Simplify
|
||||
detectDuplicates();
|
||||
}
|
||||
virtual void visit(AstCoverToggle* nodep) override {
|
||||
void visit(AstCoverToggle* nodep) override {
|
||||
m_toggleps.push_back(nodep);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
//--------------------
|
||||
virtual void visit(AstNodeMath*) override {} // Accelerate
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNodeMath*) override {} // Accelerate
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit CoverageJoinVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~CoverageJoinVisitor() override {
|
||||
~CoverageJoinVisitor() override {
|
||||
V3Stats::addStat("Coverage, Toggle points joined", m_statToggleJoins);
|
||||
}
|
||||
};
|
||||
|
|
@ -116,5 +117,5 @@ public:
|
|||
void V3CoverageJoin::coverageJoin(AstNetlist* rootp) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ CoverageJoinVisitor{rootp}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("coveragejoin", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("coveragejoin", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@
|
|||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Dead state, as a visitor of each AstNode
|
||||
|
||||
|
|
@ -78,7 +80,6 @@ private:
|
|||
bool m_sideEffect = false; // Side effects discovered in assign RHS
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
void checkAll(AstNode* nodep) {
|
||||
if (nodep != nodep->dtypep()) { // NodeDTypes reference themselves
|
||||
|
|
@ -102,7 +103,7 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
if (m_modp) m_modp->user1Inc(); // e.g. Class under Package
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
|
|
@ -120,12 +121,12 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
void visit(AstCFunc* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
if (nodep->scopep()) nodep->scopep()->user1Inc();
|
||||
}
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
void visit(AstScope* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
if (nodep->aboveScopep()) nodep->aboveScopep()->user1Inc();
|
||||
|
|
@ -136,14 +137,14 @@ private:
|
|||
m_scopesp.push_back(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCell* nodep) override {
|
||||
void visit(AstCell* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
m_cellsp.push_back(nodep);
|
||||
nodep->modp()->user1Inc();
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeVarRef* nodep) override {
|
||||
void visit(AstNodeVarRef* nodep) override {
|
||||
// Note NodeAssign skips calling this in some cases
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
|
|
@ -155,7 +156,7 @@ private:
|
|||
if (nodep->varp()) nodep->varp()->user1Inc();
|
||||
if (nodep->classOrPackagep()) nodep->classOrPackagep()->user1Inc();
|
||||
}
|
||||
virtual void visit(AstNodeFTaskRef* nodep) override {
|
||||
void visit(AstNodeFTaskRef* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
if (nodep->classOrPackagep()) {
|
||||
|
|
@ -166,11 +167,11 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstMethodCall* nodep) override {
|
||||
void visit(AstMethodCall* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
}
|
||||
virtual void visit(AstRefDType* nodep) override {
|
||||
void visit(AstRefDType* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkDType(nodep);
|
||||
checkAll(nodep);
|
||||
|
|
@ -184,7 +185,7 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstClassRefDType* nodep) override {
|
||||
void visit(AstClassRefDType* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkDType(nodep);
|
||||
checkAll(nodep);
|
||||
|
|
@ -197,12 +198,12 @@ private:
|
|||
}
|
||||
if (nodep->classp()) nodep->classp()->user1Inc();
|
||||
}
|
||||
virtual void visit(AstNodeDType* nodep) override {
|
||||
void visit(AstNodeDType* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkDType(nodep);
|
||||
checkAll(nodep);
|
||||
}
|
||||
virtual void visit(AstEnumItemRef* nodep) override {
|
||||
void visit(AstEnumItemRef* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
if (nodep->classOrPackagep()) {
|
||||
|
|
@ -214,13 +215,13 @@ private:
|
|||
}
|
||||
checkAll(nodep);
|
||||
}
|
||||
virtual void visit(AstMemberSel* nodep) override {
|
||||
void visit(AstMemberSel* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (nodep->varp()) nodep->varp()->user1Inc();
|
||||
if (nodep->fromp()->dtypep()) nodep->fromp()->dtypep()->user1Inc(); // classref
|
||||
checkAll(nodep);
|
||||
}
|
||||
virtual void visit(AstModport* nodep) override {
|
||||
void visit(AstModport* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_elimCells) {
|
||||
if (!nodep->varsp()) {
|
||||
|
|
@ -230,14 +231,14 @@ private:
|
|||
}
|
||||
checkAll(nodep);
|
||||
}
|
||||
virtual void visit(AstSelLoopVars* nodep) override {
|
||||
void visit(AstSelLoopVars* nodep) override {
|
||||
// Var under a SelLoopVars means we haven't called V3Width to remove them yet
|
||||
VL_RESTORER(m_selloopvarsp);
|
||||
m_selloopvarsp = nodep;
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
}
|
||||
virtual void visit(AstTypedef* nodep) override {
|
||||
void visit(AstTypedef* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (m_elimCells && !nodep->attrPublic()) {
|
||||
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
||||
|
|
@ -248,20 +249,20 @@ private:
|
|||
// Normal modules may disappear, e.g. if they are parameterized then removed
|
||||
if (nodep->attrPublic() && m_modp && VN_IS(m_modp, Package)) m_modp->user1Inc();
|
||||
}
|
||||
virtual void visit(AstVarScope* nodep) override {
|
||||
void visit(AstVarScope* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
if (nodep->scopep()) nodep->scopep()->user1Inc();
|
||||
if (mightElimVar(nodep->varp())) m_vscsp.push_back(nodep);
|
||||
}
|
||||
virtual void visit(AstVar* nodep) override {
|
||||
void visit(AstVar* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
if (nodep->isSigPublic() && m_modp && VN_IS(m_modp, Package)) m_modp->user1Inc();
|
||||
if (m_selloopvarsp) nodep->user1Inc();
|
||||
if (mightElimVar(nodep)) m_varsp.push_back(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeAssign* nodep) override {
|
||||
void visit(AstNodeAssign* nodep) override {
|
||||
// See if simple assignments to variables may be eliminated because
|
||||
// that variable is never used.
|
||||
// Similar code in V3Life
|
||||
|
|
@ -284,7 +285,7 @@ private:
|
|||
}
|
||||
|
||||
//-----
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
void visit(AstNode* nodep) override {
|
||||
if (nodep->isOutputter()) m_sideEffect = true;
|
||||
iterateChildren(nodep);
|
||||
checkAll(nodep);
|
||||
|
|
@ -446,7 +447,7 @@ public:
|
|||
// We may have removed some datatypes, cleanup
|
||||
nodep->typeTablep()->repairCache();
|
||||
}
|
||||
virtual ~DeadVisitor() override = default;
|
||||
~DeadVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -455,30 +456,29 @@ public:
|
|||
void V3Dead::deadifyModules(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ DeadVisitor{nodep, false, false, false, false}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("deadModules", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
V3Global::dumpCheckGlobalTree("deadModules", 0, dumpTree() >= 6);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyDTypes(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ DeadVisitor{nodep, false, true, false, false}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("deadDtypes", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("deadDtypes", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyDTypesScoped(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ DeadVisitor{nodep, false, true, true, false}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("deadDtypesScoped", 0,
|
||||
v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("deadDtypesScoped", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyAll(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ DeadVisitor{nodep, true, true, false, true}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("deadAll", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("deadAll", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
||||
void V3Dead::deadifyAllScoped(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ DeadVisitor{nodep, true, true, true, true}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("deadAllScoped", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("deadAllScoped", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@
|
|||
#include <deque>
|
||||
#include <map>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Delayed state, as a visitor of each AstNode
|
||||
|
||||
|
|
@ -102,7 +104,6 @@ private:
|
|||
std::unordered_map<const AstVarScope*, int> m_scopeVecMap; // Next var number for each scope
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
void markVarUsage(AstNodeVarRef* nodep, bool blocking) {
|
||||
// Ignore if warning is disabled on this reference (used by V3Force).
|
||||
|
|
@ -153,13 +154,13 @@ private:
|
|||
varp = new AstVar(oldvarscp->fileline(), VVarType::BLOCKTEMP, name,
|
||||
VFlagBitPacked(), width);
|
||||
}
|
||||
addmodp->addStmtp(varp);
|
||||
addmodp->addStmtsp(varp);
|
||||
m_modVarMap.emplace(std::make_pair(addmodp, name), varp);
|
||||
}
|
||||
|
||||
AstVarScope* const varscp
|
||||
= new AstVarScope(oldvarscp->fileline(), oldvarscp->scopep(), varp);
|
||||
oldvarscp->scopep()->addVarp(varscp);
|
||||
oldvarscp->scopep()->addVarsp(varscp);
|
||||
return varscp;
|
||||
}
|
||||
|
||||
|
|
@ -356,33 +357,33 @@ private:
|
|||
postLogicp = new AstIf(nodep->fileline(),
|
||||
new AstVarRef(nodep->fileline(), setvscp, VAccess::READ));
|
||||
UINFO(9, " Created " << postLogicp << endl);
|
||||
finalp->addStmtp(postLogicp);
|
||||
finalp->addStmtsp(postLogicp);
|
||||
finalp->user3p(setvscp); // Remember IF's vset variable
|
||||
finalp->user4p(postLogicp); // and the associated IF, as we may be able to reuse it
|
||||
}
|
||||
postLogicp->addIfsp(new AstAssign(nodep->fileline(), selectsp, valreadp));
|
||||
postLogicp->addThensp(new AstAssign(nodep->fileline(), selectsp, valreadp));
|
||||
return newlhsp;
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNetlist* nodep) override {
|
||||
void visit(AstNetlist* nodep) override {
|
||||
// VV***** We reset all userp() on the netlist
|
||||
m_modVarMap.clear();
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
void visit(AstScope* nodep) override {
|
||||
UINFO(4, " MOD " << nodep << endl);
|
||||
AstNode::user3ClearTree();
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
void visit(AstCFunc* nodep) override {
|
||||
VL_RESTORER(m_cfuncp);
|
||||
{
|
||||
m_cfuncp = nodep;
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstActive* nodep) override {
|
||||
void visit(AstActive* nodep) override {
|
||||
m_activep = nodep;
|
||||
VL_RESTORER(m_inInitial);
|
||||
{
|
||||
|
|
@ -392,7 +393,7 @@ private:
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstAssignDly* nodep) override {
|
||||
void visit(AstAssignDly* nodep) override {
|
||||
m_inDly = true;
|
||||
m_nextDlyp
|
||||
= VN_CAST(nodep->nextp(), AssignDly); // Next assignment in same block, maybe nullptr.
|
||||
|
|
@ -426,7 +427,7 @@ private:
|
|||
m_nextDlyp = nullptr;
|
||||
}
|
||||
|
||||
virtual void visit(AstVarRef* nodep) override {
|
||||
void visit(AstVarRef* nodep) override {
|
||||
if (!nodep->user2Inc()) { // Not done yet
|
||||
if (m_inDly && nodep->access().isWriteOrRW()) {
|
||||
UINFO(4, "AssignDlyVar: " << nodep << endl);
|
||||
|
|
@ -488,18 +489,18 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeReadWriteMem* nodep) override {
|
||||
void visit(AstNodeReadWriteMem* nodep) override {
|
||||
VL_RESTORER(m_ignoreBlkAndNBlk);
|
||||
m_ignoreBlkAndNBlk = true; // $readmem/$writemem often used in mem models
|
||||
// so we will suppress BLKANDNBLK warnings
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeFor* nodep) override { // LCOV_EXCL_LINE
|
||||
void visit(AstNodeFor* nodep) override { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc(
|
||||
"For statements should have been converted to while statements in V3Begin");
|
||||
}
|
||||
virtual void visit(AstWhile* nodep) override {
|
||||
void visit(AstWhile* nodep) override {
|
||||
VL_RESTORER(m_inLoop);
|
||||
{
|
||||
m_inLoop = true;
|
||||
|
|
@ -508,12 +509,12 @@ private:
|
|||
}
|
||||
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit DelayedVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~DelayedVisitor() override {
|
||||
~DelayedVisitor() override {
|
||||
V3Stats::addStat("Optimizations, Delayed shared-sets", m_statSharedSet);
|
||||
}
|
||||
};
|
||||
|
|
@ -524,5 +525,5 @@ public:
|
|||
void V3Delayed::delayedAll(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ DelayedVisitor{nodep}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("delayed", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("delayed", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
|
||||
class DepthVisitor final : public VNVisitor {
|
||||
|
|
@ -49,7 +51,6 @@ private:
|
|||
V3UniqueNames m_tempNames; // For generating unique temporary variable names
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
void createDeepTemp(AstNode* nodep) {
|
||||
UINFO(6, " Deep " << nodep << endl);
|
||||
|
|
@ -73,7 +74,7 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
void visit(AstCFunc* nodep) override {
|
||||
VL_RESTORER(m_cfuncp);
|
||||
VL_RESTORER(m_mtaskbodyp);
|
||||
{
|
||||
|
|
@ -85,7 +86,7 @@ private:
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstMTaskBody* nodep) override {
|
||||
void visit(AstMTaskBody* nodep) override {
|
||||
VL_RESTORER(m_cfuncp);
|
||||
VL_RESTORER(m_mtaskbodyp);
|
||||
{
|
||||
|
|
@ -106,7 +107,7 @@ private:
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeStmt* nodep) override {
|
||||
void visit(AstNodeStmt* nodep) override {
|
||||
if (!nodep->isStatement()) {
|
||||
iterateChildren(nodep);
|
||||
} else {
|
||||
|
|
@ -114,8 +115,8 @@ private:
|
|||
}
|
||||
}
|
||||
// Operators
|
||||
virtual void visit(AstNodeTermop* nodep) override {}
|
||||
virtual void visit(AstNodeMath* nodep) override {
|
||||
void visit(AstNodeTermop* nodep) override {}
|
||||
void visit(AstNodeMath* nodep) override {
|
||||
// We have some operator defines that use 2 parens, so += 2.
|
||||
{
|
||||
VL_RESTORER(m_depth);
|
||||
|
|
@ -142,19 +143,19 @@ private:
|
|||
m_cfuncp->isStatic(false);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstUCFunc* nodep) override {
|
||||
void visit(AstUCFunc* nodep) override {
|
||||
needNonStaticFunc(nodep);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstUCStmt* nodep) override {
|
||||
void visit(AstUCStmt* nodep) override {
|
||||
needNonStaticFunc(nodep);
|
||||
visitStmt(nodep);
|
||||
}
|
||||
|
||||
//--------------------
|
||||
// Default: Just iterate
|
||||
virtual void visit(AstVar*) override {} // Don't hit varrefs under vars
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstVar*) override {} // Don't hit varrefs under vars
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
|
|
@ -162,7 +163,7 @@ public:
|
|||
: m_tempNames{"__Vdeeptemp"} {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~DepthVisitor() override = default;
|
||||
~DepthVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -171,5 +172,5 @@ public:
|
|||
void V3Depth::depthAll(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ DepthVisitor{nodep}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("depth", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 6);
|
||||
V3Global::dumpCheckGlobalTree("depth", 0, dumpTree() >= 6);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
|
||||
class DepthBlockVisitor final : public VNVisitor {
|
||||
|
|
@ -44,7 +46,6 @@ private:
|
|||
int m_deepNum = 0; // How many functions made
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
AstCFunc* createDeepFunc(AstNode* nodep) {
|
||||
VNRelinker relinkHandle;
|
||||
|
|
@ -57,7 +58,7 @@ private:
|
|||
funcp->isStatic(m_cfuncp->isStatic());
|
||||
funcp->isLoose(m_cfuncp->isLoose());
|
||||
funcp->addStmtsp(nodep);
|
||||
scopep->addActivep(funcp);
|
||||
scopep->addBlocksp(funcp);
|
||||
// Call sub function at the point where the body was removed from
|
||||
AstCCall* const callp = new AstCCall(nodep->fileline(), funcp);
|
||||
if (VN_IS(m_modp, Class)) {
|
||||
|
|
@ -71,7 +72,7 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
UINFO(4, " MOD " << nodep << endl);
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
|
|
@ -80,7 +81,7 @@ private:
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
void visit(AstCFunc* nodep) override {
|
||||
// We recurse into this.
|
||||
VL_RESTORER(m_depth);
|
||||
VL_RESTORER(m_cfuncp);
|
||||
|
|
@ -106,7 +107,7 @@ private:
|
|||
}
|
||||
m_depth--;
|
||||
}
|
||||
virtual void visit(AstNodeStmt* nodep) override {
|
||||
void visit(AstNodeStmt* nodep) override {
|
||||
if (!nodep->isStatement()) {
|
||||
iterateChildren(nodep);
|
||||
} else {
|
||||
|
|
@ -114,15 +115,15 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeMath*) override {} // Accelerate
|
||||
void visit(AstNodeMath*) override {} // Accelerate
|
||||
//--------------------
|
||||
virtual void visit(AstVar*) override {} // Don't hit varrefs under vars
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstVar*) override {} // Don't hit varrefs under vars
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit DepthBlockVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~DepthBlockVisitor() override = default;
|
||||
~DepthBlockVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -131,5 +132,5 @@ public:
|
|||
void V3DepthBlock::depthBlockAll(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ DepthBlockVisitor{nodep}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("deepblock", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("deepblock", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@
|
|||
|
||||
#include <map>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
|
||||
class DescopeVisitor final : public VNVisitor {
|
||||
|
|
@ -53,7 +55,6 @@ private:
|
|||
FuncMmap m_modFuncs; // Name of public functions added
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
static bool modIsSingleton(AstNodeModule* modp) {
|
||||
// True iff there's exactly one instance of this module in the design (including top).
|
||||
|
|
@ -139,14 +140,14 @@ private:
|
|||
UINFO(6,
|
||||
" at " << newfuncp->argTypes() << " und " << funcp->argTypes() << endl);
|
||||
funcp->declPrivate(true);
|
||||
AstNode* argsp = nullptr;
|
||||
AstVarRef* argsp = nullptr;
|
||||
for (AstNode* stmtp = newfuncp->argsp(); stmtp; stmtp = stmtp->nextp()) {
|
||||
if (AstVar* const portp = VN_CAST(stmtp, Var)) {
|
||||
if (portp->isIO() && !portp->isFuncReturn()) {
|
||||
AstNode* const newp = new AstVarRef(
|
||||
AstVarRef* const newp = new AstVarRef(
|
||||
portp->fileline(), portp,
|
||||
portp->isWritable() ? VAccess::WRITE : VAccess::READ);
|
||||
argsp = argsp ? argsp->addNextNull(newp) : newp;
|
||||
argsp = AstNode::addNext(argsp, newp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -185,11 +186,11 @@ private:
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNetlist* nodep) override {
|
||||
void visit(AstNetlist* nodep) override {
|
||||
nodep->dpiExportTriggerp(nullptr);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
m_modp = nodep;
|
||||
|
|
@ -199,17 +200,17 @@ private:
|
|||
makePublicFuncWrappers();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
void visit(AstScope* nodep) override {
|
||||
m_scopep = nodep;
|
||||
iterateChildren(nodep);
|
||||
m_scopep = nullptr;
|
||||
}
|
||||
virtual void visit(AstVarScope* nodep) override {
|
||||
void visit(AstVarScope* nodep) override {
|
||||
// Delete the varscope when we're finished
|
||||
nodep->unlinkFrBack();
|
||||
pushDeletep(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeVarRef* nodep) override {
|
||||
void visit(AstNodeVarRef* nodep) override {
|
||||
iterateChildren(nodep);
|
||||
if (!nodep->varScopep()) {
|
||||
UASSERT_OBJ(nodep->varp()->isFuncLocal(), nodep,
|
||||
|
|
@ -233,7 +234,7 @@ private:
|
|||
nodep->varScopep(nullptr);
|
||||
UINFO(9, " refout " << nodep << " selfPtr=" << nodep->selfPointer() << endl);
|
||||
}
|
||||
virtual void visit(AstCCall* nodep) override {
|
||||
void visit(AstCCall* nodep) override {
|
||||
// UINFO(9, " " << nodep << endl);
|
||||
iterateChildren(nodep);
|
||||
// Convert the hierch name
|
||||
|
|
@ -243,9 +244,9 @@ private:
|
|||
// Can't do this, as we may have more calls later
|
||||
// nodep->funcp()->scopep(nullptr);
|
||||
}
|
||||
virtual void visit(AstCMethodCall* nodep) override { iterateChildren(nodep); }
|
||||
virtual void visit(AstCNew* nodep) override { iterateChildren(nodep); }
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
void visit(AstCMethodCall* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstCNew* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstCFunc* nodep) override {
|
||||
VL_RESTORER(m_funcp);
|
||||
if (!nodep->user1()) {
|
||||
// Static functions should have been moved under the corresponding AstClassPackage
|
||||
|
|
@ -257,7 +258,7 @@ private:
|
|||
// If it's under a scope, move it up to the top
|
||||
if (m_scopep) {
|
||||
nodep->unlinkFrBack();
|
||||
m_modp->addStmtp(nodep);
|
||||
m_modp->addStmtsp(nodep);
|
||||
|
||||
if (nodep->funcPublic()) {
|
||||
// There may be multiple public functions by the same name;
|
||||
|
|
@ -268,13 +269,13 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVar*) override {}
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstVar*) override {}
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit DescopeVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~DescopeVisitor() override = default;
|
||||
~DescopeVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -283,5 +284,5 @@ public:
|
|||
void V3Descope::descopeAll(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ DescopeVisitor{nodep}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("descope", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("descope", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// V3DupFinder class functions
|
||||
|
||||
|
|
@ -98,7 +100,5 @@ void V3DupFinder::dumpFile(const string& filename, bool tree) {
|
|||
}
|
||||
|
||||
void V3DupFinder::dumpFilePrefixed(const string& nameComment, bool tree) {
|
||||
if (v3Global.opt.dumpTree()) { //
|
||||
dumpFile(v3Global.debugFilename(nameComment) + ".hash", tree);
|
||||
}
|
||||
if (dump()) dumpFile(v3Global.debugFilename(nameComment) + ".hash", tree);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ public:
|
|||
}
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
// Expose minimal set of superclass interface
|
||||
using Super::begin;
|
||||
|
|
|
|||
|
|
@ -57,11 +57,11 @@ string EmitCBaseVisitor::funcNameProtect(const AstCFunc* nodep, const AstNodeMod
|
|||
return name;
|
||||
}
|
||||
|
||||
AstCFile* EmitCBaseVisitor::newCFile(const string& filename, bool slow, bool source) {
|
||||
AstCFile* EmitCBaseVisitor::newCFile(const string& filename, bool slow, bool source, bool add) {
|
||||
AstCFile* const cfilep = new AstCFile(v3Global.rootp()->fileline(), filename);
|
||||
cfilep->slow(slow);
|
||||
cfilep->source(source);
|
||||
v3Global.rootp()->addFilesp(cfilep);
|
||||
if (add) v3Global.rootp()->addFilesp(cfilep);
|
||||
return cfilep;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ public:
|
|||
&& (varp->basicp() && !varp->basicp()->isOpaque()); // Aggregates can't be anon
|
||||
}
|
||||
|
||||
static AstCFile* newCFile(const string& filename, bool slow, bool source);
|
||||
static AstCFile* newCFile(const string& filename, bool slow, bool source, bool add = true);
|
||||
string cFuncArgs(const AstCFunc* nodep);
|
||||
void emitCFuncHeader(const AstCFunc* funcp, const AstNodeModule* modp, bool withScope);
|
||||
void emitCFuncDecl(const AstCFunc* funcp, const AstNodeModule* modp, bool cLinkage = false);
|
||||
|
|
@ -110,7 +110,7 @@ public:
|
|||
|
||||
// CONSTRUCTORS
|
||||
EmitCBaseVisitor() = default;
|
||||
virtual ~EmitCBaseVisitor() override = default;
|
||||
~EmitCBaseVisitor() override = default;
|
||||
};
|
||||
|
||||
#endif // guard
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ class EmitCConstInit VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
uint32_t m_unpackedWord = 0;
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
uint32_t tabModulus(AstNodeDType* dtypep) {
|
||||
const uint32_t elemBytes = dtypep->widthTotalBytes();
|
||||
|
|
@ -45,7 +44,7 @@ class EmitCConstInit VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
|
||||
protected:
|
||||
// VISITORS
|
||||
virtual void visit(AstInitArray* nodep) override {
|
||||
void visit(AstInitArray* nodep) override {
|
||||
VL_RESTORER(m_inUnpacked);
|
||||
VL_RESTORER(m_unpackedWord);
|
||||
m_inUnpacked = true;
|
||||
|
|
@ -94,11 +93,11 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstInitItem* nodep) override { // LCOV_EXCL_START
|
||||
void visit(AstInitItem* nodep) override { // LCOV_EXCL_START
|
||||
nodep->v3fatal("Handled by AstInitArray");
|
||||
} // LCOV_EXCL_STOP
|
||||
|
||||
virtual void visit(AstConst* nodep) override {
|
||||
void visit(AstConst* nodep) override {
|
||||
const V3Number& num = nodep->num();
|
||||
UASSERT_OBJ(!num.isFourState(), nodep, "4-state value in constant pool");
|
||||
const AstNodeDType* const dtypep = nodep->dtypep();
|
||||
|
|
@ -145,7 +144,7 @@ protected:
|
|||
}
|
||||
|
||||
// Default
|
||||
virtual void visit(AstNode* nodep) override { // LCOV_EXCL_START
|
||||
void visit(AstNode* nodep) override { // LCOV_EXCL_START
|
||||
nodep->v3fatalSrc("Unknown node type reached EmitCConstInit: " << nodep->prettyTypeName());
|
||||
} // LCOV_EXCL_STOP
|
||||
};
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#include <algorithm>
|
||||
#include <cinttypes>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Const pool emitter
|
||||
|
||||
|
|
@ -38,7 +40,6 @@ class EmitCConstPool final : public EmitCConstInit {
|
|||
VDouble0 m_constsEmitted;
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
V3OutCFile* newOutCFile() const {
|
||||
const string fileName = v3Global.opt.makeDir() + "/" + topClassName() + "__ConstPool_"
|
||||
|
|
@ -100,7 +101,7 @@ class EmitCConstPool final : public EmitCConstInit {
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstConst* nodep) override {
|
||||
void visit(AstConst* nodep) override {
|
||||
m_outFileSize += nodep->num().isString() ? 10 : nodep->isWide() ? nodep->widthWords() : 1;
|
||||
EmitCConstInit::visit(nodep);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,18 +36,20 @@ constexpr int EMITC_NUM_CONSTW = 8;
|
|||
|
||||
class EmitCLazyDecls final : public VNVisitor {
|
||||
// NODE STATE/TYPES
|
||||
// AstNode::user2() -> bool. Already emitted decl for symbols.
|
||||
const VNUser2InUse m_inuser2;
|
||||
// None allowed to support threaded emitting
|
||||
|
||||
// MEMBERS
|
||||
std::unordered_set<string> m_emittedManually; // Set of names already declared manually.
|
||||
EmitCBaseVisitor& m_emitter; // For access to file output
|
||||
bool m_needsBlankLine = false; // Emit blank line if any declarations were emitted (cosmetic)
|
||||
std::set<AstNode*> m_emitted; // -> in set. Already emitted decl for symbols.
|
||||
|
||||
// METHODS
|
||||
bool declaredOnce(AstNode* nodep) { return m_emitted.insert(nodep).second; }
|
||||
|
||||
void lazyDeclare(AstCFunc* funcp) {
|
||||
// Already declared in this compilation unit
|
||||
if (funcp->user2SetOnce()) return;
|
||||
if (!declaredOnce(funcp)) return;
|
||||
// Check if this kind of function is lazily declared
|
||||
if (!(funcp->isMethod() && funcp->isLoose()) && !funcp->dpiImportPrototype()) return;
|
||||
// Already declared manually
|
||||
|
|
@ -58,7 +60,7 @@ class EmitCLazyDecls final : public VNVisitor {
|
|||
}
|
||||
|
||||
void lazyDeclareConstPoolVar(AstVar* varp) {
|
||||
if (varp->user2SetOnce()) return; // Already declared
|
||||
if (!declaredOnce(varp)) return; // Already declared
|
||||
const string nameProtect
|
||||
= m_emitter.topClassName() + "__ConstPool__" + varp->nameProtect();
|
||||
m_emitter.puts("extern const ");
|
||||
|
|
@ -68,17 +70,17 @@ class EmitCLazyDecls final : public VNVisitor {
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNodeCCall* nodep) override {
|
||||
void visit(AstNodeCCall* nodep) override {
|
||||
lazyDeclare(nodep->funcp());
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstAddrOfCFunc* nodep) override {
|
||||
void visit(AstAddrOfCFunc* nodep) override {
|
||||
lazyDeclare(nodep->funcp());
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstVarRef* nodep) override {
|
||||
void visit(AstVarRef* nodep) override {
|
||||
AstVar* const varp = nodep->varp();
|
||||
// Only constant pool symbols are lazy declared for now ...
|
||||
if (EmitCBaseVisitor::isConstPoolMod(EmitCParentModule::get(varp))) {
|
||||
|
|
@ -86,9 +88,7 @@ class EmitCLazyDecls final : public VNVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstNode* nodep) override { iterateChildrenConst(nodep); }
|
||||
|
||||
VL_DEBUG_FUNC;
|
||||
void visit(AstNode* nodep) override { iterateChildrenConst(nodep); }
|
||||
|
||||
public:
|
||||
explicit EmitCLazyDecls(EmitCBaseVisitor& emitter)
|
||||
|
|
@ -106,8 +106,8 @@ public:
|
|||
m_emitter.puts(suffix);
|
||||
m_emitter.ensureNewLine();
|
||||
}
|
||||
void declared(AstCFunc* nodep) { nodep->user2SetOnce(); }
|
||||
void reset() { AstNode::user2ClearTree(); }
|
||||
void declared(AstCFunc* nodep) { m_emitted.insert(nodep); }
|
||||
void reset() { m_emitted.clear(); }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -152,7 +152,6 @@ protected:
|
|||
|
||||
public:
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
// ACCESSORS
|
||||
void splitSizeInc(int count) { m_splitSize += count; }
|
||||
|
|
@ -211,7 +210,7 @@ public:
|
|||
|
||||
// VISITORS
|
||||
using EmitCConstInit::visit;
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
void visit(AstCFunc* nodep) override {
|
||||
VL_RESTORER(m_useSelfForThis);
|
||||
VL_RESTORER(m_cfuncp);
|
||||
m_cfuncp = nodep;
|
||||
|
|
@ -279,12 +278,12 @@ public:
|
|||
if (nodep->ifdef() != "") puts("#endif // " + nodep->ifdef() + "\n");
|
||||
}
|
||||
|
||||
virtual void visit(AstVar* nodep) override {
|
||||
void visit(AstVar* nodep) override {
|
||||
UASSERT_OBJ(m_cfuncp, nodep, "Cannot emit non-local variable");
|
||||
emitVarDecl(nodep);
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeAssign* nodep) override {
|
||||
void visit(AstNodeAssign* nodep) override {
|
||||
bool paren = true;
|
||||
bool decind = false;
|
||||
bool rhs = true;
|
||||
|
|
@ -366,8 +365,8 @@ public:
|
|||
if (decind) ofp()->blockDec();
|
||||
puts(";\n");
|
||||
}
|
||||
virtual void visit(AstAlwaysPublic*) override {}
|
||||
virtual void visit(AstAssocSel* nodep) override {
|
||||
void visit(AstAlwaysPublic*) override {}
|
||||
void visit(AstAssocSel* nodep) override {
|
||||
iterateAndNextNull(nodep->fromp());
|
||||
putbs(".at(");
|
||||
AstAssocArrayDType* const adtypep = VN_AS(nodep->fromp()->dtypep(), AssocArrayDType);
|
||||
|
|
@ -379,7 +378,7 @@ public:
|
|||
}
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstWildcardSel* nodep) override {
|
||||
void visit(AstWildcardSel* nodep) override {
|
||||
iterateAndNextNull(nodep->fromp());
|
||||
putbs(".at(");
|
||||
AstWildcardArrayDType* const adtypep = VN_AS(nodep->fromp()->dtypep(), WildcardArrayDType);
|
||||
|
|
@ -387,7 +386,7 @@ public:
|
|||
iterateAndNextNull(nodep->bitp());
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstCCall* nodep) override {
|
||||
void visit(AstCCall* nodep) override {
|
||||
const AstCFunc* const funcp = nodep->funcp();
|
||||
const AstNodeModule* const funcModp = EmitCParentModule::get(funcp);
|
||||
if (funcp->dpiImportPrototype()) {
|
||||
|
|
@ -413,7 +412,7 @@ public:
|
|||
}
|
||||
emitCCallArgs(nodep, nodep->selfPointerProtect(m_useSelfForThis));
|
||||
}
|
||||
virtual void visit(AstCMethodCall* nodep) override {
|
||||
void visit(AstCMethodCall* nodep) override {
|
||||
const AstCFunc* const funcp = nodep->funcp();
|
||||
UASSERT_OBJ(!funcp->isLoose(), nodep, "Loose method called via AstCMethodCall");
|
||||
iterate(nodep->fromp());
|
||||
|
|
@ -421,7 +420,7 @@ public:
|
|||
puts(funcp->nameProtect());
|
||||
emitCCallArgs(nodep, "");
|
||||
}
|
||||
virtual void visit(AstCNew* nodep) override {
|
||||
void visit(AstCNew* nodep) override {
|
||||
bool comma = false;
|
||||
puts("std::make_shared<" + prefixNameProtect(nodep->dtypep()) + ">(");
|
||||
puts("vlSymsp"); // TODO make this part of argsp, and eliminate when unnecessary
|
||||
|
|
@ -433,7 +432,7 @@ public:
|
|||
}
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstCMethodHard* nodep) override {
|
||||
void visit(AstCMethodHard* nodep) override {
|
||||
iterate(nodep->fromp());
|
||||
puts(".");
|
||||
puts(nodep->name());
|
||||
|
|
@ -455,8 +454,8 @@ public:
|
|||
UASSERT_OBJ(!nodep->isStatement() || VN_IS(nodep->dtypep(), VoidDType), nodep,
|
||||
"Statement of non-void data type");
|
||||
}
|
||||
virtual void visit(AstLambdaArgRef* nodep) override { putbs(nodep->nameProtect()); }
|
||||
virtual void visit(AstWith* nodep) override {
|
||||
void visit(AstLambdaArgRef* nodep) override { putbs(nodep->nameProtect()); }
|
||||
void visit(AstWith* nodep) override {
|
||||
// With uses a C++11 lambda
|
||||
putbs("[=](");
|
||||
if (auto* const argrefp = nodep->indexArgRefp()) {
|
||||
|
|
@ -471,11 +470,11 @@ public:
|
|||
iterateAndNextNull(nodep->exprp());
|
||||
puts("; }\n");
|
||||
}
|
||||
virtual void visit(AstNodeCase* nodep) override { // LCOV_EXCL_LINE
|
||||
void visit(AstNodeCase* nodep) override { // LCOV_EXCL_LINE
|
||||
// In V3Case...
|
||||
nodep->v3fatalSrc("Case statements should have been reduced out");
|
||||
}
|
||||
virtual void visit(AstComment* nodep) override {
|
||||
void visit(AstComment* nodep) override {
|
||||
string at;
|
||||
if (nodep->showAt()) {
|
||||
at = " at " + nodep->fileline()->ascii();
|
||||
|
|
@ -487,7 +486,7 @@ public:
|
|||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstCoverDecl* nodep) override {
|
||||
void visit(AstCoverDecl* nodep) override {
|
||||
puts("vlSelf->__vlCoverInsert("); // As Declared in emitCoverageDecl
|
||||
puts("&(vlSymsp->__Vcoverage[");
|
||||
puts(cvtToStr(nodep->dataDeclThisp()->binNum()));
|
||||
|
|
@ -515,7 +514,7 @@ public:
|
|||
putsQuoted(nodep->linescov());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstCoverInc* nodep) override {
|
||||
void visit(AstCoverInc* nodep) override {
|
||||
if (v3Global.opt.threads()) {
|
||||
puts("vlSymsp->__Vcoverage[");
|
||||
puts(cvtToStr(nodep->declp()->dataDeclThisp()->binNum()));
|
||||
|
|
@ -526,17 +525,17 @@ public:
|
|||
puts("]);\n");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCReturn* nodep) override {
|
||||
void visit(AstCReturn* nodep) override {
|
||||
puts("return (");
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstDisplay* nodep) override {
|
||||
void visit(AstDisplay* nodep) override {
|
||||
string text = nodep->fmtp()->text();
|
||||
if (nodep->addNewline()) text += "\n";
|
||||
displayNode(nodep, nodep->fmtp()->scopeNamep(), text, nodep->fmtp()->exprsp(), false);
|
||||
}
|
||||
virtual void visit(AstDumpCtl* nodep) override {
|
||||
void visit(AstDumpCtl* nodep) override {
|
||||
switch (nodep->ctlType()) {
|
||||
case VDumpCtlType::FILE:
|
||||
puts("vlSymsp->_vm_contextp__->dumpfile(");
|
||||
|
|
@ -575,7 +574,7 @@ public:
|
|||
default: nodep->v3fatalSrc("Bad case, unexpected " << nodep->ctlType().ascii());
|
||||
}
|
||||
}
|
||||
virtual void visit(AstScopeName* nodep) override {
|
||||
void visit(AstScopeName* nodep) override {
|
||||
// For use under AstCCalls for dpiImports. ScopeNames under
|
||||
// displays are handled in AstDisplay
|
||||
if (!nodep->dpiExport()) {
|
||||
|
|
@ -584,20 +583,20 @@ public:
|
|||
putbs("(&(vlSymsp->" + protect("__Vscope_" + scope) + "))");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstSFormat* nodep) override {
|
||||
void visit(AstSFormat* nodep) override {
|
||||
displayNode(nodep, nodep->fmtp()->scopeNamep(), nodep->fmtp()->text(),
|
||||
nodep->fmtp()->exprsp(), false);
|
||||
}
|
||||
virtual void visit(AstSFormatF* nodep) override {
|
||||
void visit(AstSFormatF* nodep) override {
|
||||
displayNode(nodep, nodep->scopeNamep(), nodep->text(), nodep->exprsp(), false);
|
||||
}
|
||||
virtual void visit(AstFScanF* nodep) override {
|
||||
void visit(AstFScanF* nodep) override {
|
||||
displayNode(nodep, nullptr, nodep->text(), nodep->exprsp(), true);
|
||||
}
|
||||
virtual void visit(AstSScanF* nodep) override {
|
||||
void visit(AstSScanF* nodep) override {
|
||||
displayNode(nodep, nullptr, nodep->text(), nodep->exprsp(), true);
|
||||
}
|
||||
virtual void visit(AstValuePlusArgs* nodep) override {
|
||||
void visit(AstValuePlusArgs* nodep) override {
|
||||
puts("VL_VALUEPLUSARGS_IN");
|
||||
emitIQW(nodep->outp());
|
||||
puts("(");
|
||||
|
|
@ -609,19 +608,19 @@ public:
|
|||
iterateAndNextNull(nodep->outp());
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstTestPlusArgs* nodep) override {
|
||||
void visit(AstTestPlusArgs* nodep) override {
|
||||
puts("VL_TESTPLUSARGS_I(");
|
||||
emitCvtPackStr(nodep->searchp());
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstFError* nodep) override {
|
||||
void visit(AstFError* nodep) override {
|
||||
puts("VL_FERROR_IN(");
|
||||
iterateAndNextNull(nodep->filep());
|
||||
putbs(", ");
|
||||
iterateAndNextNull(nodep->strp());
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstFGetS* nodep) override {
|
||||
void visit(AstFGetS* nodep) override {
|
||||
checkMaxWords(nodep);
|
||||
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), nullptr);
|
||||
}
|
||||
|
|
@ -634,7 +633,7 @@ public:
|
|||
<< " bits exceeds hardcoded limit VL_VALUE_STRING_MAX_WORDS in verilatedos.h");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstFOpen* nodep) override {
|
||||
void visit(AstFOpen* nodep) override {
|
||||
iterateAndNextNull(nodep->filep());
|
||||
puts(" = VL_FOPEN_NN(");
|
||||
emitCvtPackStr(nodep->filenamep());
|
||||
|
|
@ -644,13 +643,13 @@ public:
|
|||
emitCvtPackStr(nodep->modep());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstFOpenMcd* nodep) override {
|
||||
void visit(AstFOpenMcd* nodep) override {
|
||||
iterateAndNextNull(nodep->filep());
|
||||
puts(" = VL_FOPEN_MCD_N(");
|
||||
emitCvtPackStr(nodep->filenamep());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstNodeReadWriteMem* nodep) override {
|
||||
void visit(AstNodeReadWriteMem* nodep) override {
|
||||
puts(nodep->cFuncPrefixp());
|
||||
puts("N(");
|
||||
puts(nodep->isHex() ? "true" : "false");
|
||||
|
|
@ -699,14 +698,14 @@ public:
|
|||
}
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstFClose* nodep) override {
|
||||
void visit(AstFClose* nodep) override {
|
||||
puts("VL_FCLOSE_I(");
|
||||
iterateAndNextNull(nodep->filep());
|
||||
puts("); ");
|
||||
iterateAndNextNull(nodep->filep()); // For safety, so user doesn't later WRITE with it.
|
||||
puts(" = 0;\n");
|
||||
}
|
||||
virtual void visit(AstFFlush* nodep) override {
|
||||
void visit(AstFFlush* nodep) override {
|
||||
if (!nodep->filep()) {
|
||||
puts("Verilated::runFlushCallbacks();\n");
|
||||
} else {
|
||||
|
|
@ -717,7 +716,7 @@ public:
|
|||
puts("); }\n");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstFSeek* nodep) override {
|
||||
void visit(AstFSeek* nodep) override {
|
||||
puts("(VL_FSEEK_I(");
|
||||
iterateAndNextNull(nodep->filep());
|
||||
puts(",");
|
||||
|
|
@ -726,17 +725,17 @@ public:
|
|||
iterateAndNextNull(nodep->operation());
|
||||
puts(") == -1 ? -1 : 0)");
|
||||
}
|
||||
virtual void visit(AstFTell* nodep) override {
|
||||
void visit(AstFTell* nodep) override {
|
||||
puts("VL_FTELL_I(");
|
||||
iterateAndNextNull(nodep->filep());
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstFRewind* nodep) override {
|
||||
void visit(AstFRewind* nodep) override {
|
||||
puts("(VL_FSEEK_I(");
|
||||
iterateAndNextNull(nodep->filep());
|
||||
puts(", 0, 0) == -1 ? -1 : 0)");
|
||||
}
|
||||
virtual void visit(AstFRead* nodep) override {
|
||||
void visit(AstFRead* nodep) override {
|
||||
puts("VL_FREAD_I(");
|
||||
puts(cvtToStr(nodep->memp()->widthMin())); // Need real storage width
|
||||
putbs(",");
|
||||
|
|
@ -779,12 +778,12 @@ public:
|
|||
}
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstSysFuncAsTask* nodep) override {
|
||||
void visit(AstSysFuncAsTask* nodep) override {
|
||||
if (!nodep->lhsp()->isWide()) puts("(void)");
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
if (!nodep->lhsp()->isWide()) puts(";");
|
||||
}
|
||||
virtual void visit(AstSystemT* nodep) override {
|
||||
void visit(AstSystemT* nodep) override {
|
||||
puts("(void)VL_SYSTEM_I");
|
||||
emitIQW(nodep->lhsp());
|
||||
puts("(");
|
||||
|
|
@ -796,7 +795,7 @@ public:
|
|||
iterateAndNextNull(nodep->lhsp());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstSystemF* nodep) override {
|
||||
void visit(AstSystemF* nodep) override {
|
||||
puts("VL_SYSTEM_I");
|
||||
emitIQW(nodep->lhsp());
|
||||
puts("(");
|
||||
|
|
@ -808,30 +807,30 @@ public:
|
|||
iterateAndNextNull(nodep->lhsp());
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstJumpBlock* nodep) override {
|
||||
void visit(AstJumpBlock* nodep) override {
|
||||
nodep->labelNum(++m_labelNum);
|
||||
puts("{\n"); // Make it visually obvious label jumps outside these
|
||||
iterateAndNextNull(nodep->stmtsp());
|
||||
iterateAndNextNull(nodep->endStmtsp());
|
||||
puts("}\n");
|
||||
}
|
||||
virtual void visit(AstJumpGo* nodep) override {
|
||||
void visit(AstJumpGo* nodep) override {
|
||||
puts("goto __Vlabel" + cvtToStr(nodep->labelp()->blockp()->labelNum()) + ";\n");
|
||||
}
|
||||
virtual void visit(AstJumpLabel* nodep) override {
|
||||
void visit(AstJumpLabel* nodep) override {
|
||||
puts("__Vlabel" + cvtToStr(nodep->blockp()->labelNum()) + ": ;\n");
|
||||
}
|
||||
virtual void visit(AstWhile* nodep) override {
|
||||
void visit(AstWhile* nodep) override {
|
||||
iterateAndNextNull(nodep->precondsp());
|
||||
puts("while (");
|
||||
iterateAndNextNull(nodep->condp());
|
||||
puts(") {\n");
|
||||
iterateAndNextNull(nodep->bodysp());
|
||||
iterateAndNextNull(nodep->stmtsp());
|
||||
iterateAndNextNull(nodep->incsp());
|
||||
iterateAndNextNull(nodep->precondsp()); // Need to recompute before next loop
|
||||
puts("}\n");
|
||||
}
|
||||
virtual void visit(AstNodeIf* nodep) override {
|
||||
void visit(AstNodeIf* nodep) override {
|
||||
puts("if (");
|
||||
if (!nodep->branchPred().unknown()) {
|
||||
puts(nodep->branchPred().ascii());
|
||||
|
|
@ -840,7 +839,7 @@ public:
|
|||
iterateAndNextNull(nodep->condp());
|
||||
if (!nodep->branchPred().unknown()) puts(")");
|
||||
puts(") {\n");
|
||||
iterateAndNextNull(nodep->ifsp());
|
||||
iterateAndNextNull(nodep->thensp());
|
||||
puts("}");
|
||||
if (!nodep->elsesp()) {
|
||||
puts("\n");
|
||||
|
|
@ -855,7 +854,7 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstExprStmt* nodep) override {
|
||||
void visit(AstExprStmt* nodep) override {
|
||||
// GCC allows compound statements in expressions, but this is not standard.
|
||||
// So we use an immediate-evaluation lambda and comma operator
|
||||
putbs("([&]() {\n");
|
||||
|
|
@ -864,7 +863,7 @@ public:
|
|||
iterateAndNextNull(nodep->resultp());
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstStop* nodep) override {
|
||||
void visit(AstStop* nodep) override {
|
||||
puts("VL_STOP_MT(");
|
||||
putsQuoted(protect(nodep->fileline()->filename()));
|
||||
puts(", ");
|
||||
|
|
@ -872,38 +871,38 @@ public:
|
|||
puts(", \"\"");
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstFinish* nodep) override {
|
||||
void visit(AstFinish* nodep) override {
|
||||
puts("VL_FINISH_MT(");
|
||||
putsQuoted(protect(nodep->fileline()->filename()));
|
||||
puts(", ");
|
||||
puts(cvtToStr(nodep->fileline()->lineno()));
|
||||
puts(", \"\");\n");
|
||||
}
|
||||
virtual void visit(AstPrintTimeScale* nodep) override {
|
||||
void visit(AstPrintTimeScale* nodep) override {
|
||||
puts("VL_PRINTTIMESCALE(");
|
||||
putsQuoted(protect(nodep->name()));
|
||||
puts(", ");
|
||||
putsQuoted(nodep->timeunit().ascii());
|
||||
puts(", vlSymsp->_vm_contextp__);\n");
|
||||
}
|
||||
virtual void visit(AstRand* nodep) override {
|
||||
void visit(AstRand* nodep) override {
|
||||
emitOpName(nodep, nodep->emitC(), nodep->seedp(), nullptr, nullptr);
|
||||
}
|
||||
virtual void visit(AstTime* nodep) override {
|
||||
void visit(AstTime* nodep) override {
|
||||
puts("VL_TIME_UNITED_Q(");
|
||||
if (nodep->timeunit().isNone()) nodep->v3fatalSrc("$time has no units");
|
||||
puts(cvtToStr(nodep->timeunit().multiplier()
|
||||
/ v3Global.rootp()->timeprecision().multiplier()));
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstTimeD* nodep) override {
|
||||
void visit(AstTimeD* nodep) override {
|
||||
puts("VL_TIME_UNITED_D(");
|
||||
if (nodep->timeunit().isNone()) nodep->v3fatalSrc("$realtime has no units");
|
||||
puts(cvtToStr(nodep->timeunit().multiplier()
|
||||
/ v3Global.rootp()->timeprecision().multiplier()));
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstTimeFormat* nodep) override {
|
||||
void visit(AstTimeFormat* nodep) override {
|
||||
puts("VL_TIMEFORMAT_IINI(");
|
||||
iterateAndNextNull(nodep->unitsp());
|
||||
puts(", ");
|
||||
|
|
@ -914,7 +913,7 @@ public:
|
|||
iterateAndNextNull(nodep->widthp());
|
||||
puts(", vlSymsp->_vm_contextp__);\n");
|
||||
}
|
||||
virtual void visit(AstNodeSimpleText* nodep) override {
|
||||
void visit(AstNodeSimpleText* nodep) override {
|
||||
const string text = m_inUC && m_useSelfForThis
|
||||
? VString::replaceWord(nodep->text(), "this", "vlSelf")
|
||||
: nodep->text();
|
||||
|
|
@ -924,42 +923,42 @@ public:
|
|||
ofp()->putsNoTracking(text);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstTextBlock* nodep) override {
|
||||
void visit(AstTextBlock* nodep) override {
|
||||
visit(static_cast<AstNodeSimpleText*>(nodep));
|
||||
for (AstNode* childp = nodep->nodesp(); childp; childp = childp->nextp()) {
|
||||
iterate(childp);
|
||||
if (nodep->commas() && childp->nextp()) puts(", ");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCStmt* nodep) override {
|
||||
void visit(AstCStmt* nodep) override {
|
||||
putbs("");
|
||||
iterateAndNextNull(nodep->bodysp());
|
||||
iterateAndNextNull(nodep->exprsp());
|
||||
}
|
||||
virtual void visit(AstCMath* nodep) override {
|
||||
void visit(AstCMath* nodep) override {
|
||||
putbs("");
|
||||
iterateAndNextNull(nodep->bodysp());
|
||||
iterateAndNextNull(nodep->exprsp());
|
||||
}
|
||||
virtual void visit(AstUCStmt* nodep) override {
|
||||
void visit(AstUCStmt* nodep) override {
|
||||
VL_RESTORER(m_inUC);
|
||||
m_inUC = true;
|
||||
putsDecoration(ifNoProtect("// $c statement at " + nodep->fileline()->ascii() + "\n"));
|
||||
iterateAndNextNull(nodep->bodysp());
|
||||
iterateAndNextNull(nodep->exprsp());
|
||||
puts("\n");
|
||||
}
|
||||
virtual void visit(AstUCFunc* nodep) override {
|
||||
void visit(AstUCFunc* nodep) override {
|
||||
VL_RESTORER(m_inUC);
|
||||
m_inUC = true;
|
||||
puts("\n");
|
||||
putsDecoration(ifNoProtect("// $c function at " + nodep->fileline()->ascii() + "\n"));
|
||||
iterateAndNextNull(nodep->bodysp());
|
||||
iterateAndNextNull(nodep->exprsp());
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
// Operators
|
||||
virtual void visit(AstNodeTermop* nodep) override {
|
||||
void visit(AstNodeTermop* nodep) override {
|
||||
emitOpName(nodep, nodep->emitC(), nullptr, nullptr, nullptr);
|
||||
}
|
||||
virtual void visit(AstNodeUniop* nodep) override {
|
||||
void visit(AstNodeUniop* nodep) override {
|
||||
if (nodep->emitCheckMaxWords()
|
||||
&& (nodep->widthWords() > VL_MULS_MAX_WORDS
|
||||
|| nodep->lhsp()->widthWords() > VL_MULS_MAX_WORDS)) {
|
||||
|
|
@ -979,7 +978,7 @@ public:
|
|||
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nullptr, nullptr);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeBiop* nodep) override {
|
||||
void visit(AstNodeBiop* nodep) override {
|
||||
if (nodep->emitCheckMaxWords() && nodep->widthWords() > VL_MULS_MAX_WORDS) {
|
||||
nodep->v3warn(
|
||||
E_UNSUPPORTED,
|
||||
|
|
@ -999,11 +998,11 @@ public:
|
|||
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), nullptr);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstNodeTriop* nodep) override {
|
||||
void visit(AstNodeTriop* nodep) override {
|
||||
UASSERT_OBJ(!emitSimpleOk(nodep), nodep, "Triop cannot be described in a simple way");
|
||||
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), nodep->thsp());
|
||||
}
|
||||
virtual void visit(AstRedXor* nodep) override {
|
||||
void visit(AstRedXor* nodep) override {
|
||||
if (nodep->lhsp()->isWide()) {
|
||||
visit(static_cast<AstNodeUniop*>(nodep));
|
||||
} else {
|
||||
|
|
@ -1019,7 +1018,7 @@ public:
|
|||
puts(")");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCCast* nodep) override {
|
||||
void visit(AstCCast* nodep) override {
|
||||
// Extending a value of the same word width is just a NOP.
|
||||
if (nodep->size() <= VL_IDATASIZE) {
|
||||
puts("(IData)(");
|
||||
|
|
@ -1029,26 +1028,26 @@ public:
|
|||
iterateAndNextNull(nodep->lhsp());
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstNodeCond* nodep) override {
|
||||
void visit(AstNodeCond* nodep) override {
|
||||
// Widths match up already, so we'll just use C++'s operator w/o any temps.
|
||||
if (nodep->expr1p()->isWide()) {
|
||||
emitOpName(nodep, nodep->emitC(), nodep->condp(), nodep->expr1p(), nodep->expr2p());
|
||||
if (nodep->thenp()->isWide()) {
|
||||
emitOpName(nodep, nodep->emitC(), nodep->condp(), nodep->thenp(), nodep->elsep());
|
||||
} else {
|
||||
putbs("(");
|
||||
iterateAndNextNull(nodep->condp());
|
||||
putbs(" ? ");
|
||||
iterateAndNextNull(nodep->expr1p());
|
||||
iterateAndNextNull(nodep->thenp());
|
||||
putbs(" : ");
|
||||
iterateAndNextNull(nodep->expr2p());
|
||||
iterateAndNextNull(nodep->elsep());
|
||||
puts(")");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstMemberSel* nodep) override {
|
||||
void visit(AstMemberSel* nodep) override {
|
||||
iterateAndNextNull(nodep->fromp());
|
||||
putbs("->");
|
||||
puts(nodep->varp()->nameProtect());
|
||||
}
|
||||
virtual void visit(AstNullCheck* nodep) override {
|
||||
void visit(AstNullCheck* nodep) override {
|
||||
puts("VL_NULL_CHECK(");
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
puts(", ");
|
||||
|
|
@ -1057,17 +1056,17 @@ public:
|
|||
puts(cvtToStr(nodep->fileline()->lineno()));
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstNewCopy* nodep) override {
|
||||
void visit(AstNewCopy* nodep) override {
|
||||
puts("std::make_shared<" + prefixNameProtect(nodep->dtypep()) + ">(");
|
||||
puts("*"); // i.e. make into a reference
|
||||
iterateAndNextNull(nodep->rhsp());
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstSel* nodep) override {
|
||||
void visit(AstSel* nodep) override {
|
||||
// Note ASSIGN checks for this on a LHS
|
||||
emitOpName(nodep, nodep->emitC(), nodep->fromp(), nodep->lsbp(), nodep->thsp());
|
||||
}
|
||||
virtual void visit(AstReplicate* nodep) override {
|
||||
void visit(AstReplicate* nodep) override {
|
||||
if (nodep->lhsp()->widthMin() == 1 && !nodep->isWide()) {
|
||||
UASSERT_OBJ((static_cast<int>(VN_AS(nodep->rhsp(), Const)->toUInt())
|
||||
* nodep->lhsp()->widthMin())
|
||||
|
|
@ -1086,7 +1085,7 @@ public:
|
|||
emitOpName(nodep, nodep->emitC(), nodep->lhsp(), nodep->rhsp(), nullptr);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstStreamL* nodep) override {
|
||||
void visit(AstStreamL* nodep) override {
|
||||
// Attempt to use a "fast" stream function for slice size = power of 2
|
||||
if (!nodep->isWide()) {
|
||||
const uint32_t isPow2 = VN_AS(nodep->rhsp(), Const)->num().countOnes() == 1;
|
||||
|
|
@ -1108,14 +1107,14 @@ public:
|
|||
emitOpName(nodep, "VL_STREAML_%nq%lq%rq(%lw, %P, %li, %ri)", nodep->lhsp(), nodep->rhsp(),
|
||||
nullptr);
|
||||
}
|
||||
virtual void visit(AstCastDynamic* nodep) override {
|
||||
void visit(AstCastDynamic* nodep) override {
|
||||
putbs("VL_CAST_DYNAMIC(");
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
puts(", ");
|
||||
iterateAndNextNull(nodep->rhsp());
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstCountBits* nodep) override {
|
||||
void visit(AstCountBits* nodep) override {
|
||||
putbs("VL_COUNTBITS_");
|
||||
emitIQW(nodep->lhsp());
|
||||
puts("(");
|
||||
|
|
@ -1135,9 +1134,9 @@ public:
|
|||
iterateAndNextNull(nodep->fhsp());
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstInitItem* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstInitItem* nodep) override { iterateChildren(nodep); }
|
||||
// Terminals
|
||||
virtual void visit(AstVarRef* nodep) override {
|
||||
void visit(AstVarRef* nodep) override {
|
||||
const AstVar* const varp = nodep->varp();
|
||||
const AstNodeModule* const varModp = EmitCParentModule::get(varp);
|
||||
if (isConstPoolMod(varModp)) {
|
||||
|
|
@ -1154,14 +1153,14 @@ public:
|
|||
}
|
||||
puts(nodep->varp()->nameProtect());
|
||||
}
|
||||
virtual void visit(AstAddrOfCFunc* nodep) override {
|
||||
void visit(AstAddrOfCFunc* nodep) override {
|
||||
// Note: Can be thought to handle more, but this is all that is needed right now
|
||||
const AstCFunc* const funcp = nodep->funcp();
|
||||
UASSERT_OBJ(funcp->isLoose(), nodep, "Cannot take address of non-loose method");
|
||||
puts("&");
|
||||
puts(funcNameProtect(funcp));
|
||||
}
|
||||
virtual void visit(AstConst* nodep) override {
|
||||
void visit(AstConst* nodep) override {
|
||||
if (m_emitConstInit) {
|
||||
EmitCConstInit::visit(nodep);
|
||||
} else if (nodep->isWide()) {
|
||||
|
|
@ -1174,12 +1173,12 @@ public:
|
|||
}
|
||||
|
||||
//
|
||||
virtual void visit(AstMTaskBody* nodep) override {
|
||||
void visit(AstMTaskBody* nodep) override {
|
||||
VL_RESTORER(m_useSelfForThis);
|
||||
m_useSelfForThis = true;
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
virtual void visit(AstConsAssoc* nodep) override {
|
||||
void visit(AstConsAssoc* nodep) override {
|
||||
putbs(nodep->dtypep()->cType("", false, false));
|
||||
puts("()");
|
||||
if (nodep->defaultp()) {
|
||||
|
|
@ -1188,7 +1187,7 @@ public:
|
|||
puts(")");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstSetAssoc* nodep) override {
|
||||
void visit(AstSetAssoc* nodep) override {
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
putbs(".set(");
|
||||
iterateAndNextNull(nodep->keyp());
|
||||
|
|
@ -1197,7 +1196,7 @@ public:
|
|||
iterateAndNextNull(nodep->valuep());
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstConsWildcard* nodep) override {
|
||||
void visit(AstConsWildcard* nodep) override {
|
||||
putbs(nodep->dtypep()->cType("", false, false));
|
||||
puts("()");
|
||||
if (nodep->defaultp()) {
|
||||
|
|
@ -1206,7 +1205,7 @@ public:
|
|||
puts(")");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstSetWildcard* nodep) override {
|
||||
void visit(AstSetWildcard* nodep) override {
|
||||
iterateAndNextNull(nodep->lhsp());
|
||||
putbs(".set(");
|
||||
iterateAndNextNull(nodep->keyp());
|
||||
|
|
@ -1215,7 +1214,7 @@ public:
|
|||
iterateAndNextNull(nodep->valuep());
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstConsDynArray* nodep) override {
|
||||
void visit(AstConsDynArray* nodep) override {
|
||||
putbs(nodep->dtypep()->cType("", false, false));
|
||||
if (!nodep->lhsp()) {
|
||||
puts("()");
|
||||
|
|
@ -1230,7 +1229,7 @@ public:
|
|||
puts(")");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstConsQueue* nodep) override {
|
||||
void visit(AstConsQueue* nodep) override {
|
||||
putbs(nodep->dtypep()->cType("", false, false));
|
||||
if (!nodep->lhsp()) {
|
||||
puts("()");
|
||||
|
|
@ -1245,22 +1244,22 @@ public:
|
|||
puts(")");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCReset* nodep) override {
|
||||
void visit(AstCReset* nodep) override {
|
||||
AstVar* const varp = nodep->varrefp()->varp();
|
||||
emitVarReset(varp);
|
||||
}
|
||||
virtual void visit(AstExecGraph* nodep) override {
|
||||
void visit(AstExecGraph* nodep) override {
|
||||
// The location of the AstExecGraph within the containing AstCFunc is where we want to
|
||||
// invoke the graph and wait for it to complete. Emitting the children does just that.
|
||||
UASSERT_OBJ(!nodep->mTaskBodiesp(), nodep, "These should have been lowered");
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
virtual void visit(AstChangeDet* nodep) override { //
|
||||
void visit(AstChangeDet* nodep) override { //
|
||||
m_blkChangeDetVec.push_back(nodep);
|
||||
}
|
||||
|
||||
// Default
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
void visit(AstNode* nodep) override {
|
||||
puts(string("\n???? // ") + nodep->prettyTypeName() + "\n");
|
||||
iterateChildren(nodep);
|
||||
// LCOV_EXCL_START
|
||||
|
|
@ -1278,7 +1277,7 @@ public:
|
|||
m_trackText = trackText;
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~EmitCFunc() override = default;
|
||||
~EmitCFunc() override = default;
|
||||
};
|
||||
|
||||
#endif // guard
|
||||
|
|
|
|||
|
|
@ -24,12 +24,13 @@
|
|||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Internal EmitC implementation
|
||||
|
||||
class EmitCHeader final : public EmitCConstInit {
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
void decorateFirst(bool& first, const string& str) {
|
||||
if (first) {
|
||||
|
|
@ -326,7 +327,7 @@ class EmitCHeader final : public EmitCConstInit {
|
|||
// Close output file
|
||||
VL_DO_CLEAR(delete m_ofp, m_ofp = nullptr);
|
||||
}
|
||||
virtual ~EmitCHeader() override = default;
|
||||
~EmitCHeader() override = default;
|
||||
|
||||
public:
|
||||
static void main(const AstNodeModule* modp) { EmitCHeader emitCHeader(modp); }
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Visitor that gathers the headers required by an AstCFunc
|
||||
|
||||
|
|
@ -68,59 +70,59 @@ class EmitCGatherDependencies final : VNVisitor {
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstCCall* nodep) override {
|
||||
void visit(AstCCall* nodep) override {
|
||||
addSelfDependency(nodep->selfPointer(), nodep->funcp());
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
virtual void visit(AstCNew* nodep) override {
|
||||
void visit(AstCNew* nodep) override {
|
||||
addDTypeDependency(nodep->dtypep());
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
virtual void visit(AstCMethodCall* nodep) override {
|
||||
void visit(AstCMethodCall* nodep) override {
|
||||
addDTypeDependency(nodep->fromp()->dtypep());
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
virtual void visit(AstNewCopy* nodep) override {
|
||||
void visit(AstNewCopy* nodep) override {
|
||||
addDTypeDependency(nodep->dtypep());
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
virtual void visit(AstMemberSel* nodep) override {
|
||||
void visit(AstMemberSel* nodep) override {
|
||||
addDTypeDependency(nodep->fromp()->dtypep());
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeVarRef* nodep) override {
|
||||
void visit(AstNodeVarRef* nodep) override {
|
||||
addSelfDependency(nodep->selfPointer(), nodep->varp());
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
virtual void visit(AstCoverDecl* nodep) override {
|
||||
void visit(AstCoverDecl* nodep) override {
|
||||
addSymsDependency();
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
virtual void visit(AstCoverInc* nodep) override {
|
||||
void visit(AstCoverInc* nodep) override {
|
||||
addSymsDependency();
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
virtual void visit(AstDumpCtl* nodep) override {
|
||||
void visit(AstDumpCtl* nodep) override {
|
||||
addSymsDependency();
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
virtual void visit(AstScopeName* nodep) override {
|
||||
void visit(AstScopeName* nodep) override {
|
||||
addSymsDependency();
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
virtual void visit(AstPrintTimeScale* nodep) override {
|
||||
void visit(AstPrintTimeScale* nodep) override {
|
||||
addSymsDependency();
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
virtual void visit(AstTimeFormat* nodep) override {
|
||||
void visit(AstTimeFormat* nodep) override {
|
||||
addSymsDependency();
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeSimpleText* nodep) override {
|
||||
void visit(AstNodeSimpleText* nodep) override {
|
||||
if (nodep->text().find("vlSymsp") != string::npos) addSymsDependency();
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
virtual void visit(AstNode* nodep) override { iterateChildrenConst(nodep); }
|
||||
void visit(AstNode* nodep) override { iterateChildrenConst(nodep); }
|
||||
|
||||
// CONSTRUCTOR
|
||||
explicit EmitCGatherDependencies(AstCFunc* cfuncp) {
|
||||
|
|
@ -148,6 +150,7 @@ class EmitCImp final : EmitCFunc {
|
|||
const std::set<string>* m_requiredHeadersp; // Header files required by output file
|
||||
std::string m_subFileName; // substring added to output filenames
|
||||
V3UniqueNames m_uniqueNames; // For generating unique file names
|
||||
std::deque<AstCFile*>& m_cfilesr; // cfiles generated by this emit
|
||||
|
||||
// METHODS
|
||||
void openNextOutputFile(const std::set<string>& headers, const string& subFileName) {
|
||||
|
|
@ -160,7 +163,8 @@ class EmitCImp final : EmitCFunc {
|
|||
// Unfortunately we have some lint checks here, so we can't just skip processing.
|
||||
// We should move them to a different stage.
|
||||
const string filename = VL_DEV_NULL;
|
||||
newCFile(filename, /* slow: */ m_slow, /* source: */ true);
|
||||
m_cfilesr.push_back(
|
||||
newCFile(filename, /* slow: */ m_slow, /* source: */ true, /* add */ false));
|
||||
m_ofp = new V3OutCFile(filename);
|
||||
} else {
|
||||
string filename = v3Global.opt.makeDir() + "/" + prefixNameProtect(m_fileModp);
|
||||
|
|
@ -170,7 +174,8 @@ class EmitCImp final : EmitCFunc {
|
|||
}
|
||||
if (m_slow) filename += "__Slow";
|
||||
filename += ".cpp";
|
||||
newCFile(filename, /* slow: */ m_slow, /* source: */ true);
|
||||
m_cfilesr.push_back(
|
||||
newCFile(filename, /* slow: */ m_slow, /* source: */ true, /* add */ false));
|
||||
m_ofp = v3Global.opt.systemC() ? new V3OutScFile(filename) : new V3OutCFile(filename);
|
||||
}
|
||||
|
||||
|
|
@ -509,7 +514,7 @@ class EmitCImp final : EmitCFunc {
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
void visit(AstCFunc* nodep) override {
|
||||
if (splitNeeded()) {
|
||||
// Splitting file, so using parallel build.
|
||||
v3Global.useParallelBuild(true);
|
||||
|
|
@ -522,9 +527,10 @@ class EmitCImp final : EmitCFunc {
|
|||
EmitCFunc::visit(nodep);
|
||||
}
|
||||
|
||||
explicit EmitCImp(const AstNodeModule* modp, bool slow)
|
||||
explicit EmitCImp(const AstNodeModule* modp, bool slow, std::deque<AstCFile*>& cfilesr)
|
||||
: m_fileModp{modp}
|
||||
, m_slow{slow} {
|
||||
, m_slow{slow}
|
||||
, m_cfilesr{cfilesr} {
|
||||
UINFO(5, " Emitting implementation of " << prefixNameProtect(modp) << endl);
|
||||
|
||||
m_modp = modp;
|
||||
|
|
@ -540,10 +546,12 @@ class EmitCImp final : EmitCFunc {
|
|||
// Emit implementations of all AstCFunc
|
||||
emitCFuncImp(modp);
|
||||
}
|
||||
virtual ~EmitCImp() override = default;
|
||||
~EmitCImp() override = default;
|
||||
|
||||
public:
|
||||
static void main(const AstNodeModule* modp, bool slow) { EmitCImp{modp, slow}; }
|
||||
static void main(const AstNodeModule* modp, bool slow, std::deque<AstCFile*>& cfilesr) {
|
||||
EmitCImp{modp, slow, cfilesr};
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -551,14 +559,14 @@ public:
|
|||
|
||||
class EmitCTrace final : EmitCFunc {
|
||||
// NODE STATE/TYPES
|
||||
// Cleared on netlist
|
||||
// AstNode::user1() -> int. Enum number
|
||||
const VNUser1InUse m_inuser1;
|
||||
// None allowed to support threaded emitting
|
||||
|
||||
// MEMBERS
|
||||
const bool m_slow; // Making slow file
|
||||
int m_enumNum = 0; // Enumeration number (whole netlist)
|
||||
V3UniqueNames m_uniqueNames; // For generating unique file names
|
||||
std::unordered_map<AstNode*, int> m_enumNumMap; // EnumDType to enumeration number
|
||||
std::deque<AstCFile*>& m_cfilesr; // cfiles generated by this emit
|
||||
|
||||
// METHODS
|
||||
void openNextOutputFile() {
|
||||
|
|
@ -573,8 +581,9 @@ class EmitCTrace final : EmitCFunc {
|
|||
if (m_slow) filename += "__Slow";
|
||||
filename += ".cpp";
|
||||
|
||||
AstCFile* const cfilep = newCFile(filename, m_slow, true /*source*/);
|
||||
AstCFile* const cfilep = newCFile(filename, m_slow, true /*source*/, false /*add*/);
|
||||
cfilep->support(true);
|
||||
m_cfilesr.push_back(cfilep);
|
||||
|
||||
if (optSystemC()) {
|
||||
m_ofp = new V3OutScFile(filename);
|
||||
|
|
@ -710,10 +719,10 @@ class EmitCTrace final : EmitCFunc {
|
|||
// Skip over refs-to-refs, but stop before final ref so can get data type name
|
||||
// Alternatively back in V3Width we could push enum names from upper typedefs
|
||||
if (AstEnumDType* const enump = VN_CAST(nodep->skipRefToEnump(), EnumDType)) {
|
||||
int enumNum = enump->user1();
|
||||
int enumNum = m_enumNumMap[enump];
|
||||
if (!enumNum) {
|
||||
enumNum = ++m_enumNum;
|
||||
enump->user1(enumNum);
|
||||
m_enumNumMap[enump] = enumNum;
|
||||
int nvals = 0;
|
||||
puts("{\n");
|
||||
puts("const char* " + protect("__VenumItemNames") + "[]\n");
|
||||
|
|
@ -816,7 +825,7 @@ class EmitCTrace final : EmitCFunc {
|
|||
|
||||
// VISITORS
|
||||
using EmitCFunc::visit; // Suppress hidden overloaded virtual function warning
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
void visit(AstCFunc* nodep) override {
|
||||
if (!nodep->isTrace()) return;
|
||||
if (nodep->slow() != m_slow) return;
|
||||
|
||||
|
|
@ -831,17 +840,17 @@ class EmitCTrace final : EmitCFunc {
|
|||
|
||||
EmitCFunc::visit(nodep);
|
||||
}
|
||||
virtual void visit(AstTracePushNamePrefix* nodep) override {
|
||||
void visit(AstTracePushNamePrefix* nodep) override {
|
||||
puts("tracep->pushNamePrefix(");
|
||||
putsQuoted(VIdProtect::protectWordsIf(nodep->prefix(), nodep->protect()));
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstTracePopNamePrefix* nodep) override { //
|
||||
void visit(AstTracePopNamePrefix* nodep) override { //
|
||||
puts("tracep->popNamePrefix(");
|
||||
puts(cvtToStr(nodep->count()));
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstTraceDecl* nodep) override {
|
||||
void visit(AstTraceDecl* nodep) override {
|
||||
const int enumNum = emitTraceDeclDType(nodep->dtypep());
|
||||
if (nodep->arrayRange().ranged()) {
|
||||
puts("for (int i = 0; i < " + cvtToStr(nodep->arrayRange().elements()) + "; ++i) {\n");
|
||||
|
|
@ -852,7 +861,7 @@ class EmitCTrace final : EmitCFunc {
|
|||
puts("\n");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstTraceInc* nodep) override {
|
||||
void visit(AstTraceInc* nodep) override {
|
||||
if (nodep->declp()->arrayRange().ranged()) {
|
||||
// It traces faster if we unroll the loop
|
||||
for (int i = 0; i < nodep->declp()->arrayRange().elements(); i++) {
|
||||
|
|
@ -863,8 +872,9 @@ class EmitCTrace final : EmitCFunc {
|
|||
}
|
||||
}
|
||||
|
||||
explicit EmitCTrace(AstNodeModule* modp, bool slow)
|
||||
: m_slow{slow} {
|
||||
explicit EmitCTrace(AstNodeModule* modp, bool slow, std::deque<AstCFile*>& cfilesr)
|
||||
: m_slow{slow}
|
||||
, m_cfilesr{cfilesr} {
|
||||
m_modp = modp;
|
||||
// Open output file
|
||||
openNextOutputFile();
|
||||
|
|
@ -875,10 +885,12 @@ class EmitCTrace final : EmitCFunc {
|
|||
// Close output file
|
||||
VL_DO_CLEAR(delete m_ofp, m_ofp = nullptr);
|
||||
}
|
||||
virtual ~EmitCTrace() override = default;
|
||||
~EmitCTrace() override = default;
|
||||
|
||||
public:
|
||||
static void main(AstNodeModule* modp, bool slow) { EmitCTrace{modp, slow}; }
|
||||
static void main(AstNodeModule* modp, bool slow, std::deque<AstCFile*>& cfilesr) {
|
||||
EmitCTrace{modp, slow, cfilesr};
|
||||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -888,19 +900,27 @@ void V3EmitC::emitcImp() {
|
|||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
// Make parent module pointers available.
|
||||
const EmitCParentModule emitCParentModule;
|
||||
std::list<std::deque<AstCFile*>> cfiles;
|
||||
|
||||
// Process each module in turn
|
||||
for (const AstNode* nodep = v3Global.rootp()->modulesp(); nodep; nodep = nodep->nextp()) {
|
||||
if (VN_IS(nodep, Class)) continue; // Imped with ClassPackage
|
||||
const AstNodeModule* const modp = VN_AS(nodep, NodeModule);
|
||||
EmitCImp::main(modp, /* slow: */ true);
|
||||
EmitCImp::main(modp, /* slow: */ false);
|
||||
cfiles.emplace_back();
|
||||
EmitCImp::main(modp, /* slow: */ true, cfiles.back());
|
||||
cfiles.emplace_back();
|
||||
EmitCImp::main(modp, /* slow: */ false, cfiles.back());
|
||||
}
|
||||
|
||||
// Emit trace routines (currently they can only exist in the top module)
|
||||
if (v3Global.opt.trace() && !v3Global.opt.lintOnly()) {
|
||||
EmitCTrace::main(v3Global.rootp()->topModulep(), /* slow: */ true);
|
||||
EmitCTrace::main(v3Global.rootp()->topModulep(), /* slow: */ false);
|
||||
cfiles.emplace_back();
|
||||
EmitCTrace::main(v3Global.rootp()->topModulep(), /* slow: */ true, cfiles.back());
|
||||
cfiles.emplace_back();
|
||||
EmitCTrace::main(v3Global.rootp()->topModulep(), /* slow: */ false, cfiles.back());
|
||||
}
|
||||
for (const auto& collr : cfiles) {
|
||||
for (const auto cfilep : collr) v3Global.rootp()->addFilesp(cfilep);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#include <map>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
|
||||
class EmitCInlines final : EmitCBaseVisitor {
|
||||
|
|
@ -32,18 +34,18 @@ class EmitCInlines final : EmitCBaseVisitor {
|
|||
// METHODS
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstCNew* nodep) override {
|
||||
void visit(AstCNew* nodep) override {
|
||||
if (v3Global.opt.savable())
|
||||
v3warn(E_UNSUPPORTED, "Unsupported: --savable with dynamic new");
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstDumpCtl* nodep) override {
|
||||
void visit(AstDumpCtl* nodep) override {
|
||||
if (v3Global.opt.trace()) v3Global.needTraceDumper(true);
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
//---------------------------------------
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
explicit EmitCInlines(AstNetlist* nodep) { iterate(nodep); }
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
#include <map>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
|
||||
class EmitCMain final : EmitCBaseVisitor {
|
||||
|
|
@ -32,7 +34,7 @@ class EmitCMain final : EmitCBaseVisitor {
|
|||
|
||||
// VISITORS
|
||||
// This visitor doesn't really iterate, but exist to appease base class
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); } // LCOV_EXCL_LINE
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); } // LCOV_EXCL_LINE
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
|
|
|
|||
|
|
@ -26,13 +26,14 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
//######################################################################
|
||||
// Emit statements
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
// ######################################################################
|
||||
// Emit statements
|
||||
|
||||
class CMakeEmitter final {
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
// STATIC FUNCTIONS
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
class EmitCModel final : public EmitCFunc {
|
||||
// TYPES
|
||||
using CFuncVector = std::vector<const AstCFunc*>;
|
||||
|
|
@ -34,8 +36,6 @@ class EmitCModel final : public EmitCFunc {
|
|||
V3UniqueNames m_uniqueNames; // For generating unique file names
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC;
|
||||
|
||||
CFuncVector findFuncps(std::function<bool(const AstCFunc*)> cb) {
|
||||
CFuncVector funcps;
|
||||
for (AstNode* nodep = m_modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
|
|
@ -190,7 +190,7 @@ class EmitCModel final : public EmitCFunc {
|
|||
+ "C* tfp, int levels, int options = 0);\n");
|
||||
if (optSystemC()) {
|
||||
puts("/// SC tracing; avoid overloaded virtual function lint warning\n");
|
||||
puts("virtual void trace(sc_trace_file* tfp) const override { "
|
||||
puts("void trace(sc_trace_file* tfp) const override { "
|
||||
"::sc_core::sc_module::trace(tfp); }\n");
|
||||
}
|
||||
}
|
||||
|
|
@ -552,6 +552,11 @@ class EmitCModel final : public EmitCFunc {
|
|||
"elaboration.\");\n");
|
||||
puts(/**/ "}");
|
||||
}
|
||||
puts(/**/ "if (tfp->isOpen()) {\n");
|
||||
puts(/****/ "vl_fatal(__FILE__, __LINE__, __FILE__,\"'" + topClassName()
|
||||
+ +"::trace()' shall not be called after '" + v3Global.opt.traceClassBase()
|
||||
+ "C::open()'.\");\n");
|
||||
puts(/**/ "}\n");
|
||||
puts(/**/ "if (false && levels && options) {} // Prevent unused\n");
|
||||
puts(/**/ "tfp->spTrace()->addModel(this);\n");
|
||||
puts(/**/ "tfp->spTrace()->addInitCb(&" + protect("trace_init") + ", &(vlSymsp->TOP));\n");
|
||||
|
|
@ -565,7 +570,7 @@ class EmitCModel final : public EmitCFunc {
|
|||
// Some hackery to locate handle__V for trace_init_task
|
||||
// Considered a pragma on the handle, but that still doesn't help us attach it here
|
||||
string handle = funcp->name();
|
||||
const size_t wr_len = strlen("__Vdpiimwrap_");
|
||||
const size_t wr_len = std::strlen("__Vdpiimwrap_");
|
||||
UASSERT_OBJ(handle.substr(0, wr_len) == "__Vdpiimwrap_", funcp,
|
||||
"Strange trace_init_task function name");
|
||||
handle = "vlSymsp->TOP." + handle.substr(wr_len);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Symbol table emitting
|
||||
|
||||
|
|
@ -211,7 +213,7 @@ class EmitCSyms final : EmitCBaseVisitor {
|
|||
const string::size_type dpos = whole.rfind("__DOT__");
|
||||
if (dpos != string::npos) {
|
||||
scpName = whole.substr(0, dpos);
|
||||
varBase = whole.substr(dpos + strlen("__DOT__"));
|
||||
varBase = whole.substr(dpos + std::strlen("__DOT__"));
|
||||
} else {
|
||||
varBase = whole;
|
||||
}
|
||||
|
|
@ -258,7 +260,7 @@ class EmitCSyms final : EmitCBaseVisitor {
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNetlist* nodep) override {
|
||||
void visit(AstNetlist* nodep) override {
|
||||
// Collect list of scopes
|
||||
iterateChildren(nodep);
|
||||
varsExpand();
|
||||
|
|
@ -280,8 +282,8 @@ class EmitCSyms final : EmitCBaseVisitor {
|
|||
if (!m_dpiHdrOnly) emitDpiImp();
|
||||
}
|
||||
}
|
||||
virtual void visit(AstConstPool* nodep) override {} // Ignore
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstConstPool* nodep) override {} // Ignore
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
nameCheck(nodep);
|
||||
VL_RESTORER(m_modp);
|
||||
{
|
||||
|
|
@ -289,7 +291,7 @@ class EmitCSyms final : EmitCBaseVisitor {
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCellInline* nodep) override {
|
||||
void visit(AstCellInline* nodep) override {
|
||||
if (v3Global.opt.vpi()) {
|
||||
const string type
|
||||
= (nodep->origModName() == "__BEGIN__") ? "SCOPE_OTHER" : "SCOPE_MODULE";
|
||||
|
|
@ -300,7 +302,7 @@ class EmitCSyms final : EmitCBaseVisitor {
|
|||
std::make_pair(name, ScopeData(scopeSymString(name), name_dedot, timeunit, type)));
|
||||
}
|
||||
}
|
||||
virtual void visit(AstScope* nodep) override {
|
||||
void visit(AstScope* nodep) override {
|
||||
if (VN_IS(m_modp, Class)) return; // The ClassPackage is what is visible
|
||||
nameCheck(nodep);
|
||||
|
||||
|
|
@ -315,7 +317,7 @@ class EmitCSyms final : EmitCBaseVisitor {
|
|||
timeunit, type)));
|
||||
}
|
||||
}
|
||||
virtual void visit(AstScopeName* nodep) override {
|
||||
void visit(AstScopeName* nodep) override {
|
||||
const string name = nodep->scopeSymName();
|
||||
// UINFO(9,"scnameins sp "<<nodep->name()<<" sp "<<nodep->scopePrettySymName()
|
||||
// <<" ss"<<name<<endl);
|
||||
|
|
@ -337,19 +339,19 @@ class EmitCSyms final : EmitCBaseVisitor {
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVar* nodep) override {
|
||||
void visit(AstVar* nodep) override {
|
||||
nameCheck(nodep);
|
||||
iterateChildren(nodep);
|
||||
if (nodep->isSigUserRdPublic() && !m_cfuncp)
|
||||
m_modVars.emplace_back(std::make_pair(m_modp, nodep));
|
||||
}
|
||||
virtual void visit(AstCoverDecl* nodep) override {
|
||||
void visit(AstCoverDecl* nodep) override {
|
||||
// Assign numbers to all bins, so we know how big of an array to use
|
||||
if (!nodep->dataDeclNullp()) { // else duplicate we don't need code for
|
||||
nodep->binNum(m_coverBins++);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCFunc* nodep) override {
|
||||
void visit(AstCFunc* nodep) override {
|
||||
nameCheck(nodep);
|
||||
if (nodep->dpiImportPrototype() || nodep->dpiExportDispatcher()) m_dpis.push_back(nodep);
|
||||
VL_RESTORER(m_cfuncp);
|
||||
|
|
@ -360,8 +362,8 @@ class EmitCSyms final : EmitCBaseVisitor {
|
|||
}
|
||||
|
||||
//---------------------------------------
|
||||
virtual void visit(AstConst*) override {}
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstConst*) override {}
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
explicit EmitCSyms(AstNetlist* nodep, bool dpiHdrOnly)
|
||||
|
|
|
|||
|
|
@ -24,13 +24,14 @@
|
|||
#include "V3HierBlock.h"
|
||||
#include "V3Os.h"
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Emit statements and math operators
|
||||
|
||||
class EmitMk final {
|
||||
public:
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
void putMakeClassEntry(V3OutMkFile& of, const string& name) {
|
||||
of.puts("\t" + V3Os::filenameNonDirExt(name) + " \\\n");
|
||||
|
|
@ -292,7 +293,7 @@ class EmitMkHierVerilation final {
|
|||
of.puts("# Verilation of hierarchical blocks are executed in this directory\n");
|
||||
of.puts("VM_HIER_RUN_DIR := " + cwd + "\n");
|
||||
of.puts("# Common options for hierarchical blocks\n");
|
||||
const string fullpath_bin = V3Os::filenameRealPath(v3Global.opt.bin());
|
||||
const string fullpath_bin = V3Os::filenameRealPath(v3Global.opt.buildDepBin());
|
||||
const string verilator_wrapper = V3Os::filenameDir(fullpath_bin) + "/verilator";
|
||||
of.puts("VM_HIER_VERILATOR := " + verilator_wrapper + "\n");
|
||||
of.puts("VM_HIER_INPUT_FILES := \\\n");
|
||||
|
|
@ -399,7 +400,6 @@ public:
|
|||
V3OutMkFile of(m_makefile);
|
||||
emit(of);
|
||||
}
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
265
src/V3EmitV.cpp
265
src/V3EmitV.cpp
|
|
@ -26,6 +26,8 @@
|
|||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Emit statements and math operators
|
||||
|
||||
|
|
@ -36,7 +38,6 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
AstSenTree* m_sensesp; // Domain for printing one a ALWAYS under a ACTIVE
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
virtual void puts(const string& str) = 0;
|
||||
virtual void putbs(const string& str) = 0;
|
||||
|
|
@ -53,14 +54,14 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNetlist* nodep) override { iterateAndNextConstNull(nodep->modulesp()); }
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstNetlist* nodep) override { iterateAndNextConstNull(nodep->modulesp()); }
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
putfs(nodep, nodep->verilogKwd() + " " + prefixNameProtect(nodep) + ";\n");
|
||||
iterateChildrenConst(nodep);
|
||||
putqs(nodep, "end" + nodep->verilogKwd() + "\n");
|
||||
}
|
||||
virtual void visit(AstPort* nodep) override {}
|
||||
virtual void visit(AstNodeFTask* nodep) override {
|
||||
void visit(AstPort* nodep) override {}
|
||||
void visit(AstNodeFTask* nodep) override {
|
||||
putfs(nodep, nodep->isFunction() ? "function" : "task");
|
||||
puts(" ");
|
||||
puts(nodep->prettyName());
|
||||
|
|
@ -70,7 +71,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
putfs(nodep, nodep->isFunction() ? "endfunction\n" : "endtask\n");
|
||||
}
|
||||
|
||||
virtual void visit(AstBegin* nodep) override {
|
||||
void visit(AstBegin* nodep) override {
|
||||
if (nodep->name() == "") {
|
||||
putbs("begin\n");
|
||||
} else {
|
||||
|
|
@ -79,7 +80,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
iterateChildrenConst(nodep);
|
||||
puts("end\n");
|
||||
}
|
||||
virtual void visit(AstFork* nodep) override {
|
||||
void visit(AstFork* nodep) override {
|
||||
if (nodep->name() == "") {
|
||||
putbs("fork\n");
|
||||
} else {
|
||||
|
|
@ -89,19 +90,19 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
puts(nodep->joinType().verilogKwd());
|
||||
puts("\n");
|
||||
}
|
||||
virtual void visit(AstFinal* nodep) override {
|
||||
void visit(AstFinal* nodep) override {
|
||||
putfs(nodep, "final begin\n");
|
||||
iterateChildrenConst(nodep);
|
||||
putqs(nodep, "end\n");
|
||||
}
|
||||
virtual void visit(AstInitial* nodep) override {
|
||||
void visit(AstInitial* nodep) override {
|
||||
putfs(nodep, "initial begin\n");
|
||||
iterateChildrenConst(nodep);
|
||||
putqs(nodep, "end\n");
|
||||
}
|
||||
virtual void visit(AstInitialAutomatic* nodep) override { iterateChildrenConst(nodep); }
|
||||
virtual void visit(AstInitialStatic* nodep) override { iterateChildrenConst(nodep); }
|
||||
virtual void visit(AstAlways* nodep) override {
|
||||
void visit(AstInitialAutomatic* nodep) override { iterateChildrenConst(nodep); }
|
||||
void visit(AstInitialStatic* nodep) override { iterateChildrenConst(nodep); }
|
||||
void visit(AstAlways* nodep) override {
|
||||
putfs(nodep, "always ");
|
||||
if (m_sensesp) {
|
||||
iterateAndNextConstNull(m_sensesp);
|
||||
|
|
@ -110,10 +111,10 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
iterateAndNextConstNull(nodep->sensesp());
|
||||
}
|
||||
putbs(" begin\n");
|
||||
iterateAndNextConstNull(nodep->bodysp());
|
||||
iterateAndNextConstNull(nodep->stmtsp());
|
||||
putqs(nodep, "end\n");
|
||||
}
|
||||
virtual void visit(AstAlwaysPublic* nodep) override {
|
||||
void visit(AstAlwaysPublic* nodep) override {
|
||||
putfs(nodep, "/*verilator public_flat_rw ");
|
||||
if (m_sensesp) {
|
||||
iterateAndNextConstNull(m_sensesp);
|
||||
|
|
@ -122,46 +123,46 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
iterateAndNextConstNull(nodep->sensesp());
|
||||
}
|
||||
putqs(nodep, " ");
|
||||
iterateAndNextConstNull(nodep->bodysp());
|
||||
iterateAndNextConstNull(nodep->stmtsp());
|
||||
putqs(nodep, "*/\n");
|
||||
}
|
||||
virtual void visit(AstNodeAssign* nodep) override {
|
||||
void visit(AstNodeAssign* nodep) override {
|
||||
if (VN_IS(nodep, AssignForce)) puts("force ");
|
||||
iterateAndNextConstNull(nodep->lhsp());
|
||||
putfs(nodep, " " + nodep->verilogKwd() + " ");
|
||||
iterateAndNextConstNull(nodep->rhsp());
|
||||
if (!m_suppressSemi) puts(";\n");
|
||||
}
|
||||
virtual void visit(AstAssignDly* nodep) override {
|
||||
void visit(AstAssignDly* nodep) override {
|
||||
iterateAndNextConstNull(nodep->lhsp());
|
||||
putfs(nodep, " <= ");
|
||||
iterateAndNextConstNull(nodep->rhsp());
|
||||
puts(";\n");
|
||||
}
|
||||
virtual void visit(AstAssignAlias* nodep) override {
|
||||
void visit(AstAssignAlias* nodep) override {
|
||||
putbs("alias ");
|
||||
iterateAndNextConstNull(nodep->lhsp());
|
||||
putfs(nodep, " = ");
|
||||
iterateAndNextConstNull(nodep->rhsp());
|
||||
if (!m_suppressSemi) puts(";\n");
|
||||
}
|
||||
virtual void visit(AstAssignW* nodep) override {
|
||||
void visit(AstAssignW* nodep) override {
|
||||
putfs(nodep, "assign ");
|
||||
iterateAndNextConstNull(nodep->lhsp());
|
||||
putbs(" = ");
|
||||
iterateAndNextConstNull(nodep->rhsp());
|
||||
if (!m_suppressSemi) puts(";\n");
|
||||
}
|
||||
virtual void visit(AstRelease* nodep) override {
|
||||
void visit(AstRelease* nodep) override {
|
||||
puts("release ");
|
||||
iterateAndNextConstNull(nodep->lhsp());
|
||||
if (!m_suppressSemi) puts(";\n");
|
||||
}
|
||||
virtual void visit(AstBreak*) override {
|
||||
void visit(AstBreak*) override {
|
||||
putbs("break");
|
||||
if (!m_suppressSemi) puts(";\n");
|
||||
}
|
||||
virtual void visit(AstSenTree* nodep) override {
|
||||
void visit(AstSenTree* nodep) override {
|
||||
// AstSenItem is called for dumping in isolation by V3Order
|
||||
putfs(nodep, "@(");
|
||||
for (AstNode* expp = nodep->sensesp(); expp; expp = expp->nextp()) {
|
||||
|
|
@ -170,13 +171,13 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
}
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstSenItem* nodep) override {
|
||||
void visit(AstSenItem* nodep) override {
|
||||
putfs(nodep, "");
|
||||
puts(nodep->edgeType().verilogKwd());
|
||||
if (nodep->sensp()) puts(" ");
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeCase* nodep) override {
|
||||
void visit(AstNodeCase* nodep) override {
|
||||
putfs(nodep, "");
|
||||
if (const AstCase* const casep = VN_CAST(nodep, Case)) {
|
||||
if (casep->priorityPragma()) puts("priority ");
|
||||
|
|
@ -197,27 +198,27 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
iterateAndNextConstNull(nodep->itemsp());
|
||||
putqs(nodep, "endcase\n");
|
||||
}
|
||||
virtual void visit(AstCaseItem* nodep) override {
|
||||
void visit(AstCaseItem* nodep) override {
|
||||
if (nodep->condsp()) {
|
||||
iterateAndNextConstNull(nodep->condsp());
|
||||
} else {
|
||||
putbs("default");
|
||||
}
|
||||
putfs(nodep, ": begin ");
|
||||
iterateAndNextConstNull(nodep->bodysp());
|
||||
iterateAndNextConstNull(nodep->stmtsp());
|
||||
putqs(nodep, "end\n");
|
||||
}
|
||||
virtual void visit(AstComment* nodep) override {
|
||||
void visit(AstComment* nodep) override {
|
||||
puts(std::string{"// "} + nodep->name() + "\n");
|
||||
iterateChildrenConst(nodep);
|
||||
}
|
||||
virtual void visit(AstContinue*) override {
|
||||
void visit(AstContinue*) override {
|
||||
putbs("continue");
|
||||
if (!m_suppressSemi) puts(";\n");
|
||||
}
|
||||
virtual void visit(AstCoverDecl*) override {} // N/A
|
||||
virtual void visit(AstCoverInc*) override {} // N/A
|
||||
virtual void visit(AstCoverToggle*) override {} // N/A
|
||||
void visit(AstCoverDecl*) override {} // N/A
|
||||
void visit(AstCoverInc*) override {} // N/A
|
||||
void visit(AstCoverToggle*) override {} // N/A
|
||||
|
||||
void visitNodeDisplay(AstNode* nodep, AstNode* fileOrStrgp, const string& text,
|
||||
AstNode* exprsp) {
|
||||
|
|
@ -234,26 +235,26 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
}
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstDisable* nodep) override { putbs("disable " + nodep->name() + ";\n"); }
|
||||
virtual void visit(AstDisplay* nodep) override {
|
||||
void visit(AstDisable* nodep) override { putbs("disable " + nodep->name() + ";\n"); }
|
||||
void visit(AstDisplay* nodep) override {
|
||||
visitNodeDisplay(nodep, nodep->filep(), nodep->fmtp()->text(), nodep->fmtp()->exprsp());
|
||||
}
|
||||
virtual void visit(AstElabDisplay* nodep) override {
|
||||
void visit(AstElabDisplay* nodep) override {
|
||||
visitNodeDisplay(nodep, nullptr, nodep->fmtp()->text(), nodep->fmtp()->exprsp());
|
||||
}
|
||||
virtual void visit(AstFScanF* nodep) override {
|
||||
void visit(AstFScanF* nodep) override {
|
||||
visitNodeDisplay(nodep, nodep->filep(), nodep->text(), nodep->exprsp());
|
||||
}
|
||||
virtual void visit(AstSScanF* nodep) override {
|
||||
void visit(AstSScanF* nodep) override {
|
||||
visitNodeDisplay(nodep, nodep->fromp(), nodep->text(), nodep->exprsp());
|
||||
}
|
||||
virtual void visit(AstSFormat* nodep) override {
|
||||
void visit(AstSFormat* nodep) override {
|
||||
visitNodeDisplay(nodep, nodep->lhsp(), nodep->fmtp()->text(), nodep->fmtp()->exprsp());
|
||||
}
|
||||
virtual void visit(AstSFormatF* nodep) override {
|
||||
void visit(AstSFormatF* nodep) override {
|
||||
visitNodeDisplay(nodep, nullptr, nodep->text(), nodep->exprsp());
|
||||
}
|
||||
virtual void visit(AstFOpen* nodep) override {
|
||||
void visit(AstFOpen* nodep) override {
|
||||
putfs(nodep, nodep->verilogKwd());
|
||||
putbs("(");
|
||||
iterateAndNextConstNull(nodep->filenamep());
|
||||
|
|
@ -261,36 +262,34 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
iterateAndNextConstNull(nodep->modep());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstFOpenMcd* nodep) override {
|
||||
void visit(AstFOpenMcd* nodep) override {
|
||||
putfs(nodep, nodep->verilogKwd());
|
||||
putbs("(");
|
||||
iterateAndNextConstNull(nodep->filenamep());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstFClose* nodep) override {
|
||||
void visit(AstFClose* nodep) override {
|
||||
putfs(nodep, nodep->verilogKwd());
|
||||
putbs("(");
|
||||
if (nodep->filep()) iterateAndNextConstNull(nodep->filep());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstFFlush* nodep) override {
|
||||
void visit(AstFFlush* nodep) override {
|
||||
putfs(nodep, nodep->verilogKwd());
|
||||
putbs("(");
|
||||
if (nodep->filep()) iterateAndNextConstNull(nodep->filep());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstJumpBlock* nodep) override {
|
||||
void visit(AstJumpBlock* nodep) override {
|
||||
putbs("begin : label" + cvtToStr(nodep->labelNum()) + "\n");
|
||||
if (nodep->stmtsp()) iterateAndNextConstNull(nodep->stmtsp());
|
||||
puts("end\n");
|
||||
}
|
||||
virtual void visit(AstJumpGo* nodep) override {
|
||||
void visit(AstJumpGo* nodep) override {
|
||||
putbs("disable label" + cvtToStr(nodep->labelp()->blockp()->labelNum()) + ";\n");
|
||||
}
|
||||
virtual void visit(AstJumpLabel* nodep) override {
|
||||
putbs("// " + cvtToStr(nodep->blockp()) + ":\n");
|
||||
}
|
||||
virtual void visit(AstNodeReadWriteMem* nodep) override {
|
||||
void visit(AstJumpLabel* nodep) override { putbs("// " + cvtToStr(nodep->blockp()) + ":\n"); }
|
||||
void visit(AstNodeReadWriteMem* nodep) override {
|
||||
putfs(nodep, nodep->verilogKwd());
|
||||
putbs("(");
|
||||
if (nodep->filenamep()) iterateAndNextConstNull(nodep->filenamep());
|
||||
|
|
@ -306,17 +305,17 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
}
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstSysFuncAsTask* nodep) override {
|
||||
void visit(AstSysFuncAsTask* nodep) override {
|
||||
iterateAndNextConstNull(nodep->lhsp());
|
||||
puts(";\n");
|
||||
}
|
||||
virtual void visit(AstSysIgnore* nodep) override {
|
||||
void visit(AstSysIgnore* nodep) override {
|
||||
putfs(nodep, nodep->verilogKwd());
|
||||
putbs("(");
|
||||
iterateAndNextConstNull(nodep->exprsp());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstNodeFor* nodep) override {
|
||||
void visit(AstNodeFor* nodep) override {
|
||||
putfs(nodep, "for (");
|
||||
{
|
||||
VL_RESTORER(m_suppressSemi);
|
||||
|
|
@ -328,27 +327,27 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
iterateAndNextConstNull(nodep->incsp());
|
||||
}
|
||||
puts(") begin\n");
|
||||
iterateAndNextConstNull(nodep->bodysp());
|
||||
iterateAndNextConstNull(nodep->stmtsp());
|
||||
putqs(nodep, "end\n");
|
||||
}
|
||||
virtual void visit(AstRepeat* nodep) override {
|
||||
void visit(AstRepeat* nodep) override {
|
||||
putfs(nodep, "repeat (");
|
||||
iterateAndNextConstNull(nodep->countp());
|
||||
puts(") begin\n");
|
||||
iterateAndNextConstNull(nodep->bodysp());
|
||||
iterateAndNextConstNull(nodep->stmtsp());
|
||||
putfs(nodep, "end\n");
|
||||
}
|
||||
virtual void visit(AstWhile* nodep) override {
|
||||
void visit(AstWhile* nodep) override {
|
||||
iterateAndNextConstNull(nodep->precondsp());
|
||||
putfs(nodep, "while (");
|
||||
iterateAndNextConstNull(nodep->condp());
|
||||
puts(") begin\n");
|
||||
iterateAndNextConstNull(nodep->bodysp());
|
||||
iterateAndNextConstNull(nodep->stmtsp());
|
||||
iterateAndNextConstNull(nodep->incsp());
|
||||
iterateAndNextConstNull(nodep->precondsp()); // Need to recompute before next loop
|
||||
putfs(nodep, "end\n");
|
||||
}
|
||||
virtual void visit(AstNodeIf* nodep) override {
|
||||
void visit(AstNodeIf* nodep) override {
|
||||
putfs(nodep, "");
|
||||
if (const AstIf* const ifp = VN_CAST(nodep, If)) {
|
||||
if (ifp->priorityPragma()) puts("priority ");
|
||||
|
|
@ -358,7 +357,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
puts("if (");
|
||||
iterateAndNextConstNull(nodep->condp());
|
||||
puts(") begin\n");
|
||||
iterateAndNextConstNull(nodep->ifsp());
|
||||
iterateAndNextConstNull(nodep->thensp());
|
||||
if (nodep->elsesp()) {
|
||||
putqs(nodep, "end\n");
|
||||
putqs(nodep, "else begin\n");
|
||||
|
|
@ -366,7 +365,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
}
|
||||
putqs(nodep, "end\n");
|
||||
}
|
||||
virtual void visit(AstPast* nodep) override {
|
||||
void visit(AstPast* nodep) override {
|
||||
putfs(nodep, "$past(");
|
||||
iterateAndNextConstNull(nodep->exprp());
|
||||
if (nodep->ticksp()) {
|
||||
|
|
@ -375,21 +374,21 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
}
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstReturn* nodep) override {
|
||||
void visit(AstReturn* nodep) override {
|
||||
putfs(nodep, "return ");
|
||||
iterateAndNextConstNull(nodep->lhsp());
|
||||
puts(";\n");
|
||||
}
|
||||
virtual void visit(AstStop* nodep) override { putfs(nodep, "$stop;\n"); }
|
||||
virtual void visit(AstFinish* nodep) override { putfs(nodep, "$finish;\n"); }
|
||||
virtual void visit(AstNodeSimpleText* nodep) override {
|
||||
void visit(AstStop* nodep) override { putfs(nodep, "$stop;\n"); }
|
||||
void visit(AstFinish* nodep) override { putfs(nodep, "$finish;\n"); }
|
||||
void visit(AstNodeSimpleText* nodep) override {
|
||||
if (nodep->tracking() || m_trackText) {
|
||||
puts(nodep->text());
|
||||
} else {
|
||||
putsNoTracking(nodep->text());
|
||||
}
|
||||
}
|
||||
virtual void visit(AstTextBlock* nodep) override {
|
||||
void visit(AstTextBlock* nodep) override {
|
||||
visit(static_cast<AstNodeSimpleText*>(nodep));
|
||||
{
|
||||
VL_RESTORER(m_suppressSemi);
|
||||
|
|
@ -400,25 +399,25 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstScopeName* nodep) override {}
|
||||
virtual void visit(AstCStmt* nodep) override {
|
||||
void visit(AstScopeName* nodep) override {}
|
||||
void visit(AstCStmt* nodep) override {
|
||||
putfs(nodep, "$_CSTMT(");
|
||||
iterateAndNextConstNull(nodep->bodysp());
|
||||
iterateAndNextConstNull(nodep->exprsp());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstCMath* nodep) override {
|
||||
void visit(AstCMath* nodep) override {
|
||||
putfs(nodep, "$_CMATH(");
|
||||
iterateAndNextConstNull(nodep->bodysp());
|
||||
iterateAndNextConstNull(nodep->exprsp());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstUCStmt* nodep) override {
|
||||
void visit(AstUCStmt* nodep) override {
|
||||
putfs(nodep, "$c(");
|
||||
iterateAndNextConstNull(nodep->bodysp());
|
||||
iterateAndNextConstNull(nodep->exprsp());
|
||||
puts(");\n");
|
||||
}
|
||||
virtual void visit(AstUCFunc* nodep) override {
|
||||
void visit(AstUCFunc* nodep) override {
|
||||
putfs(nodep, "$c(");
|
||||
iterateAndNextConstNull(nodep->bodysp());
|
||||
iterateAndNextConstNull(nodep->exprsp());
|
||||
puts(")");
|
||||
}
|
||||
|
||||
|
|
@ -481,25 +480,23 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeTermop* nodep) override {
|
||||
emitVerilogFormat(nodep, nodep->emitVerilog());
|
||||
}
|
||||
virtual void visit(AstNodeUniop* nodep) override {
|
||||
void visit(AstNodeTermop* nodep) override { emitVerilogFormat(nodep, nodep->emitVerilog()); }
|
||||
void visit(AstNodeUniop* nodep) override {
|
||||
emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp());
|
||||
}
|
||||
virtual void visit(AstNodeBiop* nodep) override {
|
||||
void visit(AstNodeBiop* nodep) override {
|
||||
emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp(), nodep->rhsp());
|
||||
}
|
||||
virtual void visit(AstNodeTriop* nodep) override {
|
||||
void visit(AstNodeTriop* nodep) override {
|
||||
emitVerilogFormat(nodep, nodep->emitVerilog(), nodep->lhsp(), nodep->rhsp(),
|
||||
nodep->thsp());
|
||||
}
|
||||
virtual void visit(AstMemberSel* nodep) override {
|
||||
void visit(AstMemberSel* nodep) override {
|
||||
iterate(nodep->fromp());
|
||||
puts(".");
|
||||
puts(nodep->prettyName());
|
||||
}
|
||||
virtual void visit(AstAttrOf* nodep) override {
|
||||
void visit(AstAttrOf* nodep) override {
|
||||
putfs(nodep, "$_ATTROF(");
|
||||
iterateAndNextConstNull(nodep->fromp());
|
||||
if (nodep->dimp()) {
|
||||
|
|
@ -508,7 +505,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
}
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstInitArray* nodep) override {
|
||||
void visit(AstInitArray* nodep) override {
|
||||
putfs(nodep, "'{");
|
||||
int comma = 0;
|
||||
const auto& mapr = nodep->map();
|
||||
|
|
@ -521,16 +518,16 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
}
|
||||
puts("}");
|
||||
}
|
||||
virtual void visit(AstNodeCond* nodep) override {
|
||||
void visit(AstNodeCond* nodep) override {
|
||||
putbs("(");
|
||||
iterateAndNextConstNull(nodep->condp());
|
||||
putfs(nodep, " ? ");
|
||||
iterateAndNextConstNull(nodep->expr1p());
|
||||
iterateAndNextConstNull(nodep->thenp());
|
||||
putbs(" : ");
|
||||
iterateAndNextConstNull(nodep->expr2p());
|
||||
iterateAndNextConstNull(nodep->elsep());
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstRange* nodep) override {
|
||||
void visit(AstRange* nodep) override {
|
||||
puts("[");
|
||||
if (VN_IS(nodep->leftp(), Const) && VN_IS(nodep->rightp(), Const)) {
|
||||
// Looks nicer if we print [1:0] rather than [32'sh1:32sh0]
|
||||
|
|
@ -545,7 +542,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
puts("]");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstSel* nodep) override {
|
||||
void visit(AstSel* nodep) override {
|
||||
iterateAndNextConstNull(nodep->fromp());
|
||||
puts("[");
|
||||
if (VN_IS(nodep->lsbp(), Const)) {
|
||||
|
|
@ -569,18 +566,18 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
}
|
||||
puts("]");
|
||||
}
|
||||
virtual void visit(AstSliceSel* nodep) override {
|
||||
void visit(AstSliceSel* nodep) override {
|
||||
iterateAndNextConstNull(nodep->fromp());
|
||||
puts(cvtToStr(nodep->declRange()));
|
||||
}
|
||||
virtual void visit(AstTypedef* nodep) override {
|
||||
void visit(AstTypedef* nodep) override {
|
||||
putfs(nodep, "typedef ");
|
||||
iterateAndNextConstNull(nodep->dtypep());
|
||||
puts(" ");
|
||||
puts(nodep->prettyName());
|
||||
puts(";\n");
|
||||
}
|
||||
virtual void visit(AstBasicDType* nodep) override {
|
||||
void visit(AstBasicDType* nodep) override {
|
||||
if (nodep->isSigned()) putfs(nodep, "signed ");
|
||||
putfs(nodep, nodep->prettyName());
|
||||
if (nodep->rangep()) {
|
||||
|
|
@ -593,15 +590,15 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
puts(":0] ");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstConstDType* nodep) override {
|
||||
void visit(AstConstDType* nodep) override {
|
||||
putfs(nodep, "const ");
|
||||
iterate(nodep->subDTypep());
|
||||
}
|
||||
virtual void visit(AstNodeArrayDType* nodep) override {
|
||||
void visit(AstNodeArrayDType* nodep) override {
|
||||
iterate(nodep->subDTypep());
|
||||
iterateAndNextConstNull(nodep->rangep());
|
||||
}
|
||||
virtual void visit(AstNodeUOrStructDType* nodep) override {
|
||||
void visit(AstNodeUOrStructDType* nodep) override {
|
||||
puts(nodep->verilogKwd() + " ");
|
||||
if (nodep->packed()) puts("packed ");
|
||||
puts("\n");
|
||||
|
|
@ -609,12 +606,12 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
iterateAndNextConstNull(nodep->membersp());
|
||||
puts("}");
|
||||
}
|
||||
virtual void visit(AstMemberDType* nodep) override {
|
||||
void visit(AstMemberDType* nodep) override {
|
||||
iterate(nodep->subDTypep());
|
||||
puts(" ");
|
||||
puts(nodep->name());
|
||||
}
|
||||
virtual void visit(AstNodeFTaskRef* nodep) override {
|
||||
void visit(AstNodeFTaskRef* nodep) override {
|
||||
if (nodep->dotted() != "") {
|
||||
putfs(nodep, nodep->dotted());
|
||||
puts(".");
|
||||
|
|
@ -626,14 +623,14 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
iterateAndNextConstNull(nodep->pinsp());
|
||||
puts(")");
|
||||
}
|
||||
virtual void visit(AstArg* nodep) override { iterateAndNextConstNull(nodep->exprp()); }
|
||||
virtual void visit(AstPrintTimeScale* nodep) override {
|
||||
void visit(AstArg* nodep) override { iterateAndNextConstNull(nodep->exprp()); }
|
||||
void visit(AstPrintTimeScale* nodep) override {
|
||||
puts(nodep->verilogKwd());
|
||||
puts(";\n");
|
||||
}
|
||||
|
||||
// Terminals
|
||||
virtual void visit(AstVarRef* nodep) override {
|
||||
void visit(AstVarRef* nodep) override {
|
||||
if (nodep->varScopep()) {
|
||||
putfs(nodep, nodep->varScopep()->prettyName());
|
||||
} else {
|
||||
|
|
@ -649,7 +646,7 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual void visit(AstVarXRef* nodep) override {
|
||||
void visit(AstVarXRef* nodep) override {
|
||||
putfs(nodep, nodep->dotted());
|
||||
puts(".");
|
||||
if (nodep->varp()) {
|
||||
|
|
@ -658,12 +655,12 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
puts(nodep->prettyName());
|
||||
}
|
||||
}
|
||||
virtual void visit(AstConst* nodep) override { putfs(nodep, nodep->num().ascii(true, true)); }
|
||||
void visit(AstConst* nodep) override { putfs(nodep, nodep->num().ascii(true, true)); }
|
||||
|
||||
// Just iterate
|
||||
virtual void visit(AstTopScope* nodep) override { iterateChildrenConst(nodep); }
|
||||
virtual void visit(AstScope* nodep) override { iterateChildrenConst(nodep); }
|
||||
virtual void visit(AstVar* nodep) override {
|
||||
void visit(AstTopScope* nodep) override { iterateChildrenConst(nodep); }
|
||||
void visit(AstScope* nodep) override { iterateChildrenConst(nodep); }
|
||||
void visit(AstVar* nodep) override {
|
||||
if (nodep->isIO()) {
|
||||
putfs(nodep, nodep->verilogKwd());
|
||||
puts(" ");
|
||||
|
|
@ -691,21 +688,21 @@ class EmitVBaseVisitor VL_NOT_FINAL : public EmitCBaseVisitor {
|
|||
}
|
||||
puts(m_suppressVarSemi ? "\n" : ";\n");
|
||||
}
|
||||
virtual void visit(AstActive* nodep) override {
|
||||
void visit(AstActive* nodep) override {
|
||||
m_sensesp = nodep->sensesp();
|
||||
iterateAndNextConstNull(nodep->stmtsp());
|
||||
m_sensesp = nullptr;
|
||||
}
|
||||
virtual void visit(AstParseRef* nodep) override { puts(nodep->prettyName()); }
|
||||
virtual void visit(AstVarScope*) override {}
|
||||
virtual void visit(AstNodeText*) override {}
|
||||
virtual void visit(AstTraceDecl*) override {}
|
||||
virtual void visit(AstTraceInc*) override {}
|
||||
void visit(AstParseRef* nodep) override { puts(nodep->prettyName()); }
|
||||
void visit(AstVarScope*) override {}
|
||||
void visit(AstNodeText*) override {}
|
||||
void visit(AstTraceDecl*) override {}
|
||||
void visit(AstTraceInc*) override {}
|
||||
// NOPs
|
||||
virtual void visit(AstPragma*) override {}
|
||||
virtual void visit(AstCell*) override {} // Handled outside the Visit class
|
||||
void visit(AstPragma*) override {}
|
||||
void visit(AstCell*) override {} // Handled outside the Visit class
|
||||
// Default
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
void visit(AstNode* nodep) override {
|
||||
puts(std::string{"\n???? // "} + nodep->prettyTypeName() + "\n");
|
||||
iterateChildrenConst(nodep);
|
||||
// Not v3fatalSrc so we keep processing
|
||||
|
|
@ -720,7 +717,7 @@ public:
|
|||
explicit EmitVBaseVisitor(bool suppressUnknown, AstSenTree* domainp)
|
||||
: m_suppressUnknown{suppressUnknown}
|
||||
, m_sensesp{domainp} {}
|
||||
virtual ~EmitVBaseVisitor() override = default;
|
||||
~EmitVBaseVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -731,11 +728,11 @@ class EmitVFileVisitor final : public EmitVBaseVisitor {
|
|||
V3OutFile* m_ofp;
|
||||
// METHODS
|
||||
V3OutFile* ofp() const { return m_ofp; }
|
||||
virtual void puts(const string& str) override { ofp()->puts(str); }
|
||||
virtual void putbs(const string& str) override { ofp()->putbs(str); }
|
||||
virtual void putfs(AstNode*, const string& str) override { putbs(str); }
|
||||
virtual void putqs(AstNode*, const string& str) override { putbs(str); }
|
||||
virtual void putsNoTracking(const string& str) override { ofp()->putsNoTracking(str); }
|
||||
void puts(const string& str) override { ofp()->puts(str); }
|
||||
void putbs(const string& str) override { ofp()->putbs(str); }
|
||||
void putfs(AstNode*, const string& str) override { putbs(str); }
|
||||
void putqs(AstNode*, const string& str) override { putbs(str); }
|
||||
void putsNoTracking(const string& str) override { ofp()->putsNoTracking(str); }
|
||||
|
||||
public:
|
||||
EmitVFileVisitor(AstNode* nodep, V3OutFile* ofp, bool trackText, bool suppressUnknown)
|
||||
|
|
@ -744,7 +741,7 @@ public:
|
|||
m_trackText = trackText;
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~EmitVFileVisitor() override = default;
|
||||
~EmitVFileVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -754,11 +751,11 @@ class EmitVStreamVisitor final : public EmitVBaseVisitor {
|
|||
// MEMBERS
|
||||
std::ostream& m_os;
|
||||
// METHODS
|
||||
virtual void putsNoTracking(const string& str) override { m_os << str; }
|
||||
virtual void puts(const string& str) override { putsNoTracking(str); }
|
||||
virtual void putbs(const string& str) override { puts(str); }
|
||||
virtual void putfs(AstNode*, const string& str) override { putbs(str); }
|
||||
virtual void putqs(AstNode*, const string& str) override { putbs(str); }
|
||||
void putsNoTracking(const string& str) override { m_os << str; }
|
||||
void puts(const string& str) override { putsNoTracking(str); }
|
||||
void putbs(const string& str) override { puts(str); }
|
||||
void putfs(AstNode*, const string& str) override { putbs(str); }
|
||||
void putqs(AstNode*, const string& str) override { putbs(str); }
|
||||
|
||||
public:
|
||||
EmitVStreamVisitor(const AstNode* nodep, std::ostream& os)
|
||||
|
|
@ -766,7 +763,7 @@ public:
|
|||
, m_os(os) { // Need () or GCC 4.8 false warning
|
||||
iterate(const_cast<AstNode*>(nodep));
|
||||
}
|
||||
virtual ~EmitVStreamVisitor() override = default;
|
||||
~EmitVStreamVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -779,7 +776,7 @@ class EmitVPrefixedFormatter final : public V3OutFormatter {
|
|||
int m_column = 0; // Rough location; need just zero or non-zero
|
||||
FileLine* m_prefixFl;
|
||||
// METHODS
|
||||
virtual void putcOutput(char chr) override {
|
||||
void putcOutput(char chr) override {
|
||||
if (chr == '\n') {
|
||||
m_column = 0;
|
||||
m_os << chr;
|
||||
|
|
@ -796,7 +793,7 @@ class EmitVPrefixedFormatter final : public V3OutFormatter {
|
|||
}
|
||||
}
|
||||
|
||||
virtual void putsOutput(const char* strg) override {
|
||||
void putsOutput(const char* strg) override {
|
||||
for (const char* cp = strg; *cp; cp++) putcOutput(*cp);
|
||||
}
|
||||
|
||||
|
|
@ -812,7 +809,7 @@ public:
|
|||
m_prefixFl = v3Global.rootp()->fileline(); // NETLIST's fileline instead of nullptr to
|
||||
// avoid nullptr checks
|
||||
}
|
||||
virtual ~EmitVPrefixedFormatter() override {
|
||||
~EmitVPrefixedFormatter() override {
|
||||
if (m_column) puts("\n");
|
||||
}
|
||||
};
|
||||
|
|
@ -822,13 +819,13 @@ class EmitVPrefixedVisitor final : public EmitVBaseVisitor {
|
|||
EmitVPrefixedFormatter m_formatter; // Special verilog formatter (Way down the
|
||||
// inheritance is another unused V3OutFormatter)
|
||||
// METHODS
|
||||
virtual void putsNoTracking(const string& str) override { m_formatter.putsNoTracking(str); }
|
||||
virtual void puts(const string& str) override { m_formatter.puts(str); }
|
||||
void putsNoTracking(const string& str) override { m_formatter.putsNoTracking(str); }
|
||||
void puts(const string& str) override { m_formatter.puts(str); }
|
||||
// We don't use m_formatter's putbs because the tokens will change filelines
|
||||
// and insert returns at the proper locations
|
||||
virtual void putbs(const string& str) override { m_formatter.puts(str); }
|
||||
virtual void putfs(AstNode* nodep, const string& str) override { putfsqs(nodep, str, false); }
|
||||
virtual void putqs(AstNode* nodep, const string& str) override { putfsqs(nodep, str, true); }
|
||||
void putbs(const string& str) override { m_formatter.puts(str); }
|
||||
void putfs(AstNode* nodep, const string& str) override { putfsqs(nodep, str, false); }
|
||||
void putqs(AstNode* nodep, const string& str) override { putfsqs(nodep, str, true); }
|
||||
void putfsqs(AstNode* nodep, const string& str, bool quiet) {
|
||||
if (m_formatter.prefixFl() != nodep->fileline()) {
|
||||
m_formatter.prefixFl(nodep->fileline());
|
||||
|
|
@ -846,7 +843,7 @@ public:
|
|||
if (user3mark) VNUser3InUse::check();
|
||||
iterate(const_cast<AstNode*>(nodep));
|
||||
}
|
||||
virtual ~EmitVPrefixedVisitor() override = default;
|
||||
~EmitVPrefixedVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Emit statements and math operators
|
||||
|
||||
|
|
@ -39,7 +41,6 @@ class EmitXmlFileVisitor final : public VNVisitor {
|
|||
uint64_t m_id = 0;
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
// Outfile methods
|
||||
V3OutFile* ofp() const { return m_ofp; }
|
||||
|
|
@ -101,11 +102,11 @@ class EmitXmlFileVisitor final : public VNVisitor {
|
|||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstAssignW* nodep) override {
|
||||
void visit(AstAssignW* nodep) override {
|
||||
outputTag(nodep, "contassign"); // IEEE: vpiContAssign
|
||||
outputChildrenEnd(nodep, "contassign");
|
||||
}
|
||||
virtual void visit(AstCell* nodep) override {
|
||||
void visit(AstCell* nodep) override {
|
||||
outputTag(nodep, "instance"); // IEEE: vpiInstance
|
||||
puts(" defName=");
|
||||
putsQuoted(nodep->modName()); // IEEE vpiDefName
|
||||
|
|
@ -113,7 +114,7 @@ class EmitXmlFileVisitor final : public VNVisitor {
|
|||
putsQuoted(nodep->origName());
|
||||
outputChildrenEnd(nodep, "instance");
|
||||
}
|
||||
virtual void visit(AstNodeIf* nodep) override {
|
||||
void visit(AstNodeIf* nodep) override {
|
||||
outputTag(nodep, "if");
|
||||
puts(">\n");
|
||||
iterateAndNextNull(nodep->op1p());
|
||||
|
|
@ -127,7 +128,7 @@ class EmitXmlFileVisitor final : public VNVisitor {
|
|||
}
|
||||
puts("</if>\n");
|
||||
}
|
||||
virtual void visit(AstWhile* nodep) override {
|
||||
void visit(AstWhile* nodep) override {
|
||||
outputTag(nodep, "while");
|
||||
puts(">\n");
|
||||
puts("<begin>\n");
|
||||
|
|
@ -150,19 +151,19 @@ class EmitXmlFileVisitor final : public VNVisitor {
|
|||
}
|
||||
puts("</while>\n");
|
||||
}
|
||||
virtual void visit(AstNetlist* nodep) override {
|
||||
void visit(AstNetlist* nodep) override {
|
||||
puts("<netlist>\n");
|
||||
iterateChildren(nodep);
|
||||
puts("</netlist>\n");
|
||||
}
|
||||
virtual void visit(AstConstPool* nodep) override {
|
||||
void visit(AstConstPool* nodep) override {
|
||||
if (!v3Global.opt.xmlOnly()) {
|
||||
puts("<constpool>\n");
|
||||
iterateChildren(nodep);
|
||||
puts("</constpool>\n");
|
||||
}
|
||||
}
|
||||
virtual void visit(AstInitArray* nodep) override {
|
||||
void visit(AstInitArray* nodep) override {
|
||||
puts("<initarray>\n");
|
||||
const auto& mapr = nodep->map();
|
||||
for (const auto& itr : mapr) {
|
||||
|
|
@ -174,7 +175,7 @@ class EmitXmlFileVisitor final : public VNVisitor {
|
|||
}
|
||||
puts("</initarray>\n");
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
outputTag(nodep, "");
|
||||
puts(" origName=");
|
||||
putsQuoted(nodep->origName());
|
||||
|
|
@ -184,7 +185,7 @@ class EmitXmlFileVisitor final : public VNVisitor {
|
|||
if (nodep->modPublic()) puts(" public=\"true\"");
|
||||
outputChildrenEnd(nodep, "");
|
||||
}
|
||||
virtual void visit(AstVar* nodep) override {
|
||||
void visit(AstVar* nodep) override {
|
||||
const VVarType typ = nodep->varType();
|
||||
const string kw = nodep->verilogKwd();
|
||||
const string vt = nodep->dtypep()->name();
|
||||
|
|
@ -222,7 +223,7 @@ class EmitXmlFileVisitor final : public VNVisitor {
|
|||
if (nodep->attrSFormat()) puts(" sformat=\"true\"");
|
||||
outputChildrenEnd(nodep, "");
|
||||
}
|
||||
virtual void visit(AstPin* nodep) override {
|
||||
void visit(AstPin* nodep) override {
|
||||
// What we call a pin in verilator is a port in the IEEE spec.
|
||||
outputTag(nodep, "port"); // IEEE: vpiPort
|
||||
if (nodep->modVarp()->isIO()) {
|
||||
|
|
@ -232,12 +233,12 @@ class EmitXmlFileVisitor final : public VNVisitor {
|
|||
// Children includes vpiHighConn and vpiLowConn; we don't support port bits (yet?)
|
||||
outputChildrenEnd(nodep, "port");
|
||||
}
|
||||
virtual void visit(AstSenItem* nodep) override {
|
||||
void visit(AstSenItem* nodep) override {
|
||||
outputTag(nodep, "");
|
||||
puts(" edgeType=\"" + cvtToStr(nodep->edgeType().ascii()) + "\""); // IEEE vpiTopModule
|
||||
outputChildrenEnd(nodep, "");
|
||||
}
|
||||
virtual void visit(AstModportVarRef* nodep) override {
|
||||
void visit(AstModportVarRef* nodep) override {
|
||||
// Dump direction for Modport references
|
||||
const string kw = nodep->direction().xmlKwd();
|
||||
outputTag(nodep, "");
|
||||
|
|
@ -245,13 +246,13 @@ class EmitXmlFileVisitor final : public VNVisitor {
|
|||
putsQuoted(kw);
|
||||
outputChildrenEnd(nodep, "");
|
||||
}
|
||||
virtual void visit(AstVarXRef* nodep) override {
|
||||
void visit(AstVarXRef* nodep) override {
|
||||
outputTag(nodep, "");
|
||||
puts(" dotted=");
|
||||
putsQuoted(nodep->dotted());
|
||||
outputChildrenEnd(nodep, "");
|
||||
}
|
||||
virtual void visit(AstNodeCCall* nodep) override {
|
||||
void visit(AstNodeCCall* nodep) override {
|
||||
outputTag(nodep, "");
|
||||
puts(" func=");
|
||||
putsQuoted(nodep->funcp()->name());
|
||||
|
|
@ -259,7 +260,7 @@ class EmitXmlFileVisitor final : public VNVisitor {
|
|||
}
|
||||
|
||||
// Data types
|
||||
virtual void visit(AstBasicDType* nodep) override {
|
||||
void visit(AstBasicDType* nodep) override {
|
||||
outputTag(nodep, "basicdtype");
|
||||
if (nodep->isRanged()) {
|
||||
puts(" left=\"" + cvtToStr(nodep->left()) + "\"");
|
||||
|
|
@ -268,7 +269,7 @@ class EmitXmlFileVisitor final : public VNVisitor {
|
|||
if (nodep->isSigned()) { puts(" signed=\"true\""); }
|
||||
puts("/>\n");
|
||||
}
|
||||
virtual void visit(AstIfaceRefDType* nodep) override {
|
||||
void visit(AstIfaceRefDType* nodep) override {
|
||||
string mpn;
|
||||
outputTag(nodep, "");
|
||||
if (nodep->isModport()) mpn = nodep->modportName();
|
||||
|
|
@ -276,19 +277,19 @@ class EmitXmlFileVisitor final : public VNVisitor {
|
|||
putsQuoted(mpn);
|
||||
outputChildrenEnd(nodep, "");
|
||||
}
|
||||
virtual void visit(AstDisplay* nodep) override {
|
||||
void visit(AstDisplay* nodep) override {
|
||||
outputTag(nodep, "");
|
||||
puts(" displaytype=");
|
||||
putsQuoted(nodep->verilogKwd());
|
||||
outputChildrenEnd(nodep, "");
|
||||
}
|
||||
virtual void visit(AstElabDisplay* nodep) override {
|
||||
void visit(AstElabDisplay* nodep) override {
|
||||
outputTag(nodep, "");
|
||||
puts(" displaytype=");
|
||||
putsQuoted(nodep->verilogKwd());
|
||||
outputChildrenEnd(nodep, "");
|
||||
}
|
||||
virtual void visit(AstExtend* nodep) override {
|
||||
void visit(AstExtend* nodep) override {
|
||||
outputTag(nodep, "");
|
||||
puts(" width=");
|
||||
putsQuoted(cvtToStr(nodep->width()));
|
||||
|
|
@ -296,7 +297,7 @@ class EmitXmlFileVisitor final : public VNVisitor {
|
|||
putsQuoted(cvtToStr(nodep->lhsp()->widthMinV()));
|
||||
outputChildrenEnd(nodep, "");
|
||||
}
|
||||
virtual void visit(AstExtendS* nodep) override {
|
||||
void visit(AstExtendS* nodep) override {
|
||||
outputTag(nodep, "");
|
||||
puts(" width=");
|
||||
putsQuoted(cvtToStr(nodep->width()));
|
||||
|
|
@ -306,7 +307,7 @@ class EmitXmlFileVisitor final : public VNVisitor {
|
|||
}
|
||||
|
||||
// Default
|
||||
virtual void visit(AstNode* nodep) override {
|
||||
void visit(AstNode* nodep) override {
|
||||
outputTag(nodep, "");
|
||||
outputChildrenEnd(nodep, "");
|
||||
}
|
||||
|
|
@ -316,7 +317,7 @@ public:
|
|||
: m_ofp{ofp} {
|
||||
iterate(nodep);
|
||||
}
|
||||
virtual ~EmitXmlFileVisitor() override = default;
|
||||
~EmitXmlFileVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -330,14 +331,13 @@ private:
|
|||
std::deque<FileLine*> m_nodeModules;
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstNetlist* nodep) override {
|
||||
void visit(AstNetlist* nodep) override {
|
||||
// Children are iterated backwards to ensure correct compilation order
|
||||
iterateChildrenBackwards(nodep);
|
||||
}
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
// Only list modules and interfaces
|
||||
// Assumes modules and interfaces list is already sorted level wise
|
||||
if (!nodep->dead() && (VN_IS(nodep, Module) || VN_IS(nodep, Iface))
|
||||
|
|
@ -346,7 +346,7 @@ private:
|
|||
}
|
||||
}
|
||||
//-----
|
||||
virtual void visit(AstNode*) override {
|
||||
void visit(AstNode*) override {
|
||||
// All modules are present at root so no need to iterate on children
|
||||
}
|
||||
|
||||
|
|
@ -364,7 +364,7 @@ public:
|
|||
}
|
||||
m_os << "</module_files>\n";
|
||||
}
|
||||
virtual ~ModuleFilesXmlVisitor() override = default;
|
||||
~ModuleFilesXmlVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -378,12 +378,11 @@ private:
|
|||
bool m_hasChildren = false;
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstConstPool*) override {}
|
||||
void visit(AstConstPool*) override {}
|
||||
|
||||
virtual void visit(AstNodeModule* nodep) override {
|
||||
void visit(AstNodeModule* nodep) override {
|
||||
if (nodep->level() >= 0
|
||||
&& nodep->level() <= 2) { // ==2 because we don't add wrapper when in XML mode
|
||||
m_os << "<cells>\n";
|
||||
|
|
@ -402,7 +401,7 @@ private:
|
|||
m_os << "</cells>\n";
|
||||
}
|
||||
}
|
||||
virtual void visit(AstCell* nodep) override {
|
||||
void visit(AstCell* nodep) override {
|
||||
if (nodep->modp()->dead()) return;
|
||||
if (!m_hasChildren) m_os << ">\n";
|
||||
m_os << "<cell " << nodep->fileline()->xmlDetailedLocation() << " name=\"" << nodep->name()
|
||||
|
|
@ -422,7 +421,7 @@ private:
|
|||
m_hasChildren = true;
|
||||
}
|
||||
//-----
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
|
|
@ -431,7 +430,7 @@ public:
|
|||
// Operate on whole netlist
|
||||
nodep->accept(*this);
|
||||
}
|
||||
virtual ~HierCellsXmlVisitor() override = default;
|
||||
~HierCellsXmlVisitor() override = default;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
# include "V3Ast.h"
|
||||
# include "V3Global.h"
|
||||
# include "V3Stats.h"
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
|
|
@ -54,7 +55,7 @@ v3errorIniter v3errorInit;
|
|||
V3ErrorCode::V3ErrorCode(const char* msgp) {
|
||||
// Return error encoding for given string, or ERROR, which is a bad code
|
||||
for (int codei = V3ErrorCode::EC_MIN; codei < V3ErrorCode::_ENUM_MAX; codei++) {
|
||||
const V3ErrorCode code = V3ErrorCode(codei);
|
||||
const V3ErrorCode code{codei};
|
||||
if (0 == VL_STRCASECMP(msgp, code.ascii())) {
|
||||
m_e = code;
|
||||
return;
|
||||
|
|
@ -69,9 +70,9 @@ V3ErrorCode::V3ErrorCode(const char* msgp) {
|
|||
void V3Error::init() {
|
||||
for (int i = 0; i < V3ErrorCode::_ENUM_MAX; i++) {
|
||||
s_describedEachWarn[i] = false;
|
||||
s_pretendError[i] = V3ErrorCode(i).pretendError();
|
||||
s_pretendError[i] = V3ErrorCode{i}.pretendError();
|
||||
}
|
||||
if (VL_UNCOVERABLE(string(V3ErrorCode(V3ErrorCode::_ENUM_MAX).ascii()) != " MAX")) {
|
||||
if (VL_UNCOVERABLE(string(V3ErrorCode{V3ErrorCode::_ENUM_MAX}.ascii()) != " MAX")) {
|
||||
v3fatalSrc("Enum table in V3ErrorCode::EC_ascii() is munged");
|
||||
}
|
||||
}
|
||||
|
|
@ -275,8 +276,10 @@ void V3Error::v3errorEnd(std::ostringstream& sstr, const string& extra) {
|
|||
s_tellManual = 2;
|
||||
}
|
||||
#ifndef V3ERROR_NO_GLOBAL_
|
||||
if (debug()) {
|
||||
if (dumpTree()) {
|
||||
v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("final.tree", 990));
|
||||
}
|
||||
if (debug()) {
|
||||
if (s_errorExitCb) s_errorExitCb();
|
||||
V3Stats::statsFinalAll(v3Global.rootp());
|
||||
V3Stats::statsReport();
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <array>
|
||||
#include <bitset>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
|
@ -142,15 +143,15 @@ public:
|
|||
};
|
||||
// clang-format on
|
||||
enum en m_e;
|
||||
inline V3ErrorCode()
|
||||
V3ErrorCode()
|
||||
: m_e{EC_MIN} {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline V3ErrorCode(en _e)
|
||||
constexpr V3ErrorCode(en _e)
|
||||
: m_e{_e} {}
|
||||
explicit V3ErrorCode(const char* msgp); // Matching code or ERROR
|
||||
explicit inline V3ErrorCode(int _e)
|
||||
explicit V3ErrorCode(int _e)
|
||||
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
||||
operator en() const { return m_e; }
|
||||
constexpr operator en() const { return m_e; }
|
||||
const char* ascii() const {
|
||||
// clang-format off
|
||||
static const char* const names[] = {
|
||||
|
|
@ -220,16 +221,16 @@ public:
|
|||
|| m_e == VARHIDDEN);
|
||||
}
|
||||
};
|
||||
inline bool operator==(const V3ErrorCode& lhs, const V3ErrorCode& rhs) {
|
||||
constexpr bool operator==(const V3ErrorCode& lhs, const V3ErrorCode& rhs) {
|
||||
return lhs.m_e == rhs.m_e;
|
||||
}
|
||||
inline bool operator==(const V3ErrorCode& lhs, V3ErrorCode::en rhs) { return lhs.m_e == rhs; }
|
||||
inline bool operator==(V3ErrorCode::en lhs, const V3ErrorCode& rhs) { return lhs == rhs.m_e; }
|
||||
constexpr bool operator==(const V3ErrorCode& lhs, V3ErrorCode::en rhs) { return lhs.m_e == rhs; }
|
||||
constexpr bool operator==(V3ErrorCode::en lhs, const V3ErrorCode& rhs) { return lhs == rhs.m_e; }
|
||||
inline std::ostream& operator<<(std::ostream& os, const V3ErrorCode& rhs) {
|
||||
return os << rhs.ascii();
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// ######################################################################
|
||||
|
||||
class V3Error final {
|
||||
// Base class for any object that wants debugging and error reporting
|
||||
|
|
@ -317,7 +318,6 @@ public:
|
|||
};
|
||||
|
||||
// Global versions, so that if the class doesn't define a operator, we get the functions anyways.
|
||||
inline int debug() { return V3Error::debugDefault(); }
|
||||
inline void v3errorEnd(std::ostringstream& sstr) { V3Error::v3errorEnd(sstr); }
|
||||
inline void v3errorEndFatal(std::ostringstream& sstr) {
|
||||
V3Error::v3errorEnd(sstr);
|
||||
|
|
@ -412,19 +412,47 @@ inline void v3errorEndFatal(std::ostringstream& sstr) {
|
|||
V3ERROR_NA; \
|
||||
return value
|
||||
|
||||
/// Declare a convenience debug() routine that may be added to any class in
|
||||
/// Verilator so that --debugi-<srcfile> will work to control UINFOs in
|
||||
/// that class:
|
||||
#define VL_DEBUG_FUNC \
|
||||
static int debug() { \
|
||||
// Helper macros for VL_DEFINE_DEBUG_FUNCTIONS
|
||||
#define VL_DEFINE_DEBUG(name) \
|
||||
VL_ATTR_UNUSED static int debug##name() { \
|
||||
static int level = -1; \
|
||||
if (VL_UNLIKELY(level < 0)) { \
|
||||
const int debugSrcLevel = v3Global.opt.debugSrcLevel(__FILE__); \
|
||||
if (!v3Global.opt.available()) return debugSrcLevel; \
|
||||
level = debugSrcLevel; \
|
||||
std::string tag{VL_STRINGIFY(name)}; \
|
||||
tag[0] = std::tolower(tag[0]); \
|
||||
const unsigned debugTag = v3Global.opt.debugLevel(tag); \
|
||||
const unsigned debugSrc = v3Global.opt.debugSrcLevel(__FILE__); \
|
||||
const unsigned debugLevel = debugTag >= debugSrc ? debugTag : debugSrc; \
|
||||
if (!v3Global.opt.available()) return static_cast<int>(debugLevel); \
|
||||
level = static_cast<int>(debugLevel); \
|
||||
} \
|
||||
return level; \
|
||||
}
|
||||
} \
|
||||
static_assert(true, "")
|
||||
|
||||
#define VL_DEFINE_DUMP(name) \
|
||||
VL_ATTR_UNUSED static int dump##name() { \
|
||||
static int level = -1; \
|
||||
if (VL_UNLIKELY(level < 0)) { \
|
||||
std::string tag{VL_STRINGIFY(name)}; \
|
||||
tag[0] = std::tolower(tag[0]); \
|
||||
const unsigned dumpTag = v3Global.opt.dumpLevel(tag); \
|
||||
const unsigned dumpSrc = v3Global.opt.dumpSrcLevel(__FILE__); \
|
||||
const unsigned dumpLevel = dumpTag >= dumpSrc ? dumpTag : dumpSrc; \
|
||||
if (!v3Global.opt.available()) return static_cast<int>(dumpLevel); \
|
||||
level = static_cast<int>(dumpLevel); \
|
||||
} \
|
||||
return level; \
|
||||
} \
|
||||
static_assert(true, "")
|
||||
|
||||
// Define debug*() and dump*() routines. This needs to be added to every compilation unit so that
|
||||
// --debugi-<tag/srcfile> and --dumpi-<tag/srcfile> can be used to control debug prints and dumping
|
||||
#define VL_DEFINE_DEBUG_FUNCTIONS \
|
||||
VL_DEFINE_DEBUG(); /* Define 'int debug()' */ \
|
||||
VL_DEFINE_DUMP(); /* Define 'int dump()' */ \
|
||||
VL_DEFINE_DUMP(Graph); /* Define 'int dumpGraph()' */ \
|
||||
VL_DEFINE_DUMP(Tree); /* Define 'int dumpTree()' */ \
|
||||
static_assert(true, "")
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
//######################################################################
|
||||
// Expand state, as a visitor of each AstNode
|
||||
|
||||
|
|
@ -53,7 +55,6 @@ private:
|
|||
VDouble0 m_statWideLimited; // Statistic tracking
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
bool doExpand(AstNode* nodep) {
|
||||
++m_statWides;
|
||||
|
|
@ -306,14 +307,14 @@ private:
|
|||
for (int w = 0; w < nodep->widthWords(); ++w) {
|
||||
addWordAssign(nodep, w,
|
||||
new AstCond{fl, rhsp->condp()->cloneTree(true),
|
||||
newAstWordSelClone(rhsp->expr1p(), w),
|
||||
newAstWordSelClone(rhsp->expr2p(), w)});
|
||||
newAstWordSelClone(rhsp->thenp(), w),
|
||||
newAstWordSelClone(rhsp->elsep(), w)});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
virtual void visit(AstExtend* nodep) override {
|
||||
void visit(AstExtend* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
iterateChildren(nodep);
|
||||
if (nodep->isWide()) {
|
||||
|
|
@ -339,7 +340,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstSel* nodep) override {
|
||||
void visit(AstSel* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
iterateChildren(nodep);
|
||||
// Remember, Sel's may have non-integer rhs, so need to optimize for that!
|
||||
|
|
@ -628,7 +629,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void visit(AstConcat* nodep) override {
|
||||
void visit(AstConcat* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
iterateChildren(nodep);
|
||||
if (nodep->isWide()) {
|
||||
|
|
@ -665,7 +666,7 @@ private:
|
|||
return true;
|
||||
}
|
||||
|
||||
virtual void visit(AstReplicate* nodep) override {
|
||||
void visit(AstReplicate* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
iterateChildren(nodep);
|
||||
if (nodep->isWide()) {
|
||||
|
|
@ -750,10 +751,10 @@ private:
|
|||
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstEq* nodep) override { visitEqNeq(nodep); }
|
||||
virtual void visit(AstNeq* nodep) override { visitEqNeq(nodep); }
|
||||
void visit(AstEq* nodep) override { visitEqNeq(nodep); }
|
||||
void visit(AstNeq* nodep) override { visitEqNeq(nodep); }
|
||||
|
||||
virtual void visit(AstRedOr* nodep) override {
|
||||
void visit(AstRedOr* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
iterateChildren(nodep);
|
||||
FileLine* const fl = nodep->fileline();
|
||||
|
|
@ -775,7 +776,7 @@ private:
|
|||
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstRedAnd* nodep) override {
|
||||
void visit(AstRedAnd* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
iterateChildren(nodep);
|
||||
FileLine* const fl = nodep->fileline();
|
||||
|
|
@ -805,7 +806,7 @@ private:
|
|||
VL_DO_DANGLING(replaceWithDelete(nodep, newp), nodep);
|
||||
}
|
||||
}
|
||||
virtual void visit(AstRedXor* nodep) override {
|
||||
void visit(AstRedXor* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
iterateChildren(nodep);
|
||||
if (nodep->lhsp()->isWide()) {
|
||||
|
|
@ -825,7 +826,7 @@ private:
|
|||
// which the inlined function does nicely.
|
||||
}
|
||||
|
||||
virtual void visit(AstNodeStmt* nodep) override {
|
||||
void visit(AstNodeStmt* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
if (!nodep->isStatement()) {
|
||||
iterateChildren(nodep);
|
||||
|
|
@ -835,7 +836,7 @@ private:
|
|||
iterateChildren(nodep);
|
||||
m_stmtp = nullptr;
|
||||
}
|
||||
virtual void visit(AstNodeAssign* nodep) override {
|
||||
void visit(AstNodeAssign* nodep) override {
|
||||
if (nodep->user1SetOnce()) return; // Process once
|
||||
m_stmtp = nodep;
|
||||
iterateChildren(nodep);
|
||||
|
|
@ -876,13 +877,13 @@ private:
|
|||
}
|
||||
|
||||
//--------------------
|
||||
virtual void visit(AstVar*) override {} // Don't hit varrefs under vars
|
||||
virtual void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
void visit(AstVar*) override {} // Don't hit varrefs under vars
|
||||
void visit(AstNode* nodep) override { iterateChildren(nodep); }
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
explicit ExpandVisitor(AstNetlist* nodep) { iterate(nodep); }
|
||||
virtual ~ExpandVisitor() override {
|
||||
~ExpandVisitor() override {
|
||||
V3Stats::addStat("Optimizations, expand wides", m_statWides);
|
||||
V3Stats::addStat("Optimizations, expand wide words", m_statWideWords);
|
||||
V3Stats::addStat("Optimizations, expand limited", m_statWideLimited);
|
||||
|
|
@ -898,5 +899,5 @@ public:
|
|||
void V3Expand::expandAll(AstNetlist* nodep) {
|
||||
UINFO(2, __FUNCTION__ << ": " << endl);
|
||||
{ ExpandVisitor{nodep}; } // Destruct before checking
|
||||
V3Global::dumpCheckGlobalTree("expand", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
||||
V3Global::dumpCheckGlobalTree("expand", 0, dumpTree() >= 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@
|
|||
#endif
|
||||
// clang-format on
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
// If change this code, run a test with the below size set very small
|
||||
// #define INFILTER_IPC_BUFSIZ 16
|
||||
constexpr int INFILTER_IPC_BUFSIZ = (64 * 1024); // For debug, try this as a small number
|
||||
|
|
@ -94,7 +96,7 @@ class V3FileDependImp final {
|
|||
const string fn = filename();
|
||||
const int err = stat(fn.c_str(), &m_stat);
|
||||
if (err != 0) {
|
||||
memset(&m_stat, 0, sizeof(m_stat));
|
||||
std::memset(&m_stat, 0, sizeof(m_stat));
|
||||
m_stat.st_mtime = 1;
|
||||
m_exists = false;
|
||||
// Not an error... This can occur due to `line directives in the .vpp files
|
||||
|
|
@ -146,7 +148,7 @@ V3FileDependImp dependImp; // Depend implementation class
|
|||
//######################################################################
|
||||
// V3FileDependImp
|
||||
|
||||
inline void V3FileDependImp::writeDepend(const string& filename) {
|
||||
void V3FileDependImp::writeDepend(const string& filename) {
|
||||
const std::unique_ptr<std::ofstream> ofp{V3File::new_ofstream(filename)};
|
||||
if (ofp->fail()) v3fatal("Can't write " << filename);
|
||||
|
||||
|
|
@ -154,7 +156,7 @@ inline void V3FileDependImp::writeDepend(const string& filename) {
|
|||
if (i.target()) *ofp << i.filename() << " ";
|
||||
}
|
||||
*ofp << " : ";
|
||||
*ofp << v3Global.opt.bin();
|
||||
*ofp << v3Global.opt.buildDepBin();
|
||||
*ofp << " ";
|
||||
|
||||
for (const DependFile& i : m_filenameList) {
|
||||
|
|
@ -171,7 +173,7 @@ inline void V3FileDependImp::writeDepend(const string& filename) {
|
|||
}
|
||||
}
|
||||
|
||||
inline std::vector<string> V3FileDependImp::getAllDeps() const {
|
||||
std::vector<string> V3FileDependImp::getAllDeps() const {
|
||||
std::vector<string> r;
|
||||
for (const auto& itr : m_filenameList) {
|
||||
if (!itr.target() && itr.exists()) r.push_back(itr.filename());
|
||||
|
|
@ -179,7 +181,7 @@ inline std::vector<string> V3FileDependImp::getAllDeps() const {
|
|||
return r;
|
||||
}
|
||||
|
||||
inline void V3FileDependImp::writeTimes(const string& filename, const string& cmdlineIn) {
|
||||
void V3FileDependImp::writeTimes(const string& filename, const string& cmdlineIn) {
|
||||
const std::unique_ptr<std::ofstream> ofp{V3File::new_ofstream(filename)};
|
||||
if (ofp->fail()) v3fatal("Can't write " << filename);
|
||||
|
||||
|
|
@ -214,7 +216,7 @@ inline void V3FileDependImp::writeTimes(const string& filename, const string& cm
|
|||
}
|
||||
}
|
||||
|
||||
inline bool V3FileDependImp::checkTimes(const string& filename, const string& cmdlineIn) {
|
||||
bool V3FileDependImp::checkTimes(const string& filename, const string& cmdlineIn) {
|
||||
const std::unique_ptr<std::ifstream> ifp{V3File::new_ifstream_nodepend(filename)};
|
||||
if (ifp->fail()) {
|
||||
UINFO(2, " --check-times failed: no input " << filename << endl);
|
||||
|
|
@ -346,7 +348,6 @@ class VInFilterImp final {
|
|||
|
||||
private:
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
bool readContents(const string& filename, StrList& outl) {
|
||||
if (m_pid) {
|
||||
|
|
@ -389,7 +390,7 @@ private:
|
|||
if (!m_pidExited && waitpid(m_pid, &m_pidStatus, hang ? 0 : WNOHANG)) {
|
||||
UINFO(1, "--pipe-filter: Exited, status "
|
||||
<< m_pidStatus << " exit=" << WEXITSTATUS(m_pidStatus) << " err"
|
||||
<< strerror(errno) << endl);
|
||||
<< std::strerror(errno) << endl);
|
||||
m_readEof = true;
|
||||
m_pidExited = true;
|
||||
}
|
||||
|
|
@ -495,7 +496,7 @@ private:
|
|||
constexpr int P_WR = 1;
|
||||
|
||||
if (pipe(fd_stdin) != 0 || pipe(fd_stdout) != 0) {
|
||||
v3fatal("--pipe-filter: Can't pipe: " << strerror(errno));
|
||||
v3fatal("--pipe-filter: Can't pipe: " << std::strerror(errno));
|
||||
}
|
||||
if (fd_stdin[P_RD] <= 2 || fd_stdin[P_WR] <= 2 || fd_stdout[P_RD] <= 2
|
||||
|| fd_stdout[P_WR] <= 2) {
|
||||
|
|
@ -507,7 +508,7 @@ private:
|
|||
UINFO(1, "--pipe-filter: /bin/sh -c " << command << endl);
|
||||
|
||||
const pid_t pid = fork();
|
||||
if (pid < 0) v3fatal("--pipe-filter: fork failed: " << strerror(errno));
|
||||
if (pid < 0) v3fatal("--pipe-filter: fork failed: " << std::strerror(errno));
|
||||
if (pid == 0) { // Child
|
||||
UINFO(6, "In child\n");
|
||||
close(fd_stdin[P_WR]);
|
||||
|
|
@ -518,7 +519,7 @@ private:
|
|||
|
||||
execl("/bin/sh", "sh", "-c", command.c_str(), static_cast<char*>(nullptr));
|
||||
// Don't use v3fatal, we don't share the common structures any more
|
||||
fprintf(stderr, "--pipe-filter: exec failed: %s\n", strerror(errno));
|
||||
fprintf(stderr, "--pipe-filter: exec failed: %s\n", std::strerror(errno));
|
||||
_exit(1);
|
||||
} else { // Parent
|
||||
UINFO(6, "In parent, child pid " << pid << " stdin " << fd_stdin[P_WR] << "->"
|
||||
|
|
|
|||
24
src/V3File.h
24
src/V3File.h
|
|
@ -206,7 +206,7 @@ public:
|
|||
V3OutFile(V3OutFile&&) = delete;
|
||||
V3OutFile& operator=(V3OutFile&&) = delete;
|
||||
|
||||
virtual ~V3OutFile() override;
|
||||
~V3OutFile() override;
|
||||
void putsForceIncs();
|
||||
|
||||
private:
|
||||
|
|
@ -216,15 +216,15 @@ private:
|
|||
}
|
||||
|
||||
// CALLBACKS
|
||||
virtual void putcOutput(char chr) override {
|
||||
void putcOutput(char chr) override {
|
||||
m_bufferp->at(m_usedBytes++) = chr;
|
||||
if (VL_UNLIKELY(m_usedBytes >= WRITE_BUFFER_SIZE_BYTES)) writeBlock();
|
||||
}
|
||||
virtual void putsOutput(const char* str) override {
|
||||
void putsOutput(const char* str) override {
|
||||
std::size_t len = strlen(str);
|
||||
std::size_t availableBytes = WRITE_BUFFER_SIZE_BYTES - m_usedBytes;
|
||||
while (VL_UNLIKELY(len >= availableBytes)) {
|
||||
memcpy(m_bufferp->data() + m_usedBytes, str, availableBytes);
|
||||
std::memcpy(m_bufferp->data() + m_usedBytes, str, availableBytes);
|
||||
m_usedBytes = WRITE_BUFFER_SIZE_BYTES;
|
||||
writeBlock();
|
||||
str += availableBytes;
|
||||
|
|
@ -232,7 +232,7 @@ private:
|
|||
availableBytes = WRITE_BUFFER_SIZE_BYTES;
|
||||
}
|
||||
if (len > 0) {
|
||||
memcpy(m_bufferp->data() + m_usedBytes, str, len);
|
||||
std::memcpy(m_bufferp->data() + m_usedBytes, str, len);
|
||||
m_usedBytes += len;
|
||||
}
|
||||
}
|
||||
|
|
@ -246,7 +246,7 @@ public:
|
|||
: V3OutFile{filename, V3OutFormatter::LA_C} {
|
||||
resetPrivate();
|
||||
}
|
||||
virtual ~V3OutCFile() override = default;
|
||||
~V3OutCFile() override = default;
|
||||
virtual void putsHeader() { puts("// Verilated -*- C++ -*-\n"); }
|
||||
virtual void putsIntTopInclude() { putsForceIncs(); }
|
||||
virtual void putsGuard();
|
||||
|
|
@ -270,9 +270,9 @@ class V3OutScFile final : public V3OutCFile {
|
|||
public:
|
||||
explicit V3OutScFile(const string& filename)
|
||||
: V3OutCFile{filename} {}
|
||||
virtual ~V3OutScFile() override = default;
|
||||
virtual void putsHeader() override { puts("// Verilated -*- SystemC -*-\n"); }
|
||||
virtual void putsIntTopInclude() override {
|
||||
~V3OutScFile() override = default;
|
||||
void putsHeader() override { puts("// Verilated -*- SystemC -*-\n"); }
|
||||
void putsIntTopInclude() override {
|
||||
putsForceIncs();
|
||||
puts("#include \"systemc.h\"\n");
|
||||
puts("#include \"verilated_sc.h\"\n");
|
||||
|
|
@ -283,7 +283,7 @@ class V3OutVFile final : public V3OutFile {
|
|||
public:
|
||||
explicit V3OutVFile(const string& filename)
|
||||
: V3OutFile{filename, V3OutFormatter::LA_VERILOG} {}
|
||||
virtual ~V3OutVFile() override = default;
|
||||
~V3OutVFile() override = default;
|
||||
virtual void putsHeader() { puts("// Verilated -*- Verilog -*-\n"); }
|
||||
};
|
||||
|
||||
|
|
@ -293,7 +293,7 @@ public:
|
|||
: V3OutFile{filename, V3OutFormatter::LA_XML} {
|
||||
blockIndent(2);
|
||||
}
|
||||
virtual ~V3OutXmlFile() override = default;
|
||||
~V3OutXmlFile() override = default;
|
||||
virtual void putsHeader() { puts("<?xml version=\"1.0\" ?>\n"); }
|
||||
};
|
||||
|
||||
|
|
@ -301,7 +301,7 @@ class V3OutMkFile final : public V3OutFile {
|
|||
public:
|
||||
explicit V3OutMkFile(const string& filename)
|
||||
: V3OutFile{filename, V3OutFormatter::LA_MK} {}
|
||||
virtual ~V3OutMkFile() override = default;
|
||||
~V3OutMkFile() override = default;
|
||||
virtual void putsHeader() { puts("# Verilated -*- Makefile -*-\n"); }
|
||||
// No automatic indentation yet.
|
||||
void puts(const char* strg) { putsNoTracking(strg); }
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue