Improve V3Split (#8385)

Various cleanups, simplifications and improvements:
- Build the output bottom up, eliminating AstSplitPlaceholder
- Replace the 'ignore step' pruning with removing the vertices and edges
- Treat an NBA written variable as a block input, enabling more splits
- Move instead of clone leaf statements

Overall V3Split is faster, uses less memory, can do more splits, is
simpler algorithmically, and has half the lines of code in V3Split

Most notably this can now be split, which could not be before:

```systemverilog
always @(posedge clk) begin
    a <= !a;
    if (a) b <= c;
end
```

t_x_rand_mt_stability* pin $random values, but there is one random seed
per C thread, so they depend on which thread runs the block. More
splitting moved that block onto a different thread, so force a single
MTask in those tests to keep them stable.

Some property/assert test changed hit counts due to races, but are now
closer to what might be expected.
This commit is contained in:
Geza Lore
2026-09-17 23:11:26 +02:00
committed by GitHub
parent 2d0eaab5df
commit 1c4c6c9e9d
33 changed files with 533 additions and 751 deletions
-7
View File
@@ -1221,13 +1221,6 @@ public:
ASTGEN_MEMBERS_AstSetuphold;
bool sameNode(const AstNode* /*samep*/) const override { return true; }
};
class AstSplitPlaceholder final : public AstNodeStmt {
public:
// Dummy node used within V3Split; never exists outside of V3Split.
explicit AstSplitPlaceholder(FileLine* fl)
: ASTGEN_SUPER_SplitPlaceholder(fl) {}
ASTGEN_MEMBERS_AstSplitPlaceholder;
};
class AstStackTraceT final : public AstNodeStmt {
// $stacktrace used as task
public:
+327 -686
View File
File diff suppressed because it is too large Load Diff
+4 -1
View File
@@ -18,10 +18,13 @@ module t (
reg [15:0] v3;
integer nosplit;
// Write needed so that V3Dead doesn't kill v0..v3. In its own block, as it only reads
// them, so would split out of the block below anyway.
always @(posedge clk) begin
// write needed so that V3Dead doesn't kill v0..v3
$write(" values %x %x %x\n", v1, v2, v3);
end
always @(posedge clk) begin
// Locally-set 'nosplit' will prevent the if from splitting
// in splitAlwaysAll(). This whole always block should still be
// intact when we call splitReorderAll() which is the subject
+6 -5
View File
@@ -46,12 +46,13 @@ module t (
cyc <= cyc + 1;
if (cyc >= 4) a_drop <= 1'b0;
if (cyc == 19) begin
// Counts pinned to Verilator (NFA per-cycle reject). For all-fail windows
// others are one lower (it does not fire the end-of-sim tick); see the sva
// lessons "multi-cycle end-of-simulation offset" note.
// Counts pinned to Verilator (NFA per-cycle reject). The all-fail windows do not
// include the end-of-simulation tick, as the $finish below takes effect before the
// properties are sampled for this cycle; see the sva lessons "multi-cycle
// end-of-simulation offset" note.
`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(low0_fail_q.size(), 19);
`checkd(low2_fail_q.size(), 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;
@@ -11,7 +11,7 @@ import vltest_bootstrap
test.scenarios('simulator')
test.compile(verilator_flags2=["--binary -fno-reorder"])
test.compile(verilator_flags2=["--binary -fno-reorder -fno-split"])
test.execute(expect_filename=test.golden_filename)
@@ -14,7 +14,7 @@ test.scenarios('simulator')
test.compile(verilator_flags2=["--stats"])
if test.vlt_all:
test.file_grep(test.stats, r'Optimizations, Split always\s+(\d+)', 0)
test.file_grep(test.stats, r'Optimizations, Split always\s+(\d+)', 10)
test.execute()
@@ -55,7 +55,60 @@ module t (
l_split_1 <= l_split_2 | m_din;
end
// (The checker block is an exception, it won't split.)
reg [15:0] p_split_1, p_split_2;
always @(posedge clk) begin
if (m_din != 16'h0) begin
$write("");
p_split_1 <= m_din;
end
p_split_2 <= ~m_din;
end
reg [15:0] q_split_1, q_split_2;
always @(posedge clk) begin
if (m_din[0]) q_split_1 <= 16'h1;
else q_split_2 <= 16'h2;
end
reg [15:0] r_split_mem[0:3];
reg [1:0] r_split_idx = 2'd0;
always @(posedge clk) begin
r_split_mem[r_split_idx] <= m_din;
r_split_idx <= r_split_idx + 2'd1;
end
// Inlining this leaves only its comment behind, as its body is dead
task automatic dead_task;
automatic integer loc;
begin
loc = 1;
end
endtask
integer seed = 1;
reg [15:0] t_split_1, t_split_2;
always @(posedge clk) begin
// Nothing is left under the 'if', but the impure condition keeps its
// vertex, so the condition alone is kept as a statement
if ($random(seed) != 0) begin
dead_task();
end
t_split_1 <= m_din;
t_split_2 <= ~m_din;
end
reg [15:0] u_split_1, u_split_2;
always @(posedge clk) begin
// The same, but this condition reads only block inputs, so the vertex is
// pruned and the 'if' goes altogether
if (m_din[2]) begin
dead_task();
end
u_split_1 <= m_din;
u_split_2 <= ~m_din;
end
// The checker block won't split.
always @(posedge clk) begin
if (cyc != 0) begin
cyc <= cyc + 1;
@@ -70,18 +123,34 @@ module t (
if (!(a_split_1 == 16'hfeed && a_split_2 == 16'hfeed)) $stop;
if (!(d_split_1 == 16'h0112 && d_split_2 == 16'h0112)) $stop;
if (!(h_split_1 == 16'hfeed && h_split_2 == 16'h0112)) $stop;
if (!(p_split_1 == 16'hfeed && p_split_2 == 16'h0112)) $stop;
if (!(q_split_1 == 16'h1)) $stop;
if (!(r_split_idx == 2'd3)) $stop;
if (!(r_split_mem[1] == 16'hfeed && r_split_mem[2] == 16'hfeed)) $stop;
if (!(t_split_1 == 16'hfeed && t_split_2 == 16'h0112)) $stop;
if (!(u_split_1 == 16'hfeed && u_split_2 == 16'h0112)) $stop;
end
if (cyc == 5) begin
m_din <= 16'he22e;
if (!(a_split_1 == 16'he11e && a_split_2 == 16'he11e)) $stop;
if (!(d_split_1 == 16'h0112 && d_split_2 == 16'h0112)) $stop;
if (!(h_split_1 == 16'hfeed && h_split_2 == 16'h0112)) $stop;
if (!(p_split_1 == 16'hfeed && p_split_2 == 16'h0112)) $stop;
if (!(q_split_1 == 16'h1)) $stop;
if (!(r_split_idx == 2'd0 && r_split_mem[3] == 16'hfeed)) $stop;
if (!(t_split_1 == 16'hfeed && t_split_2 == 16'h0112)) $stop;
if (!(u_split_1 == 16'hfeed && u_split_2 == 16'h0112)) $stop;
end
if (cyc == 6) begin
m_din <= 16'he33e;
if (!(a_split_1 == 16'he22e && a_split_2 == 16'he22e)) $stop;
if (!(d_split_1 == 16'h1ee1 && d_split_2 == 16'h0112)) $stop;
if (!(h_split_1 == 16'he11e && h_split_2 == 16'h1ee1)) $stop;
if (!(p_split_1 == 16'he11e && p_split_2 == 16'h1ee1)) $stop;
if (!(q_split_1 == 16'h1 && q_split_2 == 16'h2)) $stop;
if (!(r_split_idx == 2'd1 && r_split_mem[0] == 16'he11e)) $stop;
if (!(t_split_1 == 16'he11e && t_split_2 == 16'h1ee1)) $stop;
if (!(u_split_1 == 16'he11e && u_split_2 == 16'h1ee1)) $stop;
end
if (cyc == 7) begin
$write("*-* All Finished *-*\n");
@@ -11,10 +11,16 @@ import vltest_bootstrap
test.scenarios('simulator')
test.compile(verilator_flags2=["--stats"])
test.compile(verilator_flags2=[
"--stats",
"--timing",
# To fill code coverage
"--dumpi-V3Split",
"9",
])
if test.vlt_all:
test.file_grep(test.stats, r'Optimizations, Split always\s+(\d+)', 4)
test.file_grep(test.stats, r'Optimizations, Split always\s+(\d+)', 0)
test.execute()
@@ -8,8 +8,8 @@ module t (
input clk
);
integer cyc;
initial cyc = 1;
integer cyc = 1;
always @(posedge clk) cyc <= cyc + 1;
reg [15:0] m_din;
@@ -101,10 +101,57 @@ module t (
end
end // always @ (posedge clk)
reg [15:0] n_split_1, n_split_2;
always @(posedge clk) begin
if (cyc != 0) begin
cyc <= cyc + 1;
@(negedge clk);
n_split_1 <= m_din;
n_split_2 <= ~m_din;
end
reg [15:0] o_split_1, o_split_2;
reg [15:0] o_cnt;
always @(posedge clk) begin
o_cnt = 16'h0;
while (o_cnt < m_din) begin
if (m_din[0]) break;
o_cnt = o_cnt + 16'h1;
end
o_split_1 <= m_din;
if (m_din[1]) o_split_2 <= ~m_din;
end
reg [15:0] p_split_1;
reg [15:0] p_cnt;
always @(posedge clk) begin : pblk
p_split_1 <= m_din;
p_cnt = 16'h0;
while (p_cnt < m_din) begin
@(negedge clk);
disable pblk;
end
end
// The same constructs, but outside of any always block
function automatic [15:0] fret(input [15:0] a);
fret = 16'h0;
if (a[0]) return 16'hbeef;
fret = a;
endfunction
reg [15:0] q_init_1, q_init_2, q_init_3;
reg [15:0] q_cnt;
initial begin : qblk
if (m_din == 16'h0) q_init_1 = 16'h1;
q_init_1 <= 16'h2;
q_init_2 = fret(m_din | 16'h1);
q_cnt = 16'h0;
while (q_cnt < (m_din | 16'h1)) begin
q_cnt = q_cnt + 16'h1;
q_init_3 = q_cnt;
disable qblk;
end
end
always @(posedge clk) begin
if (cyc == 1) begin
m_din <= 16'hfeed;
end
@@ -116,6 +163,10 @@ module t (
if (!(f_split_1 == 16'hfeed && f_split_2 == 16'hfeed)) $stop;
if (!(m_split_1 == 16'hfeed && m_split_2 == 16'h0000)) $stop;
if (!(z_split_1 == 16'h0112 && z_split_2 == 16'h0112)) $stop;
if (!(n_split_1 == 16'hfeed && n_split_2 == 16'h0112)) $stop;
if (!(o_split_1 == 16'hfeed)) $stop;
if (!(p_split_1 == 16'hfeed)) $stop;
if (!(q_init_1 == 16'h2 && q_init_2 == 16'hbeef && q_init_3 == 16'h1)) $stop;
end
if (cyc == 5) begin
m_din <= 16'he22e;
@@ -128,6 +179,9 @@ module t (
$stop;
if (!(m_split_1 == 16'hfeed && m_split_2 == 16'h0000)) $stop;
if (!(z_split_1 == 16'h0112 && z_split_2 == 16'h0112)) $stop;
if (!(n_split_1 == 16'he11e && n_split_2 == 16'h1ee1)) $stop;
if (!(o_split_1 == 16'hfeed)) $stop;
if (!(p_split_1 == 16'hfeed)) $stop;
end
if (cyc == 6) begin
m_din <= 16'he33e;
@@ -140,6 +194,9 @@ module t (
$stop;
if (!(m_split_1 == 16'he11e && m_split_2 == 16'h0000)) $stop;
if (!(z_split_1 == 16'h1ee1 && z_split_2 == 16'h0112)) $stop;
if (!(n_split_1 == 16'he22e && n_split_2 == 16'h1dd1)) $stop;
if (!(o_split_1 == 16'he11e && o_split_2 == 16'h1ee1)) $stop;
if (!(p_split_1 == 16'he11e)) $stop;
end
if (cyc == 7) begin
$write("*-* All Finished *-*\n");
@@ -14,7 +14,7 @@ test.scenarios('simulator')
test.compile(verilator_flags2=["--stats", test.wno_unopthreads_for_few_cores])
if test.vlt_all:
test.file_grep(test.stats, r'Optimizations, Split always\s+(\d+)', 12)
test.file_grep(test.stats, r'Optimizations, Split always\s+(\d+)', 13)
test.execute()
+11 -11
View File
@@ -77,22 +77,22 @@ module t (
cyc <= cyc + 1;
crc <= {crc[62:0], crc[63] ^ crc[2] ^ crc[0]};
if (cyc == 19) begin
// Constant-true window [0:3]: K=0..16 succeed at cyc K+3 = 3..19.
`checkd(high_bounded_pass_q.size(), 17); // Other sims: 16
// Constant-true window [0:3]: K=0..15 succeed at cyc K+3 = 3..18.
`checkd(high_bounded_pass_q.size(), 16);
`checkd(high_bounded_pass_q[0], 3); // Other sims: 4
`checkd(high_bounded_pass_q[$], 19);
// Degenerate [0:0]: K=0..19 succeed at cyc K = 0..19.
`checkd(high_degenerate_pass_q.size(), 20); // Other sims: 19
`checkd(high_degenerate_pass_q[0], 0); // Other sims: 0, 1
`checkd(high_degenerate_pass_q[$], 19);
`checkd(high_bounded_pass_q[$], 18);
// Degenerate [0:0]: K=0..18 succeed at cyc K = 0..18.
`checkd(high_degenerate_pass_q.size(), 19);
`checkd(high_degenerate_pass_q[0], 0); // Some other sims: 1
`checkd(high_degenerate_pass_q[$], 18);
// Constant-false: every attempt fails immediately.
`checkd(low_bounded_fail_q.size(), 20); // Other sims: 19
`checkd(low_degenerate_fail_q.size(), 20); // Other sims: 19
`checkd(low_bounded_fail_q.size(), 19);
`checkd(low_degenerate_fail_q.size(), 19);
// CRC + disable streams
`checkd(rand_bounded_pass_q.size(), 0);
`checkd(rand_bounded_fail_q.size(), 20); // Other sims: 19, 11
`checkd(rand_bounded_fail_q.size(), 19); // Some other sims: 11
`checkd(disable_bounded_pass_q.size(), 0);
`checkd(disable_bounded_fail_q.size(), 8); // Other sims: 5, 6
`checkd(disable_bounded_fail_q.size(), 7); // Other sims: 5, 6
$write("*-* All Finished *-*\n");
$finish;
end
+6 -6
View File
@@ -51,16 +51,16 @@ module t (
always @(posedge clk) begin
cyc <= cyc + 1;
if (cyc == 49) begin
// Constant-true [1:33]: K=0..16 succeed at cyc K+33 = 33..49.
`checkd(wide_pass_q.size(), 17);
// Constant-true [1:33]: K=0..15 succeed at cyc K+33 = 33..48.
`checkd(wide_pass_q.size(), 16);
`checkd(wide_pass_q[0], 33);
`checkd(wide_pass_q[$], 49);
`checkd(wide_pass_q[$], 48);
end
if (cyc == 1041) begin
// Constant-true [1:1025]: K=0..16 succeed at cyc K+1025 = 1025..1041.
`checkd(wide_ring_pass_q.size(), 17);
// Constant-true [1:1025]: K=0..15 succeed at cyc K+1025 = 1025..1040.
`checkd(wide_ring_pass_q.size(), 16);
`checkd(wide_ring_pass_q[0], 1025);
`checkd(wide_ring_pass_q[$], 1041);
`checkd(wide_ring_pass_q[$], 1040);
`checkd(wide_fail_q.size(), 1025);
`checkd(wide_fail_q[0], 1025);
`checkd(wide_fail_q[$], 1025);
+2 -2
View File
@@ -55,8 +55,8 @@ module t (
// ovl/novl deltas vs Verilator are 1-cycle preponed-sampling differences.
$display("ovl=%0d novl=%0d impl=%0d nimp=%0d wide=%0d", ovl_f, novl_f, impl_f, nimp_f,
wide_f);
`checkd(ovl_f, 29); // Other sims: 28, one other sim: 5
`checkd(novl_f, 20); // Other sims: 19
`checkd(ovl_f, 28); // One other sim: 5
`checkd(novl_f, 19);
`checkd(impl_f, 9);
`checkd(nimp_f, 0);
`checkd(wide_f, 0);
+1 -1
View File
@@ -36,7 +36,7 @@ module t (
cyc <= cyc + 1;
if (cyc == 10) begin
`checkd(low_s_fail_q.size(), low_w_fail_q.size());
`checkd(low_w_fail_q.size(), 9);
`checkd(low_w_fail_q.size(), 8);
$write("*-* All Finished *-*\n");
$finish;
end
+1 -1
View File
@@ -26,7 +26,7 @@ module t (
always @(posedge clk) begin
cyc <= cyc + 1;
if (cyc == 10) begin
`checkd(vacuous_passes, 10);
`checkd(vacuous_passes, 9);
$write("*-* All Finished *-*\n");
$finish;
end
+2 -1
View File
@@ -11,7 +11,8 @@ import vltest_bootstrap
test.scenarios('vlt')
test.compile(timing_loop=True, verilator_flags2=['--assert', '--timing', '--coverage-user'])
test.compile(timing_loop=True,
verilator_flags2=['--assert', '--timing', '--coverage-user', '-Wno-UNOPTTHREADS'])
test.execute()
@@ -1,3 +1,2 @@
ACTION_RAN
%Error: t/t_property_nfa_stop_error_limit_crossing.v:23: Verilog $stop
Aborting...
-4
View File
@@ -8,8 +8,6 @@
<map from="PSOAAo" to="_Syms"/>
<map from="PS9tBB" to="__024root"/>
<map from="PSm6SZ" to="__PVT__secret_cyc"/>
<map from="PSfqIT" to="__PVT__secret_cyc_r"/>
<map from="PStVCQ" to="__PVT__secret_r"/>
<map from="PSfqS0" to="__PVT__t__DOT__secret_inst"/>
<map from="PSScAO" to="__VactTriggered"/>
<map from="PSrjMj" to="__Vdly__secret_cyc"/>
@@ -19,12 +17,10 @@
<map from="PS76My" to="__Vfunc_dpii_a_func__0__Vfuncout"/>
<map from="PSAZvl" to="__VicoDidInit"/>
<map from="PSk0iX" to="__VicoTriggered"/>
<map from="PSAUcz" to="__Vinline_0__eval_body__nba___Vinline_0__nba_sequent__TOP__0___Vdly__t__DOT__secret_inst2__DOT__secret_cyc"/>
<map from="PSo9XV" to="__VnbaExecute"/>
<map from="PSmzsT" to="__VnbaTriggered"/>
<map from="PSJZmm" to="__Vscopep_t__secret_inst"/>
<map from="PSnH92" to="__VstlTriggered"/>
<map from="PS25fg" to="__Vtask_dpix_a_task__1__i"/>
<map from="PSJN3f" to="__Vtrigprevexpr___TOP__clk__0"/>
<map from="PSGb9V" to="__Vtrigprevexpr___TOP__clk__1"/>
<map from="PSyTg5" to="_ctor_var_reset"/>
+2 -2
View File
@@ -7,11 +7,11 @@ top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8
top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d
rand = 0x5fa24450
rand = 0x24800459
rand = 0xfd8d9d77
rand = 0xb722072d
rand = 0x244113f3
rand = 0x776efb08
x_assigned = 0x08507ff6
Last rand = 0x776efb08
Last rand = 0x8b3a9df4
*-* All Finished *-*
+5 -1
View File
@@ -13,7 +13,11 @@ import glob
test.scenarios("vltmt")
test.top_filename = "t/t_x_rand_stability.v"
test.compile(verilator_flags2=["--x-initial unique"])
# $random has one seed per C thread, so the values printed depend on which thread runs the
# block. Force a single MTask, which then runs on the main thread, to make this stable
# against changes in partitioning.
test.compile(
verilator_flags2=["--x-initial unique", "--threads-max-mtasks 1", "-Wno-UNOPTTHREADS"])
test.execute(all_run_flags=["+verilator+rand+reset+2"], expect_filename=test.golden_filename)
+2 -2
View File
@@ -7,11 +7,11 @@ top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8
top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d
rand = 0x5fa24450
rand = 0x24800459
rand = 0xfd8d9d77
rand = 0xb722072d
rand = 0x244113f3
rand = 0x776efb08
x_assigned = 0x08507ff6
Last rand = 0x776efb08
Last rand = 0x8b3a9df4
*-* All Finished *-*
+4 -1
View File
@@ -12,7 +12,10 @@ import vltest_bootstrap
test.scenarios("vltmt")
test.top_filename = "t/t_x_rand_stability.v"
test.compile(verilator_flags2=["--x-initial unique", "-DADD_SIGNAL"])
# See t_x_rand_mt_stability.py for why a single MTask is forced.
test.compile(verilator_flags2=[
"--x-initial unique", "-DADD_SIGNAL", "--threads-max-mtasks 1", "-Wno-UNOPTTHREADS"
])
test.execute(all_run_flags=["+verilator+rand+reset+2"], expect_filename=test.golden_filename)
@@ -7,11 +7,11 @@ top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8
top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d
rand = 0x5fa24450
rand = 0x24800459
rand = 0xfd8d9d77
rand = 0xb722072d
rand = 0x244113f3
rand = 0x776efb08
x_assigned = 0x08507ff6
Last rand = 0x776efb08
Last rand = 0x8b3a9df4
*-* All Finished *-*
@@ -12,7 +12,10 @@ import vltest_bootstrap
test.scenarios("vltmt")
test.top_filename = "t/t_x_rand_stability.v"
test.compile(verilator_flags2=["--x-initial unique", "-DADD_SIGNAL", "--trace"])
# See t_x_rand_mt_stability.py for why a single MTask is forced.
test.compile(verilator_flags2=[
"--x-initial unique", "-DADD_SIGNAL", "--trace", "--threads-max-mtasks 1", "-Wno-UNOPTTHREADS"
])
test.execute(all_run_flags=["+verilator+rand+reset+2"], expect_filename=test.golden_filename)
@@ -7,11 +7,11 @@ top.t.the_sub_yes_inline_2 no_init 0xa36c65459f4b9f46
top.t.the_sub_yes_inline_1 no_init 0x842cd8b1033a58
top.t.the_sub_no_inline_1 no_init 0x42d55205d10c58f8
top.t.the_sub_no_inline_2 no_init 0xac98037e5042d96d
rand = 0x5fa24450
rand = 0x24800459
rand = 0xfd8d9d77
rand = 0xb722072d
rand = 0x244113f3
rand = 0x776efb08
x_assigned = 0x08507ff6
Last rand = 0x776efb08
Last rand = 0x8b3a9df4
*-* All Finished *-*
@@ -12,7 +12,10 @@ import vltest_bootstrap
test.scenarios("vltmt")
test.top_filename = "t/t_x_rand_stability.v"
test.compile(verilator_flags2=["--x-initial unique", "--trace"])
# See t_x_rand_mt_stability.py for why a single MTask is forced.
test.compile(verilator_flags2=[
"--x-initial unique", "--trace", "--threads-max-mtasks 1", "-Wno-UNOPTTHREADS"
])
test.execute(all_run_flags=["+verilator+rand+reset+2"], expect_filename=test.golden_filename)
@@ -7,11 +7,11 @@ top.t.the_sub_yes_inline_2 no_init 0x0
top.t.the_sub_yes_inline_1 no_init 0x0
top.t.the_sub_no_inline_1 no_init 0x0
top.t.the_sub_no_inline_2 no_init 0x0
rand = 0x5fa24450
rand = 0x24800459
rand = 0xfd8d9d77
rand = 0xb722072d
rand = 0x244113f3
rand = 0x776efb08
x_assigned = 0x08507ff6
Last rand = 0x776efb08
Last rand = 0x8b3a9df4
*-* All Finished *-*
@@ -12,7 +12,10 @@ import vltest_bootstrap
test.scenarios("vltmt")
test.top_filename = "t/t_x_rand_stability.v"
test.compile(verilator_flags2=["--x-initial unique", "-DNOT_RAND"])
# See t_x_rand_mt_stability.py for why a single MTask is forced.
test.compile(verilator_flags2=[
"--x-initial unique", "-DNOT_RAND", "--threads-max-mtasks 1", "-Wno-UNOPTTHREADS"
])
test.execute(all_run_flags=["+verilator+rand+reset+0"], expect_filename=test.golden_filename)