08_UVM object pack 및 unpack : 초보자를 위한 자동화 매크로 활용법 완벽 가이드

UVM 초보자를 위한 자동화 매크로 활용법: pack 및 unpack 완벽 가이드

UVM 자동화 매크로를 활용한 데이터 패킹 및 언패킹

UVM (Universal Verification Methodology)을 처음 접하는 엔지니어 여러분들을 환영합니다! Verilog 또는 SystemVerilog에 대한 기본적인 이해를 갖추셨다면, UVM의 강력한 기능 중 하나인 자동화 매크로를 활용하여 효율적인 검증 환경을 구축할 수 있습니다. 특히, 시리얼 통신 (SPI, I2C, RS-232 등)과 같이 데이터를 직렬 형태로 다루어야 하는 상황에서 pack 및 unpack 기능은 매우 유용합니다.

이번 포스팅에서는 UVM 자동화 매크로를 사용하여 class 변수들을 bit 또는 byte 스트림으로 패킹하고, 반대로 bit 스트림을 언패킹하여 class 내용을 복원하는 방법에 대해 자세히 알아보겠습니다. UVM에서 제공하는 세 가지 주요 패킹/언패킹 함수와 사용자 정의 후킹 함수인 do_pack 및 do_unpack의 활용 예시를 통해 여러분의 이해를 돕고자 합니다.

주요 pack 및 unpack 함수

UVM은 데이터를 효율적으로 처리하기 위해 다음과 같은 세 가지 주요 함수를 제공합니다.

  • pack: class의 내용을 bit 단위로 연결하여 bit 타입의 배열로 반환합니다.
  • pack_bytes: class의 내용을 bit 단위로 연결한 후 byte 단위로 묶어 byte 타입의 배열로 반환합니다.
  • pack_ints: class의 내용을 bit 단위로 연결한 후 integer 단위로 묶어 int 타입의 배열로 반환합니다.
  • unpack: bit 타입의 배열로부터 속성 값을 추출하여 해당하는 class 변수에 저장합니다.
  • unpack_bytes: byte 타입의 배열로부터 속성 값을 추출하여 해당하는 class 변수에 저장합니다.
  • unpack_ints: int 타입의 배열로부터 속성 값을 추출하여 해당하는 class 변수에 저장합니다.

자동화 매크로 사용 예시: Pack

다음 예제에서는 주소와 데이터를 저장하는 Packet 이라는 class를 정의하고, `uvm_field_int 매크로를 사용하여 자동화를 활성화합니다. UVM_DEFAULT는 해당 변수에 모든 기본 자동화 메서드를 적용하도록 지정합니다.

주의할 점은 `uvm_object_utils_* 내에 나열된 변수의 순서가 데이터를 패킹하고 언패킹하는 데 사용된다는 것입니다.

class Packet extends uvm_object;
  rand bit [3:0] m_addr;
  rand bit [3:0] m_wdata;
  rand bit [3:0] m_rdata;
  rand bit 		 m_wr;

  `uvm_object_utils_begin(Packet)
    `uvm_field_int(m_addr, 	UVM_DEFAULT)
    `uvm_field_int(m_wdata, UVM_DEFAULT)
    `uvm_field_int(m_rdata, UVM_DEFAULT)
    `uvm_field_int(m_wr,		UVM_DEFAULT)
  `uvm_object_utils_end

  function new(string name = "Packet");
    super.new(name);
  endfunction
endclass

class pack_test extends uvm_test;
  `uvm_component_utils(pack_test)
  function new(string name = "pack_test", uvm_component parent=null);
    super.new(name, parent);
  endfunction

  bit 						m_bits[];
  byte unsigned		m_bytes[];
  int  unsigned		m_ints[];

  virtual function void build_phase(uvm_phase phase);
    Packet m_pkt = Packet::type_id::create("Packet");
    m_pkt.randomize();
    m_pkt.print();

    m_pkt.pack(m_bits);
    m_pkt.pack_bytes(m_bytes);
    m_pkt.pack_ints(m_ints);

    `uvm_info(get_type_name(), $sformatf("m_bits=%p", m_bits), UVM_LOW)
    `uvm_info(get_type_name(), $sformatf("m_bytes=%p", m_bytes), UVM_LOW)
    `uvm_info(get_type_name(), $sformatf("m_ints=%p", m_ints), UVM_LOW)
  endfunction
endclass

module tb;
  initial begin
    run_test("pack_test");
  end
endmodule

자동화 매크로 사용 예시: Unpack

이번에는 unpack_test 라는 새로운 test class를 만들어 두 개의 Packet 객체를 생성합니다. 하나만 랜덤화하고 다른 하나는 비워둔 상태로 둡니다. 그런 다음 첫 번째 객체의 내용을 배열로 패킹하고, 이 배열을 두 번째 객체로 언패킹하여 내용을 표시합니다. 다른 타입의 pack 함수에 대해서도 동일한 과정을 반복합니다.

