Pass array to a function

I am passing an array to a function. I don’t know the size of the array that a caller will use.

Here is what I am observing:
case 1) when I use like below, I see an error “Illegal ref port connection”

function func1 (ref int a []);

case 2) when I use this below, where I remove the ref, I don’t see an error

function func1 (int a []);

case 3) when I use like below, where I specify the size of the array, I don’t see an error

function func1 (ref int a [5]);

One full example is shown below:

module x;
  function func1 (ref int a [5]);
    $display ("%p", a);
  endfunction
  
  initial begin
    int a [5] = {1,2,3,4,5};
    func1(a);
  end
endmodule


In reply to verif_learner:

There are many more restrictions when using pass by reference direction. The formal and actual argument types must match exactly. A fixed sized array is not the same type as a dynamic array. Another restriction your tool did not catch is you can only use pass by reference with functions/tasks that have an automatic lifetime. See this link.

Also, you are declaring your function without an explicit return type. The Verilog implicit default is 1-bit return value. Use ‘function void’

In reply to dave_59:

In reply to verif_learner:
There are many more restrictions when using pass by reference direction. The formal and actual argument types must match exactly. A fixed sized array is not the same type as a dynamic array. Another restriction your tool did not catch is you can only use pass by reference with functions/tasks that have an automatic lifetime. See this link.
Also, you are declaring your function without an explicit return type. The Verilog implicit default is 1-bit return value. Use ‘function void’

ok. So, what is the option available if I want to pass an array as an argument to a function if I do not know the size of the array. I assume this is a very common issue in verification.
For example, if I am passing a array that contains packet data to the function, most likely I will not know the size of the packet at all.

In reply to verif_learner:

Usually, the packet is a class object with an arrays as a member. You just pass the object’s handle as an input to the function.

If you make sure you always use a dynamic array, you can pass an array by reference.

module x;
  function func1 (ref int a []);
    $display ("%p", a);
  endfunction
 
  initial begin
    int a [];
    a = {1,2,3,4,5};
    func1(a);
  end
endmodule

In reply to dave_59:

In reply to verif_learner:
Usually, the packet is a class object with an arrays as a member. You just pass the object’s handle as an input to the function.
If you make sure you always use a dynamic array, you can pass an array by reference.

module x;
function func1 (ref int a [5]);
$display ("%p", a);
endfunction
initial begin
int a [];
a = {1,2,3,4,5};
func1(a);
end
endmodule

Dave,

I am going through LRM section 7.7.
This is what it says,

A subroutine that accepts a dynamic array or queue can be passed a dynamic array, queue, or fixed-size array of a compatible type.
For example, the declaration
task t ( string arr );
declares a task that accepts one argument, a dynamic array of strings. This task can accept any onedimensional unpacked array of strings or any one-dimensional dynamic array or queue of strings.

I am interpreting this as if the formal argument to the function is dynamic array then one can call this function with another dynamic array.
Am I interpreting something incorrectly?

In reply to verif_learner:

Yes, I made a mistake in my example. Now they are both dynamic arrays. BTW, section 7.7 discusses the rules for passing arrays by value. Passing by references has more strict rules.