What is meant by reference argument must be automatic?

I am new to system verilog.
In this program i am getting error

“task or function ‘pass_by_ref’ with ref arguments must be automatic”
please help me…

program main();
int a;

initial
begin
#10 a = 10;
#10 a = 20;
#10 a = 30;
#10 $finish;
end

task pass_by_val(int i);
forever
@i $display("pass_by_val: I is %0d",i);
endtask


task pass_by_ref(ref int i);
forever
@i $display("pass_by_ref: I is %0d",i);
endtask

initial
pass_by_val(a);

initial
pass_by_ref(a);

endprogram

In reply to R Divyaa:

When you pass any arguments by reference, the task should be automatic.

task automatic pass_by_ref(ref int i);
.
.
.
endtask

Regards,
D

The LRM says

It shall be illegal to use argument passing by reference for subroutines with a lifetime of static.

The reason for this restriction is that you are allowed to hierarchically reference the arguments of a task/function as static variables from the outside of that task/function, and that would not make any sense if the arguments are references. A reference is only valid during an active call of that task/function.

In reply to dave_59:

Hi Mr.Dave
" It shall be illegal to use argument passing by reference for subroutines with a lifetime of static " ,I have read the
reason for this restriction from your reply.But still i did not get the clear concept which you explained in those two lines.
Please explain with help of small code to understand,it could be a great help to me!

In reply to Ramesh D:

Prior to Verilog-2001, all named blocks like functions and tasks had static lifetimes. A block with a static lifetime means that the variables inside the block, as well as arguments to tasks and functions, are all allocated and initialized at time 0. And there is only one set of variable for all invocations of the block. In contrast, the variables of an automatic block are allocated and initialized upon activation of that block (i.e. when you call a task or function) and there is a new allocation for each activation of the block. This allows you to have re-entrant tasks or recursive functions with each activation having an independent set of arguments and variables.

For backward compatibility with Verilog, SystemVerilog continues to give named blocks a static lifetime by default, but tasks and functions declared as methods inside classes have an automatic lifetime and may not be given a static lifetime.

In the example above, both tasks pass_by_val() and pass_by_ref() have static lifetimes. You could change the second initial block to

initial begin
      pass_by_val.i = 5;
      $display(pass_by_val.i); // will display 5
      fork 
         #11 pass_by_val(a); // a = 10, copied to pass_by_val.i
         #12 $display(pass_by_val.i); // will display "10"
         #30 pass_by_val.i = 2; // will display "pass_by_val: I is 2"
      join
  end

The $display at time 12 shows 10 because that was the value passed to i. The assignment statement at time 30 cause the @i event control to trigger and execut the $display inside pass_by_val().

If you change the third initial block to

initial begin
      pass_by_ref.i = 5;
      $display(pass_by_ref.i);
      pass_by_ref(a);
      ...
       

What variable is i referencing? We haven’t called pass_by_ref yet, so ‘a’ is not referenced by i yet. This is just one of many problems where pass_by_ref.i could reference something that does not exist yet, or something that did exist, but no longer does.