In a previous post, we discussed key topics on class handles and objects. Understanding these concepts is essential to grasp how shallow and deep copy operations work in SystemVerilog.

Key Concepts Covered:

  • Class Handles and Objects
  • Shallow Copy
  • Deep Copy

Shallow Copy in SystemVerilog

When copying one object to another, SystemVerilog offers two types of copying mechanisms: shallow copy and deep copy. Let’s first discuss shallow copy, a simpler form of copying.

Shallow Copy Example

In shallow copying, the content of one object is transferred to another. However, the nested objects (i.e., objects inside other objects) are not completely copied. Instead, only their handles are assigned to the new object. This means that both the original and the new object share the same instance of the nested object.

Here’s an example to demonstrate shallow copying in SystemVerilog:

class Header;
    int id;
    
    function new (int id);
        this.id = id;
    endfunction
    
    function showId();
        $display("id=0x%0d", id);
    endfunction
endclass

class Packet;
    int addr;
    int data;
    Header hdr; // Nested class object
    
    function new (int addr, int data, int id);
        hdr = new(id);
        this.addr = addr;
        this.data = data;
    endfunction
    
    function display (string name);
        $display("[%s] addr=0x%0h data=0x%0h id=%0d", name, addr, data, hdr.id);
    endfunction
endclass

module tb;
    Packet p1, p2;
    
    initial begin
        // Create a new packet object called p1
        p1 = new(32'hface_cafe, 32'h1234_5678, 26);
        p1.display("p1");
        
        // Shallow copy p1 into p2
        p2 = new p1;
        p2.display("p2");
        
        // Modify p1's data
        p1.addr = 32'habcd_ef12;
        p1.data = 32'h5a5a_5a5a;
        p1.hdr.id = 17;
        p1.display("p1");
        
        // Print p2 and notice the shared hdr.id
        p2.display("p2");
    end
endmodule

What Happens in Shallow Copy?

In this example:

  • A Packet object p1 is created with specific values.
  • We use shallow copy (p2 = new p1) to create p2 with the same values as p1.
  • After modifying p1, notice that the hdr.id value is not changed in p2 even though p1‘s hdr.id was updated.

Simulation Output:

[p1] addr=0xfacecafe data=0x12345678 id=26
[p2] addr=0xfacecafe data=0x12345678 id=26

[p1] addr=0xabcdef12 data=0x5a5a5a5a id=17
[p2] addr=0xfacecafe data=0x12345678 id=17

As seen in the output, p2 shares the same handle for the nested object hdr as p1. Changing hdr.id in p1 also affects p2.


Deep Copy in SystemVerilog

Unlike shallow copy, deep copy copies everything, including nested objects. A deep copy requires custom code because SystemVerilog doesn’t support deep copying by default.

Deep Copy Example

In a deep copy, all objects, including nested ones, are copied fully, not just their handles. Here’s how to implement a deep copy in SystemVerilog:

class Packet;
    ...
    function copy(Packet p);
        this.addr = p.addr;
        this.data = p.data;
        this.hdr.id = p.hdr.id;  // Full copy of nested object
    endfunction
    ...
endclass

module tb;
    Packet p1, p2;
    
    initial begin
        p1 = new(32'hface_cafe, 32'h1234_5678, 32'h1a);
        p1.display("p1");
        
        p2 = new(1, 2, 3);
        p2.copy(p1);
        p2.display("p2");
        
        // Modify p1's data
        p1.addr = 32'habcd_ef12;
        p1.data = 32'h5a5a_5a5a;
        p1.hdr.id = 32'h11;
        p1.display("p1");
        
        // Now print p2 and notice the change in p2's hdr.id
        p2.display("p2");
    end
endmodule

What Happens in Deep Copy?

In the above example, we defined a custom copy() function that performs a full copy of p1 into p2. This ensures that the nested object hdr inside Packet is also copied completely, not just the handle.

Simulation Output:

[p1] addr=0xfacecafe data=0x12345678 id=26
[p2] addr=0xfacecafe data=0x12345678 id=26

[p1] addr=0xabcdef12 data=0x5a5a5a5a id=17
[p2] addr=0xfacecafe data=0x12345678 id=26

In this case, even though p1‘s hdr.id changes, p2 retains its original id since the copy function created a deep copy of all its data, including the nested Header object.


Key Differences Between Shallow and Deep Copy

Here’s a quick comparison of shallow copy and deep copy:

FeatureShallow CopyDeep Copy
Handles copied?Yes, only handles of nested objects.Yes, actual objects are fully copied.
Nested objects copied?No, only handles to nested objects.Yes, nested objects are fully copied.
PerformanceFaster due to fewer data copied.Slower due to full object copying.
Use caseWhen object independence is not required.When object independence is required.

Conclusion: When to Use Shallow or Deep Copy

  • Use shallow copy when you want faster performance and don’t need full independence between objects.
  • Use deep copy when you require full independence between objects, ensuring that all nested objects are copied fully.
Scroll to Top