2
\$\begingroup\$

I am finding it hard to understand how handle passing in function arguments works. I have written 3 codes. The last one is giving a bad handle error.

First I would like to know if I am right in thinking the function call s1.copy(s2); passes the handle s2 to s in the copy method (it is pass by reference)?

For code 1, I think the handle s2 is passed to s and hence s refers to the same object and the code works fine.

I am skeptical about code 2 working. s2 has null handle so how s1.copy(s2); works? Is it like s2 is output argument so on calling copy method the statement s=new(); will provide handle to s and same handle is passed to s2. So s and s2 refer same object and after function call s is destroyed but s2 is still there pointing to the same object?

The code 3 gives error stating "bad handle". In the module I have done s2=new(); so won't the s2 handle be passed to s on the function call s1.copy(s2);? Is it something related to the argument being declared as output?

code1

class sample;
 rand bit[3:0] a;
 rand bit b;
 function void copy(sample s); 
 s.a=this.a;
 s.b=this.b;
 endfunction 
endclass
module tb;
 sample s1,s2;
 initial begin
 s1=new();
 s2=new();
 s1.randomize();
 $display("s1_a=%0d,s1_b=%b",s1.a,s1.b);
 s1.copy(s2);// copying s1 fields to s2
 $display("s2_a=%0d,s2_b=%b",s2.a,s2.b);
 end
endmodule

code 2

class sample;
 rand bit[3:0] a;
 rand bit b;
 function void copy(output sample s);
 s=new();
 s.a=this.a;
 s.b=this.b;
 endfunction
endclass
module tb;
 sample s1,s2;
 initial begin
 s1=new();
 s1.randomize();
 $display("s1_a=%0d,s1_b=%b",s1.a,s1.b);
 s1.copy(s2);// copying s1 fields to s2
 $display("s2_a=%0d,s2_b=%b",s2.a,s2.b);
 end
endmodule

code 3

class sample;
 rand bit[3:0] a;
 rand bit b;
 function void copy(output sample s);
 s.a=this.a;
 s.b=this.b;
 endfunction
endclass
module tb;
 sample s1,s2;
 initial begin
 s1=new();
 s2=new();
 s1.randomize();
 $display("s1_a=%0d,s1_b=%b",s1.a,s1.b);
 s1.copy(s2);// copying s1 fields to s2
 $display("s2_a=%0d,s2_b=%b",s2.a,s2.b);
 end
endmodule
toolic
10.8k11 gold badges31 silver badges35 bronze badges
asked Nov 21, 2024 at 10:41
\$\endgroup\$
1
  • \$\begingroup\$ code 2 is really clone, not copy. \$\endgroup\$ Commented Nov 21, 2024 at 20:43

2 Answers 2

3
\$\begingroup\$

First I would like to know if I am right in thinking the function call s1.copy(s2); passes the handle s2 to s in the copy method (it is pass by reference)?

It depends on how you declared the copy function. Refer to IEEE Std 1800-2023 section 13.4 Functions:

Functions can have the same formal arguments as tasks. 
Function argument directions are as follows:
 input // copy value in at beginning
 output // copy value out at end
 inout // copy in at beginning and out at end
 ref // pass reference (see 13.5.2)
Function declarations default to the formal direction input if no
direction has been specified.

You do not pass the argument as a reference in any of your code examples; that requires the ref keyword.

In the first code example, you pass the argument as an input since you did not explicitly use a direction. This works as you expected it to. The handle was copied into the function, and the object was already constructed before calling the function.

In the 2nd code example, s is null, but the first thing you do inside the function is to construct the object with new. This is why you do not get an error.

In the 3rd code example, s2 is constructed before the function call, but the s object inside the function is null because it is declared as an output. The s2 object was not copied at the start of the function. You did not construct s inside the function, but you tried to access its contents with this line:

s.a=this.a;

That is why you got an error.

answered Nov 21, 2024 at 11:37
\$\endgroup\$
2
  • \$\begingroup\$ So can this be concluded this? In code 1 the function argument is input so handle s2 is passed to s in copy method. But in case of codes 2 and 3 the function argument is output so vice-versa(handle s passed to s2) will happen? That is why in code 3 despite of s2 pointing to an object before function call, s is null as s2 won't be passed to s. If s = new(); is done s is no more a null handle and at the end of the function handle s is passed to s2. So now s2 refers to some other object which was referred by s. \$\endgroup\$ Commented Nov 21, 2024 at 14:17
  • \$\begingroup\$ @Kartikey: yes, I think your understanding is correct. \$\endgroup\$ Commented Nov 21, 2024 at 14:24
2
\$\begingroup\$

It would help to first understand that class variables hold references (handles) to class objects. When making an assignment from one class variable to another class variable, you are copying the reference to the object, not the the object itself. input arguments to functions/tasks are assignments upon entry, and output arguments are assignments upon exit from the function/task.

The copy() method of a class is designed to copy all the properties of a class from one object to another object. Both source and destination objects must be constructed before calling the copy method. That is what your code 1 does. It copies the class handle stored in s1 to the s argument of the copy method, then proceeds to copy the individual class properties.

The copy() method in code 2 is more like what is referred to as a clone method. That is class construction followed by copy. It's usually written as a separate clone() method that calls copy(), and returns a handle to the new object instead of passing the handle out as an output argument.

class sample;
 rand bit[3:0] a;
 rand bit b;
function void copy(sample rhs); // rhs is right-hand-side of the assignment 
 this.a=rhs.a;
 this.b=rhs.b;
endfunction
function sample clone();
 sample lhs = new();
 lhs.copy(this);
 return lhs;
endfunction
endclass
module tb;
 sample s1,s2;
 initial begin
 s1=new();
 assert(s1.randomize());
 $display("s1_a=%0d,s1_b=%b",s1.a,s1.b);
 s2 = s1.clone();// copying s1 fields to s2
 $display("s2_a=%0d,s2_b=%b",s2.a,s2.b);
 end
endmodule

Your code 3 is almost the same as code 1, except you reversed the implicit input direction to an output, so the the s argument never gets the handle that was stored in s2, so s remains null inside the function. If it weren't for the fatal error, the null value of s would have been copied as an output to s2, making it null.

answered Nov 21, 2024 at 18:06
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.