[UVM] UVM Reporting 완전 정리 | `uvm_info, `uvm_error, `uvm_fatal, verbosity, report_server

2026. 4. 10. 20:02UVM

반응형

UVM 리포팅 시스템이란?

UVM은 `uvm_info, `uvm_warning, `uvm_error, `uvm_fatal 네 가지 매크로로 메시지를 출력하는 통합 리포팅 시스템을 제공합니다. 단순 $display와 달리 심각도(severity), 식별자(ID), 상세 수준(verbosity)을 함께 관리할 수 있어 대규모 테스트벤치에서 필수입니다.


4가지 심각도 매크로

// 형식: `uvm_("", "", )

`uvm_info("DRV",  "트랜잭션 전송 시작",     UVM_LOW)
`uvm_info("DRV",  "addr = 0x100",           UVM_MEDIUM)
`uvm_info("DRV",  "내부 상태 덤프",          UVM_HIGH)

`uvm_warning("SCB", "예상과 다른 데이터 수신")      // 계속 진행
`uvm_error("SCB",   "scoreboard 미스매치 발생")     // 에러 카운트 +1
`uvm_fatal("CFG",   "필수 인터페이스 연결 안됨")    // 즉시 시뮬 중단

Verbosity 레벨

Verbosity는 메시지의 상세 수준입니다. 런타임에 설정된 레벨보다 높은 verbosity의 메시지는 출력되지 않습니다. 기본값은 UVM_MEDIUM입니다.

// 낮을수록 항상 출력, 높을수록 필터링됨
UVM_NONE   = 0    // 항상 출력
UVM_LOW    = 100  // 중요 정보
UVM_MEDIUM = 200  // 기본값 (default 출력 임계치)
UVM_HIGH   = 300  // 디버그용 상세 정보
UVM_FULL   = 400  // 매우 상세 (개발 중에만 사용)
UVM_DEBUG  = 500  // 최대 상세

Verbosity 실시간 변경

// 커맨드라인으로 변경
// +UVM_VERBOSITY=UVM_HIGH

// 코드에서 변경 (특정 컴포넌트에만 적용)
env.agent.driver.set_report_verbosity_level(UVM_HIGH);

// 전체 레벨 변경
uvm_top.set_report_verbosity_level_hier(UVM_HIGH);

$sformatf로 동적 메시지 출력

task run_phase(uvm_phase phase);
  my_item tr;
  forever begin
    seq_item_port.get_next_item(tr);
    `uvm_info("DRV",
      $sformatf("Driving: addr=0x%0h data=0x%0h wr=%0b",
                tr.addr, tr.data, tr.write),
      UVM_LOW)
    // ... 드라이빙
    seq_item_port.item_done();
  end
endtask

에러/경고 제어 — set_report_*

특정 ID의 메시지 행동을 변경하거나 억제할 수 있습니다.

// 특정 ID의 UVM_ERROR를 UVM_WARNING으로 격하
set_report_severity_id_override(UVM_ERROR, "SCB", UVM_WARNING);

// 특정 ID 메시지 완전히 억제
set_report_id_action(UVM_INFO, "NOISY_ID", UVM_NO_ACTION);

// 특정 ID 로그 파일로 출력
set_report_id_file("DRV", log_file_handle);
set_report_id_action("DRV", UVM_LOG | UVM_DISPLAY);

uvm_report_server — 전역 통계 관리

uvm_report_server는 시뮬레이션 전체의 에러/경고 카운트를 관리합니다. 시뮬레이션 종료 시 자동으로 요약 리포트를 출력합니다.

// 에러 카운트 직접 확인
function void check_phase(uvm_phase phase);
  uvm_report_server rs = uvm_report_server::get_server();
  int err_cnt = rs.get_severity_count(UVM_ERROR);
  if (err_cnt > 0)
    `uvm_fatal("TEST", $sformatf("Test FAILED: %0d errors", err_cnt))
  else
    `uvm_info("TEST", "Test PASSED", UVM_NONE)
endfunction

// 시뮬레이션 끝 자동 요약 예시:
// --- UVM Report Summary ---
// UVM_INFO   : 1523
// UVM_WARNING:    2
// UVM_ERROR  :    0
// UVM_FATAL  :    0

 

uvm_field_* 매크로 — do_print / do_copy / do_compare 자동화

uvm_object 기반 클래스(주로 sequence_item, transaction)에서 uvm_object_utils_begin / uvm_object_utils_end 블록 안에 uvm_field_* 매크로를 선언하면, print / copy / compare / pack / unpack 동작이 자동으로 구현됩니다. 별도 함수 작성 없이 item.print(), item.compare(other)를 바로 쓸 수 있습니다.

class my_seq_item extends uvm_sequence_item;
  rand bit [7:0]  addr;
  rand bit [31:0] data;
  rand bit        wr_en;
  string          tag;

  `uvm_object_utils_begin(my_seq_item)
    `uvm_field_int   (addr,  UVM_ALL_ON)
    `uvm_field_int   (data,  UVM_ALL_ON)
    `uvm_field_int   (wr_en, UVM_ALL_ON)
    `uvm_field_string(tag,   UVM_ALL_ON)
  `uvm_object_utils_end

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

uvm_field_* 매크로 종류

매크로 대상 타입 설명
`uvm_field_int(F, FLAG) int, bit, logic 등 정수형 정수형 필드 등록
`uvm_field_string(F, FLAG) string 문자열 필드 등록
`uvm_field_object(F, FLAG) uvm_object 파생 클래스 객체 필드 등록 (deep copy 지원)
`uvm_field_array_int(F, FLAG) 배열 (int[]) 정수 배열 등록
`uvm_field_queue_int(F, FLAG) 큐 (int $queue) 정수 큐 등록
`uvm_field_enum(T, F, FLAG) enum 타입 enum 필드 등록 (T는 enum 타입명)

FLAG 주요 값

FLAG 의미
UVM_ALL_ON print, copy, compare, pack/unpack 모두 활성화 (기본 권장)
UVM_NOPRINT print 제외
UVM_NOCOPY copy 제외
UVM_NOCOMPARE compare 제외 (Scoreboard에서 비교 대상 제외 시 유용)
UVM_DEFAULT UVM_ALL_ON과 동일
// 활용 예
my_seq_item a = my_seq_item::type_id::create("a");
my_seq_item b = my_seq_item::type_id::create("b");

a.print();          // uvm_field_*가 선언된 모든 필드 출력
b.copy(a);          // a의 모든 필드를 b에 deep copy
a.compare(b);       // 필드 단위로 비교, 다르면 에러 메시지 출력
// Scoreboard에서 예측값 vs 실제값 비교 시 자주 활용됨

💡 주의: uvm_field_* 매크로는 편리하지만 런타임 오버헤드가 있습니다. 대규모 시뮬레이션에서 성능이 중요하다면 do_print(), do_copy(), do_compare()를 직접 오버라이드하는 방식도 고려할 수 있습니다.