uvm sequences has two callback methods pre_body() and post_body(), which are executed before and after the sequence body() method execution. These callbacks are called only when start_sequence() of sequencer or start() method of the sequence is called. User should not call these methods.
virtualtask pre_body()
virtualtask post_body()
(S)Example
In this example, I just printed messages from pre_body() and post_body() methods. These methods can be used for initialization, synchronization with some events or cleanup.
class demo_pre_body_post_body extends uvm_sequence #(instruction);
instruction req;
function new(string name="demo_pre_body_post_body");
super.new(name);
endfunction
One main advantage of sequences is smaller sequences can be used to create sequences to generate stimulus required for todays complex protocol.
To create a sequence using another sequence, following steps has to be done
1)Extend the uvm_sequence class and define a new class.
2)Declare instances of child sequences which will be used to create new sequence.
3)Start the child sequence using <instance>.start() method in body() method.
Sequential Sequences
To executes child sequences sequentially, child sequence start() method should be called sequentially in body method.
In the below example you can see all the 3 steps mentioned above.
In this example, I have defined 2 child sequences. These child sequences can be used as normal sequences.
(S)Sequence 1 code:
This sequence generates 4 PUSH_A instructions.
virtualtask body();
repeat(4) begin `uvm_do_with(req, { inst == PUSH_A; });
end endtask
(S)Sequence 2 code:
This sequence generates 4 PUSH_B instructions.
virtualtask body();
repeat(4) begin `uvm_do_with(req, { inst == PUSH_B; });
end endtask
(S)Sequential Sequence code:
This sequence first calls sequence 1 and then calls sequence 2.
class sequential_sequence extends uvm_sequence #(instruction);
seq_a s_a;
seq_b s_b;
function new(string name="sequential_sequence");
super.new(name);
endfunction