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

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

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

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

이번 포스팅에서는 UVM 자동화 매크로를 사용하여 class 변수들을 bit 또는 byte 스트림으로 패킹하고, 반대로 bit 스트림을 언패킹하여 class 내용을 복원하는 방법에 대해 자세히 알아보겠습니다. UVM에서 제공하는 세 가지 주요 패킹/언패킹 함수와 사용자 정의 후킹 함수인 do_packdo_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와 마찬가지로 packunpack 또한 사용자 정의 가능한 후킹 함수인 do_packdo_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