지노랩 /JinoLab

[SystemVerilog] 4.15 객체 복사(Copying Objects) 본문

SystemVerilog검증/4. 객체지향 OOP 기초

[SystemVerilog] 4.15 객체 복사(Copying Objects)

지노랩/JinoLab 2025. 3. 1. 09:25

 

SystemVerilog에서 객체를 복사해야 하는 경우가 있다. 예를 들어, 원본 데이터를 변경하지 않고 루틴에서 사용하거나, 생성기(generator)에서 객체의 제약을 유지해야 하는 경우다. 객체를 복사하는 방법은 크게 두 가지가 있다.

  1. new 키워드를 사용하여 기본적인 복사를 수행하는 방법
  2. 직접 사용자 정의 복사 메서드를 작성하여 더 정교한 복사를 수행하는 방법

Section 8.3에서는 왜 복사 메서드를 만들어야 하는지에 대한 설명이 포함되어 있다.


4.15.1 new를 사용한 객체 복사(Copying an object with new)

new 키워드를 사용하면 쉽게 객체 복사가 가능하다. 새로운 객체가 생성되며, 기존 객체의 모든 변수가 복사된다.

예제 4-27: 간단한 클래스를 new를 사용하여 복사하기

class BusTran;
  bit [31:0] addr, crc, data[8];
endclass

BusTran src, dst;
initial begin
  src = new();    // 첫 번째 객체 생성
  dst = new src;  // new를 사용하여 복사
end

위 예제에서는 new를 사용하여 src 객체를 복사하여 dst를 만든다. 하지만, 이 방식은 얕은 복사(shallow copy)이며, 객체 내부에 다른 클래스의 핸들을 포함하고 있을 경우 해당 핸들은 복사되지 않는다.

예제 4-28: 복합 클래스 복사하기

class BusTran;
  bit [31:0] addr, crc, data[8];
  static int count = 0;
  int id;
  Statistics stats;

  function new;
    stats = new;
    id = count++;
  endfunction
endclass

BusTran src, dst;
initial begin
  src = new();
  src.stats.startT = 42;
  dst = new src;  // 객체 복사
  dst.stats.startT = 84;  // dst.stats를 변경하면 src.stats도 변경됨
end

위 코드에서 dst는 src를 복사하지만, 내부적으로 포함된 Statistics 객체는 별도로 복사되지 않는다. 따라서 dst.stats.startT = 84;를 실행하면 src.stats.startT도 영향을 받는다.

얕은 복사(shallow copy) 문제

아래 그림을 보면 new를 사용한 복사에서 객체의 상위 계층만 복사되고, 내부 핸들은 동일한 객체를 가리키는 문제가 있다.

  • 복사 전 상태

src가 Statistics 객체를 포함하고 있다.

 

  • 복사 후 상태
    dst는 새로운 BusTran 객체이지만, 여전히 같은 Statistics 객체를 가리키고 있다.

new를 사용한 복사는 기본적으로 얕은 복사(shallow copy)이며, 내부 객체를 별도로 복사하지 않는다.

 


4.15.2 사용자 정의 단순 복사 함수(Writing your own simple copy function)

얕은 복사의 문제를 해결하기 위해 사용자가 직접 copy 함수를 정의할 수 있다.

예제 4-29: 단순 복사 함수 작성

class BusTran;
  bit [31:0] addr, crc, data[8];

  function BusTran copy;
    copy = new;
    copy.addr = addr;
    copy.crc = crc;
    copy.data = data; // 배열 복사
  endfunction
endclass

위 코드에서 copy 함수는 new를 통해 새로운 객체를 생성한 후, 기존 객체의 데이터를 복사한다.

예제 4-30: 복사 함수 사용

BusTran src, dst;
initial begin
  src = new();
  dst = src.copy(); // copy()를 사용하여 복사
end

이 방식은 단순한 데이터만 포함된 객체에는 유용하지만, 내부 객체를 포함하는 복합 클래스에서는 여전히 문제가 발생할 수 있다.


4.15.3 사용자 정의 깊은 복사 함수(Writing your own deep copy function)

복합 객체를 포함한 클래스의 경우, 깊은 복사(deep copy)를 수행해야 한다. 즉, 내부 객체도 새로운 인스턴스를 생성하여 복사해야 한다.

예제 4-31: 깊은 복사 함수 작성

class BusTran;
  bit [31:0] addr, crc, data[8];
  Statistics stats;
  static int count = 0;
  int id;

  function new;
    stats = new();
    id = count++;
  endfunction

  function BusTran copy;
    copy = new();
    copy.addr = addr;
    copy.crc = crc;
    copy.data = data;
    copy.stats = stats.copy(); // 내부 객체도 복사
    id = count++;
  endfunction
endclass

위 코드에서 copy.stats = stats.copy();를 호출하여 내부 객체도 새로운 인스턴스로 복사함으로써, 기존의 얕은 복사 문제를 해결한다.

깊은 복사 후 상태

  • 복사 전 상태
  • src ----> id=3, stats ----> startT=42 dst ----> NULL
  • 복사 후 상태
  • src ----> id=3, stats ----> startT=42 dst ----> id=4, stats ----> startT=96 (별도의 객체로 복사됨)

 

즉, 깊은 복사를 수행하면 src.stats와 dst.stats가 서로 다른 객체가 되어, dst.stats.startT = 96;을 변경해도 src.stats에는 영향을 주지 않는다.

깊은 복사(Deep Copy)란?
얕은 복사(Shallow Copy)는 객체의 레퍼런스만 복사하는 방식이지만, 깊은 복사는 내부 객체까지 새로운 인스턴스를 생성하여 복사하는 방식이다.
SystemVerilog에서는 copy 메서드를 직접 구현하여 깊은 복사를 수행할 수 있다.


결론

SystemVerilog에서 객체를 복사하는 방법은 new를 사용한 기본 복사(얕은 복사)와 사용자 정의 복사 메서드(깊은 복사)가 있다.

  • new 사용 → 단순한 얕은 복사만 가능 (내부 객체는 복사되지 않음)
  • 사용자 정의 copy 함수 → 모든 데이터를 포함한 깊은 복사 수행 가능
  • 깊은 복사를 수행하려면, 내부 객체도 copy 함수를 제공해야 한다.

객체 복사는 검증 환경에서 중요한 개념이며, 복사 방식을 올바르게 이해해야 효율적인 테스트벤치를 설계할 수 있다.

 

 

 

 

Chris Spear 저자님의

SystemVerilog For Verification

A Guide to Learning the Testbench Language Features

내용을 기본으로 작성되었습니다.