merge upstream master and resolve conflicts
This commit is contained in:
commit
c618361fa2
|
|
@ -158,7 +158,7 @@ jobs:
|
|||
with:
|
||||
path: repo
|
||||
- name: Cache $CCACHE_DIR
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
|
||||
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v5
|
||||
with:
|
||||
path: ${{ env.CCACHE_DIR }}
|
||||
key: msbuild-msvc-cmake
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ jobs:
|
|||
fetch-depth: ${{ inputs.dev-gcov && '0' || '1' }} # Coverage flow needs full history
|
||||
|
||||
- name: Cache $CCACHE_DIR
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
|
||||
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v5
|
||||
env:
|
||||
CACHE_KEY: ${{ env.CACHE_BASE_KEY }}-ccache
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ jobs:
|
|||
sudo apt install ccache mold help2man libfl-dev libjemalloc-dev libsystemc-dev
|
||||
|
||||
- name: Use saved ccache
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
|
||||
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v5
|
||||
with:
|
||||
path: ccache
|
||||
key: rtlmeter-build-ccache-${{ inputs.runs-on }}-${{ inputs.cc }}-${{ inputs.sha }}-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ jobs:
|
|||
|
||||
- name: Use saved ccache
|
||||
if: ${{ env.CCACHE_DISABLE == 0 }}
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
|
||||
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v5
|
||||
with:
|
||||
path: ${{ env.CCACHE_DIR }}
|
||||
key: rtlmeter-run-ccache-${{ inputs.runs-on }}-${{ inputs.cc }}-${{ inputs.cases }}-${{ inputs.compileArgs }}-${{ github.run_id }}-${{ github.run_attempt }}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ jobs:
|
|||
ls -lsha
|
||||
|
||||
- name: Cache $CCACHE_DIR
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
|
||||
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v5
|
||||
env:
|
||||
CACHE_KEY: ${{ env.CACHE_BASE_KEY }}-ccache2
|
||||
with:
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ cmake_minimum_required(VERSION 3.15)
|
|||
cmake_policy(SET CMP0091 NEW) # Use MSVC_RUNTIME_LIBRARY to select the runtime
|
||||
project(
|
||||
Verilator
|
||||
VERSION 5.049
|
||||
VERSION 5.051
|
||||
HOMEPAGE_URL https://verilator.org
|
||||
LANGUAGES CXX
|
||||
)
|
||||
|
|
|
|||
52
Changes
52
Changes
|
|
@ -10,7 +10,21 @@ The changes in each Verilator version are described below. The
|
|||
contributors that suggested or implemented a given issue are shown in []. Thanks!
|
||||
|
||||
|
||||
Verilator 5.049 devel
|
||||
Verilator 5.051 devel
|
||||
==========================
|
||||
|
||||
**Other:**
|
||||
|
||||
* Add comments as a branch description in coverage .info files (#7843). [Eryk Szpotanski]
|
||||
* Optimize random initialization. [Geza Lore, Testorrent USA, Inc.]
|
||||
* Fix DFG misoptimizing bound checks (#7755). [Jakub Michalski]
|
||||
* Fix unique0 case side effects (#7787). [Pawel Klopotek]
|
||||
* Fix cleaning purity cache after assertions. [Geza Lore, Testorrent USA, Inc.]
|
||||
* Fix clang++ ambiguous overload of '==' operator (#7863). [Pawel Kojma, Antmicro Ltd.]
|
||||
* Fix heap-use-after-free in `VlRNG::VlRNG()` (#7865). [Dragon-Git]
|
||||
|
||||
|
||||
Verilator 5.050 2026-07-01
|
||||
==========================
|
||||
|
||||
**Important:**
|
||||
|
|
@ -32,7 +46,7 @@ Verilator 5.049 devel
|
|||
* Improve `--coverage-fsm` (#7490) (#7529) (#7561) (#7573) (#7619). [Yogish Sekhar]
|
||||
* Change `+verilator+seed` to default to 1, and 0 to randomly select (#7325) (#7516). [Miguel]
|
||||
* Change JSON to include parameter constant mnemonics for FSM Coverage (#7531). [Yogish Sekhar]
|
||||
* Support assert property 'default disable iff` (#4848) (#7723). [Artur Bieniek, Antmicro Ltd.]
|
||||
* Support assert property `default disable iff` (#4848) (#7723). [Artur Bieniek, Antmicro Ltd.]
|
||||
* Support printing enum names for %p and %s (#5523) (#7338 repair) (#7521) (#7527). [Nick Brereton]
|
||||
* Support weak `until` / `until_with` property operators (#7290) (#7548) (#7685). [Yilou Wang]
|
||||
* Support `s_eventually` (#7291) (#7508). [Bartłomiej Chmiel, Antmicro Ltd.]
|
||||
|
|
@ -67,6 +81,7 @@ Verilator 5.049 devel
|
|||
* Support property case (#7682) (#7721). [Artur Bieniek, Antmicro Ltd.]
|
||||
* Support `s_until` and `s_until_with`(#7722). [Artur Bieniek, Antmicro Ltd.]
|
||||
* Support covergroup runtime model Phase A1 (#7728). [Matthew Ballance]
|
||||
* Support hierarchical reference cross members (#7749) (#7820). [Matthew Ballance]
|
||||
* Support reduction XOR/AND operations in constraints (#7753). [Kornel Uriasz, Antmicro Ltd.]
|
||||
* Support NBAs in initial blocks (#7754). [Igor Zaworski, Antmicro Ltd.]
|
||||
* Support assertion control system tasks in classes and interfaces (#7761). [Yilou Wang]
|
||||
|
|
@ -75,6 +90,11 @@ Verilator 5.049 devel
|
|||
* Support $assertcontrol control_type from lock to kill (#7788). [Yilou Wang]
|
||||
* Support unbounded always [m:$] and strong s_always liveness (#7798). [Yilou Wang]
|
||||
* Support method calls on a sub-interface via a virtual interface (#7800). [Yilou Wang]
|
||||
* Support global $assertcontrol (#7807). [Artur Bieniek, Antmicro Ltd.]
|
||||
* Support VPI access to unpacked struct members (#7823). [Nick Brereton]
|
||||
* Support variable-length intersect in SVA sequences (#7835). [Yilou Wang]
|
||||
* Support dynamic loading of VPI extensions (#7727). [Matthew Ballance]
|
||||
* Optimize DFG cycle breaking to do less work (#7210). [Geza Lore, Testorrent USA, Inc.]
|
||||
* Optimize emitting to_string() for compiler speedup (#7468). [Jakub Michalski, Antmicro Ltd.]
|
||||
* Optimize additional DFG peephole cases (#7553). [Varun Koyyalagunta, Testorrent USA, Inc.]
|
||||
* Optimize forced signal handling (#7554 partial) (#7572) (#7594) (#7596). [Krzysztof Bieganski, Artur Bieniek, Antmicro Ltd.]
|
||||
|
|
@ -97,7 +117,12 @@ Verilator 5.049 devel
|
|||
* Optimize input combinational logic by change detection (#7784). [Geza Lore, Testorrent USA, Inc.]
|
||||
* Optimize decoder case statements into lookup tables (#7795). [Geza Lore, Testorrent USA, Inc.]
|
||||
* Optimize wide decoder case statements into decoder expressions (#7804). [Geza Lore, Testorrent USA, Inc.]
|
||||
* Optimize DFG cycle breaking to do less work (#7210). [Geza Lore, Testorrent USA, Inc.]
|
||||
* Optimize statically known oversize shifts (#7806). [Geza Lore, Testorrent USA, Inc.]
|
||||
* Optimize generated function inlining (#7811). [Geza Lore, Testorrent USA, Inc.]
|
||||
* Optimize bit-scan loops into most-set-bit or $countones (#7822). [Thomas Santerre]
|
||||
* Optimize additional expression patterns (#7824). [Geza Lore, Testorrent USA, Inc.]
|
||||
* Optimize module inlining heuristic (#7837). [Geza Lore, Testorrent USA, Inc.]
|
||||
* Fix `$bits` on unpacked structs (#4521) (#7796). [Nick Brereton]
|
||||
* Fix TSP variable ordering for mtasks (#5342) (#7610). [Muzaffer Kal]
|
||||
* Fix inlining static initializer in V3Gate (#5381) (#7503). [Andrew Nolte] [Geza Lore, Testorrent USA, Inc.]
|
||||
* Fix timed nested fork block with disable (#6720) (#7743). [Marco Bartoli]
|
||||
|
|
@ -147,6 +172,7 @@ Verilator 5.049 devel
|
|||
* Fix reference counting for modport task references (#7628). [Nick Brereton]
|
||||
* Fix internal error when handling typedefs containing parameterized class type members (#7635) (#7661). [em2machine]
|
||||
* Fix forceable signal with a procedural continuous assign (#7638) (#7639). [Zubin Jain]
|
||||
* Fix scheduling of virtual interface method writes (#7641). [Artur Bieniek, Antmicro Ltd.]
|
||||
* Fix implicit conversions of VlWide (#7642). [Geza Lore, Testorrent USA, Inc.]
|
||||
* Fix CASEINCOMPLETE to not warn on `unique0 case` (#7647).
|
||||
* Fix hierarchical coverage counts for duplicate no-inline module instances (#7649). [Yogish Sekhar]
|
||||
|
|
@ -173,17 +199,29 @@ Verilator 5.049 devel
|
|||
* Fix s_eventually in parameterized interfaces (#7741). [Nick Brereton]
|
||||
* Fix dpi export pointers (#7742) (#7751). [Yilin Li]
|
||||
* Fix force on unpacked bit select (#7744) (#7745). [Nikolai Kumar]
|
||||
* Fix `$` as unsupported coverpoint-bin range bounds (#7750) (#7825). [Matthew Ballance]
|
||||
* Fix FSM detect unchecked casts and variable redeclaration (#7758). [Adam Kostrzewski, Antmicro Ltd.]
|
||||
* Fix no-scope internal error on virtual interface method calls (#7759). [Yilou Wang]
|
||||
* Fix 'case (_) inside' with x wildcards (#7766). [Geza Lore, Testorrent USA, Inc.]
|
||||
* Fix `case (_) inside` with x wildcards (#7766). [Geza Lore, Testorrent USA, Inc.]
|
||||
* Fix not failing assertion when RHS of a range window rejects once (#7773). [Artur Bieniek, Antmicro Ltd.]
|
||||
* Fix $fflush and autoflush with --threads (#7782).
|
||||
* Fix out-of-bounds read value for 2-state types (#7785). [Jakub Michalski]
|
||||
* Fix `cover property` of an implication counting vacuous matches (#7789). [Yilou Wang]
|
||||
* Fix randomization of dynamic arrays of objects (#7790). [Ryszard Rozak, Antmicro Ltd.]
|
||||
* Fix `$bits` on unpacked structs (#4521) (#7796). [Nick Brereton]
|
||||
* Fix randomize() with skipping derived pre/post_randomize (#7799). [Yilou Wang]
|
||||
* Fix skewed dist operator for arrays (#7802). [Jakub Wasilewski, Antmicro Ltd.]
|
||||
* Fix assertion when loop unrolling failed (#7810). [Geza Lore, Testorrent USA, Inc.]
|
||||
* Fix CASEINCOMPLETE for all uncovered enum items (#7815) (#7817). [Saksham]
|
||||
* Fix split optimization nested-class crash (#7826). [Igor Zaworski, Antmicro Ltd.]
|
||||
* Fix class/var named identically to an enclosing-scope type (#7827) (#7828). [Tom Jackson]
|
||||
* Fix performance on large package-scoped structs (#7830). [Wolfgang Mayerwieser]
|
||||
* Fix unclocked concurrent assertion misreported as unsupported (#7831). [Yilou Wang]
|
||||
* Fix insertion of expression coverage statement (#7832). [Ryszard Rozak, Antmicro Ltd.]
|
||||
* Fix lifetime of expression coverage variable (#7834). [Ryszard Rozak, Antmicro Ltd.]
|
||||
* Fix disable iff ignored when its condition is held continuously true (#7841). [Yilou Wang]
|
||||
* Fix constant pool cache after dead scope removal (#7845). [Nick Brereton]
|
||||
* Fix covergroups without --coverage (#7848) (#7849). [Joshua Leahy]
|
||||
* Fix class scope '::' reference through an inherited type parameter (#7844). [Sergey Chusov]
|
||||
|
||||
|
||||
Verilator 5.048 2026-04-26
|
||||
|
|
@ -520,7 +558,7 @@ Verilator 5.044 2026-01-01
|
|||
* Support clocking output delay `1step` (#6681). [Ondrej Ille]
|
||||
* Support parsing of dotted `bins_expression` (#6683). [Pawel Kojma, Antmicro Ltd.]
|
||||
* Support constant expression cycle delays in sequences (#6691). [Ryszard Rozak, Antmicro Ltd.]
|
||||
* Support general global constraints (#6709) (#6711). [Yilou Wang]
|
||||
* Support general global constraints (#6709) (#6711) (#7833) (#7838). [Yilou Wang]
|
||||
* Support complex std::randomize patterns (#6736) (#6737). [Yilou Wang]
|
||||
* Support `rand_mode` in global constraint gathering (#6740) (#6752). [Yilou Wang]
|
||||
* Support reduction or in constraints (#6840). [Pawel Kojma, Antmicro Ltd.]
|
||||
|
|
@ -5714,7 +5752,7 @@ Verilator 3.104 2003-04-30
|
|||
**Major:**
|
||||
|
||||
* Indicate direction of ports with VL_IN and VL_OUT.
|
||||
* Allow $c32, etc, to specify width of the $c statement for VCS.
|
||||
* Allow $c32, etc, to specify width of the $c statement.
|
||||
* Numerous performance improvements, worth about 25%
|
||||
|
||||
**Minor:**
|
||||
|
|
|
|||
|
|
@ -653,6 +653,7 @@ description of these arguments.
|
|||
+verilator+solver+file+<filename> Set random solver log filename
|
||||
+verilator+V Show verbose version and config
|
||||
+verilator+version Show version and exit
|
||||
+verilator+vpi+<library>[:<bootstrap>] Load VPI shared library
|
||||
+verilator+wno+unsatconstr+<value> Disable constraint warnings
|
||||
|
||||
|
||||
|
|
|
|||
30
configure.ac
30
configure.ac
|
|
@ -12,7 +12,7 @@
|
|||
# Then 'make maintainer-dist'
|
||||
#AC_INIT([Verilator],[#.### YYYY-MM-DD])
|
||||
#AC_INIT([Verilator],[#.### devel])
|
||||
AC_INIT([Verilator],[5.049 devel],
|
||||
AC_INIT([Verilator],[5.051 devel],
|
||||
[https://verilator.org],
|
||||
[verilator],[https://verilator.org])
|
||||
|
||||
|
|
@ -589,6 +589,34 @@ m4_foreach([ldflag], [
|
|||
AC_SUBST(CFG_LDLIBS_THREADS)
|
||||
AC_SUBST(CFG_LDFLAGS_THREADS_CMAKE)
|
||||
|
||||
# Find link flags for runtime VPI library loading (+verilator+vpi+<lib>).
|
||||
# The model executable must export its VPI symbols so the dlopen'd library can
|
||||
# resolve them: -rdynamic (GNU ld) or -Wl,-export_dynamic (Darwin); the first the
|
||||
# linker accepts wins. -ldl provides dlopen/dlsym where it is a separate library.
|
||||
_MY_LDLIBS_CHECK_SET(CFG_LDFLAGS_DYNAMIC, -rdynamic)
|
||||
# -Wl,-export_dynamic contains a comma, so probe it directly rather than through
|
||||
# the _MY_LDLIBS_CHECK_* macros (which re-expand their flag argument unquoted).
|
||||
if test "$CFG_LDFLAGS_DYNAMIC" = ""; then
|
||||
ACO_SAVE_LIBS="$LIBS"
|
||||
LIBS="$LIBS -Wl,-export_dynamic"
|
||||
AC_MSG_CHECKING([whether $CXX linker accepts -Wl,-export_dynamic])
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM([[]])],
|
||||
[_my_result=yes
|
||||
if test -s conftest.err; then
|
||||
if grep -e "-export_dynamic" conftest.err >/dev/null; then
|
||||
_my_result=no
|
||||
fi
|
||||
fi],
|
||||
[_my_result=no])
|
||||
AC_MSG_RESULT($_my_result)
|
||||
LIBS="$ACO_SAVE_LIBS"
|
||||
if test "$_my_result" = "yes"; then CFG_LDFLAGS_DYNAMIC="-Wl,-export_dynamic"; fi
|
||||
fi
|
||||
AC_SUBST(CFG_LDFLAGS_DYNAMIC)
|
||||
_MY_LDLIBS_CHECK_OPT(CFG_LDLIBS_DYNAMIC, -ldl)
|
||||
AC_SUBST(CFG_LDLIBS_DYNAMIC)
|
||||
|
||||
# If 'mold' is installed, use it to link for faster buildtimes
|
||||
_MY_LDLIBS_CHECK_OPT(CFG_LDFLAGS_SRC, -fuse-ld=mold)
|
||||
_MY_LDLIBS_CHECK_OPT(CFG_LDFLAGS_VERILATED, -fuse-ld=mold)
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ David Turner
|
|||
Dercury
|
||||
Diego Roux
|
||||
Dominick Grochowina
|
||||
Dragon-Git
|
||||
Don Williamson
|
||||
Drew Ranck
|
||||
Drew Taussig
|
||||
|
|
@ -69,6 +70,7 @@ Edgar E. Iglesias
|
|||
Eric Mejdrich
|
||||
Eric Müller
|
||||
Eric Rippey
|
||||
Eryk Szpotański
|
||||
Eunseo Song
|
||||
Ethan Sifferman
|
||||
Eyck Jentzsch
|
||||
|
|
@ -146,6 +148,7 @@ Jose Loyola
|
|||
Josep Sans
|
||||
Joseph Nwabueze
|
||||
Josh Redford
|
||||
Joshua Leahy
|
||||
Julian Carrier
|
||||
Julian Daube
|
||||
Julie Schwartz
|
||||
|
|
@ -257,6 +260,7 @@ Samuel Riedel
|
|||
Sean Cross
|
||||
Sebastien Van Cauwenberghe
|
||||
Secturion
|
||||
Sergey Chusov
|
||||
Sergey Fedorov
|
||||
Sergi Granell
|
||||
Seth Pellegrino
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ DPI Example
|
|||
In the SYSTEMC example above, if you wanted to import C++ functions into
|
||||
Verilog, put in our.v:
|
||||
|
||||
.. code-block:: sv
|
||||
.. code-block::
|
||||
|
||||
import "DPI-C" function int add (input int a, input int b);
|
||||
|
||||
|
|
@ -211,7 +211,7 @@ Verilator extends the DPI format to allow using the same scheme to
|
|||
efficiently add system functions. Use a dollar-sign prefixed system
|
||||
function name for the import, but note it must be escaped.
|
||||
|
||||
.. code-block:: sv
|
||||
.. code-block::
|
||||
|
||||
import "DPI-C" function integer \$myRand;
|
||||
|
||||
|
|
|
|||
|
|
@ -139,6 +139,20 @@ Options:
|
|||
|
||||
Displays program version and exits.
|
||||
|
||||
.. option:: +verilator+vpi+<library>[:<bootstrap>]
|
||||
|
||||
Load a VPI shared library before simulation starts. Only available when the
|
||||
model was Verilated with :vlopt:`--vpi` and :vlopt:`--main` (or
|
||||
:vlopt:`--binary`). ``<library>`` is the path to the shared library. If
|
||||
``:<bootstrap>`` is given, that named no-argument function is called;
|
||||
otherwise the library's ``vlog_startup_routines`` array (IEEE 1800 38.37.2) is
|
||||
invoked. May be repeated to load multiple libraries.
|
||||
|
||||
Runtime loading is supported on POSIX platforms only (it relies on the
|
||||
executable exporting its VPI symbols to the loaded library); on Windows the
|
||||
argument is rejected and the VPI code must instead be statically linked
|
||||
into the model.
|
||||
|
||||
.. option:: +verilator+wno+unsatconstr+<value>
|
||||
|
||||
Disable unsatisfied constraint warnings at simulation runtime. When set to
|
||||
|
|
|
|||
|
|
@ -477,6 +477,7 @@ Syms
|
|||
Synopsys
|
||||
SystemC
|
||||
SystemVerilog
|
||||
Szpotanski
|
||||
Takatsukasa
|
||||
Tambe
|
||||
Tarik
|
||||
|
|
@ -537,6 +538,7 @@ Verilog
|
|||
Vighnesh
|
||||
Viktor
|
||||
Vilp
|
||||
VlRNG
|
||||
VlWide
|
||||
Vlip
|
||||
Vm
|
||||
|
|
@ -684,6 +686,7 @@ countones
|
|||
cout
|
||||
covergroup
|
||||
covergroups
|
||||
coverpoint
|
||||
coverpoints
|
||||
cpp
|
||||
cppstyle
|
||||
|
|
@ -946,6 +949,7 @@ misconnected
|
|||
misconversion
|
||||
misdetecting
|
||||
misoptimized
|
||||
misoptimizing
|
||||
missized
|
||||
mk
|
||||
mno
|
||||
|
|
@ -1207,6 +1211,7 @@ typename
|
|||
uint
|
||||
un
|
||||
unbased
|
||||
unclocked
|
||||
uncomment
|
||||
undef
|
||||
undefineall
|
||||
|
|
|
|||
|
|
@ -89,6 +89,12 @@
|
|||
# include <unistd.h>
|
||||
# define _VL_HAVE_GETRLIMIT
|
||||
#endif
|
||||
#if VM_VPI
|
||||
# include <cstring>
|
||||
# ifndef _WIN32
|
||||
# include <dlfcn.h> // dlopen
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "verilated_threads.h"
|
||||
// clang-format on
|
||||
|
|
@ -260,6 +266,58 @@ void VL_WARN_MT(const char* filename, int linenum, const char* hier, const char*
|
|||
}});
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Runtime VPI shared library loading (--vpi)
|
||||
|
||||
// Load one VPI shared library named by a +verilator+vpi+<lib>[:<bootstrap>] argument.
|
||||
// 'arg' is the payload after the prefix: either "<lib>" (invoke the library's
|
||||
// vlog_startup_routines array) or "<lib>:<bootstrap>" (invoke the named bootstrap).
|
||||
void Verilated::loadVpiLib(const std::string& arg) VL_MT_UNSAFE {
|
||||
#if VM_VPI
|
||||
if (arg.empty()) return;
|
||||
#ifdef _WIN32
|
||||
VL_FATAL_MT("", 0, "",
|
||||
"+verilator+vpi+: runtime VPI library loading is not supported on"
|
||||
" Windows; link the VPI code into the model instead");
|
||||
#else
|
||||
using vlog_startup_t = void (*)();
|
||||
// Split <lib>:<bootstrap> on the last ':'
|
||||
const std::string::size_type colon_pos = arg.rfind(':');
|
||||
const bool has_entry = (colon_pos != std::string::npos);
|
||||
const std::string libpath = has_entry ? arg.substr(0, colon_pos) : arg;
|
||||
const std::string entry_name = has_entry ? arg.substr(colon_pos + 1) : std::string{};
|
||||
void* handle = dlopen(libpath.c_str(), RTLD_LAZY);
|
||||
if (!handle)
|
||||
// The library path is stable; the dlerror() text is platform-specific, so put it on
|
||||
// a separate "- " line (test golden files strip "- " lines, keeping output portable).
|
||||
VL_FATAL_MT(
|
||||
"", 0, "",
|
||||
(std::string{"Cannot load VPI library: "} + libpath + "\n- dlerror: " + dlerror())
|
||||
.c_str());
|
||||
if (has_entry) {
|
||||
vlog_startup_t bsp = reinterpret_cast<vlog_startup_t>(dlsym(handle, entry_name.c_str()));
|
||||
if (!bsp)
|
||||
VL_FATAL_MT(
|
||||
"", 0, "",
|
||||
(std::string{"Cannot find VPI bootstrap '"} + entry_name + "' in: " + libpath)
|
||||
.c_str());
|
||||
bsp();
|
||||
} else {
|
||||
vlog_startup_t* routinesp
|
||||
= reinterpret_cast<vlog_startup_t*>(dlsym(handle, "vlog_startup_routines"));
|
||||
if (!routinesp)
|
||||
VL_FATAL_MT(
|
||||
"", 0, "",
|
||||
(std::string{"Cannot find 'vlog_startup_routines' in: "} + libpath).c_str());
|
||||
for (int j = 0; routinesp[j]; ++j) routinesp[j]();
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
// Never reached: the command-line handler only calls this when compiled with --vpi.
|
||||
(void)arg;
|
||||
#endif
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// Debug prints
|
||||
|
||||
|
|
@ -319,7 +377,6 @@ void VL_PRINTF_MT(const char* formatp, ...) VL_MT_SAFE {
|
|||
}
|
||||
|
||||
void VL_FFLUSH_MT() VL_MT_SAFE {
|
||||
va_list ap;
|
||||
VerilatedThreadMsgQueue::post(VerilatedMsg{[=]() { //
|
||||
Verilated::runFlushCallbacks();
|
||||
}});
|
||||
|
|
@ -506,9 +563,10 @@ IData VL_URANDOM_SEEDED_II(IData seed) VL_MT_SAFE {
|
|||
}
|
||||
|
||||
IData VL_SCOPED_RAND_RESET_I(int obits, uint64_t scopeHash, uint64_t salt) VL_MT_UNSAFE {
|
||||
if (Verilated::threadContextp()->randReset() == 0) return 0;
|
||||
const int randReset = Verilated::threadContextp()->randReset();
|
||||
if (randReset == 0) return 0;
|
||||
IData data = ~0;
|
||||
if (Verilated::threadContextp()->randReset() != 1) { // if 2, randomize
|
||||
if (randReset != 1) { // if 2, randomize
|
||||
VlRNG rng{Verilated::threadContextp()->randSeed() ^ scopeHash ^ salt};
|
||||
data = rng.rand64();
|
||||
}
|
||||
|
|
@ -517,9 +575,10 @@ IData VL_SCOPED_RAND_RESET_I(int obits, uint64_t scopeHash, uint64_t salt) VL_MT
|
|||
}
|
||||
|
||||
QData VL_SCOPED_RAND_RESET_Q(int obits, uint64_t scopeHash, uint64_t salt) VL_MT_UNSAFE {
|
||||
if (Verilated::threadContextp()->randReset() == 0) return 0;
|
||||
const int randReset = Verilated::threadContextp()->randReset();
|
||||
if (randReset == 0) return 0;
|
||||
QData data = ~0ULL;
|
||||
if (Verilated::threadContextp()->randReset() != 1) { // if 2, randomize
|
||||
if (randReset != 1) { // if 2, randomize
|
||||
VlRNG rng{Verilated::threadContextp()->randSeed() ^ scopeHash ^ salt};
|
||||
data = rng.rand64();
|
||||
}
|
||||
|
|
@ -529,10 +588,17 @@ QData VL_SCOPED_RAND_RESET_Q(int obits, uint64_t scopeHash, uint64_t salt) VL_MT
|
|||
|
||||
WDataOutP VL_SCOPED_RAND_RESET_W(int obits, WDataOutP outwp, uint64_t scopeHash,
|
||||
uint64_t salt) VL_MT_UNSAFE {
|
||||
if (Verilated::threadContextp()->randReset() != 2) { return VL_RAND_RESET_W(obits, outwp); }
|
||||
VlRNG rng{Verilated::threadContextp()->randSeed() ^ scopeHash ^ salt};
|
||||
for (int i = 0; i < VL_WORDS_I(obits) - 1; ++i) outwp[i] = rng.rand64();
|
||||
outwp[VL_WORDS_I(obits) - 1] = rng.rand64() & VL_MASK_E(obits);
|
||||
const int words = VL_WORDS_I(obits);
|
||||
const int randReset = Verilated::threadContextp()->randReset();
|
||||
if (randReset == 0) {
|
||||
VL_MEMSET_ZERO_W(outwp, words);
|
||||
} else if (randReset == 1) {
|
||||
VL_MEMSET_ONES_W(outwp, words);
|
||||
} else {
|
||||
VlRNG rng{Verilated::threadContextp()->randSeed() ^ scopeHash ^ salt};
|
||||
for (int i = 0; i < words; ++i) outwp[i] = rng.rand64();
|
||||
}
|
||||
outwp[words - 1] &= VL_MASK_E(obits);
|
||||
return outwp;
|
||||
}
|
||||
|
||||
|
|
@ -557,30 +623,14 @@ WDataOutP VL_SCOPED_RAND_RESET_ASSIGN_W(int obits, WDataOutP outwp, uint64_t sco
|
|||
}
|
||||
|
||||
IData VL_RAND_RESET_I(int obits) VL_MT_SAFE {
|
||||
if (Verilated::threadContextp()->randReset() == 0) return 0;
|
||||
const int randReset = Verilated::threadContextp()->randReset();
|
||||
if (randReset == 0) return 0;
|
||||
IData data = ~0;
|
||||
if (Verilated::threadContextp()->randReset() != 1) { // if 2, randomize
|
||||
data = VL_RANDOM_I();
|
||||
}
|
||||
if (randReset != 1) data = VL_RANDOM_I(); // if 2, randomize
|
||||
data &= VL_MASK_I(obits);
|
||||
return data;
|
||||
}
|
||||
|
||||
QData VL_RAND_RESET_Q(int obits) VL_MT_SAFE {
|
||||
if (Verilated::threadContextp()->randReset() == 0) return 0;
|
||||
QData data = ~0ULL;
|
||||
if (Verilated::threadContextp()->randReset() != 1) { // if 2, randomize
|
||||
data = VL_RANDOM_Q();
|
||||
}
|
||||
data &= VL_MASK_Q(obits);
|
||||
return data;
|
||||
}
|
||||
|
||||
WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE {
|
||||
for (int i = 0; i < VL_WORDS_I(obits) - 1; ++i) outwp[i] = VL_RAND_RESET_I(32);
|
||||
outwp[VL_WORDS_I(obits) - 1] = VL_RAND_RESET_I(32) & VL_MASK_E(obits);
|
||||
return outwp;
|
||||
}
|
||||
WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE {
|
||||
// Not inlined to speed up compilation of slowpath code
|
||||
return VL_ZERO_W(obits, outwp);
|
||||
|
|
@ -3544,6 +3594,17 @@ void VerilatedContextImp::commandArgVl(const std::string& arg) {
|
|||
// and the run can be reproduced by passing +verilator+seed+<that_value>.
|
||||
if (u64 == 0) u64 = pickRandomSeed();
|
||||
randSeed(static_cast<int>(u64));
|
||||
} else if (commandArgVlString(arg, "+verilator+vpi+", str)) {
|
||||
// With --vpi, load the requested shared library now. Without --vpi there is
|
||||
// no VPI runtime, so warn the argument is ignored.
|
||||
#if VM_VPI
|
||||
Verilated::loadVpiLib(str);
|
||||
#else
|
||||
VL_WARN_MT(
|
||||
"COMMAND_LINE", 0, "",
|
||||
("+verilator+vpi+ ignored: simulation was not compiled with --vpi '" + arg + "'")
|
||||
.c_str()); // LCOV_EXCL_LINE (gcov zeroes this wrapped continuation line)
|
||||
#endif
|
||||
} else if (arg == "+verilator+V") {
|
||||
VerilatedImp::versionDump(); // Someday more info too
|
||||
VL_FATAL_MT("COMMAND_LINE", 0, "",
|
||||
|
|
|
|||
|
|
@ -1036,6 +1036,9 @@ public:
|
|||
static void scTraceBeforeElaborationError() VL_ATTR_NORETURN VL_MT_SAFE;
|
||||
static void stackCheck(QData needSize) VL_MT_UNSAFE;
|
||||
|
||||
// Internal: Load a VPI shared library (+verilator+vpi+<lib>[:<bootstrap>])
|
||||
static void loadVpiLib(const std::string& arg) VL_MT_UNSAFE;
|
||||
|
||||
// Internal: Get and set DPI context
|
||||
static const VerilatedScope* dpiScope() VL_MT_SAFE { return t_s.t_dpiScopep; }
|
||||
static void dpiScope(const VerilatedScope* scopep) VL_MT_SAFE { t_s.t_dpiScopep = scopep; }
|
||||
|
|
|
|||
|
|
@ -52,6 +52,9 @@ CFG_GCH_IF_CLANG = @CFG_GCH_IF_CLANG@
|
|||
CFG_LDFLAGS_VERILATED = @CFG_LDFLAGS_VERILATED@
|
||||
# Linker libraries for multithreading
|
||||
CFG_LDLIBS_THREADS = @CFG_LDLIBS_THREADS@
|
||||
# Linker flags/libraries for runtime VPI library loading (+verilator+vpi+<lib>)
|
||||
CFG_LDFLAGS_DYNAMIC = @CFG_LDFLAGS_DYNAMIC@
|
||||
CFG_LDLIBS_DYNAMIC = @CFG_LDLIBS_DYNAMIC@
|
||||
|
||||
######################################################################
|
||||
# Programs
|
||||
|
|
@ -93,6 +96,7 @@ VK_CPPFLAGS_ALWAYS += \
|
|||
-DVM_TRACE_FST=$(VM_TRACE_FST) \
|
||||
-DVM_TRACE_VCD=$(VM_TRACE_VCD) \
|
||||
-DVM_TRACE_SAIF=$(VM_TRACE_SAIF) \
|
||||
-DVM_VPI=$(VM_VPI) \
|
||||
$(CFG_CXXFLAGS_NO_UNUSED) \
|
||||
|
||||
ifeq ($(CFG_WITH_CCWARN),yes) # Local... Else don't burden users
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@
|
|||
/// \file
|
||||
/// \brief Verilated functional-coverage collection runtime implementation
|
||||
///
|
||||
/// Compiled and linked when "verilator --coverage" is used with covergroups.
|
||||
/// Linked when covergroups are present. The coverage-database registration
|
||||
/// is compiled only with "verilator --coverage".
|
||||
///
|
||||
//=============================================================================
|
||||
|
||||
|
|
@ -22,7 +23,9 @@
|
|||
|
||||
#include "verilated_covergroup.h"
|
||||
|
||||
#if VM_COVERAGE
|
||||
#include "verilated_cov.h"
|
||||
#endif
|
||||
|
||||
void VlCoverpoint::init(const char* hier, uint32_t atLeast, int nBins) {
|
||||
m_hier = hier;
|
||||
|
|
@ -54,6 +57,7 @@ std::string VlCoverpoint::binName(int i) const {
|
|||
return name;
|
||||
}
|
||||
|
||||
#if VM_COVERAGE
|
||||
void VlCoverpoint::registerBins(VerilatedCovContext* covcontextp, const char* page) {
|
||||
for (int i = 0; i < binCount(); ++i) {
|
||||
const VlCovNamer& nm = namerFor(i);
|
||||
|
|
@ -76,3 +80,4 @@ void VlCoverpoint::registerBins(VerilatedCovContext* covcontextp, const char* pa
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif // VM_COVERAGE
|
||||
|
|
|
|||
|
|
@ -124,10 +124,6 @@ extern WDataOutP VL_SCOPED_RAND_RESET_ASSIGN_W(int obits, WDataOutP outwp, uint6
|
|||
|
||||
/// Random reset a signal of given width (init time only)
|
||||
extern IData VL_RAND_RESET_I(int obits) VL_MT_SAFE;
|
||||
/// Random reset a signal of given width (init time only)
|
||||
extern QData VL_RAND_RESET_Q(int obits) VL_MT_SAFE;
|
||||
/// Random reset a signal of given width (init time only)
|
||||
extern WDataOutP VL_RAND_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE;
|
||||
|
||||
/// Zero reset a signal (slow - else use VL_ZERO_W)
|
||||
extern WDataOutP VL_ZERO_RESET_W(int obits, WDataOutP outwp) VL_MT_SAFE;
|
||||
|
|
@ -1025,14 +1021,10 @@ static inline IData VL_EQ_R(int words, VlQueue<T> q, WDataInP const rwp) VL_PURE
|
|||
} else if (sizeof(T) == 4) {
|
||||
for (int i = 0; (i < wordsInQ + 1); ++i) { nequal |= (q.at(wordsInQ - i) ^ rwp[i]); }
|
||||
} else if (sizeof(T) == 8) {
|
||||
QData temp = 0;
|
||||
int qSize = q.size() - 1;
|
||||
for (int i = 0; (i < qSize); i += 2) {
|
||||
temp = q.at(qSize - i);
|
||||
nequal |= (static_cast<QData>(q.at(qSize - i)) >> 32 ^ rwp[i + 1]);
|
||||
temp = rwp[i + 1];
|
||||
nequal |= (static_cast<QData>(q.at(qSize - i)) ^ rwp[i]);
|
||||
temp = rwp[i];
|
||||
}
|
||||
}
|
||||
return (nequal == 0);
|
||||
|
|
@ -1042,7 +1034,6 @@ template <std::size_t N_Words>
|
|||
static inline IData VL_EQ_R(int words, const VlQueue<VlWide<N_Words>>& q,
|
||||
WDataInP const rwp) VL_PURE {
|
||||
EData nequal = 0;
|
||||
const int wordsInQ = q.size() * N_Words;
|
||||
if ((q.size() * N_Words) != words) { return false; }
|
||||
int count = 0;
|
||||
for (int qIndex = q.size() - 1; qIndex >= 0; qIndex--) {
|
||||
|
|
@ -1953,7 +1944,6 @@ static inline void VL_STREAMR_RRI(int lbits, VlQueue<T_Value>& to_q,
|
|||
const VlQueue<VlWide<N_Words>>& from_q, IData rd) VL_MT_SAFE {
|
||||
to_q.clear();
|
||||
|
||||
VL_CONSTEXPR_CXX17 size_t otherSize = 4 * N_Words;
|
||||
VL_CONSTEXPR_CXX17 size_t sizeOfThis = sizeof(T_Value);
|
||||
T_Value temp = 0;
|
||||
for (auto val : from_q) {
|
||||
|
|
|
|||
|
|
@ -337,6 +337,7 @@ public:
|
|||
|
||||
~VlProcess() {
|
||||
if (m_parentp) m_parentp->detach(this);
|
||||
if (t_currentp == this) t_currentp = m_parentp.get();
|
||||
}
|
||||
|
||||
void attach(VlProcess* childp) { m_children.insert(childp); }
|
||||
|
|
@ -2069,8 +2070,24 @@ struct VlNull final {
|
|||
operator T*() const {
|
||||
return nullptr;
|
||||
}
|
||||
template <class T>
|
||||
bool operator==(T* rhs) const {
|
||||
return !rhs;
|
||||
}
|
||||
template <class T>
|
||||
bool operator==(const T* rhs) const {
|
||||
return !rhs;
|
||||
}
|
||||
};
|
||||
inline bool operator==(const void* ptr, VlNull) { return !ptr; }
|
||||
|
||||
template <class T>
|
||||
inline bool operator==(T* lhs, VlNull) {
|
||||
return !lhs;
|
||||
}
|
||||
template <class T>
|
||||
inline bool operator==(const T* lhs, VlNull) {
|
||||
return !lhs;
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
// Verilog class reference container
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "V3AstUserAllocator.h"
|
||||
#include "V3Stats.h"
|
||||
#include "V3UniqueNames.h"
|
||||
|
||||
VL_DEFINE_DEBUG_FUNCTIONS;
|
||||
|
||||
|
|
@ -228,6 +229,9 @@ class AssertVisitor final : public VNVisitor {
|
|||
AstNode* m_failsp = nullptr; // Current fail statement
|
||||
AstNodeCoverOrAssert* m_assertp = nullptr; // Current assertion
|
||||
AstFinal* m_finalp = nullptr; // Current final block
|
||||
VDouble0 m_statLiftedCaseExprs; // Count of purified case expressions
|
||||
AstNodeFTask* m_ftaskp = nullptr; // Current function/task
|
||||
V3UniqueNames m_caseTempNames{"__VCase"};
|
||||
// Map from (expression, senTree) to AstAlways that computes delayed values of the expression
|
||||
std::unordered_map<VNRef<AstNodeExpr>, std::unordered_map<VNRef<AstSenTree>, AstAlways*>>
|
||||
m_modExpr2Sen2DelayedAlwaysp;
|
||||
|
|
@ -278,30 +282,26 @@ class AssertVisitor final : public VNVisitor {
|
|||
}
|
||||
VL_UNREACHABLE;
|
||||
}
|
||||
static string assertActionControlPrefix(VAssertDirectiveType directiveType) {
|
||||
const int controlled = !!(static_cast<int>(directiveType)
|
||||
& (static_cast<int>(VAssertDirectiveType::ASSERT)
|
||||
| static_cast<int>(VAssertDirectiveType::COVER)
|
||||
| static_cast<int>(VAssertDirectiveType::ASSUME)));
|
||||
const int checkRuntime = controlled & static_cast<int>(v3Global.opt.assertOn());
|
||||
return "("s + std::to_string(controlled ^ 1) + " || ("s + std::to_string(checkRuntime)
|
||||
+ " && "s;
|
||||
|
||||
static bool isControlled(VAssertDirectiveType directiveType) {
|
||||
return (static_cast<int>(directiveType)
|
||||
& (static_cast<int>(VAssertDirectiveType::ASSERT)
|
||||
| static_cast<int>(VAssertDirectiveType::COVER)
|
||||
| static_cast<int>(VAssertDirectiveType::ASSUME)));
|
||||
}
|
||||
static AstNodeExpr* assertPassOnCond(FileLine* fl, VAssertType type,
|
||||
VAssertDirectiveType directiveType, bool vacuous) {
|
||||
if (!isControlled(directiveType)) return new AstConst{fl, AstConst::BitTrue{}};
|
||||
if (!v3Global.opt.assertOn()) return new AstConst{fl, AstConst::BitFalse{}};
|
||||
return new AstCExpr{fl, AstCExpr::Pure{},
|
||||
assertActionControlPrefix(directiveType)
|
||||
+ assertCtlGetCall(assertPassOnQuery(vacuous), type, directiveType)
|
||||
+ "))"s,
|
||||
1};
|
||||
assertCtlGetCall(assertPassOnQuery(vacuous), type, directiveType), 1};
|
||||
}
|
||||
static AstNodeExpr* assertFailOnCond(FileLine* fl, VAssertType type,
|
||||
VAssertDirectiveType directiveType) {
|
||||
if (!isControlled(directiveType)) return new AstConst{fl, AstConst::BitTrue{}};
|
||||
if (!v3Global.opt.assertOn()) return new AstConst{fl, AstConst::BitFalse{}};
|
||||
return new AstCExpr{fl, AstCExpr::Pure{},
|
||||
assertActionControlPrefix(directiveType)
|
||||
+ assertCtlGetCall("ASSERT_CTL_FAIL_ON", type, directiveType)
|
||||
+ "))"s,
|
||||
1};
|
||||
assertCtlGetCall("ASSERT_CTL_FAIL_ON", type, directiveType), 1};
|
||||
}
|
||||
string assertDisplayMessage(const AstNode* nodep, const string& prefix, const string& message,
|
||||
VDisplayType severity) {
|
||||
|
|
@ -374,6 +374,7 @@ class AssertVisitor final : public VNVisitor {
|
|||
AstNodeIf* const newp = new AstIf{fl, condp, bodyp};
|
||||
newp->isBoundsCheck(true); // To avoid LATCH warning
|
||||
newp->user1(true); // Don't assert/cover this if
|
||||
newp->user2(true); // Mark as an assertOn() check
|
||||
return newp;
|
||||
}
|
||||
static AstNodeStmt* newIfAssertFailOn(AstNode* bodyp, VAssertDirectiveType directiveType,
|
||||
|
|
@ -385,6 +386,7 @@ class AssertVisitor final : public VNVisitor {
|
|||
AstNodeIf* const newp = new AstIf{fl, condp, bodyp};
|
||||
newp->isBoundsCheck(true); // To avoid LATCH warning
|
||||
newp->user1(true); // Don't assert/cover this if
|
||||
newp->user2(true); // Mark as an assertOn() check
|
||||
return newp;
|
||||
}
|
||||
|
||||
|
|
@ -696,10 +698,10 @@ class AssertVisitor final : public VNVisitor {
|
|||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
return;
|
||||
}
|
||||
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
iterateChildren(nodep);
|
||||
|
||||
if (nodep->user2()) {
|
||||
// Combine consecutive assertOn checks if possible
|
||||
if (AstIf* const backp = VN_CAST(nodep->backp(), If)) {
|
||||
|
|
@ -757,6 +759,28 @@ class AssertVisitor final : public VNVisitor {
|
|||
|
||||
//========== Case assertions
|
||||
void visit(AstCase* nodep) override {
|
||||
// Introduce temporary variable for AstCase if needed - it is done here and not in V3Case
|
||||
// because this phase is before V3Scope and V3Case is not. Doing it before V3Scope ensures
|
||||
// that V3Scope will take care of a scope creation
|
||||
// We also need to do it before V3Begin, co that pragmas like `unique0` also work correctly
|
||||
if (!nodep->exprp()->isPure()) {
|
||||
++m_statLiftedCaseExprs;
|
||||
FileLine* const fl = nodep->exprp()->fileline();
|
||||
AstVar* const varp = new AstVar{fl, VVarType::BLOCKTEMP, m_caseTempNames.get(nodep),
|
||||
nodep->exprp()->dtypep()};
|
||||
AstNodeExpr* const origp = nodep->exprp()->unlinkFrBack();
|
||||
nodep->addHereThisAsNext(
|
||||
new AstAssign{fl, new AstVarRef{fl, varp, VAccess::WRITE}, origp});
|
||||
nodep->exprp(new AstVarRef{fl, varp, VAccess::READ});
|
||||
if (m_ftaskp) {
|
||||
varp->funcLocal(true);
|
||||
varp->lifetime(VLifetime::AUTOMATIC_EXPLICIT);
|
||||
m_ftaskp->stmtsp()->addHereThisAsNext(varp);
|
||||
} else {
|
||||
m_modp->stmtsp()->addHereThisAsNext(varp);
|
||||
}
|
||||
VIsCached::clearCacheTree();
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
if (!nodep->user1SetOnce()) {
|
||||
bool has_default = false;
|
||||
|
|
@ -1182,6 +1206,9 @@ public:
|
|||
V3Stats::addStat("Assertions, $past variables", m_statPastVars);
|
||||
V3Stats::addStat("Assertions, assertOn checks combined", m_statAssertOnCombined);
|
||||
V3Stats::addStat("Assertions, assertOn checks hoisted", m_statAssertOnHoisted);
|
||||
V3Stats::addStat("Assertions, lifted impure case expressions", m_statLiftedCaseExprs);
|
||||
// Rewrites can change purity, e.g. by compiling out assertion statements with --no-assert
|
||||
VIsCached::clearCacheTree();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1000,8 +1000,8 @@ public:
|
|||
// this matters, the caller must handle the dtype difference as appropriate. If 'mergeDType' is
|
||||
// false, the returned VarScope will have _->dtypep()->sameTree(initp->dtypep()) return true.
|
||||
AstVarScope* findConst(AstConst* initp, bool mergeDType);
|
||||
// Rebuild hashes after potential removals
|
||||
void reCache();
|
||||
// Rebuild hashes and missing variable scopes after potential removals
|
||||
void rebuildVarScopesAndCache();
|
||||
};
|
||||
class AstConstraint final : public AstNode {
|
||||
// Constraint
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
// Routines for dumping dict fields (NOTE: due to leading ',' they can't be used for first field in
|
||||
|
|
@ -1779,14 +1780,28 @@ AstVarScope* AstConstPool::findConst(AstConst* initp, bool mergeDType) {
|
|||
return varScopep;
|
||||
}
|
||||
|
||||
void AstConstPool::reCache() {
|
||||
void AstConstPool::rebuildVarScopesAndCache() {
|
||||
m_tables.clear();
|
||||
m_consts.clear();
|
||||
std::unordered_map<const AstVar*, AstVarScope*> varScopeps;
|
||||
for (AstVarScope* vscp = m_scopep->varsp(); vscp; vscp = VN_CAST(vscp->nextp(), VarScope)) {
|
||||
AstNode* const valuep = vscp->varp()->valuep();
|
||||
const V3Hash hash = V3Hasher::uncachedHash(valuep);
|
||||
if (VN_IS(valuep, InitArray)) m_tables.emplace(hash.value(), vscp);
|
||||
if (VN_IS(valuep, Const)) m_consts.emplace(hash.value(), vscp);
|
||||
varScopeps.emplace(vscp->varp(), vscp);
|
||||
}
|
||||
for (AstNode* nodep = m_modp->stmtsp(); nodep; nodep = nodep->nextp()) {
|
||||
AstVar* const varp = VN_CAST(nodep, Var);
|
||||
if (!varp) continue;
|
||||
AstNode* const valuep = varp->valuep();
|
||||
if (!valuep) continue;
|
||||
const bool isTable = VN_IS(valuep, InitArray);
|
||||
const AstConst* const constp = VN_CAST(valuep, Const);
|
||||
if (!isTable && !constp) continue;
|
||||
AstVarScope*& vscp = varScopeps[varp];
|
||||
if (!vscp) {
|
||||
vscp = new AstVarScope{varp->fileline(), m_scopep, varp};
|
||||
m_scopep->addVarsp(vscp);
|
||||
}
|
||||
if (isTable) m_tables.emplace(V3Hasher::uncachedHash(valuep).value(), vscp);
|
||||
if (constp) m_consts.emplace(constp->num().toHash().value(), vscp);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -597,7 +597,7 @@ public:
|
|||
// We may have removed some datatypes, cleanup
|
||||
nodep->typeTablep()->repairCache();
|
||||
VIsCached::clearCacheTree(); // Removing assignments may affect isPure
|
||||
nodep->constPoolp()->reCache();
|
||||
nodep->constPoolp()->rebuildVarScopesAndCache();
|
||||
}
|
||||
~DeadVisitor() override {
|
||||
V3Stats::addStatSum("Optimizations, deadified FTasks", m_statFTasksDeadified);
|
||||
|
|
|
|||
|
|
@ -620,6 +620,12 @@ DfgVertex::DfgVertex(DfgGraph& dfg, VDfgType type, FileLine* flp, const DfgDataT
|
|||
dfg.addVertex(*this);
|
||||
}
|
||||
|
||||
bool DfgVertex::unsafe() const {
|
||||
if (is<DfgMux>()) return true;
|
||||
if (is<DfgArraySel>()) return !as<DfgArraySel>()->bitp()->is<DfgConst>();
|
||||
return false;
|
||||
}
|
||||
|
||||
void DfgVertex::typeCheck(const DfgGraph& dfg) const {
|
||||
|
||||
#define CHECK(cond, msg) \
|
||||
|
|
|
|||
|
|
@ -195,6 +195,8 @@ public:
|
|||
UASSERT_OBJ(m_dtype.isPacked(), this, "Non packed vertex has no 'width'");
|
||||
return m_dtype.size();
|
||||
}
|
||||
// Has terminating side-effect
|
||||
bool unsafe() const;
|
||||
|
||||
// Type check vertex (for debugging)
|
||||
void typeCheck(const DfgGraph& dfg) const;
|
||||
|
|
|
|||
|
|
@ -2269,7 +2269,7 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
}
|
||||
|
||||
void visit(DfgLogAnd* const vtxp) override {
|
||||
if (binary(vtxp)) return;
|
||||
if (binary(vtxp) || vtxp->rhsp()->unsafe()) return;
|
||||
|
||||
DfgVertex* const lhsp = vtxp->lhsp();
|
||||
DfgVertex* const rhsp = vtxp->rhsp();
|
||||
|
|
@ -2287,11 +2287,11 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
}
|
||||
|
||||
void visit(DfgLogIf* const vtxp) override {
|
||||
if (binary(vtxp)) return;
|
||||
if (binary(vtxp) || vtxp->rhsp()->unsafe()) return;
|
||||
}
|
||||
|
||||
void visit(DfgLogOr* const vtxp) override {
|
||||
if (binary(vtxp)) return;
|
||||
if (binary(vtxp) || vtxp->rhsp()->unsafe()) return;
|
||||
|
||||
DfgVertex* const lhsp = vtxp->lhsp();
|
||||
DfgVertex* const rhsp = vtxp->rhsp();
|
||||
|
|
@ -2890,13 +2890,13 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
}
|
||||
|
||||
if (vtxp->dtype() == m_bitDType) {
|
||||
if (isSame(condp, thenp)) { // a ? a : b becomes a | b
|
||||
if (isSame(condp, thenp) && !elsep->unsafe()) { // a ? a : b becomes a | b
|
||||
APPLYING(REPLACE_COND_WITH_THEN_BRANCH_COND) {
|
||||
replace(make<DfgOr>(vtxp, condp, elsep));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (isSame(condp, elsep)) { // a ? b : a becomes a & b
|
||||
if (isSame(condp, elsep) && !thenp->unsafe()) { // a ? b : a becomes a & b
|
||||
APPLYING(REPLACE_COND_WITH_ELSE_BRANCH_COND) {
|
||||
replace(make<DfgAnd>(vtxp, condp, thenp));
|
||||
return;
|
||||
|
|
@ -2905,28 +2905,28 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
}
|
||||
|
||||
if (vtxp->width() <= VL_QUADSIZE) {
|
||||
if (isZero(thenp)) { // a ? 0 : b becomes ~a & b
|
||||
if (isZero(thenp) && !elsep->unsafe()) { // a ? 0 : b becomes ~a & b
|
||||
APPLYING(REPLACE_COND_WITH_THEN_BRANCH_ZERO) {
|
||||
DfgVertex* const maskp = replicate(vtxp, make<DfgNot>(condp, condp));
|
||||
replace(make<DfgAnd>(vtxp, maskp, elsep));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (isOnes(thenp)) { // a ? 1 : b becomes a | b
|
||||
if (isOnes(thenp) && !elsep->unsafe()) { // a ? 1 : b becomes a | b
|
||||
APPLYING(REPLACE_COND_WITH_THEN_BRANCH_ONES) {
|
||||
DfgVertex* const maskp = replicate(vtxp, condp);
|
||||
replace(make<DfgOr>(vtxp, maskp, elsep));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (isZero(elsep)) { // a ? b : 0 becomes a & b
|
||||
if (isZero(elsep) && !thenp->unsafe()) { // a ? b : 0 becomes a & b
|
||||
APPLYING(REPLACE_COND_WITH_ELSE_BRANCH_ZERO) {
|
||||
DfgVertex* const maskp = replicate(vtxp, condp);
|
||||
replace(make<DfgAnd>(vtxp, maskp, thenp));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (isOnes(elsep)) { // a ? b : 1 becomes ~a | b
|
||||
if (isOnes(elsep) && !thenp->unsafe()) { // a ? b : 1 becomes ~a | b
|
||||
APPLYING(REPLACE_COND_WITH_ELSE_BRANCH_ONES) {
|
||||
DfgVertex* const maskp = replicate(vtxp, make<DfgNot>(condp, condp));
|
||||
replace(make<DfgOr>(vtxp, maskp, thenp));
|
||||
|
|
@ -2935,7 +2935,8 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
}
|
||||
|
||||
if (DfgOr* const tOrp = thenp->cast<DfgOr>()) {
|
||||
if (isSame(tOrp->lhsp(), elsep)) { // a ? b | c : b becomes b | (a & c)
|
||||
if (isSame(tOrp->lhsp(), elsep)
|
||||
&& !tOrp->rhsp()->unsafe()) { // a ? b | c : b becomes b | (a & c)
|
||||
APPLYING(REPLACE_COND_THEN_OR_LHS) {
|
||||
DfgVertex* const maskp = replicate(vtxp, condp);
|
||||
DfgAnd* const andp = make<DfgAnd>(vtxp, maskp, tOrp->rhsp());
|
||||
|
|
@ -2943,7 +2944,8 @@ class V3DfgPeephole final : public DfgVisitor {
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (isSame(tOrp->rhsp(), elsep)) { // a ? b | c : c becomes c | (a & b)
|
||||
if (isSame(tOrp->rhsp(), elsep)
|
||||
&& !tOrp->lhsp()->unsafe()) { // a ? b | c : c becomes c | (a & b)
|
||||
APPLYING(REPLACE_COND_THEN_OR_RHS) {
|
||||
DfgVertex* const maskp = replicate(vtxp, condp);
|
||||
DfgAnd* const andp = make<DfgAnd>(vtxp, maskp, tOrp->lhsp());
|
||||
|
|
|
|||
|
|
@ -683,7 +683,8 @@ class EmitCHeader final : public EmitCConstInit {
|
|||
if (v3Global.opt.mtasks()) puts("#include \"verilated_threads.h\"\n");
|
||||
if (v3Global.opt.savable()) puts("#include \"verilated_save.h\"\n");
|
||||
if (v3Global.opt.coverage()) puts("#include \"verilated_cov.h\"\n");
|
||||
if (v3Global.opt.coverage()) puts("#include \"verilated_covergroup.h\"\n");
|
||||
if (v3Global.opt.coverage() || v3Global.useCovergroup())
|
||||
puts("#include \"verilated_covergroup.h\"\n");
|
||||
if (v3Global.usesTiming()) puts("#include \"verilated_timing.h\"\n");
|
||||
if (v3Global.useRandomizeMethods()) puts("#include \"verilated_random.h\"\n");
|
||||
if (v3Global.usesForce()) puts("#include \"verilated_force.h\"\n");
|
||||
|
|
|
|||
|
|
@ -104,6 +104,8 @@ private:
|
|||
puts("\n");
|
||||
|
||||
if (v3Global.opt.vpi()) {
|
||||
// VPI shared libraries requested via +verilator+vpi+<lib> are loaded by
|
||||
// contextp->commandArgs() above, before the statically-linked startup routines.
|
||||
puts("// Hook VPI startup routines and invoke callback\n");
|
||||
puts("if (vlog_startup_routines) {\n");
|
||||
puts(/**/ "for (auto routinep = &vlog_startup_routines[0]; *routinep; routinep++)"
|
||||
|
|
|
|||
|
|
@ -70,7 +70,8 @@ class EmitCModel final : public EmitCFunc {
|
|||
if (v3Global.opt.mtasks()) puts("#include \"verilated_threads.h\"\n");
|
||||
if (v3Global.opt.savable()) puts("#include \"verilated_save.h\"\n");
|
||||
if (v3Global.opt.coverage()) puts("#include \"verilated_cov.h\"\n");
|
||||
if (v3Global.opt.coverage()) puts("#include \"verilated_covergroup.h\"\n");
|
||||
if (v3Global.opt.coverage() || v3Global.useCovergroup())
|
||||
puts("#include \"verilated_covergroup.h\"\n");
|
||||
if (v3Global.dpi()) puts("#include \"svdpi.h\"\n");
|
||||
|
||||
// Declare foreign instances up front to make C++ happy
|
||||
|
|
|
|||
|
|
@ -567,6 +567,12 @@ public:
|
|||
of.puts("VM_TRACE_VCD = ");
|
||||
of.puts(v3Global.opt.traceEnabledVcd() ? "1" : "0");
|
||||
of.puts("\n");
|
||||
of.puts("# VPI enabled? 0/1 (from --vpi)\n");
|
||||
of.puts("VM_VPI = ");
|
||||
of.puts(v3Global.opt.vpi() ? "1" : "0");
|
||||
of.puts("\n");
|
||||
// Link flags for runtime VPI library loading are emitted by emitOverallMake() after
|
||||
// verilated.mk is included (so $(CFG_LDFLAGS_DYNAMIC)/$(CFG_LDLIBS_DYNAMIC) are defined).
|
||||
|
||||
of.puts("\n### Object file lists...\n");
|
||||
for (int support = 0; support < 3; ++support) {
|
||||
|
|
@ -729,6 +735,17 @@ public:
|
|||
of.puts("\n### Executable rules... (from --exe)\n");
|
||||
of.puts("VPATH += $(VM_USER_DIR)\n");
|
||||
of.puts("\n");
|
||||
|
||||
if (v3Global.opt.vpi()) {
|
||||
// Runtime VPI library loading (+verilator+vpi+<lib>) needs the executable to
|
||||
// export its VPI symbols so the dlopen'd library can resolve them, plus the
|
||||
// dl library for dlopen/dlsym. The exact flags are probed at configure time
|
||||
// (CFG_LDFLAGS_DYNAMIC / CFG_LDLIBS_DYNAMIC in verilated.mk).
|
||||
of.puts("# Runtime VPI library loading (+verilator+vpi+) link requirements\n");
|
||||
of.puts("LDFLAGS += $(CFG_LDFLAGS_DYNAMIC)\n");
|
||||
of.puts("LDLIBS += $(CFG_LDLIBS_DYNAMIC)\n");
|
||||
of.puts("\n");
|
||||
}
|
||||
}
|
||||
|
||||
const string compilerIncludePch
|
||||
|
|
|
|||
|
|
@ -245,7 +245,8 @@ std::vector<std::string> V3Global::verilatedCppFiles() {
|
|||
if (v3Global.opt.vpi()) result.emplace_back("verilated_vpi.cpp");
|
||||
if (v3Global.opt.savable()) result.emplace_back("verilated_save.cpp");
|
||||
if (v3Global.opt.coverage()) result.emplace_back("verilated_cov.cpp");
|
||||
if (v3Global.opt.coverage()) result.emplace_back("verilated_covergroup.cpp");
|
||||
if (v3Global.opt.coverage() || v3Global.useCovergroup())
|
||||
result.emplace_back("verilated_covergroup.cpp");
|
||||
for (const string& base : v3Global.opt.traceSourceBases())
|
||||
result.emplace_back(base + "_c.cpp");
|
||||
if (v3Global.usesProbDist()) result.emplace_back("verilated_probdist.cpp");
|
||||
|
|
|
|||
|
|
@ -1013,18 +1013,23 @@ public:
|
|||
if (checkUnresolvedRef(VN_CAST(dtypep, RefDType))) return true;
|
||||
} else if (const AstParamTypeDType* const paramTypep
|
||||
= VN_CAST(symp->nodep(), ParamTypeDType)) {
|
||||
// ParamTypeDType child may be wrapped in RequireDType or unwrapped
|
||||
// Before V3Param the declared default is in childDTypep (possibly
|
||||
// wrapped in a RequireDType); after V3Param it is consumed and the
|
||||
// bound type is the resolved data type, e.g. a type parameter
|
||||
// inherited from a specialized base class (REQ #(Item) -> class Item).
|
||||
AstNode* childp = paramTypep->childDTypep();
|
||||
if (const AstRequireDType* const reqp = VN_CAST(childp, RequireDType)) {
|
||||
childp = reqp->lhsp();
|
||||
}
|
||||
if (isValidTypeNode(childp)) return true;
|
||||
if (checkUnresolvedRef(VN_CAST(childp, RefDType))) return true;
|
||||
const AstNode* const checkp = childp ? childp : paramTypep->skipRefp();
|
||||
if (isValidTypeNode(checkp)) return true;
|
||||
if (checkUnresolvedRef(VN_CAST(checkp, RefDType))) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
VSymEnt* resolveClassOrPackage(VSymEnt* lookSymp, AstClassOrPackageRef* nodep, bool fallback,
|
||||
bool classOnly, const string& forWhat) {
|
||||
bool classOnly, const string& forWhat,
|
||||
bool deferIfUnresolved = false) {
|
||||
if (nodep->classOrPackageSkipp()) return getNodeSym(nodep->classOrPackageSkipp());
|
||||
VSymEnt* foundp;
|
||||
VSymEnt* searchSymp = lookSymp;
|
||||
|
|
@ -1050,6 +1055,7 @@ public:
|
|||
nodep->classOrPackageNodep(foundp->nodep());
|
||||
return foundp;
|
||||
}
|
||||
if (deferIfUnresolved) return nullptr;
|
||||
const string suggest
|
||||
= suggestSymFallback(lookSymp, nodep->name(), LinkNodeMatcherClassOrPackage{});
|
||||
nodep->v3error((classOnly ? "Class" : "Package/class")
|
||||
|
|
@ -4758,8 +4764,9 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
|||
VL_RESTORER(m_pinSymp);
|
||||
|
||||
if (!nodep->classOrPackageSkipp() && nodep->name() != "local::") {
|
||||
const bool deferIfUnresolved = m_statep->forPrimary() && m_insideClassExtParam;
|
||||
m_statep->resolveClassOrPackage(m_ds.m_dotSymp, nodep, m_ds.m_dotPos != DP_PACKAGE,
|
||||
false, ":: reference");
|
||||
false, ":: reference", deferIfUnresolved);
|
||||
}
|
||||
|
||||
// ClassRef's have pins, so track
|
||||
|
|
|
|||
|
|
@ -307,6 +307,7 @@ class LinkIncVisitor final : public VNVisitor {
|
|||
return new AstSub{nodep->fileline(), lhsp, rhsp};
|
||||
case AstAssignCompound::operation::Xor:
|
||||
return new AstXor{nodep->fileline(), lhsp, rhsp};
|
||||
default:; // Error below // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
nodep->v3fatalSrc("Unhandled compound assignment operation");
|
||||
|
|
|
|||
|
|
@ -542,7 +542,7 @@ bool V3Options::fileStatNormal(const string& filename) {
|
|||
}
|
||||
|
||||
string V3Options::fileExists(const string& filename) {
|
||||
// Surprisingly, for VCS and other simulators, this process
|
||||
// Surprisingly, for some other simulators, this process
|
||||
// is quite slow; presumably because of re-reading each directory
|
||||
// many times. So we read a whole dir at once and cache it
|
||||
|
||||
|
|
|
|||
|
|
@ -1053,7 +1053,7 @@ class ConstraintExprVisitor final : public VNVisitor {
|
|||
nodep->user1(false);
|
||||
return;
|
||||
}
|
||||
bool anyChild = false;
|
||||
int anyChild = false; // Used as bool
|
||||
if (AstNodeExpr* const cp = VN_CAST(nodep->op1p(), NodeExpr)) {
|
||||
propagateUser1InlineRecurse(cp);
|
||||
anyChild |= cp->user1();
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ void VlcTop::writeInfo(const string& filename) {
|
|||
// FNF:<number_functions_found>
|
||||
// FNH:<number_functions_hit>
|
||||
// Branches:
|
||||
// BRDA:<line_number>,<block_number>,<branch_number>,<taken_count_or_-_for_zero>
|
||||
// BRDA:<line_number>,<block_number>,<branch>,<taken_count_or_-_for_zero>
|
||||
// BRF:<number_of_branches_found>
|
||||
// BRH:<number_of_branches_hit>
|
||||
// Line counts:
|
||||
|
|
@ -273,8 +273,14 @@ void VlcTop::writeInfo(const string& filename) {
|
|||
for (const VlcPoint* point : infoPoints) {
|
||||
os << "BRDA:" << sc.lineno() << ",";
|
||||
os << "0,";
|
||||
os << point_num << ",";
|
||||
os << point->count() << "\n";
|
||||
if (point->comment().empty()) {
|
||||
os << point_num;
|
||||
} else {
|
||||
std::string comment(point->comment());
|
||||
std::replace(comment.begin(), comment.end(), ',', '_');
|
||||
os << comment;
|
||||
}
|
||||
os << "," << point->count() << "\n";
|
||||
|
||||
branchesHit += opt.countOk(point->count());
|
||||
++point_num;
|
||||
|
|
|
|||
|
|
@ -33,9 +33,7 @@ module t (
|
|||
|
||||
initial begin
|
||||
`checkh($dimensions (array_unpk), 3);
|
||||
`ifndef VCS
|
||||
`checkh($unpacked_dimensions (array_unpk), 2); // IEEE 2009
|
||||
`endif
|
||||
`checkh($bits (array_unpk), 2*2*2);
|
||||
`checkh($low (array_unpk), 2);
|
||||
`checkh($high (array_unpk), 3);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ module t (
|
|||
assert property (@(posedge clk) always [2:$] a_low) else low2_fail_q.push_back(cyc);
|
||||
|
||||
// a_drop is high then drops at cyc 5 and stays low: deterministic single
|
||||
// transition, so Verilator and Questa agree on the failing ticks exactly.
|
||||
// transition, so Verilator and others agree on the failing ticks exactly.
|
||||
assert property (@(posedge clk) always [2:$] a_drop) else drop_fail_q.push_back(cyc);
|
||||
|
||||
always @(posedge clk) begin
|
||||
|
|
@ -43,12 +43,12 @@ module t (
|
|||
if (cyc >= 4) a_drop <= 1'b0;
|
||||
if (cyc == 19) begin
|
||||
// Counts pinned to Verilator (NFA per-cycle reject). For all-fail windows
|
||||
// Questa is one lower (it does not fire the end-of-sim tick); see the sva
|
||||
// others are one lower (it does not fire the end-of-sim tick); see the sva
|
||||
// lessons "multi-cycle end-of-simulation offset" note.
|
||||
`checkd(high_fail_q.size(), 0); // Questa: 0
|
||||
`checkd(low0_fail_q.size(), 20); // Questa: 19
|
||||
`checkd(low2_fail_q.size(), 18); // Questa: 17
|
||||
`checkd(drop_fail_q[0], 5); // first fail tick: a_drop sampled low from cyc 5
|
||||
`checkd(high_fail_q.size(), 0);
|
||||
`checkd(low0_fail_q.size(), 20); // All others: 19
|
||||
`checkd(low2_fail_q.size(), 18); // All others: 17
|
||||
`checkd(drop_fail_q[0], 5); // All others: 6; first fail tick: a_drop sampled low from cyc 5
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
|||
|
|
@ -66,12 +66,12 @@ module t (
|
|||
end
|
||||
else if (cyc == 99) begin
|
||||
`checkh(crc, 64'hc77bb9b3784ea091);
|
||||
`checkd(count_fail1, 66); // Questa: 66
|
||||
`checkd(count_fail2, 69); // Questa: 69
|
||||
`checkd(count_fail3, 26); // Questa: 26
|
||||
`checkd(count_fail4, 66); // Questa: 66
|
||||
`checkd(count_fail5, 80); // Questa: 80
|
||||
`checkd(count_fail6, 27); // Questa: 27
|
||||
`checkd(count_fail1, 66);
|
||||
`checkd(count_fail2, 69);
|
||||
`checkd(count_fail3, 26);
|
||||
`checkd(count_fail4, 66);
|
||||
`checkd(count_fail5, 80);
|
||||
`checkd(count_fail6, 27);
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
|||
|
|
@ -95,23 +95,23 @@ module t (
|
|||
end
|
||||
else if (cyc == 99) begin
|
||||
`checkh(crc, 64'hc77bb9b3784ea091);
|
||||
`checkd(count_fail1, 5); // Questa: 5
|
||||
`checkd(count_fail2, 25); // Questa: 25
|
||||
`checkd(count_fail3, 9); // Questa: 9
|
||||
`checkd(count_fail4, 49); // Questa: 49
|
||||
`checkd(count_fail5, 0); // Questa: 0
|
||||
// NFA merge-node range [*M:N] over-counts rejects (Questa: 51); match
|
||||
`checkd(count_fail1, 5);
|
||||
`checkd(count_fail2, 25); // One other sim: 19
|
||||
`checkd(count_fail3, 9);
|
||||
`checkd(count_fail4, 49);
|
||||
`checkd(count_fail5, 0);
|
||||
// NFA merge-node range [*M:N] over-counts rejects; match
|
||||
// detection is correct, only reject counting is imprecise
|
||||
`checkd(count_fail6, 59);
|
||||
`checkd(count_fail7, 51); // Questa: 51
|
||||
`checkd(count_fail8, 20); // Questa: 20
|
||||
`checkd(count_fail6, 59); // All other sims: 51
|
||||
`checkd(count_fail7, 51);
|
||||
`checkd(count_fail8, 20);
|
||||
// IEEE 1800-2023 16.9.2 permits empty match of [*0]; NFA reports
|
||||
// rejects on each tick while Questa suppresses (Questa: 20)
|
||||
`checkd(count_fail9, 49);
|
||||
`checkd(count_fail10, 59); // Questa: 59
|
||||
// rejects on each tick while others suppress
|
||||
`checkd(count_fail9, 49); // Most others: 20, one other 49
|
||||
`checkd(count_fail10, 59);
|
||||
// a[*] ##1 b: NFA treats unbounded [*] as liveness (no reject);
|
||||
// Questa treats as definite antecedent (Questa: 29)
|
||||
`checkd(count_fail11, 0);
|
||||
// Should be definite antecedent
|
||||
`checkd(count_fail11, 0); // All other sims: 29
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ module t (
|
|||
else if (cyc == 99) begin
|
||||
`checkh(crc, 64'hc77bb9b3784ea091);
|
||||
`checkd(count_fail_257, 0);
|
||||
// Questa: 31 -- pre-existing ~26.5% NFA reject gap on |-> ##1 [*N]
|
||||
`checkd(count_fail_513, 23);
|
||||
// Mismatch due to pre-existing ~26.5% NFA reject gap on |-> ##1 [*N]
|
||||
`checkd(count_fail_513, 23); // All other sims: 31
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
`ifdef verilator
|
||||
`define no_optimize(v) $c(v)
|
||||
`else
|
||||
|
|
@ -12,7 +14,7 @@
|
|||
`endif
|
||||
// verilog_format: on
|
||||
|
||||
module t ( /*AUTOARG*/);
|
||||
module t;
|
||||
logic clk = 0;
|
||||
int imm_fails = 0, conc_fails = 0;
|
||||
logic a = 1'b1; // antecedent always true
|
||||
|
|
@ -58,11 +60,8 @@ module t ( /*AUTOARG*/);
|
|||
end
|
||||
|
||||
final begin
|
||||
// Concrete counts cross-checked against Questa 2022.3: imm_fails=5 conc_fails=7.
|
||||
if (imm_fails != 5 || conc_fails != 7) begin
|
||||
$display("%%Error: imm_fails=%0d (exp 5) conc_fails=%0d (exp 7)", imm_fails, conc_fails);
|
||||
$stop;
|
||||
end
|
||||
`checkd(imm_fails, 5);
|
||||
`checkd(conc_fails, 7); // Other sims: 7 or 1
|
||||
$write("*-* All Finished *-*\n");
|
||||
end
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ interface AssertCtlIface;
|
|||
$assertcontrol(3, 2, 1);
|
||||
endfunction
|
||||
function void fail_check();
|
||||
assert (0) `stop; else fails++;
|
||||
assert (0) `stop;
|
||||
else fails++;
|
||||
endfunction
|
||||
function void run_checks();
|
||||
assert_off();
|
||||
|
|
@ -69,12 +70,13 @@ module t;
|
|||
$assertcontrol(3, 2, 1);
|
||||
endfunction
|
||||
function void fail_check();
|
||||
assert (0) `stop; else class_fails++;
|
||||
assert (0) `stop;
|
||||
else class_fails++;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
AssertCtlClass assert_ctl_class;
|
||||
AssertCtlIface assert_ctl_iface();
|
||||
AssertCtlIface assert_ctl_iface ();
|
||||
virtual AssertCtlIface v_assert_ctl_iface = assert_ctl_iface;
|
||||
|
||||
always #5 clk = !clk;
|
||||
|
|
@ -84,17 +86,17 @@ module t;
|
|||
|
||||
assert property (@(posedge clk) 1'b0 |-> ##1 1'b1) begin
|
||||
vacuous_passes++;
|
||||
end else
|
||||
`stop;
|
||||
end
|
||||
else `stop;
|
||||
|
||||
assert property (@(posedge clk) 1'b1 |-> ##1 1'b1) begin
|
||||
nonvacuous_passes++;
|
||||
end else
|
||||
`stop;
|
||||
end
|
||||
else `stop;
|
||||
|
||||
assert property (@(posedge clk) 1'b1 |-> ##1 1'b0) begin
|
||||
end else
|
||||
concurrent_fails++;
|
||||
end
|
||||
else concurrent_fails++;
|
||||
|
||||
task automatic tick_and_check(input int exp_vacuous, input int exp_nonvacuous,
|
||||
input int exp_concurrent_fails);
|
||||
|
|
@ -110,62 +112,73 @@ module t;
|
|||
|
||||
$assertcontrol(4, 16, 1);
|
||||
$assertcontrol(5, 16, 1);
|
||||
$assertcontrol(3*`IMPURE_ONE, 2*`IMPURE_ONE);
|
||||
$assertcontrol(3 * `IMPURE_ONE, 2 * `IMPURE_ONE);
|
||||
|
||||
$assertcontrol(3, 255, 7);
|
||||
$assertcontrol(6, 255, 7);
|
||||
$assertcontrol(8, 255, 7);
|
||||
|
||||
assert (1) imm_passes++; else `stop;
|
||||
assert (1) imm_passes++;
|
||||
else `stop;
|
||||
`checkd(imm_passes, 1);
|
||||
|
||||
$assertcontrol(1, 2, 1);
|
||||
$assertcontrol(4, 2, 1);
|
||||
assert (1) imm_passes++; else `stop;
|
||||
assert (1) imm_passes++;
|
||||
else `stop;
|
||||
`checkd(imm_passes, 2);
|
||||
|
||||
$assertcontrol(2, 2, 1);
|
||||
$assertcontrol(4, 2, 1);
|
||||
assert (1) imm_passes++; else `stop;
|
||||
assert (1) imm_passes++;
|
||||
else `stop;
|
||||
`checkd(imm_passes, 2);
|
||||
|
||||
$assertcontrol(3, 2, 1);
|
||||
|
||||
$assertcontrol(1, 2, 1);
|
||||
$assertcontrol(7, 2, 1);
|
||||
assert (1) imm_passes++; else `stop;
|
||||
assert (1) imm_passes++;
|
||||
else `stop;
|
||||
`checkd(imm_passes, 3);
|
||||
|
||||
$assertcontrol(2, 2, 1);
|
||||
$assertcontrol(7, 2, 1);
|
||||
assert (1) imm_passes++; else `stop;
|
||||
assert (1) imm_passes++;
|
||||
else `stop;
|
||||
`checkd(imm_passes, 3);
|
||||
|
||||
$assertcontrol(10, 2, 1);
|
||||
assert (1) imm_passes++; else `stop;
|
||||
assert (1) imm_passes++;
|
||||
else `stop;
|
||||
`checkd(imm_passes, 4);
|
||||
|
||||
$assertcontrol(11, 2, 1);
|
||||
assert (1) imm_passes++; else `stop;
|
||||
assert (1) imm_passes++;
|
||||
else `stop;
|
||||
`checkd(imm_passes, 5);
|
||||
|
||||
$assertcontrol(6, 2, 1);
|
||||
|
||||
assert (0) `stop; else imm_fails++;
|
||||
assert (0) `stop;
|
||||
else imm_fails++;
|
||||
`checkd(imm_fails, 1);
|
||||
|
||||
$assertcontrol(1, 2, 1);
|
||||
$assertcontrol(9, 2, 1);
|
||||
assert (0) `stop; else imm_fails++;
|
||||
assert (0) `stop;
|
||||
else imm_fails++;
|
||||
`checkd(imm_fails, 2);
|
||||
|
||||
$assertcontrol(2, 2, 1);
|
||||
$assertcontrol(9, 2, 1);
|
||||
assert (0) `stop; else imm_fails++;
|
||||
assert (0) `stop;
|
||||
else imm_fails++;
|
||||
`checkd(imm_fails, 2);
|
||||
|
||||
$assertcontrol(8, 2, 1);
|
||||
assert (0) `stop; else imm_fails++;
|
||||
assert (0) `stop;
|
||||
else imm_fails++;
|
||||
`checkd(imm_fails, 3);
|
||||
|
||||
assert_ctl_class.assert_off();
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
module t;
|
||||
initial begin
|
||||
$assertcontrol(100*`IMPURE_ONE);
|
||||
$assertcontrol(100 * `IMPURE_ONE);
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -16,10 +16,8 @@ module t (
|
|||
integer action_hits = 0;
|
||||
integer cyc = 0;
|
||||
|
||||
assert property (@(posedge clk) ##1 1'b1)
|
||||
action_hits++;
|
||||
else
|
||||
action_hits--;
|
||||
assert property (@(posedge clk) ##1 1'b1) action_hits++;
|
||||
else action_hits--;
|
||||
|
||||
always @(posedge clk) begin
|
||||
cyc++;
|
||||
|
|
|
|||
|
|
@ -75,14 +75,14 @@ module t (
|
|||
end
|
||||
else if (cyc == 99) begin
|
||||
`checkh(crc, 64'hc77bb9b3784ea091);
|
||||
`checkd(count_fail1, 20); // Questa: 20
|
||||
`checkd(count_fail2, 25); // Questa: 25
|
||||
`checkd(count_fail3, 19); // Questa: 19
|
||||
`checkd(count_fail4, 0); // Questa: 0
|
||||
`checkd(count_fail5, 20); // Questa: 20
|
||||
`checkd(count_fail6, 25); // Questa: 25
|
||||
`checkd(count_fail7, 20); // Questa: 20
|
||||
`checkd(count_fail8, 20); // Questa: 20
|
||||
`checkd(count_fail1, 20);
|
||||
`checkd(count_fail2, 25);
|
||||
`checkd(count_fail3, 19);
|
||||
`checkd(count_fail4, 0);
|
||||
`checkd(count_fail5, 20);
|
||||
`checkd(count_fail6, 25);
|
||||
`checkd(count_fail7, 20);
|
||||
`checkd(count_fail8, 20);
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
|||
|
|
@ -56,10 +56,10 @@ module t (
|
|||
end
|
||||
else if (cyc == 99) begin
|
||||
`checkh(crc, 64'hc77bb9b3784ea091);
|
||||
`checkd(count_fail1, 34); // Questa: 29
|
||||
`checkd(count_fail2, 27); // Questa: 32
|
||||
`checkd(count_fail3, 25); // Questa: 29
|
||||
`checkd(count_fail4, 0); // Questa: 0
|
||||
`checkd(count_fail1, 34); // Other sims: 29, one other: 20
|
||||
`checkd(count_fail2, 27); // Other sims: 32, one other: 25
|
||||
`checkd(count_fail3, 25); // Other sims: 29, one other: 25
|
||||
`checkd(count_fail4, 0);
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ test.compile(verilator_flags2=['--binary', '--stats'])
|
|||
|
||||
test.execute(check_finished=True)
|
||||
|
||||
test.file_grep(test.stats, r'Assertions, assertOn checks combined\s+(\d+)', 3)
|
||||
test.file_grep(test.stats, r'Assertions, assertOn checks hoisted\s+(\d+)', 16)
|
||||
test.file_grep(test.stats, r'Assertions, assertOn checks combined\s+(\d+)', 4)
|
||||
test.file_grep(test.stats, r'Assertions, assertOn checks hoisted\s+(\d+)', 42)
|
||||
|
||||
test.passes()
|
||||
|
|
|
|||
|
|
@ -57,9 +57,8 @@ module t (
|
|||
end
|
||||
else if (cyc == 99) begin
|
||||
`checkh(crc, 64'hc77bb9b3784ea091);
|
||||
// Questa 2022.3 golden: count_gated=5, count_ref=12.
|
||||
`checkd(count_gated, 5);
|
||||
`checkd(count_ref, 12);
|
||||
`checkd(count_gated, 5); // Other sims same, one other: 4
|
||||
`checkd(count_ref, 12); // Other sims same, one other: 10
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
|||
|
|
@ -44,10 +44,9 @@ module t (
|
|||
end
|
||||
|
||||
// Counts read in final (Postponed) to avoid same-timestep races.
|
||||
// Concrete Verilator counts; Questa: fails_single=17 fails_multi=17
|
||||
final begin
|
||||
`checkd(fails_single, 17);
|
||||
`checkd(fails_multi, 17);
|
||||
`checkd(fails_single, 17); // Other sims: 0
|
||||
`checkd(fails_multi, 17); // Other sims: 0
|
||||
$write("*-* All Finished *-*\n");
|
||||
end
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -33,13 +33,12 @@ module t;
|
|||
task automatic run_pass();
|
||||
assert (1) begin
|
||||
pass_count++;
|
||||
end else
|
||||
`stop;
|
||||
end
|
||||
else `stop;
|
||||
endtask
|
||||
|
||||
task automatic run_fail();
|
||||
assert (0)
|
||||
`stop;
|
||||
assert (0) `stop;
|
||||
else begin
|
||||
fail_count++;
|
||||
end
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ test.compile(verilator_flags2=['--stats'])
|
|||
|
||||
test.execute()
|
||||
|
||||
test.file_grep(test.stats, r'LiftExpr, lifted calls\s+(\d+)', 3)
|
||||
test.file_grep(test.stats, r'LiftExpr, lifted calls\s+(\d+)', 2)
|
||||
test.file_grep(test.stats, r'Assertions, lifted impure case expressions\s+(\d+)', 2)
|
||||
|
||||
test.passes()
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ test.compile(verilator_flags2=['--stats'])
|
|||
|
||||
test.execute()
|
||||
|
||||
test.file_grep(test.stats, r'LiftExpr, lifted calls\s+(\d+)', 3)
|
||||
test.file_grep(test.stats, r'LiftExpr, lifted calls\s+(\d+)', 2)
|
||||
test.file_grep(test.stats, r'Assertions, lifted impure case expressions\s+(\d+)', 2)
|
||||
|
||||
test.passes()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# This program is free software; you can redistribute it and/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-FileCopyrightText: 2026 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
test.compile(verilator_flags2=['--binary', '-Wno-WIDTHTRUNC'])
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
interface irq_if (
|
||||
input logic clk,
|
||||
input logic resetn
|
||||
);
|
||||
logic irq;
|
||||
logic te;
|
||||
logic halted;
|
||||
logic fault;
|
||||
logic wfi;
|
||||
clocking cb @(posedge clk);
|
||||
default input #1step output #2ns;
|
||||
output irq;
|
||||
output te;
|
||||
input halted;
|
||||
input fault;
|
||||
input wfi;
|
||||
endclocking
|
||||
modport DUT_IRQ_PORT(input clk, resetn, output halted, fault, wfi);
|
||||
endinterface
|
||||
class base_test_class;
|
||||
function int foo();
|
||||
endfunction
|
||||
virtual irq_if.DUT_IRQ_PORT irq_vif;
|
||||
function new(string name);
|
||||
endfunction
|
||||
virtual function void build_phase();
|
||||
if (irq_vif == null) begin
|
||||
if (foo()) $display();
|
||||
end
|
||||
endfunction
|
||||
endclass
|
||||
module tb_top;
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# This program is free software; you can redistribute it and/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-FileCopyrightText: 2024 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile()
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Sergey Chusov
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// A factory-like static method, as used by UVM's type_id::create().
|
||||
class registry #(type T = int);
|
||||
static function T create();
|
||||
T r = new;
|
||||
return r;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class item;
|
||||
int val;
|
||||
typedef registry#(item) type_id;
|
||||
function new();
|
||||
val = 42;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
class seq_base #(type REQ = int, type RSP = REQ);
|
||||
REQ req;
|
||||
endclass
|
||||
|
||||
// Non-parameterized class extending a parameterized base.
|
||||
// REQ is a type parameter inherited from the (specialized) base class and is
|
||||
// here used as a '::' class scope: REQ::type_id::create(). Resolving REQ in
|
||||
// this position requires deferring until after V3Param has bound REQ to item.
|
||||
class seq extends seq_base #(item);
|
||||
function int make();
|
||||
REQ r;
|
||||
r = REQ::type_id::create();
|
||||
return r.val;
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
module t;
|
||||
seq s;
|
||||
initial begin
|
||||
s = new;
|
||||
if (s.make() != 42) $stop;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -21,7 +21,7 @@ class C;
|
|||
endclass
|
||||
|
||||
class D;
|
||||
my_t a; // second use of the type name after the shadowing variable...
|
||||
my_t a; // second use of the type name after the shadowing variable...
|
||||
my_t my_t; // ... is also legal; both resolve to the $unit typedef
|
||||
endclass
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
test.scenarios('linter')
|
||||
|
||||
test.lint(verilator_flags2=["-libmap t/t_config_libmap_inc.map"],
|
||||
|
|
|
|||
|
|
@ -8,17 +8,21 @@
|
|||
// values only within the declared distribution and cover all buckets.
|
||||
|
||||
// verilog_format: off
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
// foreach (a[i]) if (gate) a[i] dist {...}
|
||||
class ClsIf;
|
||||
rand bit [3:0] a [4];
|
||||
rand bit [3:0] a[4];
|
||||
bit gate;
|
||||
constraint c {
|
||||
foreach (a[i]) {
|
||||
if (gate == 1'b1) {
|
||||
a[i] dist { 4'd0 := 3, [4'd1:4'd4] := 1 };
|
||||
a[i] dist {
|
||||
4'd0 := 3,
|
||||
[4'd1 : 4'd4] := 1
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -26,22 +30,30 @@ endclass
|
|||
|
||||
// foreach (a[i]) gate -> a[i] dist {...}
|
||||
class ClsImpl;
|
||||
rand bit [3:0] a [4];
|
||||
rand bit [3:0] a[4];
|
||||
bit gate;
|
||||
constraint c {
|
||||
foreach (a[i]) {
|
||||
gate -> (a[i] dist { 4'd0 := 3, [4'd1:4'd4] := 1 });
|
||||
gate ->
|
||||
(a[i] dist {
|
||||
4'd0 := 3,
|
||||
[4'd1 : 4'd4] := 1
|
||||
});
|
||||
}
|
||||
}
|
||||
endclass
|
||||
|
||||
// foreach (a[i]) gateA -> (gateB -> a[i] dist {...}) -- doubly-nested implication
|
||||
class ClsImplChained;
|
||||
rand bit [3:0] a [4];
|
||||
rand bit [3:0] a[4];
|
||||
bit gateA, gateB;
|
||||
constraint c {
|
||||
foreach (a[i]) {
|
||||
gateA -> (gateB -> (a[i] dist { 4'd0 := 3, [4'd1:4'd4] := 1 }));
|
||||
gateA ->
|
||||
(gateB -> (a[i] dist {
|
||||
4'd0 := 3,
|
||||
[4'd1 : 4'd4] := 1
|
||||
}));
|
||||
}
|
||||
}
|
||||
endclass
|
||||
|
|
@ -59,8 +71,8 @@ module t;
|
|||
`checkd(obj.randomize(), 1)
|
||||
foreach (obj.a[i]) begin
|
||||
if (obj.a[i] > 4) begin
|
||||
$write("%%Error: %s:%0d: if: value out of dist range: %0d\n",
|
||||
`__FILE__, `__LINE__, obj.a[i]);
|
||||
$write("%%Error: %s:%0d: if: value out of dist range: %0d\n", `__FILE__, `__LINE__,
|
||||
obj.a[i]);
|
||||
$stop;
|
||||
end
|
||||
if (obj.a[i] == 0) seen_zero++;
|
||||
|
|
@ -68,8 +80,9 @@ module t;
|
|||
end
|
||||
end
|
||||
if (seen_zero == 0 || seen_nonzero == 0) begin
|
||||
$write("%%Error: %s:%0d: dist inside foreach+if: not all buckets hit (zero=%0d nonzero=%0d)\n",
|
||||
`__FILE__, `__LINE__, seen_zero, seen_nonzero);
|
||||
$write(
|
||||
"%%Error: %s:%0d: dist inside foreach+if: not all buckets hit (zero=%0d nonzero=%0d)\n",
|
||||
`__FILE__, `__LINE__, seen_zero, seen_nonzero);
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
|
@ -85,8 +98,8 @@ module t;
|
|||
`checkd(obj.randomize(), 1)
|
||||
foreach (obj.a[i]) begin
|
||||
if (obj.a[i] > 4) begin
|
||||
$write("%%Error: %s:%0d: ->: value out of dist range: %0d\n",
|
||||
`__FILE__, `__LINE__, obj.a[i]);
|
||||
$write("%%Error: %s:%0d: ->: value out of dist range: %0d\n", `__FILE__, `__LINE__,
|
||||
obj.a[i]);
|
||||
$stop;
|
||||
end
|
||||
if (obj.a[i] == 0) seen_zero++;
|
||||
|
|
@ -94,8 +107,9 @@ module t;
|
|||
end
|
||||
end
|
||||
if (seen_zero == 0 || seen_nonzero == 0) begin
|
||||
$write("%%Error: %s:%0d: dist inside foreach+->: not all buckets hit (zero=%0d nonzero=%0d)\n",
|
||||
`__FILE__, `__LINE__, seen_zero, seen_nonzero);
|
||||
$write(
|
||||
"%%Error: %s:%0d: dist inside foreach+->: not all buckets hit (zero=%0d nonzero=%0d)\n",
|
||||
`__FILE__, `__LINE__, seen_zero, seen_nonzero);
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
|
@ -112,8 +126,8 @@ module t;
|
|||
`checkd(obj.randomize(), 1)
|
||||
foreach (obj.a[i]) begin
|
||||
if (obj.a[i] > 4) begin
|
||||
$write("%%Error: %s:%0d: ->->: value out of dist range: %0d\n",
|
||||
`__FILE__, `__LINE__, obj.a[i]);
|
||||
$write("%%Error: %s:%0d: ->->: value out of dist range: %0d\n", `__FILE__, `__LINE__,
|
||||
obj.a[i]);
|
||||
$stop;
|
||||
end
|
||||
if (obj.a[i] == 0) seen_zero++;
|
||||
|
|
@ -121,8 +135,9 @@ module t;
|
|||
end
|
||||
end
|
||||
if (seen_zero == 0 || seen_nonzero == 0) begin
|
||||
$write("%%Error: %s:%0d: dist inside foreach+->->: not all buckets hit (zero=%0d nonzero=%0d)\n",
|
||||
`__FILE__, `__LINE__, seen_zero, seen_nonzero);
|
||||
$write(
|
||||
"%%Error: %s:%0d: dist inside foreach+->->: not all buckets hit (zero=%0d nonzero=%0d)\n",
|
||||
`__FILE__, `__LINE__, seen_zero, seen_nonzero);
|
||||
$stop;
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,13 +14,20 @@
|
|||
// Scalar: uniform over [0:9] (10% each)
|
||||
class DistScalarRange;
|
||||
rand bit [3:0] x;
|
||||
constraint c { x dist {[4'd0:4'd9] := 1}; }
|
||||
constraint c {
|
||||
x dist {
|
||||
[4'd0 : 4'd9] := 1
|
||||
};
|
||||
}
|
||||
endclass
|
||||
|
||||
// Array foreach: uniform over [0:4] (20% each per element)
|
||||
class DistForeachUniform;
|
||||
rand bit [2:0] a[5];
|
||||
constraint c { foreach (a[i]) a[i] dist {[3'd0:3'd4] := 1}; }
|
||||
constraint c {
|
||||
foreach (a[i])
|
||||
a[i] dist {[3'd0 : 3'd4] := 1};
|
||||
}
|
||||
endclass
|
||||
|
||||
// Array foreach: mixed single + range
|
||||
|
|
@ -28,32 +35,50 @@ endclass
|
|||
// 0: 5/14 ~= 35.7%, 1..9: 1/14 ~= 7.1% each
|
||||
class DistForeachMixed;
|
||||
rand bit [3:0] a[5];
|
||||
constraint c { foreach (a[i]) a[i] dist {4'd0 := 5, [4'd1:4'd9] := 1}; }
|
||||
constraint c {
|
||||
foreach (a[i])
|
||||
a[i] dist {
|
||||
4'd0 := 5,
|
||||
[4'd1 : 4'd9] := 1
|
||||
};
|
||||
}
|
||||
endclass
|
||||
|
||||
// Scalar signed int: uniform over negative range [-9:0] (10% each)
|
||||
class DistNegRange;
|
||||
rand int x;
|
||||
constraint c { x dist {[-9:0] := 1}; }
|
||||
constraint c {
|
||||
x dist {
|
||||
[-9 : 0] := 1
|
||||
};
|
||||
}
|
||||
endclass
|
||||
|
||||
// Non-constant unsigned range bounds: uniform over [lo_val:hi_val] = [2:7] (6 values)
|
||||
class DistVarRangeUnsigned;
|
||||
rand bit [3:0] x;
|
||||
bit [3:0] lo_val = 4'd2, hi_val = 4'd7;
|
||||
constraint c { x dist {[lo_val:hi_val] := 1}; }
|
||||
constraint c {
|
||||
x dist {
|
||||
[lo_val : hi_val] := 1
|
||||
};
|
||||
}
|
||||
endclass
|
||||
|
||||
// Mixed const/non-const bounds: lo is constant, hi is a variable [1:hi_val] = [1:7]
|
||||
class DistMixedBounds;
|
||||
rand bit [3:0] x;
|
||||
bit [3:0] hi_val = 4'd7;
|
||||
constraint c { x dist {[4'd1:hi_val] := 1}; }
|
||||
constraint c {
|
||||
x dist {
|
||||
[4'd1 : hi_val] := 1
|
||||
};
|
||||
}
|
||||
endclass
|
||||
|
||||
module t;
|
||||
parameter int N = 2000; // randomize() calls per test
|
||||
parameter int TOL_PCT = 30; // +-% tolerance on expected counts
|
||||
parameter int N = 2000; // randomize() calls per test
|
||||
parameter int TOL_PCT = 30; // +-% tolerance on expected counts
|
||||
|
||||
initial begin
|
||||
|
||||
|
|
@ -71,8 +96,7 @@ module t;
|
|||
end
|
||||
cnt[obj.x]++;
|
||||
end
|
||||
foreach (cnt[v])
|
||||
`check_tol(cnt[v], N/10)
|
||||
foreach (cnt[v]) `check_tol(cnt[v], N / 10)
|
||||
end
|
||||
|
||||
// --- T2: array foreach uniform [0:4], 5 elements * N calls ---
|
||||
|
|
@ -91,8 +115,7 @@ module t;
|
|||
cnt[obj.a[i]]++;
|
||||
end
|
||||
end
|
||||
foreach (cnt[v])
|
||||
`check_tol(cnt[v], N)
|
||||
foreach (cnt[v]) `check_tol(cnt[v], N)
|
||||
end
|
||||
|
||||
// --- T3: array foreach mixed {0:=5, [1:9]:=1}, 5 elements * N calls ---
|
||||
|
|
@ -113,9 +136,8 @@ module t;
|
|||
cnt[obj.a[i]]++;
|
||||
end
|
||||
end
|
||||
`check_tol(cnt[0], N*5*5/14)
|
||||
for (int v = 1; v <= 9; v++)
|
||||
`check_tol(cnt[v], N*5*1/14)
|
||||
`check_tol(cnt[0], N * 5 * 5 / 14)
|
||||
for (int v = 1; v <= 9; v++) `check_tol(cnt[v], N * 5 * 1 / 14)
|
||||
end
|
||||
|
||||
// --- T4: signed int, uniform over negative range [-9:0] ---
|
||||
|
|
@ -131,10 +153,9 @@ module t;
|
|||
$write("%%Error: x=%0d outside valid range [-9:0]\n", obj.x);
|
||||
`stop;
|
||||
end
|
||||
cnt[obj.x + 9]++;
|
||||
cnt[obj.x+9]++;
|
||||
end
|
||||
foreach (cnt[v])
|
||||
`check_tol(cnt[v], N/10)
|
||||
foreach (cnt[v]) `check_tol(cnt[v], N / 10)
|
||||
end
|
||||
|
||||
// --- T5: non-constant unsigned range bounds [lo_val:hi_val] = [2:7] ---
|
||||
|
|
@ -151,8 +172,7 @@ module t;
|
|||
end
|
||||
cnt[obj.x]++;
|
||||
end
|
||||
for (int v = 2; v <= 7; v++)
|
||||
`check_tol(cnt[v], N/6)
|
||||
for (int v = 2; v <= 7; v++) `check_tol(cnt[v], N / 6)
|
||||
end
|
||||
|
||||
// --- T6: mixed const/non-const bounds [4'd1:hi_val] = [1:7] ---
|
||||
|
|
@ -169,8 +189,7 @@ module t;
|
|||
end
|
||||
cnt[obj.x]++;
|
||||
end
|
||||
for (int v = 1; v <= 7; v++)
|
||||
`check_tol(cnt[v], N/7)
|
||||
for (int v = 1; v <= 7; v++) `check_tol(cnt[v], N / 7)
|
||||
end
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
|
|
|
|||
|
|
@ -13,6 +13,6 @@ test.scenarios('simulator')
|
|||
|
||||
test.compile(verilator_flags2=['--coverage-expr --binary'])
|
||||
|
||||
test.execute()
|
||||
test.execute(all_run_flags=[" +verilator+coverage+file+" + test.obj_dir + "/coverage.dat"])
|
||||
|
||||
test.passes()
|
||||
|
|
|
|||
|
|
@ -4,32 +4,32 @@ DA:15,1
|
|||
DA:18,1
|
||||
DA:55,10
|
||||
DA:56,10
|
||||
BRDA:56,0,0,10
|
||||
BRDA:56,0,1,0
|
||||
BRDA:56,0,if,10
|
||||
BRDA:56,0,else,0
|
||||
DA:57,10
|
||||
DA:58,10
|
||||
DA:60,9
|
||||
BRDA:60,0,0,1
|
||||
BRDA:60,0,1,9
|
||||
BRDA:60,0,if,1
|
||||
BRDA:60,0,else,9
|
||||
DA:61,9
|
||||
BRDA:61,0,0,1
|
||||
BRDA:61,0,1,9
|
||||
BRDA:61,0,if,1
|
||||
BRDA:61,0,else,9
|
||||
DA:62,1
|
||||
DA:63,1
|
||||
DA:66,9
|
||||
BRDA:66,0,0,1
|
||||
BRDA:66,0,1,9
|
||||
BRDA:66,0,if,1
|
||||
BRDA:66,0,else,9
|
||||
DA:67,9
|
||||
BRDA:67,0,0,1
|
||||
BRDA:67,0,1,9
|
||||
BRDA:67,0,if,1
|
||||
BRDA:67,0,else,9
|
||||
DA:69,9
|
||||
DA:70,9
|
||||
DA:73,9
|
||||
BRDA:73,0,0,1
|
||||
BRDA:73,0,1,9
|
||||
BRDA:73,0,if,1
|
||||
BRDA:73,0,else,9
|
||||
DA:74,9
|
||||
BRDA:74,0,0,1
|
||||
BRDA:74,0,1,9
|
||||
BRDA:74,0,if,1
|
||||
BRDA:74,0,else,9
|
||||
DA:75,1
|
||||
DA:76,1
|
||||
DA:79,9
|
||||
|
|
@ -41,8 +41,8 @@ DA:87,1
|
|||
DA:88,1
|
||||
DA:89,1
|
||||
DA:91,7
|
||||
BRDA:91,0,0,1
|
||||
BRDA:91,0,1,7
|
||||
BRDA:91,0,if,1
|
||||
BRDA:91,0,else,7
|
||||
DA:92,1
|
||||
DA:93,1
|
||||
DA:96,7
|
||||
|
|
@ -52,67 +52,67 @@ DA:101,0
|
|||
DA:102,0
|
||||
DA:104,0
|
||||
DA:105,10
|
||||
BRDA:105,0,0,0
|
||||
BRDA:105,0,1,10
|
||||
BRDA:105,0,block,0
|
||||
BRDA:105,0,block,10
|
||||
DA:106,10
|
||||
DA:107,10
|
||||
BRDA:107,0,0,0
|
||||
BRDA:107,0,1,10
|
||||
BRDA:107,0,block,0
|
||||
BRDA:107,0,block,10
|
||||
DA:110,1
|
||||
DA:111,1
|
||||
DA:113,1
|
||||
DA:115,1
|
||||
DA:120,7
|
||||
BRDA:120,0,0,1
|
||||
BRDA:120,0,1,7
|
||||
BRDA:120,0,if,1
|
||||
BRDA:120,0,else,7
|
||||
DA:121,1
|
||||
DA:122,1
|
||||
DA:127,1
|
||||
DA:129,1
|
||||
DA:140,20
|
||||
DA:141,18
|
||||
BRDA:141,0,0,2
|
||||
BRDA:141,0,1,18
|
||||
BRDA:141,0,if,2
|
||||
BRDA:141,0,else,18
|
||||
DA:142,2
|
||||
DA:145,18
|
||||
DA:164,20
|
||||
DA:165,20
|
||||
DA:166,20
|
||||
BRDA:166,0,0,0
|
||||
BRDA:166,0,1,20
|
||||
BRDA:166,0,if,0
|
||||
BRDA:166,0,else,20
|
||||
DA:168,0
|
||||
DA:170,18
|
||||
BRDA:170,0,0,2
|
||||
BRDA:170,0,1,18
|
||||
BRDA:170,0,if,2
|
||||
BRDA:170,0,else,18
|
||||
DA:172,2
|
||||
DA:174,18
|
||||
DA:188,11
|
||||
DA:189,11
|
||||
DA:190,11
|
||||
BRDA:190,0,0,11
|
||||
BRDA:190,0,1,0
|
||||
BRDA:190,0,if,11
|
||||
BRDA:190,0,else,0
|
||||
DA:191,11
|
||||
DA:194,11
|
||||
DA:195,11
|
||||
BRDA:195,0,0,11
|
||||
BRDA:195,0,1,0
|
||||
BRDA:195,0,if,11
|
||||
BRDA:195,0,else,0
|
||||
DA:196,11
|
||||
DA:199,11
|
||||
DA:200,11
|
||||
BRDA:200,0,0,11
|
||||
BRDA:200,0,1,0
|
||||
BRDA:200,0,if,11
|
||||
BRDA:200,0,else,0
|
||||
DA:201,11
|
||||
DA:215,10
|
||||
DA:216,10
|
||||
DA:219,11
|
||||
DA:221,11
|
||||
DA:222,10
|
||||
BRDA:222,0,0,1
|
||||
BRDA:222,0,1,10
|
||||
BRDA:222,0,if,1
|
||||
BRDA:222,0,else,10
|
||||
DA:223,1
|
||||
DA:225,10
|
||||
BRDA:225,0,0,1
|
||||
BRDA:225,0,1,10
|
||||
BRDA:225,0,if,1
|
||||
BRDA:225,0,else,10
|
||||
DA:226,1
|
||||
DA:229,11
|
||||
DA:230,11
|
||||
|
|
@ -121,12 +121,12 @@ DA:232,11
|
|||
DA:233,11
|
||||
DA:253,10
|
||||
DA:254,9
|
||||
BRDA:254,0,0,1
|
||||
BRDA:254,0,1,9
|
||||
BRDA:254,0,if,1
|
||||
BRDA:254,0,else,9
|
||||
DA:256,1
|
||||
DA:257,1
|
||||
BRDA:257,0,0,0
|
||||
BRDA:257,0,1,1
|
||||
BRDA:257,0,if,0
|
||||
BRDA:257,0,else,1
|
||||
DA:266,10
|
||||
DA:267,10
|
||||
DA:268,1
|
||||
|
|
@ -139,8 +139,8 @@ DA:277,10
|
|||
DA:278,10
|
||||
DA:288,0
|
||||
DA:289,0
|
||||
BRDA:289,0,0,0
|
||||
BRDA:289,0,1,0
|
||||
BRDA:289,0,if,0
|
||||
BRDA:289,0,else,0
|
||||
DA:290,0
|
||||
DA:292,0
|
||||
DA:293,0
|
||||
|
|
@ -157,66 +157,66 @@ DA:328,10
|
|||
DA:329,10
|
||||
DA:330,10
|
||||
DA:333,31
|
||||
BRDA:333,0,0,0
|
||||
BRDA:333,0,1,31
|
||||
BRDA:333,0,cond_then,0
|
||||
BRDA:333,0,cond_else,31
|
||||
DA:334,28
|
||||
BRDA:334,0,0,3
|
||||
BRDA:334,0,1,28
|
||||
BRDA:334,0,cond_then,3
|
||||
BRDA:334,0,cond_else,28
|
||||
DA:335,1
|
||||
BRDA:335,0,0,1
|
||||
BRDA:335,0,1,0
|
||||
BRDA:335,0,cond_then,1
|
||||
BRDA:335,0,cond_else,0
|
||||
DA:336,10
|
||||
DA:337,10
|
||||
BRDA:337,0,0,10
|
||||
BRDA:337,0,1,3
|
||||
BRDA:337,0,2,7
|
||||
BRDA:337,0,block,10
|
||||
BRDA:337,0,cond_then,3
|
||||
BRDA:337,0,cond_else,7
|
||||
DA:338,10
|
||||
BRDA:338,0,0,10
|
||||
BRDA:338,0,1,0
|
||||
BRDA:338,0,2,10
|
||||
BRDA:338,0,block,10
|
||||
BRDA:338,0,cond_then,0
|
||||
BRDA:338,0,cond_else,10
|
||||
DA:340,19
|
||||
BRDA:340,0,0,12
|
||||
BRDA:340,0,1,19
|
||||
BRDA:340,0,2,7
|
||||
BRDA:340,0,3,5
|
||||
BRDA:340,0,cond_then,12
|
||||
BRDA:340,0,cond_else,19
|
||||
BRDA:340,0,cond_then,7
|
||||
BRDA:340,0,cond_else,5
|
||||
DA:343,11
|
||||
BRDA:343,0,0,11
|
||||
BRDA:343,0,1,0
|
||||
BRDA:343,0,cond_then,11
|
||||
BRDA:343,0,cond_else,0
|
||||
DA:349,22
|
||||
BRDA:349,0,0,20
|
||||
BRDA:349,0,1,22
|
||||
BRDA:349,0,cond_then,20
|
||||
BRDA:349,0,cond_else,22
|
||||
DA:352,11
|
||||
DA:353,10
|
||||
BRDA:353,0,0,0
|
||||
BRDA:353,0,1,1
|
||||
BRDA:353,0,2,1
|
||||
BRDA:353,0,3,10
|
||||
BRDA:353,0,cond_then,0
|
||||
BRDA:353,0,cond_else,1
|
||||
BRDA:353,0,if,1
|
||||
BRDA:353,0,else,10
|
||||
DA:354,10
|
||||
DA:356,11
|
||||
BRDA:356,0,0,11
|
||||
BRDA:356,0,1,1
|
||||
BRDA:356,0,2,10
|
||||
BRDA:356,0,block,11
|
||||
BRDA:356,0,cond_then,1
|
||||
BRDA:356,0,cond_else,10
|
||||
DA:359,55
|
||||
BRDA:359,0,0,11
|
||||
BRDA:359,0,1,55
|
||||
BRDA:359,0,block,11
|
||||
BRDA:359,0,block,55
|
||||
DA:360,55
|
||||
DA:362,44
|
||||
BRDA:362,0,0,11
|
||||
BRDA:362,0,1,11
|
||||
BRDA:362,0,2,33
|
||||
BRDA:362,0,3,44
|
||||
BRDA:362,0,block,11
|
||||
BRDA:362,0,cond_then,11
|
||||
BRDA:362,0,cond_else,33
|
||||
BRDA:362,0,block,44
|
||||
DA:363,44
|
||||
DA:366,11
|
||||
BRDA:366,0,0,0
|
||||
BRDA:366,0,1,11
|
||||
BRDA:366,0,if,0
|
||||
BRDA:366,0,else,11
|
||||
DA:367,11
|
||||
DA:370,10
|
||||
BRDA:370,0,0,1
|
||||
BRDA:370,0,1,10
|
||||
BRDA:370,0,cond_then,1
|
||||
BRDA:370,0,cond_else,10
|
||||
DA:373,10
|
||||
DA:374,9
|
||||
BRDA:374,0,0,1
|
||||
BRDA:374,0,1,9
|
||||
BRDA:374,0,if,1
|
||||
BRDA:374,0,else,9
|
||||
BRF:83
|
||||
BRH:32
|
||||
end_of_record
|
||||
|
|
|
|||
|
|
@ -60,18 +60,17 @@ module t (
|
|||
// A cover of an implication counts only non-vacuous matches (IEEE
|
||||
// 1800-2023 16.15.2): the antecedent must match. So it is identical to the
|
||||
// corresponding sequence cover, not the vacuous implication value.
|
||||
`checkd(n_imp_no, n_seq)
|
||||
`checkd(n_imp_ov, n_seq0)
|
||||
`checkd(n_imp_no, n_seq); // Other sims: pass, 73
|
||||
`checkd(n_imp_ov, n_seq0); // Other sims: pass, 45
|
||||
// A named-property cover lowers the same implication, so it also counts
|
||||
// non-vacuously (regression guard for the property-inlining path).
|
||||
`checkd(n_named, n_imp_no)
|
||||
// Pinned Verilator counts; Questa golden cross-checked.
|
||||
`checkd(n_imp_no, 28) // Questa: 28
|
||||
`checkd(n_imp_ov, 27) // Questa: 27
|
||||
`checkd(n_seq, 28) // Questa: 28
|
||||
`checkd(n_seq0, 27) // Questa: 27
|
||||
`checkd(n_bool, 55) // Questa: 54
|
||||
`checkd(n_named, 28) // Questa: 28
|
||||
`checkd(n_named, n_imp_no);
|
||||
`checkd(n_imp_no, 28);
|
||||
`checkd(n_imp_ov, 27); // Other sims: pass, 73
|
||||
`checkd(n_seq, 28); // Other sims: 45, 27
|
||||
`checkd(n_seq0, 27);
|
||||
`checkd(n_bool, 55); // Other sims: pass, 25
|
||||
`checkd(n_named, 28); // Other sims: 73, 54, 54
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -69,22 +69,21 @@ module t (
|
|||
|
||||
// Read the counters in 'final', not the clocked block: a same-cycle read of a
|
||||
// cover counter races the cover's increment under --threads (vltmt). Verilator
|
||||
// counts one more end-of-match than Questa 2022.3 on some forms at the
|
||||
// simulation boundary; the Questa value is noted per check.
|
||||
// counts one more end-of-match than others on some forms.
|
||||
final begin
|
||||
`ifdef TEST_VERBOSE
|
||||
$write("simple=%0d clocked=%0d clk_dis=%0d def_dis=%0d range=%0d 2=%0d 3=%0d\n", hit_simple,
|
||||
hit_clocked, hit_clocked_disable, hit_default_disable, hit_consrep_range, hit_consrep_2,
|
||||
hit_consrep_3);
|
||||
`endif
|
||||
`checkd(hit_simple, 96); // Questa: 95
|
||||
`checkd(hit_clocked, 149); // Questa: 149
|
||||
`checkd(hit_clocked_disable, 27); // Questa: 27
|
||||
`checkd(hit_default_disable, 30); // Questa: 30
|
||||
`checkd(hit_consrep_2, 30); // Questa: 29
|
||||
`checkd(hit_consrep_3, 14); // Questa: 13
|
||||
`checkd(hit_simple, 96); // Other sims: 5, 95
|
||||
`checkd(hit_clocked, 149);
|
||||
`checkd(hit_clocked_disable, 27);
|
||||
`checkd(hit_default_disable, 30);
|
||||
`checkd(hit_consrep_2, 30); // Other sims: 29
|
||||
`checkd(hit_consrep_3, 14); // Other sims: 13
|
||||
// a[*2:3] == a[*2] or a[*3] (IEEE 1800-2023 16.9.2)
|
||||
`checkd(hit_consrep_range, hit_consrep_2 + hit_consrep_3); // 44; Questa: 42
|
||||
`checkd(hit_consrep_range, hit_consrep_2 + hit_consrep_3);
|
||||
$write("*-* All Finished *-*\n");
|
||||
end
|
||||
endmodule
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
TN:verilator_coverage
|
||||
SF:t/t_cover_toggle_min.v
|
||||
DA:10,1
|
||||
BRDA:10,0,0,1
|
||||
BRDA:10,0,1,0
|
||||
BRDA:10,0,2,0
|
||||
BRDA:10,0,3,0
|
||||
BRDA:10,0,a[0]:0->1,1
|
||||
BRDA:10,0,a[0]:1->0,0
|
||||
BRDA:10,0,a[1]:0->1,0
|
||||
BRDA:10,0,a[1]:1->0,0
|
||||
DA:11,1
|
||||
BRDA:11,0,0,0
|
||||
BRDA:11,0,1,0
|
||||
BRDA:11,0,2,1
|
||||
BRDA:11,0,3,0
|
||||
BRDA:11,0,b[0]:0->1,0
|
||||
BRDA:11,0,b[0]:1->0,0
|
||||
BRDA:11,0,b[1]:0->1,1
|
||||
BRDA:11,0,b[1]:1->0,0
|
||||
DA:12,1
|
||||
BRDA:12,0,0,1
|
||||
BRDA:12,0,1,1
|
||||
BRDA:12,0,2,1
|
||||
BRDA:12,0,3,0
|
||||
BRDA:12,0,c[0]:0->1,1
|
||||
BRDA:12,0,c[0]:1->0,1
|
||||
BRDA:12,0,c[1]:0->1,1
|
||||
BRDA:12,0,c[1]:1->0,0
|
||||
BRF:12
|
||||
BRH:0
|
||||
end_of_record
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# This program is free software; you can redistribute it and/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-FileCopyrightText: 2026 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt_all')
|
||||
test.top_filename = 't/t_covergroup_cross.v'
|
||||
|
||||
# runs without --coverage
|
||||
test.compile(verilator_flags2=['--Wno-COVERIGN'])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# This program is free software; you can redistribute it and/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-FileCopyrightText: 2026 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
test.top_filename = 't/t_covergroup_option.v'
|
||||
|
||||
# runs without --coverage
|
||||
test.compile(verilator_flags2=['--Wno-COVERIGN'])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -5,9 +5,7 @@
|
|||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
package pkg;
|
||||
typedef struct {
|
||||
logic [7:0] value;
|
||||
} field_t;
|
||||
typedef struct {logic [7:0] value;} field_t;
|
||||
typedef struct {
|
||||
field_t f0;
|
||||
field_t f1;
|
||||
|
|
@ -19,11 +17,9 @@ package pkg;
|
|||
} hwif_t;
|
||||
endpackage
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
module t (
|
||||
input clk
|
||||
);
|
||||
|
||||
import pkg::*;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# This program is free software; you can redistribute it and/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-FileCopyrightText: 2026 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(verilator_flags2=["-runtime-debug"])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Antmicro
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
|
||||
module t (
|
||||
input clk
|
||||
);
|
||||
wire mem_wire;
|
||||
bit [15:0] idx = 65535;
|
||||
bit mem_reg[0:34000];
|
||||
assign mem_wire = mem_reg[idx];
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (idx < 65533) begin
|
||||
$display("oob_val %d", mem_wire);
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
else begin
|
||||
idx <= idx - 1;
|
||||
mem_reg[idx] <= 0;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: VPI test library for t_flag_main_vpi
|
||||
//
|
||||
// Loaded at runtime via +verilator+vpi+<path> to verify that --binary --vpi
|
||||
// correctly loads shared libraries and invokes vlog_startup_routines[] (or a
|
||||
// named bootstrap). The design drives its own clock; this library only
|
||||
// observes 'count' via a cbValueChange callback and calls $finish after
|
||||
// MAX_TICKS edges -- so a successful $finish proves the library was loaded
|
||||
// and is able to register callbacks and reach signals by name.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/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-FileCopyrightText: 2025 Wilson Snyder
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#include "vpi_user.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
// Number of count increments to observe before calling $finish
|
||||
static const int MAX_TICKS = 10;
|
||||
static vpiHandle s_count_handle = nullptr;
|
||||
|
||||
static PLI_INT32 count_change_cb(p_cb_data /*cb_data*/) {
|
||||
if (!s_count_handle) return 0;
|
||||
s_vpi_value val;
|
||||
val.format = vpiIntVal;
|
||||
vpi_get_value(s_count_handle, &val);
|
||||
if (val.value.integer >= MAX_TICKS) {
|
||||
vpi_printf(const_cast<char*>("*-* All Finished *-*\n"));
|
||||
vpi_control(vpiFinish, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PLI_INT32 start_of_sim_cb(p_cb_data /*cb_data*/) {
|
||||
s_count_handle = vpi_handle_by_name(const_cast<char*>("t.count"), nullptr);
|
||||
if (!s_count_handle) {
|
||||
vpi_printf(const_cast<char*>("ERROR: cannot find t.count\n"));
|
||||
vpi_control(vpiFinish, 1);
|
||||
return 0;
|
||||
}
|
||||
// Observe count: fire a callback whenever it changes
|
||||
t_cb_data cb_data;
|
||||
s_vpi_time t;
|
||||
s_vpi_value val;
|
||||
t.type = vpiSuppressTime;
|
||||
val.format = vpiSuppressVal;
|
||||
cb_data.reason = cbValueChange;
|
||||
cb_data.cb_rtn = count_change_cb;
|
||||
cb_data.obj = s_count_handle;
|
||||
cb_data.time = &t;
|
||||
cb_data.value = &val;
|
||||
cb_data.user_data = nullptr;
|
||||
vpi_register_cb(&cb_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PLI_INT32 end_of_sim_cb(p_cb_data /*cb_data*/) {
|
||||
vpi_printf(const_cast<char*>("VPI end of simulation\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_callbacks() {
|
||||
// cbStartOfSimulation
|
||||
t_cb_data cb_data;
|
||||
s_vpi_time t;
|
||||
t.type = vpiSuppressTime;
|
||||
cb_data.reason = cbStartOfSimulation;
|
||||
cb_data.cb_rtn = start_of_sim_cb;
|
||||
cb_data.obj = nullptr;
|
||||
cb_data.time = &t;
|
||||
cb_data.value = nullptr;
|
||||
cb_data.user_data = nullptr;
|
||||
vpi_register_cb(&cb_data);
|
||||
|
||||
// cbEndOfSimulation
|
||||
cb_data.reason = cbEndOfSimulation;
|
||||
cb_data.cb_rtn = end_of_sim_cb;
|
||||
vpi_register_cb(&cb_data);
|
||||
}
|
||||
|
||||
// IEEE 1800 section 37: vlog_startup_routines[] -- null-terminated array of startup functions
|
||||
extern "C" {
|
||||
void (*vlog_startup_routines[])() = {register_callbacks, nullptr};
|
||||
|
||||
// Named bootstrap entrypoint -- used when library is loaded as <path>:my_vpi_bootstrap
|
||||
void my_vpi_bootstrap() { register_callbacks(); }
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
*-* All Finished *-*
|
||||
VPI end of simulation
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# This program is free software; you can redistribute it and/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-FileCopyrightText: 2025 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
# Compile with --binary --vpi to exercise the VPI-aware generated main.
|
||||
# Also compile a VPI shared library to be loaded at runtime via +verilator+vpi+.
|
||||
test.compile(make_pli=True, verilator_flags2=["--binary --vpi --public-flat-rw"])
|
||||
|
||||
# Run the generated binary; load the VPI library via the +verilator+vpi+ plusarg.
|
||||
# The VPI library's output (observed 'count' reaching MAX_TICKS, then end-of-sim) is
|
||||
# checked against the golden .out file.
|
||||
# Also pass a non-VPI plusarg (skipped by the loader's prefix check) and a bare
|
||||
# +verilator+vpi+ with an empty payload (skipped by the empty-arg check), so both
|
||||
# loader-skip branches are exercised alongside the real library load.
|
||||
test.execute(all_run_flags=[
|
||||
"+othertest", "+verilator+vpi+", "+verilator+vpi+" + test.obj_dir + "/libvpi.so"
|
||||
],
|
||||
check_finished=True,
|
||||
expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain
|
||||
// SPDX-FileCopyrightText: 2025 Wilson Snyder
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Test for --binary --vpi runtime library loading. The design provides its
|
||||
// own clock (so the simulation has Verilog event activity); the VPI library
|
||||
// (t_flag_main_vpi.cpp), loaded at runtime via +verilator+vpi+, observes
|
||||
// 'count' via a cbValueChange callback and calls $finish after MAX_TICKS
|
||||
// edges. Signals are public so the library can reach them by name
|
||||
// (requires --public-flat-rw).
|
||||
module t;
|
||||
|
||||
reg clk /*verilator public_flat_rw*/;
|
||||
reg [31:0] count /*verilator public_flat_rw*/;
|
||||
|
||||
initial begin
|
||||
clk = 0;
|
||||
count = 0;
|
||||
end
|
||||
|
||||
// Self-driving clock: the design itself keeps the simulation alive
|
||||
always #5 clk = ~clk;
|
||||
|
||||
always @(posedge clk) count <= count + 1;
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
%Error: Cannot find VPI bootstrap 'no_such_fn' in: obj_vlt/t_flag_main_vpi_badentry/libvpi.so
|
||||
Aborting...
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# This program is free software; you can redistribute it and/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-FileCopyrightText: 2025 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
# A valid library loaded with a :<bootstrap> entry that does not exist must
|
||||
# fail with a clear error (the missing-named-bootstrap branch of the loader).
|
||||
test.top_filename = 't/t_flag_main_vpi.v'
|
||||
test.pli_filename = 't/t_flag_main_vpi.cpp'
|
||||
|
||||
test.compile(make_pli=True, verilator_flags2=["--binary --vpi --public-flat-rw"])
|
||||
|
||||
test.execute(fails=True,
|
||||
all_run_flags=["+verilator+vpi+" + test.obj_dir + "/libvpi.so:no_such_fn"],
|
||||
expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
%Error: Cannot load VPI library: obj_vlt/t_flag_main_vpi_badlib/nonexistent.so
|
||||
Aborting...
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# This program is free software; you can redistribute it and/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-FileCopyrightText: 2025 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
# +verilator+vpi+ pointing at a non-existent library must fail with a clear
|
||||
# error (the dlopen-failure branch of the runtime loader).
|
||||
test.top_filename = 't/t_flag_main_vpi.v'
|
||||
|
||||
test.compile(verilator_flags2=["--binary --vpi --public-flat-rw"])
|
||||
|
||||
# The fatal names the (stable, relative) library path; the platform-specific dlerror()
|
||||
# detail is emitted on a "- " line, which golden comparison strips, so the .out is portable.
|
||||
test.execute(fails=True,
|
||||
all_run_flags=["+verilator+vpi+" + test.obj_dir + "/nonexistent.so"],
|
||||
expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
*-* All Finished *-*
|
||||
VPI end of simulation
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# This program is free software; you can redistribute it and/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-FileCopyrightText: 2025 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
# Same design and VPI library as t_flag_main_vpi, but loaded via the
|
||||
# +verilator+vpi+<path>:<name> named-bootstrap syntax instead of vlog_startup_routines[].
|
||||
test.top_filename = 't/t_flag_main_vpi.v'
|
||||
test.pli_filename = 't/t_flag_main_vpi.cpp'
|
||||
|
||||
test.compile(make_pli=True, verilator_flags2=["--binary --vpi --public-flat-rw"])
|
||||
|
||||
test.execute(all_run_flags=["+verilator+vpi+" + test.obj_dir + "/libvpi.so:my_vpi_bootstrap"],
|
||||
check_finished=True,
|
||||
expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: Second VPI test library for t_flag_main_vpi_multi
|
||||
//
|
||||
// A second, independent VPI library loaded alongside t_flag_main_vpi.cpp via a
|
||||
// repeated +verilator+vpi+ argument, to verify multiple libraries are loaded.
|
||||
// Its startup routine prints a marker proving it was loaded; it does not drive
|
||||
// or finish the simulation (the first library does that).
|
||||
//
|
||||
// This program is free software; you can redistribute it and/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-FileCopyrightText: 2025 Wilson Snyder
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#include "vpi_user.h"
|
||||
|
||||
static void lib2_startup() { vpi_printf(const_cast<char*>("second VPI library loaded\n")); }
|
||||
|
||||
// IEEE 1800 section 37: vlog_startup_routines[] -- null-terminated array of startup functions
|
||||
extern "C" {
|
||||
void (*vlog_startup_routines[])() = {lib2_startup, nullptr};
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
second VPI library loaded
|
||||
*-* All Finished *-*
|
||||
VPI end of simulation
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# This program is free software; you can redistribute it and/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-FileCopyrightText: 2025 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import os
|
||||
import platform
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
# Two +verilator+vpi+ arguments load two independent libraries: the first
|
||||
# (t_flag_main_vpi.cpp) observes the design and calls $finish; the second
|
||||
# (t_flag_main_vpi_lib2.cpp) prints a marker proving it too was loaded.
|
||||
test.top_filename = 't/t_flag_main_vpi.v'
|
||||
test.pli_filename = 't/t_flag_main_vpi.cpp'
|
||||
|
||||
test.compile(make_pli=True, verilator_flags2=["--binary --vpi --public-flat-rw"])
|
||||
|
||||
# Build the second VPI library (make_pli only builds libvpi.so), mirroring the
|
||||
# driver's own pli flags.
|
||||
root = os.environ['VERILATOR_ROOT']
|
||||
pli2_cmd = [
|
||||
os.environ['CXX'], "-I" + root + "/include/vltstd", "-I" + root + "/include", "-fPIC",
|
||||
"-shared"
|
||||
]
|
||||
pli2_cmd += (["-Wl,-undefined,dynamic_lookup"] if platform.system() == 'Darwin' else ["-rdynamic"])
|
||||
pli2_cmd += ["-o", test.obj_dir + "/libvpi2.so", "t/t_flag_main_vpi_lib2.cpp"]
|
||||
test.run(logfile=test.obj_dir + "/pli2_compile.log", cmd=pli2_cmd)
|
||||
|
||||
test.execute(all_run_flags=[
|
||||
"+verilator+vpi+" + test.obj_dir + "/libvpi.so",
|
||||
"+verilator+vpi+" + test.obj_dir + "/libvpi2.so"
|
||||
],
|
||||
check_finished=True,
|
||||
expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
||||
//*************************************************************************
|
||||
// DESCRIPTION: Verilator: VPI test library lacking vlog_startup_routines
|
||||
//
|
||||
// Loaded via +verilator+vpi+<path> with no :<bootstrap> entry, to exercise
|
||||
// the loader's error path when a library defines neither a named bootstrap
|
||||
// nor the vlog_startup_routines[] array.
|
||||
//
|
||||
// This program is free software; you can redistribute it and/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-FileCopyrightText: 2025 Wilson Snyder
|
||||
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
//
|
||||
//*************************************************************************
|
||||
|
||||
#include "vpi_user.h"
|
||||
|
||||
// Intentionally no vlog_startup_routines and no bootstrap; just some symbol so
|
||||
// the shared object is non-empty and loads successfully.
|
||||
extern "C" void t_flag_main_vpi_noarray_present() {}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
%Error: Cannot find 'vlog_startup_routines' in: obj_vlt/t_flag_main_vpi_noarray/libvpi.so
|
||||
Aborting...
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# This program is free software; you can redistribute it and/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-FileCopyrightText: 2025 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
# A library loaded with no :<bootstrap> entry that lacks vlog_startup_routines
|
||||
# must fail with a clear error (the missing-array branch of the loader).
|
||||
test.top_filename = 't/t_flag_main_vpi.v'
|
||||
test.pli_filename = 't/t_flag_main_vpi_noarray.cpp'
|
||||
|
||||
test.compile(make_pli=True, verilator_flags2=["--binary --vpi --public-flat-rw"])
|
||||
|
||||
test.execute(fails=True,
|
||||
all_run_flags=["+verilator+vpi+" + test.obj_dir + "/libvpi.so"],
|
||||
expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# This program is free software; you can redistribute it and/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-FileCopyrightText: 2025 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
# --vpi without --exe (no generated main, library-only output): the Makefile
|
||||
# must still report VM_VPI = 1, but must NOT add the runtime-VPI link flags since
|
||||
# there is no executable to export VPI symbols from. Exercises the exe()==false
|
||||
# branch of the VPI link-flag gate in V3EmitMk.
|
||||
test.top_filename = 't/t_flag_main_vpi.v'
|
||||
|
||||
test.compile(make_main=False, verilator_make_gmake=False, verilator_flags2=["--vpi --timing"])
|
||||
|
||||
test.file_grep(test.obj_dir + "/V" + test.name + "_classes.mk", r'VM_VPI = 1')
|
||||
# Without --exe there is no executable to export symbols from or to dlopen into,
|
||||
# so the runtime-VPI link flags (CFG_LDFLAGS_DYNAMIC/CFG_LDLIBS_DYNAMIC, probed at
|
||||
# configure time) must not be referenced in the generated Makefile.
|
||||
mk = test.obj_dir + "/V" + test.name + ".mk"
|
||||
test.file_grep_not(mk, r'CFG_LDFLAGS_DYNAMIC')
|
||||
test.file_grep_not(mk, r'CFG_LDLIBS_DYNAMIC')
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
%Warning: COMMAND_LINE:0: +verilator+vpi+ ignored: simulation was not compiled with --vpi '+verilator+vpi+/nonexistent.so'
|
||||
[0] Hello
|
||||
*-* All Finished *-*
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# This program is free software; you can redistribute it and/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-FileCopyrightText: 2025 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('vlt')
|
||||
|
||||
# Compile with --binary but WITHOUT --vpi.
|
||||
# Passing +verilator+vpi+ at runtime should emit a warning, not load anything.
|
||||
test.compile(top_filename='t/t_flag_main.v', verilator_flags2=["--binary"])
|
||||
|
||||
# Without --vpi there is no loader, so the plusarg is ignored with a warning (checked via
|
||||
# the golden .out). The plusarg value is fixed, so the warning text is portable.
|
||||
test.execute(all_run_flags=["+verilator+vpi+/nonexistent.so"],
|
||||
check_finished=True,
|
||||
expect_filename=test.golden_filename)
|
||||
|
||||
test.passes()
|
||||
|
|
@ -5,7 +5,8 @@
|
|||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define checkh(g,e) do if ((g) !==(e)) begin $write("%%Error: %s:%0d: got=%x exp=%x\n", `__FILE__,`__LINE__, (g),(e)); $stop; end while(0)
|
||||
`define stop $stop
|
||||
`define checkh(g,e) do if ((g) !==(e)) begin $write("%%Error: %s:%0d: got=%x exp=%x\n", `__FILE__,`__LINE__, (g),(e)); `stop; end while(0)
|
||||
|
||||
`ifdef CMT
|
||||
`define FORCEABLE /*verilator forceable*/
|
||||
|
|
|
|||
|
|
@ -97,8 +97,6 @@ module paramed ( /*AUTOARG*/
|
|||
// No else
|
||||
endgenerate
|
||||
|
||||
`ifndef NC // for(genvar) unsupported
|
||||
`ifndef ATSIM // for(genvar) unsupported
|
||||
generate
|
||||
// Empty loop body, local genvar
|
||||
for (genvar j = 0; j < 3; j = j + 1) begin
|
||||
|
|
@ -107,8 +105,6 @@ module paramed ( /*AUTOARG*/
|
|||
for (genvar j = 0; j < 5; j = j + 1) begin
|
||||
end
|
||||
endgenerate
|
||||
`endif
|
||||
`endif
|
||||
|
||||
generate
|
||||
endgenerate
|
||||
|
|
|
|||
|
|
@ -10,30 +10,34 @@ module t (
|
|||
input clk
|
||||
);
|
||||
|
||||
integer cyc = 0;
|
||||
integer cyc = 0;
|
||||
|
||||
wire out;
|
||||
reg in;
|
||||
wire out;
|
||||
reg in;
|
||||
|
||||
Genit g (.clk(clk), .value(in), .result(out));
|
||||
Genit g (
|
||||
.clk(clk),
|
||||
.value(in),
|
||||
.result(out)
|
||||
);
|
||||
|
||||
always @ (posedge clk) begin
|
||||
always @(posedge clk) begin
|
||||
//$write("[%0t] cyc==%0d %x %x\n", $time, cyc, in, out);
|
||||
cyc <= cyc + 1;
|
||||
if (cyc==0) begin
|
||||
if (cyc == 0) begin
|
||||
// Setup
|
||||
in <= 1'b1;
|
||||
end
|
||||
else if (cyc==1) begin
|
||||
else if (cyc == 1) begin
|
||||
in <= 1'b0;
|
||||
end
|
||||
else if (cyc==2) begin
|
||||
else if (cyc == 2) begin
|
||||
if (out != 1'b1) $stop;
|
||||
end
|
||||
else if (cyc==3) begin
|
||||
else if (cyc == 3) begin
|
||||
if (out != 1'b0) $stop;
|
||||
end
|
||||
else if (cyc==9) begin
|
||||
else if (cyc == 9) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
|
@ -41,7 +45,11 @@ module t (
|
|||
|
||||
endmodule
|
||||
|
||||
module Generate (clk, value, result);
|
||||
module Generate (
|
||||
clk,
|
||||
value,
|
||||
result
|
||||
);
|
||||
input clk;
|
||||
input value;
|
||||
output result;
|
||||
|
|
@ -50,63 +58,73 @@ module Generate (clk, value, result);
|
|||
|
||||
assign result = Internal;
|
||||
|
||||
always @(posedge clk)
|
||||
Internal <= value;
|
||||
always @(posedge clk) Internal <= value;
|
||||
endmodule
|
||||
|
||||
module Checker (clk, value);
|
||||
module Checker (
|
||||
clk,
|
||||
value
|
||||
);
|
||||
input clk, value;
|
||||
|
||||
always @(posedge clk) begin
|
||||
$write ("[%0t] value=%h\n", $time, value);
|
||||
$write("[%0t] value=%h\n", $time, value);
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
module Test (clk, value, result);
|
||||
module Test (
|
||||
clk,
|
||||
value,
|
||||
result
|
||||
);
|
||||
input clk;
|
||||
input value;
|
||||
output result;
|
||||
|
||||
Generate gen (clk, value, result);
|
||||
Checker chk (clk, gen.Internal);
|
||||
Generate gen (
|
||||
clk,
|
||||
value,
|
||||
result
|
||||
);
|
||||
Checker chk (
|
||||
clk,
|
||||
gen.Internal
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
module Genit (clk, value, result);
|
||||
module Genit (
|
||||
clk,
|
||||
value,
|
||||
result
|
||||
);
|
||||
input clk;
|
||||
input value;
|
||||
output result;
|
||||
|
||||
`ifndef ATSIM // else unsupported
|
||||
`ifndef NC // else unsupported
|
||||
`ifndef IVERILOG // else unsupported
|
||||
`define WITH_FOR_GENVAR
|
||||
`endif
|
||||
`endif
|
||||
`endif
|
||||
|
||||
`define WITH_GENERATE
|
||||
`define WITH_GENERATE
|
||||
`ifdef WITH_GENERATE
|
||||
`ifndef WITH_FOR_GENVAR
|
||||
genvar i;
|
||||
`endif
|
||||
generate
|
||||
for (
|
||||
`ifdef WITH_FOR_GENVAR
|
||||
genvar
|
||||
`endif
|
||||
i = 0; i < 1; i = i + 1)
|
||||
begin : foo
|
||||
Test tt (clk, value, result);
|
||||
end
|
||||
for (genvar i = 0; i < 1; i = i + 1) begin : foo
|
||||
Test tt (
|
||||
clk,
|
||||
value,
|
||||
result
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
`else
|
||||
Test tt (clk, value, result);
|
||||
Test tt (
|
||||
clk,
|
||||
value,
|
||||
result
|
||||
);
|
||||
`endif
|
||||
|
||||
wire Result2 = t.g.foo[0].tt.gen.Internal; // Works - Do not change!
|
||||
always @ (posedge clk) begin
|
||||
always @(posedge clk) begin
|
||||
$write("[%0t] Result2 = %x\n", $time, Result2);
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# This program is free software; you can redistribute it and/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-FileCopyrightText: 2026 Wilson Snyder
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
import vltest_bootstrap
|
||||
|
||||
test.scenarios('simulator')
|
||||
|
||||
test.compile(verilator_flags2=['--binary'])
|
||||
|
||||
test.execute()
|
||||
|
||||
test.passes()
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
module t;
|
||||
|
||||
reg clk = 1;
|
||||
reg [7:0] d = 0;
|
||||
reg [7:0] q = 0;
|
||||
|
||||
// Clock generation
|
||||
always #0.5 clk = ~clk;
|
||||
|
||||
// Input signal generation
|
||||
initial begin
|
||||
// verilator lint_off INITIALDLY
|
||||
d <= 0;
|
||||
repeat (5) @(posedge clk);
|
||||
d <= 1;
|
||||
@(posedge clk);
|
||||
d <= 2;
|
||||
@(posedge clk);
|
||||
d <= 3;
|
||||
@(posedge clk);
|
||||
d <= 4;
|
||||
@(posedge clk);
|
||||
d <= 0;
|
||||
repeat (5) @(posedge clk);
|
||||
$finish;
|
||||
end
|
||||
|
||||
// Unit under test (flip-flop)
|
||||
always @(posedge clk) q <= d;
|
||||
|
||||
always @(negedge clk) begin
|
||||
$display("[%0t] d=%x q=%x", $time, d, q);
|
||||
if (d == 1) `checkd(q, 0);
|
||||
if (d == 2) `checkd(q, 1);
|
||||
if (d == 3) `checkd(q, 2);
|
||||
if (d == 4) `checkd(q, 3);
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -34,9 +34,9 @@ module t (
|
|||
if (sgn_wide[2:0] != 3'sh7) $stop;
|
||||
if (unsgn_wide[2:0] != 3'h7) $stop;
|
||||
// Simulators differ here.
|
||||
if (sgn_wide !== 8'sbzzzzz111 // z-extension - NC
|
||||
&& sgn_wide !== 8'sb11111111)
|
||||
$stop; // sign extension - VCS
|
||||
if (sgn_wide !== 8'sbzzzzz111 // z-extension - some others
|
||||
&& sgn_wide !== 8'sb11111111) // sign extension - some others
|
||||
$stop;
|
||||
if (unsgn_wide !== 8'sbzzzzz111 && unsgn_wide !== 8'sb00000111) $stop;
|
||||
cyc <= cyc + 1;
|
||||
if (cyc == 3) begin
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ module t (
|
|||
|
||||
counter_io c1_data();
|
||||
counter_io c2_data();
|
||||
//counter_io c3_data; // IEEE illegal, and VCS doesn't allow non-() as it does with cells
|
||||
// counter_io c3_data; // IEEE illegal
|
||||
counter_io c3_data();
|
||||
|
||||
counter_ansi c1 (.clkm(clk),
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ module t;
|
|||
|
||||
initial begin
|
||||
// Check numbering with 0 first
|
||||
// NC has a bug here
|
||||
if (foos[0].x !== 1'b1) $stop;
|
||||
if (foos[1].x !== 1'b1) $stop;
|
||||
if (foos[2].x !== 1'b0) $stop;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
// SPDX-FileCopyrightText: 2026 PlanV GmbH
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
// verilog_format: off
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0);
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
interface inner_if;
|
||||
|
|
|
|||
|
|
@ -244,9 +244,7 @@ module t (
|
|||
`checkh(67'h0 ** 21'h0, 67'h1);
|
||||
`checkh(67'sh0 ** 21'sh0, 67'sh1);
|
||||
`checkh(67'h10 ** 21'h0, 67'h1);
|
||||
`ifndef VCS
|
||||
`checkh(61'h7ab3811219 ** 21'ha6e30, 61'h01ea58c703687e81);
|
||||
`endif
|
||||
if (cyc==0) begin end
|
||||
else if (cyc==1) begin a <= 67'h0; b <= 67'h0; end
|
||||
else if (cyc==2) begin a <= 67'h0; b <= 67'h3; end
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue