Sequencer는 테스트 시나리오가 흘러가는 출발점이다. Sequence -> Sequencer 흐름을 따라가며, Sequencer가 어떤 역할을 하고, 어떻게 동작하는지 알아보자.
- Sequence에서 트랜잭션을 생성
- Sequencer가 트랜잭션을 받아 Driver로 전달
1. Sequence란 무엇인가?
시퀀스(Sequence)는 DUT(Device Under Test)에 가하는 자극(stimulus)의 패턴을 정의한 클래스 기반 객체를 뜻한다.
즉, “어떤 데이터를 언제, 어떻게, 몇 번 보낼 것인가?”를 정의하고 생성하는 설계도이자 시나리오이다.
initial begin
clk = 0; rst = 1; #10;
rst = 0;
addr = 8'h05;
data = 8'hAA;
write_en = 1; #20;
write_en = 0;
end
Verilog 테스트벤치에서는 테스트 데이터를 다음과 같이 작성한다. 이런 테스트벤치는 고정된 자극만 제공해 다양한 상황을 자동으로 검증하기 어렵고, 재사용성과 확장성이 낮다는 한계가 있다.
// Transaction Class
class my_data extends uvm_sequence_item;
rand bit [3:0] addr;
rand bit [7:0] data;
constraint c_addr_range {
addr inside {[0:15]};
}
constraint c_data_even {
data % 2 == 0;
}
`uvm_object_utils(my_data)
function new(string name = "my_data");
super.new(name);
endfunction
endclass
// Sequence Class
class my_sequence extends uvm_sequence #(my_data);
`uvm_object_utils(my_sequence)
function new(string name = "my_sequence");
super.new(name);
endfunction
virtual task body();
my_data tx;
repeat (5) begin
tx = my_data::type_id::create("tx");
assert(tx.randomize()); // constraint 기반 랜덤화
`uvm_info("SEQ", $sformatf("addr=%0d, data=%0d", tx.addr, tx.data), UVM_MEDIUM)
start_item(tx);
finish_item(tx);
end
endtask
endclass
이를 극복하기 위해 SystemVerilog에서는 Constraint Random 기법을 사용한다. Sequence는 단순히 값을 정해주는 데 그치지 않고, 제약 조건(constraint)을 설정한 뒤, 그 안에서 무작위(Random)로 다양한 테스트 데이터를 생성하게된다.
1) Transaction
Transaction(트랜잭션)은 UVM에서 DUT와 주고받는 데이터 단위를 표현한 클래스 기반의 객체를 뜻한다.
class my_data extends uvm_sequence_item;
rand bit [7:0] addr;
rand bit [15:0] data;
constraint c_addr { addr inside {[0:15]}; }
`uvm_object_utils(my_data)
function new(string name = "my_data");
super.new(name);
endfunction
endclass
2) Constraint
Constraint는 SystemVerilog에서 랜덤 변수에 대해 "이런 조건을 만족해야 해"라고 제한을 거는 문법이다. 즉, rand로 무작위 값을 생성할 때, 완전 무작위가 아니라, "제약 조건을 만족하는 범위 내에서만 랜덤" 하도록 만들어 준다.
- 테스트 자동화를 위해 무작위 데이터를 만들고 싶지만, 설계가 받아들일 수 없는 값은 피해야 한다.
- 예를 들어, 주소는 0~15만 허용되고, 데이터는 짝수만 가능하다면?
- 이 조건을 강제로 걸어주는 것이 constraint이다.
// 제약 조건 정의
constraint c1 { addr inside {[0:15]}; }
constraint c2 { data % 2 == 0; } // 짝수만 허용
3) randomize()
randomize()는 클래스 객체의 rand로 선언된 변수들을 제약 조건(constraint)을 만족하는 무작위(Random) 값으로 채워주는 함수이다.
2. Sequencer란 무엇인가?
Sequencer는 Sequence(시나리오)에서 생성한 트랜잭션을 Driver에게 전달해주는 중간 관리자 역할을 한다. 즉, 트랜잭션이 흐르는 파이프라인의 중심 허브 역할을 하게된다.
- Sequence는 트랜잭션을 "만드는 역할"
- Sequencer는 그것을 "줄 세우고 전달하는 역할"
- Driver는 받아서 "실행하는 역할"
Sequence와 Driver 사이에서 트랜잭션을 주고받는 메일박스 같은 역할을 하게 된다... 라고 이해하면 된다. 다만, 단순한 mailbox보다 더 구조화되고 안전한 통신을 위해 특별히 설계된 컴포넌트라고 생각하자!
'이론 공부 > UVM (Universal Verification Methodology)' 카테고리의 다른 글
UVM Testbench Structure - 05. Monitor (0) | 2025.04.19 |
---|---|
UVM Testbench Structure - 04. Driver (0) | 2025.04.19 |
UVM Testbench Structure - 02. Agent (0) | 2025.04.18 |
UVM Testbench Structure - 01. UVM TOP (0) | 2025.04.18 |
UVM 개요 (0) | 2025.04.18 |