Merge from master for release.

This commit is contained in:
Wilson Snyder 2021-03-12 15:48:45 -05:00
commit f0d664530d
303 changed files with 7242 additions and 4632 deletions

View File

@ -1,6 +1,6 @@
---
name: Bug report
about: Something isn't working as expected, and it isn't "Unsupported." (Note our contributor agreement at https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.adoc)
about: Something isn't working as expected, and it isn't "Unsupported." (Note our contributor agreement at https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.rst)
title: ''
labels: new
assignees: ''

View File

@ -1,6 +1,6 @@
---
name: Feature Request
about: Request something should be supported, or a new feature added. (Note our contributor agreement at https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.adoc)
about: Request something should be supported, or a new feature added. (Note our contributor agreement at https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.rst)
title: ''
labels: new
assignees: ''

View File

@ -1,6 +1,6 @@
---
name: Q and A, or Other
about: Ask a question, not related to a specific bug or feature request. (Note our contributor agreement at https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.adoc)
about: Ask a question, not related to a specific bug or feature request. (Note our contributor agreement at https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.rst)
title: ''
labels: new
assignees: ''

View File

@ -1 +1 @@
We appreciate your contributing to Verilator. If this is your first commit, please add your name to docs/CONTRIBUTORS, and read our contributing guidelines in docs/CONTRIBUTING.adoc.
We appreciate your contributing to Verilator. If this is your first commit, please add your name to docs/CONTRIBUTORS, and read our contributing guidelines in docs/CONTRIBUTING.rst.

View File

@ -1,5 +1,5 @@
# DESCRIPTION: Github actions config
# This name is key to badges in README.adoc, so we use the name build
# This name is key to badges in README.rst, so we use the name build
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
name: build

View File

@ -1,5 +1,4 @@
# DESCRIPTION: Github actions config
# This name is key to badges in README.adoc, so we use the name build
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
name: clang-format

View File

@ -66,6 +66,12 @@ jobs:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
include:
- { test: dist, num: '' }
name: test-${{ matrix.test }}${{ matrix.num }}

22
Changes
View File

