1. Why use sequence
The main function of sequence is to facilitate the generation of transactions for testing. It is unreasonable to directly generate a transaction in the driver during verification. The reasons include:
- The function of the driver is to convert the transaction into an excitation signal. If the function generating the transaction is placed in the driver, the functions of the driver will be too coupled and cause unnecessary problems.
- If a transaction is generated directly in the driver in one test, the driver code must be modified when other transactions are generated in another test, which is not convenient for code reuse.
Therefore, when building the verification platform, we will get used to generating transaction s in the sequence, mount the sequence in the sequencer, and connect the driver and the sequencer to complete the generation of incentives.
2. Start sequence
There are two ways to start a sequence: direct start and default sequence start.
- Direct start
my_sequence my_seq; my_seq = my_sequence::type_id::create("my_seq"); my_seq.start(sequencer);
- default sequence
class case0_sequence extends uvm_sequence #(my_transaction); my_transaction m_trans; function new(string name= "case0_sequence"); super.new(name); endfunction virtual task pre_body(); `uvm_info("sequence0", "pre_body is called!!!", UVM_LOW) endtask virtual task post_body(); `uvm_info("sequence0", "post_body is called!!!", UVM_LOW) endtask virtual task body(); if(starting_phase != null) starting_phase.raise_objection(this); #100; `uvm_info("sequence0", "body is called!!!", UVM_LOW) if(starting_phase != null) starting_phase.drop_objection(this); endtask `uvm_object_utils(case0_sequence) endclass class my_case0 extends base_test; function new(string name = "my_case0", uvm_component parent = null); super.new(name,parent); endfunction extern virtual function void build_phase(uvm_phase phase); `uvm_component_utils(my_case0) endclass function void my_case0::build_phase(uvm_phase phase); case0_sequence cseq; super.build_phase(phase); cseq = new("cseq"); uvm_config_db#(uvm_sequence_base)::set(this, "env.i_agt.sqr.main_phase", "default_sequence", cseq); endfunction class my_case1 extends base_test; function new(string name = "my_case1", uvm_component parent = null); super.new(name,parent); endfunction extern virtual function void build_phase(uvm_phase phase); `uvm_component_utils(my_case1) endclass function void my_case1::build_phase(uvm_phase phase); super.build_phase(phase); uvm_config_db#(uvm_object_wrapper)::set(this, "env.i_agt.sqr.main_phase", "default_sequence", case0_sequence::type_id::get()); endfunction
3. Arbitration of sequence
It is allowed to start multiple sequences on the same sequencer at the same time, as follows:
task my_case0::main_phase(uvm_phase phase); sequence0 seq0; sequence1 seq1; seq0 = new("seq0"); seq0.starting_phase = phase; seq1 = new("seq1"); seq1.starting_phase = phase; env.i_agt.sqr.set_arbitration(SEQ_ARB_STRICT_FIFO); fork seq0.start(env.i_agt.sqr); seq1.start(env.i_agt.sqr); join endtask
How to schedule the order between two sequences depends on the priority of the sequence and the arbitration mode of the current platform.
- Priority of sequence
Each sequence is doing uvm_do has a priority parameter. The priority parameter must be greater than or equal to - 1. The higher the value, the higher the priority. By default, the priority parameter is - 1.
The priority of sequence can be changed by yourself. Using uvm_do_pri() or uvm_do_pri_with()
`uvm_do_pri(transaction, priority) `uvm_do_pri_with(transaction, priority,constraint)
- Arbitration mode of sequence
Arbitration mode | describe |
---|---|
SEQ_ARB_FIFO | By default, the sequencer's arbitration algorithm will strictly follow the first in first out order without considering the priority |
SEQ_ARB_WEIGHTED | Weighted arbitration |
SEQ_ARB_RANDOM | Completely random selection |
SEQ_ARB_STRICT_FIFO | Strictly follow the priority. When there are multiple sequence s with the same priority, they are selected in the order of first in first out |
SEQ_ARB_STRICT_RANDOM | It is strictly in accordance with the priority. When there are multiple sequence s with the same priority, it is randomly selected from the highest priority |
SEQ_ARB_USER | Users can customize a new arbitration algorithm |