Passing arguments by reference

confused in using ref function? what is the benefit of using ref in function arguments? give an example how variable values will effect with & without using ref in function arguments

In a function, the only benefit is performance in passing large data structures like an array instead of using an inout.

In a task that consumes time, a ref can be used instead of an inout to capture value changes that occur while the task is active. Remember that an inout argument is copied into the task when it is called, and copied out when the task returns. Here is an example that I did not try, so excuse the typos.

module top;
logic A,B;
task automatic mytask(inout logic arg1, ref logic arg2);
  #0 $display("%m %t arg1 %b arg2 %b",$time,arg1,arg2);
  // actual arguments have been set to 0
  #5 $display("%m %t arg1 %b arg2 %b",$time,arg1,arg2);
  #0 arg1 = 1; arg2 = 1;
  #5 $display("%m %t arg1 %b arg2 %b",$time,arg1,arg2);
endtask
initial #1 mytask(A,B);
initial begin
       A = 'z; B ='z;
       #2 A = 0; B = 0; // after call 
       // arguments have been set to 1
       #5 $display("%m %t A %b B %b",$time,A ,B);
       #5 $display("%m %t A %b B %b",$time,A ,B);
end
endmodule

See the difference between the inout and pass by ref arguments.

Note that a class variable is a reference to a class handle already, so passing a class variable by reference rarely has any benefit.

In reply to dave_59:

thank you dave_59…

In reply to kulwantsingh:

Hello Dave,

I tried the following below process but still I was getting the same error i.e. “invalid ref argument usage because actual argument is not a variable”

Extern Task Instance:

extern virtual task d_c_p(int j, ref rst, ref clk, ref dbn);

Task Declaration:

task d_c_p(int j, ref rst, ref clk, ref dbn);

Task Usage: Note, this task is called multiple times recursively
logic dbn_l[MAX_LIMIT];

d_c_p(j, r_vif.rst, r_vif.clk, dbn_l[j]);

Am I making any silly mistake ? Kindly provide your comments.

Regards,
Desperado

In reply to desperadorocks:

Thanks Dave…

Got your response in another post.

FI…
https://verificationacademy.com/forums/systemverilog/can-array-element-be-passed-ref-argument-task

Thanks,
Desperado

In reply to desperadorocks:

Works for me in Questa.

module top;
class C; 
   bit a[10];
   extern virtual task p(ref bit c);
endclass : C
   task C::p(ref bit c);
      #10;  
   endtask : p
   C c	=new;
   
   initial begin
      c.p(c.a[1]);
   end
endmodule : top

Can you show me a small, complete, self-contained example?

In reply to dave_59:

Hello Dave,

Please find the example given below.


module top;

class fruit; 
 logic dbn_l[2];

 extern virtual task apple(ref logic fruit_type); 
endclass: fruit 

task fruit::apple(ref logic fruit_type);
 #10 $display("Inside Apple. Value of fruit_type = %0d\n", fruit_type);
endtask: apple


fruit fr = new();


initial begin
 fr.dbn_l[0] = 1; 
 fr.dbn_l[1] = 1; 
 fr.apple(fr.dbn_l[1]);
end 

endmodule: top 


And below is the error message when I ran in Incisive. Its working fine in VCS.


 
 irun: 13.10-e280: (c) Copyright 1995-2014 Cadence Design Systems, Inc.
file: task_ref.sv
 fr.apple(fr.dbn_l[1]);
                 |
ncvlog: *E,BADRFA (task_ref.sv,20|17): invalid ref argument usage because actual argument is not a variable.  [SystemVerilog].
        module worklib.top:sv
                errors: 1, warnings: 0
ncvlog: *F,NOTOPL: no top-level unit found, must have recursive instances.
irun: *E,VLGERR: An error occurred during parsing.  Review the log file for errors with the code *E and fix those identified problems to proceed.  Exiting with code (status 2).


I suppose its a tool issue. Will check with the corresponding CAE team.

Had a doubt on the UVM register and posted the same in the below link and awaiting your valuable comments.

https://verificationacademy.com/forums/uvm/one-physical-register-two-address-mapped-it-how-take-care-inside-uvm-reg-model

Thanks,
Desperado !!