Class handles passed as output and reference parameters to a fucntion

Hi,
I have a question about the class handles passed as output parameters to a function. In the code below, cell2 object has been created in the program and it is passed as a parameter to copy function. (this parameter is of the type output). This code gives a runtime fatal error. In second case, if I comment out the new statement (to = new (7, 8);) in the copy function, however, code runs correctly. If I change the ‘to’ output parameter of copy function to ref instead of output, the code works in both the cases. (whether the to = new (7, 8) statement is commented out or not.)
Can someone help me to understand this behaviour.
-sunil

 virtual class base_tr;
  static int count;
  int id;
  
  function new ();
    id = count++;
  endfunction
  
  //pure virtual function bit compare (input base_tr to);
  //pure virtual function base_tr copy (input base_tr to = null);
  //pure virtual function void display (input string prefix = "");   
endclass : base_tr
    
class uni_cell extends base_tr;
  rand int x1;
  rand bit [31:0] x2;
  extern virtual function void copy (output uni_cell to);
    function new (int x1, int x2);
    this.x1 = x1;
    this.x2 = x2;
  endfunction
endclass : uni_cell
    
function void uni_cell :: copy (output uni_cell to);
  //to = new (7, 8);
  to.x1 = this.x1;
  to.x2 = this.x2;
endfunction : copy
    
program automatic test;
  uni_cell cell1;
  uni_cell cell2;
  uni_cell cell3;
initial begin
  //uni_cell cell1;
  cell1 = new (3, 4);
  cell2 = new (1, 2);
  cell3 = new (0, 0);
  cell3 = new (1, 4);
  
  cell1.copy (cell2);
  $write ("cell2.x1 = %d, cell2.x2 = %d\n", cell2.x1, cell2.x2);
  
end
  
endprogram : test 

In reply to puranik.sunil@tcs.com:

Here, you want to copy the cell1 object into cell2 object and you have passed the cell2 object in an argument of copy function. So, here the cell2 is an input to that function. Hence, if you will take it as input or ref instead of output than it will work.

In addition, in your code there is no any nested class in uni_cell class. So, shallow copy will also work here.

Even, you can write a copy method without passing the destination object in a function argument. It makes the code more readable and clears your intension. Please find the snippet below.

function uni_cell uni_cell :: copy ();
  copy = new (7, 8);
  copy.x1 = this.x1;
  copy.x2 = this.x2;
endfunction : copy

  //Inside program block
  cell2 = cell1.copy();

In reply to bdreku:

Thanks for the response. I have already tried passing the parameter as input and that works. I was interested in checking the functionality of output and reference class handle parameters passed to a function. so I was experimenting with this code. For example, I had tried the code below and it works since the when a class parameter is passed, it is the handle that is passed and so we are able to change the object pointed to by handle. My question here is different : If I use the ‘to’ parameter as an output for the copy function and even after initializing the cell2 object in program and passing same cell2 object as output parameter to the function, why should there be a fatal runtime error?

 virtual class base_tr;
  static int count;
  int id;
 
  function new ();
    id = count++;
  endfunction
 
  //pure virtual function bit compare (input base_tr to);
  //pure virtual function base_tr copy (input base_tr to = null);
  //pure virtual function void display (input string prefix = "");   
endclass : base_tr
 
class uni_cell extends base_tr;
  rand int x1;
  rand bit [31:0] x2;
  extern virtual function void copy (input uni_cell to);
  function new (int x1, int x2);
    this.x1 = x1;
    this.x2 = x2;
  endfunction
endclass : uni_cell
 
function void uni_cell :: copy (input uni_cell to);
  //to = new (7, 8);
  to.x1 = this.x1;
  to.x2 = this.x2;
endfunction : copy
 
program automatic test;
  uni_cell cell1;
  uni_cell cell2;
  uni_cell cell3;
initial begin
  //uni_cell cell1;
  cell1 = new (3, 4);
  cell2 = new (1, 2);
  cell3 = new (0, 0);
  cell3 = new (1, 4);
 
  cell1.copy (cell2);
  $write ("cell2.x1 = %d, cell2.x2 = %d\n", cell2.x1, cell2.x2);
 
end
 
endprogram : test 

In reply to puranik.sunil@tcs.com:

Hi,
I understand your problem that why using output is giving you error. can you just tell whether the above code (that is using argument as input) is working fine with or without commenting to = new (7, 8);.

In reply to Mukul Goyal:

Hi,
It seems your problem is related to using functions correctly. If we go by basic definition then:
Functions will only return a single value and cannot use either output or inout statements. I hope it will clear your doubt.

Thanks,
Mukul

The problem is that you are assuming that mode “output” does a “copy in” of the value you provide. It does not; it only “copies out” the value. So inside the function the formal has the default value of the type (i.e. null for a class type) and, even worse, if the function itself didn’t fail, it would assign null to the cell2 on the return. Here is a simple example to make this clear:


module top;
   class C;
      int x;
      function void f (output C a);
         if (a == null)  
            $display("arg is null");
      endfunction
   endclass

   C c1 = new;
   C c2 = new;
   initial begin
      c1.x = 1;
      c1.f(c2); 
      if (c2 == null)  
         $display("c2 is null");
   end
endmodule

If you need to use the value coming into the function, the formal must be of mode input, inout, or ref.

In reply to Mukul Goyal:

Functions will only return a single value and cannot use either output or inout statements.

That is not correct. Although there are situations that have that requirement, this is not one of them.

But in any case, “input” is the correct mode here because you only need the value of the object handle inside the function to be able to write to the class object. Writing to a member of a class object does not mean the handle argument has to be declared as an output. You access class objects by an indirect reference to a handle. You only need an output if you need to change the handle value.

In reply to dave_59:

Thanks dave for making things clear.But I still don’t understand why the below example do not give error when output is used.

function void uni_cell :: copy (output uni_cell to);
//to = new (7, 8);
to.x1 = this.x1;
to.x2 = this.x2;
endfunction : copy

Can you please tell source of error here.

In reply to Mukul Goyal:

I get an error. to.x1 will produce an error if ‘to’ is null.