merge upstream master and resolve conflicts

This commit is contained in:
Yilou Wang 2026-07-04 13:52:01 +02:00
commit c618361fa2
146 changed files with 2528 additions and 1283 deletions

View File

@ -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

View File

@ -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:

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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:

View File

@ -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
View File

@ -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:**

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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, "",

View File

@ -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; }

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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();
}
};

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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) \

View File

@ -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;

View File

@ -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());

View File

@ -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");

View File

@ -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++)"

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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

View File

@ -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");

View File

@ -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

View File

@ -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();

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -14,7 +14,7 @@
module t;
initial begin
$assertcontrol(100*`IMPURE_ONE);
$assertcontrol(100 * `IMPURE_ONE);
$finish;
end
endmodule

View File

@ -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++;

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -9,7 +9,6 @@
import vltest_bootstrap
test.scenarios('simulator')
test.scenarios('linter')
test.lint(verilator_flags2=["-libmap t/t_config_libmap_inc.map"],

View File

@ -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

View File

@ -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");

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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()

View File

@ -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::*;

View File

@ -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()

View File

@ -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

View File

@ -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(); }
}

View File

@ -0,0 +1,2 @@
*-* All Finished *-*
VPI end of simulation

View File

@ -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()

View File

@ -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

View File

@ -0,0 +1,2 @@
%Error: Cannot find VPI bootstrap 'no_such_fn' in: obj_vlt/t_flag_main_vpi_badentry/libvpi.so
Aborting...

View File

@ -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()

View File

@ -0,0 +1,2 @@
%Error: Cannot load VPI library: obj_vlt/t_flag_main_vpi_badlib/nonexistent.so
Aborting...

View File

@ -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()

View File

@ -0,0 +1,2 @@
*-* All Finished *-*
VPI end of simulation

View File

@ -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()

View File

@ -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};
}

View File

@ -0,0 +1,3 @@
second VPI library loaded
*-* All Finished *-*
VPI end of simulation

View File

@ -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()

View File

@ -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() {}

View File

@ -0,0 +1,2 @@
%Error: Cannot find 'vlog_startup_routines' in: obj_vlt/t_flag_main_vpi_noarray/libvpi.so
Aborting...

View File

@ -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()

View File

@ -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()

View File

@ -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 *-*

View File

@ -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()

View File

@ -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*/

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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),

View File

@ -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;

View File

@ -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;

View File

@ -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