@ -2,6 +2,28 @@ Revision history for Verilator
The contributors that suggested a given feature are shown in []. Thanks!
* Verilator 4.200 2021-03-12
** Add simulation context (VerilatedContext) to allow multiple fully independent
models to be in the same process. Please see the updated examples. (#2660)
** Add context->time() and context->timeInc() API calls, to set simulation time.
These now are recommended in place of the legacy sc_time_stamp().
**** Converted Asciidoc documentation into reStructuredText (RST) format.
**** --inhibit-sim is planned for deprecation, file a bug if this is still being used.
**** Fix range inheritance on port without data type (#2753). [Embedded Go]
**** Fix slice-assign overflow (#2803) (#2811). [David Turner]
**** Fix interface array connection ordering broken in v4.110 (#2827). [Don Owen]
**** Fix or-reduction on different scopes broken in 4.110 (#2828). [Yinan Xu]
**** Fix MSVC++ compile error. (#2831) (#2833) [Drew Taussig]
* Verilator 4.110 2021-02-25

View File

@ -43,6 +43,7 @@ docs/clang-format.txt$
docs/doxygen-doc/.*
examples/xml_py/copied/
examples/xml_py/graph.*
sonar-project.properties
src/Makefile$
src/Makefile_obj$
include/verilated.mk$

View File

@ -124,7 +124,7 @@ DISTFILES_INC = $(INFOS) .gitignore \
Changes \
LICENSE \
MANIFEST.SKIP \
README.adoc \
README.rst \
verilator-config.cmake.in \
verilator-config-version.cmake.in \
bin/verilator \
@ -134,16 +134,16 @@ DISTFILES_INC = $(INFOS) .gitignore \
bin/verilator_includer \
bin/verilator_profcfunc \
docs/.gitignore \
docs/CONTRIBUTING.adoc \
docs/CONTRIBUTING.rst \
docs/CONTRIBUTORS \
docs/Makefile.in \
docs/TODO \
docs/doxygen-mainpage \
docs/doxygen.config \
docs/install.adoc \
docs/internals.adoc \
docs/install.rst \
docs/internals.rst \
docs/verilator_logo.png \
docs/xml.adoc \
docs/xml.rst \
install-sh configure *.pod \
include/*.[chv]* \
include/*.in \
@ -474,9 +474,7 @@ clang-format:
|| echo "*** You are not using clang-format 10.0, indents may differ from master's ***"
$(CLANGFORMAT) $(CLANGFORMAT_FLAGS) $(CLANGFORMAT_FILES)
YAPF = yapf3
YAPF_FLAGS = -i
YAPF_FILES = \
PY_PROGRAMS = \
examples/xml_py/vl_file_copy \
examples/xml_py/vl_hier_graph \
src/astgen \
@ -486,14 +484,32 @@ YAPF_FILES = \
src/flexfix \
src/vlcovgen \
nodist/code_coverage \
nodist/code_coverage.dat \
nodist/dot_importer \
nodist/fuzzer/actual_fail \
nodist/fuzzer/generate_dictionary \
nodist/install_test \
PY_FILES = \
$(PY_PROGRAMS) \
nodist/code_coverage.dat \
YAPF = yapf3
YAPF_FLAGS = -i
yapf:
$(YAPF) $(YAPF_FLAGS) $(YAPF_FILES)
$(YAPF) $(YAPF_FLAGS) $(PY_FILES)
FLAKE8 = flake8
FLAKE8_FLAGS = \
--extend-exclude=fastcov.py \
--ignore=E123,E129,E251,E501,W503,W504,E701
PYLINT = pylint
PYLINT_FLAGS = --disable=R0801
lint-py:
$(FLAKE8) $(FLAKE8_FLAGS) $(PY_PROGRAMS)
$(PYLINT) $(PYLINT_FLAGS) $(PY_PROGRAMS)
format-pl-exec:
-chmod a+x test_regress/t/*.pl

View File

@ -1,154 +0,0 @@
// Github doesn't render images unless absolute URL
:!toc:
ifdef::env-github[]
image:https://img.shields.io/badge/License-LGPL%20v3-blue.svg[license LGPLv3,link=https://www.gnu.org/licenses/lgpl-3.0]
image:https://img.shields.io/badge/License-Artistic%202.0-0298c3.svg[license Artistic-2.0,link=https://opensource.org/licenses/Artistic-2.0]
image:https://api.codacy.com/project/badge/Grade/fa78caa433c84a4ab9049c43e9debc6f[Code Quality,link=https://www.codacy.com/gh/verilator/verilator]
image:https://codecov.io/gh/verilator/verilator/branch/master/graph/badge.svg[Coverage,link=https://codecov.io/gh/verilator/verilator]
image:https://github.com/verilator/verilator/workflows/build/badge.svg[Build Status (GitHub),link=https://github.com/verilator/verilator/actions?query=workflow%3Abuild]
endif::[]
ifdef::env-github[]
:link_verilator_contributing: link:docs/CONTRIBUTING.adoc
:link_verilator_install: link:docs/install.adoc
endif::[]
ifndef::env-github[]
:link_verilator_contributing: https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.adoc
:link_verilator_install: https://verilator.org/install
endif::[]
:link_verilator_commercial_support: https://verilator.org/verilator_commercial_support
== Welcome to Verilator
[cols="a,a",indent=0,frame="none",grid="rows"]
|===
^.^| *Welcome to Verilator, the fastest Verilog/SystemVerilog simulator.*
+++ <br/> +++ &bullet; Accepts synthesizable Verilog or SystemVerilog
+++ <br/> +++ &bullet; Performs lint code-quality checks
+++ <br/> +++ &bullet; Compiles into multithreaded {cpp}, or SystemC
+++ <br/> +++ &bullet; Creates XML to front-end your own tools
<.^|image:https://www.veripool.org/img/verilator_256_200_min.png[Logo,256,200]
>.^|image:https://www.veripool.org/img/verilator_multithreaded_performance_bg-min.png[,388,178]
^.^| *Fast*
+++ <br/> +++ &bullet; Outperforms many commercial simulators
+++ <br/> +++ &bullet; Single- and multi-threaded output models
^.^| *Widely Used*
+++ <br/> +++ &bullet; Wide industry and academic deployment
+++ <br/> +++ &bullet; Out-of-the-box support from Arm, and RISC-V vendor IP
<.^|image:https://www.veripool.org/img/verilator_usage_400x200-min.png[,400,200]
>.^|image:https://www.veripool.org/img/verilator_community_400x125-min.png[,400,125]
^.^| *Community Driven & Openly Licensed*
+++ <br/> +++ &bullet; Guided by the https://chipsalliance.org/[CHIPS Alliance] and https://www.linuxfoundation.org/[Linux Foundation]
+++ <br/> +++ &bullet; Open, and free as in both speech and beer
+++ <br/> +++ &bullet; More simulation for your verification budget
^.^| *Commercial Support Available*
+++ <br/> +++ &bullet; Commercial support contracts
+++ <br/> +++ &bullet; Design support contracts
+++ <br/> +++ &bullet; Enhancement contracts
<.^|image:https://www.veripool.org/img/verilator_support_400x125-min.png[,400,125]
|===
== What Verilator Does
Verilator is invoked with parameters similar to GCC or Synopsys's VCS. It
"Verilates" the specified Verilog or SystemVerilog code by
reading it, 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 {cpp}/SystemC wrapper file, which instantiates the
"Verilated" model of the user's top level module. These {cpp}/SystemC
files are then compiled by a {cpp} compiler (gcc/clang/MSVC++). The
resulting executable performs the design simulation. Verilator also
supports linking its generated libraries, optionally encrypted, into other
simulators.
Verilator may not be the best choice if you are expecting a full featured
replacement for NC-Verilog, 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 http://iverilog.icarus.com[Icarus Verilog] for
this.) However, if you are looking for a path to migrate SystemVerilog to
{cpp} or SystemC, or your team is comfortable writing just a touch of {cpp}
code, Verilator is the tool for you.
== Performance
Verilator does not simply convert Verilog HDL to {cpp} or SystemC. Rather,
Verilator compiles your code into a much faster optimized and optionally
thread-partitioned model, which is in turn wrapped inside a
{cpp}/SystemC module. The results are a compiled
Verilog model that executes even on a single-thread over 10x faster than
standalone SystemC, and on a single thread is about 100 times faster than
interpreted Verilog simulators such as http://iverilog.icarus.com[Icarus
Verilog]. Another 2-10x speedup might be gained from 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.
For more information on how Verilator stacks up to some of the other
closed-sourced and open-sourced Verilog simulators, see the
https://www.veripool.org/verilog_sim_benchmarks.html[Verilog Simulator
Benchmarks]. (If you benchmark Verilator, please see the notes in the
https://verilator.org/verilator_doc.pdf[Verilator manual (PDF)], and also
if possible post on the forums the results; there may be additional tweaks
possible.)
== Installation & Documentation
For more information:
* {link_verilator_install}[Verilator installation and package directory
structure]
* https://verilator.org/verilator_doc.html[Verilator manual (HTML)],
or https://verilator.org/verilator_doc.pdf[Verilator manual (PDF)]
* https://github.com/verilator/verilator-announce[Subscribe to verilator announcements]
* https://verilator.org/forum[Verilator forum]
* https://verilator.org/issues[Verilator issues]
== Support
Verilator is a community project, guided by the
https://chipsalliance.org/[CHIPS Alliance] under the
https://www.linuxfoundation.org/[Linux Foundation].
We appreciate and welcome your contributions in whatever form; please see
{link_verilator_contributing}[Contributing to Verilator]. Thanks to our
https://verilator.org/verilator_doc.html#CONTRIBUTORS[Contributors and
Sponsors].
Verilator also supports and encourages commercial support models and
organizations; please see {link_verilator_commercial_support}[Verilator
Commercial Support].
== Related Projects
* http://gtkwave.sourceforge.net/[GTKwave] - Waveform viewer for Verilator
traces.
* http://iverilog.icarus.com[Icarus Verilog] - Icarus is a full featured
interpreted Verilog simulator. If Verilator does not support your needs,
perhaps Icarus may.
== Open License
Verilator is Copyright 2003-2021 by Wilson Snyder. (Report bugs to
https://verilator.org/issues[Verilator Issues].)
Verilator is free software; you can redistribute it and/or modify it under
the terms of either the GNU Lesser General Public License Version 3 or the
Perl Artistic License Version 2.0. See the documentation for more
details.

160
README.rst Normal file
View File

@ -0,0 +1,160 @@
.. Github doesn't render images unless absolute URL
.. Do not know of a conditional tag, "only: github" nor "github display" works
.. image:: https://img.shields.io/badge/License-LGPL%20v3-blue.svg
:target: https://www.gnu.org/licenses/lgpl-3.0]
.. image:: https://img.shields.io/badge/License-Artistic%202.0-0298c3.svg
:target: https://opensource.org/licenses/Artistic-2.0
.. image:: https://api.codacy.com/project/badge/Grade/fa78caa433c84a4ab9049c43e9debc6f
:target: https://www.codacy.com/gh/verilator/verilator
.. image:: https://codecov.io/gh/verilator/verilator/branch/master/graph/badge.svg
:target: https://codecov.io/gh/verilator/verilator
.. image:: https://github.com/verilator/verilator/workflows/build/badge.svg
:target: https://github.com/verilator/verilator/actions?query=workflow%3Abuild
Welcome to Verilator
====================
.. list-table::
* - **Welcome to Verilator, the fastest Verilog/SystemVerilog simulator.**
* Accepts synthesizable Verilog or SystemVerilog
* Performs lint code-quality checks
* Compiles into multithreaded C++, or SystemC
* Creates XML to front-end your own tools
- |Logo|
* - |verilator multithreaded performance bg min|
- **Fast**
* Outperforms many commercial simulators
* Single- and multi-threaded output models
* - **Widely Used**
* Wide industry and academic deployment
* Out-of-the-box support from Arm, and RISC-V vendor IP
- |verilator usage 400x200 min|
* - |verilator community 400x125 min|
- **Community Driven & Openly Licensed**
* Guided by the `CHIPS Alliance`_ and `Linux Foundation`_
* Open, and free as in both speech and beer
* More simulation for your verification budget
* - **Commercial Support Available**
* Commercial support contracts
* Design support contracts
* Enhancement contracts
- |verilator support 400x125 min|
What Verilator Does
===================
Verilator is invoked with parameters similar to GCC or Synopsys's VCS. It
"Verilates" the specified Verilog or SystemVerilog code by reading it,
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++). The resulting
executable performs the design simulation. Verilator also supports linking
its generated libraries, optionally encrypted, into other simulators.
Verilator may not be the best choice if you are expecting a full featured
replacement for NC-Verilog, 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.
Performance
===========
Verilator does not simply convert Verilog HDL to C++ or SystemC. Rather,
Verilator compiles your code into a much faster optimized and optionally
thread-partitioned model, which is in turn wrapped inside a C++/SystemC
module. The results are a compiled Verilog model that executes even on a
single-thread over 10x faster than standalone SystemC, and on a single
thread is about 100 times faster than interpreted Verilog simulators such
as `Icarus Verilog`_. Another 2-10x speedup might be gained from
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.
For more information on how Verilator stacks up to some of the other
closed-sourced and open-sourced Verilog simulators, see the `Verilog
Simulator Benchmarks
<https://www.veripool.org/verilog_sim_benchmarks.html>`_. (If you
benchmark Verilator, please see the notes in the `Verilator manual (PDF)
<https://verilator.org/verilator_doc.pdf>`_, and also if possible post on
the forums the results; there may be additional tweaks possible.)
Installation & Documentation
============================
For more information:
- `Verilator installation and package directory structure
<https://verilator.org/install>`_
- `Verilator manual (HTML) <https://verilator.org/verilator_doc.html>`_,
or `Verilator manual (PDF) <https://verilator.org/verilator_doc.pdf>`_
- `Subscribe to verilator announcements
<https://github.com/verilator/verilator-announce>`_
- `Verilator forum <https://verilator.org/forum>`_
- `Verilator issues <https://verilator.org/issues>`_
Support
=======
Verilator is a community project, guided by the `CHIPS Alliance`_ under the
`Linux Foundation`_.
We appreciate and welcome your contributions in whatever form; please see
`Contributing to Verilator
<https://github.com/verilator/verilator/blob/master/docs/CONTRIBUTING.rst>`_.
Thanks to our `Contributors and Sponsors
<https://verilator.org/verilator_doc.html#CONTRIBUTORS>`_.
Verilator also supports and encourages commercial support models and
organizations; please see `Verilator Commercial Support
<https://verilator.org/verilator_commercial_support>`_.
Related Projects
================
- `GTKwave <http://gtkwave.sourceforge.net/>`_ - Waveform viewer for
Verilator traces.
- `Icarus Verilog`_ - Icarus is a full featured interpreted Verilog
simulator. If Verilator does not support your needs, perhaps Icarus may.
Open License
============
Verilator is Copyright 2003-2021 by Wilson Snyder. (Report bugs to
`Verilator Issues <https://verilator.org/issues>`_.)
Verilator is free software; you can redistribute it and/or modify it under
the terms of either the GNU Lesser General Public License Version 3 or the
Perl Artistic License Version 2.0. See the documentation for more details.
.. _CHIPS Alliance: https://chipsalliance.org
.. _Icarus Verilog: http://iverilog.icarus.com
.. _Linux Foundation: https://www.linuxfoundation.org
.. |Logo| image:: https://www.veripool.org/img/verilator_256_200_min.png
.. |verilator multithreaded performance bg min| image:: https://www.veripool.org/img/verilator_multithreaded_performance_bg-min.png
.. |verilator usage 400x200 min| image:: https://www.veripool.org/img/verilator_usage_400x200-min.png
.. |verilator community 400x125 min| image:: https://www.veripool.org/img/verilator_community_400x125-min.png
.. |verilator support 400x125 min| image:: https://www.veripool.org/img/verilator_support_400x125-min.png

View File

@ -1953,7 +1953,8 @@ Displays program version and exits.
=head1 EXAMPLE C++ EXECUTION
We'll compile this example into C++.
We'll compile this example into C++. For an extended and commented version
of what this C++ code is doing, see examples/make_tracing_c/sim_main.cpp.
mkdir test_our
cd test_our
@ -1968,21 +1969,24 @@ We'll compile this example into C++.
#include "Vour.h"
#include "verilated.h"
int main(int argc, char** argv, char** env) {
Verilated::commandArgs(argc, argv);
Vour* top = new Vour;
while (!Verilated::gotFinish()) { top->eval(); }
VerilatedContext* contextp = new VerilatedContext;
contextp->commandArgs(argc, argv);
Vour* top = new Vour{contextp};
while (!contextp->gotFinish()) { top->eval(); }
delete top;
exit(0);
delete contextp;
return 0;
}
EOF
See the README in the source kit for various ways to install or point to
Verilator binaries. In brief, if you installed Verilator using the package
manager of your operating system, or did a "make install" to place
Verilator into your default path, you do not need anything special in your
environment, and should not have VERILATOR_ROOT set. However, if you
installed Verilator from sources and want to run Verilator out of where you
compiled Verilator, you need to point to the kit:
Next we need Verilator installed. See the README in the source kit for
various ways to install or point to Verilator binaries. In brief, if you
installed Verilator using the package manager of your operating system, or
did a "make install" to place Verilator into your default path, you do not
need anything special in your environment, and should not have
VERILATOR_ROOT set. However, if you installed Verilator from sources and
want to run Verilator out of where you compiled Verilator, you need to
point to the kit:
# See above; don't do this if using an OS-distributed Verilator
export VERILATOR_ROOT=/path/to/where/verilator/was/installed
@ -2037,13 +2041,12 @@ This is an example similar to the above, but using SystemC.
#include "Vour.h"
int sc_main(int argc, char** argv) {
Verilated::commandArgs(argc, argv);
sc_clock clk("clk", 10, SC_NS, 0.5, 3, SC_NS, true);
Vour* top;
top = new Vour("top");
sc_clock clk{"clk", 10, SC_NS, 0.5, 3, SC_NS, true};
Vour* top = new Vour{"top"};
top->clk(clk);
while (!Verilated::gotFinish()) { sc_start(1, SC_NS); }
delete top;
exit(0);
return 0;
}
EOF
@ -2101,15 +2104,15 @@ When using SystemC, evaluation of the Verilated model is managed by the SystemC
kernel, and for the most part can be ignored. When using C++, the user
must call eval(), or eval_step() and eval_end_step().
1. When there is a single design instantiated at the C++ level that needs to
evaluate, just call designp->eval().
1. When there is a single design instantiated at the C++ level that needs
to evaluate within a given context, just call designp->eval().
2. When there are multiple designs instantiated at the C++ level that
need to evaluate, call first_designp->eval_step() then ->eval_step() on all
other designs. Then call ->eval_end_step() on the first design then all
other designs. If there is only a single design, you would call
eval_step() then eval_end_step(); in fact eval() described above is just a
wrapper which calls these two functions.
2. When there are multiple designs instantiated at the C++ level that need
to evaluate within a context, call first_designp->eval_step() then
->eval_step() on all other designs. Then call ->eval_end_step() on the
first design then all other designs. If there is only a single design, you
would call eval_step() then eval_end_step(); in fact eval() described above
is just a wrapper which calls these two functions.
When eval() is called Verilator looks for changes in clock signals and
evaluates related sequential always blocks, such as computing always_ff @
@ -2124,7 +2127,7 @@ or all inputs go directly to always_ff statements, as is typical, then you
can change non-clock inputs on the negative edge of the input clock, which
will be faster as there will be fewer eval() calls.
For more information on evaluation, see docs/internals.adoc in the
For more information on evaluation, see docs/internals.rst in the
distribution.
@ -2704,7 +2707,7 @@ accesses the above signal "readme" would be:
read_and_check();
}
delete top;
exit(0);
return 0;
}
EOF
@ -5127,6 +5130,10 @@ Verilator currently requires C++11 or newer compilers. Verilator will
require C++14 or newer compilers for both compiling Verilator and compiling
Verilated models no sooner than January 2022.
=item --inhibit-sim
The --inhibit-sim option is planned for removal no sooner than July 2021.
=item Configuration File -msg
The -msg argument to lint_off has been replaced with -rule. -msg is
@ -5414,8 +5421,14 @@ controlled by --assert are disabled.
=item Why do I get "undefined reference to `sc_time_stamp()'"?
In C++ (non SystemC) code you need to define this function so that the
simulator knows the current time. See the "CONNECTING TO C++" examples.
In 4.200 and later, using the timeInc function is recommended instead. See
the "CONNECTING TO C++" examples. Some linkers (MSVC++) still require
sc_time_stamp() to be defined, either define this with ("double
sc_time_stamp() { return 0; }") or compile the Verilated code with
-DVL_TIME_CONTEXT.
Prior to Verilator 4.200, the sc_time_stamp function needs to be defined in
C++ (non SystemC) to return the current simulation time.
=item Why do I get "undefined reference to `VL_RAND_RESET_I' or `Verilated::...'"?
@ -5753,7 +5766,7 @@ L<verilator_coverage>, L<verilator_gantt>, L<verilator_profcfunc>, L<make>,
L<verilator --help> which is the source for this document,
and docs/internals.adoc in the distribution.
and docs/internals.rst in the distribution.
=cut

View File

@ -158,22 +158,25 @@ verilator_coverage - Verilator coverage analyzer
verilator_coverage -write-info merged.info -read <datafiles>...
Verilator_coverage processes Verilator coverage reports.
Verilator_coverage processes Verilated model-generated coverage reports.
With --anotate, it reads the specified data file and generates annotated
source code with coverage metrics annotated. If multiple coverage points
exist on the same line, additional lines will be inserted to report the
additional points.
With --annotate, it reads the specified coverage data file and generates
annotated source code with coverage metrics annotated. If multiple
coverage points exist on the same source code line, additional lines will
be inserted to report the additional points.
Additional Verilog-standard arguments specify the search paths necessary to
find the source code that the coverage analysis was performed on.
Additional Verilog-XL-style standard arguments specify the search paths
necessary to find the source code that the coverage analysis was performed
on.
To get correct coverage percentages, you may wish to read logs/coverage.dat
into Emacs and do a M-x keep-lines to include only those statistics of
interest.
To filter those items to be included in coverage, you may read
logs/coverage.dat into an editor and do a M-x keep-lines to include only
those statistics of interest and save to a new .dat file.
For Verilog conditions that should never occur, you should add a $stop
statement. This will remove the coverage during the next build.
For Verilog conditions that should never occur, either add a $stop
statement to the appropriate statement block, or see the Verilator
documentation on "// verilator coverage_off" and "coverage_off". This will
remove the coverage points after the model is re-Verilated.
=head1 ARGUMENTS
@ -181,12 +184,12 @@ statement. This will remove the coverage during the next build.
=item I<filename>
Specify input data file, may be repeated to read multiple inputs. If no
Specify input data file. May be repeated to read multiple inputs. If no
data file is specified, by default coverage.dat is read.
=item --annotate I<output_directory>
Sprcifies the directory name that source files with annotated coverage data
Specifies the directory name that source files with annotated coverage data
should be written to.
=item --annotate-all

View File

@ -544,9 +544,9 @@ scale printed, i.e. a certain about of time for each character width. The
Y-axis shows threads, each thread's execution is shown on one line. That
line shows "[" at the position in time when it executes.
Following the "[" is the cpu number the task executed on, followed by zero
Following the "[" is the CPU number the task executed on, followed by zero
or more "-" to make the width of the characters match the scaled execution
time, followed by a "]". If the scale is too small, the cpu number and
time, followed by a "]". If the scale is too small, the CPU number and
mtask number will not be printed. If the scale is very small, a "&"
indicates multiple mtasks started at that time position.

View File

@ -103,28 +103,64 @@ elif [ "$CI_BUILD_STAGE_NAME" = "test" ]; then
nodist/code_coverage --stages 1- --scenarios=--dist
;;
coverage-vlt-0)
nodist/code_coverage --stages 1- --scenarios=--vlt --hashset=0/4
nodist/code_coverage --stages 1- --scenarios=--vlt --hashset=0/10
;;
coverage-vlt-1)
nodist/code_coverage --stages 1- --scenarios=--vlt --hashset=1/4
nodist/code_coverage --stages 1- --scenarios=--vlt --hashset=1/10
;;
coverage-vlt-2)
nodist/code_coverage --stages 1- --scenarios=--vlt --hashset=2/4
nodist/code_coverage --stages 1- --scenarios=--vlt --hashset=2/10
;;
coverage-vlt-3)
nodist/code_coverage --stages 1- --scenarios=--vlt --hashset=3/4
nodist/code_coverage --stages 1- --scenarios=--vlt --hashset=3/10
;;
coverage-vlt-4)
nodist/code_coverage --stages 1- --scenarios=--vlt --hashset=4/10
;;
coverage-vlt-5)
nodist/code_coverage --stages 1- --scenarios=--vlt --hashset=5/10
;;
coverage-vlt-6)
nodist/code_coverage --stages 1- --scenarios=--vlt --hashset=6/10
;;
coverage-vlt-7)
nodist/code_coverage --stages 1- --scenarios=--vlt --hashset=7/10
;;
coverage-vlt-8)
nodist/code_coverage --stages 1- --scenarios=--vlt --hashset=8/10
;;
coverage-vlt-9)
nodist/code_coverage --stages 1- --scenarios=--vlt --hashset=9/10
;;
coverage-vltmt-0)
nodist/code_coverage --stages 1- --scenarios=--vltmt --hashset=0/4
nodist/code_coverage --stages 1- --scenarios=--vltmt --hashset=0/10
;;
coverage-vltmt-1)
nodist/code_coverage --stages 1- --scenarios=--vltmt --hashset=1/4
nodist/code_coverage --stages 1- --scenarios=--vltmt --hashset=1/10
;;
coverage-vltmt-2)
nodist/code_coverage --stages 1- --scenarios=--vltmt --hashset=2/4
nodist/code_coverage --stages 1- --scenarios=--vltmt --hashset=2/10
;;
coverage-vltmt-3)
nodist/code_coverage --stages 1- --scenarios=--vltmt --hashset=3/4
nodist/code_coverage --stages 1- --scenarios=--vltmt --hashset=3/10
;;
coverage-vltmt-4)
nodist/code_coverage --stages 1- --scenarios=--vltmt --hashset=4/10
;;
coverage-vltmt-5)
nodist/code_coverage --stages 1- --scenarios=--vltmt --hashset=5/10
;;
coverage-vltmt-6)
nodist/code_coverage --stages 1- --scenarios=--vltmt --hashset=6/10
;;
coverage-vltmt-7)
nodist/code_coverage --stages 1- --scenarios=--vltmt --hashset=7/10
;;
coverage-vltmt-8)
nodist/code_coverage --stages 1- --scenarios=--vltmt --hashset=8/10
;;
coverage-vltmt-9)
nodist/code_coverage --stages 1- --scenarios=--vltmt --hashset=9/10
;;
*)
fatal "Unknown test: $TESTS"

View File

@ -1,49 +0,0 @@
= Verilator Docker Build Environment
This Verilator Build container is set up to compile and test a Verilator
build. It uses the following parameters:
* Source repository (default: https://github.com/verilator/verilator)
* Source revision (default: master)
* Compiler (GCC 9.3.0, clang 10.0.0, default: 9.3.0)
The container is published as `verilator/verilator-buildenv` on
https://hub.docker.com/repository/docker/verilator/verilator-buildenv[docker hub].
To run the basic build using the current Verilator master:
docker run -ti verilator/verilator-buildenv
To also run tests:
docker run -ti verilator/verilator-buildenv test
To change the compiler:
docker run -ti -e CC=clang-10 -e CXX=clang++-10 verilator/verilator-buildenv test
The tests that involve gdb are not working due to security restrictions.
To run those too:
....
docker run -ti -e CC=clang-10 -e CXX=clang++-10 --cap-add=SYS_PTRACE --security-opt seccomp=unconfined verilator/verilator-buildenv test
....
Rather then building using a remote git repository you may prefer to use a
working copy on the local filesystem. Mount the local working copy path as
a volume and use that in place of git. When doing this be careful to have
all changes committed to the local git area. To build the current HEAD from
top of a repository:
....
docker run -ti -v ${PWD}:/tmp/repo -e REPO=/tmp/repo -e REV=`git rev-parse --short HEAD` --cap-add=SYS_PTRACE --security-opt seccomp=unconfined verilator/verilator-buildenv test
....
== Rebuilding
To rebuild the Verilator-buildenv docker image, run:
docker build .
This will also build SystemC under all supported compiler variants to
reduce the SystemC testing time.

View File

@ -0,0 +1,64 @@
================================
Verilator Build Docker Container
================================
This Verilator Build Docker Container is set up to compile and test a
Verilator build. It uses the following parameters:
- Source repository (default: https://github.com/verilator/verilator)
- Source revision (default: master)
- Compiler (GCC 9.3.0, clang 10.0.0, default: 9.3.0)
The container is published as ``verilator/verilator-buildenv`` on `docker
hub
<https://hub.docker.com/repository/docker/verilator/verilator-buildenv>`__.
To run the basic build using the current Verilator master:
::
docker run -ti verilator/verilator-buildenv
To also run tests:
::
docker run -ti verilator/verilator-buildenv test
To change the compiler:
::
docker run -ti -e CC=clang-10 -e CXX=clang++-10 verilator/verilator-buildenv test
The tests that involve gdb are not working due to security restrictions.
To run those too:
::
docker run -ti -e CC=clang-10 -e CXX=clang++-10 --cap-add=SYS_PTRACE --security-opt seccomp=unconfined verilator/verilator-buildenv test
Rather then building using a remote git repository you may prefer to use a
working copy on the local filesystem. Mount the local working copy path as
a volume and use that in place of git. When doing this be careful to have
all changes committed to the local git area. To build the current HEAD from
top of a repository:
::
docker run -ti -v ${PWD}:/tmp/repo -e REPO=/tmp/repo -e REV=`git rev-parse --short HEAD` --cap-add=SYS_PTRACE --security-opt seccomp=unconfined verilator/verilator-buildenv test
Rebuilding
==========
To rebuild the Verilator-buildenv docker image, run:
::
docker build .
This will also build SystemC under all supported compiler variants to
reduce the SystemC testing time.

View File

@ -1,59 +0,0 @@
= Verilator Executable Docker Container
The Verilator Executable Docker Container allows you to run Verilator
easily as a docker image, e.g.:
docker run -ti verilator/verilator:latest --version
This will install the container, run the latest Verilator and print
Verilator's version.
Containers are automatically built for all released versions, so you may
easily compare results across versions, e.g.:
docker run -ti verilator/verilator:4.030 --version
Verilator needs to read and write files on the local system. To simplify
this process, use the `verilator-docker` convenience script. This script
takes the version number, and all remaining arguments are passed through to
Verilator. e.g.:
./verilator-docker 4.030 --version
or
./verilator-docker 4.030 --cc test.v
If you prefer not to use `verilator-docker` you must give the container
access to your files as a volume with appropriate user rights. For example
to Verilate test.v:
....
docker run -ti -v ${PWD}:/work --user $(id -u):$(id -g) verilator/verilator:latest --cc test.v
....
This method can only access files below the current directory. An
alternative is setup the volume `-workdir`.
You can also work in the container by setting the entrypoint
(don't forget to mount a volume if you want your work persistent):
docker run -ti --entrypoint /bin/bash verilator/verilator:latest
You can also use the container to build Verilator at a specific
commit:
docker build --build-arg SOURCE_COMMIT=<commit> .
== Internals
The Dockerfile builds Verilator and removes the tree when completed to
reduce the image size. The entrypoint is set as a wrapper script
(`verilator-wrap.sh`). That script 1. calls Verilator, and 2. copies the
Verilated runtime files to the `obj_dir` or the `-Mdir` respectively. This
allows the user to have the files to they may later build the C++ output
with the matching runtime files. The wrapper also patches the Verilated
Makefile accordingly.
There is also a hook defined that is run by docker hub via automated
builds.

74
ci/docker/run/README.rst Normal file
View File

@ -0,0 +1,74 @@
=====================================
Verilator Executable Docker Container
=====================================
The Verilator Executable Docker Container allows you to run Verilator
easily as a docker image, e.g.:
::
docker run -ti verilator/verilator:latest --version
This will install the container, run the latest Verilator and print
Verilator's version.
Containers are automatically built for all released versions, so you may
easily compare results across versions, e.g.:
::
docker run -ti verilator/verilator:4.030 --version
Verilator needs to read and write files on the local system. To simplify
this process, use the ``verilator-docker`` convenience script. This script
takes the version number, and all remaining arguments are passed through to
Verilator. e.g.:
::
./verilator-docker 4.030 --version
or
::
./verilator-docker 4.030 --cc test.v
If you prefer not to use ``verilator-docker`` you must give the container
access to your files as a volume with appropriate user rights. For example
to Verilate test.v:
::
docker run -ti -v ${PWD}:/work --user $(id -u):$(id -g) verilator/verilator:latest --cc test.v
This method can only access files below the current directory. An
alternative is setup the volume ``-workdir``.
You can also work in the container by setting the entrypoint (don't forget
to mount a volume if you want your work persistent):
::
docker run -ti --entrypoint /bin/bash verilator/verilator:latest
You can also use the container to build Verilator at a specific commit:
::
docker build --build-arg SOURCE_COMMIT=<commit> .
Internals
=========
The Dockerfile builds Verilator and removes the tree when completed to
reduce the image size. The entrypoint is set as a wrapper script
(``verilator-wrap.sh``). That script 1. calls Verilator, and 2. copies the
Verilated runtime files to the ``obj_dir`` or the ``-Mdir``
respectively. This allows the user to have the files to they may later
build the C++ output with the matching runtime files. The wrapper also
patches the Verilated Makefile accordingly.
There is also a hook defined that is run by docker hub via automated
builds.

View File

@ -7,7 +7,7 @@
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
#AC_INIT([Verilator],[#.### devel])
AC_INIT([Verilator],[4.110 2021-02-25],
AC_INIT([Verilator],[4.200 2021-03-12],
[https://verilator.org],
[verilator],[https://verilator.org])
# When releasing, also update header of Changes file

View File

@ -1,82 +0,0 @@
= How to contribute to Verilator
Thanks for using Verilator! We welcome your contributions in whatever form.
This contributing document contains some suggestions that may make
contributions flow more efficiently.
==== Did you find a bug?
* Please **Ensure the bug was not already reported** by searching
https://verilator.org/issues[Verilator Issues].
* If you're unable to find an open issue addressing the problem,
https://verilator.org/issues/new[open a new Verilator issue].
** Be sure to include a **code sample** or an **executable test case**
demonstrating the bug and expected behavior that is not occurring.
** The ideal example works against other simulators, and is in the
test_regress/t test format, as described in
link:internals.adoc[docs/internals].
==== Did you write a patch that fixes a bug?
* Please https://verilator.org/issues/new[Open a new issue].
* You may attach a patch to the issue, or (preferred) may request a GitHub
pull request.
** Verilator uses GitHub Actions to provide continuous integration. You may
want to enable Actions on your GitHub branch to ensure your changes
keep the tests passing. See link:internals.adoc[docs/internals].
* Your source-code contributions must be certified as open source, under
the https://developercertificate.org/[Developer Certificate of
Origin]. On your first contribution, you must either:
** Have your patch include the addition of your name to
link:CONTRIBUTORS[docs/CONTRIBUTORS] (preferred).
** Use "git -s" as part of your commit. This adds a "signed-of-by"
attribute which will certify your contribution as described in the
https://github.com/wking/signed-off-by/blob/master/Documentation/SubmittingPatches[Signed-of-By
convention].
** Email, or post in an issue a statement that you certify your
contributions.
** In any of these cases your name will be added to
link:CONTRIBUTORS[docs/CONTRIBUTORS] and you are agreeing all future
contributions are also certified.
** We occasionally accept contributions where people do not want their name
published. Please email us; you must still privately certify your
contribution.
* Your test contributions are generally considered released into the
Creative Commons Public Domain (CC0), unless you request otherwise or put
a GNU/Artistic license on your file.
* Most important is we get your patch. If you'd like to clean up
indentation and related issues ahead of our feedback, that is
appreciated; please see the coding conventions in
link:internals.adoc[docs/internals].
==== Do you have questions?
* Please see FAQ section and rest of the
https://verilator.org/verilator_doc.html[Verilator manual],
or https://verilator.org/verilator_doc.pdf[Verilator manual (PDF)].
* Ask any question in the
https://verilator.org/forum[Verilator forum].
==== Code of Conduct
* Our contributors and participants pledge to make participation in our
project and our community a positive experience for everyone. We follow
the https://www.contributor-covenant.org/version/1/4/code-of-conduct.html[Contributor
Covenant version 1.4].
Thanks!

93
docs/CONTRIBUTING.rst Normal file
View File

@ -0,0 +1,93 @@
=========================
Contributing to Verilator
=========================
Thanks for using Verilator! We welcome your contributions in whatever form.
This contributing document contains some suggestions that may make
contributions flow more efficiently.
Did you find a bug?
===================
- Please **Ensure the bug was not already reported** by searching
`Verilator Issues <https://verilator.org/issues>`__.
- If you're unable to find an open issue addressing the problem, `open a
new Verilator issue <https://verilator.org/issues/new>`__.
- Be sure to include a **code sample** or an **executable test case**
demonstrating the bug and expected behavior that is not occurring.
- The ideal example works against other simulators, and is in the
test_regress/t test format, as described in `docs/internals
<internals.rst>`__.
Did you write a patch that fixes a bug?
=======================================
- Please `Open a new issue <https://verilator.org/issues/new>`__.
- You may attach a patch to the issue, or (preferred) may request a
GitHub pull request.
- Verilator uses GitHub Actions to provide continuous integration. You
may want to enable Actions on your GitHub branch to ensure your changes
keep the tests passing. See `docs/internals <internals.rst>`__.
- Your source-code contributions must be certified as open source,
under the `Developer Certificate of
Origin <https://developercertificate.org/>`__. On your first
contribution, you must either:
- Have your patch include the addition of your name to `docs/CONTRIBUTORS
<CONTRIBUTORS>`__ (preferred).
- Use "git -s" as part of your commit. This adds a "signed-of-by"
attribute which will certify your contribution as described in the
`Signed-of-By convention
<https://github.com/wking/signed-off-by/blob/master/Documentation/SubmittingPatches>`__.
- Email, or post in an issue a statement that you certify your
contributions.
- In any of these cases your name will be added to `docs/CONTRIBUTORS
<CONTRIBUTORS>`__ and you are agreeing all future contributions are
also certified.
- We occasionally accept contributions where people do not want their
name published. Please email us; you must still privately certify your
contribution.
- Your test contributions are generally considered released into the
Creative Commons Public Domain (CC0), unless you request otherwise or
put a GNU/Artistic license on your file.
- Most important is we get your patch. If youd like to clean up
indentation and related issues ahead of our feedback, that is
appreciated; please see the coding conventions in `docs/internals
<internals.rst>`__.
Do you have questions?
======================
- Please see FAQ section and rest of the `Verilator
manual <https://verilator.org/verilator_doc.html>`__, or `Verilator
manual (PDF) <https://verilator.org/verilator_doc.pdf>`__.
- Ask any question in the `Verilator forum
<https://verilator.org/forum>`__.
Code of Conduct
===============
- Our contributors and participants pledge to make participation in our
project and our community a positive experience for everyone. We follow
the `Contributor Covenant version 1.4
<https://www.contributor-covenant.org/version/1/4/code-of-conduct.html>`__.
Thanks!

View File

@ -12,6 +12,7 @@ Conor McCullough
Dan Petrisko
David Horton
David Stanford
David Turner
Driss Hafdi
Edgar E. Iglesias
Eric Rippey
@ -89,3 +90,4 @@ Yuri Victorovich
Yutetsu TAKATSUKASA
Yves Mathieu
HyungKi Jeong
Drew Taussig

View File

@ -19,8 +19,8 @@
#### Start of system configuration section. ####
ASCIIDOCTOR = asciidoctor
DOXYGEN = doxygen
RST2HTML = rst2html
#### End of system configuration section. ####
######################################################################
@ -30,8 +30,8 @@ DOXYGEN = doxygen
default:
@echo "error: make not supported here, run 'make docs' from Verilator top-level"
%.html: %.adoc
$(ASCIIDOCTOR) $< -n -o $@
%.html: %.rst
$(RST2HTML) $< $@
clean mostlyclean distclean maintainer-clean::
rm -f $(SCRIPTS) *.tmp

View File

@ -1,303 +0,0 @@
= Verilator Installation
:toc: right
// Github doesn't render unless absolute URL
image::https://www.veripool.org/img/verilator_256_200_min.png[Logo,256,200,role="right"]
== Introduction
This discusses how to install Verilator. For more general information
please see https://verilator.org[verilator.org].
== Quick-start
=== Install From a Package Manager
Using a distribution's package manager is the easiest way to get
started. (Note packages are unlikely to have the most recent version, so
Git, below, maybe a better alternative.) To install as a package:
apt-get install verilator
If this works, skip down to <<Running Verilator>>.
=== Docker
Verilator is available in pre-built Docker containers. See
https://github.com/verilator/verilator/blob/master/ci/docker/run/README.adoc
=== Git
Installing Verilator with Git provides the most flexibility.
For additional options and details see the additional sections below. In
brief:
// Also update README
....
# Prerequisites:
#sudo apt-get install git make autoconf g++ flex bison
#sudo apt-get install libfl2 # Ubuntu only (ignore if gives error)
#sudo apt-get install libfl-dev # Ubuntu only (ignore if gives error)
git clone https://github.com/verilator/verilator # Only first time
## Note the URL above is not a page you can see with a browser, it's for git only
# Every time you need to build:
unsetenv VERILATOR_ROOT # For csh; ignore error if on bash
unset VERILATOR_ROOT # For bash
cd verilator
git pull # Make sure git repository is up-to-date
git tag # See what versions exist
#git checkout master # Use development branch (e.g. recent bug fixes)
#git checkout stable # Use most recent stable release
#git checkout v{version} # Switch to specified release version
autoconf # Create ./configure script
./configure
make
sudo make install
# Now see "man verilator" or online verilator.pdf's for the example tutorials
....
If this works, skip down to <<Running Verilator>>.
== Detailed Build Instructions
This section describes details of the build process, and assumes you are
building from Git or a tarball. For using a pre-built binary for your
Linux distribution, see instead <<Install From a Package Manager>>.
=== OS Requirements
Verilator is developed and has primary testing on Ubuntu, with additional
testing on FreeBSD and Apple OS-X. Versions have also built on Redhat
Linux, HPUX and Solaris. It should run with minor porting on any
GNU/Linux-ish platform. Verilator also works on Windows under Cygwin, and
Windows under MinGW (gcc -mno-cygwin). Verilated output (not Verilator
itself) compiles under all the options above, plus MSVC++.
=== Install Prerequisites
To build or run Verilator you need these standard packages:
sudo apt-get install perl python3 make
sudo apt-get install g++ # Alternatively, clang
sudo apt-get install libgz # Non-Ubuntu (ignore if gives error)
sudo apt-get install libfl2 libfl-dev zlibc zlib1g zlib1g-dev # Ubuntu only (ignore if gives error)
To build or run the following are optional but should be installed for
good performance:
sudo apt-get install ccache # If present at build, needed for run
sudo apt-get install libgoogle-perftools-dev numactl perl-doc
To build Verilator you will need to install these packages; these do not
need to be present to run Verilator:
sudo apt-get install git autoconf flex bison
Those developing Verilator itself may also want these (see internals.adoc):
sudo apt-get install gdb asciidoctor graphviz cmake clang clang-format gprof lcov
cpan install Pod::Perldoc
cpan install Parallel::Forker
==== Install SystemC
If you will be using SystemC (vs straight C++ output), download
https://www.accellera.org/downloads/standards/systemc[SystemC].
Follow their installation instructions. You will need to set `SYSTEMC_INCLUDE`
to point to the include directory with `systemc.h` in it, and `SYSTEMC_LIBDIR`
to points to the directory with `libsystemc.a` in it. (Older installations
may set `SYSTEMC` and `SYSTEMC_ARCH` instead.)
==== Install GTKWave
To make use of Verilator FST tracing you will want
http://gtkwave.sourceforge.net/[GTKwave] installed, however this is not
required at Verilator build time.
=== Obtain Sources
You may use Git or a tarball for the sources. Git is the supported option.
(If using a historical build that uses a tarball, tarballs are obtained
from https://www.veripool.org/projects/verilator/wiki/Download[Verilator
Downloads]; we presume you know how to use it, and is not described here.)
Get the sources from the repository: (You need do this only once, ever.)
git clone https://github.com/verilator/verilator # Only first time
## Note the URL above is not a page you can see with a browser, it's for git only
Enter the checkout and determine what version/branch to use:
cd verilator
git pull # Make sure we're up-to-date
git tag # See what versions exist
#git checkout master # Use development branch (e.g. recent bug fix)
#git checkout stable # Use most recent release
#git checkout v{version} # Switch to specified release version
=== Auto Configure
Create the configuration script:
autoconf # Create ./configure script
=== Eventual Installation Options
Before configuring the build, you have to decide how you're going to
eventually install the kit. Verilator will be compiling the current value
of `VERILATOR_ROOT`, `SYSTEMC_INCLUDE`, and `SYSTEMC_LIBDIR` as defaults
into the executable, so they must be correct before configuring.
These are the options:
==== 1. Run-in-Place from VERILATOR_ROOT
Our personal favorite is to always run Verilator in-place from its Git
directory. This allows the easiest experimentation and upgrading, and
allows many versions of Verilator to co-exist on a system.
export VERILATOR_ROOT=`pwd` # if your shell is bash
setenv VERILATOR_ROOT `pwd` # if your shell is csh
./configure
# Running will use files from $VERILATOR_ROOT, so no install needed
Note after installing (below steps), a calling program or shell must set
the environment variable `VERILATOR_ROOT` to point to this Git directory,
then execute `$VERILATOR_ROOT/bin/verilator`, which will find the path to
all needed files.
==== 2. Install into a CAD Disk
You may eventually be installing onto a project/company-wide "CAD" tools
disk that may support multiple versions of every tool. Target the build to
a destination directory name that includes the Verilator version name:
unset VERILATOR_ROOT # if your shell is bash
unsetenv VERILATOR_ROOT # if your shell is csh
# For the tarball, use the version number instead of git describe
./configure --prefix /CAD_DISK/verilator/`git describe | sed "s/verilator_//"`
Note after installing (below steps), if you use
http://modules.sourceforge.net/[modulecmd], you'll want a module file like
the following:
.modulecmd's verilator/version file
----
set install_root /CAD_DISK/verilator/{version-number-used-above}
unsetenv VERILATOR_ROOT
prepend-path PATH $install_root/bin
prepend-path MANPATH $install_root/man
prepend-path PKG_CONFIG_PATH $install_root/share/pkgconfig
----
==== 3. Install into a Specific Path
You may eventually install Verilator into a specific installation prefix,
as most GNU tools support:
unset VERILATOR_ROOT # if your shell is bash
unsetenv VERILATOR_ROOT # if your shell is csh
./configure --prefix /opt/verilator-VERSION
Then after installing (below steps) you will need to add
`/opt/verilator-VERSION/bin` to `$PATH`.
==== 4. Install System Globally
The final option is to eventually install Verilator globally, using the
normal system paths:
unset VERILATOR_ROOT # if your shell is bash
unsetenv VERILATOR_ROOT # if your shell is csh
./configure
Then after installing (below) the binary directories should already be in
your `$PATH`.
=== Configure
The command to configure the package was described in the previous step.
Developers should configure to have more complete developer tests.
Additional packages may be required for these tests.
export VERILATOR_AUTHOR_SITE=1 # Put in your .bashrc
./configure --enable-longtests ...above options...
=== Compile
Compile Verilator:
make -j
=== Test
Check the compilation by running self-tests:
make test
=== Install
If you used any but the <<1. Run-in-Place from VERILATOR_ROOT>> scheme,
install to the OS-standard place:
make install
== Running Verilator
To run Verilator, see the example sections in the
https://verilator.org/verilator_doc.html[Verilator manual (HTML)],
or https://verilator.org/verilator_doc.pdf[Verilator manual (PDF)].
Also see the `examples/` directory that is part of the kit, and is installed
(in a OS-specific place, often in e.g. `/usr/local/share/verilator/examples`).
cd examples/make_hello_c
make
Note if you did a `make install` above you should not have `VERILATOR_ROOT`
set in your environment; it is built into the executable.
== Announcements
To get notified of new releases, go to
https://github.com/verilator/verilator-announce[Verilator announcement
repository] and follow the instructions there.
== Directory Structure
Some relevant files and directories in this package are as follows:
Changes => Version history
README.adoc => This document
bin/verilator => Compiler wrapper invoked to Verilate code
docs/ => Additional documentation
examples/make_hello_c => Example GNU-make simple Verilog->C++ conversion
examples/make_hello_sc => Example GNU-make simple Verilog->SystemC conversion
examples/make_tracing_c => Example GNU-make Verilog->C++ with tracing
examples/make_tracing_sc => Example GNU-make Verilog->SystemC with tracing
examples/make_protect_lib => Example using --protect-lib
examples/cmake_hello_c => Example building make_hello_c with CMake
examples/cmake_hello_sc => Example building make_hello_sc with CMake
examples/cmake_tracing_c => Example building make_tracing_c with CMake
examples/cmake_tracing_sc => Example building make_tracing_sc with CMake
examples/cmake_protect_lib => Example building make_protect_lib with CMake
include/ => Files that should be in your -I compiler path
include/verilated*.cpp => Global routines to link into your simulator
include/verilated*.h => Global headers
include/verilated.mk => Common Makefile
src/ => Translator source code
test_regress => Internal tests
For files created after a design is Verilated, see the
https://verilator.org/verilator_doc.html[Verilator manual (HTML)],
or https://verilator.org/verilator_doc.pdf[Verilator manual (PDF)].
== License
Copyright 2008-2021 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0.
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0

397
docs/install.rst Normal file
View File

@ -0,0 +1,397 @@
|Logo|
======================
Verilator Installation
======================
.. contents::
:depth: 3
Introduction
============
This discusses how to install Verilator. For more general information
please see `verilator.org <https://verilator.org>`__.
Quick-start
===========
Install From a Package Manager
------------------------------
Using a distribution's package manager is the easiest way to get
started. (Note packages are unlikely to have the most recent version, so
Git, below, maybe a better alternative.) To install as a package:
::
apt-get install verilator
If this works, skip down to `Running Verilator <#_running_verilator>`__.
Docker
------
Verilator is available in pre-built Docker containers. See
https://github.com/verilator/verilator/blob/master/ci/docker/run/README.rst
Git
---
Installing Verilator with Git provides the most flexibility. For
additional options and details see the additional sections below. In
brief:
::
# Prerequisites:
#sudo apt-get install git make autoconf g++ flex bison
#sudo apt-get install libfl2 # Ubuntu only (ignore if gives error)
#sudo apt-get install libfl-dev # Ubuntu only (ignore if gives error)
git clone https://github.com/verilator/verilator # Only first time
## Note the URL above is not a page you can see with a browser, it's for git only
# Every time you need to build:
unsetenv VERILATOR_ROOT # For csh; ignore error if on bash
unset VERILATOR_ROOT # For bash
cd verilator
git pull # Make sure git repository is up-to-date
git tag # See what versions exist
#git checkout master # Use development branch (e.g. recent bug fixes)
#git checkout stable # Use most recent stable release
#git checkout v{version} # Switch to specified release version
autoconf # Create ./configure script
./configure
make
sudo make install
# Now see "man verilator" or online verilator.pdf's for the example tutorials
If this works, skip down to `Running Verilator <#_running_verilator>`__.
Detailed Build Instructions
===========================
This section describes details of the build process, and assumes you are
building from Git or a tarball. For using a pre-built binary for your
Linux distribution, see instead `Install From a Package
Manager <#_install_from_a_package_manager>`__.
OS Requirements
---------------
Verilator is developed and has primary testing on Ubuntu, with additional
testing on FreeBSD and Apple OS-X. Versions have also built on Redhat
Linux, HPUX and Solaris. It should run with minor porting on any
GNU/Linux-ish platform. Verilator also works on Windows under Cygwin, and
Windows under MinGW (gcc -mno-cygwin). Verilated output (not Verilator
itself) compiles under all the options above, plus MSVC++.
Install Prerequisites
---------------------
To build or run Verilator you need these standard packages:
::
sudo apt-get install perl python3 make
sudo apt-get install g++ # Alternatively, clang
sudo apt-get install libgz # Non-Ubuntu (ignore if gives error)
sudo apt-get install libfl2 libfl-dev zlibc zlib1g zlib1g-dev # Ubuntu only (ignore if gives error)
To build or run the following are optional but should be installed for good
performance:
::
sudo apt-get install ccache # If present at build, needed for run
sudo apt-get install libgoogle-perftools-dev numactl perl-doc
To build Verilator you will need to install these packages; these do not
need to be present to run Verilator:
::
sudo apt-get install git autoconf flex bison
Those developing Verilator itself may also want these (see internals.rst):
::
sudo apt-get install gdb asciidoctor graphviz cmake clang clang-format gprof lcov
cpan install Pod::Perldoc
cpan install Parallel::Forker
Install SystemC
~~~~~~~~~~~~~~~
If you will be using SystemC (vs straight C++ output), download `SystemC
<https://www.accellera.org/downloads/standards/systemc>`__. Follow their
installation instructions. You will need to set ``SYSTEMC_INCLUDE`` to
point to the include directory with ``systemc.h`` in it, and
``SYSTEMC_LIBDIR`` to points to the directory with ``libsystemc.a`` in
it. (Older installations may set ``SYSTEMC`` and ``SYSTEMC_ARCH`` instead.)
Install GTKWave
~~~~~~~~~~~~~~~
To make use of Verilator FST tracing you will want `GTKwave
<http://gtkwave.sourceforge.net/>`__ installed, however this is not
required at Verilator build time.
Obtain Sources
--------------
You may use Git or a tarball for the sources. Git is the supported
option. (If using a historical build that uses a tarball, tarballs are
obtained from `Verilator Downloads
<https://www.veripool.org/projects/verilator/wiki/Download>`__; we presume
you know how to use it, and is not described here.)
Get the sources from the repository: (You need do this only once, ever.)
::
git clone https://github.com/verilator/verilator # Only first time
## Note the URL above is not a page you can see with a browser, it's for git only
Enter the checkout and determine what version/branch to use:
::
cd verilator
git pull # Make sure we're up-to-date
git tag # See what versions exist
#git checkout master # Use development branch (e.g. recent bug fix)
#git checkout stable # Use most recent release
#git checkout v{version} # Switch to specified release version
Auto Configure
--------------
Create the configuration script:
::
autoconf # Create ./configure script
Eventual Installation Options
-----------------------------
Before configuring the build, you have to decide how you're going to
eventually install the kit. Verilator will be compiling the current value
of ``VERILATOR_ROOT``, ``SYSTEMC_INCLUDE``, and ``SYSTEMC_LIBDIR`` as
defaults into the executable, so they must be correct before configuring.
These are the options:
1. Run-in-Place from VERILATOR_ROOT
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Our personal favorite is to always run Verilator in-place from its Git
directory. This allows the easiest experimentation and upgrading, and
allows many versions of Verilator to co-exist on a system.
::
export VERILATOR_ROOT=`pwd` # if your shell is bash
setenv VERILATOR_ROOT `pwd` # if your shell is csh
./configure
# Running will use files from $VERILATOR_ROOT, so no install needed
Note after installing (below steps), a calling program or shell must set
the environment variable ``VERILATOR_ROOT`` to point to this Git directory,
then execute ``$VERILATOR_ROOT/bin/verilator``, which will find the path to
all needed files.
2. Install into a CAD Disk
~~~~~~~~~~~~~~~~~~~~~~~~~~
You may eventually be installing onto a project/company-wide "CAD" tools
disk that may support multiple versions of every tool. Target the build to
a destination directory name that includes the Verilator version name:
::
unset VERILATOR_ROOT # if your shell is bash
unsetenv VERILATOR_ROOT # if your shell is csh
# For the tarball, use the version number instead of git describe
./configure --prefix /CAD_DISK/verilator/`git describe | sed "s/verilator_//"`
Note after installing (below steps), if you use `modulecmd
<http://modules.sourceforge.net/>`__, you'll want a module file like the
following:
**modulecmd's verilator/version file.**
::
set install_root /CAD_DISK/verilator/{version-number-used-above}
unsetenv VERILATOR_ROOT
prepend-path PATH $install_root/bin
prepend-path MANPATH $install_root/man
prepend-path PKG_CONFIG_PATH $install_root/share/pkgconfig
3. Install into a Specific Path
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You may eventually install Verilator into a specific installation prefix,
as most GNU tools support:
::
unset VERILATOR_ROOT # if your shell is bash
unsetenv VERILATOR_ROOT # if your shell is csh
./configure --prefix /opt/verilator-VERSION
Then after installing (below steps) you will need to add
``/opt/verilator-VERSION/bin`` to ``$PATH``.
4. Install System Globally
~~~~~~~~~~~~~~~~~~~~~~~~~~
The final option is to eventually install Verilator globally, using the
normal system paths:
::
unset VERILATOR_ROOT # if your shell is bash
unsetenv VERILATOR_ROOT # if your shell is csh
./configure
Then after installing (below) the binary directories should already be
in your ``$PATH``.
Configure
---------
The command to configure the package was described in the previous step.
Developers should configure to have more complete developer tests.
Additional packages may be required for these tests.
::
export VERILATOR_AUTHOR_SITE=1 # Put in your .bashrc
./configure --enable-longtests ...above options...
Compile
-------
Compile Verilator:
::
make -j
Test
----
Check the compilation by running self-tests:
::
make test
Install
-------
If you used any but the `1. Run-in-Place from VERILATOR_ROOT
<#_1_run_in_place_from_verilator_root>`__ scheme, install to the
OS-standard place:
::
make install
Running Verilator
=================
To run Verilator, see the example sections in the `Verilator manual (HTML)
<https://verilator.org/verilator_doc.html>`__, or `Verilator manual (PDF)
<https://verilator.org/verilator_doc.pdf>`__.
Also see the ``examples/`` directory that is part of the kit, and is
installed (in a OS-specific place, often in e.g.
``/usr/local/share/verilator/examples``).
::
cd examples/make_hello_c
make
Note if you did a ``make install`` above you should not have
``VERILATOR_ROOT`` set in your environment; it is built into the
executable.
Announcements
=============
To get notified of new releases, go to `Verilator announcement repository
<https://github.com/verilator/verilator-announce>`__ and follow the
instructions there.
Directory Structure
===================
Some relevant files and directories in this package are as follows:
::
Changes => Version history
README.rst => This document
bin/verilator => Compiler wrapper invoked to Verilate code
docs/ => Additional documentation
examples/make_hello_c => Example GNU-make simple Verilog->C++ conversion
examples/make_hello_sc => Example GNU-make simple Verilog->SystemC conversion
examples/make_tracing_c => Example GNU-make Verilog->C++ with tracing
examples/make_tracing_sc => Example GNU-make Verilog->SystemC with tracing
examples/make_protect_lib => Example using --protect-lib
examples/cmake_hello_c => Example building make_hello_c with CMake
examples/cmake_hello_sc => Example building make_hello_sc with CMake
examples/cmake_tracing_c => Example building make_tracing_c with CMake
examples/cmake_tracing_sc => Example building make_tracing_sc with CMake
examples/cmake_protect_lib => Example building make_protect_lib with CMake
include/ => Files that should be in your -I compiler path
include/verilated*.cpp => Global routines to link into your simulator
include/verilated*.h => Global headers
include/verilated.mk => Common Makefile
src/ => Translator source code
test_regress => Internal tests
For files created after a design is Verilated, see the `Verilator manual
(HTML) <https://verilator.org/verilator_doc.html>`__, or `Verilator
manual (PDF) <https://verilator.org/verilator_doc.pdf>`__.
License
=======
Copyright 2008-2021 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0.
.. |Logo| image:: https://www.veripool.org/img/verilator_256_200_min.png

File diff suppressed because it is too large Load Diff

1213
docs/internals.rst Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,72 +0,0 @@
= Verilator XML Output
:toc: right
// Github doesn't render unless absolute URL
image::https://www.veripool.org/img/verilator_256_200_min.png[Logo,256,200,role="right"]
== Introduction
This document describes Verilator's XML output. For more general information
please see https://verilator.org[verilator.org].
== General
Verilator's XML output is enabled with the `--xml-only` flag. It contains
limited information about the elaborated design including files, modules,
instance hierarchy, logic and data types. There is no formal schema since part
of the structure of the XML document matches the compiled code which would
require the schema to describe legal SystemVerilog structure. The intended
usage is to enable other downstream tools to take advantage of Verilator's
parser.
== Structure
The XML document consists of 4 sections within the top level `verilator_xml`
element:
`<files>`...`</files>`::
This section contains a list of all design files read, including the
built-in constructs and the command line as their own entries. Each
`<file>` has an attribute `id` which is a short ASCII string unique to that
file. Other elements' `loc` attributes use this id to refer to a particular
file.
`<module_files>`...`</module_files>`::
All files containing Verilog module definitions are listed in this section.
This element's contents is a subset of the `<files>` element's contents.
`<cells>`...`</cells>`::
The cells section of the XML document contains the design instance
hierarchy. Each instance is represented with the `<cell>` element with the
following attributes:
* `fl` (deprecated): The file id and line number where the module was
instanced. Use `loc` instead.
* `loc`: The file id, first line number, last line number, first column
number and last column number of the identifier where the module was
instanced, separated by commas.
* `name`: The instance name.
* `submodname`: The module name uniquified with particular parameter values (if any).
* `hier`: The full hierarchy path.
`<netlist>`...`</netlist>`::
The netlist section contains a number of `<module>`...`</module>` elements,
each describing the contents of that module, and a single `<typetable>`...
`</typetable>` element which lists all used types used within the
modules. Each type has a numeric `id` attribute that is referred to by
elements in the `<module>` elements using the `dtype_id` attribute.
== Distribution
Copyright 2020-2021 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0.
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0

81
docs/xml.rst Normal file
View File

@ -0,0 +1,81 @@
|Logo|
===========================
Verilator XML Output Format
===========================
Introduction
============
This document describes Verilator's XML output. For more general
information please see `verilator.org <https://verilator.org>`__.
General
=======
Verilator's XML output is enabled with the ``--xml-only`` flag. It contains
limited information about the elaborated design including files, modules,
instance hierarchy, logic and data types. There is no formal schema since
part of the structure of the XML document matches the compiled code which
would require the schema to describe legal SystemVerilog structure. The
intended usage is to enable other downstream tools to take advantage of
Verilator's parser.
Structure
=========
The XML document consists of 4 sections within the top level
``verilator_xml`` element:
``<files>``\ ... ``</files>``
This section contains a list of all design files read, including the
built-in constructs and the command line as their own entries. Each
``<file>`` has an attribute ``id`` which is a short ASCII string
unique to that file. Other elements' ``loc`` attributes use this id
to refer to a particular file.
``<module_files>``\ ... ``</module_files>``
All files containing Verilog module definitions are listed in this
section. This element's contents is a subset of the ``<files>``
element's contents.
``<cells>``\ ... ``</cells>``
The cells section of the XML document contains the design instance
hierarchy. Each instance is represented with the ``<cell>`` element
with the following attributes:
- ``fl`` (deprecated): The file id and line number where the module
was instanced. Use ``loc`` instead.
- ``loc``: The file id, first line number, last line number, first
column number and last column number of the identifier where the
module was instanced, separated by commas.
- ``name``: The instance name.
- ``submodname``: The module name uniquified with particular
parameter values (if any).
- ``hier``: The full hierarchy path.
``<netlist>``\ ... ``</netlist>``
The netlist section contains a number of
``<module>``\ ... ``</module>`` elements, each describing the
contents of that module, and a single ``<typetable>``\ ...
``</typetable>`` element which lists all used types used within the
modules. Each type has a numeric ``id`` attribute that is referred to
by elements in the ``<module>`` elements using the ``dtype_id``
attribute.
.. __distribution:
Distribution
============
Copyright 2020-2021 by Wilson Snyder. Verilator is free software; you can
redistribute it and/or modify it under the terms of either the GNU Lesser
General Public License Version 3 or the Perl Artistic License Version 2.0.
.. |Logo| image:: https://www.veripool.org/img/verilator_256_200_min.png

View File

@ -26,7 +26,7 @@ int sc_main(int argc, char* argv[]) {
if (false && argc && argv) {}
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v"
Vtop* top = new Vtop("top");
Vtop* top = new Vtop{"top"};
// Initialize SC model
sc_start(1, SC_NS);

View File

@ -17,7 +17,7 @@ module secret_impl
logic [31:0] accum_q = 0;
logic [31:0] secret_value = 9;
initial $display("%m: initialized");
initial $display("[%0t] %m: initialized", $time);
always @(posedge clk) begin
accum_q <= accum_q + a;

View File

@ -16,25 +16,24 @@
#include <verilated_vcd_c.h>
#endif
vluint64_t main_time = 0;
double sc_time_stamp() { return main_time; }
int main(int argc, char** argv, char** env) {
if (false && argc && argv && env) {}
Verilated::debug(0);
Verilated::randReset(2);
Verilated::commandArgs(argc, argv);
// Construct context to hold simulation time, etc
VerilatedContext* contextp = new VerilatedContext;
contextp->debug(0);
contextp->randReset(2);
contextp->commandArgs(argc, argv);
// Construct the Verilated model, including the secret module
Vtop* top = new Vtop;
Vtop* top = new Vtop{contextp};
#if VM_TRACE
// When tracing, the contents of the secret module will not be seen
VerilatedVcdC* tfp = nullptr;
const char* flag = Verilated::commandArgsPlusMatch("trace");
const char* flag = contextp->commandArgsPlusMatch("trace");
if (flag && 0 == strcmp(flag, "+trace")) {
Verilated::traceEverOn(true);
contextp->traceEverOn(true);
VL_PRINTF("Enabling waves into logs/vlt_dump.vcd...\n");
tfp = new VerilatedVcdC;
top->trace(tfp, 99);
@ -46,12 +45,12 @@ int main(int argc, char** argv, char** env) {
top->clk = 0;
// Simulate until $finish
while (!Verilated::gotFinish()) {
main_time++;
while (!contextp->gotFinish()) {
contextp->timeInc(1);
top->clk = ~top->clk & 0x1;
top->eval();
#if VM_TRACE
if (tfp) tfp->dump(main_time);
if (tfp) tfp->dump(contextp->time());
#endif
}
@ -69,6 +68,8 @@ int main(int argc, char** argv, char** env) {
// Destroy model
delete top;
top = nullptr;
delete contextp;
contextp = nullptr;
// Return good completion status
// Don't use exit() or destructor won't get called

View File

@ -14,42 +14,45 @@
// Include model header, generated from Verilating "top.v"
#include "Vtop.h"
// Current simulation time (64-bit unsigned)
vluint64_t main_time = 0;
// Called by $time in Verilog
double sc_time_stamp() {
return main_time; // Note does conversion to real, to match SystemC
}
int main(int argc, char** argv, char** env) {
// This is a more complicated example, please also see the simpler examples/make_hello_c.
// Prevent unused variable warnings
if (false && argc && argv && env) {}
// Set debug level, 0 is off, 9 is highest presently used
// May be overridden by commandArgs
Verilated::debug(0);
// Randomization reset policy
// May be overridden by commandArgs
Verilated::randReset(2);
// Verilator must compute traced signals
Verilated::traceEverOn(true);
// Pass arguments so Verilated code can see them, e.g. $value$plusargs
// This needs to be called before you create any model
Verilated::commandArgs(argc, argv);
// Create logs/ directory in case we have traces to put under it
Verilated::mkdir("logs");
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v"
// Using unique_ptr is similar to "Vtop* top = new Vtop" then deleting at end
const std::unique_ptr<Vtop> top{new Vtop};
// Construct a VerilatedContext to hold simulation time, etc.
// Multiple modules (made later below with Vtop) may share the same
// context to share time, or modules may have different contexts if
// they should be independent from each other.
// Set some inputs
// Using unique_ptr is similar to
// "VerilatedContext* contextp = new VerilatedContext" then deleting at end.
const std::unique_ptr<VerilatedContext> contextp{new VerilatedContext};
// Set debug level, 0 is off, 9 is highest presently used
// May be overridden by commandArgs argument parsing
contextp->debug(0);
// Randomization reset policy
// May be overridden by commandArgs argument parsing
contextp->randReset(2);
// Verilator must compute traced signals
contextp->traceEverOn(true);
// Pass arguments so Verilated code can see them, e.g. $value$plusargs
// This needs to be called before you create any model
contextp->commandArgs(argc, argv);
// Construct the Verilated model, from Vtop.h generated from Verilating "top.v".
// Using unique_ptr is similar to "Vtop* top = new Vtop" then deleting at end.
// "TOP" will be the hierarchical name of the module.
const std::unique_ptr<Vtop> top{new Vtop{contextp.get(), "TOP"}};
// Set Vtop's input signals
top->reset_l = !0;
top->clk = 0;
top->in_small = 1;
@ -59,8 +62,19 @@ int main(int argc, char** argv, char** env) {
top->in_wide[2] = 0x3;
// Simulate until $finish
while (!Verilated::gotFinish()) {
main_time++; // Time passes...
while (!contextp->gotFinish()) {
// Historical note, before Verilator 4.200 Verilated::gotFinish()
// was used above in place of contextp->gotFinish().
// Most of the contextp-> calls can use Verilated:: calls instead;
// the Verilated:: versions simply assume there's a single context
// being used (per thread). It's faster and clearer to use the
// newer contextp-> versions.
contextp->timeInc(1); // 1 timeprecision period passes...
// Historical note, before Verilator 4.200 a sc_time_stamp()
// function was required instead of using timeInc. Once timeInc()
// is called (with non-zero), the Verilated libraries assume the
// new API, and sc_time_stamp() will no longer work.
// Toggle a fast (time/2 period) clock
top->clk = !top->clk;
@ -70,7 +84,7 @@ int main(int argc, char** argv, char** env) {
// this only on a negedge of clk, because we know
// reset is not sampled there.
if (!top->clk) {
if (main_time > 1 && main_time < 10) {
if (contextp->time() > 1 && contextp->time() < 10) {
top->reset_l = !1; // Assert reset
} else {
top->reset_l = !0; // Deassert reset
@ -82,23 +96,23 @@ int main(int argc, char** argv, char** env) {
// Evaluate model
// (If you have multiple models being simulated in the same
// timestep then instead of eval(), call eval_step() on each, then
// eval_end_step() on each.)
// eval_end_step() on each. See the manual.)
top->eval();
// Read outputs
VL_PRINTF("[%" VL_PRI64 "d] clk=%x rstl=%x iquad=%" VL_PRI64 "x"
" -> oquad=%" VL_PRI64 "x owide=%x_%08x_%08x\n",
main_time, top->clk, top->reset_l, top->in_quad, top->out_quad, top->out_wide[2],
top->out_wide[1], top->out_wide[0]);
contextp->time(), top->clk, top->reset_l, top->in_quad, top->out_quad,
top->out_wide[2], top->out_wide[1], top->out_wide[0]);
}
// Final model cleanup
top->final();
// Coverage analysis (since test passed)
// Coverage analysis (calling write only after the test is known to pass)
#if VM_COVERAGE
Verilated::mkdir("logs");
VerilatedCov::write("logs/coverage.dat");
contextp->coveragep()->write("logs/coverage.dat");
#endif
// Return good completion status

View File

@ -29,21 +29,26 @@ int sc_main(int argc, char* argv[]) {
// Prevent unused variable warnings
if (false && argc && argv) {}
// Create logs/ directory in case we have traces to put under it
Verilated::mkdir("logs");
// Set debug level, 0 is off, 9 is highest presently used
// May be overridden by commandArgs
// May be overridden by commandArgs argument parsing
Verilated::debug(0);
// Randomization reset policy
// May be overridden by commandArgs
// May be overridden by commandArgs argument parsing
Verilated::randReset(2);
#if VM_TRACE
// Before any evaluation, need to know to calculate those signals only used for tracing
Verilated::traceEverOn(true);
#endif
// Pass arguments so Verilated code can see them, e.g. $value$plusargs
// This needs to be called before you create any model
Verilated::commandArgs(argc, argv);
// Create logs/ directory in case we have traces to put under it
Verilated::mkdir("logs");
// General logfile
ios::sync_with_stdio();
@ -64,7 +69,7 @@ int sc_main(int argc, char* argv[]) {
// Using unique_ptr is similar to "Vtop* top = new Vtop" then deleting at end
const std::unique_ptr<Vtop> top{new Vtop{"top"}};
// Attach signals to the model
// Attach Vtop's signals to this upper model
top->clk(clk);
top->fastclk(fastclk);
top->reset_l(reset_l);
@ -75,11 +80,6 @@ int sc_main(int argc, char* argv[]) {
top->out_quad(out_quad);
top->out_wide(out_wide);
#if VM_TRACE
// Before any evaluation, need to know to calculate those signals only used for tracing
Verilated::traceEverOn(true);
#endif
// You must do one evaluation before enabling waves, in order to allow
// SystemC to interconnect everything for testing.
sc_start(1, SC_NS);
@ -128,7 +128,7 @@ int sc_main(int argc, char* argv[]) {
}
#endif
// Coverage analysis (since test passed)
// Coverage analysis (calling write only after the test is known to pass)
#if VM_COVERAGE
Verilated::mkdir("logs");
VerilatedCov::write("logs/coverage.dat");

View File

@ -1,16 +1,16 @@
#!/usr/bin/env python3
# -*- Python -*- See copyright, etc below
# pylint: disable=C0114,C0115,R0903
######################################################################
import argparse
import os
import re
import subprocess
import sys
import tempfile
import xml.etree.ElementTree as ET
from shutil import copy2
from pprint import pprint, pformat
# from pprint import pprint, pformat
#######################################################################
@ -22,19 +22,20 @@ class VlFileCopy:
# ideally this script would check against options mentioned in help
debug=0,
output_dir='copied'): # directory name we output file uses
self.debug = debug
xml_temp = tempfile.NamedTemporaryFile()
args = [
vargs = [
'--xml-output',
xml_temp.name,
'--bbox-sys', # Parse some stuff can't translate
'--bbox-unsup',
'--prefix vlxml'
] # So we know name of .xml output
args += verilator_args
self.run_verilator(args)
vargs += verilator_args
self.run_verilator(vargs)
self.tree = ET.parse(xml_temp.name)
os.makedirs(output_dir, 0o777, True)
@ -49,13 +50,13 @@ class VlFileCopy:
print("\tcp %s %s" % (filename, output_dir))
copy2(filename, output_dir)
def run_verilator(self, args):
def run_verilator(self, vargs):
"""Run Verilator command, check errors"""
if os.getenv("VERILATOR_ROOT"):
command = os.getenv("VERILATOR_ROOT") + "/bin/verilator"
else:
command = "verilator"
command += ' ' + ' '.join(args)
command += ' ' + ' '.join(vargs)
if self.debug:
print("\t%s " % command)
status = subprocess.call(command, shell=True)
@ -119,6 +120,6 @@ SPDX-License-Identifier: CC0-1.0
fc = VlFileCopy(output_dir=args.odir, debug=args.debug, verilator_args=rem)
######################################################################
### Local Variables:
### compile-command: "./vl_file_copy -h ; VERILATOR_ROOT=$V4 ./vl_file_copy +define+thru top.v"
### End:
# Local Variables:
# compile-command: "./vl_file_copy -h ; VERILATOR_ROOT=$V4 ./vl_file_copy +define+thru top.v"
# End:

View File

@ -1,16 +1,14 @@
#!/usr/bin/env python3
# -*- Python -*- See copyright, etc below
# pylint: disable=C0103,C0114,C0115,C0115,C0116,R0914
######################################################################
import argparse
import os
import re
import subprocess
import sys
import tempfile
import xml.etree.ElementTree as ET
from shutil import copy2
from pprint import pprint, pformat
# from pprint import pprint, pformat
#######################################################################
@ -28,15 +26,15 @@ class VlHierGraph:
xml_temp = tempfile.NamedTemporaryFile()
args = [
vargs = [
'--xml-output',
xml_temp.name,
'--bbox-sys', # Parse some stuff can't translate
'--bbox-unsup',
'--prefix vlxml'
] # So we know name of .xml output
args += verilator_args
self.run_verilator(args)
vargs += verilator_args
self.run_verilator(vargs)
self.tree = ET.parse(xml_temp.name)
with open(output_filename, "w") as fh:
@ -70,18 +68,18 @@ class VlHierGraph:
fh.write("}\n")
def name_to_vertex_number(self, name):
if not name in self.name_to_number:
if name not in self.name_to_number:
self.next_vertex_number += 1
self.name_to_number[name] = self.next_vertex_number
return self.name_to_number[name]
def run_verilator(self, args):
def run_verilator(self, vargs):
"""Run Verilator command, check errors"""
if os.getenv("VERILATOR_ROOT"):
command = os.getenv("VERILATOR_ROOT") + "/bin/verilator"
else:
command = "verilator"
command += ' ' + ' '.join(args)
command += ' ' + ' '.join(vargs)
if self.debug:
print("\t%s " % command)
status = subprocess.call(command, shell=True)
@ -146,6 +144,6 @@ SPDX-License-Identifier: CC0-1.0
verilator_args=rem)
######################################################################
### Local Variables:
### compile-command: "./vl_hier_graph -h ; VERILATOR_ROOT=$V4 ./vl_hier_graph +define+thru top.v"
### End:
# Local Variables:
# compile-command: "./vl_hier_graph -h ; VERILATOR_ROOT=$V4 ./vl_hier_graph +define+thru top.v"
# End:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -26,10 +26,10 @@
#include <map>
//=============================================================================
// VerilatedCovImpBase
/// Implementation base class for constants
// VerilatedCovConst
// Implementation constants
struct VerilatedCovImpBase VL_NOT_FINAL {
struct VerilatedCovConst VL_NOT_FINAL {
// TYPES
enum { MAX_KEYS = 33 }; /// Maximum user arguments + filename+lineno
enum { KEY_UNDEF = 0 }; /// Magic key # for unspecified values
@ -39,16 +39,16 @@ struct VerilatedCovImpBase VL_NOT_FINAL {
// VerilatedCovImpItem
/// Implementation class for a VerilatedCov item
class VerilatedCovImpItem VL_NOT_FINAL : VerilatedCovImpBase {
class VerilatedCovImpItem VL_NOT_FINAL {
public: // But only local to this file
// MEMBERS
int m_keys[MAX_KEYS]; ///< Key
int m_vals[MAX_KEYS]; ///< Value for specified key
int m_keys[VerilatedCovConst::MAX_KEYS]; ///< Key
int m_vals[VerilatedCovConst::MAX_KEYS]; ///< Value for specified key
// CONSTRUCTORS
// Derived classes should call zero() in their constructor
VerilatedCovImpItem() {
for (int i = 0; i < MAX_KEYS; ++i) {
m_keys[i] = KEY_UNDEF;
for (int i = 0; i < VerilatedCovConst::MAX_KEYS; ++i) {
m_keys[i] = VerilatedCovConst::KEY_UNDEF;
m_vals[i] = 0;
}
}
@ -83,11 +83,13 @@ public:
//=============================================================================
// VerilatedCovImp
/// Implementation class for VerilatedCov. See that class for public method information.
/// All value and keys are indexed into a unique number. Thus we can greatly reduce
/// the storage requirements for otherwise identical keys.
///
/// Implementation class for VerilatedCovContext. See that class for
/// public method information. All value and keys are indexed into a
/// unique number. Thus we can greatly reduce the storage requirements for
/// otherwise identical keys.
class VerilatedCovImp final : VerilatedCovImpBase {
class VerilatedCovImp final : public VerilatedCovContext {
private:
// TYPES
typedef std::map<const std::string, int> ValueIndexMap;
@ -99,18 +101,21 @@ private:
ValueIndexMap m_valueIndexes VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for values
IndexValueMap m_indexValues VL_GUARDED_BY(m_mutex); ///< Unique arbitrary value for keys
ItemList m_items VL_GUARDED_BY(m_mutex); ///< List of all items
int m_nextIndex VL_GUARDED_BY(m_mutex) = (KEY_UNDEF + 1); ///< Next insert value
int m_nextIndex VL_GUARDED_BY(m_mutex)
= (VerilatedCovConst::KEY_UNDEF + 1); ///< Next insert value
VerilatedCovImpItem* m_insertp VL_GUARDED_BY(m_mutex) = nullptr; ///< Item about to insert
const char* m_insertFilenamep VL_GUARDED_BY(m_mutex) = nullptr; ///< Filename about to insert
int m_insertLineno VL_GUARDED_BY(m_mutex) = 0; ///< Line number about to insert
public:
// CONSTRUCTORS
VerilatedCovImp() = default;
VL_UNCOPYABLE(VerilatedCovImp);
public:
~VerilatedCovImp() { clearGuts(); }
protected:
friend class VerilatedCovContext;
virtual ~VerilatedCovImp() override { clearGuts(); }
static VerilatedCovImp& imp() VL_MT_SAFE {
static VerilatedCovImp s_singleton;
return s_singleton;
@ -133,7 +138,7 @@ private:
for (const char* pos = text.c_str(); *pos; ++pos) {
if (!isprint(*pos) || *pos == '%' || *pos == '"') {
char hex[10];
sprintf(hex, "%%%02X", pos[0]);
VL_SNPRINTF(hex, 10, "%%%02X", pos[0]);
rtn += hex;
} else {
rtn += *pos;
@ -203,8 +208,8 @@ private:
}
bool itemMatchesString(VerilatedCovImpItem* itemp, const std::string& match)
VL_REQUIRES(m_mutex) {
for (int i = 0; i < MAX_KEYS; ++i) {
if (itemp->m_keys[i] != KEY_UNDEF) {
for (int i = 0; i < VerilatedCovConst::MAX_KEYS; ++i) {
if (itemp->m_keys[i] != VerilatedCovConst::KEY_UNDEF) {
// We don't compare keys, only values
std::string val = m_indexValues[itemp->m_vals[i]];
if (std::string::npos != val.find(match)) { // Found
@ -235,17 +240,17 @@ private:
m_items.clear();
m_indexValues.clear();
m_valueIndexes.clear();
m_nextIndex = KEY_UNDEF + 1;
m_nextIndex = VerilatedCovConst::KEY_UNDEF + 1;
}
public:
// PUBLIC METHODS
void clear() VL_EXCLUDES(m_mutex) {
void clear() VL_MT_SAFE_EXCLUDES(m_mutex) {
Verilated::quiesce();
const VerilatedLockGuard lock(m_mutex);
clearGuts();
}
void clearNonMatch(const char* matchp) VL_EXCLUDES(m_mutex) {
void clearNonMatch(const char* matchp) VL_MT_SAFE_EXCLUDES(m_mutex) {
Verilated::quiesce();
const VerilatedLockGuard lock(m_mutex);
if (matchp && matchp[0]) {
@ -260,24 +265,25 @@ public:
m_items = newlist;
}
}
void zero() VL_EXCLUDES(m_mutex) {
void zero() VL_MT_SAFE_EXCLUDES(m_mutex) {
Verilated::quiesce();
const VerilatedLockGuard lock(m_mutex);
for (const auto& itemp : m_items) itemp->zero();
}
// We assume there's always call to i/f/p in that order
void inserti(VerilatedCovImpItem* itemp) VL_EXCLUDES(m_mutex) {
void inserti(VerilatedCovImpItem* itemp) VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lock(m_mutex);
assert(!m_insertp);
m_insertp = itemp;
}
void insertf(const char* filenamep, int lineno) VL_EXCLUDES(m_mutex) {
void insertf(const char* filenamep, int lineno) VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lock(m_mutex);
m_insertFilenamep = filenamep;
m_insertLineno = lineno;
}
void insertp(const char* ckeyps[MAX_KEYS], const char* valps[MAX_KEYS]) VL_EXCLUDES(m_mutex) {
void insertp(const char* ckeyps[VerilatedCovConst::MAX_KEYS],
const char* valps[VerilatedCovConst::MAX_KEYS]) VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lock(m_mutex);
assert(m_insertp);
// First two key/vals are filename
@ -296,14 +302,14 @@ public:
valps[2] = page_default.c_str();
// Keys -> strings
std::string keys[MAX_KEYS];
for (int i = 0; i < MAX_KEYS; ++i) {
std::string keys[VerilatedCovConst::MAX_KEYS];
for (int i = 0; i < VerilatedCovConst::MAX_KEYS; ++i) {
if (ckeyps[i] && ckeyps[i][0]) keys[i] = ckeyps[i];
}
// Ignore empty keys
for (int i = 0; i < MAX_KEYS; ++i) {
for (int i = 0; i < VerilatedCovConst::MAX_KEYS; ++i) {
if (!keys[i].empty()) {
for (int j = i + 1; j < MAX_KEYS; ++j) {
for (int j = i + 1; j < VerilatedCovConst::MAX_KEYS; ++j) {
if (keys[i] == keys[j]) { // Duplicate key. Keep the last one
keys[i] = "";
break;
@ -313,7 +319,7 @@ public:
}
// Insert the values
int addKeynum = 0;
for (int i = 0; i < MAX_KEYS; ++i) {
for (int i = 0; i < VerilatedCovConst::MAX_KEYS; ++i) {
const std::string key = keys[i];
if (!keys[i].empty()) {
const std::string val = valps[i];
@ -334,7 +340,7 @@ public:
m_insertp = nullptr;
}
void write(const char* filename) VL_EXCLUDES(m_mutex) {
void write(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex) {
Verilated::quiesce();
const VerilatedLockGuard lock(m_mutex);
#ifndef VM_COVERAGE
@ -358,8 +364,8 @@ public:
std::string hier;
bool per_instance = false;
for (int i = 0; i < MAX_KEYS; ++i) {
if (itemp->m_keys[i] != KEY_UNDEF) {
for (int i = 0; i < VerilatedCovConst::MAX_KEYS; ++i) {
if (itemp->m_keys[i] != VerilatedCovConst::KEY_UNDEF) {
std::string key = VerilatedCovKey::shortKey(m_indexValues[itemp->m_keys[i]]);
std::string val = m_indexValues[itemp->m_vals[i]];
if (key == VL_CIK_PER_INSTANCE) {
@ -406,64 +412,62 @@ public:
};
//=============================================================================
// VerilatedCov
// VerilatedCovContext
void VerilatedCov::clear() VL_MT_SAFE { VerilatedCovImp::imp().clear(); }
void VerilatedCov::clearNonMatch(const char* matchp) VL_MT_SAFE {
VerilatedCovImp::imp().clearNonMatch(matchp);
void VerilatedCovContext::clear() VL_MT_SAFE { impp()->clear(); }
void VerilatedCovContext::clearNonMatch(const char* matchp) VL_MT_SAFE {
impp()->clearNonMatch(matchp);
}
void VerilatedCov::zero() VL_MT_SAFE { VerilatedCovImp::imp().zero(); }
void VerilatedCov::write(const char* filenamep) VL_MT_SAFE {
VerilatedCovImp::imp().write(filenamep);
void VerilatedCovContext::zero() VL_MT_SAFE { impp()->zero(); }
void VerilatedCovContext::write(const char* filenamep) VL_MT_SAFE { impp()->write(filenamep); }
void VerilatedCovContext::_inserti(vluint32_t* itemp) VL_MT_SAFE {
impp()->inserti(new VerilatedCoverItemSpec<vluint32_t>(itemp));
}
void VerilatedCov::_inserti(vluint32_t* itemp) VL_MT_SAFE {
VerilatedCovImp::imp().inserti(new VerilatedCoverItemSpec<vluint32_t>(itemp));
void VerilatedCovContext::_inserti(vluint64_t* itemp) VL_MT_SAFE {
impp()->inserti(new VerilatedCoverItemSpec<vluint64_t>(itemp));
}
void VerilatedCov::_inserti(vluint64_t* itemp) VL_MT_SAFE {
VerilatedCovImp::imp().inserti(new VerilatedCoverItemSpec<vluint64_t>(itemp));
}
void VerilatedCov::_insertf(const char* filename, int lineno) VL_MT_SAFE {
VerilatedCovImp::imp().insertf(filename, lineno);
void VerilatedCovContext::_insertf(const char* filename, int lineno) VL_MT_SAFE {
impp()->insertf(filename, lineno);
}
#define K(n) const char* key##n
#define A(n) const char *key##n, const char *valp##n // Argument list
#define C(n) key##n, valp##n // Calling argument list
#define N(n) "", "" // Null argument list
void VerilatedCov::_insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10),
A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), A(20),
A(21), A(22), A(23), A(24), A(25), A(26), A(27), A(28),
A(29)) VL_MT_SAFE {
const char* keyps[VerilatedCovImpBase::MAX_KEYS]
void VerilatedCovContext::_insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9),
A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18),
A(19), A(20), A(21), A(22), A(23), A(24), A(25), A(26), A(27),
A(28), A(29)) VL_MT_SAFE {
const char* keyps[VerilatedCovConst::MAX_KEYS]
= {nullptr, nullptr, nullptr, // filename,lineno,page
key0, key1, key2, key3, key4, key5, key6, key7, key8, key9,
key10, key11, key12, key13, key14, key15, key16, key17, key18, key19,
key20, key21, key22, key23, key24, key25, key26, key27, key28, key29};
const char* valps[VerilatedCovImpBase::MAX_KEYS]
const char* valps[VerilatedCovConst::MAX_KEYS]
= {nullptr, nullptr, nullptr, // filename,lineno,page
valp0, valp1, valp2, valp3, valp4, valp5, valp6, valp7, valp8, valp9,
valp10, valp11, valp12, valp13, valp14, valp15, valp16, valp17, valp18, valp19,
valp20, valp21, valp22, valp23, valp24, valp25, valp26, valp27, valp28, valp29};
VerilatedCovImp::imp().insertp(keyps, valps);
impp()->insertp(keyps, valps);
}
// And versions with fewer arguments (oh for a language with named parameters!)
void VerilatedCov::_insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8),
A(9)) VL_MT_SAFE {
void VerilatedCovContext::_insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8),
A(9)) VL_MT_SAFE {
_insertp(C(0), C(1), C(2), C(3), C(4), C(5), C(6), C(7), C(8), C(9), N(10), N(11), N(12),
N(13), N(14), N(15), N(16), N(17), N(18), N(19), N(20), N(21), N(22), N(23), N(24),
N(25), N(26), N(27), N(28), N(29));
}
void VerilatedCov::_insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10),
A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18),
A(19)) VL_MT_SAFE {
void VerilatedCovContext::_insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9),
A(10), A(11), A(12), A(13), A(14), A(15), A(16), A(17), A(18),
A(19)) VL_MT_SAFE {
_insertp(C(0), C(1), C(2), C(3), C(4), C(5), C(6), C(7), C(8), C(9), C(10), C(11), C(12),
C(13), C(14), C(15), C(16), C(17), C(18), C(19), N(20), N(21), N(22), N(23), N(24),
N(25), N(26), N(27), N(28), N(29));
}
// Backward compatibility for Verilator
void VerilatedCov::_insertp(A(0), A(1), K(2), int val2, K(3), int val3, K(4),
const std::string& val4, A(5), A(6), A(7)) VL_MT_SAFE {
void VerilatedCovContext::_insertp(A(0), A(1), K(2), int val2, K(3), int val3, K(4),
const std::string& val4, A(5), A(6), A(7)) VL_MT_SAFE {
std::string val2str = vlCovCvtToStr(val2);
std::string val3str = vlCovCvtToStr(val3);
_insertp(C(0), C(1), key2, val2str.c_str(), key3, val3str.c_str(), key4, val4.c_str(), C(5),
@ -474,3 +478,26 @@ void VerilatedCov::_insertp(A(0), A(1), K(2), int val2, K(3), int val3, K(4),
#undef C
#undef N
#undef K
//=============================================================================
// VerilatedCov
#ifndef VL_NO_LEGACY
VerilatedCovContext* VerilatedCov::threadCovp() VL_MT_SAFE {
return Verilated::threadContextp()->coveragep();
}
#endif
//=============================================================================
// VerilatedContext
VerilatedCovContext* VerilatedContext::coveragep() VL_MT_SAFE {
static VerilatedMutex s_mutex;
if (VL_UNLIKELY(!m_coveragep)) {
const VerilatedLockGuard lock(s_mutex);
if (VL_LIKELY(!m_coveragep)) { // Not redundant, prevents race
m_coveragep.reset(new VerilatedCovImp);
}
}
return reinterpret_cast<VerilatedCovContext*>(m_coveragep.get());
}

View File

@ -16,15 +16,18 @@
///
//=============================================================================
#ifndef _VERILATED_COV_H_
#define _VERILATED_COV_H_ 1
#ifndef VERILATOR_VERILATED_COV_H_
#define VERILATOR_VERILATED_COV_H_
#include "verilatedos.h"
#include "verilated.h"
#include <iostream>
#include <sstream>
#include <string>
class VerilatedCovImp;
//=============================================================================
/// Conditionally compile coverage code
@ -68,9 +71,9 @@
/// VL_COVER_INSERT(&m_cases[i], "comment", "Coverage Case", "i", cvtToNumStr(i));
/// }
#define VL_COVER_INSERT(countp, ...) \
VL_IF_COVER(VerilatedCov::_inserti(countp); VerilatedCov::_insertf(__FILE__, __LINE__); \
VerilatedCov::_insertp("hier", name(), __VA_ARGS__))
#define VL_COVER_INSERT(covcontextp, countp, ...) \
VL_IF_COVER(covcontextp->_inserti(countp); covcontextp->_insertf(__FILE__, __LINE__); \
covcontextp->_insertp("hier", name(), __VA_ARGS__))
//=============================================================================
/// Convert VL_COVER_INSERT value arguments to strings
@ -83,29 +86,35 @@ template <class T> std::string vlCovCvtToStr(const T& t) VL_PURE {
//=============================================================================
// VerilatedCov
/// Verilator coverage global class
////
/// Global class with methods affecting all coverage data.
/// Verilator coverage per-context structure
/// All public methods in this class are thread safe.
class VerilatedCov final {
VL_UNCOPYABLE(VerilatedCov);
class VerilatedCovContext VL_NOT_FINAL : public VerilatedVirtualBase {
VL_UNCOPYABLE(VerilatedCovContext);
public:
// GLOBAL METHODS
// METHODS
/// Return default filename
static const char* defaultFilename() VL_PURE { return "coverage.dat"; }
/// Write all coverage data to a file
static void write(const char* filenamep = defaultFilename()) VL_MT_SAFE;
void write(const char* filenamep = defaultFilename()) VL_MT_SAFE;
/// Clear coverage points (and call delete on all items)
void clear() VL_MT_SAFE;
/// Clear items not matching the provided string
void clearNonMatch(const char* matchp) VL_MT_SAFE;
/// Zero coverage points
void zero() VL_MT_SAFE;
public: // But Internal use only
/// Insert a coverage item
/// We accept from 1-30 key/value pairs, all as strings.
/// Call _insert1, followed by _insert2 and _insert3
/// Do not call directly; use VL_COVER_INSERT or higher level macros instead
// _insert1: Remember item pointer with count. (Not const, as may add zeroing function)
static void _inserti(vluint32_t* itemp) VL_MT_SAFE;
static void _inserti(vluint64_t* itemp) VL_MT_SAFE;
void _inserti(vluint32_t* itemp) VL_MT_SAFE;
void _inserti(vluint64_t* itemp) VL_MT_SAFE;
// _insert2: Set default filename and line number
static void _insertf(const char* filename, int lineno) VL_MT_SAFE;
void _insertf(const char* filename, int lineno) VL_MT_SAFE;
// _insert3: Set parameters
// We could have just the maximum argument version, but this compiles
// much slower (nearly 2x) than having smaller versions also. However
@ -113,25 +122,65 @@ public:
#define K(n) const char* key##n
#define A(n) const char *key##n, const char *valp##n // Argument list
#define D(n) const char *key##n = nullptr, const char *valp##n = nullptr // Argument list
static void _insertp(D(0), D(1), D(2), D(3), D(4), D(5), D(6), D(7), D(8), D(9));
static void _insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10), D(11),
D(12), D(13), D(14), D(15), D(16), D(17), D(18), D(19));
static void _insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10), A(11),
A(12), A(13), A(14), A(15), A(16), A(17), A(18), A(19), A(20), D(21),
D(22), D(23), D(24), D(25), D(26), D(27), D(28), D(29));
void _insertp(D(0), D(1), D(2), D(3), D(4), D(5), D(6), D(7), D(8), D(9));
void _insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10), D(11), D(12),
D(13), D(14), D(15), D(16), D(17), D(18), D(19));
void _insertp(A(0), A(1), A(2), A(3), A(4), A(5), A(6), A(7), A(8), A(9), A(10), A(11), A(12),
A(13), A(14), A(15), A(16), A(17), A(18), A(19), A(20), D(21), D(22), D(23),
D(24), D(25), D(26), D(27), D(28), D(29));
// Backward compatibility for Verilator
static void _insertp(A(0), A(1), K(2), int val2, K(3), int val3, K(4), const std::string& val4,
A(5), A(6), A(7));
void _insertp(A(0), A(1), K(2), int val2, K(3), int val3, K(4), const std::string& val4, A(5),
A(6), A(7));
#undef K
#undef A
#undef D
/// Clear coverage points (and call delete on all items)
static void clear() VL_MT_SAFE;
/// Clear items not matching the provided string
static void clearNonMatch(const char* matchp) VL_MT_SAFE;
/// Zero coverage points
static void zero() VL_MT_SAFE;
protected:
friend class VerilatedCovImp;
// CONSTRUCTORS
// Internal: Only made as part of VerilatedCovImp
VerilatedCovContext() {}
virtual ~VerilatedCovContext() {}
// METHODS
// Internal: access to implementation class
VerilatedCovImp* impp() { return reinterpret_cast<VerilatedCovImp*>(this); }
};
//=============================================================================
// VerilatedCov
/// Verilator coverage global class
///
/// Global class that accesses via current thread's context. These are
/// provided for backward-compatibility, use VerilatedContext->coveragep()
/// instead.
#ifndef VL_NO_LEGACY
class VerilatedCov final {
VL_UNCOPYABLE(VerilatedCov);
public:
// METHODS
/// Return default filename for the current thread
static const char* defaultFilename() VL_PURE { return VerilatedCovContext::defaultFilename(); }
/// Write all coverage data to a file for the current thread
static void write(const char* filenamep = defaultFilename()) VL_MT_SAFE {
threadCovp()->write(filenamep);
}
/// Clear coverage points (and call delete on all items) for the current thread
static void clear() VL_MT_SAFE { threadCovp()->clear(); }
/// Clear items not matching the provided string for the current thread
static void clearNonMatch(const char* matchp) VL_MT_SAFE {
threadCovp()->clearNonMatch(matchp);
}
/// Zero coverage points for the current thread
static void zero() VL_MT_SAFE { threadCovp()->zero(); }
private:
/// Current thread's coverage structure
static VerilatedCovContext* threadCovp() VL_MT_SAFE;
};
#endif
#endif // Guard

View File

@ -16,8 +16,8 @@
///
//=============================================================================
#ifndef _VERILATED_COV_KEY_H_
#define _VERILATED_COV_KEY_H_ 1
#ifndef VERILATOR_VERILATED_COV_KEY_H_
#define VERILATOR_VERILATED_COV_KEY_H_
#include "verilatedos.h"

View File

@ -19,7 +19,7 @@
///
//=========================================================================
#define _VERILATED_DPI_CPP_
#define VERILATOR_VERILATED_DPI_CPP_
#include "verilatedos.h"
#include "verilated_dpi.h"
@ -37,11 +37,11 @@
//======================================================================
// Internal macros
#define _VL_SVDPI_WARN(...) VL_PRINTF_MT(__VA_ARGS__)
#define VL_SVDPI_WARN_(...) VL_PRINTF_MT(__VA_ARGS__)
// Function requires a "context" in the import declaration
#define _VL_SVDPI_CONTEXT_WARN() \
_VL_SVDPI_WARN("%%Warning: DPI C Function called by Verilog DPI import with missing " \
#define VL_SVDPI_CONTEXT_WARN_() \
VL_SVDPI_WARN_("%%Warning: DPI C Function called by Verilog DPI import with missing " \
"'context' keyword.\n")
//======================================================================
@ -120,7 +120,7 @@ void svGetPartselLogic(svLogicVecVal* dp, const svLogicVecVal* sp, int lsb, int
dp[VL_WORDS_I(width) - 1].bval &= VL_MASK_I(width);
}
void svPutPartselBit(svBitVecVal* dp, const svBitVecVal s, int lbit, int width) {
// See also _VL_INSERT_WI
// See also _vl_insert_WI
int hbit = lbit + width - 1;
int hoffset = VL_BITBIT_I(hbit);
int loffset = VL_BITBIT_I(lbit);
@ -218,7 +218,7 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, i
int indx2, int indx3) {
void* datap = varp->datap();
if (VL_UNLIKELY(nargs != varp->udims())) {
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function called on"
VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function called on"
" %d dimensional array using %d dimensional function.\n",
varp->udims(), nargs);
return nullptr;
@ -226,7 +226,7 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, i
if (nargs >= 1) {
datap = varp->datapAdjustIndex(datap, 1, indx1);
if (VL_UNLIKELY(!datap)) {
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 1 "
VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function index 1 "
"out of bounds; %d outside [%d:%d].\n",
indx1, varp->left(1), varp->right(1));
return nullptr;
@ -235,7 +235,7 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, i
if (nargs >= 2) {
datap = varp->datapAdjustIndex(datap, 2, indx2);
if (VL_UNLIKELY(!datap)) {
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 2 "
VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function index 2 "
"out of bounds; %d outside [%d:%d].\n",
indx2, varp->left(2), varp->right(2));
return nullptr;
@ -244,7 +244,7 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, i
if (nargs >= 3) {
datap = varp->datapAdjustIndex(datap, 3, indx3);
if (VL_UNLIKELY(!datap)) {
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function index 3 "
VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function index 3 "
"out of bounds; %d outside [%d:%d].\n",
indx1, varp->left(3), varp->right(3));
return nullptr;
@ -285,7 +285,7 @@ static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s,
return;
}
default: // LCOV_EXCL_START // Errored earlier
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
varp->vltype());
return; // LCOV_EXCL_STOP
}
@ -327,7 +327,7 @@ static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandl
return;
}
default: // LCOV_EXCL_START // Errored earlier
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
varp->vltype());
return; // LCOV_EXCL_STOP
}
@ -343,14 +343,14 @@ static void _vl_svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecV
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0]; return;
case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0]; return;
case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0]; return;
case VLVT_UINT64: *(reinterpret_cast<QData*>(datap)) = _VL_SET_QII(s[1], s[0]); break;
case VLVT_UINT64: *(reinterpret_cast<QData*>(datap)) = VL_SET_QII(s[1], s[0]); break;
case VLVT_WDATA: {
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i];
return;
}
default: // LCOV_EXCL_START // Errored earlier
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
varp->vltype());
return; // LCOV_EXCL_STOP
}
@ -365,16 +365,14 @@ static void _vl_svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogic
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = s[0].aval; return;
case VLVT_UINT16: *(reinterpret_cast<SData*>(datap)) = s[0].aval; return;
case VLVT_UINT32: *(reinterpret_cast<IData*>(datap)) = s[0].aval; return;
case VLVT_UINT64:
*(reinterpret_cast<QData*>(datap)) = _VL_SET_QII(s[1].aval, s[0].aval);
break;
case VLVT_UINT64: *(reinterpret_cast<QData*>(datap)) = VL_SET_QII(s[1].aval, s[0].aval); break;
case VLVT_WDATA: {
WDataOutP wdatap = (reinterpret_cast<WDataOutP>(datap));
for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i].aval;
return;
}
default: // LCOV_EXCL_START // Errored earlier
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
varp->vltype());
return; // LCOV_EXCL_STOP
}
@ -390,7 +388,7 @@ static svBit _vl_svGetBitArrElem(const svOpenArrayHandle s, int nargs, int indx1
switch (varp->vltype()) { // LCOV_EXCL_BR_LINE
case VLVT_UINT8: return (*(reinterpret_cast<CData*>(datap))) & 1;
default: // LCOV_EXCL_START // Errored earlier
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
varp->vltype());
return 0; // LCOV_EXCL_STOP
}
@ -406,7 +404,7 @@ static void _vl_svPutBitArrElem(const svOpenArrayHandle d, svBit value, int narg
switch (varp->vltype()) { // LCOV_EXCL_BR_LINE
case VLVT_UINT8: *(reinterpret_cast<CData*>(datap)) = value; return;
default: // LCOV_EXCL_START // Errored earlier
_VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
VL_SVDPI_WARN_("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n",
varp->vltype());
return; // LCOV_EXCL_STOP
}
@ -720,7 +718,7 @@ void svPutLogicArrElem3(const svOpenArrayHandle d, svLogic value, int indx1, int
svScope svGetScope() {
if (VL_UNLIKELY(!Verilated::dpiInContext())) {
_VL_SVDPI_CONTEXT_WARN();
VL_SVDPI_CONTEXT_WARN_();
return nullptr;
}
// NOLINTNEXTLINE(google-readability-casting)
@ -742,7 +740,7 @@ const char* svGetNameFromScope(const svScope scope) {
svScope svGetScopeFromName(const char* scopeName) {
// NOLINTNEXTLINE(google-readability-casting)
return (svScope)(VerilatedImp::scopeFind(scopeName));
return (svScope)(Verilated::threadContextp()->scopeFind(scopeName));
}
int svPutUserData(const svScope scope, void* userKey, void* userData) {
@ -756,7 +754,7 @@ void* svGetUserData(const svScope scope, void* userKey) {
int svGetCallerInfo(const char** fileNamepp, int* lineNumberp) {
if (VL_UNLIKELY(!Verilated::dpiInContext())) {
_VL_SVDPI_CONTEXT_WARN();
VL_SVDPI_CONTEXT_WARN_();
return false;
}
if (VL_LIKELY(fileNamepp)) *fileNamepp = Verilated::dpiFilenamep(); // thread local

View File

@ -20,8 +20,8 @@
///
//*************************************************************************
#ifndef _VERILATED_DPI_H_
#define _VERILATED_DPI_H_ 1 ///< Header Guard
#ifndef VERILATOR_VERILATED_DPI_H_
#define VERILATOR_VERILATED_DPI_H_ ///< Header Guard
#include "verilatedos.h"
#include "verilated.h" // Also presumably included by caller
@ -32,18 +32,18 @@
//===================================================================
// SETTING OPERATORS
/// Convert svBitVecVal to Verilator internal data
// Convert svBitVecVal to Verilator internal data
static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, const svBitVecVal* lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits);
for (int i = 0; i < words - 1; ++i) owp[i] = lwp[i];
owp[words - 1] = lwp[words - 1] & VL_MASK_I(obits);
}
static inline QData VL_SET_Q_SVBV(const svBitVecVal* lwp) VL_MT_SAFE {
return _VL_SET_QII(lwp[1], lwp[0]);
return VL_SET_QII(lwp[1], lwp[0]);
}
static inline IData VL_SET_I_SVBV(const svBitVecVal* lwp) VL_MT_SAFE { return lwp[0]; }
/// Convert Verilator internal data to svBitVecVal
// Convert Verilator internal data to svBitVecVal
static inline void VL_SET_SVBV_W(int obits, svBitVecVal* owp, WDataInP lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits);
for (int i = 0; i < words - 1; ++i) owp[i] = lwp[i];
@ -54,20 +54,20 @@ static inline void VL_SET_SVBV_Q(int, svBitVecVal* owp, QData ld) VL_MT_SAFE {
VL_SET_WQ(owp, ld);
}
/// Convert svLogicVecVal to Verilator internal data
/// Note these functions ignore X/Z in svLogicVecVal
// Convert svLogicVecVal to Verilator internal data
// Note these functions ignore X/Z in svLogicVecVal
static inline void VL_SET_W_SVLV(int obits, WDataOutP owp, const svLogicVecVal* lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits);
for (int i = 0; i < words - 1; ++i) owp[i] = lwp[i].aval;
owp[words - 1] = lwp[words - 1].aval & VL_MASK_I(obits);
}
static inline QData VL_SET_Q_SVLV(const svLogicVecVal* lwp) VL_MT_SAFE {
return _VL_SET_QII(lwp[1].aval, lwp[0].aval);
return VL_SET_QII(lwp[1].aval, lwp[0].aval);
}
static inline IData VL_SET_I_SVLV(const svLogicVecVal* lwp) VL_MT_SAFE { return lwp[0].aval; }
/// Convert Verilator internal data to svLogicVecVal
/// Note these functions never create X/Z in svLogicVecVal
// Convert Verilator internal data to svLogicVecVal
// Note these functions never create X/Z in svLogicVecVal
static inline void VL_SET_SVLV_W(int obits, svLogicVecVal* owp, WDataInP lwp) VL_MT_SAFE {
int words = VL_WORDS_I(obits);
for (int i = 0; i < words; ++i) owp[i].bval = 0;

View File

@ -15,7 +15,6 @@
/// \brief C++ Tracing in FST Format
///
//=============================================================================
// SPDIFF_OFF
// clang-format off
@ -66,8 +65,8 @@ VerilatedFst::~VerilatedFst() {
if (m_strbuf) VL_DO_CLEAR(delete[] m_strbuf, m_strbuf = nullptr);
}
void VerilatedFst::open(const char* filename) VL_MT_UNSAFE {
m_assertOne.check();
void VerilatedFst::open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lock(m_mutex);
m_fst = fstWriterCreate(filename, 1);
fstWriterSetPackType(m_fst, FST_WR_PT_LZ4);
fstWriterSetTimescaleFromString(m_fst, timeResStr().c_str()); // lintok-begin-on-ref
@ -97,15 +96,16 @@ void VerilatedFst::open(const char* filename) VL_MT_UNSAFE {
if (!m_strbuf) m_strbuf = new char[maxBits() + 32];
}
void VerilatedFst::close() {
m_assertOne.check();
VerilatedTrace<VerilatedFst>::close();
void VerilatedFst::close() VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lock(m_mutex);
VerilatedTrace<VerilatedFst>::closeBase();
fstWriterClose(m_fst);
m_fst = nullptr;
}
void VerilatedFst::flush() {
VerilatedTrace<VerilatedFst>::flush();
void VerilatedFst::flush() VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lock(m_mutex);
VerilatedTrace<VerilatedFst>::flushBase();
fstWriterFlushContext(m_fst);
}

View File

@ -17,8 +17,8 @@
//=============================================================================
// SPDIFF_OFF
#ifndef _VERILATED_FST_C_H_
#define _VERILATED_FST_C_H_ 1
#ifndef VERILATOR_VERILATED_FST_C_H_
#define VERILATOR_VERILATED_FST_C_H_
#include "verilated.h"
#include "verilated_trace.h"
@ -32,8 +32,8 @@
//=============================================================================
// VerilatedFst
/// Base class to create a Verilator FST dump
/// This is an internally used class - see VerilatedFstC for what to call from applications
// Base class to create a Verilator FST dump
// This is an internally used class - see VerilatedFstC for what to call from applications
class VerilatedFst final : public VerilatedTrace<VerilatedFst> {
private:
@ -82,27 +82,28 @@ protected:
public:
//=========================================================================
// External interface to client code
// (All must be threadsafe)
explicit VerilatedFst(void* fst = nullptr);
~VerilatedFst();
/// Open the file; call isOpen() to see if errors
void open(const char* filename) VL_MT_UNSAFE;
/// Close the file
void close() VL_MT_UNSAFE;
/// Flush any remaining data to this file
void flush() VL_MT_UNSAFE;
/// Is file open?
bool isOpen() const { return m_fst != nullptr; }
// Open the file; call isOpen() to see if errors
void open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex);
// Close the file
void close() VL_MT_SAFE_EXCLUDES(m_mutex);
// Flush any remaining data to this file
void flush() VL_MT_SAFE_EXCLUDES(m_mutex);
// Return if file is open
bool isOpen() const VL_MT_SAFE { return m_fst != nullptr; }
//=========================================================================
// Internal interface to Verilator generated code
/// Inside dumping routines, declare a data type
// Inside dumping routines, declare a data type
void declDTypeEnum(int dtypenum, const char* name, vluint32_t elements,
unsigned int minValbits, const char** itemNamesp, const char** itemValuesp);
/// Inside dumping routines, declare a signal
// Inside dumping routines, declare a signal
void declBit(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
fstVarType vartype, bool array, int arraynum);
void declBus(vluint32_t code, const char* name, int dtypenum, fstVarDir vardir,
@ -126,7 +127,6 @@ template <> void VerilatedTrace<VerilatedFst>::set_time_resolution(const std::st
// VerilatedFstC
/// Create a FST dump file in C standalone (no SystemC) simulations.
/// Also derived for use in SystemC simulations.
/// Thread safety: Unless otherwise indicated, every function is VL_MT_UNSAFE_ONE
class VerilatedFstC final {
VerilatedFst m_sptrace; ///< Trace file being created
@ -135,22 +135,22 @@ class VerilatedFstC final {
VL_UNCOPYABLE(VerilatedFstC);
public:
/// Construct the dump. Optional argument is ignored.
explicit VerilatedFstC(void* filep = nullptr)
: m_sptrace{filep} {}
/// Destruct, flush, and close the dump
~VerilatedFstC() { close(); }
/// Routines can only be called from one thread; allow next call from different thread
void changeThread() { spTrace()->changeThread(); }
// ACCESSORS
/// Is file open?
bool isOpen() const { return m_sptrace.isOpen(); }
// METHODS
// METHODS - User called
/// Return if file is open
bool isOpen() const VL_MT_SAFE { return m_sptrace.isOpen(); }
/// Open a new FST file
void open(const char* filename) VL_MT_UNSAFE_ONE { m_sptrace.open(filename); }
void open(const char* filename) VL_MT_SAFE { m_sptrace.open(filename); }
/// Close dump
void close() VL_MT_UNSAFE_ONE { m_sptrace.close(); }
void close() VL_MT_SAFE { m_sptrace.close(); }
/// Flush dump
void flush() VL_MT_UNSAFE_ONE { m_sptrace.flush(); }
void flush() VL_MT_SAFE { m_sptrace.flush(); }
/// Write one cycle of dump data
void dump(vluint64_t timeui) { m_sptrace.dump(timeui); }
/// Write one cycle of dump data - backward compatible and to reduce
@ -158,16 +158,26 @@ public:
void dump(double timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
void dump(vluint32_t timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
void dump(int timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
/// Set time units (s/ms, defaults to ns)
/// For Verilated models, these propage from the Verilated default --timeunit
void set_time_unit(const char* unitp) { m_sptrace.set_time_unit(unitp); }
void set_time_unit(const std::string& unit) { m_sptrace.set_time_unit(unit); }
/// Set time resolution (s/ms, defaults to ns)
/// For Verilated models, these propage from the Verilated default --timeunit
void set_time_resolution(const char* unitp) { m_sptrace.set_time_resolution(unitp); }
void set_time_resolution(const std::string& unit) { m_sptrace.set_time_resolution(unit); }
/// Internal class access
// METHODS - Internal/backward compatible
// \protectedsection
// Set time units (s/ms, defaults to ns)
// Users should not need to call this, as for Verilated models, these
// propage from the Verilated default timeunit
void set_time_unit(const char* unitp) VL_MT_SAFE { m_sptrace.set_time_unit(unitp); }
void set_time_unit(const std::string& unit) VL_MT_SAFE { m_sptrace.set_time_unit(unit); }
// Set time resolution (s/ms, defaults to ns)
// Users should not need to call this, as for Verilated models, these
// propage from the Verilated default timeprecision
void set_time_resolution(const char* unitp) VL_MT_SAFE {
m_sptrace.set_time_resolution(unitp);
}
void set_time_resolution(const std::string& unit) VL_MT_SAFE {
m_sptrace.set_time_resolution(unit);
}
// Internal class access
inline VerilatedFst* spTrace() { return &m_sptrace; };
};

View File

@ -21,8 +21,8 @@
///
//*************************************************************************
#ifndef _VERILATED_HEAVY_H_
#define _VERILATED_HEAVY_H_ 1 ///< Header Guard
#ifndef VERILATOR_VERILATED_HEAVY_H_
#define VERILATOR_VERILATED_HEAVY_H_ ///< Header Guard
#include "verilated.h"
@ -900,8 +900,8 @@ extern IData VL_SSCANF_INX(int lbits, const std::string& ld, const char* formatp
extern void VL_SFORMAT_X(int obits_ignored, std::string& output, const char* formatp,
...) VL_MT_SAFE;
extern std::string VL_SFORMATF_NX(const char* formatp, ...) VL_MT_SAFE;
extern void VL_TIMEFORMAT_IINI(int units, int precision, const std::string& suffix,
int width) VL_MT_SAFE;
extern void VL_TIMEFORMAT_IINI(int units, int precision, const std::string& suffix, int width,
VerilatedContext* contextp) VL_MT_SAFE;
extern IData VL_VALUEPLUSARGS_INW(int rbits, const std::string& ld, WDataOutP rwp) VL_MT_SAFE;
inline IData VL_VALUEPLUSARGS_INI(int rbits, const std::string& ld, CData& rdr) VL_MT_SAFE {
WData rwp[2]; // WData must always be at least 2
@ -956,10 +956,4 @@ extern IData VL_ATOI_N(const std::string& str, int base) VL_PURE;
extern IData VL_FGETS_NI(std::string& dest, IData fpi);
//======================================================================
// Dumping
extern const char* vl_dumpctl_filenamep(bool setit = false,
const std::string& filename = "") VL_MT_SAFE;
#endif // Guard

View File

@ -16,11 +16,12 @@
///
//=========================================================================
#ifndef _VERILATED_IMP_H_
#define _VERILATED_IMP_H_ 1 ///< Header Guard
#ifndef VERILATOR_VERILATED_IMP_H_
#define VERILATOR_VERILATED_IMP_H_ ///< Header Guard
// clang-format off
#if !defined(_VERILATED_CPP_) && !defined(_VERILATED_DPI_CPP_) && !defined(_VERILATED_VPI_CPP_)
#if !defined(VERILATOR_VERILATED_CPP_) && !defined(VERILATOR_VERILATED_DPI_CPP_) \
&& !defined(VERILATOR_VERILATED_VPI_CPP_) && !defined(VERILATOR_VERILATED_SAVE_CPP_)
# error "verilated_imp.h only to be included by verilated*.cpp internals"
#endif
@ -99,13 +100,13 @@ private:
public:
// METHODS
//// Add message to queue (called by producer)
void post(const VerilatedMsg& msg) VL_EXCLUDES(m_mutex) {
void post(const VerilatedMsg& msg) VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lock(m_mutex);
m_queue.insert(msg); // Pass by value to copy the message into queue
++m_depth;
}
/// Service queue until completion (called by consumer)
void process() VL_EXCLUDES(m_mutex) {
void process() VL_MT_SAFE_EXCLUDES(m_mutex) {
// Tracking m_depth is redundant to e.g. getting the mutex and looking at queue size,
// but on the reader side it's 4x faster to test an atomic then getting a mutex
while (m_depth) {
@ -190,78 +191,238 @@ public:
}
};
//======================================================================
// VerilatedContextImpData
/// Class for hidden implementation members inside VerilatedContext
// Avoids needing std::unordered_map inside verilated.h
class VerilatedContextImpData final {
friend class VerilatedContext;
friend class VerilatedContextImp;
protected:
/// Map of <scope_name, scope pointer>
// Used by scopeInsert, scopeFind, scopeErase, scopeNameMap
mutable VerilatedMutex m_nameMutex; ///< Protect m_nameMap
VerilatedScopeNameMap m_nameMap VL_GUARDED_BY(m_nameMutex);
};
//======================================================================
// VerilatedContextImp
// Class to "add" implementation-only methods to VerilatedContext
class VerilatedContextImp final : VerilatedContext {
friend class VerilatedContext;
// MEMBERS - non-static not allowed, use only VerilatedContext
// Select initial value of otherwise uninitialized signals.
// Internal note: Globals may multi-construct, see verilated.cpp top.
// Medium speed, so uses singleton accessing
struct Statics {
VerilatedMutex s_randMutex; // Mutex protecting s_randSeedEpoch
// Number incrementing on each reseed, 0=illegal
int s_randSeedEpoch = 1; // Reads ok, wish had a VL_WRITE_GUARDED_BY(s_randMutex)
};
static Statics& s() {
static Statics s_s;
return s_s;
}
private:
// CONSTRUCTORS - no data can live here, use only VerilatedContext
VerilatedContextImp() = delete;
~VerilatedContextImp() = delete;
public: // But only for verilated*.cpp
// METHODS - extending into VerilatedContext, call via impp()->
// Random seed handling
vluint64_t randSeedDefault64() const VL_MT_SAFE;
static vluint32_t randSeedEpoch() VL_MT_SAFE { return s().s_randSeedEpoch; }
// METHODS - timeformat
int timeFormatUnits() VL_MT_SAFE {
if (m_s.m_timeFormatUnits == VerilatedContext::Serialized::UNITS_NONE)
return timeprecision();
return m_s.m_timeFormatUnits;
}
void timeFormatUnits(int value) VL_MT_SAFE { m_s.m_timeFormatUnits = value; }
int timeFormatPrecision() const VL_MT_SAFE { return m_s.m_timeFormatPrecision; }
void timeFormatPrecision(int value) VL_MT_SAFE { m_s.m_timeFormatPrecision = value; }
int timeFormatWidth() const VL_MT_SAFE { return m_s.m_timeFormatWidth; }
void timeFormatWidth(int value) VL_MT_SAFE { m_s.m_timeFormatWidth = value; }
std::string timeFormatSuffix() VL_MT_SAFE_EXCLUDES(m_timeDumpMutex) {
const VerilatedLockGuard lock(m_timeDumpMutex);
return m_timeFormatSuffix;
}
void timeFormatSuffix(const std::string& value) VL_MT_SAFE_EXCLUDES(m_timeDumpMutex) {
const VerilatedLockGuard lock(m_timeDumpMutex);
m_timeFormatSuffix = value;
}
// METHODS - arguments
std::string argPlusMatch(const char* prefixp) VL_MT_SAFE_EXCLUDES(m_argMutex);
std::pair<int, char**> argc_argv() VL_MT_SAFE_EXCLUDES(m_argMutex);
public: // But only for verilated*.cpp
// METHODS - scope name
void scopeInsert(const VerilatedScope* scopep) VL_MT_SAFE;
void scopeErase(const VerilatedScope* scopep) VL_MT_SAFE;
public: // But only for verilated*.cpp
// METHODS - file IO
IData fdNewMcd(const char* filenamep) VL_MT_SAFE_EXCLUDES(m_fdMutex) {
const VerilatedLockGuard lock(m_fdMutex);
if (m_fdFreeMct.empty()) return 0;
IData idx = m_fdFreeMct.back();
m_fdFreeMct.pop_back();
m_fdps[idx] = fopen(filenamep, "w");
if (VL_UNLIKELY(!m_fdps[idx])) return 0;
return (1 << idx);
}
IData fdNew(const char* filenamep, const char* modep) VL_MT_SAFE_EXCLUDES(m_fdMutex) {
FILE* fp = fopen(filenamep, modep);
if (VL_UNLIKELY(!fp)) return 0;
// Bit 31 indicates it's a descriptor not a MCD
const VerilatedLockGuard lock(m_fdMutex);
if (m_fdFree.empty()) {
// Need to create more space in m_fdps and m_fdFree
const std::size_t start = std::max<std::size_t>(31UL + 1UL + 3UL, m_fdps.size());
const std::size_t excess = 10;
m_fdps.resize(start + excess);
std::fill(m_fdps.begin() + start, m_fdps.end(), (FILE*)0);
m_fdFree.resize(excess);
for (std::size_t i = 0, id = start; i < m_fdFree.size(); ++i, ++id) {
m_fdFree[i] = id;
}
}
IData idx = m_fdFree.back();
m_fdFree.pop_back();
m_fdps[idx] = fp;
return (idx | (1UL << 31)); // bit 31 indicates not MCD
}
void fdFlush(IData fdi) VL_MT_SAFE_EXCLUDES(m_fdMutex) {
const VerilatedLockGuard lock(m_fdMutex);
const VerilatedFpList fdlist = fdToFpList(fdi);
for (const auto& i : fdlist) fflush(i);
}
IData fdSeek(IData fdi, IData offset, IData origin) VL_MT_SAFE_EXCLUDES(m_fdMutex) {
const VerilatedLockGuard lock(m_fdMutex);
const VerilatedFpList fdlist = fdToFpList(fdi);
if (VL_UNLIKELY(fdlist.size() != 1)) return 0;
return static_cast<IData>(
fseek(*fdlist.begin(), static_cast<long>(offset), static_cast<int>(origin)));
}
IData fdTell(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 0;
return static_cast<IData>(ftell(*fdlist.begin()));
}
void fdWrite(IData fdi, const std::string& output) VL_MT_SAFE_EXCLUDES(m_fdMutex) {
const VerilatedLockGuard lock(m_fdMutex);
const VerilatedFpList fdlist = fdToFpList(fdi);
for (const auto& i : fdlist) {
if (VL_UNLIKELY(!i)) continue;
(void)fwrite(output.c_str(), 1, output.size(), i);
}
}
void fdClose(IData fdi) VL_MT_SAFE_EXCLUDES(m_fdMutex) {
const VerilatedLockGuard lock(m_fdMutex);
if ((fdi & (1 << 31)) != 0) {
// Non-MCD case
IData idx = VL_MASK_I(31) & fdi;
if (VL_UNLIKELY(idx >= m_fdps.size())) return;
if (VL_UNLIKELY(!m_fdps[idx])) return; // Already free
fclose(m_fdps[idx]);
m_fdps[idx] = (FILE*)0;
m_fdFree.push_back(idx);
} else {
// MCD case
for (int i = 0; (fdi != 0) && (i < 31); i++, fdi >>= 1) {
if (fdi & VL_MASK_I(1)) {
fclose(m_fdps[i]);
m_fdps[i] = nullptr;
m_fdFreeMct.push_back(i);
}
}
}
}
inline 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;
return *fdlist.begin();
}
private:
VerilatedFpList fdToFpList(IData fdi) VL_REQUIRES(m_fdMutex) {
VerilatedFpList fp;
if ((fdi & (1 << 31)) != 0) {
// Non-MCD case
const IData idx = fdi & VL_MASK_I(31);
switch (idx) {
case 0: fp.push_back(stdin); break;
case 1: fp.push_back(stdout); break;
case 2: fp.push_back(stderr); break;
default:
if (VL_LIKELY(idx < m_fdps.size())) fp.push_back(m_fdps[idx]);
break;
}
} else {
// MCD Case
for (size_t i = 0; (fdi != 0) && (i < fp.capacity()); ++i, fdi >>= 1) {
if (fdi & VL_MASK_I(1)) fp.push_back(m_fdps[i]);
}
}
return fp;
}
protected:
// METHODS - protected
void commandArgsAddGuts(int argc, const char** argv);
void commandArgVl(const std::string& arg);
bool commandArgVlValue(const std::string& arg, const std::string& prefix, std::string& valuer);
void commandArgDump() const VL_MT_SAFE_EXCLUDES(m_argMutex);
};
//======================================================================
// VerilatedImp
class VerilatedImpData final {
// Whole class is internal use only - Global information shared between verilated*.cpp files.
// All only medium-speed, so use singleton function
protected:
friend class Verilated;
friend class VerilatedImp;
// TYPES
typedef std::vector<std::string> ArgVec;
typedef std::map<std::pair<const void*, void*>, void*> UserMap;
typedef std::map<const char*, int, VerilatedCStrCmp> ExportNameMap;
// MEMBERS
struct Serialized { // All these members serialized/deserialized
int m_timeFormatUnits = UNITS_NONE; // $timeformat units
int m_timeFormatPrecision = 0; // $timeformat number of decimal places
int m_timeFormatWidth = 20; // $timeformat character width
enum { UNITS_NONE = 99 }; // Default based on precision
Serialized() = default;
~Serialized() = default;
} m_ser;
VerilatedMutex m_sergMutex; ///< Protect m_ser
struct SerializedG { // All these members serialized/deserialized and guarded
std::string m_timeFormatSuffix; // $timeformat printf format
} m_serg VL_GUARDED_BY(m_sergMutex);
// Nothing below here is save-restored; users expected to re-register appropriately
VerilatedMutex m_argMutex; ///< Protect m_argVec, m_argVecLoaded
/// Argument list (NOT save-restored, may want different results)
ArgVec m_argVec VL_GUARDED_BY(m_argMutex);
bool m_argVecLoaded VL_GUARDED_BY(m_argMutex); ///< Ever loaded argument list
VerilatedMutex m_userMapMutex; ///< Protect m_userMap
// For userInsert, userFind. As indexed by pointer is common across contexts.
UserMap m_userMap VL_GUARDED_BY(m_userMapMutex); ///< Map of <(scope,userkey), userData>
VerilatedMutex m_nameMutex; ///< Protect m_nameMap
/// Map of <scope_name, scope pointer>
VerilatedScopeNameMap m_nameMap VL_GUARDED_BY(m_nameMutex);
VerilatedMutex m_hierMapMutex; ///< Protect m_hierMap
/// Map that represents scope hierarchy
// Used by hierarchyAdd, hierarchyRemove, hierarchyMap
VerilatedHierarchyMap m_hierMap VL_GUARDED_BY(m_hierMapMutex);
// Slow - somewhat static:
VerilatedMutex m_exportMutex; ///< Protect m_nameMap
/// Map of <export_func_proto, func number>
// Used by exportInsert, exportFind, exportName.
// Export numbers same across all contexts as just a string-to-number conversion
ExportNameMap m_exportMap VL_GUARDED_BY(m_exportMutex);
int m_exportNext VL_GUARDED_BY(m_exportMutex); ///< Next export funcnum
// File I/O
VerilatedMutex m_fdMutex; ///< Protect m_fdps, m_fdFree
std::vector<FILE*> m_fdps VL_GUARDED_BY(m_fdMutex); ///< File descriptors
/// List of free descriptors (SLOW - FOPEN/CLOSE only)
std::vector<IData> m_fdFree VL_GUARDED_BY(m_fdMutex);
// List of free descriptors in the MCT region [4, 32)
std::vector<IData> m_fdFreeMct VL_GUARDED_BY(m_fdMutex);
int m_exportNext VL_GUARDED_BY(m_exportMutex) = 0; ///< Next export funcnum
// CONSTRUCTORS
VerilatedImpData()
: m_argVecLoaded{false}
, m_exportNext{0} {
m_fdps.resize(31);
std::fill(m_fdps.begin(), m_fdps.end(), (FILE*)0);
m_fdFreeMct.resize(30);
for (std::size_t i = 0, id = 1; i < m_fdFreeMct.size(); ++i, ++id) { m_fdFreeMct[i] = id; }
}
VerilatedImpData() = default;
};
class VerilatedImp final {
@ -270,95 +431,62 @@ protected:
friend class Verilated;
// MEMBERS
union VerilatedImpU { ///< Enclose in an union to call ctor/dtor manually
VerilatedImpData v;
VerilatedImpU() {} // Can't be = default;
~VerilatedImpU() {} // Can't be = default;
};
static VerilatedImpU s_s; ///< Static Singleton; One and only static this
static VerilatedImpData& s() { // Singleton
static VerilatedImpData s_s;
return s_s;
}
public: // But only for verilated*.cpp
// CONSTRUCTORS
VerilatedImp() = default;
~VerilatedImp() = default;
static void setup();
static void teardown();
private:
VL_UNCOPYABLE(VerilatedImp);
public:
// METHODS - debug
static void internalsDump() VL_MT_SAFE;
static void versionDump() VL_MT_SAFE;
// METHODS - arguments
public:
static void commandArgs(int argc, const char** argv) VL_EXCLUDES(s_s.v.m_argMutex);
static void commandArgsAdd(int argc, const char** argv) VL_EXCLUDES(s_s.v.m_argMutex);
static std::string argPlusMatch(const char* prefixp) VL_EXCLUDES(s_s.v.m_argMutex) {
const VerilatedLockGuard lock(s_s.v.m_argMutex);
// Note prefixp does not include the leading "+"
size_t len = strlen(prefixp);
if (VL_UNLIKELY(!s_s.v.m_argVecLoaded)) {
s_s.v.m_argVecLoaded = true; // Complain only once
VL_FATAL_MT("unknown", 0, "",
"%Error: Verilog called $test$plusargs or $value$plusargs without"
" testbench C first calling Verilated::commandArgs(argc,argv).");
}
for (const auto& i : s_s.v.m_argVec) {
if (i[0] == '+') {
if (0 == strncmp(prefixp, i.c_str() + 1, len)) return i;
}
}
return "";
}
private:
static void commandArgsAddGuts(int argc, const char** argv) VL_REQUIRES(s_s.v.m_argMutex);
static void commandArgVl(const std::string& arg);
static bool commandArgVlValue(const std::string& arg, const std::string& prefix,
std::string& valuer);
public:
// METHODS - user scope tracking
// We implement this as a single large map instead of one map per scope
// We implement this as a single large map instead of one map per scope.
// 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 {
const VerilatedLockGuard lock(s_s.v.m_userMapMutex);
const auto it = s_s.v.m_userMap.find(std::make_pair(scopep, userKey));
if (it != s_s.v.m_userMap.end()) {
const VerilatedLockGuard lock(s().m_userMapMutex);
const auto it = s().m_userMap.find(std::make_pair(scopep, userKey));
if (it != s().m_userMap.end()) {
it->second = userData;
} else {
s_s.v.m_userMap.emplace(std::make_pair(scopep, userKey), userData);
s().m_userMap.emplace(std::make_pair(scopep, userKey), userData);
}
}
static inline void* userFind(const void* scopep, void* userKey) VL_MT_SAFE {
const VerilatedLockGuard lock(s_s.v.m_userMapMutex);
const auto& it = vlstd::as_const(s_s.v.m_userMap).find(std::make_pair(scopep, userKey));
if (VL_UNLIKELY(it == s_s.v.m_userMap.end())) return nullptr;
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;
return it->second;
}
private:
public: // But only for verilated.cpp
/// Symbol table destruction cleans up the entries for each scope.
static void userEraseScope(const VerilatedScope* scopep) VL_MT_SAFE {
// Slow ok - called once/scope on destruction, so we simply iterate.
const VerilatedLockGuard lock(s_s.v.m_userMapMutex);
for (auto it = s_s.v.m_userMap.begin(); it != s_s.v.m_userMap.end();) {
const VerilatedLockGuard lock(s().m_userMapMutex);
for (auto it = s().m_userMap.begin(); it != s().m_userMap.end();) {
if (it->first.first == scopep) {
s_s.v.m_userMap.erase(it++);
s().m_userMap.erase(it++);
} else {
++it;
}
}
}
static void userDump() VL_MT_SAFE {
const VerilatedLockGuard lock(
s_s.v.m_userMapMutex); // Avoid it changing in middle of dump
const VerilatedLockGuard lock(s().m_userMapMutex); // Avoid it changing in middle of dump
bool first = true;
for (const auto& i : s_s.v.m_userMap) {
for (const auto& i : s().m_userMap) {
if (first) {
VL_PRINTF_MT(" userDump:\n");
first = false;
@ -368,54 +496,18 @@ private:
}
}
public: // But only for verilated*.cpp
// METHODS - scope name
static void scopeInsert(const VerilatedScope* scopep) VL_MT_SAFE {
// Slow ok - called once/scope at construction
const VerilatedLockGuard lock(s_s.v.m_nameMutex);
const auto it = s_s.v.m_nameMap.find(scopep->name());
if (it == s_s.v.m_nameMap.end()) s_s.v.m_nameMap.emplace(scopep->name(), scopep);
}
static inline const VerilatedScope* scopeFind(const char* namep) VL_MT_SAFE {
const VerilatedLockGuard lock(s_s.v.m_nameMutex);
// If too slow, can assume this is only VL_MT_SAFE_POSINIT
const auto& it = s_s.v.m_nameMap.find(namep);
if (VL_UNLIKELY(it == s_s.v.m_nameMap.end())) return nullptr;
return it->second;
}
static void scopeErase(const VerilatedScope* scopep) VL_MT_SAFE {
// Slow ok - called once/scope at destruction
const VerilatedLockGuard lock(s_s.v.m_nameMutex);
userEraseScope(scopep);
const auto it = s_s.v.m_nameMap.find(scopep->name());
if (it != s_s.v.m_nameMap.end()) s_s.v.m_nameMap.erase(it);
}
static void scopesDump() VL_MT_SAFE {
const VerilatedLockGuard lock(s_s.v.m_nameMutex);
VL_PRINTF_MT(" scopesDump:\n");
for (const auto& i : s_s.v.m_nameMap) {
const VerilatedScope* scopep = i.second;
scopep->scopeDump();
}
VL_PRINTF_MT("\n");
}
static const VerilatedScopeNameMap* scopeNameMap() VL_MT_SAFE_POSTINIT {
// Thread save only assuming this is called only after model construction completed
return &s_s.v.m_nameMap;
}
public: // But only for verilated*.cpp
// METHODS - hierarchy
static void hierarchyAdd(const VerilatedScope* fromp, const VerilatedScope* top) VL_MT_SAFE {
// Slow ok - called at construction for VPI accessible elements
const VerilatedLockGuard lock(s_s.v.m_hierMapMutex);
s_s.v.m_hierMap[fromp].push_back(top);
const VerilatedLockGuard lock(s().m_hierMapMutex);
s().m_hierMap[fromp].push_back(top);
}
static void hierarchyRemove(const VerilatedScope* fromp,
const VerilatedScope* top) VL_MT_SAFE {
// Slow ok - called at destruction for VPI accessible elements
const VerilatedLockGuard lock(s_s.v.m_hierMapMutex);
VerilatedHierarchyMap& map = s_s.v.m_hierMap;
const VerilatedLockGuard lock(s().m_hierMapMutex);
VerilatedHierarchyMap& map = s().m_hierMap;
if (map.find(fromp) == map.end()) return;
auto& scopes = map[fromp];
const auto it = find(scopes.begin(), scopes.end(), top);
@ -423,7 +515,7 @@ public: // But only for verilated*.cpp
}
static const VerilatedHierarchyMap* hierarchyMap() VL_MT_SAFE_POSTINIT {
// Thread save only assuming this is called only after model construction completed
return &s_s.v.m_hierMap;
return &s().m_hierMap;
}
public: // But only for verilated*.cpp
@ -437,19 +529,19 @@ public: // But only for verilated*.cpp
// miss at the cost of a multiply, and all lookups move to slowpath.
static int exportInsert(const char* namep) VL_MT_SAFE {
// Slow ok - called once/function at creation
const VerilatedLockGuard lock(s_s.v.m_exportMutex);
const auto it = s_s.v.m_exportMap.find(namep);
if (it == s_s.v.m_exportMap.end()) {
s_s.v.m_exportMap.emplace(namep, s_s.v.m_exportNext++);
return s_s.v.m_exportNext++;
const VerilatedLockGuard lock(s().m_exportMutex);
const auto it = s().m_exportMap.find(namep);
if (it == s().m_exportMap.end()) {
s().m_exportMap.emplace(namep, s().m_exportNext++);
return s().m_exportNext++;
} else {
return it->second;
}
}
static int exportFind(const char* namep) VL_MT_SAFE {
const VerilatedLockGuard lock(s_s.v.m_exportMutex);
const auto& it = s_s.v.m_exportMap.find(namep);
if (VL_LIKELY(it != s_s.v.m_exportMap.end())) return it->second;
const VerilatedLockGuard lock(s().m_exportMutex);
const auto& it = s().m_exportMap.find(namep);
if (VL_LIKELY(it != s().m_exportMap.end())) return it->second;
std::string msg = (std::string("%Error: Testbench C called ") + namep
+ " but no such DPI export function name exists in ANY model");
VL_FATAL_MT("unknown", 0, "", msg.c_str());
@ -457,16 +549,16 @@ public: // But only for verilated*.cpp
}
static const char* exportName(int funcnum) VL_MT_SAFE {
// Slowpath; find name for given export; errors only so no map to reverse-map it
const VerilatedLockGuard lock(s_s.v.m_exportMutex);
for (const auto& i : s_s.v.m_exportMap) {
const VerilatedLockGuard lock(s().m_exportMutex);
for (const auto& i : s().m_exportMap) {
if (i.second == funcnum) return i.first;
}
return "*UNKNOWN*";
}
static void exportsDump() VL_MT_SAFE {
const VerilatedLockGuard lock(s_s.v.m_exportMutex);
const VerilatedLockGuard lock(s().m_exportMutex);
bool first = true;
for (const auto& i : s_s.v.m_exportMap) {
for (const auto& i : s().m_exportMap) {
if (first) {
VL_PRINTF_MT(" exportDump:\n");
first = false;
@ -476,131 +568,6 @@ public: // But only for verilated*.cpp
}
// We don't free up m_exportMap until the end, because we can't be sure
// what other models are using the assigned funcnum's.
public: // But only for verilated*.cpp
// METHODS - timeformat
static std::string timeFormatSuffix() VL_MT_SAFE;
static void timeFormatSuffix(const std::string& value) VL_MT_SAFE;
static int timeFormatUnits() VL_MT_SAFE {
if (s_s.v.m_ser.m_timeFormatUnits == VerilatedImpData::Serialized::UNITS_NONE) {
return Verilated::timeprecision();
}
return s_s.v.m_ser.m_timeFormatUnits;
}
static int timeFormatPrecision() VL_MT_SAFE { return s_s.v.m_ser.m_timeFormatPrecision; }
static int timeFormatWidth() VL_MT_SAFE { return s_s.v.m_ser.m_timeFormatWidth; }
static void timeFormatUnits(int value) VL_MT_SAFE;
static void timeFormatPrecision(int value) VL_MT_SAFE;
static void timeFormatWidth(int value) VL_MT_SAFE;
public: // But only for verilated*.cpp
// METHODS - file IO
static IData fdNewMcd(const char* filenamep) VL_MT_SAFE {
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
if (s_s.v.m_fdFreeMct.empty()) return 0;
IData idx = s_s.v.m_fdFreeMct.back();
s_s.v.m_fdFreeMct.pop_back();
s_s.v.m_fdps[idx] = fopen(filenamep, "w");
if (VL_UNLIKELY(!s_s.v.m_fdps[idx])) return 0;
return (1 << idx);
}
static IData fdNew(const char* filenamep, const char* modep) VL_MT_SAFE {
FILE* fp = fopen(filenamep, modep);
if (VL_UNLIKELY(!fp)) return 0;
// Bit 31 indicates it's a descriptor not a MCD
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
if (s_s.v.m_fdFree.empty()) {
// Need to create more space in m_fdps and m_fdFree
const std::size_t start = std::max<std::size_t>(31UL + 1UL + 3UL, s_s.v.m_fdps.size());
const std::size_t excess = 10;
s_s.v.m_fdps.resize(start + excess);
std::fill(s_s.v.m_fdps.begin() + start, s_s.v.m_fdps.end(), (FILE*)0);
s_s.v.m_fdFree.resize(excess);
for (std::size_t i = 0, id = start; i < s_s.v.m_fdFree.size(); ++i, ++id) {
s_s.v.m_fdFree[i] = id;
}
}
IData idx = s_s.v.m_fdFree.back();
s_s.v.m_fdFree.pop_back();
s_s.v.m_fdps[idx] = fp;
return (idx | (1UL << 31)); // bit 31 indicates not MCD
}
static void fdFlush(IData fdi) VL_MT_SAFE {
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
const VerilatedFpList fdlist = fdToFpList(fdi);
for (const auto& i : fdlist) fflush(i);
}
static IData fdSeek(IData fdi, IData offset, IData origin) VL_MT_SAFE {
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
const VerilatedFpList fdlist = fdToFpList(fdi);
if (VL_UNLIKELY(fdlist.size() != 1)) return 0;
return static_cast<IData>(
fseek(*fdlist.begin(), static_cast<long>(offset), static_cast<int>(origin)));
}
static IData fdTell(IData fdi) VL_MT_SAFE {
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
const VerilatedFpList fdlist = fdToFpList(fdi);
if (VL_UNLIKELY(fdlist.size() != 1)) return 0;
return static_cast<IData>(ftell(*fdlist.begin()));
}
static void fdWrite(IData fdi, const std::string& output) VL_MT_SAFE {
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
const VerilatedFpList fdlist = fdToFpList(fdi);
for (const auto& i : fdlist) {
if (VL_UNLIKELY(!i)) continue;
(void)fwrite(output.c_str(), 1, output.size(), i);
}
}
static void fdClose(IData fdi) VL_MT_SAFE {
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
if ((fdi & (1 << 31)) != 0) {
// Non-MCD case
IData idx = VL_MASK_I(31) & fdi;
if (VL_UNLIKELY(idx >= s_s.v.m_fdps.size())) return;
if (VL_UNLIKELY(!s_s.v.m_fdps[idx])) return; // Already free
fclose(s_s.v.m_fdps[idx]);
s_s.v.m_fdps[idx] = (FILE*)0;
s_s.v.m_fdFree.push_back(idx);
} else {
// MCD case
for (int i = 0; (fdi != 0) && (i < 31); i++, fdi >>= 1) {
if (fdi & VL_MASK_I(1)) {
fclose(s_s.v.m_fdps[i]);
s_s.v.m_fdps[i] = nullptr;
s_s.v.m_fdFreeMct.push_back(i);
}
}
}
}
static inline FILE* fdToFp(IData fdi) VL_MT_SAFE {
const VerilatedLockGuard lock(s_s.v.m_fdMutex);
const VerilatedFpList fdlist = fdToFpList(fdi);
if (VL_UNLIKELY(fdlist.size() != 1)) return nullptr;
return *fdlist.begin();
}
private:
static inline VerilatedFpList fdToFpList(IData fdi) VL_REQUIRES(s_s.v.m_fdMutex) {
VerilatedFpList fp;
if ((fdi & (1 << 31)) != 0) {
// Non-MCD case
const IData idx = fdi & VL_MASK_I(31);
switch (idx) {
case 0: fp.push_back(stdin); break;
case 1: fp.push_back(stdout); break;
case 2: fp.push_back(stderr); break;
default:
if (VL_LIKELY(idx < s_s.v.m_fdps.size())) fp.push_back(s_s.v.m_fdps[idx]);
break;
}
} else {
// MCD Case
for (size_t i = 0; (fdi != 0) && (i < fp.capacity()); ++i, fdi >>= 1) {
if (fdi & VL_MASK_I(1)) fp.push_back(s_s.v.m_fdps[i]);
}
}
return fp;
}
};
//======================================================================

View File

@ -19,8 +19,8 @@
///
//*************************************************************************
#ifndef _VERILATED_INTRINSICS_H_
#define _VERILATED_INTRINSICS_H_ 1 ///< Header Guard
#ifndef VERILATOR_VERILATED_INTRINSICS_H_
#define VERILATOR_VERILATED_INTRINSICS_H_ ///< Header Guard
// clang-format off

View File

@ -16,9 +16,12 @@
///
//=============================================================================
#define VERILATOR_VERILATED_SAVE_CPP_
#include "verilatedos.h"
#include "verilated.h"
#include "verilated_save.h"
#include "verilated_imp.h"
#include <cerrno>
#include <fcntl.h>
@ -43,7 +46,7 @@
// CONSTANTS
/// Value of first bytes of each file (must be multiple of 8 bytes)
static const char* const VLTSAVE_HEADER_STR = "verilatorsave01\n";
static const char* const VLTSAVE_HEADER_STR = "verilatorsave02\n";
/// Value of last bytes of each file (must be multiple of 8 bytes)
static const char* const VLTSAVE_TRAILER_STR = "vltsaved";
@ -77,11 +80,6 @@ void VerilatedSerialize::header() VL_MT_UNSAFE_ONE {
VerilatedSerialize& os = *this; // So can cut and paste standard << code below
assert((strlen(VLTSAVE_HEADER_STR) & 7) == 0); // Keep aligned
os.write(VLTSAVE_HEADER_STR, strlen(VLTSAVE_HEADER_STR));
// Verilated doesn't do it itself, as if we're not using save/restore
// it doesn't need to compile this stuff in
os.write(Verilated::serialized1Ptr(), Verilated::serialized1Size());
os.write(Verilated::serialized2Ptr(), Verilated::serialized2Size());
}
void VerilatedDeserialize::header() VL_MT_UNSAFE_ONE {
@ -95,8 +93,6 @@ void VerilatedDeserialize::header() VL_MT_UNSAFE_ONE {
VL_FATAL_MT(fn.c_str(), 0, "", msg.c_str());
// Die before we close() as close would infinite loop
}
os.read(Verilated::serialized1Ptr(), Verilated::serialized1Size());
os.read(Verilated::serialized2Ptr(), Verilated::serialized2Size());
}
void VerilatedSerialize::trailer() VL_MT_UNSAFE_ONE {
@ -249,3 +245,19 @@ void VerilatedRestore::fill() VL_MT_UNSAFE_ONE {
//=============================================================================
// Serialization of types
VerilatedSerialize& operator<<(VerilatedSerialize& os, VerilatedContext* rhsp) {
os.write(rhsp->serialized1Ptr(), rhsp->serialized1Size());
os << rhsp->impp()->timeFormatSuffix();
os << rhsp->dumpfile();
return os;
}
VerilatedDeserialize& operator>>(VerilatedDeserialize& os, VerilatedContext* rhsp) {
os.read(rhsp->serialized1Ptr(), rhsp->serialized1Size());
std::string s;
os >> s;
rhsp->impp()->timeFormatSuffix(s);
os >> s;
rhsp->dumpfile(s);
return os;
}

View File

@ -16,8 +16,8 @@
///
//=============================================================================
#ifndef _VERILATED_SAVE_C_H_
#define _VERILATED_SAVE_C_H_ 1
#ifndef VERILATOR_VERILATED_SAVE_C_H_
#define VERILATOR_VERILATED_SAVE_C_H_
#include "verilatedos.h"
#include "verilated_heavy.h"
@ -61,7 +61,7 @@ public:
std::string filename() const { return m_filename; }
virtual void close() VL_MT_UNSAFE_ONE { flush(); }
virtual void flush() VL_MT_UNSAFE_ONE {}
inline VerilatedSerialize& write(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE {
VerilatedSerialize& write(const void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE {
const vluint8_t* __restrict dp = (const vluint8_t* __restrict)datap;
while (size) {
bufferCheck();
@ -122,7 +122,7 @@ public:
std::string filename() const { return m_filename; }
virtual void close() VL_MT_UNSAFE_ONE { flush(); }
virtual void flush() VL_MT_UNSAFE_ONE {}
inline VerilatedDeserialize& read(void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE {
VerilatedDeserialize& read(void* __restrict datap, size_t size) VL_MT_UNSAFE_ONE {
vluint8_t* __restrict dp = static_cast<vluint8_t* __restrict>(datap);
while (size) {
bufferCheck();
@ -236,7 +236,7 @@ inline VerilatedSerialize& operator<<(VerilatedSerialize& os, float& rhs) {
inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, float& rhs) {
return os.read(&rhs, sizeof(rhs));
}
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, std::string& rhs) {
inline VerilatedSerialize& operator<<(VerilatedSerialize& os, const std::string& rhs) {
vluint32_t len = rhs.length();
os << len;
return os.write(rhs.data(), len);
@ -247,6 +247,9 @@ inline VerilatedDeserialize& operator>>(VerilatedDeserialize& os, std::string& r
rhs.resize(len);
return os.read((void*)rhs.data(), len);
}
VerilatedSerialize& operator<<(VerilatedSerialize& os, VerilatedContext* rhsp);
VerilatedDeserialize& operator>>(VerilatedDeserialize& os, VerilatedContext* rhsp);
template <class T_Key, class T_Value>
VerilatedSerialize& operator<<(VerilatedSerialize& os, VlAssocArray<T_Key, T_Value>& rhs) {
os << rhs.atDefault();

View File

@ -19,8 +19,8 @@
///
//*************************************************************************
#ifndef _VERILATED_SC_H_
#define _VERILATED_SC_H_ 1 ///< Header Guard
#ifndef VERILATOR_VERILATED_SC_H_
#define VERILATOR_VERILATED_SC_H_ ///< Header Guard
#include "verilatedos.h"

View File

@ -24,8 +24,8 @@
///
//*************************************************************************
#ifndef _VERILATED_SYM_PROPS_H_
#define _VERILATED_SYM_PROPS_H_ 1 ///< Header Guard
#ifndef VERILATOR_VERILATED_SYM_PROPS_H_
#define VERILATOR_VERILATED_SYM_PROPS_H_ ///< Header Guard
#include "verilatedos.h"
@ -70,7 +70,7 @@ public:
class VerilatedVarProps VL_NOT_FINAL {
// TYPES
enum { MAGIC = 0xddc4f829 };
static constexpr vluint32_t MAGIC = 0xddc4f829UL;
// MEMBERS
const vluint32_t m_magic; // Magic number
const VerilatedVarType m_vltype; // Data type

View File

@ -23,8 +23,8 @@
///
//*************************************************************************
#ifndef _VERILATED_SYMS_H_
#define _VERILATED_SYMS_H_ 1 ///< Header Guard
#ifndef VERILATOR_VERILATED_SYMS_H_
#define VERILATOR_VERILATED_SYMS_H_ ///< Header Guard
#include "verilatedos.h"
#include "verilated_heavy.h"

View File

@ -19,6 +19,11 @@
#include <cstdio>
//=============================================================================
// Globals
// Internal note: Globals may multi-construct, see verilated.cpp top.
std::atomic<vluint64_t> VlMTaskVertex::s_yields;
VL_THREAD_LOCAL VlThreadPool::ProfileTrace* VlThreadPool::t_profilep = nullptr;
@ -35,12 +40,12 @@ VlMTaskVertex::VlMTaskVertex(vluint32_t upstreamDepCount)
//=============================================================================
// VlWorkerThread
VlWorkerThread::VlWorkerThread(VlThreadPool* poolp, bool profiling)
: m_waiting{false}
, m_poolp{poolp}
VlWorkerThread::VlWorkerThread(VlThreadPool* poolp, VerilatedContext* contextp, bool profiling)
: m_poolp{poolp}
, m_profiling{profiling} // Must init this last -- after setting up fields that it might read:
, m_exiting{false}
, m_cthread{startWorker, this} {}
, m_cthread{startWorker, this}
, m_contextp{contextp} {}
VlWorkerThread::~VlWorkerThread() {
m_exiting.store(true, std::memory_order_release);
@ -70,12 +75,15 @@ void VlWorkerThread::workerLoop() {
if (VL_UNLIKELY(m_profiling)) m_poolp->tearDownProfilingClientThread();
}
void VlWorkerThread::startWorker(VlWorkerThread* workerp) { workerp->workerLoop(); }
void VlWorkerThread::startWorker(VlWorkerThread* workerp) {
Verilated::threadContextp(workerp->m_contextp);
workerp->workerLoop();
}
//=============================================================================
// VlThreadPool
VlThreadPool::VlThreadPool(int nThreads, bool profiling)
VlThreadPool::VlThreadPool(VerilatedContext* contextp, int nThreads, bool profiling)
: m_profiling{profiling} {
// --threads N passes nThreads=N-1, as the "main" threads counts as 1
unsigned cpus = std::thread::hardware_concurrency();
@ -89,7 +97,7 @@ VlThreadPool::VlThreadPool(int nThreads, bool profiling)
}
// Create'em
for (int i = 0; i < nThreads; ++i) {
m_workers.push_back(new VlWorkerThread(this, profiling));
m_workers.push_back(new VlWorkerThread(this, contextp, profiling));
}
// Set up a profile buffer for the current thread too -- on the
// assumption that it's the same thread that calls eval and may be
@ -109,7 +117,7 @@ void VlThreadPool::tearDownProfilingClientThread() {
t_profilep = nullptr;
}
void VlThreadPool::setupProfilingClientThread() {
void VlThreadPool::setupProfilingClientThread() VL_MT_SAFE_EXCLUDES(m_mutex) {
assert(!t_profilep);
t_profilep = new ProfileTrace;
// Reserve some space in the thread-local profiling buffer;
@ -121,7 +129,7 @@ void VlThreadPool::setupProfilingClientThread() {
}
}
void VlThreadPool::profileAppendAll(const VlProfileRec& rec) {
void VlThreadPool::profileAppendAll(const VlProfileRec& rec) VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lk(m_mutex);
for (const auto& profilep : m_allProfiles) {
// Every thread's profile trace gets a copy of rec.
@ -129,7 +137,8 @@ void VlThreadPool::profileAppendAll(const VlProfileRec& rec) {
}
}
void VlThreadPool::profileDump(const char* filenamep, vluint64_t ticksElapsed) {
void VlThreadPool::profileDump(const char* filenamep, vluint64_t ticksElapsed)
VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lk(m_mutex);
VL_DEBUG_IF(VL_DBG_MSGF("+prof+threads writing to '%s'\n", filenamep););
@ -145,8 +154,9 @@ void VlThreadPool::profileDump(const char* filenamep, vluint64_t ticksElapsed) {
fprintf(fp, "VLPROFTHREAD 1.0 # Verilator thread profile dump version 1.0\n");
fprintf(fp, "VLPROF arg --threads %" VL_PRI64 "u\n", vluint64_t(m_workers.size() + 1));
fprintf(fp, "VLPROF arg +verilator+prof+threads+start+%" VL_PRI64 "u\n",
Verilated::profThreadsStart());
fprintf(fp, "VLPROF arg +verilator+prof+threads+window+%u\n", Verilated::profThreadsWindow());
Verilated::threadContextp()->profThreadsStart());
fprintf(fp, "VLPROF arg +verilator+prof+threads+window+%u\n",
Verilated::threadContextp()->profThreadsWindow());
fprintf(fp, "VLPROF stat yields %" VL_PRI64 "u\n", VlMTaskVertex::yields());
vluint32_t thread_id = 0;

View File

@ -16,8 +16,8 @@
///
//=============================================================================
#ifndef _VERILATED_THREADS_H_
#define _VERILATED_THREADS_H_
#ifndef VERILATOR_VERILATED_THREADS_H_
#define VERILATOR_VERILATED_THREADS_H_
#include "verilatedos.h"
#include "verilated.h" // for VerilatedMutex and clang annotations
@ -189,7 +189,7 @@ private:
VerilatedMutex m_mutex;
std::condition_variable_any m_cv;
// Only notify the condition_variable if the worker is waiting
bool m_waiting VL_GUARDED_BY(m_mutex);
bool m_waiting VL_GUARDED_BY(m_mutex) = false;
// Why a vector? We expect the pending list to be very short, typically
// 0 or 1 or 2, so popping from the front shouldn't be
@ -203,16 +203,17 @@ private:
bool m_profiling; // Is profiling enabled?
std::atomic<bool> m_exiting; // Worker thread should exit
std::thread m_cthread; // Underlying C++ thread record
VerilatedContext* m_contextp; // Context for spawned thread
VL_UNCOPYABLE(VlWorkerThread);
public:
// CONSTRUCTORS
explicit VlWorkerThread(VlThreadPool* poolp, bool profiling);
explicit VlWorkerThread(VlThreadPool* poolp, VerilatedContext* contextp, bool profiling);
~VlWorkerThread();
// METHODS
inline void dequeWork(ExecRec* workp) {
inline void dequeWork(ExecRec* workp) VL_MT_SAFE_EXCLUDES(m_mutex) {
// Spin for a while, waiting for new data
for (int i = 0; i < VL_LOCK_SPINS; ++i) {
if (VL_LIKELY(m_ready_size.load(std::memory_order_relaxed))) { //
@ -233,7 +234,8 @@ public:
m_ready_size.fetch_sub(1, std::memory_order_relaxed);
}
inline void wakeUp() { addTask(nullptr, false, nullptr); }
inline void addTask(VlExecFnp fnp, bool evenCycle, VlThrSymTab sym) {
inline void addTask(VlExecFnp fnp, bool evenCycle, VlThrSymTab sym)
VL_MT_SAFE_EXCLUDES(m_mutex) {
bool notify;
{
const VerilatedLockGuard lk(m_mutex);
@ -262,6 +264,7 @@ class VlThreadPool final {
// corrupting the profiling data. It's super cheap to append
// a VlProfileRec struct on the end of a pre-allocated vector;
// this is the only cost we pay in real-time during a profiling cycle.
// Internal note: Globals may multi-construct, see verilated.cpp top.
static VL_THREAD_LOCAL ProfileTrace* t_profilep;
ProfileSet m_allProfiles VL_GUARDED_BY(m_mutex);
VerilatedMutex m_mutex;
@ -271,7 +274,7 @@ public:
// Construct a thread pool with 'nThreads' dedicated threads. The thread
// pool will create these threads and make them available to execute tasks
// via this->workerp(index)->addTask(...)
VlThreadPool(int nThreads, bool profiling);
VlThreadPool(VerilatedContext* contextp, int nThreads, bool profiling);
~VlThreadPool();
// METHODS
@ -285,11 +288,11 @@ public:
t_profilep->emplace_back();
return &(t_profilep->back());
}
void profileAppendAll(const VlProfileRec& rec);
void profileDump(const char* filenamep, vluint64_t ticksElapsed);
void profileAppendAll(const VlProfileRec& rec) VL_MT_SAFE_EXCLUDES(m_mutex);
void profileDump(const char* filenamep, vluint64_t ticksElapsed) VL_MT_SAFE_EXCLUDES(m_mutex);
// In profiling mode, each executing thread must call
// this once to setup profiling state:
void setupProfilingClientThread();
void setupProfilingClientThread() VL_MT_SAFE_EXCLUDES(m_mutex);
void tearDownProfilingClientThread();
private:

View File

@ -12,13 +12,12 @@
//=============================================================================
///
/// \file
/// \brief Tracing functionality common to all formats
/// \brief Internal tracing functionality common to all formats
///
//=============================================================================
// SPDIFF_OFF
#ifndef _VERILATED_TRACE_H_
#define _VERILATED_TRACE_H_ 1
#ifndef VERILATOR_VERILATED_TRACE_H_
#define VERILATOR_VERILATED_TRACE_H_
// clang-format off
@ -48,21 +47,21 @@ private:
public:
// Put an element at the back of the queue
void put(T value) {
void put(T value) VL_MT_SAFE_EXCLUDES(m_mutex) {
VerilatedLockGuard lock(m_mutex);
m_queue.push_back(value);
m_cv.notify_one();
}
// Put an element at the front of the queue
void put_front(T value) {
void put_front(T value) VL_MT_SAFE_EXCLUDES(m_mutex) {
VerilatedLockGuard lock(m_mutex);
m_queue.push_front(value);
m_cv.notify_one();
}
// Get an element from the front of the queue. Blocks if none available
T get() {
T get() VL_MT_SAFE_EXCLUDES(m_mutex) {
VerilatedLockGuard lock(m_mutex);
m_cv.wait(lock, [this]() VL_REQUIRES(m_mutex) { return !m_queue.empty(); });
assert(!m_queue.empty());
@ -72,7 +71,7 @@ public:
}
// Non blocking get
bool tryGet(T& result) {
bool tryGet(T& result) VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lockGuard(m_mutex);
if (m_queue.empty()) return false;
result = m_queue.front();
@ -152,7 +151,8 @@ private:
double m_timeRes; ///< Time resolution (ns/ms etc)
double m_timeUnit; ///< Time units (ns/ms etc)
void addCallbackRecord(std::vector<CallbackRecord>& cbVec, CallbackRecord& cbRec);
void addCallbackRecord(std::vector<CallbackRecord>& cbVec, CallbackRecord& cbRec)
VL_MT_SAFE_EXCLUDES(m_mutex);
// Equivalent to 'this' but is of the sub-type 'T_Derived*'. Use 'self()->'
// to access duck-typed functions to avoid a virtual function call.
@ -204,7 +204,7 @@ protected:
//=========================================================================
// Internals available to format specific implementations
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
VerilatedMutex m_mutex; // Ensure dump() etc only called from single thread
vluint32_t nextCode() const { return m_nextCode; }
vluint32_t numSignals() const { return m_numSignals; }
@ -221,13 +221,13 @@ protected:
void declCode(vluint32_t code, vluint32_t bits, bool tri);
/// Is this an escape?
// Is this an escape?
bool isScopeEscape(char c) { return c != '\f' && (isspace(c) || c == m_scopeEscape); }
/// Character that splits scopes. Note whitespace are ALWAYS escapes.
// Character that splits scopes. Note whitespace are ALWAYS escapes.
char scopeEscape() { return m_scopeEscape; }
void close();
void flush();
void closeBase();
void flushBase();
//=========================================================================
// Virtual functions to be provided by the format specific implementation
@ -248,30 +248,24 @@ public:
~VerilatedTrace();
// Set time units (s/ms, defaults to ns)
void set_time_unit(const char* unitp);
void set_time_unit(const std::string& unit);
void set_time_unit(const char* unitp) VL_MT_SAFE;
void set_time_unit(const std::string& unit) VL_MT_SAFE;
// Set time resolution (s/ms, defaults to ns)
void set_time_resolution(const char* unitp);
void set_time_resolution(const std::string& unit);
void set_time_resolution(const char* unitp) VL_MT_SAFE;
void set_time_resolution(const std::string& unit) VL_MT_SAFE;
// Call
void dump(vluint64_t timeui);
void dump(vluint64_t timeui) VL_MT_SAFE_EXCLUDES(m_mutex);
//=========================================================================
// Non-hot path internal interface to Verilator generated code
void addInitCb(initCb_t cb, void* userp) VL_MT_UNSAFE_ONE;
void addFullCb(dumpCb_t cb, void* userp) VL_MT_UNSAFE_ONE;
void addChgCb(dumpCb_t cb, void* userp) VL_MT_UNSAFE_ONE;
void addCleanupCb(dumpCb_t cb, void* userp) VL_MT_UNSAFE_ONE;
void changeThread() { m_assertOne.changeThread(); }
void module(const std::string& name) VL_MT_UNSAFE_ONE {
m_assertOne.check();
m_moduleName = name;
}
void addInitCb(initCb_t cb, void* userp) VL_MT_SAFE;
void addFullCb(dumpCb_t cb, void* userp) VL_MT_SAFE;
void addChgCb(dumpCb_t cb, void* userp) VL_MT_SAFE;
void addCleanupCb(dumpCb_t cb, void* userp) VL_MT_SAFE;
void module(const std::string& name) VL_MT_UNSAFE;
void scopeEscape(char flag) { m_scopeEscape = flag; }
//=========================================================================

View File

@ -15,7 +15,6 @@
/// \brief Implementation of tracing functionality common to all trace formats
///
//=============================================================================
// SPDIFF_OFF
// clang-format off
@ -70,7 +69,7 @@ static std::string doubleToTimescale(double value) {
else if (value >= 1e-18) { suffixp = "as"; value *= 1e18; }
// clang-format on
char valuestr[100];
sprintf(valuestr, "%0.0f%s", value, suffixp);
VL_SNPRINTF(valuestr, 100, "%0.0f%s", value, suffixp);
return valuestr; // Gets converted to string, so no ref to stack
}
@ -237,7 +236,7 @@ template <> void VerilatedTrace<VL_DERIVED_T>::shutdownWorker() {
//=============================================================================
// Life cycle
template <> void VerilatedTrace<VL_DERIVED_T>::close() {
template <> void VerilatedTrace<VL_DERIVED_T>::closeBase() {
#ifdef VL_TRACE_THREADED
shutdownWorker();
while (m_numTraceBuffers) {
@ -247,7 +246,7 @@ template <> void VerilatedTrace<VL_DERIVED_T>::close() {
#endif
}
template <> void VerilatedTrace<VL_DERIVED_T>::flush() {
template <> void VerilatedTrace<VL_DERIVED_T>::flushBase() {
#ifdef VL_TRACE_THREADED
// Hand an empty buffer to the worker thread
vluint32_t* const bufferp = getTraceBuffer();
@ -263,12 +262,12 @@ template <> void VerilatedTrace<VL_DERIVED_T>::flush() {
// Callbacks to run on global events
template <> void VerilatedTrace<VL_DERIVED_T>::onFlush(void* selfp) {
// Note this calls 'flush' on the derived class
// This calls 'flush' on the derived classo (which must then get any mutex)
reinterpret_cast<VL_DERIVED_T*>(selfp)->flush();
}
template <> void VerilatedTrace<VL_DERIVED_T>::onExit(void* selfp) {
// Note this calls 'close' on the derived class
// This calls 'close' on the derived class (which must then get any mutex)
reinterpret_cast<VL_DERIVED_T*>(selfp)->close();
}
@ -292,8 +291,8 @@ VerilatedTrace<VL_DERIVED_T>::VerilatedTrace()
, m_numTraceBuffers { 0 }
#endif
{
set_time_unit(Verilated::timeunitString());
set_time_resolution(Verilated::timeprecisionString());
set_time_unit(Verilated::threadContextp()->timeunitString());
set_time_resolution(Verilated::threadContextp()->timeprecisionString());
}
template <> VerilatedTrace<VL_DERIVED_T>::~VerilatedTrace() {
@ -301,7 +300,7 @@ template <> VerilatedTrace<VL_DERIVED_T>::~VerilatedTrace() {
Verilated::removeFlushCb(VerilatedTrace<VL_DERIVED_T>::onFlush, this);
Verilated::removeExitCb(VerilatedTrace<VL_DERIVED_T>::onExit, this);
#ifdef VL_TRACE_THREADED
close();
closeBase();
#endif
}
@ -309,8 +308,6 @@ template <> VerilatedTrace<VL_DERIVED_T>::~VerilatedTrace() {
// Internals available to format specific implementations
template <> void VerilatedTrace<VL_DERIVED_T>::traceInit() VL_MT_UNSAFE {
m_assertOne.check();
// Note: It is possible to re-open a trace file (VCD in particular),
// so we must reset the next code here, but it must have the same number
// of codes on re-open
@ -355,7 +352,7 @@ template <> void VerilatedTrace<VL_DERIVED_T>::traceInit() VL_MT_UNSAFE {
template <>
void VerilatedTrace<VL_DERIVED_T>::declCode(vluint32_t code, vluint32_t bits, bool tri) {
if (!code) {
if (VL_UNCOVERABLE(!code)) {
VL_FATAL_MT(__FILE__, __LINE__, "", "Internal: internal trace problem, code 0 is illegal");
}
// Note: The tri-state flag is not used by Verilator, but is here for
@ -377,24 +374,26 @@ template <> std::string VerilatedTrace<VL_DERIVED_T>::timeResStr() const {
//=========================================================================
// External interface to client code
template <> void VerilatedTrace<VL_DERIVED_T>::set_time_unit(const char* unitp) {
template <> void VerilatedTrace<VL_DERIVED_T>::set_time_unit(const char* unitp) VL_MT_SAFE {
m_timeUnit = timescaleToDouble(unitp);
}
template <> void VerilatedTrace<VL_DERIVED_T>::set_time_unit(const std::string& unit) {
template <> void VerilatedTrace<VL_DERIVED_T>::set_time_unit(const std::string& unit) VL_MT_SAFE {
set_time_unit(unit.c_str());
}
template <> void VerilatedTrace<VL_DERIVED_T>::set_time_resolution(const char* unitp) {
template <> void VerilatedTrace<VL_DERIVED_T>::set_time_resolution(const char* unitp) VL_MT_SAFE {
m_timeRes = timescaleToDouble(unitp);
}
template <> void VerilatedTrace<VL_DERIVED_T>::set_time_resolution(const std::string& unit) {
template <>
void VerilatedTrace<VL_DERIVED_T>::set_time_resolution(const std::string& unit) VL_MT_SAFE {
set_time_resolution(unit.c_str());
}
template <> void VerilatedTrace<VL_DERIVED_T>::dump(vluint64_t timeui) {
m_assertOne.check();
template <>
void VerilatedTrace<VL_DERIVED_T>::dump(vluint64_t timeui) VL_MT_SAFE_EXCLUDES(m_mutex) {
// Not really VL_MT_SAFE but more VL_MT_UNSAFE_ONE.
// This does get the mutex, but if multiple threads are trying to dump
// chances are the data being dumped will have other problems
const VerilatedLockGuard lock(m_mutex);
if (VL_UNCOVERABLE(m_timeLastDump && timeui <= m_timeLastDump)) { // LCOV_EXCL_START
VL_PRINTF_MT("%%Warning: previous dump at t=%" VL_PRI64 "u, requesting t=%" VL_PRI64
"u, dump call ignored\n",
@ -427,7 +426,7 @@ template <> void VerilatedTrace<VL_DERIVED_T>::dump(vluint64_t timeui) {
m_traceBufferWritep += 3;
} else {
// Update time point
flush();
flushBase();
emitTimeChange(timeui);
}
#else
@ -473,8 +472,9 @@ template <> void VerilatedTrace<VL_DERIVED_T>::dump(vluint64_t timeui) {
template <>
void VerilatedTrace<VL_DERIVED_T>::addCallbackRecord(std::vector<CallbackRecord>& cbVec,
CallbackRecord& cbRec) {
m_assertOne.check();
CallbackRecord& cbRec)
VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lock(m_mutex);
if (VL_UNCOVERABLE(timeLastDump() != 0)) { // LCOV_EXCL_START
std::string msg = (std::string("Internal: ") + __FILE__ + "::" + __FUNCTION__
+ " called with already open file");
@ -483,22 +483,26 @@ void VerilatedTrace<VL_DERIVED_T>::addCallbackRecord(std::vector<CallbackRecord>
cbVec.push_back(cbRec);
}
template <> void VerilatedTrace<VL_DERIVED_T>::addInitCb(initCb_t cb, void* userp) {
template <> void VerilatedTrace<VL_DERIVED_T>::addInitCb(initCb_t cb, void* userp) VL_MT_SAFE {
CallbackRecord cbr(cb, userp);
addCallbackRecord(m_initCbs, cbr);
}
template <> void VerilatedTrace<VL_DERIVED_T>::addFullCb(dumpCb_t cb, void* userp) {
template <> void VerilatedTrace<VL_DERIVED_T>::addFullCb(dumpCb_t cb, void* userp) VL_MT_SAFE {
CallbackRecord cbr(cb, userp);
addCallbackRecord(m_fullCbs, cbr);
}
template <> void VerilatedTrace<VL_DERIVED_T>::addChgCb(dumpCb_t cb, void* userp) {
template <> void VerilatedTrace<VL_DERIVED_T>::addChgCb(dumpCb_t cb, void* userp) VL_MT_SAFE {
CallbackRecord cbr(cb, userp);
addCallbackRecord(m_chgCbs, cbr);
}
template <> void VerilatedTrace<VL_DERIVED_T>::addCleanupCb(dumpCb_t cb, void* userp) {
template <> void VerilatedTrace<VL_DERIVED_T>::addCleanupCb(dumpCb_t cb, void* userp) VL_MT_SAFE {
CallbackRecord cbr(cb, userp);
addCallbackRecord(m_cleanupCbs, cbr);
}
template <> void VerilatedTrace<VL_DERIVED_T>::module(const std::string& name) VL_MT_UNSAFE {
// Called via callbacks way above in call stack, which already hold m_mutex
m_moduleName = name;
}
//=========================================================================
// Hot path internal interface to Verilator generated code
@ -651,6 +655,8 @@ void verilated_trace_imp_selftest() {
#define SELF_CHECK_TS(scale) \
SELF_CHECK(doubleToTimescale(timescaleToDouble(scale)), std::string{scale});
SELF_CHECK_TS("100s");
SELF_CHECK_TS("10s");
SELF_CHECK_TS("1s");
SELF_CHECK_TS("100ms");
SELF_CHECK_TS("10ms");

View File

@ -15,7 +15,6 @@
/// \brief C++ Tracing in VCD Format
///
//=============================================================================
// SPDIFF_OFF
// clang-format off
@ -34,8 +33,6 @@
# include <unistd.h>
#endif
// SPDIFF_ON
#ifndef O_LARGEFILE // For example on WIN32
# define O_LARGEFILE 0
#endif
@ -100,14 +97,14 @@ VerilatedVcd::VerilatedVcd(VerilatedVcdFile* filep) {
m_suffixesp = nullptr;
}
void VerilatedVcd::open(const char* filename) {
m_assertOne.check();
void VerilatedVcd::open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lock(m_mutex);
if (isOpen()) return;
// Set member variables
m_filename = filename; // "" is ok, as someone may overload open
openNext(m_rolloverMB != 0);
openNextImp(m_rolloverMB != 0);
if (!isOpen()) return;
dumpHeader();
@ -116,13 +113,17 @@ void VerilatedVcd::open(const char* filename) {
m_suffixesp = &m_suffixes[0]; // Note: C++11 m_suffixes.data();
// When using rollover, the first chunk contains the header only.
if (m_rolloverMB) openNext(true);
if (m_rolloverMB) openNextImp(true);
}
void VerilatedVcd::openNext(bool incFilename) {
void VerilatedVcd::openNext(bool incFilename) VL_MT_SAFE_EXCLUDES(m_mutex) {
// Open next filename in concat sequence, mangle filename if
// incFilename is true.
m_assertOne.check();
const VerilatedLockGuard lock(m_mutex);
openNextImp(incFilename);
}
void VerilatedVcd::openNextImp(bool incFilename) {
closePrev(); // Close existing
if (incFilename) {
// Find _0000.{ext} in filename
@ -166,7 +167,7 @@ void VerilatedVcd::openNext(bool incFilename) {
}
bool VerilatedVcd::preChangeDump() {
if (VL_UNLIKELY(m_rolloverMB && m_wroteBytes > m_rolloverMB)) openNext(true);
if (VL_UNLIKELY(m_rolloverMB && m_wroteBytes > m_rolloverMB)) openNextImp(true);
return isOpen();
}
@ -222,7 +223,7 @@ void VerilatedVcd::closePrev() {
// This function is on the flush() call path
if (!isOpen()) return;
VerilatedTrace<VerilatedVcd>::flush();
VerilatedTrace<VerilatedVcd>::flushBase();
bufferFlush();
m_isOpen = false;
m_filep->close();
@ -239,9 +240,9 @@ void VerilatedVcd::closeErr() {
m_filep->close(); // May get error, just ignore it
}
void VerilatedVcd::close() {
void VerilatedVcd::close() VL_MT_SAFE_EXCLUDES(m_mutex) {
// This function is on the flush() call path
m_assertOne.check();
const VerilatedLockGuard lock(m_mutex);
if (!isOpen()) return;
if (m_evcd) {
printStr("$vcdclose ");
@ -251,11 +252,12 @@ void VerilatedVcd::close() {
closePrev();
// closePrev() called VerilatedTrace<VerilatedVcd>::flush(), so we just
// need to shut down the tracing thread here.
VerilatedTrace<VerilatedVcd>::close();
VerilatedTrace<VerilatedVcd>::closeBase();
}
void VerilatedVcd::flush() {
VerilatedTrace<VerilatedVcd>::flush();
void VerilatedVcd::flush() VL_MT_SAFE_EXCLUDES(m_mutex) {
const VerilatedLockGuard lock(m_mutex);
VerilatedTrace<VerilatedVcd>::flushBase();
bufferFlush();
}
@ -269,7 +271,7 @@ void VerilatedVcd::printStr(const char* str) {
void VerilatedVcd::printQuad(vluint64_t n) {
char buf[100];
sprintf(buf, "%" VL_PRI64 "u", n);
VL_SNPRINTF(buf, 100, "%" VL_PRI64 "u", n);
printStr(buf);
}
@ -293,7 +295,6 @@ void VerilatedVcd::bufferFlush() VL_MT_UNSAFE_ONE {
// We add output data to m_writep.
// When it gets nearly full we dump it using this routine which calls write()
// This is much faster than using buffered I/O
m_assertOne.check();
if (VL_UNLIKELY(!isOpen())) return;
char* wp = m_wrBufp;
while (true) {
@ -347,9 +348,16 @@ void VerilatedVcd::printIndent(int level_change) {
void VerilatedVcd::dumpHeader() {
printStr("$version Generated by VerilatedVcd $end\n");
time_t time_str = time(nullptr);
printStr("$date ");
printStr(ctime(&time_str));
{
time_t tick = time(nullptr);
tm ticktm;
VL_LOCALTIME_R(&tick, &ticktm);
constexpr int bufsize = 50;
char buf[bufsize];
strftime(buf, bufsize, "%c", &ticktm);
printStr(buf);
}
printStr(" $end\n");
printStr("$timescale ");
@ -487,11 +495,12 @@ void VerilatedVcd::declare(vluint32_t code, const char* name, const char* wirep,
decl += wirep; // usually "wire"
}
char buf[1000];
sprintf(buf, " %2d ", bits);
constexpr size_t bufsize = 1000;
char buf[bufsize];
VL_SNPRINTF(buf, bufsize, " %2d ", bits);
decl += buf;
if (m_evcd) {
sprintf(buf, "<%u", code);
VL_SNPRINTF(buf, bufsize, "<%u", code);
decl += buf;
} else {
// Add string code to decl
@ -505,7 +514,8 @@ void VerilatedVcd::declare(vluint32_t code, const char* name, const char* wirep,
// 1 bit values don't have a ' ' separator between value and string code
const bool isBit = bits == 1;
entryp[0] = ' '; // Separator
std::strcpy(entryp + !isBit, buf); // Code (overwrite separator if isBit)
// Use memcpy as we checked size above, and strcpy is flagged unsafe
std::memcpy(entryp + !isBit, buf, strlen(buf)); // Code (overwrite separator if isBit)
entryp[length + !isBit] = '\n'; // Replace '\0' with line termination '\n'
// Set length of suffix (used to increment write pointer)
entryp[VL_TRACE_SUFFIX_ENTRY_SIZE - 1] = !isBit + length + 1;
@ -513,12 +523,12 @@ void VerilatedVcd::declare(vluint32_t code, const char* name, const char* wirep,
decl += " ";
decl += basename;
if (array) {
sprintf(buf, "(%d)", arraynum);
VL_SNPRINTF(buf, bufsize, "(%d)", arraynum);
decl += buf;
hiername += buf;
}
if (bussed) {
sprintf(buf, " [%d:%d]", msb, lsb);
VL_SNPRINTF(buf, bufsize, " [%d:%d]", msb, lsb);
decl += buf;
}
decl += " $end\n";
@ -656,8 +666,8 @@ void VerilatedVcd::emitWData(vluint32_t code, const WData* newvalp, int bits) {
VL_ATTR_ALWINLINE
void VerilatedVcd::emitDouble(vluint32_t code, double newval) {
char* wp = m_writep;
// Buffer can't overflow before sprintf; we sized during declaration
sprintf(wp, "r%.16g", newval);
// Buffer can't overflow before VL_SNPRINTF; we sized during declaration
VL_SNPRINTF(wp, m_wrChunkSize, "r%.16g", newval);
wp += strlen(wp);
finishLine(code, wp);
}
@ -770,8 +780,8 @@ void VerilatedVcd::fullTriArray(vluint32_t code, const vluint32_t* newvalp,
void VerilatedVcd::fullDouble(vluint32_t code, const double newval) {
// cppcheck-suppress invalidPointerCast
(*(reinterpret_cast<double*>(oldp(code)))) = newval;
// Buffer can't overflow before sprintf; we sized during declaration
sprintf(m_writep, "r%.16g", newval);
// Buffer can't overflow before VL_SNPRINTF; we sized during declaration
VL_SNPRINTF(m_writep, m_wrChunkSize, "r%.16g", newval);
m_writep += strlen(m_writep);
*m_writep++ = ' ';
m_writep = writeCode(m_writep, code);
@ -869,6 +879,10 @@ void vcdTestMain(const char* filenamep) {
{
VerilatedVcdC* vcdp = new VerilatedVcdC;
vcdp->evcd(true);
vcdp->set_time_unit("1ms");
vcdp->set_time_unit(std::string("1ms"));
vcdp->set_time_resolution("1ns");
vcdp->set_time_resolution(std::string("1ns"));
vcdp->spTrace()->addInitCb(&vcdInit, 0);
vcdp->spTrace()->addFullCb(&vcdFull, 0);
vcdp->spTrace()->addChgCb(&vcdChange, 0);

View File

@ -17,8 +17,8 @@
//=============================================================================
// SPDIFF_OFF
#ifndef _VERILATED_VCD_C_H_
#define _VERILATED_VCD_C_H_ 1
#ifndef VERILATOR_VERILATED_VCD_C_H_
#define VERILATOR_VERILATED_VCD_C_H_
#include "verilated.h"
#include "verilated_trace.h"
@ -48,8 +48,8 @@ public:
//=============================================================================
// VerilatedVcd
/// Base class to create a Verilator VCD dump
/// This is an internally used class - see VerilatedVcdC for what to call from applications
// Base class to create a Verilator VCD dump
// This is an internally used class - see VerilatedVcdC for what to call from applications
class VerilatedVcd VL_NOT_FINAL : public VerilatedTrace<VerilatedVcd> {
private:
@ -86,9 +86,9 @@ private:
// 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();
}
void openNextImp(bool incFilename);
void closePrev();
void closeErr();
void openNext();
void makeNameMap();
void deleteNameMap();
void printIndent(int level_change);
@ -136,20 +136,20 @@ public:
~VerilatedVcd();
// ACCESSORS
/// Set size in megabytes after which new file should be created
// Set size in megabytes after which new file should be created
void rolloverMB(vluint64_t rolloverMB) { m_rolloverMB = rolloverMB; }
// METHODS
/// Open the file; call isOpen() to see if errors
void open(const char* filename) VL_MT_UNSAFE_ONE;
/// Open next data-only file
void openNext(bool incFilename) VL_MT_UNSAFE_ONE;
/// Close the file
void close() VL_MT_UNSAFE_ONE;
/// Flush any remaining data to this file
void flush() VL_MT_UNSAFE_ONE;
/// Is file open?
bool isOpen() const { return m_isOpen; }
// Open the file; call isOpen() to see if errors
void open(const char* filename) VL_MT_SAFE_EXCLUDES(m_mutex);
// Open next data-only file
void openNext(bool incFilename) VL_MT_SAFE_EXCLUDES(m_mutex);
// Close the file
void close() VL_MT_SAFE_EXCLUDES(m_mutex);
// Flush any remaining data to this file
void flush() VL_MT_SAFE_EXCLUDES(m_mutex);
// Return if file is open
bool isOpen() const VL_MT_SAFE { return m_isOpen; }
//=========================================================================
// Internal interface to Verilator generated code
@ -211,8 +211,8 @@ public:
chgDouble(oldp - this->oldp(0), newval);
}
/// Inside dumping routines, dump one signal, faster when not inlined
/// due to code size reduction.
// Inside dumping routines, dump one signal, faster when not inlined
// due to code size reduction.
void fullBit(vluint32_t code, const vluint32_t newval);
void fullBus(vluint32_t code, const vluint32_t newval, int bits);
void fullQuad(vluint32_t code, const vluint64_t newval, int bits);
@ -225,8 +225,8 @@ public:
int bits);
void fullDouble(vluint32_t code, const double newval);
/// Inside dumping routines, dump one signal if it has changed.
/// We do want to inline these to avoid calls when the value did not change.
// Inside dumping routines, dump one signal if it has changed.
// We do want to inline these to avoid calls when the value did not change.
inline void chgBit(vluint32_t code, const vluint32_t newval) {
vluint32_t diff = oldp(code)[0] ^ newval;
if (VL_UNLIKELY(diff)) fullBit(code, newval);
@ -327,7 +327,6 @@ template <> void VerilatedTrace<VerilatedVcd>::set_time_resolution(const std::st
// VerilatedVcdC
/// Create a VCD dump file in C standalone (no SystemC) simulations.
/// Also derived for use in SystemC simulations.
/// Thread safety: Unless otherwise indicated, every function is VL_MT_UNSAFE_ONE
class VerilatedVcdC VL_NOT_FINAL {
VerilatedVcd m_sptrace; ///< Trace file being created
@ -336,48 +335,56 @@ class VerilatedVcdC VL_NOT_FINAL {
VL_UNCOPYABLE(VerilatedVcdC);
public:
/// Construct the dump. Optional argument is a preconstructed file.
explicit VerilatedVcdC(VerilatedVcdFile* filep = nullptr)
: m_sptrace{filep} {}
/// Destruct, flush, and close the dump
~VerilatedVcdC() { close(); }
/// Routines can only be called from one thread; allow next call from different thread
void changeThread() { spTrace()->changeThread(); }
public:
// ACCESSORS
/// Is file open?
bool isOpen() const { return m_sptrace.isOpen(); }
// METHODS
// METHODS - User called
/// Return if file is open
bool isOpen() const VL_MT_SAFE { return m_sptrace.isOpen(); }
/// Open a new VCD file
/// This includes a complete header dump each time it is called,
/// just as if this object was deleted and reconstructed.
void open(const char* filename) VL_MT_UNSAFE_ONE { m_sptrace.open(filename); }
void open(const char* filename) VL_MT_SAFE { m_sptrace.open(filename); }
/// Continue a VCD dump by rotating to a new file name
/// The header is only in the first file created, this allows
/// "cat" to be used to combine the header plus any number of data files.
void openNext(bool incFilename = true) VL_MT_UNSAFE_ONE { m_sptrace.openNext(incFilename); }
void openNext(bool incFilename = true) VL_MT_SAFE { m_sptrace.openNext(incFilename); }
/// Set size in megabytes after which new file should be created
void rolloverMB(size_t rolloverMB) { m_sptrace.rolloverMB(rolloverMB); }
void rolloverMB(size_t rolloverMB) VL_MT_SAFE { m_sptrace.rolloverMB(rolloverMB); }
/// Close dump
void close() VL_MT_UNSAFE_ONE { m_sptrace.close(); }
void close() VL_MT_SAFE { m_sptrace.close(); }
/// Flush dump
void flush() VL_MT_UNSAFE_ONE { m_sptrace.flush(); }
void flush() VL_MT_SAFE { m_sptrace.flush(); }
/// Write one cycle of dump data
void dump(vluint64_t timeui) { m_sptrace.dump(timeui); }
void dump(vluint64_t timeui) VL_MT_SAFE { m_sptrace.dump(timeui); }
/// Write one cycle of dump data - backward compatible and to reduce
/// conversion warnings. It's better to use a vluint64_t time instead.
void dump(double timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
void dump(vluint32_t timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
void dump(int timestamp) { dump(static_cast<vluint64_t>(timestamp)); }
/// Set time units (s/ms, defaults to ns)
/// For Verilated models, these propage from the Verilated default --timeunit
void set_time_unit(const char* unit) { m_sptrace.set_time_unit(unit); }
void set_time_unit(const std::string& unit) { m_sptrace.set_time_unit(unit); }
/// Set time resolution (s/ms, defaults to ns)
/// For Verilated models, these propage from the Verilated default --timeunit
void set_time_resolution(const char* unit) { m_sptrace.set_time_resolution(unit); }
void set_time_resolution(const std::string& unit) { m_sptrace.set_time_resolution(unit); }
/// Internal class access
// METHODS - Internal/backward compatible
// \protectedsection
// Set time units (s/ms, defaults to ns)
// Users should not need to call this, as for Verilated models, these
// propage from the Verilated default timeunit
void set_time_unit(const char* unit) VL_MT_SAFE { m_sptrace.set_time_unit(unit); }
void set_time_unit(const std::string& unit) VL_MT_SAFE { m_sptrace.set_time_unit(unit); }
// Set time resolution (s/ms, defaults to ns)
// Users should not need to call this, as for Verilated models, these
// propage from the Verilated default timeprecision
void set_time_resolution(const char* unit) VL_MT_SAFE { m_sptrace.set_time_resolution(unit); }
void set_time_resolution(const std::string& unit) VL_MT_SAFE {
m_sptrace.set_time_resolution(unit);
}
// Internal class access
inline VerilatedVcd* spTrace() { return &m_sptrace; }
#ifdef VL_TRACE_VCD_OLD_API
@ -385,7 +392,8 @@ public:
// Note: These are only for testing for backward compatibility with foreign
// code and is not used by Verilator. Do not use these as there is no
// guarantee of functionality.
/// Use evcd format
// Use evcd format
void evcd(bool flag) VL_MT_UNSAFE_ONE { m_sptrace.evcd(flag); }
#endif
};

View File

@ -15,12 +15,10 @@
/// \brief Verilator tracing in VCD Format
///
//=============================================================================
// SPDIFF_OFF
#include "verilatedos.h"
#include "verilated_vcd_sc.h"
// SPDIFF_ON
//======================================================================
//======================================================================

View File

@ -15,27 +15,26 @@
/// This class is not threadsafe, as the SystemC kernel is not threadsafe.
///
//=============================================================================
// SPDIFF_OFF
#ifndef _VERILATED_VCD_SC_H_
#define _VERILATED_VCD_SC_H_ 1
#ifndef VERILATOR_VERILATED_VCD_SC_H_
#define VERILATOR_VERILATED_VCD_SC_H_
#include "verilatedos.h"
#include "verilated_sc.h"
#include "verilated_vcd_c.h"
// SPDIFF_ON
//=============================================================================
// VerilatedVcdSc
///
/// This class is passed to the SystemC simulation kernel, just like a
/// documented SystemC trace format.
/// This class creates a Verilator-friendly VCD trace format with the
/// SystemC simulation kernel, just like a SystemC-documented trace format.
class VerilatedVcdSc final : sc_trace_file, public VerilatedVcdC {
// CONSTRUCTORS
VL_UNCOPYABLE(VerilatedVcdSc);
public:
/// Construct a SC trace object, and register with the SystemC kernel
VerilatedVcdSc() {
sc_get_curr_simcontext()->add_trace_file(this);
// We want to avoid a depreciated warning, but still be back compatible.
@ -48,16 +47,17 @@ public:
}
spTrace()->set_time_resolution(sc_get_time_resolution().to_string());
}
/// Destruct, flush, and close the dump
virtual ~VerilatedVcdSc() { close(); }
// METHODS
/// Called by SystemC simulate()
// METHODS - for SC kernel
// Called by SystemC simulate()
virtual void cycle(bool delta_cycle) {
if (!delta_cycle) this->dump(sc_time_stamp().to_double());
}
private:
/// Fake outs for linker
// METHODS - Fake outs for linker
#ifdef NC_SYSTEMC
// Cadence Incisive has these as abstract functions so we must create them

View File

@ -21,7 +21,7 @@
///
//=========================================================================
#define _VERILATED_VPI_CPP_
#define VERILATOR_VERILATED_VPI_CPP_
#include "verilated.h"
#include "verilated_vpi.h"
@ -35,21 +35,21 @@
// Internal constants
#define VL_DEBUG_IF_PLI VL_DEBUG_IF
constexpr unsigned VL_VPI_LINE_SIZE = 8192;
constexpr unsigned VL_VPI_LINE_SIZE_ = 8192;
//======================================================================
// Internal macros
#define _VL_VPI_INTERNAL VerilatedVpiImp::error_info()->setMessage(vpiInternal)->setMessage
#define _VL_VPI_SYSTEM VerilatedVpiImp::error_info()->setMessage(vpiSystem)->setMessage
#define _VL_VPI_ERROR VerilatedVpiImp::error_info()->setMessage(vpiError)->setMessage
#define _VL_VPI_WARNING VerilatedVpiImp::error_info()->setMessage(vpiWarning)->setMessage
#define _VL_VPI_NOTICE VerilatedVpiImp::error_info()->setMessage(vpiNotice)->setMessage
#define _VL_VPI_ERROR_RESET VerilatedVpiImp::error_info()->resetError
#define VL_VPI_INTERNAL_ VerilatedVpiImp::error_info()->setMessage(vpiInternal)->setMessage
#define VL_VPI_SYSTEM_ VerilatedVpiImp::error_info()->setMessage(vpiSystem)->setMessage
#define VL_VPI_ERROR_ VerilatedVpiImp::error_info()->setMessage(vpiError)->setMessage
#define VL_VPI_WARNING_ VerilatedVpiImp::error_info()->setMessage(vpiWarning)->setMessage
#define VL_VPI_NOTICE_ VerilatedVpiImp::error_info()->setMessage(vpiNotice)->setMessage
#define VL_VPI_ERROR_RESET_ VerilatedVpiImp::error_info()->resetError
// Not supported yet
#define _VL_VPI_UNIMP() \
(_VL_VPI_ERROR(__FILE__, __LINE__, Verilated::catName("Unsupported VPI function: ", VL_FUNC)))
#define VL_VPI_UNIMP_() \
(VL_VPI_ERROR_(__FILE__, __LINE__, Verilated::catName("Unsupported VPI function: ", VL_FUNC)))
//======================================================================
// Implementation
@ -62,6 +62,7 @@ class VerilatedVpio VL_NOT_FINAL {
static constexpr vluint32_t activeMagic() { return 0xfeed100f; }
// MEM MANGLEMENT
// Internal note: Globals may multi-construct, see verilated.cpp top.
static VL_THREAD_LOCAL vluint8_t* t_freeHead;
public:
@ -335,8 +336,8 @@ public:
virtual const VerilatedRange* rangep() const override { return &(varp()->packed()); }
virtual const char* fullname() const override {
static VL_THREAD_LOCAL std::string t_out;
char num[20];
sprintf(num, "%d", m_index);
char num[25];
VL_SNPRINTF(num, 25, "%d", m_index);
t_out = std::string(scopep()->name()) + "." + name() + "[" + num + "]";
return t_out.c_str();
}
@ -504,17 +505,21 @@ class VerilatedVpiImp final {
typedef std::list<VerilatedVpiCbHolder> VpioCbList;
typedef std::map<std::pair<QData, vluint64_t>, VerilatedVpiCbHolder> VpioTimedCbs;
// All only medium-speed, so use singleton function
VpioCbList m_cbObjLists[CB_ENUM_MAX_VALUE]; // Callbacks for each supported reason
VpioTimedCbs m_timedCbs; // Time based callbacks
VerilatedVpiError* m_errorInfop = nullptr; // Container for vpi error info
VerilatedAssertOneThread m_assertOne; ///< Assert only called from single thread
vluint64_t m_nextCallbackId = 1; // Id to identify callback
static VerilatedVpiImp s_s; // Singleton
static VerilatedVpiImp& s() { // Singleton
static VerilatedVpiImp s_s;
return s_s;
}
public:
static void assertOneCheck() { s_s.m_assertOne.check(); }
static vluint64_t nextCallbackId() { return ++s_s.m_nextCallbackId; }
static void assertOneCheck() { s().m_assertOne.check(); }
static vluint64_t nextCallbackId() { return ++s().m_nextCallbackId; }
static void cbReasonAdd(vluint64_t id, const s_cb_data* cb_data_p) {
// The passed cb_data_p was property of the user, so need to recreate
@ -525,20 +530,20 @@ public:
cb_data_p->reason, id, cb_data_p->obj););
VerilatedVpioVar* varop = nullptr;
if (cb_data_p->reason == cbValueChange) varop = VerilatedVpioVar::castp(cb_data_p->obj);
s_s.m_cbObjLists[cb_data_p->reason].emplace_back(id, cb_data_p, varop);
s().m_cbObjLists[cb_data_p->reason].emplace_back(id, cb_data_p, varop);
}
static void cbTimedAdd(vluint64_t id, const s_cb_data* cb_data_p, QData time) {
// The passed cb_data_p was property of the user, so need to recreate
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_register_cb reason=%d id=%" VL_PRI64
"d delay=%" VL_PRI64 "u\n",
cb_data_p->reason, id, time););
s_s.m_timedCbs.emplace(std::piecewise_construct,
s().m_timedCbs.emplace(std::piecewise_construct,
std::forward_as_tuple(std::make_pair(time, id)),
std::forward_as_tuple(id, cb_data_p, nullptr));
}
static void cbReasonRemove(vluint64_t id, vluint32_t reason) {
// Id might no longer exist, if already removed due to call after event, or teardown
VpioCbList& cbObjList = s_s.m_cbObjLists[reason];
VpioCbList& cbObjList = s().m_cbObjLists[reason];
// We do not remove it now as we may be iterating the list,
// instead set to nullptr and will cleanup later
for (auto& ir : cbObjList) {
@ -547,13 +552,13 @@ public:
}
static void cbTimedRemove(vluint64_t id, QData time) {
// Id might no longer exist, if already removed due to call after event, or teardown
const auto it = s_s.m_timedCbs.find(std::make_pair(time, id));
if (VL_LIKELY(it != s_s.m_timedCbs.end())) it->second.invalidate();
const auto it = s().m_timedCbs.find(std::make_pair(time, id));
if (VL_LIKELY(it != s().m_timedCbs.end())) it->second.invalidate();
}
static void callTimedCbs() VL_MT_UNSAFE_ONE {
assertOneCheck();
QData time = VL_TIME_Q();
for (auto it = s_s.m_timedCbs.begin(); it != s_s.m_timedCbs.end();) {
for (auto it = s().m_timedCbs.begin(); it != s().m_timedCbs.end();) {
if (VL_UNLIKELY(it->first.first <= time)) {
VerilatedVpiCbHolder& ho = it->second;
const auto last_it = it;
@ -564,19 +569,19 @@ public:
ho.invalidate(); // Timed callbacks are one-shot
(ho.cb_rtnp())(ho.cb_datap());
}
s_s.m_timedCbs.erase(last_it);
s().m_timedCbs.erase(last_it);
} else {
++it;
}
}
}
static QData cbNextDeadline() {
const auto it = s_s.m_timedCbs.cbegin();
if (VL_LIKELY(it != s_s.m_timedCbs.cend())) return it->first.first;
const auto it = s().m_timedCbs.cbegin();
if (VL_LIKELY(it != s().m_timedCbs.cend())) return it->first.first;
return ~0ULL; // maxquad
}
static bool callCbs(vluint32_t reason) VL_MT_UNSAFE_ONE {
VpioCbList& cbObjList = s_s.m_cbObjLists[reason];
VpioCbList& cbObjList = s().m_cbObjLists[reason];
bool called = false;
if (cbObjList.empty()) return called;
const auto last = std::prev(cbObjList.end()); // prevent looping over newly added elements
@ -600,7 +605,7 @@ public:
}
static bool callValueCbs() VL_MT_UNSAFE_ONE {
assertOneCheck();
VpioCbList& cbObjList = s_s.m_cbObjLists[cbValueChange];
VpioCbList& cbObjList = s().m_cbObjLists[cbValueChange];
bool called = false;
typedef std::unordered_set<VerilatedVpioVar*> VpioVarSet;
VpioVarSet update; // set of objects to update after callbacks
@ -640,12 +645,20 @@ public:
static VerilatedVpiError* error_info() VL_MT_UNSAFE_ONE; // getter for vpi error info
};
class VerilatedVpiError final {
//// Container for vpi error info
//======================================================================
// Statics
// Internal note: Globals may multi-construct, see verilated.cpp top.
VL_THREAD_LOCAL vluint8_t* VerilatedVpio::t_freeHead = nullptr;
//======================================================================
// VerilatedVpiError
/// Internal container for vpi error info
class VerilatedVpiError final {
t_vpi_error_info m_errorInfo;
bool m_flag = false;
char m_buff[VL_VPI_LINE_SIZE];
char m_buff[VL_VPI_LINE_SIZE_];
void setError(PLI_BYTE8* message, PLI_BYTE8* code, PLI_BYTE8* file, PLI_INT32 line) {
m_errorInfo.message = message;
m_errorInfo.file = file;
@ -654,7 +667,7 @@ class VerilatedVpiError final {
do_callbacks();
}
void do_callbacks() {
if (getError()->level >= vpiError && Verilated::fatalOnVpiError()) {
if (getError()->level >= vpiError && Verilated::threadContextp()->fatalOnVpiError()) {
// Stop on vpi error/unsupported
vpi_unsupported();
}
@ -708,11 +721,6 @@ public:
static const char* strFromVpiProp(PLI_INT32 vpiVal) VL_MT_SAFE;
};
//======================================================================
VerilatedVpiImp VerilatedVpiImp::s_s; // Singleton
VL_THREAD_LOCAL vluint8_t* VerilatedVpio::t_freeHead = nullptr;
//======================================================================
// VerilatedVpi implementation
@ -742,8 +750,8 @@ PLI_INT32 VerilatedVpioReasonCb::dovpi_remove_cb() {
VerilatedVpiError* VerilatedVpiImp::error_info() VL_MT_UNSAFE_ONE {
VerilatedVpiImp::assertOneCheck();
if (VL_UNLIKELY(!s_s.m_errorInfop)) s_s.m_errorInfop = new VerilatedVpiError();
return s_s.m_errorInfop;
if (VL_UNLIKELY(!s().m_errorInfop)) s().m_errorInfop = new VerilatedVpiError();
return s().m_errorInfop;
}
//======================================================================
@ -1143,16 +1151,16 @@ vpiHandle vpi_register_cb(p_cb_data cb_data_p) {
// Don't confuse with the callback-activated t_cb_data object handle
// which is the object causing the callback rather than the callback itself
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
// cppcheck-suppress nullPointer
if (VL_UNLIKELY(!cb_data_p)) {
_VL_VPI_WARNING(__FILE__, __LINE__, "%s : callback data pointer is null", VL_FUNC);
VL_VPI_WARNING_(__FILE__, __LINE__, "%s : callback data pointer is null", VL_FUNC);
return nullptr;
}
switch (cb_data_p->reason) {
case cbAfterDelay: {
QData time = 0;
if (cb_data_p->time) time = _VL_SET_QII(cb_data_p->time->high, cb_data_p->time->low);
if (cb_data_p->time) time = VL_SET_QII(cb_data_p->time->high, cb_data_p->time->low);
QData abstime = VL_TIME_Q() + time;
vluint64_t id = VerilatedVpiImp::nextCallbackId();
VerilatedVpioTimedCb* vop = new VerilatedVpioTimedCb{id, abstime};
@ -1175,7 +1183,7 @@ vpiHandle vpi_register_cb(p_cb_data cb_data_p) {
return vop->castVpiHandle();
}
default:
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported callback type %s", VL_FUNC,
VL_VPI_WARNING_(__FILE__, __LINE__, "%s: Unsupported callback type %s", VL_FUNC,
VerilatedVpiError::strFromVpiCallbackReason(cb_data_p->reason));
return nullptr;
}
@ -1184,26 +1192,26 @@ vpiHandle vpi_register_cb(p_cb_data cb_data_p) {
PLI_INT32 vpi_remove_cb(vpiHandle cb_obj) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_remove_cb %p\n", cb_obj););
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
VerilatedVpio* vop = VerilatedVpio::castp(cb_obj);
if (VL_UNLIKELY(!vop)) return 0;
return vop->dovpi_remove_cb();
}
void vpi_get_cb_info(vpiHandle /*object*/, p_cb_data /*cb_data_p*/) { _VL_VPI_UNIMP(); }
void vpi_get_cb_info(vpiHandle /*object*/, p_cb_data /*cb_data_p*/) { VL_VPI_UNIMP_(); }
vpiHandle vpi_register_systf(p_vpi_systf_data /*systf_data_p*/) {
_VL_VPI_UNIMP();
VL_VPI_UNIMP_();
return nullptr;
}
void vpi_get_systf_info(vpiHandle /*object*/, p_vpi_systf_data /*systf_data_p*/) {
_VL_VPI_UNIMP();
VL_VPI_UNIMP_();
}
// for obtaining handles
vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
if (VL_UNLIKELY(!namep)) return nullptr;
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_handle_by_name %s %p\n", namep, scope););
const VerilatedVar* varp = nullptr;
@ -1216,7 +1224,7 @@ vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
}
{
// This doesn't yet follow the hierarchy in the proper way
scopep = Verilated::scopeFind(namep);
scopep = Verilated::threadContextp()->scopeFind(namep);
if (scopep) { // Whole thing found as a scope
if (scopep->type() == VerilatedScope::SCOPE_MODULE) {
return (new VerilatedVpioModule(scopep))->castVpiHandle();
@ -1234,11 +1242,11 @@ vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
if (scopename.find('.') == std::string::npos) {
// This is a toplevel, hence search in our TOP ports first.
scopep = Verilated::scopeFind("TOP");
scopep = Verilated::threadContextp()->scopeFind("TOP");
if (scopep) varp = scopep->varFind(baseNamep);
}
if (!varp) {
scopep = Verilated::scopeFind(scopename.c_str());
scopep = Verilated::threadContextp()->scopeFind(scopename.c_str());
if (!scopep) return nullptr;
varp = scopep->varFind(baseNamep);
}
@ -1256,7 +1264,7 @@ vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) {
// Used to get array entries
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_handle_by_index %p %d\n", object, indx););
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
// Memory words are not indexable
VerilatedVpioMemoryWord* vop = VerilatedVpioMemoryWord::castp(object);
if (VL_UNLIKELY(vop)) return nullptr;
@ -1278,7 +1286,7 @@ vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) {
indx - varop->varp()->unpacked().left()))
->castVpiHandle();
}
_VL_VPI_INTERNAL(__FILE__, __LINE__, "%s : can't resolve handle", VL_FUNC);
VL_VPI_INTERNAL_(__FILE__, __LINE__, "%s : can't resolve handle", VL_FUNC);
return nullptr;
}
@ -1287,7 +1295,7 @@ vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) {
vpiHandle vpi_handle(PLI_INT32 type, vpiHandle object) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_handle %d %p\n", type, object););
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
switch (type) {
case vpiLeftRange: {
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
@ -1297,7 +1305,7 @@ vpiHandle vpi_handle(PLI_INT32 type, vpiHandle object) {
if (VL_UNLIKELY(!vop->rangep())) return nullptr;
return (new VerilatedVpioConst(vop->rangep()->left()))->castVpiHandle();
}
_VL_VPI_WARNING(__FILE__, __LINE__,
VL_VPI_WARNING_(__FILE__, __LINE__,
"%s: Unsupported vpiHandle (%p) for type %s, nothing will be returned",
VL_FUNC, object, VerilatedVpiError::strFromVpiMethod(type));
return nullptr;
@ -1310,7 +1318,7 @@ vpiHandle vpi_handle(PLI_INT32 type, vpiHandle object) {
if (VL_UNLIKELY(!vop->rangep())) return nullptr;
return (new VerilatedVpioConst(vop->rangep()->right()))->castVpiHandle();
}
_VL_VPI_WARNING(__FILE__, __LINE__,
VL_VPI_WARNING_(__FILE__, __LINE__,
"%s: Unsupported vpiHandle (%p) for type %s, nothing will be returned",
VL_FUNC, object, VerilatedVpiError::strFromVpiMethod(type));
return nullptr;
@ -1331,7 +1339,7 @@ vpiHandle vpi_handle(PLI_INT32 type, vpiHandle object) {
return (new VerilatedVpioVar(vop->varp(), vop->scopep()))->castVpiHandle();
}
default:
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned",
VL_VPI_WARNING_(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned",
VL_FUNC, VerilatedVpiError::strFromVpiMethod(type));
return nullptr;
}
@ -1339,21 +1347,21 @@ vpiHandle vpi_handle(PLI_INT32 type, vpiHandle object) {
vpiHandle vpi_handle_multi(PLI_INT32 /*type*/, vpiHandle /*refHandle1*/, vpiHandle /*refHandle2*/,
...) {
_VL_VPI_UNIMP();
VL_VPI_UNIMP_();
return nullptr;
}
vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_iterate %d %p\n", type, object););
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
switch (type) {
case vpiMemoryWord: {
VerilatedVpioVar* vop = VerilatedVpioVar::castp(object);
if (VL_UNLIKELY(!vop)) return nullptr;
if (vop->varp()->dims() < 2) return nullptr;
if (vop->varp()->dims() > 2) {
_VL_VPI_WARNING(__FILE__, __LINE__,
VL_VPI_WARNING_(__FILE__, __LINE__,
"%s: %s, object %s has unsupported number of indices (%d)", VL_FUNC,
VerilatedVpiError::strFromVpiMethod(type), vop->fullname(),
vop->varp()->dims());
@ -1366,7 +1374,7 @@ vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
if (vop->varp()->dims() < 2) return nullptr;
// Unsupported is multidim list
if (vop->varp()->dims() > 2) {
_VL_VPI_WARNING(__FILE__, __LINE__,
VL_VPI_WARNING_(__FILE__, __LINE__,
"%s: %s, object %s has unsupported number of indices (%d)", VL_FUNC,
VerilatedVpiError::strFromVpiMethod(type), vop->fullname(),
vop->varp()->dims());
@ -1387,7 +1395,7 @@ vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
return ((new VerilatedVpioModuleIter(it->second))->castVpiHandle());
}
default:
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned",
VL_VPI_WARNING_(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned",
VL_FUNC, VerilatedVpiError::strFromVpiObjType(type));
return nullptr;
}
@ -1395,7 +1403,7 @@ vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) {
vpiHandle vpi_scan(vpiHandle object) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_scan %p\n", object););
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
VerilatedVpio* vop = VerilatedVpio::castp(object);
if (VL_UNLIKELY(!vop)) return nullptr;
return vop->dovpi_scan();
@ -1407,14 +1415,15 @@ PLI_INT32 vpi_get(PLI_INT32 property, vpiHandle object) {
// Leave this in the header file - in many cases the compiler can constant propagate "object"
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_get %d %p\n", property, object););
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
switch (property) {
case vpiTimePrecision: {
return Verilated::timeprecision();
return Verilated::threadContextp()->timeprecision();
}
case vpiTimeUnit: {
VerilatedVpioScope* vop = VerilatedVpioScope::castp(object);
if (!vop) return Verilated::timeunit(); // Null asks for global, not unlikely
if (!vop)
return Verilated::threadContextp()->timeunit(); // Null asks for global, not unlikely
return vop->scopep()->timeunit();
}
case vpiType: {
@ -1440,14 +1449,14 @@ PLI_INT32 vpi_get(PLI_INT32 property, vpiHandle object) {
return vop->size();
}
default:
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned",
VL_VPI_WARNING_(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned",
VL_FUNC, VerilatedVpiError::strFromVpiProp(property));
return 0;
}
}
PLI_INT64 vpi_get64(PLI_INT32 /*property*/, vpiHandle /*object*/) {
_VL_VPI_UNIMP();
VL_VPI_UNIMP_();
return 0;
}
@ -1455,7 +1464,7 @@ PLI_BYTE8* vpi_get_str(PLI_INT32 property, vpiHandle object) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_get_str %d %p\n", property, object););
VerilatedVpiImp::assertOneCheck();
VerilatedVpio* vop = VerilatedVpio::castp(object);
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
if (VL_UNLIKELY(!vop)) return nullptr;
switch (property) {
case vpiName: {
@ -1471,7 +1480,7 @@ PLI_BYTE8* vpi_get_str(PLI_INT32 property, vpiHandle object) {
return const_cast<PLI_BYTE8*>(VerilatedVpiError::strFromVpiObjType(vop->type()));
}
default:
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned",
VL_VPI_WARNING_(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned",
VL_FUNC, VerilatedVpiError::strFromVpiProp(property));
return nullptr;
}
@ -1479,8 +1488,8 @@ PLI_BYTE8* vpi_get_str(PLI_INT32 property, vpiHandle object) {
// delay processing
void vpi_get_delays(vpiHandle /*object*/, p_vpi_delay /*delay_p*/) { _VL_VPI_UNIMP(); }
void vpi_put_delays(vpiHandle /*object*/, p_vpi_delay /*delay_p*/) { _VL_VPI_UNIMP(); }
void vpi_get_delays(vpiHandle /*object*/, p_vpi_delay /*delay_p*/) { VL_VPI_UNIMP_(); }
void vpi_put_delays(vpiHandle /*object*/, p_vpi_delay /*delay_p*/) { VL_VPI_UNIMP_(); }
// value processing
bool vl_check_format(const VerilatedVar* varp, const p_vpi_value valuep, const char* fullname,
@ -1532,7 +1541,7 @@ bool vl_check_format(const VerilatedVar* varp, const p_vpi_value valuep, const c
} else {
status = false;
}
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", VL_FUNC,
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", VL_FUNC,
VerilatedVpiError::strFromVpiVal(valuep->format), fullname);
return status;
}
@ -1592,7 +1601,7 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
if (bits > t_outStrSz) {
// limit maximum size of output to size of buffer to prevent overrun.
bits = t_outStrSz;
_VL_VPI_WARNING(
VL_VPI_WARNING_(
__FILE__, __LINE__,
"%s: Truncating string value of %s for %s"
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
@ -1613,7 +1622,7 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
int i;
if (chars > t_outStrSz) {
// limit maximum size of output to size of buffer to prevent overrun.
_VL_VPI_WARNING(
VL_VPI_WARNING_(
__FILE__, __LINE__,
"%s: Truncating string value of %s for %s"
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
@ -1671,7 +1680,7 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
int i;
if (chars > t_outStrSz) {
// limit maximum size of output to size of buffer to prevent overrun.
_VL_VPI_WARNING(
VL_VPI_WARNING_(
__FILE__, __LINE__,
"%s: Truncating string value of %s for %s"
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
@ -1705,7 +1714,7 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
int i;
if (bytes > t_outStrSz) {
// limit maximum size of output to size of buffer to prevent overrun.
_VL_VPI_WARNING(
VL_VPI_WARNING_(
__FILE__, __LINE__,
"%s: Truncating string value of %s for %s"
" as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)",
@ -1735,14 +1744,14 @@ void vl_get_value(const VerilatedVar* varp, void* varDatap, p_vpi_value valuep,
} else if (valuep->format == vpiSuppressVal) {
return;
}
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s", VL_FUNC,
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s", VL_FUNC,
VerilatedVpiError::strFromVpiVal(valuep->format), fullname);
}
void vpi_get_value(vpiHandle object, p_vpi_value valuep) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_get_value %p\n", object););
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
if (VL_UNLIKELY(!valuep)) return;
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
@ -1756,20 +1765,20 @@ void vpi_get_value(vpiHandle object, p_vpi_value valuep) {
valuep->value.integer = vop->num();
return;
}
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", VL_FUNC,
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", VL_FUNC,
VerilatedVpiError::strFromVpiVal(valuep->format), vop->fullname());
return;
}
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported vpiHandle (%p)", VL_FUNC, object);
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported vpiHandle (%p)", VL_FUNC, object);
}
vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_p*/,
PLI_INT32 /*flags*/) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_put_value %p %p\n", object, valuep););
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
if (VL_UNLIKELY(!valuep)) {
_VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_put_value with nullptr value pointer");
VL_VPI_WARNING_(__FILE__, __LINE__, "Ignoring vpi_put_value with nullptr value pointer");
return nullptr;
}
if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) {
@ -1779,7 +1788,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
VL_DBG_MSGF("- vpi: varp=%p putatp=%p\n", vop->varp()->datap(), vop->varDatap()););
if (VL_UNLIKELY(!vop->varp()->isPublicRW())) {
_VL_VPI_WARNING(__FILE__, __LINE__,
VL_VPI_WARNING_(__FILE__, __LINE__,
"Ignoring vpi_put_value to signal marked read-only,"
" use public_flat_rw instead: %s",
vop->fullname());
@ -1801,7 +1810,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
= valuep->value.vector[0].aval & vop->mask();
return object;
} else if (vop->varp()->vltype() == VLVT_UINT64) {
*(reinterpret_cast<QData*>(vop->varDatap())) = _VL_SET_QII(
*(reinterpret_cast<QData*>(vop->varDatap())) = VL_SET_QII(
valuep->value.vector[1].aval & vop->mask(), valuep->value.vector[0].aval);
return object;
} else if (vop->varp()->vltype() == VLVT_WDATA) {
@ -1847,7 +1856,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
if (digit >= '0' && digit <= '7') {
val.half = digit - '0';
} else {
_VL_VPI_WARNING(__FILE__, __LINE__,
VL_VPI_WARNING_(__FILE__, __LINE__,
"%s: Non octal character '%c' in '%s' as value %s for %s",
VL_FUNC, digit, valuep->value.str,
VerilatedVpiError::strFromVpiVal(valuep->format),
@ -1883,13 +1892,13 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
unsigned long long val;
int success = sscanf(valuep->value.str, "%30llu%15s", &val, remainder);
if (success < 1) {
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Parsing failed for '%s' as value %s for %s",
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Parsing failed for '%s' as value %s for %s",
VL_FUNC, valuep->value.str,
VerilatedVpiError::strFromVpiVal(valuep->format), vop->fullname());
return nullptr;
}
if (success > 1) {
_VL_VPI_WARNING(__FILE__, __LINE__,
VL_VPI_WARNING_(__FILE__, __LINE__,
"%s: Trailing garbage '%s' in '%s' as value %s for %s", VL_FUNC,
remainder, valuep->value.str,
VerilatedVpiError::strFromVpiVal(valuep->format), vop->fullname());
@ -1927,7 +1936,7 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
} else if (digit >= 'A' && digit <= 'F') {
hex = digit - 'A' + 10;
} else {
_VL_VPI_WARNING(__FILE__, __LINE__,
VL_VPI_WARNING_(__FILE__, __LINE__,
"%s: Non hex character '%c' in '%s' as value %s for %s",
VL_FUNC, digit, valuep->value.str,
VerilatedVpiError::strFromVpiVal(valuep->format),
@ -1969,39 +1978,39 @@ vpiHandle vpi_put_value(vpiHandle object, p_vpi_value valuep, p_vpi_time /*time_
return object;
}
}
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s",
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s",
VL_FUNC, VerilatedVpiError::strFromVpiVal(valuep->format), vop->fullname());
return nullptr;
} else if (VerilatedVpioParam* vop = VerilatedVpioParam::castp(object)) {
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Ignoring vpi_put_value to vpiParameter: %s",
VL_VPI_WARNING_(__FILE__, __LINE__, "%s: Ignoring vpi_put_value to vpiParameter: %s",
VL_FUNC, vop->fullname());
return nullptr;
} else if (VerilatedVpioConst* vop = VerilatedVpioConst::castp(object)) {
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Ignoring vpi_put_value to vpiConstant: %s",
VL_VPI_WARNING_(__FILE__, __LINE__, "%s: Ignoring vpi_put_value to vpiConstant: %s",
VL_FUNC, vop->fullname());
return nullptr;
}
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported vpiHandle (%p)", VL_FUNC, object);
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported vpiHandle (%p)", VL_FUNC, object);
return nullptr;
}
void vpi_get_value_array(vpiHandle /*object*/, p_vpi_arrayvalue /*arrayvalue_p*/,
PLI_INT32* /*index_p*/, PLI_UINT32 /*num*/) {
_VL_VPI_UNIMP();
VL_VPI_UNIMP_();
}
void vpi_put_value_array(vpiHandle /*object*/, p_vpi_arrayvalue /*arrayvalue_p*/,
PLI_INT32* /*index_p*/, PLI_UINT32 /*num*/) {
_VL_VPI_UNIMP();
VL_VPI_UNIMP_();
}
// time processing
void vpi_get_time(vpiHandle object, p_vpi_time time_p) {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
// cppcheck-suppress nullPointer
if (VL_UNLIKELY(!time_p)) {
_VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_get_time with nullptr value pointer");
VL_VPI_WARNING_(__FILE__, __LINE__, "Ignoring vpi_get_time with nullptr value pointer");
return;
}
if (time_p->type == vpiSimTime) {
@ -2014,39 +2023,40 @@ void vpi_get_time(vpiHandle object, p_vpi_time time_p) {
} else if (time_p->type == vpiScaledRealTime) {
double dtime = VL_TIME_D();
if (VerilatedVpioScope* vop = VerilatedVpioScope::castp(object)) {
int scalePow10 = Verilated::timeprecision() - vop->scopep()->timeunit();
int scalePow10
= Verilated::threadContextp()->timeprecision() - vop->scopep()->timeunit();
double scale = vl_time_multiplier(scalePow10); // e.g. 0.0001
dtime *= scale;
}
time_p->real = dtime;
return;
}
_VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported type (%d)", VL_FUNC, time_p->type);
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported type (%d)", VL_FUNC, time_p->type);
}
// I/O routines
PLI_UINT32 vpi_mcd_open(PLI_BYTE8* filenamep) {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
return VL_FOPEN_NN(filenamep, "wb");
}
PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
VL_FCLOSE_I(mcd);
return 0;
}
PLI_BYTE8* vpi_mcd_name(PLI_UINT32 /*mcd*/) {
_VL_VPI_UNIMP();
VL_VPI_UNIMP_();
return nullptr;
}
PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8* formatp, ...) {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
va_list ap;
va_start(ap, formatp);
int chars = vpi_mcd_vprintf(mcd, formatp, ap);
@ -2056,7 +2066,7 @@ PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8* formatp, ...) {
PLI_INT32 vpi_printf(PLI_BYTE8* formatp, ...) {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
va_list ap;
va_start(ap, formatp);
int chars = vpi_vprintf(formatp, ap);
@ -2066,14 +2076,14 @@ PLI_INT32 vpi_printf(PLI_BYTE8* formatp, ...) {
PLI_INT32 vpi_vprintf(PLI_BYTE8* formatp, va_list ap) {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
return VL_VPRINTF(formatp, ap);
}
PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8* format, va_list ap) {
VerilatedVpiImp::assertOneCheck();
FILE* fp = VL_CVT_I_FP(mcd);
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
// cppcheck-suppress nullPointer
if (VL_UNLIKELY(!fp)) return 0;
int chars = vfprintf(fp, format, ap);
@ -2082,7 +2092,7 @@ PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8* format, va_list ap) {
PLI_INT32 vpi_flush(void) {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
Verilated::runFlushCallbacks();
return 0;
}
@ -2090,7 +2100,7 @@ PLI_INT32 vpi_flush(void) {
PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) {
VerilatedVpiImp::assertOneCheck();
FILE* fp = VL_CVT_I_FP(mcd);
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
if (VL_UNLIKELY(!fp)) return 1;
fflush(fp);
return 0;
@ -2099,7 +2109,7 @@ PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) {
// utility routines
PLI_INT32 vpi_compare_objects(vpiHandle /*object1*/, vpiHandle /*object2*/) {
_VL_VPI_UNIMP();
VL_VPI_UNIMP_();
return 0;
}
PLI_INT32 vpi_chk_error(p_vpi_error_info error_info_p) {
@ -2123,7 +2133,7 @@ PLI_INT32 vpi_release_handle(vpiHandle object) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_release_handle %p\n", object););
VerilatedVpiImp::assertOneCheck();
VerilatedVpio* vop = VerilatedVpio::castp(object);
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
if (VL_UNLIKELY(!vop)) return 0;
VL_DO_DANGLING(delete vop, vop);
return 1;
@ -2131,9 +2141,10 @@ PLI_INT32 vpi_release_handle(vpiHandle object) {
PLI_INT32 vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p) VL_MT_SAFE {
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
vlog_info_p->argc = Verilated::getCommandArgs()->argc;
vlog_info_p->argv = const_cast<PLI_BYTE8**>(Verilated::getCommandArgs()->argv);
VL_VPI_ERROR_RESET_();
auto argc_argv = Verilated::threadContextp()->impp()->argc_argv();
vlog_info_p->argc = argc_argv.first;
vlog_info_p->argv = argc_argv.second;
vlog_info_p->product = const_cast<PLI_BYTE8*>(Verilated::productName());
vlog_info_p->version = const_cast<PLI_BYTE8*>(Verilated::productVersion());
return 1;
@ -2142,26 +2153,26 @@ PLI_INT32 vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p) VL_MT_SAFE {
// routines added with 1364-2001
PLI_INT32 vpi_get_data(PLI_INT32 /*id*/, PLI_BYTE8* /*dataLoc*/, PLI_INT32 /*numOfBytes*/) {
_VL_VPI_UNIMP();
VL_VPI_UNIMP_();
return 0;
}
PLI_INT32 vpi_put_data(PLI_INT32 /*id*/, PLI_BYTE8* /*dataLoc*/, PLI_INT32 /*numOfBytes*/) {
_VL_VPI_UNIMP();
VL_VPI_UNIMP_();
return 0;
}
void* vpi_get_userdata(vpiHandle /*obj*/) {
_VL_VPI_UNIMP();
VL_VPI_UNIMP_();
return nullptr;
}
PLI_INT32 vpi_put_userdata(vpiHandle /*obj*/, void* /*userdata*/) {
_VL_VPI_UNIMP();
VL_VPI_UNIMP_();
return 0;
}
PLI_INT32 vpi_control(PLI_INT32 operation, ...) {
VL_DEBUG_IF_PLI(VL_DBG_MSGF("- vpi: vpi_control %d\n", operation););
VerilatedVpiImp::assertOneCheck();
_VL_VPI_ERROR_RESET();
VL_VPI_ERROR_RESET_();
switch (operation) {
case vpiFinish: {
VL_FINISH_MT("", 0, "*VPI*");
@ -2172,7 +2183,7 @@ PLI_INT32 vpi_control(PLI_INT32 operation, ...) {
return 1; // LCOV_EXCL_LINE
}
default: {
_VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, ignoring", VL_FUNC,
VL_VPI_WARNING_(__FILE__, __LINE__, "%s: Unsupported type %s, ignoring", VL_FUNC,
VerilatedVpiError::strFromVpiProp(operation));
return 0;
}
@ -2181,6 +2192,6 @@ PLI_INT32 vpi_control(PLI_INT32 operation, ...) {
vpiHandle vpi_handle_by_multi_index(vpiHandle /*obj*/, PLI_INT32 /*num_index*/,
PLI_INT32* /*index_array*/) {
_VL_VPI_UNIMP();
VL_VPI_UNIMP_();
return nullptr;
}

View File

@ -19,8 +19,8 @@
///
//=========================================================================
#ifndef _VERILATED_VPI_H_
#define _VERILATED_VPI_H_ 1 ///< Header Guard
#ifndef VERILATOR_VERILATED_VPI_H_
#define VERILATOR_VERILATED_VPI_H_ ///< Header Guard
#include "verilatedos.h"
#include "verilated.h"
@ -47,7 +47,8 @@ public:
/// Returns time of the next registered VPI callback, or
/// ~(0) if none are registered
static QData cbNextDeadline() VL_MT_UNSAFE_ONE;
/// Self test, for internal use only
// Self test, for internal use only
static void selfTest() VL_MT_UNSAFE_ONE;
};

View File

@ -22,8 +22,8 @@
///
//*************************************************************************
#ifndef _VERILATEDOS_H_
#define _VERILATEDOS_H_ 1 ///< Header Guard
#ifndef VERILATOR_VERILATEDOS_H_
#define VERILATOR_VERILATEDOS_H_ ///< Header Guard
// Current clang-format versions botch #ifdef inclusion, so
// clang-format off
@ -39,7 +39,9 @@
# define VL_ATTR_PRINTF(fmtArgNum) __attribute__((format(printf, (fmtArgNum), (fmtArgNum) + 1)))
# define VL_ATTR_PURE __attribute__((pure))
# define VL_ATTR_UNUSED __attribute__((unused))
# define VL_ATTR_WEAK __attribute__((weak))
# if !defined(_WIN32) && !defined(__MINGW32__)
# define VL_ATTR_WEAK __attribute__((weak))
# endif
# define VL_FUNC __func__
# if defined(__clang__) && defined(VL_THREADED)
# define VL_ACQUIRE(...) __attribute__((acquire_capability(__VA_ARGS__)))
@ -146,6 +148,7 @@
#define VL_MT_SAFE ///< Comment tag that function is threadsafe when VL_THREADED
#define VL_MT_SAFE_POSTINIT ///< Comment tag that function is threadsafe when VL_THREADED, only
///< during normal operation (post-init)
#define VL_MT_SAFE_EXCLUDES(mutex) VL_EXCLUDES(mutex) ///< Threadsafe and uses given mutex
#define VL_MT_UNSAFE ///< Comment tag that function is not threadsafe when VL_THREADED
#define VL_MT_UNSAFE_ONE ///< Comment tag that function is not threadsafe when VL_THREADED,
///< protected to make sure single-caller
@ -479,7 +482,7 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
#endif
//=========================================================================
// String related OS-specific functions
// String/time related OS-specific functions
#ifdef _MSC_VER
# define VL_STRCASECMP _stricmp
@ -487,6 +490,12 @@ typedef unsigned long long vluint64_t; ///< 64-bit unsigned type
# define VL_STRCASECMP strcasecmp
#endif
#ifdef _MSC_VER
# define VL_LOCALTIME_R(timep, tmp) localtime_c((tmp), (timep))
#else
# define VL_LOCALTIME_R(timep, tmp) localtime_r((timep), (tmp))
#endif
//=========================================================================
// Macros controlling target specific optimizations

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python3
# pylint: disable=C0103,C0114,C0115,C0116,R0912,R0914,R0915,W0125,W0621,exec-used
######################################################################
import argparse
@ -7,6 +8,7 @@ import multiprocessing
import os
import re
import subprocess
import sys
RealPath = os.path.dirname(os.path.realpath(__file__))
Exclude_Branch_Regexps = []
@ -36,9 +38,23 @@ def test():
ci_fold_start("configure")
print("Stage 1: configure (coverage on)")
run("autoconf")
# Exceptions can pollute the branch coverage data
run("./configure --enable-longtests CXX='g++ --coverage -fno-exceptions -DVL_GCOV'"
)
cxx_flags = (
"--coverage"
# Otherwise inline may not show as uncovered
# If we use this then e.g. verilated.h functions properly show up
# if unused.
# However, VerilatedSerialize::write then changes from covered
# to uncovered (in G++ 9.3.0) even with all inlining turned off.
# Having false negative coverage is more effort then missing negatives.
# Also this seems to explode the runtime (since a lot more data).
#+ " -fkeep-inline-functions"
# Otherwise static may not show as uncovered
+ " -fkeep-static-functions"
# Exceptions can pollute the branch coverage data
+ " -fno-exceptions"
# Define-out some impossible stuff
+ " -DVL_GCOV")
run("./configure --enable-longtests CXX='g++ " + cxx_flags + "'")
ci_fold_end()
if Args.stage_enabled[2]:
@ -123,8 +139,10 @@ def test():
# Must run in root directory to find all files
os.makedirs(cc_dir, exist_ok=True)
run(RealPath + "/fastcov.py -b -c src/obj_dbg -X --lcov" +
" --exclude /usr --exclude test_regress" + " -o " + cc_dir +
"/app_total.info")
# " --exclude /usr --exclude test_regress" + " -o " + cc_dir +
" -o " + cc_dir + "/app_total.info")
# For debug to convert single .gcna/.gcno in a directory to cov.info:
# lcov -c -d . -o cov.info
ci_fold_end()
if Args.stage_enabled[6]:
@ -223,7 +241,7 @@ def clone_sources(cc_dir):
if done:
break
if re.search(regexp, line):
#print("%s:%d: %s" % (infile, lineno, line)
# print("%s:%d: %s" % (infile, lineno, line)
line += " //code_coverage: // LCOV_EXCL_LINE LCOV_EXCL_BR_LINE"
excluded_lines += 1
excluded_br_lines += 1
@ -233,7 +251,7 @@ def clone_sources(cc_dir):
if done:
break
if re.search(regexp, line):
#print("%s:%d: %s" % (infile, lineno, line)
# print("%s:%d: %s" % (infile, lineno, line)
line += " //code_coverage: // LCOV_EXCL_BR_LINE"
excluded_br_lines += 1
done = True
@ -256,7 +274,7 @@ def cleanup_abs_paths_info(cc_dir, infile, outfile):
count=1)
line = re.sub(cc_dir + '/', '', line, count=1)
line = re.sub(r'obj_dbg/verilog.y$', 'verilog.y', line)
#print("Remaining SF: "+line)
# print("Remaining SF: "+line)
lines.append(line)
with open(outfile, "w") as ofh:
@ -397,7 +415,7 @@ if True:
elif match_from:
start = int(match_from.group(1))
else:
os.exit("%Error: --stages not understood: " + Args.stages)
sys.exit("%Error: --stages not understood: " + Args.stages)
for n in range(0, 100):
Args.stage_enabled[n] = False
for n in range(start, end + 1):
@ -406,6 +424,6 @@ if True:
test()
######################################################################
### Local Variables:
### compile-command: "cd .. ; nodist/code_coverage "
### End:
# Local Variables:
# compile-command: "cd .. ; nodist/code_coverage "
# End:

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python3
# pylint: disable=C0103,C0114,C0115,C0116,C0301
######################################################################
import argparse
@ -104,6 +105,6 @@ dotread(Args.filename)
cwrite("graph_export.cpp")
######################################################################
### Local Variables:
### compile-command: "./dot_importer ../test_regress/obj_vlt/t_EXAMPLE/*orderg_o*.dot && cat graph_export.cpp"
### End:
# Local Variables:
# compile-command: "./dot_importer ../test_regress/obj_vlt/t_EXAMPLE/*orderg_o*.dot && cat graph_export.cpp"
# End:

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python3
# pylint: disable=C0103,C0114,C0115,C0116,C0321,R0911
######################################################################
# DESCRIPTION: Fuzzer result checker
#

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python3
# pylint: disable=C0103,C0114,C0115,C0116,C0321
######################################################################
# DESCRIPTION: Fuzzer dictionary generator
#
@ -50,7 +51,7 @@ def write_file(filename, contents):
def parse_line(s):
# str->maybe str
if len(s) == 0: return
if len(s) == 0: return None
part = skip_while(lambda x: x != '"', s)
if len(part) == 0 or part[0] != '"': return None
literal_part = take_while(lambda x: x != '"', part[1:])
@ -67,7 +68,7 @@ def main():
dirname = 'dictionary'
r = system('mkdir -p ' + dirname)
assert (r == 0)
assert r == 0
for i, token in enumerate(tokens):
write_file(dirname + '/' + str(i), token)

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python3
# pylint: disable=C0103,C0114,C0115,C0116,R0801,R0915
######################################################################
import argparse
@ -6,6 +7,7 @@ import multiprocessing
import os
import shutil
import subprocess
import sys
######################################################################
@ -51,43 +53,43 @@ def test():
# run a test using just the path
if Args.stage <= 2:
print("== stage 2")
dir = testdirp
run("/bin/rm -rf " + dir)
run("/bin/mkdir -p " + dir)
odir = testdirp
run("/bin/rm -rf " + odir)
run("/bin/mkdir -p " + odir)
path = prefix + "/bin" + ":" + prefix + "/share/bin"
write_verilog(dir)
run("cd " + dir + " && PATH=" + path +
write_verilog(odir)
run("cd " + odir + " && PATH=" + path +
":$PATH verilator --cc top.v --exe sim_main.cpp")
run("cd " + dir + "/obj_dir && PATH=" + path +
run("cd " + odir + "/obj_dir && PATH=" + path +
":$PATH make -f Vtop.mk")
run("cd " + dir + " && PATH=" + path + ":$PATH obj_dir/Vtop")
run("cd " + odir + " && PATH=" + path + ":$PATH obj_dir/Vtop")
# run a test using exact path to binary
if Args.stage <= 3:
print("== stage 3")
dir = testdirn
run("/bin/rm -rf " + dir)
run("/bin/mkdir -p " + dir)
write_verilog(dir)
odir = testdirn
run("/bin/rm -rf " + odir)
run("/bin/mkdir -p " + odir)
write_verilog(odir)
bin1 = prefix + "/bin"
run("cd " + dir + " && " + bin1 +
run("cd " + odir + " && " + bin1 +
"/verilator --cc top.v --exe sim_main.cpp")
run("cd " + dir + "/obj_dir && make -f Vtop.mk")
run("cd " + dir + "/obj_dir && ./Vtop")
run("cd " + odir + "/obj_dir && make -f Vtop.mk")
run("cd " + odir + "/obj_dir && ./Vtop")
if Args.stage <= 9:
print("*-* All Finished *-*")
def write_verilog(dir):
shutil.copy2("examples/make_hello_c/top.v", dir + "/top.v")
shutil.copy2("examples/make_hello_c/sim_main.cpp", dir + "/sim_main.cpp")
def write_verilog(odir):
shutil.copy2("examples/make_hello_c/top.v", odir + "/top.v")
shutil.copy2("examples/make_hello_c/sim_main.cpp", odir + "/sim_main.cpp")
def cleanenv():
for var in os.environ:
if (var == "VERILATOR_ROOT" or var == "VERILATOR_INCLUDE"
or var == "VERILATOR_NO_OPT_BUILD"):
if var in ('VERILATOR_ROOT', 'VERILATOR_INCLUDE',
'VERILATOR_NO_OPT_BUILD'):
print("unset %s # Was '%s'" % (var, os.environ[var]))
del os.environ[var]
@ -135,6 +137,6 @@ Args = parser.parse_args()
test()
######################################################################
### Local Variables:
### compile-command: "cd .. ; nodist/install_test"
### End:
# Local Variables:
# compile-command: "cd .. ; nodist/install_test"
# End:

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3ACTIVE_H_
#define _V3ACTIVE_H_ 1
#ifndef VERILATOR_V3ACTIVE_H_
#define VERILATOR_V3ACTIVE_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3ACTIVETOP_H_
#define _V3ACTIVETOP_H_ 1
#ifndef VERILATOR_V3ACTIVETOP_H_
#define VERILATOR_V3ACTIVETOP_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -96,7 +96,8 @@ private:
: // If assertions are off, have constant propagation rip them out later
// This allows syntax errors and such to be detected normally.
(v3Global.opt.assertOn()
? static_cast<AstNode*>(new AstCMath(fl, "Verilated::assertOn()", 1))
? static_cast<AstNode*>(
new AstCMath(fl, "vlSymsp->_vm_contextp__->assertOn()", 1))
: static_cast<AstNode*>(new AstConst(fl, AstConst::BitFalse())))),
nodep, nullptr);
newp->user1(true); // Don't assert/cover this if

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3ASSERT_H_
#define _V3ASSERT_H_ 1
#ifndef VERILATOR_V3ASSERT_H_
#define VERILATOR_V3ASSERT_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3ASSERTPRE_H_
#define _V3ASSERTPRE_H_ 1
#ifndef VERILATOR_V3ASSERTPRE_H_
#define VERILATOR_V3ASSERTPRE_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -120,9 +120,9 @@ string AstNode::encodeName(const string& namein) {
// We also do *NOT* use __DOT__ etc, as we search for those
// in some replacements, and don't want to mangle the user's names.
unsigned val = pos[0] & 0xff; // Mask to avoid sign extension
char hex[10];
sprintf(hex, "__0%02X", val);
out += hex;
std::stringstream hex;
hex << std::setfill('0') << std::setw(2) << std::hex << val;
out += "__0" + hex.str();
}
}
// Shorten names

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3AST_H_
#define _V3AST_H_ 1
#ifndef VERILATOR_V3AST_H_
#define VERILATOR_V3AST_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3ASTCONSTONLY_H_
#define _V3ASTCONSTONLY_H_ 1
#ifndef VERILATOR_V3ASTCONSTONLY_H_
#define VERILATOR_V3ASTCONSTONLY_H_
// Include only in visitors that do not not edit nodes, so should use constant iterators
#define iterateAndNext error_use_iterateAndNextConst

View File

@ -14,10 +14,10 @@
//
//*************************************************************************
#ifndef _V3ASTNODES_H_
#define _V3ASTNODES_H_ 1
#ifndef VERILATOR_V3ASTNODES_H_
#define VERILATOR_V3ASTNODES_H_
#ifndef _V3AST_H_
#ifndef VERILATOR_V3AST_H_
#error "Use V3Ast.h as the include"
#endif

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3BEGIN_H_
#define _V3BEGIN_H_ 1
#ifndef VERILATOR_V3BEGIN_H_
#define VERILATOR_V3BEGIN_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3BRANCH_H_
#define _V3BRANCH_H_ 1
#ifndef VERILATOR_V3BRANCH_H_
#define VERILATOR_V3BRANCH_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3BROKEN_H_
#define _V3BROKEN_H_ 1
#ifndef VERILATOR_V3BROKEN_H_
#define VERILATOR_V3BROKEN_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3CCTORS_H_
#define _V3CCTORS_H_ 1
#ifndef VERILATOR_V3CCTORS_H_
#define VERILATOR_V3CCTORS_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3CUSE_H_
#define _V3CUSE_H_ 1
#ifndef VERILATOR_V3CUSE_H_
#define VERILATOR_V3CUSE_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3CASE_H_
#define _V3CASE_H_ 1
#ifndef VERILATOR_V3CASE_H_
#define VERILATOR_V3CASE_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3CAST_H_
#define _V3CAST_H_ 1
#ifndef VERILATOR_V3CAST_H_
#define VERILATOR_V3CAST_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3CDC_H_
#define _V3CDC_H_ 1
#ifndef VERILATOR_V3CDC_H_
#define VERILATOR_V3CDC_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3CHANGED_H_
#define _V3CHANGED_H_ 1
#ifndef VERILATOR_V3CHANGED_H_
#define VERILATOR_V3CHANGED_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3CLASS_H_
#define _V3CLASS_H_ 1
#ifndef VERILATOR_V3CLASS_H_
#define VERILATOR_V3CLASS_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3CLEAN_H_
#define _V3CLEAN_H_ 1
#ifndef VERILATOR_V3CLEAN_H_
#define VERILATOR_V3CLEAN_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3CLOCK_H_
#define _V3CLOCK_H_ 1
#ifndef VERILATOR_V3CLOCK_H_
#define VERILATOR_V3CLOCK_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3COMBINE_H_
#define _V3COMBINE_H_ 1
#ifndef VERILATOR_V3COMBINE_H_
#define VERILATOR_V3COMBINE_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3CONFIG_H_
#define _V3CONFIG_H_ 1
#ifndef VERILATOR_V3CONFIG_H_
#define VERILATOR_V3CONFIG_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -104,6 +104,7 @@ class ConstBitOpTreeVisitor final : public AstNVisitor {
public:
// METHODS
bool hasConstantResult() const { return m_constResult >= 0; }
bool sameVarAs(const AstNodeVarRef* otherp) const { return m_refp->sameGateTree(otherp); }
void setPolarity(bool compBit, int bit) {
UASSERT_OBJ(!hasConstantResult(), m_refp, "Already has result of " << m_constResult);
if (m_bitPolarity.bitIsX(bit)) { // The bit is not yet set
@ -222,6 +223,9 @@ class ConstBitOpTreeVisitor final : public AstNVisitor {
if (!varInfop) {
varInfop = new VarInfo{this, ref.m_refp};
m_varInfos[idx] = varInfop;
} else {
if (!varInfop->sameVarAs(ref.m_refp))
CONST_BITOP_SET_FAILED("different var (scope?)", ref.m_refp);
}
return *varInfop;
}
@ -687,6 +691,8 @@ private:
return true;
}
bool matchBitOpTree(AstNode* nodep) {
if (!v3Global.opt.oConstBitOpTree()) return false;
AstNode* newp = nullptr;
bool tried = false;
if (AstAnd* andp = VN_CAST(nodep, And)) { // 1 & BitOpTree
@ -703,14 +709,14 @@ private:
}
if (newp) {
UINFO(4, "Transformed leaf of bit tree to " << newp << std::endl);
if (debug() >= 9) {
if (debug() >= 9) { // LCOV_EXCL_START
static int c = 0;
std::cout << "Call matchBitOpTree[" << c << "]\n";
nodep->dumpTree(std::cout);
std::cout << "\nResult:\n";
newp->dumpTree(std::cout);
++c;
}
} // LCOV_EXCL_STOP
nodep->replaceWith(newp);
VL_DO_DANGLING(nodep->deleteTree(), nodep);
}

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3CONST_H_
#define _V3CONST_H_ 1
#ifndef VERILATOR_V3CONST_H_
#define VERILATOR_V3CONST_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3COVERAGE_H_
#define _V3COVERAGE_H_ 1
#ifndef VERILATOR_V3COVERAGE_H_
#define VERILATOR_V3COVERAGE_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3COVERAGEJOIN_H_
#define _V3COVERAGEJOIN_H_ 1
#ifndef VERILATOR_V3COVERAGEJOIN_H_
#define VERILATOR_V3COVERAGEJOIN_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3DEAD_H_
#define _V3DEAD_H_ 1
#ifndef VERILATOR_V3DEAD_H_
#define VERILATOR_V3DEAD_H_
#include "config_build.h"
#include "verilatedos.h"

View File

@ -14,8 +14,8 @@
//
//*************************************************************************
#ifndef _V3DELAYED_H_
#define _V3DELAYED_H_ 1
#ifndef VERILATOR_V3DELAYED_H_
#define VERILATOR_V3DELAYED_H_
#include "config_build.h"
#include "verilatedos.h"

Some files were not shown because too many files have changed in this diff Show More