Hierarchical sequences Link to heading

Big part of sequencer functionality( ie. complexity) is sequence arbitration. That’s why we have the whole start_item and get_next_item thing AKA driver-sequence protocol.

In this example, I am using 2 sequences with p_sequencer. By default, the priority of all items from sequences are equal and default arbitration algorithm is fifo.

class my_sequence extends uvm_sequence#(my_transaction);
  `uvm_object_utils(my_sequence)
  `uvm_declare_p_sequencer(my_sequencer)
  	function  new(string name="");
		super.new(name);
	endfunction

  	m_seq1 s1;
    m_seq2 s2;
    
  	task body();
      
      s1 = m_seq1::type_id::create("s1");
      s2 = m_seq2::type_id::create("s2");
        
      fork
        s1.start(p_sequencer);
        s2.start(p_sequencer);
      join
    endtask: body
endclass

Sequencer alternates between sequences. So, we have item from each sequence in order they were called from virtual sequence.

#  0
# 10
#  1
# 11
#  2
# 12
#  3
# 13
#  4
# 14

grab the sequencer Link to heading

In some scenarios (like in interrupt handling), it’s needed to steal the sequencer to send all the items from a given sequence. That’s why there is grab().

grab allows the sequence to send all transactions until sequence call ungrab. After that sequencer will continue getting items from other sequences

      grab();
      for(int i = 0; i < 5; i++) begin
        item = new();
        start_item(item);
        item.i = i + 10;
        finish_item(item);
      end
      ungrab();

here is the output with grab. all the items from my_seq2 is send first then the items from my_seq1.

# 10
# 11
# 12
# 13
# 14
#  0
#  1
#  2
#  3
#  4

Putting it all together Link to heading

`include "uvm_macros.svh"

import uvm_pkg::*;


class my_transaction extends uvm_sequence_item;
  rand logic[3:0] i;
endclass

class m_seq1 extends uvm_sequence#(my_transaction);
  `uvm_object_utils(m_seq1)
  	function  new(string name="");
		super.new(name);
	endfunction

    task body();
      my_transaction item;
      for(int i = 0; i < 5; i++) begin
        item = new();
        start_item(item);
        item.i = i ;
        finish_item(item);
      end
    endtask: body
endclass

class m_seq2 extends uvm_sequence#(my_transaction);
  `uvm_object_utils(m_seq2)
  	function  new(string name="");
		super.new(name);
	endfunction

    task body();
      my_transaction item;
      grab();
      for(int i = 0; i < 5; i++) begin
        item = new();
        start_item(item);
        item.i = i + 10;
        finish_item(item);
      end
      ungrab();
    endtask: body
endclass


typedef uvm_sequencer #(my_transaction) my_sequencer;

/*
*/
class my_sequence extends uvm_sequence#(my_transaction);
  `uvm_object_utils(my_sequence)
  `uvm_declare_p_sequencer(my_sequencer)
  	function  new(string name="");
		super.new(name);
	endfunction

  	m_seq1 s1;
    m_seq2 s2;
    
  	task body();
      
      s1 = m_seq1::type_id::create("s1");
      s2 = m_seq2::type_id::create("s2");
        
      fork
        s1.start(p_sequencer);
        s2.start(p_sequencer);
      join
    endtask: body
endclass

/*
*/
class driver extends uvm_driver#(my_transaction);
	`uvm_component_utils(driver)

	function  new(string name="", uvm_component parent=null);
		super.new(name, parent);
	endfunction

	task run_phase(uvm_phase phase);
      my_transaction req;
      
      forever begin
         seq_item_port.get_next_item(req);
         $display(req.i);
         seq_item_port.item_done();
      end
	endtask
endclass

/*
*/
class my_agent extends uvm_agent;
  	`uvm_component_utils(my_agent)
  
  	driver m_drv;
    my_sequencer m_seqr;
  
	function  new(string name="", uvm_component parent=null);
		super.new(name, parent);
	endfunction


	function void build_phase(uvm_phase phase);
		super.build_phase(phase);
		m_drv = driver::type_id::create("m_drv", this);
        m_seqr= my_sequencer::type_id::create("m_seqr", this);
	endfunction

	function void connect_phase(uvm_phase phase);
      super.connect_phase(phase);
      m_drv.seq_item_port.connect(m_seqr.seq_item_export);
	endfunction
endclass

/*
*/
class my_env extends uvm_env;
	`uvm_component_utils(my_env)

  	my_agent m_agt;
  
	function  new(string name="", uvm_component parent=null);
		super.new(name, parent);
	endfunction

	function void build_phase(uvm_phase phase);
		super.build_phase(phase);
      	m_agt = my_agent::type_id::create("m_agt", this);
	endfunction

	function void connect_phase(uvm_phase phase);
      	super.connect_phase(phase);
	endfunction
endclass


/*
*/
class my_test extends uvm_test;
`uvm_component_utils(my_test)

  my_env m_env;
  my_sequence m_seq;
  
  function  new(string name="", uvm_component parent=null);
      super.new(name, parent);
  endfunction

  function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      m_env = my_env::type_id::create("m_env", this);
      m_seq = my_sequence::type_id::create("m_seq");
  endfunction

  task run_phase(uvm_phase phase);
      phase.raise_objection(this);
      m_seq.start(m_env.m_agt.m_seqr, null);
      phase.drop_objection(this);
  endtask
endclass

/*
*/
module top;
  initial run_test("my_test");
endmodule