cyclic randomization of array in SV

cyclic randomization of array in SV

Defining a class variable as randc will result in cyclic randomization, meaning that all the values in a range will be obtained before a new cycle begins and the values will repeat.

But what if we want to randomize an array and obtain a different permutation in each randomization in a cyclic manner?

Spoiler! The code below won't have the work done :

randc int array [array_size] ;        

Let's see how it can be done, and to make the example more fun I'll add some constraints:

  • The values in the array must be unique, i.e. no two array members are equal.
  • The array represents a set, i.e. the order of the array-members doesn't matter. In example, if array_size=2 -> '{1,3} and '{3,1} are considered the same, and should not be repeated until the cycle is not finished.
  • The array_size in the example is going to be 6, and the values range is [1:7]. In that case the cycle is 7, because we have exactly 7 unique permutations given the above constraints - each permutation missing one of the 7 valid values.

Here is the code :

class Permutations #(int arr_size = 6, int max_number = 7) ;
? ?const int num_of_perm = calc_num_of_perm(arr_size, max_number) ;
? ? ? ? ?int arr [arr_size] ;
? ?rand? bit [0:arr_size-1][$clog2(max_number)-1 : 0] packed_arr ;
? ? ? ? ?bit [arr_size*$clog2(max_number)-1 : 0] list [$] ;

? ?constraint c_sorted {
? ? ? foreach (packed_arr[i])
? ? ? ? ?if (i > 0)
? ? ? ? ? ? packed_arr[i] > packed_arr[i-1] ;
? ?}
? ?constraint c_range {
? ? ? foreach (packed_arr[i])
? ? ? ? ?packed_arr[i] inside {[1:max_number]} ;
? ?}
? ?constraint c_not_in_list {
? ? ? !(packed_arr inside {list}) ;
? ?}
//---Functions---
? ?function void post_randomize() ;
? ? ? if (list.size == num_of_perm - 1)
? ? ? ? ?list.delete() ;
? ? ? else
? ? ? ? ?list.push_back(packed_arr) ;
? ? ? foreach (packed_arr[i])
? ? ? ? ?arr[i] = int'(packed_arr[i]) ;
? ?endfunction
//---
? ?function int factorial (int arr_size) ;
? ? ? if (arr_size == 1)
? ? ? ? ?return 1 ;
? ? ? else?
? ? ? ? ?return arr_size * factorial(arr_size-1) ;
? ?endfunction
//---
? ?function int calc_num_of_perm (int arr_size, int max_number) ;
? ? ? int result = 1;
? ? ? for (int i = 0; i < arr_size; i++)
? ? ? ? ?result *= (max_number - i) ;
? ? ? result = result / factorial(arr_size) ;
? ? ? return result ;
? ?endfunction
endclass        

  • c_sorted will result in sorted array, and taking care of both first two constraints mentioned earlier.
  • list holds all permutations that already happened. we just need not to forget to empty it when all unique permutations happened to restart the cycle. The total number of unique permutations calculated in?calc_num_of_perm(). The list gets updated in the post_randomize(). packed array also copied to unpacked array in that step.

Beware! making arr also rand and adding the next constraint may look harmless but will result in much greater solving time.

foreach (arr[i])
   arr[i] == packed_arr[i] ;         

Here is a simple testbench to check the results:

module perm_tb ;
? ?Permutations my_perm ;
? ?initial begin
? ? ? my_perm = new() ;
? ? ? for (int i=0; i<10; i++) begin
? ? ? ? ?void'(my_perm.randomize()) ;
? ? ? ? ?$display("%p", my_perm.arr) ;
? ? ? end
? ?end
endmodule        

And the results. We can easily see that the first 7 arrays are unique, and then the cycle restarts.

'{1, 2, 3, 4, 6, 7}
'{1, 2, 4, 5, 6, 7}
'{1, 2, 3, 4, 5, 7}
'{1, 2, 3, 4, 5, 6}
'{1, 3, 4, 5, 6, 7}
'{1, 2, 3, 5, 6, 7}
'{2, 3, 4, 5, 6, 7}
'{1, 2, 4, 5, 6, 7}
'{2, 3, 4, 5, 6, 7}
'{1, 2, 3, 4, 5, 6}        

Can you think of other ways to have the job done? What do you think about my solution?

要查看或添加评论,请登录

Michael Fugenfirov的更多文章

社区洞察

其他会员也浏览了