Variable slicing of a fixed size packed array in systemverilog

I’m doing something like this in SV but it gives me error.

`define s 8
int array[31:0];
int size =`s;
int queue[$];
task t();
  for(int i=31;i>=0;i-=size )
   queue.push_back(array[i-:size]);          //This doesn't works
   /* queue.push_back(array[i-:`s]);          //This works //   */
endtask

If the range of slicing MAX-MIN is fixed than i can do it but how to do if MAX-MIN is not fixed ?
How to implement above code without using defines because i want a variable size whose value is random (simulation time) but array is expecting compile time constant?

In reply to aditgupta100:

You are trying to push [i-:size] (or specifically [i-:`s]) ints into a queue of int. This might give incompatible assignment type.

Moreover, the slicing operator (+: or -:) expects the right-hand value (the one after ‘:’) to be constant. Since macros are compile time constants (text substitutes), the macro might work. Sitll the incompatible type assignment shall be showcased by simulator.

In reply to sharvil111:

In my usecase even the right hand side needs to be a variable (which is random) so it can’t be macro. So any workaround? what shall i do?

In reply to aditgupta100:
The with clause of the streaming operator can help here.

   typedef int intQ_t[$];
   for(int i=31;i>=size;i-=size ) 
      queue = {queue, intQ_t'({>>{array with [i-:size]}})};


Note that the push_back() method can only push one element on the the queue at a time.

A bit-stream cast could do the assignment in one statement without a for loop

queue = intQ_t'(array);

In reply to dave_59:

In reply to aditgupta100:
The with clause of the streaming operator can help here.

   typedef int intQ_t[$];
for(int i=31;i>=size;i-=size ) 
queue = {queue, intQ_t'({>>{array with [i-:size]}})};

Note that the push_back() method can only push one element on the the queue at a time.
A bit-stream cast could do the assignment in one statement without a for loop

queue = intQ_t'(array);

Hi Dave thanks for replying.
Can you please elaborate a more , i’m not able to understand how this works ?
I want to push slices of array to the queue such that the size of queue is (32/size) ie queue.size() = 4 in my case.

Thanks

In reply to dave_59:

Hi dave i tried your code as it is and it is giving me error :
ncvlog: *E,SOWUNS with expression in streaming concatenation is not supported.

In reply to aditgupta100:

You have to take up unsupported features with your vendor. This works fine in Questa.

It would help if you showed an example with the data you expect array and queue. Your latest description does not match what your original code was trying to do. Each push_back() was trying to push 8 elements onto the queue, and the for-loop iterated 4 times.

In reply to dave_59:

Say i have a 32 bit array ex. :
arr = 0xAFAFAFAF

and i want a queue to be like this if size = 8
queue[0] = AF
queue[1] = AF
queue[2] = AF
queue[3] = AF
Hence queue size is 4.

But if the size =16 queue should be
queue[0] = AFAF
queue[1] = AFAF

In reply to aditgupta100:

You can try this it worked for me . Check Convert task .



class t1;
  //bit [31:0]  array;
  int array;
  int size=8;
  int queue[$];
  
  task convert;
    int tmp;
    int temp_array;
    temp_array = this.array;
    for (int i=1; i*size <= 32; i++) begin
      tmp = temp_array & ((1 << size)-1);
      temp_array = temp_array >> size;
      queue.push_back(tmp);
    end
    
  endtask 
  
  task print_queue();
    foreach(queue[i]) begin
      $display("\n queue[%d]=%0h",i,queue[i]);
    end
  endtask 
  
  task delete_queue();
    queue= {};
  endtask 

endclass

module m1;
  
  t1  t;
  
  initial begin
    t=new();
    t.array= 32'hAFAF_AFAF;
    t.size = 8;
    t.convert();
    t.print_queue();
    t.delete_queue();
    $display("\nChanging size to 16");    
    t.size = 16;
    t.convert();
    t.print_queue();
    t.delete_queue();
    $display("\nChanging array value ");
    t.array=32'h5345_7821;
    t.convert();
    t.print_queue();
    t.delete_queue();
    $display("\nChanging size to 16");    
    t.size = 8;
    t.convert();
    t.print_queue();
    t.delete_queue();
      
  end
    
endmodule