Constraint with variable distribution

I have an index array of bits, and weight array with integer values.
I want to random a variable with constraint to be inside rises bits in the index array with the weight that is in the weight array.

Lets say I have 10 boxes and I want to choose one box from the boxes that ready (to sending). but give a weight to the randomization.

so I have:

bit [9:0] ready_boxes;
int [9:0] weight_box ={10,5,5,7,3,5,5,10,10,50};
rand int chosen_box;

For example:
ready_boxes = 10’b10101;
so the chosen_box should be inside [4,2,0] with dist: 0:=50, 2:=10, 4:=5

how can I implement such a constraint.

Thanks

In reply to brab:



 constraint DIST {     foreach( ready_boxes[i] )
                     {
                         if ( ready_boxes[i] == 1 )
                         {
                           chosen_box dist { i := weight_box[i] }  ; 
                      
                         }
                     }

                 } 


I get warning:
The randomize method call failed. The unique id of the failed randomize call is 297…

In reply to brab:

One issue with code is ::

int [9:0] weight_box ={10,5,5,7,3,5,5,10,10,50}; // Illegal .

Should be ::


bit [9:0] weight_box[$] = '{10,5,5,7,3,5,5,10,10,50} ; 

With the constraint , I do notice an issue . Will update

https://verificationacademy.com/verification-horizons/june-2014-volume-10-issue-2/Use-of-Iterative-Weight-Age-Constraint-to-Implement-Dynamic-Verification-Components

mentions using unpacked array elements both as weight as well as values .
Even the code given under " iterative weight-age constraint " doesn’t work ( Seems like the 2 authors didn’t verify the code )

In reply to brab:


bit [9:0] ready_boxes;
bit [9:0] weight_box[$] ={10,5,5,7,3,5,5,10,10,50};
rand int chosen_box[]; // Changed to Unpacked Array !!
rand int val ;

constraint SIZE { chosen_box.size() == weight_box.size() ; } 

constraint DIST {     foreach( ready_boxes[i] )
                     {
                         if ( ready_boxes[i] == 1 )
                         {
                           chosen_box[i] dist { i := weight_box[i] }  ; 
                         }
                     }
 
                 }

constraint VALUE { val inside { chosen_box } ; } 


Via VALUE constraint would chose any value from chosen_box with equal probability .
Each element of chosen_box would be selected a value with appropriate weight

Not 100% sure if this satisfies the weight distribution too . Please correct me if wrong

In reply to brab:

You must be in the same class as rras.

You need to divide the problem into two pieces. First constrain the chosen_box to the available ready_boxes. Then you need to apply the entire distribution to chosen_box. The values eliminated by the pick_one constraint will be removed from the distribution calculation.

class A;
rand int chosen_box;
bit [9:0] ready_boxes;
int weight_box[9:0] ={10,5,5,7,3,5,5,10,10,50};
constraint pick_one { (ready_boxes >> choosen_box)%2 == 1'b1; }
constraint pick_dist { chosen_box dist {9:=weight_box[9], 
                                        8:=weight_box[8], 
                                        7:=weight_box[7], 
                                        6:=weight_box[6], 
                                        5:=weight_box[5], 
                                        4:=weight_box[4], 
                                        3:=weight_box[3], 
                                        2:=weight_box[2], 
                                        1:=weight_box[1], 
                                        0:=weight_box[0] }; }
endclass

Note: both previous replies are not correct.

Thanks for your answer.
The number of boxes is greater than 10, it defined with define and can be more than 100.
Is there a way to write the pick_dist constraint with a loop?

Thanks!

In reply to brab:

Thanks for your answer.
The number of boxes is greater than 10, it defined with define and can be more than 100.
Is there a way to write the pick_dist constraint with a loop?

It would have helped if you said that up front. dist does not work with a variable number of distribution choices. You can handle the weights manually by selecting a random number in the range of the sum of all the weights.

You can try this, I did not test it.

class A;
  rand int chosen_box;
  bit [9:0] ready_boxes ='b111;
  int weight_box[] ={50,5,5,7,3,5,5,10,10,50};
  int bounding_box[];
  rand int weight;
  function new;
    bounding_box = new[weight_box.size()];
    foreach(weight_box[i]) 
      if (i==0) 
        bounding_box[0]=0;
    else
      bounding_box[i]=bounding_box[i-1]+weight_box[i-1];
  endfunction 
      
  constraint pick_one { (ready_boxes >> chosen_box)%2 == 1'b1; }
  constraint weight_dist {
    weight inside {[0:weight_box.sum()]};
    solve weight before chosen_box;
    foreach(weight_box[i])
      weight inside {[bounding_box[i]:bounding_box[i]+weight_box[i]]} -> i == chosen_box;
  }
endclass