Array randomization issue

Hi all,

I have a predefined array of struts (150 elements), and based on the array I should get another array (or queue) as a result of randomization. Newly created one should be the same type, but should contain less elements, and elements should be picked up from the original array.
Here is simplified pseudocode:


// type
typedef struct {string name;
                int param_1;
                int param_2;
                } traffic_t;

// predefined array
traffic_t trafic[] = '{
  '{name_1, num_11, num_12}, 
  '{name_2, num_21, num_22},
  '{name_3, num_31, num_32},
  '{name_4, num_41, num_42},  
//... 
  '{name_150, num_1501, num_1502}
};

Based on the array I should generate its reduced version, with following constraints:

  • it is not said how many elements reduced array should have, and it is should be randomly chosen
  • sum of all param_1 fields of newly created array should be == SUM_OF_PARAM_1
  • sum of all param_2 fields of newly created array should be <= SUM_OF_PARAM_2
  • the same element can appear multiple times in new array

As an example, as a result of randomization new array can contain following elements, if constraints are satisfied:


new_array[] = '{
  '{name_3,   num_31,  num_32},
  '{name_19,  num_191, num_192},
  '{name_3,   num_31,  num_32},
  '{name_120, num_120, num_120}};

I have problem to set proper constraints. I tried with:


rand traffic_t new_array[$];

  constraint c1 {
      new_array.sum(item) with (int'(item.param_1)) == PARAM_1_RATE;
	}
  constraint c2 {
      new_array.sum(item) with (int'(item.param_2)) <= PARAM_2_RATE;
	}

but it doesnt work, because all simulators I tried have tendency to start picking up elements from the beginning, instead of picking up them randomly from original array. In pseudocode I’m getting something like this:


new_array[] = '{
  '{name_1, num_11, num_12}, 
  '{name_2, num_21, num_22},
  '{name_3, num_31, num_32},
  '{name_4, num_41, num_42}};

Does anybody understand why it happens?
Any idea how to set constraints properly?

Thank you
Marko

In reply to nedicm:

How did you constrain elements in new_array are from pre-defined trafic array?

In reply to nedicm:


    class Simple;
        
        typedef struct {
               string name;
               rand int unsigned param_1;
               rand int unsigned param_2;
        } traffic_t;
        
        traffic_t trafic[];
        rand traffic_t new_array[];
        rand int N[]; //helper
        int SUM_OF_PARAM_1 = 50;
        int SUM_OF_PARAM_2 = 25;
 
        function new();
             trafic = new[1000];
             foreach(trafic[i]) begin
                 $sformat(trafic[i].name,"name_%0d",i);
                 trafic[i].param_1 = $urandom_range(0,20);
                 trafic[i].param_2 = $urandom_range(0,20);
             end
        endfunction

        constraint c1 {
                new_array.size() inside {[1:10]};
                N.size() == new_array.size();
                foreach(N[i]) N[i] inside {[0:trafic.size()-1]};  
                foreach(new_array[i]) { 
                    new_array[i].param_1 == trafic[N[i]].param_1; 
                    new_array[i].param_2 == trafic[N[i]].param_2; 
                } 
                new_array.sum() with(int'(item.param_1)) == SUM_OF_PARAM_1;
                new_array.sum() with(int'(item.param_2)) <= SUM_OF_PARAM_2;
        }

        function void post_randomize();
                foreach(new_array[i]) begin new_array[i].name = trafic[N[i]].name; end
        endfunction 
    
    endclass



https://www.linkedin.com/in/patel-rahulkumar/

In reply to Rahulkumar:

Hi Rahulkumar,
what is the meaning of helper?
Thanks

In reply to Rahulkumar:

In reply to nedicm:


class Simple;
typedef struct {
string name;
rand int unsigned param_1;
rand int unsigned param_2;
} traffic_t;
traffic_t trafic[];
rand traffic_t new_array[];
rand int N[]; //helper
int SUM_OF_PARAM_1 = 50;
int SUM_OF_PARAM_2 = 25;
function new();
trafic = new[1000];
foreach(trafic[i]) begin
$sformat(trafic[i].name,"name_%0d",i);
trafic[i].param_1 = $urandom_range(0,20);
trafic[i].param_2 = $urandom_range(0,20);
end
endfunction
constraint c1 {
new_array.size() inside {[1:10]};
N.size() == new_array.size();
foreach(N[i]) N[i] inside {[0:trafic.size()-1]};  
foreach(new_array[i]) { 
new_array[i].param_1 == trafic[N[i]].param_1; 
new_array[i].param_2 == trafic[N[i]].param_2; 
} 
new_array.sum() with(int'(item.param_1)) == SUM_OF_PARAM_1;
new_array.sum() with(int'(item.param_2)) <= SUM_OF_PARAM_2;
}
function void post_randomize();
foreach(new_array[i]) begin new_array[i].name = trafic[N[i]].name; end
endfunction 
endclass


https://www.linkedin.com/in/patel-rahulkumar/

Hi,

Did you actually try to run your code in a simulator? I tried it and the simulator is unable to solve. I think the following 2 constraints, makes it hard for the constraint to solve.

new_array.sum() with(int'(item.param_1)) == SUM_OF_PARAM_1;
new_array.sum() with(int'(item.param_2)) <= SUM_OF_PARAM_2;

There is no guarantee that sum of param1 in original array is equal to SUM_OF_PARAM_1. I think the constraint for that should also be <= SUM_OF_PARAM1. Then it’ll work.

By the way curious to know why name is not assigned in the constraint, but done in post_randomize?