In SystemVerilog, copying objects is a common requirement when working with classes and dynamic data structures. However, the distinction between shallow copy and deep copy is critical for correctly handling memory and avoiding unexpected behavior. This article explains the concepts of shallow and deep copies in SystemVerilog, supported by examples for clarity.
In SystemVerilog:
- Shallow Copy creates a new object in memory but only copies references for dynamically allocated members or nested objects. It doesn’t recursively duplicate their content. In shallow copy only the handles will be copied
- Deep Copy explicitly duplicates the entire object, including nested objects and dynamic members, ensuring complete independence. Here new object is created and all the class properties including nested class members will be copied to new handle.
Let’s use a class with a nested object to demonstrate shallow and deep copying effectively.
Defining Classes with Nested Objects
Here, we define a Transaction class that contains a nested object Metadata.
class Metadata;
int checksum;
function new(int checksum);
this.checksum = checksum;
endfunction
endclass
class Transaction;
int id;
Metadata meta; // Nested object
// Constructor
function new(int id, int checksum);
this.id = id;
this.meta = new(checksum);
endfunction
// Display method
function void display();
$display("Transaction ID: %0d, Metadata Checksum: %0d", id, meta.checksum);
endfunction
endclass
Shallow Copy Example
In a shallow copy, a new object is created, but the nested object (Metadata) is shared between the original and the copied object. Modifying the nested object through the copied instance also affects the original.
Shallow Copy Implementation
module shallow_copy_example;
initial begin
// Create original object
Transaction t1 = new(1, 123);
// Perform shallow copy
Transaction t2 = new(t1.id, t1.meta.checksum);
t2.meta = t1.meta; // Share reference of the nested object
// Modify the copied object
t2.id = 2;
t2.meta.checksum = 456; // Modify shared nested object
// Display results
$display("Shallow Copy Results:");
t1.display(); // Nested object is modified
t2.display();
end
endmodule
Output:
Shallow Copy Results:
Transaction ID: 1, Metadata Checksum: 456
Transaction ID: 2, Metadata Checksum: 456
Explanation:
- A new
Transactionobject (t2) is created. - The
Metadataobject is shared betweent1andt2(same memory). - Modifying
meta.checksumint2affectst1.
Deep Copy Example
In a deep copy, the Metadata object is duplicated, ensuring complete independence between the original and the copied Transaction.
Deep Copy Implementation
Add a copy method to the Transaction class to create a deep copy:
class Transaction;
int id;
Metadata meta;
function new(int id, int checksum);
this.id = id;
this.meta = new(checksum);
endfunction
// Deep copy method
function Transaction copy();
Transaction new_transaction = new(this.id, this.meta.checksum);
new_transaction.meta = new(this.meta.checksum); // Create a new Metadata object
return new_transaction;
endfunction
function void display();
$display("Transaction ID: %0d, Metadata Checksum: %0d", id, meta.checksum);
endfunction
endclass
Using Deep Copy
module deep_copy_example;
initial begin
// Create original object
Transaction t1 = new(1, 123);
// Perform deep copy
Transaction t2 = t1.copy();
// Modify the copied object
t2.id = 2;
t2.meta.checksum = 456; // Modify deep-copied nested object
// Display results
$display("Deep Copy Results:");
t1.display(); // Original remains unchanged
t2.display();
end
endmodule
Output:
Deep Copy Results:
Transaction ID: 1, Metadata Checksum: 123
Transaction ID: 2, Metadata Checksum: 456
Explanation:
- The
Transactionobject (t2) is a completely new object. - The
Metadataobject is also a new instance, independent of the original (t1.meta). - Modifications to
t2do not affectt1.
Summary of the Examples
| Aspect | Shallow Copy | Deep Copy |
|---|---|---|
| Object Creation | New object is created. | New object is created. |
| Nested Objects | Shared references to nested objects. | New instances of nested objects are created. |
| Modification Effect | Changes to nested objects affect both instances. | Changes to one instance do not affect the other. |