Importance of the clone( ) method

Hi ALL,

Can anybody tell me the exact application of the clone methos?
What is the significance of the clone method?

Regards,
Ankit.

The clone method is used to provide a deep (nested) copy of an object.

clone first allocates new memory for the object, then copies over each field to the new object. If a field is an object handle, then instead of copying the handle (which would do a “shallow” copy) you would call fieldname.clone() to recursively allocate memory for that field (a “deep” copy).

-Kurt

clone() returns a handle of newly created object which is copy of original object.

If you want to use copy(), New objected has to be created explicitly.

Look at page number 267, 284 of AVM cook book.

Hi Ankit,

you can simply remember as clone = create and (+) copy
That is, it first creates a new object and then copies all the data to the newly created object.

Regards,
Moneesh

Another key difference is that **clone()**is virtual;**copy()**is non-virtual. And clone() is a method of the original object; copy() is a method of the target object.
That means clone() creates a copy an object of the same class type as the original. With copy(), the original object could be a subclass of the target object’s type with additional class properties that will not get copied.

Dave

In reply to dave_59:

Hi Dave,

With copy(), the original object could be a subclass of the target object's type with additional class properties that will not get copied.

I haven’t understood why “additional class properties will not get copied” for copy() as the subclass (child) is inherited from a base class (parent), which means it has all the properties and methods of the parent. Could you explain what you meant by additional class properties not getting copied.

Thanks,
Madhu

In reply to mseyunni:

class base;
int p1;
  function void copy(base orig);
    this.p1 = orig.p1;
  endfunction
endclass
class ex_base;
  int p2;
  function void copy(base orig);
    super.copy(b);
    this.p2 = orig.p2;
  endfunction
endclass

base b1,b2;
ex_base eb1, eb2;
initial begin
   eb1 = new; eb2 = new();
   eb2.p2 = 5;
   b1 = eb1; b2 = eb2;
   b1.copy(b2); // p2 is not copied
   eb1.copy(eb2); // p2 is copied
end

Since copy() is not virtual, calling b1.copy() calls base::copy(), and the additional property p2 is not copied even though it exists in object referenced by b1.

In reply to dave_59:

p2 will copy if we write b1.copy(eb2)?

I do not understand the claims about copy() here. I agree with the example code, but in UVM the non-virtual copy() method calls the virtual do_copy() method. So the do_copy of the derived class gets called, and hence its members do get copied?

For example:


class base extends uvm_object;
    `uvm_object_utils(base)

    int f1=0;

    function void do_copy(uvm_object rhs);
        base rhs_;
        $display("do_copy of base");
        super.do_copy(rhs);
        $cast(rhs_,rhs);
        f1=rhs_.f1;
    endfunction
endclass

class ex extends base;
    `uvm_object_utils(ex)

    int f2=0;

    function void do_copy(uvm_object rhs);
        ex rhs_;
        $display("do_copy of ex");
        super.do_copy(rhs);
        $cast(rhs_,rhs);
        f2=rhs_.f2;
    endfunction
endclass

module automatic Top();

function void doit();
    base B1,B2;
    ex E1,E2;

    E1=new;
    E1.f1=123;
    E1.f2=456;
    B1=E1;
    E2=new;
    B2=E2;
    B2.copy(B1);
    $display("E2.f1=%0d",E2.f1);
    $display("E2.f2=%0d",E2.f2);

endfunction

calls the copy() on base class handles and still succesfully copies the correct derived class members:

# do_copy of ex
# do_copy of base
# E2.f1=123
# E2.f2=456

edit: I see this was actually an OVM topic, maybe this changed in UVM?

In reply to dave_59:
Hi Dave,
I can understand which you gave the example of copy but i need the example for clone() also.You said copy() is virtual in that thing i just confused what is virtual will you please clear my doudt i am new learner of SV.
thanks in advance.

In reply to NiLu:

The OVM and UVM mechanisms are the same. The OVM added the virtual do_copy() methods as a hook to the non-virtual copy() methods. This might be to get their field automation macros to work.

In reply to swethasundararaj:

class base;
int p1;
  function void copy(base orig);
    this.p1 = orig.p1;
  endfunction
  virtual function base clone(base orig);
    base h;
    h  = new;
    h.copy(orig);
    return h;
  endfunction
endclass
class ex_base;
  int p2;
  function void copy(base orig);
    super.copy(b);
    this.p2 = orig.p2;
  endfunction
   virtual function base clone(base orig);
    ex_base h, h_orig
    h  = new;
    $cast(h_orig, orig)
    h.copy(h_orig);
    return h;
  endfunction
endclass
 
base b1,b2;
ex_base eb1, eb2;
initial begin
   eb1 = new; eb2 = new();
   eb2.p2 = 5;
   b1 = eb1; b2 = eb2;
   b1.copy(b2); // p2 is not copied
   eb1.copy(eb2); // p2 is copied
end

In reply to NiLu:

I do not understand the claims about copy() here. I agree with the example code, but in UVM the non-virtual copy() method calls the virtual do_copy() method. So the do_copy of the derived class gets called, and hence its members do get copied?
For example:


function void doit();
base B1,B2;
ex E1,E2;
E1=new;
E1.f1=123;
E1.f2=456;
B1=E1;
E2=new;
B2=E2;
B2.copy(B1);
$display("E2.f1=%0d",E2.f1);
$display("E2.f2=%0d",E2.f2);
endfunction

There is quite a bit of confusion in this thread on copy vs clone.

