m_sequencer:
- Definition:
The m_sequencer is a handle to the sequencer instance in the sequence. It is default sequencer. It provides access to the sequencer’s methods and properties.
- Scope: Private (internal to UVM).
- Use Case:
The m_sequencer is automatically created and managed by UVM. It is used internally by the sequence to communicate with the sequencer. Users typically do not interact with m_sequencer directly.
p_sequencer:
- Definition:
The p_sequencer is a type-specific reference to the parent sequencer. It allows sequences to interact with user-defined methods or attributes in a customized sequencer.
- Scope: Public (available to the user).
- Use case:
When you extend the UVM sequencer and define additional functionality, sequences can access this functionality via p_sequencer. It requires type casting to ensure the sequence knows the exact type of the sequencer it interacts with.
Example for m_sequencer and p_sequencer:
m_sequencer:
Consider a simple example with an adder DUT that takes two inputs (a and b) and generates an output (sum). Here’s how the UVM sequencer works:
- sequence class
class adder_sequence extends uvm_sequence #(adder_transaction);
`uvm_object_utils(adder_sequence)
adder_transaction trans;
// Constructor
function new(string name = "adder_sequence");
super.new(name);
endfunction
// Body
virtual task body();
trans=adder_transaction::type_id::create("trans");
// Start generating transactions
for (int i=0; i<5; i++) begin
start_item(trans);
trans = adder_transaction::type_id::create("trans");
trans.randomize();
`uvm_info("SEQUENCE", $sformatf("Generated transaction: a=%0d, b=%0d", trans.a, trans.b), UVM_MEDIUM)
finish_item(trans);
end
endtask
endclass
2. Sequencer class (default or m_sequencer)
class adder_sequencer extends uvm_sequencer #(adder_transaction);
`uvm_component_utils(adder_sequencer)
// Constructor
function new(string name = "adder_sequencer", uvm_component parent = null);
super.new(name, parent);
endfunction
endclass
p_sequencer:
Suppose you want to extend the sequencer to include a transaction_count variable:
- Customized Sequencer:
class custom_adder_sequencer extends adder_sequencer;
`uvm_component_utils(custom_adder_sequencer)
int transaction_count;
// Constructor
function new(string name = "custom_adder_sequencer", uvm_component parent = null);
super.new(name, parent);
transaction_count = 0;
endfunction
endclass
2. Using p_sequencer in the Sequence:
class custom_adder_sequence extends adder_sequence;
`uvm_object_utils(custom_adder_sequence)
adder_transaction trans;
// Body
virtual task body();
trans = adder_transaction::type_id::create("trans");
for (int i=0; i<5; i++) begin
start_item(trans);
trans.randomize();
`uvm_info("SEQUENCE", $sformatf("Generated transaction: a=%0d, b=%0d", trans.a, trans.b), UVM_MEDIUM)
// Access custom sequencer properties using p_sequencer
p_sequencer.transaction_count++;
`uvm_info("SEQUENCE", $sformatf("Transaction Count: %0d", p_sequencer.transaction_count), UVM_LOW)
finish_item(trans);
end
endtask
endclass
In this example, the sequence accesses the transaction_count variable of the customized sequencer using p_sequencer.