05_UVM Object Print 완벽 분석: do_print(), sprint, convert2string 활용법

UVM Object Print 완벽 분석: do_print(), sprint, convert2string 활용법

UVM Object Print 완벽 분석: 효율적인 디버깅을 위한 가이드

UVM (Universal Verification Methodology) 기반 검증 환경에서 uvm_object는 데이터 및 컴포넌트 관련 모든 UVM 클래스의 기반이 되는 중요한 class입니다. 따라서 이 class는 파생된 모든 클래스에서 공통으로 활용할 수 있는 다양한 기능들을 제공합니다. 객체의 내용을 출력하거나, 다른 객체로 내용을 복사하거나, 두 객체를 비교하는 기능은 매우 일반적이면서도 필수적인 기능들입니다. UVM은 이러한 기능들을 모든 클래스에서 쉽고 편리하게 구현할 수 있도록 컴파일 시점에 완전한 코드로 확장되는 다양한 자동화 macro를 제공합니다.

UVM 자동화 Macro를 활용한 Object 내용 출력 예제

다음 예제는 UVM 자동화 macro를 사용하여 변수의 내용을 간단하게 출력하는 방법을 보여줍니다. Object라는 classuvm_object로부터 상속받아 부모 클래스의 모든 기능을 물려받습니다. 다양한 데이터 타입의 변수들이 선언되었으며, randomization 이후 이 변수들의 내용을 출력하려고 시도합니다.

각 데이터 타입에 대응하는 다양한 형태의 `uvm_field_* macro가 존재하며, 변수는 해당 데이터 타입의 macro와 함께 등록되어야 합니다. UVM_DEFAULT는 해당 변수가 객체에 의해 구현된 모든 기본 UVM 자동화 macro (copy, print, compare, record)에 사용되어야 함을 나타냅니다.


typedef enum {FALSE, TRUE} e_bool;
class Object extends uvm_object;

  rand e_bool       m_bool;
  rand bit[3:0]     m_mode;
  rand byte       m_data[4];
  rand shortint   m_queue[$];
  string        m_name;

  constraint c_queue { m_queue.size() == 3; }

  function new(string name = "Object");
    super.new(name);
    m_name = name;
  endfunction

  // 각 변수는 데이터 타입에 해당하는 매크로와 함께 등록해야 합니다.
  // 예를 들어, "int" 타입은 `uvm_field_int, "enum" 타입은 `uvm_field_enum,
  // "string" 타입은 `uvm_field_string을 사용합니다.
  `uvm_object_utils_begin(Object)
    `uvm_field_enum(e_bool, m_bool,  UVM_DEFAULT)
    `uvm_field_int (m_mode,        UVM_DEFAULT)
    `uvm_field_sarray_int(m_data,    UVM_DEFAULT)
    `uvm_field_queue_int(m_queue,   UVM_DEFAULT)
    `uvm_field_string(m_name,      UVM_DEFAULT)
  `uvm_object_utils_end
endclass

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

  // build phase에서 객체를 생성하고, randomize한 후 내용을 출력합니다.
  function void build_phase(uvm_phase phase);
    Object obj = Object::type_id::create("obj");
    obj.randomize();
    obj.print();
  endfunction
endclass

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

기본적으로 UVM printer는 모든 객체의 내용을 변수 이름, 데이터 타입, 크기 및 값 등을 포함하는 테이블 형식으로 출력합니다. 아래 시뮬레이션 결과에서 obj 객체가 지정된 값으로 randomization된 것을 확인할 수 있습니다. 특히 배열 (static 및 queue 모두)의 모든 인덱스 내용이 출력되는 점이 흥미롭습니다.

do_print() Method 활용

최근에는 많은 추가 코드를 발생시키고 시뮬레이터 성능을 저하시키기 때문에 자동화 macro 사용이 권장되지 않습니다. 대신 요구 사항을 구현하기 위해 do_* 콜백 훅을 사용하는 것이 좋습니다. 예를 들어, 내용을 출력하기 위해 사용자는 파생된 객체 내부에 do_print라는 함수를 구현하고 자동화 macro를 전혀 사용하지 않을 수 있습니다.

do_print 함수는 기본적으로 print 함수에 의해 호출되므로 do_print 내부에 정의된 내용은 모두 출력됩니다. 이 예에서는 필요에 따라 모든 변수를 출력할 수 있지만, 여기서는 세 개의 선택된 변수만 출력합니다.


class Object extends uvm_object;

  rand e_bool       m_bool;
  rand bit[3:0]     m_mode;
  rand byte       m_data[4];
  rand shortint   m_queue[$];
  string        m_name;

  constraint c_queue { m_queue.size() == 3; }

  function new(string name = "Object");
    super.new(name);
    m_name = name;
  endfunction

  // 자동화 매크로 대신 "do_print"를 사용합니다.
  `uvm_object_utils(Object)

  // 이 함수는 데이터 타입에 따라 변수를 출력하기 위해 printer 함수를 사용합니다.
  // 예를 들어, "int" 타입 변수는 "print_field_int" 함수를 사용하여 출력합니다.
  virtual function void do_print(uvm_printer printer);
    super.do_print(printer);
    printer.print_string("m_bool", m_bool.name());
    printer.print_field_int("m_mode", m_mode, $bits(m_mode), UVM_HEX);
    printer.print_string("m_name", m_name);
  endfunction
endclass
  

이것은 `uvm_object_utils_*를 사용한 결과와 매우 유사한 출력을 생성합니다. do_print 함수 내부에 세 개의 변수만 구현되었기 때문에 세 개의 변수만 출력되는 것에 유의하십시오.

sprint 및 convert2string 활용

sprintconvert2stringuvm_object의 내용을 문자열 형태로 반환하는 또 다른 유용한 method입니다. print()가 출력을 시뮬레이션 콘솔에 직접 표시하는 반면, 이 두 method는 객체의 정보를 가공하거나 로깅, 파일 저장 등 다른 목적으로 활용할 수 있도록 문자열 형태로 제공합니다.

  • sprint(): 객체의 필드 값을 사람이 읽기 쉬운 형태로 포맷팅하여 문자열로 반환합니다. print()와 유사한 형식을 가지지만, 출력을 화면에 표시하는 대신 문자열 변수에 저장할 수 있습니다.
  • convert2string(): 객체의 모든 정보를 문자열로 변환하는 기본적인 method입니다. sprint()보다 더 기본적인 형태의 문자열 표현을 제공할 수 있으며, 필요에 따라 추가적인 포맷팅을 적용하여 사용할 수 있습니다.

이러한 method들을 활용하면 디버깅 메시지를 사용자 정의 형식으로 만들거나, 특정 조건 하에서만 객체 정보를 기록하는 등 보다 유연한 검증 환경을 구축할 수 있습니다.

결론

UVM의 object print 기능은 검증 과정에서 객체의 상태를 확인하고 디버깅하는 데 매우 중요한 역할을 합니다. 자동화 macro를 사용하는 방법과 do_print() 콜백 함수를 직접 구현하는 방법을 이해하고, 필요에 따라 sprint()convert2string()을 활용하면 보다 효율적이고 강력한 검증 환경을 구축할 수 있습니다. Verilog/SystemVerilog 경험을 바탕으로 UVM의 다양한 기능을 익혀 검증 생산성을 향상시키세요.

다음 이전

POST ADS 2