How to deep copy UVM transaction containing queue of objects?

I have a UVM transaction extended from uvm_sequence_item (call it ‘txn’). It contains a queue of object defined as “base_obj obj_queue[$]”. The base_obj is a virtual class with pure virtual do_copy function. Concrete classes extended from base_obj are stored in obj_queue. When I implement ‘do_copy’ function in the ‘txn’ transaction, how do I deep copy obj_queue containing different types derived from base_obj?

//
class txn extends uvm_sequence_item

  base_obj obj_queue[$];

  // do_copy implementation  - how do I deep copy 'obj_queue'?

endclass


// abstract 'base_obj' class
virtual class base_obj extends uvm_object;

endclass

// concrete classes derived from base_obj
class obj_a extends base_obj

  //(do_copy implementation)

endclass


class obj_b extends base_obj

  //(do_copy implementation)

endclass

In the do_copy function of txn class, you can simply do:

obj_queue = rhs_.obj_queue;

Make sure in your extended classes that you call super.do_copy().

This would only copy handles of each object in the queue though. I want to clone (deep copy) each object in the queue.

I tried doing following in do_copy() method of “txn” class:

function void txn::do_copy(uvm_object rhs);
   if (!$cast(rhs_, rhs)) `uvm_fatal("rhs_ Cast Failed!")
   
   this.obj_queue.delete();

   foreach(rhs_.obj_queue[i])
   begin
       base_obj obj;
       if (!$cast(obj, rhs_.obj_queue[i].clone())) `uvm_fatal("obj Cast Failed!")

       this.obj_queue.push_back(obj);
   end
endfunction

…but I was getting following error:

base_obj.sv(82): Illegal call to pure virtual method 'do_copy’ in ‘txn’ .

I had ‘do_copy’ defined as a “pure virtual function” in the base_obj.sv because I wanted to enforce each derived object implement this function. Removing “pure virtual function” definition from the base_obj fixed the issue. However, I wonder if there are other ways to clone concrete objects stored in the rhs_.obj_queue and then copy the cloned objects in this.obj_queue without removing “pure virtual function” definition from the base_obj.sv.

It’s easier to implement the do_copy in your base txn class.

Using clone to duplicate the objects will work fine, but remember that the class using the objects in the base_obj queue will need to cast them to the correct type.