Merge from master for release.
This commit is contained in:
commit
f0d664530d
|
|
@ -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: ''
|
||||
|
|
|
|||
|
|
@ -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: ''
|
||||
|
|
|
|||
|
|
@ -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: ''
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
22
Changes
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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$
|
||||
|
|
|
|||
36
Makefile.in
36
Makefile.in
|
|
@ -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
|
||||
|
|
|
|||
154
README.adoc
154
README.adoc
|
|
@ -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/> +++ • Accepts synthesizable Verilog or SystemVerilog
|
||||
+++ <br/> +++ • Performs lint code-quality checks
|
||||
+++ <br/> +++ • Compiles into multithreaded {cpp}, or SystemC
|
||||
+++ <br/> +++ • 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/> +++ • Outperforms many commercial simulators
|
||||
+++ <br/> +++ • Single- and multi-threaded output models
|
||||
|
||||
^.^| *Widely Used*
|
||||
+++ <br/> +++ • Wide industry and academic deployment
|
||||
+++ <br/> +++ • 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/> +++ • Guided by the https://chipsalliance.org/[CHIPS Alliance] and https://www.linuxfoundation.org/[Linux Foundation]
|
||||
+++ <br/> +++ • Open, and free as in both speech and beer
|
||||
+++ <br/> +++ • More simulation for your verification budget
|
||||
|
||||
^.^| *Commercial Support Available*
|
||||
+++ <br/> +++ • Commercial support contracts
|
||||
+++ <br/> +++ • Design support contracts
|
||||
+++ <br/> +++ • 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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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!
|
||||
|
|
@ -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 you’d like to clean up
|
||||
indentation and related issues ahead of our feedback, that is
|
||||
appreciated; please see the coding conventions in `docs/internals
|
||||
<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!
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
1030
docs/internals.adoc
1030
docs/internals.adoc
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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; };
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
//======================================================================
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
//=========================================================================
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -15,12 +15,10 @@
|
|||
/// \brief Verilator tracing in VCD Format
|
||||
///
|
||||
//=============================================================================
|
||||
// SPDIFF_OFF
|
||||
|
||||
#include "verilatedos.h"
|
||||
#include "verilated_vcd_sc.h"
|
||||
|
||||
// SPDIFF_ON
|
||||
//======================================================================
|
||||
//======================================================================
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# pylint: disable=C0103,C0114,C0115,C0116,C0321,R0911
|
||||
######################################################################
|
||||
# DESCRIPTION: Fuzzer result checker
|
||||
#
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue