π Introduction#
As testbenches become more complex, virtual sequences and virtual sequencers are essential tools in UVM to coordinate stimulus across multiple agents and sequencers. Sequence libraries and sequence arbitration further enhance sequence management and allow reuse, randomization, and control over conflicting requests.
π Virtual Sequences#
A virtual sequence is a special type of sequence that does not generate transactions itself but coordinates the execution of other sequences, possibly across multiple sequencers. This is especially useful in SoC verification, where you need to orchestrate sequences on different interfaces (e.g., UART, SPI, PCIe).
Example:
class top_level_virtual_sequence extends uvm_sequence #(uvm_sequence_item);
`uvm_object_utils(top_level_virtual_sequence)
// Handles to lower-level sequencers
virtual_uart_sequencer uart_seqr;
virtual_spi_sequencer spi_seqr;
function new(string name = "top_level_virtual_sequence");
super.new(name);
endfunction
task body();
uart_seq uart_seq_inst = uart_seq::type_id::create("uart_seq_inst");
spi_seq spi_seq_inst = spi_seq::type_id::create("spi_seq_inst");
uart_seq_inst.start(uart_seqr);
spi_seq_inst.start(spi_seqr);
endtask
endclass
π§© Virtual Sequencers#
A virtual sequencer is a special sequencer that doesnβt connect to a driver but holds handles to other sequencers. Its main role is to pass these handles to virtual sequences, allowing them to start lower-level sequences on the appropriate sequencer.
Example:
class top_virtual_sequencer extends uvm_sequencer #(uvm_sequence_item);
`uvm_component_utils(top_virtual_sequencer)
uart_sequencer uart_seqr;
spi_sequencer spi_seqr;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
endclass
π Sequence Libraries#
A sequence library is a collection of sequences grouped together to support random selection or specific scenario-driven selection. This is useful for:
- Generating different test scenarios
- Constrained random selection of sequences
- Layered tests
Example:
uvm_sequence_library #(my_sequence_base_type) seq_lib;
initial begin
seq_lib = new("seq_lib");
seq_lib.add_sequence(seq1::get_type());
seq_lib.add_sequence(seq2::get_type());
seq_lib.randomize();
seq_lib.start(my_sequencer);
end
π― Sequence Arbitration#
When multiple sequences want to access the same sequencer (or driver), sequence arbitration resolves conflicts using a built-in arbitration policy:
- FIFO (first-in, first-out): Default mode
- Random: Randomly selects among waiting sequences
- Priority: Based on sequence priority
You can set the arbitration policy on a sequencer:
my_sequencer.set_arbitration(UVM_SEQ_ARB_RANDOM);
π Summary#
Concept | Description |
---|---|
Virtual Sequence | Coordinates multiple sequences across sequencers. |
Virtual Sequencer | Holds handles to lower-level sequencers. |
Sequence Library | Collection of sequences with randomization support. |
Sequence Arbitration | Resolves conflicts among sequences requesting the same sequencer. |