wordpress 后台忘了杭州网站排名seo
文章目录
- 一、什么是uvm_reg_adapter
- 1、what
- 2、Example
- 2.1、代码详解
- 二、如何使用uvm_reg_adapter
- 三、为什么要引入uvm_reg_adapter
一、什么是uvm_reg_adapter
1、what
uvm_reg_adapter
继承于uvm_object
,定义了用于在uvm_reg_bus_op
和特定总线事务之间进行转换的接口,使得寄存器模型和总线之间能够有效地进行通信。uvm_reg_bus_op
:定义用于寄存器和内存访问的通用总线事务的结构,具有类型(读或写)、地址、数据和字节启用信息。
类型 成员
uvm_access_e kind UVM_READ or UVM_WRITE.
uvm_reg_addr_t addr 地址;默认64位
uvm_reg_data_t data 数据:默认64位
int n_bits 传输的bit位
uvm_reg_byte_en_t byte_en 使能byte操作
uvm_status_e status 传输的结果:UVM_IS_OK, UVM_HAS_X, UVM_NOT_OK.
2、Example
class rkv_ahbmtx_reg_adapter extends uvm_reg_adapter;`uvm_object_utils(rkv_ahbmtx_reg_adapter)
function new(string name = "rkv_ahbmtx_reg_adapter");super.new(name);provides_responses = 1; // 如果总线要返回response数据,则应当使能provides_responses
endfunctionfunction uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw); //函数原型需要一字不改svt_ahb_transaction t;t.xact_type = (rw.kind == UVM_WRITE) ? svt_ahb_master_transaction::WRITE :svt_ahb_master_transaction::READ;t.addr = rw.addr;t.burst_type = svt_ahb_master_transaction::SINGLE;t.burst_size = svt_ahb_master_transaction::BURST_SIZE_32BIT;t.data = new[1]; //svt_ahb_transaction 中的data是数组,这里是single传输,所以设置size为1t.data[0] = rw.data;return t; //隐形转换
endfunctionfunction void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw); //函数原型需要一字不改svt_ahb_transaction t;if (!$cast(t, bus_item)) begin`uvm_fatal("CASTFAIL", "Provided bus_item is not of the correct type")return;endrw.kind = (t.xact_type == svt_ahb_master_transaction::WRITE) ? UVM_WRITE : UVM_READ;rw.addr = t.addr;rw.data = t.data[0];rw.status = UVM_IS_OK;
endfunction
endclass
2.1、代码详解
-
provides_responses
:如果总线要返回response
数据,则应当使能provides_responses
;若总线不支持返回response
数据(没有调用put_response(RSP)
或者item_done(RSP)
),则不应设置,负责会使得环境挂起 -
supports_byte_enable
:总线支持byte
访问,则使能 -
reg2bus
:- 函数原型:
pure virtual function uvm_sequence_item reg2bus( const ref uvm_reg_bus_op rw)
pure virtual
:纯虚方法,即没有实体的方法原型,它只可以在抽象类中定义(uvm_reg_adapter
是抽象类(virtual class uvm_reg_adapter extends uvm_object )
)- 函数声明的返回类型是
uvm_sequence_item
:uvm_sequence_item
是父类类型,但是最后return t
返回的是子类句柄(svt_ahb_transaction
实例的句柄),这里存在一个隐形转换:子类句柄转换为父类句柄并返回;也就是说最后返回的是父类句柄指向的父类类型;( 在svt_ahb_master_driver
中其参数的数据类型是svt_ahb_master_transaction
;svt_sequencer
和svt_driver
的参数都是uvm_sequence_item
,所以将其返回为uvm_sequence_item
) const ref
:const
关键字用于声明一个变量为常量,意味着该变量的值在初始化后不能被修改。const ref
表示一个常量引用,指向一个对象,但不允许通过这个引用修改该对象reg2bus()
完成的桥接场景是,如果用户在寄存器级别做了操作,那么寄存器级别操作的信息uvm_reg_bus_op
会被记录,同时调用uvm_reg_adapter::reg2bus()
函数。在完成了将uvm_reg_bus_op
的信息映射到bus_trans
之后,函数将bus_trans实例返回。而在返回bus_trans
之后,该实例将通过bus_seqeuncer
传入到bus_driver
。这里的transaction
传输是后台隐式调用的,不需要主动发起。
- 函数原型:
-
bus2reg
- 函数原型:
pure virtual function void bus2reg(uvm_sequence_item bus_item,ref uvm_reg_bus_op rw)
- 父类句柄
bus_item
指向了子类对象(实际传输的类型就是子类类型),所以要把父类句柄bus_item
指向的子类对象转换为uvm_reg_bus_op
类型;父类句柄是无法访问子类对象,需要先把父类句柄转换为子类句柄
- 函数原型:
vt_ahb_transaction t;
if (!$cast(t, bus_item)) begin`uvm_fatal("CASTFAIL", "Provided bus_item is not of the correct type")return;end
-
bus2reg
函数的功能与reg2bus
相反,完成了从bus_trans
到uvm_reg_bus_op
的内容映射。在完成映射之后,更新的uvm_reg_bus_op
数据最终返回至寄存器操作场景层。 -
对于寄存器操作,无论读操作还是写操作,都需要经历调用
reg2bus
,继而发起总线事务,而完成总线事务发回反馈之后,又需要调用bus2reg
,将总线的数据返回至寄存器操作层面。
二、如何使用uvm_reg_adapter
- 集成在
env
中 - 例化后,需要在
connect_phase
中做必要的连接
rgm.map.set_sequencer(agt.sequencer, adapter);
predictor.adapter = adapter;
三、为什么要引入uvm_reg_adapter
-
通过使用适配器,验证环境中的不同组件可以相互独立开发和修改,减少了对其他组件的依赖。
-
提高可重用性:适配器可以在不同的项目或测试环境中复用,从而节省开发时间和资源。
-
简化复杂性:在复杂的验证环境中,适配器有助于简化不同协议之间的交互,使得设计和验证人员可以专注于各自的任务,而不必担心接口细节。
-
没有适配器,组件无法轻松适应不同的协议或接口,降低了验证环境的灵活性和可重用性。