Rsort() for Multidimensional Array

I have 2-D unpacked array whose elements I need to sort in descending order .

Unfortunately SystemVerilog doesn’t allow rsort() on multidimensional arrays .


bit [31:0]  multi_array[5][int] ;
bit [31:0]  max_to_min[int] ;     //  Will  store  elements  from  multi_array  in  Max  to  Min  Order .

initial  begin
  
  //  Populating  array  
  for( int i = 4 ; i >= 0 ; i-- ) begin
     for( int j = ( i > 0 ) ? ( i - 1 ) : 0 ; j >= 0 ; j-- ) begin

       multi_array[i][j]  = i + j ;

     end
  end

  //  Logic  to  rsort() 
  
  //  multi_array.rsort()  //  Illegal 
  
end

Does SystemVerilog provide any alternative method to sort / reverse-sort for multi-dimensional arrays ?

In reply to MICRO_91:

You can stream the multi dimensional array into a linear array, perform your sort, and then put the array back in an order that suits you (you cannot use the streaming operator to target an associative array).

bit [31:0]  multi_array[5][int] ;
bit [31:0]  linear_array[$] ;

{>>{linear_array}} = multi_array;
linear_array.rsort;
foreach(multi_array[r,c]) multi_array[r][c] = linear_array.pop_front();

In reply to dave_59:

Thanks Dave , the solution works .

Wanted your thoughts on the following ::


 bit [31:0] max_to_min[5][int];   //  Same  as  bit [31:0] max_to_min[0:4][int];

I observe same output on using ::


 linear_array = { >>{ array } }; 
//  { >>{ array } }  is  same  as  ::
//  { array[0][0] , array[1][0] , array[2][0] , array[2][1] , ... , array[3][0] , array[3][1] , array[3][2] }

As a result


 q[0] =  array[0][0] ;  q[1] =  array[1][0] ;  q[2] =  array[2][0] ;  q[3] =  array[2][1] ; ...
 q[7] =  array[4][0] ; q[8] =  array[4][1] ; q[9] =  array[4][2] ; q[10] =  array[4][3] ;

How does the streaming operator on LHS work ?


 {<<{linear_array}} = array;  versus  {>>{linear_array}} = array;

How is RHS i.e array processed in both cases ?

In reply to MICRO_91:

When the LHS and RHS are both single variables, it makes no difference which side the streaming operators appear.

Realize your array is actually 3-dimensions 2-unpacked and 1-packed. The << or >> determines whether the MSBs get selected from left to right or right to left.

In reply to dave_59:

I’m trying the following code:


rand bit [5:0] multi_array [0:2][0:2];
..
..
	{>>{linear_array}} = multi_array;
	{<<{linear_array_ii}} = multi_array;

I get the following results:


multi_array = '{'{'h31, 'h33, 'h1b}, '{'h3a, 'h20, 'h39}, '{'h3b, 'h1f, 'h12}}
linear_array = '{'h3b, 'h3a, 'h39, 'h33, 'h31, 'h20, 'h1f, 'h1b, 'h12}
linear_array_ii = '{'h12, 'h3e, 'h37, 'h27, 'h1, 'h17, 'h36, 'h33, 'h23}

linear_array_ii shows entirely different entries compared to multi_array.
for ex:- 'h37, 'h1, 'h27 etc., are not present in multi_array entries.

Could you help explaining what is the difference between LHS and RHS streaming operator.

Thank you.

In reply to natasv:

You need to show a complete example. << vs >> is right-to-left versus left-to-right streaming.

In reply to dave_59:


class multidsort;
rand bit [5:0] multi_array [0:2][0:2];
bit [5:0]  linear_array[$] ;
bit [5:0]  linear_array_ii[$] ;

task sortmulti_array();
	{>>{linear_array}} = multi_array;
	{<<{linear_array_ii}} = multi_array;
	
	linear_array.rsort;
	$display("multi_array = %p",multi_array);
	$display("linear_array = %p",linear_array);
	$display("linear_array_ii = %p",linear_array_ii);
endtask
endclass


module top();

initial begin
	multidsort multidsort_ii;
	multidsort_ii = new();
	multidsort_ii.randomize();

	multidsort_ii.sortmulti_array();
end

endmodule

Result:


> run
multi_array = '{'{'h31, 'h33, 'h1b}, '{'h3a, 'h20, 'h39}, '{'h3b, 'h1f, 'h12}}
linear_array = '{'h3b, 'h3a, 'h39, 'h33, 'h31, 'h20, 'h1f, 'h1b, 'h12}
linear_array_ii = '{'h12, 'h3e, 'h37, 'h27, 'h1, 'h17, 'h36, 'h33, 'h23}

In reply to natasv:

It would be clearer if you filled the array with a fixed pattern of numbers instead of random values, then displayed the arrays in binary. Then you would see how the streaming operator fills the array.

class multidsort;
  bit [5:0] multi_array [0:2][0:2];
  function new;
    int v;
    foreach(multi_array[i,j]) multi_array[i][j] = v++;
  endfunction
  
  bit [5:0]  linear_array[$] ;
  bit [5:0]  linear_array_ii[$] ;
 
task sortmulti_array();
	{>>{linear_array}} = multi_array;
	{<<{linear_array_ii}} = multi_array;
 
	$displayb("multi_array = %p",multi_array);
	$displayb("linear_array = %p",linear_array);
  	$displayb("linear_array_ii = %p",linear_array_ii);

  	linear_array.rsort;
  	linear_array_ii.rsort;
    $display("rsort");
  	$displayb("linear_array = %p",linear_array);
	$displayb("linear_array_ii = %p",linear_array_ii);
endtask
endclass
 
 
module top();
 
initial begin
	multidsort multidsort_ii;
	multidsort_ii = new(); 
	multidsort_ii.sortmulti_array();
end
 
endmodule

This displays

# multi_array = '{'{000000, 000001, 000010}, '{000011, 000100, 000101}, '{000110, 000111, 001000}}
# linear_array = '{000000, 000001, 000010, 000011, 000100, 000101, 000110, 000111, 001000}
# linear_array_ii = '{000100, 111000, 011000, 101000, 001000, 110000, 010000, 100000, 000000}
# rsort
# linear_array = '{001000, 000111, 000110, 000101, 000100, 000011, 000010, 000001, 000000}
# linear_array_ii = '{111000, 110000, 101000, 100000, 011000, 010000, 001000, 000100, 000000}

Now you can see that the bit pattern for linear_array_ii is reversed because {<<{}} operator was used.

In reply to dave_59:

Thank you.