Tutorials

Learn More

As we discussed earlier in the section class assignment in sv, multiple handles refer to the same object. It means the same memory location will be allocated and which can be accessed by two different handles. If any handle would like to change class properties, it will reflect the same changes when it is accessed by another handle.

Based on the requirement if the user needs a separate copy of an object, copying techniques are used.

Based on copying behavior, two techniques were introduced by SystemVerilog.

  1. Shallow copy
  2. Deep copy

Shallow copy in SystemVerilog

The shallow copy is used to copy

  1. Class properties like integers, strings, instance handle, etc
  2. Nested objects are not copied, only instance handles are copied which means any changes are done in ‘nested copied object’ will also reflect in the ‘nested original object’ or vice-versa.

The new() method is used for copying.

shallow copy in sv
transaction tr1, tr2;
tr1 = new();
tr2 = new tr1;

tr2 = new tr1 will create a new object tr2 which is a copy of the tr1 object.

Example for shallow copy

class error_trans;
  bit [31:0] err_data;
  bit error;
  
  function new(bit [31:0] err_data, bit error);
    this.err_data = err_data;
    this.error = error;
  endfunction
endclass

class transaction;
  bit [31:0] data;
  int id;
  error_trans err_tr;
  
  function new();
    data = 100;
    id = 1;
    err_tr = new(32'hFFFF_FFFF, 1);
  endfunction
  
  function void display();
    $display("transaction: data = %0d, id = %0d", data, id);
    $display("error_trans: err_data = %0h, error = %0d\n", err_tr.err_data, err_tr.error);
  endfunction
endclass

module shallow_copy_example;
  transaction tr1, tr2;
  
  initial begin
    tr1 = new();
    $display("Calling display method using tr1");
    tr1.display();
    
    tr2 = new tr1;
    $display("After shallow copy tr1 --> tr2");
    $display("Calling display method using tr2");
    tr2.display();
    $display("--------------------------------");
    
    tr1.data = 200;
    tr1.id = 2;
    tr1.err_tr.err_data = 32'h1234;
    tr1.err_tr.error = 0;
    
    $display("Calling display method using tr1");
    tr1.display();
    $display("Calling display method using tr2");
    tr2.display();
    
  end
endmodule

Output:

Calling display method using tr1
transaction: data = 100, id = 1
error_trans: err_data = ffffffff, error = 1

After shallow copy tr1 --> tr2
Calling display method using tr2
transaction: data = 100, id = 1
error_trans: err_data = ffffffff, error = 1

--------------------------------
Calling display method using tr1
transaction: data = 200, id = 2
error_trans: err_data = 1234, error = 0

Calling display method using tr2
transaction: data = 100, id = 1
error_trans: err_data = 1234, error = 0

Here, error data is defined as ‘hFFFF_FFFF, and the error bit is also set to 1. For any other value of err_data, the error bit is set to 0.

Notice that

  1. The data and id class properties are copied. The tr1 and tr2 class handles refer to separate memory locations. Thus, changing values using the tr1 class handle does not affect accessing class properties with the tr2 handle.
  2. The err_tr object handle is copied alone. On changing err_data = 32’h1234 and error = 0 using tr1 class handle, the same is accessible using tr2 class handle.

To have separate memory for nested objects, deep copy provides a solution.

System Verilog Tutorials