지노랩 /JinoLab
[UVM] 5.5.5 블록 타입(Block Type) ― uvm_reg_block 상속으로 IP 블록 전체를 모델링하기 본문
UVM(Universal Verification Methodology)/5. Register Layer Class 사용하기
[UVM] 5.5.5 블록 타입(Block Type) ― uvm_reg_block 상속으로 IP 블록 전체를 모델링하기
지노랩/JinoLab 2025. 5. 9. 09:21
1 | 블록 타입의 역할
계층 클래스 설명
| Block | uvm_reg_block | IP / 서브시스템 하나를 캡슐화. 여러 레지스터·레지스터 파일·메모리·서브-블록 과 주소 맵 보유 |
| RegFile | uvm_reg_file | 블록 안 하위 레지스터 그룹 |
| Register | uvm_reg | 필드(비트) 집합 |
| Memory | uvm_mem | 대용량 RAM·FIFO |
2 | 기본 골격 & 필수 규칙
class MY_IP_BLK extends uvm_reg_block;
`uvm_object_utils(MY_IP_BLK)
// 2-1. 주소 맵
uvm_reg_map APB;
uvm_reg_map AXI;
// 2-2. 포함 요소
rand CTRL_REG_T R_CTRL;
rand STATUS_RF_TYPE RF_STAT;
BUF256x32_MEM MEM_BUF;
rand SUBSYS_BLK SUB; // 서브-블록
endclass
- 대문자 이름 또는 접두어로 내부 심볼과 충돌 방지
- 레지스터/레지스터 파일/서브-블록은 rand 속성, 메모리는 보통 non-rand
3 | 생성자(new)
function new(string name="MY_IP_BLK");
super.new(.name(name),
.has_coverage(UVM_NO_COVERAGE)); // 필요 시 변경
endfunction
4 | build() 메서드 핵심 순서
virtual function void build();
//------------------------------------------------------------------
// 4-1. 주소 맵 생성
APB = create_map(.name("APB"), .base_addr('h0),
.n_bytes(4), .endian(UVM_LITTLE_ENDIAN));
AXI = create_map("AXI", 'h8000, 4, UVM_LITTLE_ENDIAN);
default_map = APB; // 필수 지정
//------------------------------------------------------------------
//------------------------------------------------------------------
// 4-2. 레지스터 / 레지스터 파일 / 메모리 / 서브-블록 인스턴스
R_CTRL = CTRL_REG_T ::type_id::create("R_CTRL", null, get_full_name());
R_CTRL.configure(this); R_CTRL.build();
APB.add_reg(R_CTRL, 'h00, "RW", 0);
RF_STAT = STATUS_RF_TYPE::type_id::create("RF_STAT", null, get_full_name());
RF_STAT.configure(this); RF_STAT.build();
RF_STAT.map(APB, 'h100);
MEM_BUF = BUF256x32_MEM ::type_id::create("MEM_BUF", null, get_full_name());
MEM_BUF.configure(this);
APB.add_mem(MEM_BUF, 'h400, "RW", 0);
SUB = SUBSYS_BLK::type_id::create("SUB", null, get_full_name());
SUB.configure(this); SUB.build();
// 서브-블록의 default_map 을 상위 맵에 삽입
APB.add_submap(SUB.default_map, 'h800);
//------------------------------------------------------------------
endfunction
포인트
- create_map → 한 블록에 여러 주소 맵 지원 가능
- 인스턴스화 순서: create → configure(블록 부모=this) → build()
- 주소 배치: 레지스터/메모리 add_*, 레지스터 파일 map, 서브-블록 add_submap
5 | (선택) set_offset() — 런타임 오프셋 재배치
virtual function void set_offset(uvm_reg_map mp, uvm_reg_addr_t off);
R_CTRL .set_offset(mp, off + 'h00);
RF_STAT.set_offset(mp, off + 'h100);
MEM_BUF.set_offset(mp, off + 'h400);
SUB .set_offset(mp, off + 'h800);
endfunction
6 | 블록-레벨 커버리지(옵션)
covergroup cg_vals;
cp_mode : coverpoint R_CTRL.MODE.value;
cp_stat : coverpoint RF_STAT.ST0.FLAGS.value;
cross cp_mode, cp_stat;
endgroup
function new(string name="MY_IP_BLK");
super.new(name, build_coverage(UVM_CVR_FIELD_VALS));
if (has_coverage(UVM_CVR_FIELD_VALS))
cg_vals = new();
endfunction
virtual function void sample_values();
super.sample_values();
if (get_coverage(UVM_CVR_FIELD_VALS))
cg_vals.sample();
endfunction
7 | 실무 체크리스트 (Generator Writer)
단계 해야 할 일
| ① 주소 맵 정의 | 최소 1개, default_map 필드에 지정 |
| ② 객체 create/configure/build | get_full_name() 컨텍스트, parent block – this |
| ③ 맵 추가 | add_reg / add_mem / add_submap & 레지스터 파일 map() |
| ④ HDL 경로(back-door) | 필요 시 add_hdl_path[_slice]() |
| ⑤ (옵션) 커버리지 등록 | build_coverage() → has_coverage() 체크 후 covergroup 생성 |
| ⑥ 제약 | 블록 내 필드 cross 제약은 별도 constraint 블록에 배치 |
본 내용은
accellera에서 공개한
Universal Verification Methodology
(UVM) 1.2 User's Guide
를 바탕으로 작성된 글입니다.