지노랩 /JinoLab
[UVM] 5.7 특수 레지스터(Special Registers) ― “평범하지 않은 동작은 이렇게 모델링한다” 본문
UVM(Universal Verification Methodology)/5. Register Layer Class 사용하기
[UVM] 5.7 특수 레지스터(Special Registers) ― “평범하지 않은 동작은 이렇게 모델링한다”
지노랩/JinoLab 2025. 5. 14. 09:43UVM 레지스터 라이브러리가 가정하는 기본 레지스터 특성
- 고정된 유일 물리 주소
- 한 값(value)만 보유
- 어떤 인터페이스로 접근해도 행동이 동일
하지만 실제 설계에서는 다음과 같은 예외적 요구가 자주 등장합니다.
특수 사례 예시 필요 동작
| 멀티-어드레스 레지스터 | 동일 데이터가 AXI·APB 두 주소에 매핑 | 인터페이스별 주소 분기 |
| 뱅크 셀렉터 | 베이스 주소 + Bank 레지스터 값으로 실제 위치 결정 | read/write 시 동적 주소 계산 |
| 윈도우(Window) 레지스터 | 인덱스 레지스터가 가리키는 영역을 동시에 노출 | 인덱스 값에 따라 다른 데이터 반환 |
| 데이터+상태 혼합 | 쓰면 FIFO에 push, 읽으면 status clear | write 후 자동 트리거, read 후 clear |
| 가상(Shadow) 레지스터 | SW가 쓰면 내부 FSM이 다른 레지스터에 복사 | post-write 콜백으로 추가 동작 |
UVM에서 특수 행동을 넣는 5가지 방법
방법 대상 한-줄 요약
| 1. 프런트도어(Front-door) 콜백uvm_reg_cbs | 버스 트랜잭션 직전/후 | pre_write에서 주소·데이터 수정, post_read에서 값 변환 |
| 2. 백도어(Back-door) 클래스uvm_reg_backdoor or uvm_mem_backdoor | 직접 read/write | 동적 주소 계산·암호화·ECC 등 구현 |
| 3. 사용자-정의 Front-dooruvm_reg_frontdoor | 시퀀서 기반 커스텀 버스 액세스 | 멀티-버스트, 특수 핸드쉐이크 지원 |
| 4. 가상 함수 오버라이드 | read() / write() | 가장 강력하지만 마지막 수단 → 표준 API 계약 주의 |
| 5. 콜백 체인 + 상태 변수 | 레지스터/필드 클래스 확장 | write-once, lock-bit, 동시 제약 등 구현 |
구현 예시 1 — 윈도우 레지스터 (INDEX + DATA)
class win_data_cb extends uvm_reg_cbs;
uvm_reg_field index_fld;
uvm_mem target_mem;
// DATA 레지스터 읽기 전: 메모리 값 로드
virtual task pre_read(uvm_reg_item rw);
if ($cast(rw.element, DATA_REG_T)) begin
int idx = index_fld.get();
bit [31:0] val;
target_mem.peek(.offset(idx), .value(val));
rw.value[0] = val; // 읽어올 값 덮어쓰기
end
endtask
// DATA 레지스터 쓰기 후: 메모리에 반영
virtual task post_write(uvm_reg_item rw);
if ($cast(rw.element, DATA_REG_T)) begin
int idx = index_fld.get();
target_mem.poke(.offset(idx), .value(rw.value[0]));
end
endtask
endclass
구현 예시 2 — 동적 주소 계산 백도어
class banked_reg_bkdr extends uvm_reg_backdoor;
uvm_reg_field bank_sel; // BANK 필드 핸들
string base_path; // "dut.core.regs"
virtual task write(uvm_reg_item rw);
int bank = bank_sel.get();
string path = $sformatf("%s.bank[%0d].%s",
base_path, bank, rw.element.get_name());
dpi_put(path, rw.value[0]);
endtask
virtual task read(uvm_reg_item rw);
int bank = bank_sel.get();
string path = $sformatf("%s.bank[%0d].%s",
base_path, bank, rw.element.get_name());
dpi_get(path, rw.value[0]);
endtask
endclass
요령 정리
- 가장 간단한 확장부터 적용
- 비트-반전, CLR-on-Write 같은 단순 동작 → pre/post 콜백
- 버스 트랜잭션이 특수하면
- 사용자-정의 Front-door로 시퀀서 제어
- RTL 경로가 복잡·암호화
- 사용자-정의 Back-door로 전용 API 호출
- API 오버라이드는 최후
- 표준 미러·커버리지 연동을 깨뜨릴 위험이 있으니 주의
- 제너레이터 단계에서 자동 삽입
- 스펙에 “특수” 표기 → 코드 자동 생성하여 TB 유지보수 최소화
본 내용은
accellera에서 공개한
Universal Verification Methodology
(UVM) 1.2 User's Guide
를 바탕으로 작성된 글입니다.
'UVM(Universal Verification Methodology) > 5. Register Layer Class 사용하기' 카테고리의 다른 글
| [UVM] 5.7.2 매핑되지 않은(unmapped) 레지스터·메모리 다루기 (0) | 2025.05.15 |
|---|---|
| [UVM] 5.7.1 미리 정의-돼 있는 “특수 레지스터” 두 가지 (0) | 2025.05.14 |
| [UVM] 5.6.6 액티브 모니터링(Active Monitoring) ― DUT가 “스스로 바꾼” 레지스터 값을 미러에 즉시 반영하기 (0) | 2025.05.13 |
| [UVM] 5.6.5 보호 메모리(Protected Memory) 백도어 액세스 ― ECC · 암호화까지 다루는 encode/decode 콜백 (0) | 2025.05.13 |
| [UVM] 5.6.4 사용자-정의 백도어(User-defined Back-door) ― 직접 만든 API로 암호화 IP·특수 구조를 두드리는 법 (0) | 2025.05.12 |