[dv,cip] Rewrite `_DV_MUBI_DIST to avoid warnings#29330
[dv,cip] Rewrite `_DV_MUBI_DIST to avoid warnings#29330rswarbrick wants to merge 1 commit intolowRISC:masterfrom
Conversation
dedcac0 to
80bf0aa
Compare
|
Dammit! Just realised that I had an off-by-one error in the commit message. Take |
80bf0aa to
c6afdee
Compare
marnovandermaas
left a comment
There was a problem hiding this comment.
I think it's not quite right, so I've made a suggestion.
hw/dv/sv/cip_lib/cip_macros.svh
Outdated
| 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_) \ | ||
| }; |
There was a problem hiding this comment.
| 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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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>
c6afdee to
837e8c7
Compare
It turns out that randomising with a distribution like this
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:
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:
and will now have fractions like
Generalising to the macro, there are (MAX_ - 1) possible values (instead of 10), so we need to scale up by (MAX_ - 3).