`uvm_delare_p_sequencer常见用法:
`//| class mysequence extends uvm_sequence#(mydata);
//| `uvm_object_utils(mysequence)
//| `uvm_declare_p_sequencer(some_seqr_type)
//| task body`;`
//| //Access some variable in the user's custom sequencer
//| if(p_sequencer.some_variable) begin
//| ...
//| end
//| endtask
//| endclass
//`
即在sequence中想要使用sequencer中函数或变量时才会使用psequencer.
1. :`uvm_delare_p_sequencer 分析
源码如下:
`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句柄,类型为该宏传入的sequencer类型,一般为要挂载的sequencer类型。
2 start()如何处理p_sequencer?
uvm_sequence_base parent_sequence = null,
int this_priority = -1,
bit call_pre_post = 1);
bit old_automatic_phase_objection;
set_item_context(parent_sequence, sequencer);
if (!(m_sequence_state inside {UVM_CREATED,UVM_STOPPED,UVM_FINISHED})) begin
uvm_report_fatal("SEQ_NOT_DONE",
{"Sequence ", get_full_name(), " already started"},UVM_NONE);
end
function void set_item_context(uvm_sequence_base parent_seq,
uvm_sequencer_base sequencer = null);
set_use_sequence_info(1);
if (parent_seq != null) set_parent_sequence(parent_seq);
if (sequencer == null && m_parent_sequence != null) sequencer = m_parent_sequence.get_sequencer();
set_sequencer(sequencer);
if (m_parent_sequence != null) set_depth(m_parent_sequence.get_depth() + 1);
reseed();
endfunction
virtual function void set_sequencer(uvm_sequencer_base sequencer);
m_sequencer = sequencer;
m_set_p_sequencer();
endfunction
可见,start()函数会传入实际使用的sequencer句柄,这个句柄会赋给m_sequencer,再由m_sequencer赋给p_sequencer,m_squencer是base_sequencer类型,但p_sequcner是具体使用的sequencer类型,因此必须保证p_sequncer declare类型与start()传入句柄类型一致。