지노랩 /JinoLab

[UVM] 3.10.1 사용자 정의 시퀀스 선언 (Declaring User-Defined Sequences) 본문

UVM(Universal Verification Methodology)/3. 재사용 가능한 검증 컴포넌트 개발(Developing Reusabl

[UVM] 3.10.1 사용자 정의 시퀀스 선언 (Declaring User-Defined Sequences)

지노랩/JinoLab 2025. 3. 18. 13:20

 

1. 개요

UVM에서 **시퀀스(sequence)**는 여러 개의 트랜잭션(transaction) 객체로 구성되며,
하나의 시퀀스는 특정 패턴의 데이터 흐름을 정의하여 재사용 가능한 검증 시나리오를 생성하는 역할을 함.

(1) 시퀀스 활용의 이점

  • 단순한 개별 트랜잭션 대신, 시퀀스 단위의 테스트를 수행할 수 있음.
  • 재사용 가능한 시퀀스 라이브러리를 구축하여 효율적인 검증 환경을 조성.
  • 시퀀스 내부에서 다른 시퀀스를 호출하여 복잡한 검증 시나리오를 구성 가능.

(2) UVM 시퀀스 개념

  • 모든 시퀀스는 uvm_sequence 클래스를 상속받아 정의.
  • 시퀀스는 특정한 트랜잭션 유형을 다루며, 시퀀서를 통해 실행됨.
  • 시퀀서는 드라이버와 연결되어 트랜잭션을 순차적으로 실행.

2. 사용자 정의 시퀀스 생성 절차

UVM에서 사용자 정의 시퀀스를 생성하는 절차는 다음과 같음:

  1. uvm_sequence 클래스를 상속받아 사용자 정의 시퀀스를 생성.
  2. uvm_object_utils 매크로를 사용하여 시퀀스를 UVM Factory에 등록.
  3. 특정 시퀀서의 기능을 사용해야 할 경우, uvm_declare_p_sequencer 매크로를 활용.
  4. body() 태스크를 구현하여 실행할 트랜잭션 시나리오를 정의.

3. 사용자 정의 시퀀스 예제

(1) 간단한 시퀀스 정의

아래 예제는 simple_seq_do라는 사용자 정의 시퀀스를 정의한 코드임.

class simple_seq_do extends uvm_sequence #(simple_item);
    rand int count; // 랜덤 반복 횟수 설정

    constraint c1 { count > 0; count < 50; } // count 값은 1~49 사이

    // 생성자 (Constructor)
    function new(string name = "simple_seq_do");
        super.new(name);
    endfunction

    // UVM Factory에 등록
    `uvm_object_utils(simple_seq_do)

    // 시퀀스의 실행 로직을 정의하는 body() 태스크
    virtual task body();
        repeat(count) begin
            `uvm_do(req) // 트랜잭션을 생성하고 실행
        end
    endtask : body
endclass : simple_seq_do

(2) 시퀀서를 정의하여 시퀀스를 실행할 준비

위의 simple_seq_do 시퀀스는 simple_sequencer라는 시퀀서에서 실행됨.
시퀀서는 uvm_sequencer 클래스를 상속받아 정의함.

class simple_sequencer extends uvm_sequencer #(simple_item);
    `uvm_component_utils(simple_sequencer)

    function new(string name = "simple_sequencer", uvm_component parent);
        super.new(name, parent);
    endfunction
endclass
  • simple_sequencer는 simple_item 트랜잭션을 처리하는 시퀀서임.
  • simple_seq_do 시퀀스는 이 simple_sequencer에서 실행됨.

4. 사용자 정의 시퀀스 실행

위에서 정의한 simple_seq_do 시퀀스를 실행하려면 다음과 같이 설정하면 됨.

(1) 시퀀서를 생성하여 시퀀스 실행

initial begin
    simple_seq_do seq = simple_seq_do::type_id::create("seq");
    seq.start(my_sequencer);
end
  • simple_seq_do 시퀀스를 UVM Factory에서 생성.
  • start(my_sequencer)를 호출하여 시퀀스를 실행.

(2) 특정 테스트에서 기본 시퀀스 설정

initial begin
    uvm_config_db#(uvm_object_wrapper)::set(null, "uvm_test_top.my_env.my_agent.my_sequencer.run_phase",
                                             "default_sequence", simple_seq_do::get_type());
end
  • 특정 테스트에서 기본 실행할 시퀀스를 simple_seq_do로 설정.

5. 사용자 정의 시퀀스의 확장

UVM에서는 기본 시퀀스를 확장하여 다양한 테스트 시나리오를 구성할 수 있음.
예를 들어, simple_seq_do 시퀀스를 확장하여 더 복잡한 시퀀스를 만들 수 있음.

(1) 확장된 시퀀스 예제

class advanced_seq extends simple_seq_do;
    `uvm_object_utils(advanced_seq)

    function new(string name = "advanced_seq");
        super.new(name);
    endfunction

    virtual task body();
        `uvm_info("ADVANCED_SEQ", "Starting advanced sequence", UVM_LOW)

        // 기존 시퀀스 실행
        super.body();

        // 추가 트랜잭션 실행
        repeat(5) begin
            `uvm_do(req)
        end
    endtask
endclass
  • 기존 simple_seq_do 시퀀스를 확장하여 추가적인 트랜잭션을 실행.
  • super.body()를 호출하여 기본 시퀀스의 동작을 유지하면서 추가적인 동작을 수행.

(2) 확장된 시퀀스를 실행하는 방법

initial begin
    advanced_seq seq = advanced_seq::type_id::create("seq");
    seq.start(my_sequencer);
end
  • advanced_seq를 실행하여 기본 시퀀스 동작 + 추가 트랜잭션 실행.

6. 요약

  • 사용자 정의 시퀀스는 uvm_sequence를 상속받아 생성.
  • 트랜잭션을 실행하는 body() 태스크를 정의해야 함.
  • 시퀀스를 실행할 시퀀서는 uvm_sequencer를 상속받아 정의.
  • 시퀀스를 확장하여 더 복잡한 검증 시나리오를 구성할 수 있음.
  • 시퀀스를 실행하려면 start(sequencer) 메서드를 호출하면 됨.

7. 다음 단계

  • 다양한 테스트 케이스를 위한 복합적인 시퀀스 설계.
  • UVM Factory와 Configuration Database를 활용하여 더 유연한 환경 구성.
  • 시퀀스를 활용한 랜덤 검증 및 커버리지 분석.

즉, 사용자 정의 시퀀스를 활용하면 검증 환경의 재사용성을 높이고, 보다 체계적인 테스트 시나리오를 구성할 수 있음.

 

 

 

 


 

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