基于企业网站的网络营销方法南宁优化推广服务
文章目录
- 一、什么是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
-  
通过使用适配器,验证环境中的不同组件可以相互独立开发和修改,减少了对其他组件的依赖。
 -  
提高可重用性:适配器可以在不同的项目或测试环境中复用,从而节省开发时间和资源。
 -  
简化复杂性:在复杂的验证环境中,适配器有助于简化不同协议之间的交互,使得设计和验证人员可以专注于各自的任务,而不必担心接口细节。
 -  
没有适配器,组件无法轻松适应不同的协议或接口,降低了验证环境的灵活性和可重用性。
 
