Fix x assign vs init randomization (#6075)

This commit is contained in:
Todd Strader 2025-06-09 17:59:01 -04:00 committed by GitHub
parent a6bae7f196
commit d9534ec626
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 47 additions and 55 deletions

View File

@ -438,6 +438,30 @@ WDataOutP VL_SCOPED_RAND_RESET_W(int obits, WDataOutP outwp, uint64_t scopeHash,
return outwp;
}
IData VL_SCOPED_RAND_RESET_ASSIGN_I(int obits, uint64_t scopeHash, uint64_t salt) VL_MT_UNSAFE {
IData data = ~0;
VlRNG rng(Verilated::threadContextp()->randSeed() ^ scopeHash ^ salt);
data = rng.rand64();
data &= VL_MASK_I(obits);
return data;
}
QData VL_SCOPED_RAND_RESET_ASSIGN_Q(int obits, uint64_t scopeHash, uint64_t salt) VL_MT_UNSAFE {
QData data = ~0ULL;
VlRNG rng(Verilated::threadContextp()->randSeed() ^ scopeHash ^ salt);
data = rng.rand64();
data &= VL_MASK_Q(obits);
return data;
}
WDataOutP VL_SCOPED_RAND_RESET_ASSIGN_W(int obits, WDataOutP outwp, uint64_t scopeHash,
uint64_t salt) VL_MT_UNSAFE {
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);
return outwp;
}
IData VL_RAND_RESET_I(int obits) VL_MT_SAFE {
if (Verilated::threadContextp()->randReset() == 0) return 0;
IData data = ~0;
@ -447,7 +471,6 @@ IData VL_RAND_RESET_I(int obits) VL_MT_SAFE {
data &= VL_MASK_I(obits);
return data;
}
IData VL_RAND_RESET_ASSIGN_I(int obits) VL_MT_SAFE { return VL_RANDOM_I() & VL_MASK_I(obits); }
QData VL_RAND_RESET_Q(int obits) VL_MT_SAFE {
if (Verilated::threadContextp()->randReset() == 0) return 0;
@ -459,18 +482,11 @@ QData VL_RAND_RESET_Q(int obits) VL_MT_SAFE {
return data;
}
QData VL_RAND_RESET_ASSIGN_Q(int obits) VL_MT_SAFE { return VL_RANDOM_Q() & VL_MASK_Q(obits); }
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_RAND_RESET_ASSIGN_W(int obits, WDataOutP outwp) VL_MT_SAFE {
for (int i = 0; i < VL_WORDS_I(obits) - 1; ++i) outwp[i] = VL_RAND_RESET_ASSIGN_I(32);
outwp[VL_WORDS_I(obits) - 1] = VL_RAND_RESET_ASSIGN_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);

View File

@ -109,6 +109,16 @@ extern QData VL_SCOPED_RAND_RESET_Q(int obits, uint64_t scopeHash, uint64_t salt
extern WDataOutP VL_SCOPED_RAND_RESET_W(int obits, WDataOutP outwp, uint64_t scopeHash,
uint64_t salt) VL_MT_UNSAFE;
/// Random reset a signal of given width (assign time only)
extern IData VL_SCOPED_RAND_RESET_ASSIGN_I(int obits, uint64_t scopeHash,
uint64_t salt) VL_MT_UNSAFE;
/// Random reset a signal of given width (assign time only)
extern QData VL_SCOPED_RAND_RESET_ASSIGN_Q(int obits, uint64_t scopeHash,
uint64_t salt) VL_MT_UNSAFE;
/// Random reset a signal of given width (assign time only)
extern WDataOutP VL_SCOPED_RAND_RESET_ASSIGN_W(int obits, WDataOutP outwp, uint64_t scopeHash,
uint64_t salt) VL_MT_UNSAFE;
/// 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)
@ -116,13 +126,6 @@ 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;
/// Random reset a signal of given width (assign time only)
extern IData VL_RAND_RESET_ASSIGN_I(int obits) VL_MT_SAFE;
/// Random reset a signal of given width (assign time only)
extern QData VL_RAND_RESET_ASSIGN_Q(int obits) VL_MT_SAFE;
/// Random reset a signal of given width (assign time only)
extern WDataOutP VL_RAND_RESET_ASSIGN_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;

View File

@ -769,7 +769,8 @@ string EmitCFunc::emitVarResetRecurse(const AstVar* varp, bool constructing,
}
} else {
out += zeroit ? (slow ? "VL_ZERO_RESET_W(" : "VL_ZERO_W(")
: "VL_SCOPED_RAND_RESET_W(";
: (varp->isXTemp() ? "VL_SCOPED_RAND_RESET_ASSIGN_W("
: "VL_SCOPED_RAND_RESET_W(");
out += cvtToStr(dtypep->widthMin());
out += ", " + varNameProtected + suffix;
if (!zeroit) {
@ -797,6 +798,7 @@ string EmitCFunc::emitVarResetRecurse(const AstVar* varp, bool constructing,
emitVarResetScopeHash();
const uint64_t salt = VString::hashMurmur(varp->prettyName());
out += " = VL_SCOPED_RAND_RESET_";
if (varp->isXTemp()) out += "ASSIGN_";
out += dtypep->charIQWN();
out += "(" + cvtToStr(dtypep->widthMin()) + ", "
+ (m_classOrPackage ? m_classOrPackageHash : "__VscopeHash") + ", "

View File

@ -29,8 +29,6 @@ int main(int argc, const char** argv) {
Verilated::randReset(0);
#elif defined(T_X_ASSIGN_UNIQUE_1)
Verilated::randReset(1);
#elif defined(T_X_ASSIGN_UNIQUE_2)
Verilated::randReset(2);
#endif
VM_PREFIX* top = new VM_PREFIX{};
@ -41,17 +39,7 @@ int main(int argc, const char** argv) {
top->clk = 1;
top->eval();
#if defined(T_X_ASSIGN_UNIQUE_0)
if (top->o_int != 0) {
vl_fatal(__FILE__, __LINE__, "TOP.t", "x assign was not correct");
exit(1);
}
#elif defined(T_X_ASSIGN_UNIQUE_1)
if (top->o_int != -1) {
vl_fatal(__FILE__, __LINE__, "TOP.t", "x assign was not correct");
exit(1);
}
#elif defined(T_X_ASSIGN_UNIQUE_2)
#if defined(T_X_ASSIGN_UNIQUE_0) || defined(T_X_ASSIGN_UNIQUE_1)
if (top->o_int == 0 || top->o_int == -1) {
vl_fatal(__FILE__, __LINE__, "TOP.t", "x assign was not unique");
exit(1);
@ -61,6 +49,13 @@ int main(int argc, const char** argv) {
vl_fatal(__FILE__, __LINE__, "TOP.t", "incorrect module output");
exit(1);
}
uint32_t o_int_expected = EXPECTED ? 0xffffffff : 0;
if (top->o_int != o_int_expected) {
vl_fatal(__FILE__, __LINE__, "TOP.t", "incorrect module output");
exit(1);
}
#endif
VL_DO_DANGLING(delete top, top);

View File

@ -1,24 +0,0 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 by Wilson Snyder. 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-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios("vlt_all")
test.pli_filename = "t/t_x_assign.cpp"
test.top_filename = "t/t_x_assign.v"
test.compile(
make_top_shell=False,
make_main=False,
verilator_flags2=["--x-assign unique --exe", "--x-initial 0", test.pli_filename],
)
test.execute()
test.passes()

View File

@ -12,6 +12,6 @@ rand = 0xf0acf3e4
rand = 0xca0ac74c
rand = 0x4eddfc2c
rand = 0x1919db69
x_assigned = 0x00000000
x_assigned = 0x486aeb2d
Last rand = 0x2d118c9b
*-* All Finished *-*

View File

@ -12,6 +12,6 @@ rand = 0xe85acf2d
rand = 0x15e12c6a
rand = 0x0f7f28c0
rand = 0xe189c52a
x_assigned = 0x00000000
x_assigned = 0x486aeb2d
Last rand = 0xf0700dbf
*-* All Finished *-*