The problem with the quoted example is that the child class type must be known at compile time. Doing “E2=new; B2=E2;” means that B2 is pointing to type ex, so ex::do_copy() will get run as intended.

But what if we don’t know the child class type? After all, that is the whole point. We have only a handle to an object whose specific subclass is not known at compile time. The copy() method does not work in this case. Here’s a few examples:


///// option 1: no good because you must know type of rhs  
//    E2=new;                                                    
//    B2=E2;                                         
///// option 2: no good because B2 remains of type base
//    B2=new;
//    B2.copy(B1);
///// option 3: works
    void'($cast(B2, B1.clone()));
///// end options                                    
    $display("B2 type is %s", B2.get_type_name());

In reply to dave_59:

In reply to NiLu:
The OVM and UVM mechanisms are the same. The OVM added the virtual do_copy() methods as a hook to the non-virtual copy() methods. This might be to get their field automation macros to work.
In reply to swethasundararaj:

class base;
int p1;
function void copy(base orig);
this.p1 = orig.p1;
endfunction
virtual function base clone(base orig);
base h;
h  = new;
h.copy(orig);
return h;
endfunction
endclass
**class ex_base;
int p2;
function void copy(base orig);
super.copy(b);
this.p2 = orig.p2;
endfunction
virtual function base clone(base orig);
ex_base h, h_orig
h  = new;
$cast(h_orig, orig)
h.copy(h_orig);
return h;
endfunction
endclass**
base b1,b2;
ex_base eb1, eb2;
initial begin
eb1 = new; eb2 = new();
eb2.p2 = 5;
b1 = eb1; b2 = eb2;
b1.copy(b2); // p2 is not copied
eb1.copy(eb2); // p2 is copied
end

Hi dave,
I am trying to copy an extended class object, randomized multiple times having single handle.
It is to be copied to the same type of class object based on certain conditions, thus using cloning method.

I am trying to implement it like this:

class mcs_data_packet extends mcs_inst_packet;

  rand logic w1r0;

  int mcs_core=0; 
  int count =0;   

  function new ();
  endfunction:new
  
  function void copy(mcs_data_packet ext);
    super.copy(ext);
    this.w1r0 = ext.w1r0; 
  endfunction
  
  virtual function mcs_data_packet clone(mcs_data_packet ext);
    mcs_data_packet h;
    h=new();
    h.copy(ext);
    return h;
  endfunction

But getting error as below:
virtual function mcs_data_packet clone(mcs_data_packet ext);
|
ncvlog: *E,CVMNMM (mcs_data_packet.svh,23|59): Virtual method ‘mcs_data_packet::clone’ formal argument name does not match base class ‘mcs_inst_packet’.
virtual function mcs_data_packet clone(mcs_data_packet ext);
|
ncvlog: *E,CVMTMM (mcs_data_packet.svh,23|59): Virtual method ‘mcs_data_packet::clone’ formal argument type does not match base class ‘mcs_inst_packet’.
Total errors/warnings found outside modules and primitives:
errors: 2, warnings: 0

But modifying the code:

class mcs_data_packet extends mcs_inst_packet;

  rand logic w1r0;

  int mcs_core=0; 
  int count =0;   

  function new ();
  endfunction:new
  
  function void copy(mcs_data_packet ext);
    super.copy(ext);
    this.w1r0 = ext.w1r0;
  endfunction
  
  virtual function mcs_inst_packet clone(mcs_inst_packet ext);
    mcs_data_packet h,h_orig;
    h=new();
    $cast(h_orig,ext);
    h.copy(h_orig);
    return h;
  endfunction

Getting error as while cloning I am passing the extended class type to clone function while it is expecting base class type.

mcs_data_rec[0]=mcs_data.clone(mcs_data);
|
ncvlog: *E,TYCMPAT (tb.sv,1131|30): assignment operator type check failed (expecting datatype compatible with ‘class $unit::mcs_data_packet’ but found ‘class $unit::mcs_inst_packet’ instead).

Can you please explain how to clone an extended class.

In reply to ankitjain:

Both copy() and clone() are already defined as part of the uvm_object class, and you don’t want to override them.

Instead, you want to implement do_copy() instead. The clone() and copy() functions will utilize your do_copy() method.

Refer to the Transaction Methods page for more information.

I am still confused about the virtual/non virtual aspect of copy/clone after reading the thread. Can anyone please correct me if the following conclusion is wrong. do copy and do clone are virtual methods while copy and clone are not. However since there are hooks to do_copy and do_clone in copy and clone method. Hence calling copy and clone on the object will call the function implemented in the extended class object.

In reply to svq:

Unfortunately, the UVM is much more complicated than it needs to be due to its history. It is expecting that everyone is using the macros to register the class with the factory. You are not supposed to override clone() or copy(), so it really doesn’t matter if they are virtual or not in that case.

uvm_object::clone() calls the virtual create() method that get inserted by the `uvm_object_utils macro in each derived class. There is no do_clone() method; the create() method is taking the place of that.

You are correct about do_copy(). After calling create(), uvm_object::clone(), calls uvm_object::copy, which then calls the virtual do_copy().

In reply to dave_59:

Thanks Dave for the explanation. Makes sense now

In reply to dave_59:

Dave , I believe there’s a few typos


class ex_base ;   
  should  be 
class ex_base extends  base ;        // Should  extend  base 
 int p2;
  function void copy(base orig);
    super.copy(orig);                //  Arg.  name  should  be   'orig'
    this.p2 = orig.p2;
  endfunction