Foreach usage in randomization constraints

Hi,

I tried to generate the bath-tub curve distribution using the constraint posted on this verification academy page but got run-time error from the constraint used in it.

Here is the constraint used in the page

int a[5] = '{1, 11, 21, 31, 41};
  int b[5] = '{10, 20, 30, 40, 50};
  int c[5] = '{30, 15, 10, 15, 30};
  
constraint c_value { foreach (a[i])
value dist { [a[i]:b[i]] :/ c[i] };
}

And during runtime, I got the following errors.
"
**Solver failed when solving following set of constraints

integer a[2] = 21;
integer b[2] = 30;
integer c[2] = 10;
integer a[3] = 31;
integer b[3] = 40;
integer c[3] = 15;
rand integer value; // rand_mode = ON

constraint c_value // (from this) (constraint_mode = ON) (testbench.sv:10)
{
(value dist {[a[2]:b[2]] :/ c[2]});
(value dist {[a[3]:b[3]] :/ c[3]});
}

=======================================================**
"
Then I manually unrolled the foreach distribution and it worked as expected.

constraint c_value{
    value dist{
      [1:11]:/30,
      [11:20]:/15,
      [21:30]:/10,
      [31:40]:/15,
      [41:50]:/30
    };
  }

Thus I wonder why the first distribution constraints that use “foreach” will cause the solver to fail?

Thanks in advance for your help!

In reply to peterjin:

We can’t have multiple dist constraints on the same random variable with different sets of values.
So this is just pseudo code like stuff.

constraint c_value { 
    foreach (a[i])
      value dist { [a[i]:b[i]] :/ c[i] };
}

solver failure because that code looks like this:
value has 5 different dist constraints and conflict to each other

constraint c_value { 
      value dist { [a[0]:b[0]] :/ c[0] };
      value dist { [a[1]:b[1]] :/ c[1] };
      value dist { [a[2]:b[2]] :/ c[2] };
      value dist { [a[3]:b[3]] :/ c[3] };
      value dist { [a[4]:b[4]] :/ c[4] };
}

and it seems compiler doesn’t support this yet.
so it’s tough to making bath-tub curve smooth (depending on giving dynamic array size, e.g. a/b/c size),

any good way to making long dist block short, I don’t have a good idea yet.

constraint c_value { 
    value dist { 
       foreach (a[i])
         [a[i]:b[i]] :/ c[i];
    };
}

In reply to javatea:

Hi Javatea,

Thanks for your explanation!

Yes, it seems pretty hard to make the long dist block short, since foreach cannot be used inside dist{}.

Thanks

Hao

In reply to peterjin:

I believe the article was showing pseudo-code as a concept. You cannot use a dist constraint without a fixed list of values. There are other ways of constructing random distributions. One way is to select a random number to use in a series of implications where only one can be selected:

class A;
   rand int value;
 
   int a[5] = '{1, 11, 21, 31, 41};
   int b[5] = '{10, 20, 30, 40, 50};
   int c[5] = '{30, 15, 10, 15, 30};
   int d[6] = {0, 30, 45, 55, 70, 100}; // could be computed from c
   rand int range;
   constraint c_range {range inside {[d[$low(d)]:d[$high(d)]-1]};
      solve range before value; } // prevents c_value from skewing distribution
   constraint c_value {foreach (a[ii])
		       range inside {[d[ii]:d[ii+1]-1]} ->
		                        value inside {[a[ii]:b[ii]]};}
endclass

In reply to dave_59:

Hi Dave,

Very good idea.
Another method using $dist_normal(seed, mean, std);
By given range related config, then val will be a bath-tub curve in this range.

class A;
 
   rand int norm;
   // range config
   int high = 100;
   int low = 0;
   int mean = 50;
   int std = 20;
   int val;
   
  constraint c { 
    norm == normal(mean);
  }
  
  function int normal(int mean);
    return $dist_normal($urandom(), mean, std);
  endfunction
  
  function void post_randomize();
    if (norm inside {[low:high]}) begin
      val = high - norm;
    end 
    // val within designed range will be bath-tub
  endfunction
  
endclass : A

In reply to dave_59:
Hi Dave,

That’s really a brilliant way to generate bath tub curve.

Thanks so much for your help!

Hao

In reply to javatea:

Have you verified that you code produces the expected curve? And what is val supposed to be when norm falls outside the low/high range?

In reply to dave_59:

Hi Dave,

I assume we could discard the val outside of the range from the caller.
if we really want to make all val within range, then just do the following:

function int normal(int mean);
    do begin
       normal = $dist_normal($urandom(), mean, std);
    end while (!(normal inside {[low:high]}));
    return normal;
  endfunction

In reply to javatea:

A while loop might work in this particular case, but you can get stuck into an infinite loop in other cases. That is why we feed our constraints to a constraint solver which has to prove a solution exists before generating a particular solution.

And I do not think your equation gives the desired curve. It simple flips the curve as a mirror image.

In reply to dave_59:

I just try to provide a solution to have more smooth curve without hardcoded a/b/c/d array definition. with a/b/c/d fixed array, we can’t have a smooth curve unless you want to define huge array.
if the user provides bad std/mean/seed, it might break $dist_normal for sure.
everything can be fixed, e.g. just put an iteration_count in while loop to catch this issue.

In reply to dave_59:

Hi Dave,

I have a question related to using ‘dist’ operator inside a foreach loop in a systemverilog constraint. I need to generate array elements with values according to a distribution pattern. But, I’m concerned if calling ‘dist’ operator for each element will cause unintended distribution. Can you help?

Eg.

constraint c_value {
a[i].size() == 50;
foreach (a[i])
a[i] dist { [1:5] :/ 1, [6:7] :/ 1, [8:9] :/ 2};
}

  
constraint value_c{
    foreach(c1[i]){
      (num == i) dist {1:=c1[i],0:=(100-c1[i])};
    }
    num inside {[0:($size(c1)-1)]};
    solve num before value;
    value inside {[a1[num]:b1[num]]};

In reply to Rabh_91:

Each element will have the intended distribution. The loop gets unrolled into individual constraints so that the distribution of one element has no effect on the distribution of another element.