지노랩 /JinoLab
[UVM] 5.6.6 액티브 모니터링(Active Monitoring) ― DUT가 “스스로 바꾼” 레지스터 값을 미러에 즉시 반영하기 본문
UVM(Universal Verification Methodology)/5. Register Layer Class 사용하기
[UVM] 5.6.6 액티브 모니터링(Active Monitoring) ― DUT가 “스스로 바꾼” 레지스터 값을 미러에 즉시 반영하기
지노랩/JinoLab 2025. 5. 13. 11:411 | 왜 필요한가?
- 미러 값은 보통
- TB API read/write() 호출
- 버스 모니터가 관측한 트랜잭션 (옵션)
로만 갱신됩니다.
- 하지만 DUT 내부 로직이 카운터 증가, 상태비트 자동 클리어/셋 등을 수행하면 미러와 실제 값이 불일치.
➜ 액티브 모니터링: RTL 신호 변화를 직접 감지해 미러를 동기화
2 | 구현 개요
요소 해야 할 일
| 사용자-정의 백도어 (extends uvm_reg_backdoor) | ① 어떤 필드를 모니터링할지 지정② 값 변화를 감지하는 wait_for_change() 구현 |
| 미러 갱신 스레드 | backdoor.start_update_thread(reg_inst) 호출 → 내부에서 루프 수행 |
| 기존 트랜잭션 예측 | 비활성화. 액티브 모니터링 필드는 이 메커니즘만으로 갱신됨 |
3 | 필수 가상 메서드
class active_monitor_r1 extends uvm_reg_backdoor;
// 3-1. 모니터링 대상 필드?
virtual function bit is_auto_updated(string fld_name);
return (fld_name == "f1" || fld_name == "f2");
endfunction
// 3-2. 값이 바뀔 때까지 블로킹
virtual task wait_for_change();
@($root.tb_top.dut.rf.f1 or $root.tb_top.dut.rf.f2);
endtask
endclass
- is_auto_updated() – TRUE 반환한 필드는 트랜잭션 예측을 건너뛰고
액티브 모니터링 스레드에서만 갱신됩니다. - wait_for_change() – 실제 변화 이벤트를 감시해야 성능 최적.
단순 클록 엣지가 아닌, 값 변화 또는 디자인 내부 ready 신호 등 사용.
4 | 사용 예 – 블록 build 단계에서 등록
class ral_blk_with_am extends RAL_CODEC_BLK;
virtual function void build();
super.build(); // 기존 RAL 구성
// (1) 백도어 인스턴스 생성
active_monitor_r1 am = new;
// (2) 대상 레지스터에 연결
R1.set_backdoor(am); // R1은 이 블록 안 레지스터 인스턴스
// (3) 모니터링 스레드 시작
am.start_update_thread(R1); // 내부 포크 스레드 생성
endfunction
endclass
start_update_thread() 는 백도어 객체가
영구 루프: wait_for_change() → 필드 미러 갱신 → 다시 대기 …
를 실행하도록 fork-join_none 형태로 스폰합니다.
5 | 주의 사항 & 팁
항목 내용
| 동기 vs. 비동기 | 값 변경 이벤트가 클록 비동기(예: HW clear-on-read)라면 @(*) 류로 감지 |
| 미러 정확도 | 액티브 필드는 기존 bus-predict 경로를 건너뛰므로 중복 업데이트 위험 없음 |
| 성능 | 변화를 정확히 트리거할수록 시뮬 overhead ↓ |
| 다중 필드/레지스터 | 백도어 클래스 하나로 여러 레지스터를 모니터링 가능start_update_thread() 레지스터마다 호출 |
| 초기 값 | 스레드 시작 전 reg.mirror(UVM_BACKDOOR) 로 초기 미러 일치 권장 |
본 내용은
accellera에서 공개한
Universal Verification Methodology
(UVM) 1.2 User's Guide
를 바탕으로 작성된 글입니다.