지노랩 /JinoLab

[UVM] 5.5.3 레지스터 파일 타입(Register File Type) ― uvm_reg_file 확장으로 다층 레지스터군(배열·서브파일 포함)을 모델링하기 본문

UVM(Universal Verification Methodology)/5. Register Layer Class 사용하기

[UVM] 5.5.3 레지스터 파일 타입(Register File Type) ― uvm_reg_file 확장으로 다층 레지스터군(배열·서브파일 포함)을 모델링하기

지노랩/JinoLab 2025. 5. 8. 09:15

 

1 | 개념 & 규칙

항목 규칙 비고

클래스 1 개 = 레지스터 파일 1 종류 같은 구성·오프셋 규칙을 갖는 파일은 하나의 타입 클래스로 표현  
상속 class MY_RF_TYPE extends uvm_reg_file;  
utils 매크로 \uvm_object_utils(MY_RF_TYPE)`  
유일 이름 패키지 범위에서 중복되지 않도록 Generator가 관리  

2 | 프로퍼티 선언 – 등록(register)·서브 파일(register file)

class MY_RF_TYPE extends uvm_reg_file;
  // 2.1 포함 레지스터
  rand CFG_REG_T     R_CFG;          // 단일
  rand STATUS_REG_T  R_STAT[4];      // 배열

  // 2.2 포함 레지스터 파일
  rand CH_RF_TYPE    CH[2];          // 채널별 서브 파일
endclass
  • 대문자 또는 접두어로 내부 심볼과 충돌 방지
  • 모든 프로퍼티 rand — 랜덤화·제약 가능

3 | 생성자(new)

function new(string name="MY_RF_TYPE");
  super.new(name);   // uvm_reg_file 는 폭/커버리지 인자 필요 X
endfunction

4 | build() 메서드

virtual function void build();

  uvm_reg_block blk = get_block();   // 상위 블록 핸들

  // 4.1 레지스터 인스턴스화
  R_CFG = CFG_REG_T::type_id::create(
           $sformatf("%s.R_CFG", get_name()),
           null, blk.get_full_name());
  R_CFG.configure(blk, this);  // parent 블록·파일 지정
  R_CFG.build();

  foreach (R_STAT[i]) begin
    R_STAT[i] = STATUS_REG_T::type_id::create(
                $sformatf("%s.R_STAT[%0d]", get_name(), i),
                null, blk.get_full_name());
    R_STAT[i].configure(blk, this);
    R_STAT[i].build();
  end

  // 4.2 서브 레지스터 파일
  foreach (CH[i]) begin
    CH[i] = CH_RF_TYPE::type_id::create(
            $sformatf("%s.CH[%0d]", get_name(), i),
            null, blk.get_full_name());
    CH[i].configure(blk, this);
    CH[i].build();
  end
endfunction

5 | map() 메서드 – 주소 맵에 배치

virtual function void map(uvm_reg_map mp, uvm_reg_addr_t off);

  // 레지스터: add_reg(인스턴스, base+offset, access, unmapped?)
  mp.add_reg(R_CFG,  off + 'h00, "RW", 0);

  foreach (R_STAT[i])
    mp.add_reg(R_STAT[i], off + ('h10 + i*4), "RO", 0);

  // 서브 파일: 재귀 호출
  foreach (CH[i])
    CH[i].map(mp, off + ('h100 + i*'h80));
endfunction
  • off 파라미터로 상위 파일/블록 기준 오프셋 전달
  • 필요하면 add_hdl_path() 로 back-door 경로도 설정

6 | set_offset() (선택) – 런타임 주소 재배치

virtual function void set_offset(uvm_reg_map mp, uvm_reg_addr_t off);
  R_CFG. set_offset(mp, off + 'h00);
  foreach (R_STAT[i])
    R_STAT[i].set_offset(mp, off + ('h10 + i*4));
  foreach (CH[i])
    CH[i].set_offset(mp, off + ('h100 + i*'h80));
endfunction
  • 다른 맵(예: APB↔AXI) 에서 동적 오프셋 변경이 필요할 때 사용

7 | 교차 제약 예 (레지스터 간)

constraint CFG_STAT_LOCK {
  // 예: CFG.MODE 가 3일 때 STAT.EN 은 0
  R_CFG.MODE.value == 3 -> R_STAT[0].EN.value == 0;
}
  • 제약 블록을 별도 이름으로 두어 필요 시 껐다 켤 수 있게

실무 요약 체크리스트

단계 작업

클래스 선언 extends uvm_reg_file + utils 매크로
프로퍼티 포함 레지스터/서브파일을 rand 로 선언
new() super.new(name) 호출
build() create → configure(blk,this) → build() 반복
map() add_reg, 서브파일 map() 재귀 호출
⑥ (옵션) set_offset() 동적 맵 수정 필요 시 구현
⑦ (옵션) 제약·커버리지 파일 내부 교차 제약, covergroup 추가

자동 Generator는 스펙에서 주소·크기·배열 정보를 읽어 위 절차를 코드로 출력하면 됩니다.


 

본 내용은
accellera에서 공개한
Universal Verification Methodology
(UVM) 1.2 User's Guide
를 바탕으로 작성된 글입니다.