Hello Verification Academy Team,
In my understanding, we can use p_sequencer as a handle to the sequencer and through that we can access other sequencers or environment hierarchy in the sequence where uvm_declare_p_sequencer macro has been used.
Below is my understanding and relevant information. You may please correct if required.
define uvm_declare_p_sequencer(SEQUENCER) \ SEQUENCER p_sequencer;\ virtual function void m_set_p_sequencer();\ super.m_set_p_sequencer(); \ if( !$cast(p_sequencer, m_sequencer)) \
uvm_fatal(“DCLPSQ”,
$sformatf(“%m %s Error casting p_sequencer, please verify that this sequence/sequence item is intended to execute on this type of sequencer”, get_full_name()))
endfunction
p_sequencer type is specified in the argument(SEQUENCER) of uvm_declare_p_sequencer macro. When we call
uvm_declare_p_sequencer from sequence, it calls super.m_set_p_sequencer function, which internally will call m_set_sequencer of uvm_base_sequencer.
When we call start task of sequence, it internally calls for set_item_context, set_item_context calls set_sequencer, set_sequencer assigns handle of sequencer (which we have passed in start task of sequence) to m_sequencer using static cast (***This is first casting or down casting)
virtual function void set_sequencer(uvm_sequencer_base sequencer);
m_sequencer = sequencer;
m_set_p_sequencer();
endfunction
set_sequencer also calls m_set_p_sequencer(declaring `uvm_declare_p_sequencer macro should override the m_set_p_sequencer hence m_set_p_sequencer defined in macro should be executed) which will cast m_sequencer back into p_sequencer using dynamic $cast. (***This is reverse casting or up casting)
MY QUESTIONs:
- Why do we need this reverse/up casting? what is intended and achieved with this step?
- Can we pass virtual sequencer as an argument to uvm_declare_p_sequencer inside both virtual sequence and non-virtual sequence?
- In case when we are using virtual sequence, and passed virtual sequencer as an argument to uvm_declare_p_sequencer inside it , when we call this virtual sequence from test , we pass null in the start task of the virtual sequence. In this case what will happen? m_sequencer = null and then , m_sequencer = p_sequencer and p_sequencer = m_sequencer , is that correct understanding? OR m_sequencer = p_sequencer and then m_sequencer = null and p_sequencer = m_sequencer , is that correct understanding? I am getting lost here!