There are two methods we use to copy data of one uvm_object (transaction or sequence item) to another.
Copy and
Clone.
Here I will explain you difference between copy and clone.
See below code.
========================================================================
Copy and
Clone.
Here I will explain you difference between copy and clone.
See below code.
========================================================================
// do_copy method: function void do_copy(uvm_object rhs); bus_item rhs_; if(!$cast(rhs_, rhs)) begin uvm_report_error("do_copy:", "Cast failed"); return; end super.do_copy(rhs); // Chain the copy with parent classes delay = rhs_.delay; addr = rhs_.addr; op_code = rhs_.op_code; slave_name = rhs_.slave_name; data = rhs_.data; response = rhs_.response; endfunction: do_copy // Example of how do_copy would be used: // Directly: bus_item A, B; A.copy(B); // A becomes a deep copy of B // Indirectly: $cast(A, B.clone()); // Clone returns an uvm_object which needs // to be cast to the actual type
========================================================================
A.copy(B); is deep copy of B.While B.clone() returns a new object of type uvm_object which we cast to type "bus_items". So in a way A becomes deep copy of B.
Below here I am mimicking behavior of copy and clone method of UVM
typedef base_class; typedef derived_class; function base_class create(); derived_class tmp; tmp = new(); return tmp; endfunction class base_class; int A = 7; virtual function do_copy(base_class rhs); endfunction virtual function copy(base_class rhs); do_copy(rhs); endfunction virtual function base_class clone(); base_class base; base = create(); base.copy(this); return (base); endfunction endclass class derived_class extends base_class; int A = 5; function do_copy(base_class rhs); derived_class derived; $cast(derived,rhs); super.do_copy(rhs); A = derived.A; endfunction endclass module test(); derived_class d1,d2,d3; initial begin d1 = new(); d1.A = 10; d3 = new(); d3.copy(d1); $cast(d2,d1.clone()); $display("A in d1 is %0d",d1.A); $display("A in d2 is %0d",d2.A); $display("A in d3 is %0d",d3.A); d1.A = 20; $display("A in d1 is %0d",d1.A); $display("A in d2 is %0d",d2.A); $display("A in d3 is %0d",d3.A); endendmodule
Output :
A in d1 is 10 A in d2 is 10 A in d3 is 10 A in d1 is 20 A in d2 is 10 A in d3 is 10
There are two function used here copy and clone.
copy : d3.copy(d1); which is simply deep copy of d1 to d3. It works as below.1. d3 calls copy function which is defined in base_class.
2. copy function calls do_copy, as do_copy is virtual method, always latest definition of function will be executed. There is only one implementation of a virtual method per class hierarchy, and it is always the one in the latest derived class. So do_copy from "derived class" will be called.
clone : $cast(d2,d1.clone()); This method works as below.1. d1.clone() calls definition of clone from base class.
2. clone calls create method which, returns handle of type derived_class.
3. A child class handle can be directly assign to base class.
4. base.copy(this); This is basically deep copy of this(here d1) to base.5. So clone method return class variable of type "base_class" which we need to cast in derived_class, then only we can access member of class.
If you have noticed, here there is one dilemma.
base.copy(this); calls copy function from base class , which call do_copy of derived class. So in turn do_copy is called from handle of object of type base_class. So how in do_copy it can access variable A, since it is not defined in base_class.Reason is that "A" is being used by do_copy function which is in derived class. So context of A will be derived_class.
If I have written base.A then it would not work