Tutorials

Learn More

How to start a sequence?

A sequence is started by calling the start method that accepts a pointer to the sequencer through which sequence_items are sent to the driver. A pointer to the sequencer is also commonly known as m_sequencer. The start method assigns a sequencer pointer to the m_sequencer and then calls the body() task. On completing the body task with the interaction with the driver, the start() method returns. As it requires interaction with the driver, the start is a blocking method.

start method definition

virtual task start ( uvm_sequencer_base sequencer,
                     uvm_sequence_base parent_sequence = null,
                     int this_priority = -1;
                     bit call_pre_post = 1;

Arguments

Description

sequencer

While starting a sequence, on which sequencer it has to be started, need to be specified whereas other arguments are optional.

parent_sequence

parent_sequence is a sequence that calls the current sequence. If parent_sequence is null, then this sequence is a root parent otherwise, it is a child of parent_sequence.  The parent_sequence’s pre_do, mid_do, and post_do methods will be called during the execution of the current sequence.

this_priority

this_priority is the priority of the sequence (by default it considers the priority of the parent sequence). Higher priority is indicated by higher value.

call_pre_post

By default, call_pre_post = 1 is set which means pre_body and post_body methods will be called. To disable calling these methods, call_pre_post can be set to 0.

For a sequence named as child_seq, the start method can be called as shown below:

assert(child_seq.randomize());
child_seq.start(seqr, parent_seq, priority, call_pre_post);

The following methods are called during sequence execution via the start method:

Method type

Methods

Description

task

pre_start

It is a user-definable callback that is called before the optional execution of the pre_body task.

task

pre_body

It is a user-definable callback that is called before the execution of body only when the sequence is started with start.

task

pre_do

It is a user-definable callback task that is called on parent sequence (if any) before the item is randomized and after sequence has issued wait_for_grant() call.

function

mid_do

It is a user-definable callback function that is called after the sequence item is randomized, and just before the item is sent to the driver.

task

body

It is a user-defined task to write main sequence code.

function

post_do

It is a user-definable callback function that is called after completing the item using either put or item_done methods.

task

post_body

It is a user-definable callback task that is called after the execution of the body only when the sequence is started with the start method.

task

post_start

It is a user-definable callback that is called after the optional execution of the post_body task.

start method execution

Note: 

  1. mid_do and post_do are functions and other methods are tasks.
  2. The pre_start and post_start methods are always called.

The start method call follows the below sequence:

sub_seq.pre_start()        
sub_seq.pre_body()          if call_pre_post==1 
  parent_seq.pre_do(0)      if parent_sequence!=null 
  parent_seq.mid_do(this)   if parent_sequence!=null
sub_seq.body                YOUR STIMULUS CODE 
  parent_seq.post_do(this)  if parent_sequence!=null 
sub_seq.post_body()         if call_pre_post==1 
sub_seq.post_start()

To understand it clearly, base_seq and its derived sequence as child_seq are written with all methods defined.

execution of sequences

Only base_seq and child_seq sequences are shown below. The complete code is available at the executable link.

class base_seq extends uvm_sequence #(seq_item);
  seq_item req;
  `uvm_object_utils(base_seq)
  
  function new (string name = "base_seq");
    super.new(name);
  endfunction

  task pre_start();
    `uvm_info(get_type_name(), "Base seq: Inside pre_start", UVM_LOW);
  endtask
  
  task pre_body();
    `uvm_info(get_type_name(), "Base seq: Inside pre_body", UVM_LOW);
  endtask
  
  virtual task pre_do(bit is_item);
    `uvm_info(get_type_name(), "Base seq: Inside pre_do", UVM_LOW);
  endtask
  
  virtual function void mid_do(uvm_sequence_item this_item);
    `uvm_info(get_type_name(), "Base seq: Inside mid_do", UVM_LOW);
  endfunction
  
  task body();
    `uvm_info(get_type_name(), "Base seq: Inside Body", UVM_LOW);
    `uvm_do(req); // Calls all pre_do, mid_do and post_do methos.
    /*
    req = seq_item::type_id::create("req");
    wait_for_grant();
    assert(req.randomize());
    send_request(req);
    wait_for_item_done(); */
  endtask
  
  virtual function void post_do(uvm_sequence_item this_item);
    `uvm_info(get_type_name(), "Base seq: Inside post_do", UVM_LOW);
  endfunction
  
  task post_body();
    `uvm_info(get_type_name(), "Base seq: Inside post_body", UVM_LOW);
  endtask
endclass

class child_seq extends base_seq;
  `uvm_object_utils(child_seq)
  
  function new (string name = "child_seq");
    super.new(name);
  endfunction

  task pre_start();
    `uvm_info(get_type_name(), "Child seq: Inside pre_start", UVM_LOW);
  endtask
  
  task pre_body();
    `uvm_info(get_type_name(), "Child seq: Inside pre_body", UVM_LOW);
  endtask
  
  task pre_do(bit is_item);
    `uvm_info(get_type_name(), "Child seq: Inside pre_do", UVM_LOW);
  endtask
  
  function void mid_do(uvm_sequence_item this_item);
    `uvm_info(get_type_name(), "Child seq: Inside mid_do", UVM_LOW);
  endfunction
  
  task body();
    `uvm_info(get_type_name(), "Child seq: Inside Body", UVM_LOW);
     //`uvm_do(req); // Calls all pre_do, mid_do and post_do methos.
    
    /*req = seq_item::type_id::create("req");
    wait_for_grant();
    assert(req.randomize());
    send_request(req);
    wait_for_item_done();*/
    
    req = seq_item::type_id::create("req");
    start_item(req);
    assert(req.randomize());
    finish_item(req);
  endtask
  
  function void post_do(uvm_sequence_item this_item);
    `uvm_info(get_type_name(), "Child seq: Inside post_do", UVM_LOW);
  endfunction
  
  task post_body();
    `uvm_info(get_type_name(), "Child seq: Inside post_body", UVM_LOW);
  endtask
endclass

Output:

UVM_INFO testbench.sv(19) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside pre_start
UVM_INFO testbench.sv(23) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside pre_body
UVM_INFO testbench.sv(35) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside Body
UVM_INFO testbench.sv(27) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside pre_do
UVM_INFO testbench.sv(31) @ 0: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside mid_do
UVM_INFO driver.sv(16) @ 0: uvm_test_top.env_o.agt.drv [driver] Driving logic
UVM_INFO testbench.sv(46) @ 50: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside post_do
UVM_INFO testbench.sv(50) @ 50: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside post_body
-----------------------------------------------------------------------------------
UVM_INFO testbench.sv(62) @ 50: uvm_test_top.env_o.agt.seqr@@cseq [child_seq] Child seq: Inside pre_start
UVM_INFO testbench.sv(66) @ 50: uvm_test_top.env_o.agt.seqr@@cseq [child_seq] Child seq: Inside pre_body
UVM_INFO testbench.sv(78) @ 50: uvm_test_top.env_o.agt.seqr@@cseq [child_seq] Child seq: Inside Body
UVM_INFO testbench.sv(70) @ 50: uvm_test_top.env_o.agt.seqr@@cseq [child_seq] Child seq: Inside pre_do
UVM_INFO testbench.sv(74) @ 50: uvm_test_top.env_o.agt.seqr@@cseq [child_seq] Child seq: Inside mid_do
UVM_INFO driver.sv(16) @ 50: uvm_test_top.env_o.agt.drv [driver] Driving logic
UVM_INFO testbench.sv(94) @ 100: uvm_test_top.env_o.agt.seqr@@cseq [child_seq] Child seq: Inside post_do
UVM_INFO testbench.sv(98) @ 100: uvm_test_top.env_o.agt.seqr@@cseq [child_seq] Child seq: Inside post_body
-----------------------------------------------------------------------------------
UVM_INFO testbench.sv(62) @ 100: uvm_test_top.env_o.agt.seqr@@bseq.cseq [child_seq] Child seq: Inside pre_start
UVM_INFO testbench.sv(66) @ 100: uvm_test_top.env_o.agt.seqr@@bseq.cseq [child_seq] Child seq: Inside pre_body
UVM_INFO testbench.sv(27) @ 100: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside pre_do
UVM_INFO testbench.sv(31) @ 100: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside mid_do
UVM_INFO testbench.sv(78) @ 100: uvm_test_top.env_o.agt.seqr@@bseq.cseq [child_seq] Child seq: Inside Body
UVM_INFO testbench.sv(70) @ 100: uvm_test_top.env_o.agt.seqr@@bseq.cseq [child_seq] Child seq: Inside pre_do
UVM_INFO testbench.sv(74) @ 100: uvm_test_top.env_o.agt.seqr@@bseq.cseq [child_seq] Child seq: Inside mid_do
UVM_INFO driver.sv(16) @ 100: uvm_test_top.env_o.agt.drv [driver] Driving logic
UVM_INFO testbench.sv(94) @ 150: uvm_test_top.env_o.agt.seqr@@bseq.cseq [child_seq] Child seq: Inside post_do
UVM_INFO testbench.sv(46) @ 150: uvm_test_top.env_o.agt.seqr@@bseq [base_seq] Base seq: Inside post_do
UVM_INFO testbench.sv(98) @ 150: uvm_test_top.env_o.agt.seqr@@bseq.cseq [child_seq] Child seq: Inside post_body