지노랩 /JinoLab
[UVM] 5.5.2 레지스터 타입(Register Type) ― uvm_reg를 상속해 “하나의 레지스터 클래스”를 만드는 방법 본문
UVM(Universal Verification Methodology)/5. Register Layer Class 사용하기
[UVM] 5.5.2 레지스터 타입(Register Type) ― uvm_reg를 상속해 “하나의 레지스터 클래스”를 만드는 방법
지노랩/JinoLab 2025. 5. 7. 12:12
1 | 기본 골격 & 규칙
규칙 설명
| 클래스 1 개 = 레지스터 타입 1 개 | 같은 구조·필드 조합을 공유하는 레지스터는 하나의 타입으로 표현 |
| uvm_reg 상속 | class my_reg_type extends uvm_reg; |
| uvm_object_utils() | 팩터리·print/randomize 지원 |
| 유일한 이름 | 생성기가 파일·패키지 범위에서 중복되지 않도록 관리 |
class MY_CFG_REG extends uvm_reg;
`uvm_object_utils(MY_CFG_REG)
endclass
2 | 필드 프로퍼티 & 제약
class MY_CFG_REG extends uvm_reg;
// 2.1 모든 필드를 rand 프로퍼티로 선언
rand uvm_reg_field MODE;
rand uvm_reg_field CH[2];
// 2.2 (선택) 레지스터 레벨 제약
constraint VALID_C { MODE.value < 4; }
endclass
- 대문자 이름 권장 → uvm_reg 내부 심볼과 충돌 방지
- 한 필드짜리 레지스터일 때 → value라는 rand 프로퍼티 + dummy field 패턴으로 자연스러운 randomize 사용(가이드 예시 참고)
3 | 생성자(new)
function new(string name="MY_CFG_REG");
// super.new(name, 비트폭, 커버리지)
super.new(.name(name), .n_bits(32), .has_coverage(UVM_NO_COVERAGE));
endfunction
4 | build() 메서드
virtual function void build();
// 4.1 MODE 필드 인스턴스화
MODE = uvm_reg_field::type_id::create("MODE", null, get_full_name());
MODE.configure(this, // 부모(레지스터)
2, // 비트폭
0, // LSB
"RW", // access
0, 1, // reset_val, has_reset
1, 1, // is_rand, individually_accessible
0); // volatile
// 4.2 CH[0], CH[1] 배열 필드
foreach (CH[i]) begin
CH[i] = uvm_reg_field::type_id::create($sformatf("CH%0d",i),
null, get_full_name());
CH[i].configure(this, 1, 2+i, "RW", 0,0,1,1,0);
end
endfunction
- create() 의 parent 인자 null, context = get_full_name() → uvm_object 계층 규칙
- configure() 인자 순서: parent, size, lsb, access, reset, has_reset, is_rand, indv_acc, volatile
5 | (선택) 추가 메서드 – RMW 예
task RMW(output uvm_status_e status,
input uvm_reg_data_t data,
input uvm_reg_data_t mask);
uvm_reg_data_t tmp;
read (status, tmp);
tmp = (tmp & ~mask) | (data & mask);
write(status, tmp);
endtask
주의: UVM 표준에는 없는 “확장 API” 이므로 대문자 / 회사 접두어로 이름 충돌 방지!
6 | 레지스터-단 커버리지 모델 (옵션)
class MY_CFG_REG extends uvm_reg;
local covergroup cg_bits;
coverpoint m_data[1:0]; // 사용자 정의
endgroup
function new(string name="MY_CFG_REG");
super.new(name, 32,
build_coverage(UVM_CVR_REG_BITS)); // 레지스터 비트 커버리지 선언
if (has_coverage(UVM_CVR_REG_BITS))
cg_bits = new();
endfunction
virtual function void sample(uvm_reg_data_t data,
uvm_reg_data_t be,
bit is_rd,
uvm_reg_map map);
if (get_coverage(UVM_CVR_REG_BITS)) begin
m_data = data;
cg_bits.sample();
end
endfunction
endclass
- build_coverage() 또는 add_coverage() 로 어떤 타입 ID를 지원할지 등록
- 실제 샘플링은 get_coverage()로 ON/OFF 확인 후 수행
7 | 블록/레지스터 파일 build()에서 인스턴스화
class codec_blk extends uvm_reg_block;
rand MY_CFG_REG CONFIG;
virtual function void build();
default_map = create_map("sfr", 'h0, 4, UVM_LITTLE_ENDIAN);
CONFIG = MY_CFG_REG::type_id::create("CONFIG");
CONFIG.configure(this); // parent 블록 설정
CONFIG.build();
default_map.add_reg(CONFIG, 'h00, "RW", 0);
endfunction
endclass
핵심 체크리스트 (Generator 관점)
- uvm_reg 상속 + utils 매크로
- rand uvm_reg_field 프로퍼티 선언 & 대문자
- new() → super.new(name, width, coverage)
- build() → 필드 create + configure
- 필요 시 제약, 도우미 메서드, covergroup 추가
- 블록·파일 build()에서 타입 인스턴스화 + 맵 등록
이렇게 하면 스펙 변경 시 생성기 재실행만으로 새로운 레지스터 구조가 자동 반영됩니다.
본 내용은
accellera에서 공개한
Universal Verification Methodology
(UVM) 1.2 User's Guide
를 바탕으로 작성된 글입니다.
'UVM(Universal Verification Methodology) > 5. Register Layer Class 사용하기' 카테고리의 다른 글
| [UVM] 5.5.4 메모리 타입(Memory Type) ― uvm_mem 확장으로 RAM·FIFO 등을 모델링하기 (0) | 2025.05.08 |
|---|---|
| [UVM] 5.5.3 레지스터 파일 타입(Register File Type) ― uvm_reg_file 확장으로 다층 레지스터군(배열·서브파일 포함)을 모델링하기 (0) | 2025.05.08 |
| [UVM] 5.5.1 필드 타입(Field Type) ― 레지스터 필드를 객체로 “정의·제약·확장”하는 방법 (0) | 2025.05.07 |
| [UVM] 5.5 레지스터 모델 생성 — “Generator 작성자를 위한 실전 절차” (0) | 2025.05.06 |
| [UVM] 5.4 커버리지 모델 – RAL 내부에서도 “무엇을 얼마나 덮었는가”를 보려면 (0) | 2025.05.06 |