Driver的seq_item_port和Sequencer的seq_item_export
uvm_driver中有一个派生自uvm_seq_item_pull_port的成员 seq_item_port;
uvm_sequencer中有一个派生自uvm_seq_item_pull_imp的成员seq_item_export。
uvm_driver的源代码:
// Definition of uvm_driver
class uvm_driver #(type REQ=uvm_sequence_item,
type RSP=REQ) extends uvm_component;
// Port: seq_item_port
// Derived driver classes should use this port to request items from the
// sequencer. They may also use it to send responses back.
uvm_seq_item_pull_port #(REQ, RSP) seq_item_port;
// Port: rsp_port
// This port provides an alternate way of sending responses back to the
// originating sequencer. Which port to use depends on which export the
// sequencer provides for connection.
uvm_analysis_port #(RSP) rsp_port;
REQ req;
RSP rsp;
// Rest of the code follows ...
endclass
uvm_sequencer的源代码:
// Definition of uvm_sequencer
class uvm_sequencer #(type REQ=uvm_sequence_item, RSP=REQ)
extends uvm_sequencer_param_base #(REQ, RSP);
// Variable: seq_item_export
// This export provides access to this sequencer's implementation of the
// sequencer interface.
uvm_seq_item_pull_imp #(REQ, RSP, this_type) seq_item_export;
// Rest of the class contents follow ...
endclass
构建环境组件时,如果派生uvm_driver和uvm_sequencer的类,则可以使用这些成员变量。
Driver中的seq_item_port和Sequencer的seq_item_export的连接方式(和普通的TLM端口类似):
class my_agent extends uvm_agent;
`uvm_component_utils (my_agent)
my_driver #(my_sequence_item) m_drv;
uvm_sequencer #(my_sequence_item) m_seqr;
virtual function void connect_phase (uvm_phase phase);
// Always the port is connected to an export
m_drv.seq_item_port.connect(m_seqr.seq_item_export);
endfunction
endclass
当然如果不想使用自带的成员变量,想加入改动,也可以由uvm_component来派生Driver等组件,然后自行定义uvm_seq_item_pull_port #(REQ, RSP)等类型的变量,名字可以不再是seq_item_port等,此外与Sequencer中的export的连接方式和上面相同。
-
Driver和Sequencer之间的通信方式属于TLM通信,传输的transaction应该是uvm_sequence_item或者其子类。UVM定义了专门的TLM端口供Driver和Sequencer使用:
uvm_seq_item_pull_port #(type REQ=uvm_sequence_item, type RSP=REQ)
uvm_seq_item_pull_export #(type REQ=uvm_sequence_item, type RSP=REQ)
uvm_seq_item_pull_imp #(type REQ=uvm_sequence_item, type RSP=REQ, type imp=)
-
由上面的定义可知这些端口默认传输的数据类型是uvm_sequence_item类型,如果在定义端口的时候没有声明用户所需的transaction类型,那么会有一个潜在的类型转换,会将transaction转换为uvm_sequence_item类型,这种情况下Driver从Sequencer中的FIFO中get到的req也是uvm_sequence_item,需要进行动态类型转换,转换成用户所需的transaction类型,才能获得里面的成员数据。但是如果在Driver派生自uvm_driver的定义和Sequencer派生自uvm_sequencer的定义时就指明了用户定义的transaction类型(Sequence中也是如此),那么就不需要二次转换
uvm_sequencer #(type REQ=uvm_sequence_item,RSP=REQ)
uvm_driver #(type REQ=uvm_sequence_item, RSP=REQ
-
Driver和Sequencer之间的连接和对应关系就体现在两个TLM端口的connect上。多个Driver不能和一个Sequencer连接,多个Sequencer也不能和一个Driver连接,也就是说Driver和Sequencer是一对一的关系。实际上这句话的准确意思是一个seq_item_port只会connect一个seq_item_export,我们可以在一个Driver中(当然不能是派生自uvm_driver的Driver)定义多个uvm_seq_item_pull_port,用来连接多个Sequencer,一个uvm_seq_item_pull_port与一个Sequencer的uvm_seq_item_pull_imp连接。
uvm_seq_item_pull_* 类型的TLM端口含有许多特殊的可调用方法,Driver可以使用这些方法来从Sequencer的FIFO中得到transaction,告知transaction使用完毕,也可以将处理完的transaction返回给Sequence。具体见下一章。
参考文献:https://www.chipverify.com/uvm/uvm-driver-sequencer-handshake
https://blog.csdn.net/qq_41394155/article/details/82112540