Skip to content

Comments

[dv,cip] Rewrite `_DV_MUBI_DIST to avoid warnings#29330

Open
rswarbrick wants to merge 1 commit intolowRISC:masterfrom
rswarbrick:dv-mubi-dist
Open

[dv,cip] Rewrite `_DV_MUBI_DIST to avoid warnings#29330
rswarbrick wants to merge 1 commit intolowRISC:masterfrom
rswarbrick:dv-mubi-dist

Conversation

@rswarbrick
Copy link
Contributor

@rswarbrick rswarbrick commented Feb 17, 2026

It turns out that randomising with a distribution like this

  if (0) {
    XYZ dist { [1:0] := 1; };
  }

generates a runtime warning from Xcelium (even though the distribution expression isn't actually used).

Fortunately, range endpoints can be general expressions, so we can do everything with ternary operators instead. We can also avoid repeating stuff if we define MIN / MAX macros.

This commit also fixes the weighting for true/false. Suppose we want to distribute with weights ZeroW, OneW, OtherW for 0, 1, other in a way that e.g. the fraction of ones is OneW / (ZeroW + OneW + OtherW).

The following would definitely be wrong:

 value dist { 0      := ZeroW,
              1      := OneW,
              [2:9] := OtherW };

Because there are eight "other" values, the fractions end up looking like OneW / (ZeroW + OneW + 8 * OtherW). Oops!

To make everything line up properly, we multiply by 8:

 value dist { 0      := 8 * ZeroW,
              1      := 8 * OneW,
              [2:9] := OtherW };

and will now have fractions like

 8 * OneW / (8 * ZeroW + 8 * OneW + 8 * OtherW
  =
 OneW / (ZeroW + OneW + OtherW)

Generalising to the macro, there are (MAX_ - 1) possible values (instead of 10), so we need to scale up by (MAX_ - 3).

@rswarbrick rswarbrick requested a review from a team as a code owner February 17, 2026 11:40
@rswarbrick rswarbrick removed the request for review from a team February 17, 2026 11:40
@rswarbrick rswarbrick added the Component:DV DV issue: testbench, test case, etc. label Feb 17, 2026
@rswarbrick
Copy link
Contributor Author

rswarbrick commented Feb 17, 2026

Dammit! Just realised that I had an off-by-one error in the commit message. Take 2 3...

Copy link
Contributor

@marnovandermaas marnovandermaas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's not quite right, so I've made a suggestion.

Comment on lines 85 to 92
VAR_ dist { \
TRUE_ := (T_WEIGHT_) * ((MAX_) - 3), \
FALSE_ := (F_WEIGHT_) * ((MAX_) - 3), \
[0 : `DV_TERNARY_MIN(TRUE_, FALSE_)-1] := (OTHER_WEIGHT_), \
[(`DV_TERNARY_MIN(TRUE_, FALSE_)+1) : \
(`DV_TERNARY_MAX(TRUE_, FALSE_)-1)] := (OTHER_WEIGHT_), \
[(`DV_TERNARY_MAX(TRUE_, FALSE_)+1):(MAX_)] := (OTHER_WEIGHT_) \
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
VAR_ dist { \
TRUE_ := (T_WEIGHT_) * ((MAX_) - 3), \
FALSE_ := (F_WEIGHT_) * ((MAX_) - 3), \
[0 : `DV_TERNARY_MIN(TRUE_, FALSE_)-1] := (OTHER_WEIGHT_), \
[(`DV_TERNARY_MIN(TRUE_, FALSE_)+1) : \
(`DV_TERNARY_MAX(TRUE_, FALSE_)-1)] := (OTHER_WEIGHT_), \
[(`DV_TERNARY_MAX(TRUE_, FALSE_)+1):(MAX_)] := (OTHER_WEIGHT_) \
};
VAR_ dist { \
TRUE_ :/ T_WEIGHT_, \
FALSE_ :/ F_WEIGHT_, \
[0 : `DV_TERNARY_MIN(TRUE_, FALSE_)-1] :/ (OTHER_WEIGHT_) * (`DV_TERNARY_MIN(TRUE_, FALSE_) / MAX_), \
[(`DV_TERNARY_MIN(TRUE_, FALSE_)+1) : \
(`DV_TERNARY_MAX(TRUE_, FALSE_)-1)] :/ (OTHER_WEIGHT_) / ((MAX_ - 2) / (2*MAX_)), \
[(`DV_TERNARY_MAX(TRUE_, FALSE_)+1):(MAX_)] :/ (OTHER_WEIGHT_) / ((MAX_-`DV_TERNARY_MAX(TRUE_, FALSE_)) / MAX_) \
};

I think it may be simpler to use the proportional distribution :/ instead of the weighted distribution. Also I think there is an error with the other weight, shouldn't this be split among the three other values? I've tried to add a proportion to the expression, although admittedly the code is a bit ugly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahah: that was the whole reason for Matutem's original change. The problem is that I might have e.g. MAX=9, True=0, False=2. Then I'd end up with something like

var dist {
  0      :/ T_WEIGHT,
  2      :/ F_WEIGHT,
  [1:1] :/ OTHER_WEIGHT,
  [3:9] :/ OTHER_WEIGHT

This doesn't balance out properly (factor of two because there are two "other" ranges). But the "other" values also are biased because the ranges are different lengths. I think you have to use := to solve the latter problem.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry: I hadn't read your suggestion properly. Is your proposal to weight the ranges by their lengths? In which case, I guess it would work, except for the fact that I think the weights have to be integral. I think the end result is probably a bit more complicated than what we've got (possibly why Matute did it that way).

It turns out that randomising with a distribution like this

  if (0) {
    XYZ dist { [1:0] := 1; };
  }

generates a runtime warning from Xcelium (even though the distribution
expression isn't actually used).

Fortunately, range endpoints can be general expressions, so we can do
everything with ternary operators instead. We can also avoid repeating
stuff if we define `MIN / `MAX macros.

This commit also fixes the weighting for true/false. Suppose we want
to distribute with weights ZeroW, OneW, OtherW for 0, 1, other in a
way that e.g. the fraction of ones is OneW / (ZeroW + OneW + OtherW).

The following would definitely be wrong:

 value dist { 0      := ZeroW,
              1      := OneW,
              [2:9] := OtherW };

Because there are eight "other" values, the fractions end up looking
like OneW / (ZeroW + OneW + 8 * OtherW). Oops!

To make everything line up properly, we multiply by 8:

 value dist { 0      := 8 * ZeroW,
              1      := 8 * OneW,
              [2:9] := OtherW };

and will now have fractions like

 8 * OneW / (8 * ZeroW + 8 * OneW + 8 * OtherW
  =
 OneW / (ZeroW + OneW + OtherW)

Generalising to the macro, there are (MAX_ - 1) possible
values (instead of 10), so we need to scale up by (MAX_ - 3).

Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Component:DV DV issue: testbench, test case, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants