diff --git a/test_regress/t/t_constraint_dist_foreach_if.v b/test_regress/t/t_constraint_dist_foreach_if.v index 5d6f1b2ec..2bbf740df 100644 --- a/test_regress/t/t_constraint_dist_foreach_if.v +++ b/test_regress/t/t_constraint_dist_foreach_if.v @@ -6,10 +6,19 @@ // Test that dist constraints nested inside if / -> inside foreach produce // values only within the declared distribution and cover all buckets. +// +// The bucket draw must also be made PER ELEMENT, not once per solve and then +// shared by every element. Counting buckets across all solves cannot tell those +// apart: a single hoisted draw still hits both buckets over 100 solves, it just +// never mixes them inside one solve. So each block also counts solves in which +// at least one element landed in each bucket. With dist {0 := 3, [1:4] := 1} +// over 4 elements a per-element draw mixes in about 86 of 100 solves, whereas a +// hoisted draw can never mix and gives exactly 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); +`define check_mixed(what,gotv) do if ((gotv) == 0) begin $write("%%Error: %s:%0d: dist inside foreach+%s: bucket draw is not per-element, no solve mixed buckets\n", `__FILE__,`__LINE__, what); `stop; end while(0); // verilog_format: on // foreach (a[i]) if (gate) a[i] dist {...} @@ -64,10 +73,14 @@ module t; begin static ClsIf obj = new(); int seen_zero, seen_nonzero; + int this_zero, this_nonzero, mixed; obj.gate = 1'b1; seen_zero = 0; seen_nonzero = 0; + mixed = 0; repeat (100) begin + this_zero = 0; + this_nonzero = 0; `checkd(obj.randomize(), 1) foreach (obj.a[i]) begin if (obj.a[i] > 4) begin @@ -75,9 +88,16 @@ module t; obj.a[i]); $stop; end - if (obj.a[i] == 0) seen_zero++; - else seen_nonzero++; + if (obj.a[i] == 0) begin + seen_zero++; + this_zero++; + end + else begin + seen_nonzero++; + this_nonzero++; + end end + if (this_zero > 0 && this_nonzero > 0) mixed++; end if (seen_zero == 0 || seen_nonzero == 0) begin $write( @@ -85,16 +105,21 @@ module t; `__FILE__, `__LINE__, seen_zero, seen_nonzero); $stop; end + `check_mixed("if", mixed) end // Test -> (implication) form begin static ClsImpl obj = new(); int seen_zero, seen_nonzero; + int this_zero, this_nonzero, mixed; obj.gate = 1'b1; seen_zero = 0; seen_nonzero = 0; + mixed = 0; repeat (100) begin + this_zero = 0; + this_nonzero = 0; `checkd(obj.randomize(), 1) foreach (obj.a[i]) begin if (obj.a[i] > 4) begin @@ -102,9 +127,16 @@ module t; obj.a[i]); $stop; end - if (obj.a[i] == 0) seen_zero++; - else seen_nonzero++; + if (obj.a[i] == 0) begin + seen_zero++; + this_zero++; + end + else begin + seen_nonzero++; + this_nonzero++; + end end + if (this_zero > 0 && this_nonzero > 0) mixed++; end if (seen_zero == 0 || seen_nonzero == 0) begin $write( @@ -112,17 +144,22 @@ module t; `__FILE__, `__LINE__, seen_zero, seen_nonzero); $stop; end + `check_mixed("->", mixed) end // Test doubly-nested -> (chained implication) form begin static ClsImplChained obj = new(); int seen_zero, seen_nonzero; + int this_zero, this_nonzero, mixed; obj.gateA = 1'b1; obj.gateB = 1'b1; seen_zero = 0; seen_nonzero = 0; + mixed = 0; repeat (100) begin + this_zero = 0; + this_nonzero = 0; `checkd(obj.randomize(), 1) foreach (obj.a[i]) begin if (obj.a[i] > 4) begin @@ -130,9 +167,16 @@ module t; obj.a[i]); $stop; end - if (obj.a[i] == 0) seen_zero++; - else seen_nonzero++; + if (obj.a[i] == 0) begin + seen_zero++; + this_zero++; + end + else begin + seen_nonzero++; + this_nonzero++; + end end + if (this_zero > 0 && this_nonzero > 0) mixed++; end if (seen_zero == 0 || seen_nonzero == 0) begin $write( @@ -140,6 +184,7 @@ module t; `__FILE__, `__LINE__, seen_zero, seen_nonzero); $stop; end + `check_mixed("->->", mixed) end $write("*-* All Finished *-*\n");