class unpack_test extends uvm_test;
  `uvm_component_utils(unpack_test)
  function new(string name = "unpack_test", uvm_component parent=null);
    super.new(name, parent);
  endfunction

  bit 					m_bits[];
  byte unsigned	m_bytes[];
  int  unsigned	m_ints[];

  int m_val1, m_val2, m_val3;

  virtual function void build_phase(uvm_phase phase);
    Packet m_pkt = Packet::type_id::create("Packet");
    Packet m_pkt2 = Packet::type_id::create("Packet");

    `uvm_info(get_type_name(), $sformatf("Start pack"), UVM_LOW)
    m_pkt.randomize();
    m_pkt.print();
    m_pkt.pack(m_bits);
    `uvm_info(get_type_name(), $sformatf("packed m_bits=%p", m_bits), UVM_LOW)

    m_pkt.randomize();
    m_pkt.print();
    m_pkt.pack_bytes(m_bytes);
    `uvm_info(get_type_name(), $sformatf("packed m_bytes=%p", m_bytes), UVM_LOW)

    m_pkt.randomize();
    m_pkt.print();
    m_pkt.pack_ints(m_ints);
    `uvm_info(get_type_name(), $sformatf("packed m_ints=%p", m_ints), UVM_LOW)

    `uvm_info(get_type_name(), $sformatf("Start unpack"), UVM_LOW)
    m_val1 = m_pkt2.unpack(m_bits);
    `uvm_info(get_type_name(), $sformatf("unpacked m_val1=0x%0h", m_val1), UVM_LOW)
    m_pkt2.print();

    m_val2 = m_pkt2.unpack_bytes(m_bytes);
    `uvm_info(get_type_name(), $sformatf("unpacked m_val2=0x%0h", m_val2), UVM_LOW)
    m_pkt2.print();

    m_val3 = m_pkt2.unpack_ints(m_ints);
    `uvm_info(get_type_name(), $sformatf("unpacked m_val3=0x%0h", m_val3), UVM_LOW)
    m_pkt2.print();
  endfunction
endclass

module tb;
  initial begin
    run_test("unpack_test");
  end
endmodule

do_pack/do_unpack 사용

print, copy, compare와 마찬가지로 pack 및 unpack 또한 사용자 정의 가능한 후킹 함수인 do_pack 및 do_unpack를 제공합니다. 이를 통해 패킹 및 언패킹 동작을 사용자의 필요에 맞게 정의할 수 있습니다.

class Packet extends uvm_object;
  rand bit [3:0] m_addr;
  rand bit [3:0] m_wdata;
  rand bit [3:0] m_rdata;
  rand bit 		 m_wr;

  `uvm_object_utils(Packet)

  virtual function void do_print(uvm_printer printer);
    super.do_print(printer);
    printer.print_field_int("m_addr", m_addr, $bits(m_addr), UVM_HEX);
    printer.print_field_int("m_wdata", m_wdata, $bits(m_wdata), UVM_HEX);
    printer.print_field_int("m_rdata", m_rdata, $bits(m_rdata), UVM_HEX);
    printer.print_field_int("m_wr", m_wr, $bits(m_wr), UVM_HEX);
  endfunction

  virtual function void do_pack(uvm_packer packer);
    super.do_pack(packer);
    packer.pack_field_int(m_addr, $bits(m_addr));
    packer.pack_field_int(m_wdata, $bits(m_wdata));
    packer.pack_field_int(m_rdata, $bits(m_rdata));
                                    packer.pack_field_int(m_wr, $bits(m_wr));
  endfunction

  virtual function void do_unpack(uvm_packer packer);
    super.do_pack(packer);
    m_addr = packer.unpack_field_int($bits(m_addr));
    m_wdata = packer.unpack_field_int($bits(m_wdata));
    m_rdata = packer.unpack_field_int($bits(m_rdata));
    m_wr = packer.unpack_field_int($bits(m_wr));
  endfunction

  function new(string name = "Packet");
    super.new(name);
  endfunction
endclass

class hook_test extends uvm_test;
  `uvm_component_utils(hook_test)
  function new(string name = "hook_test", uvm_component parent=null);
    super.new(name, parent);
  endfunction

  bit 					m_bits[];
  Packet m_pkt;
  Packet m_pkt2;

  virtual function void build_phase(uvm_phase phase);
    m_pkt = Packet::type_id::create("m_pkt");
    m_pkt2 = Packet::type_id::create("m_pkt2");
    m_pkt.randomize();
    m_pkt.print();

    m_pkt.pack(m_bits);
    m_pkt2.unpack(m_bits);

    `uvm_info(get_type_name(), "--- After Unpack with Hook ---", UVM_LOW)
    m_pkt2.print();
  endfunction
endclass

module tb;
  initial begin
    run_test("hook_test");
  end
endmodule
다음 이전

POST ADS 2