UVM寄存器模型:reg adapter实现和集成
目錄
1. 概要
2.?reg/bus adapter的實(shí)現(xiàn)
3. reg/bus adapter的集成
?4.?bus2reg()和reg2bus() 是如何被調(diào)用?
4.1 bus2reg()在哪里調(diào)用?
4.2?reg2bus()在哪里調(diào)用?
4.3 小結(jié)
1. 概要
? ? ? ? UVM寄存器模型有內(nèi)建的抽象的read()和write()等寄存器訪問命令,實(shí)際的寄存器訪問需要通過對用于寄存器訪問的總線接口進(jìn)行驅(qū)動(dòng)來完成。典型的總線接口有AMAB總線家族、I2C總線、SPI總線等都可以用作寄存器訪問的總線接口。
? ? ? ? 在UVM驗(yàn)證平臺中,要完成寄存器訪問,需要進(jìn)行寄存器模型的抽象的read/write訪問動(dòng)作與具體種類總線的bus transaction之間的轉(zhuǎn)換,這就是adapter(between reg and bus)所要扮演的角色。adapter的實(shí)現(xiàn),更具體一點(diǎn)說是reg2bus和bus2reg兩個(gè)任務(wù)的實(shí)現(xiàn)隨實(shí)際使用的總線協(xié)議不同而不同。UVM有一個(gè)專門的類uvm_reg_adapter用作reg/bus adapter實(shí)現(xiàn)模板,用戶實(shí)現(xiàn)的reg/bus adapter class必須繼承于uvm_reg_adapter。
2.?reg/bus adapter的實(shí)現(xiàn)
????????reg/bus adapter的實(shí)現(xiàn)包含以下兩個(gè)要點(diǎn):
- uvm_reg_bus_op與總線transaction中各自的數(shù)據(jù)映射。
- 實(shí)現(xiàn)reg2bus()和bus2reg()兩個(gè)函數(shù),這兩個(gè)函數(shù)即實(shí)現(xiàn)了兩種transaction的數(shù)據(jù)映射,函數(shù)名則表明了它們的轉(zhuǎn)換方向。這兩個(gè)函數(shù)原型是預(yù)定義的,驗(yàn)證開發(fā)者必須去實(shí)現(xiàn)其具體處理。
????????reg2bus()和bus2reg()兩個(gè)函數(shù)是uvm_reg_adapter class中定義的純虛函數(shù)(pure virtual function) ,如下所示(uvm_reg_adapter.svh):
virtual class uvm_reg_adapter extends uvm_object; ... // Function: reg2bus//// Extensions of this class ~must~ implement this method to convert the specified// <uvm_reg_bus_op> to a corresponding <uvm_sequence_item> subtype that defines the bus// transaction.//// The method must allocate a new bus-specific <uvm_sequence_item>,// assign its members from// the corresponding members from the given generic ~rw~ bus operation, then// return it.pure virtual function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);// Function: bus2reg//// Extensions of this class ~must~ implement this method to copy members// of the given bus-specific ~bus_item~ to corresponding members of the provided// ~bus_rw~ instance. Unlike <reg2bus>, the resulting transaction// is not allocated from scratch. This is to accommodate applications// where the bus response must be returned in the original request.pure virtual function void bus2reg(uvm_sequence_item bus_item,ref uvm_reg_bus_op rw); ...? ? ? ? 此外,如果總線支持byte訪問,可以使能supports_byte_enable;如果總線UVC要返回response數(shù)據(jù),則應(yīng)當(dāng)使能provides_response。參考以下UVM代碼(uvm_reg_adapter.svh):
virtual class uvm_reg_adapter extends uvm_object;// Function: new//// Create a new instance of this type, giving it the optional ~name~.function new(string name="");super.new(name);endfunction// Variable: supports_byte_enable//// Set this bit in extensions of this class if the bus protocol supports// byte enables.bit supports_byte_enable;// Variable: provides_responses//// Set this bit in extensions of this class if the bus driver provides// separate response items.bit provides_responses; ...? ? ? ? 以下為一個(gè)基于APB總線的寄存器訪問接口的adapter類的實(shí)現(xiàn)例。
class apb_reg_adapter extends uvm_reg_adapter;`uvm_object_utils(apb_reg_adapter)function new(string name = "apb_reg_adapter");super.new(name);provides_responses = 1;endfunctionfunction uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);apb_transfer t = apb_transfer::type_id::create("t");t.trans_kind = (rw.kind == UVM_WRITE) ? WRITE : READ;t.addr = rw.addr;t.data = rw.data;t.idle_cycles = 1;return t;endfunctionfunction void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);apb_transfer t;if (!$cast(t, bus_item)) begin`uvm_fatal("CASTFAIL","Provided bus_item is not of the correct type")return;endrw.kind = (t.trans_kind == WRITE) ? UVM_WRITE : UVM_READ;rw.addr = t.addr;rw.data = t.data;rw.status = t.trans_status == OK ? UVM_IS_OK : UVM_NOT_OK;endfunction endclass????????其中,uvm_reg_bus_op為UVM預(yù)定義類,包含以下成員:
????????如以上例碼所示,一般來說,adapter的實(shí)現(xiàn)其實(shí)就是bus2reg和reg2bus兩個(gè)函數(shù)的實(shí)現(xiàn)而已。reg2bus()完成的橋接場景是,如果用戶在寄存器級別做了操作,那么寄存器級別操作的信息uvm_reg_bus_op會(huì)被記錄,同時(shí)調(diào)用uvm_reg_adapter::reg2bus()函數(shù)。在完成了將uvm_reg_bus_op的信息映射到bus_trans(即以上代碼例中的apb_transfer)之后,函數(shù)將bus_trans實(shí)例返回。而在返回bus_trans之后,該實(shí)例將通過bus_seqeuncer傳入到bus_driver。這里的transaction傳輸是后臺隱式調(diào)用的,不需要主動(dòng)發(fā)起。
????????bus2reg()函數(shù)的功能與reg2bus()相反,完成了從bus_trans到uvm_reg_bus_op的內(nèi)容映射。在完成映射之后,更新的uvm_reg_bus_op數(shù)據(jù)最終返回至寄存器操作場景層。
????????對于寄存器操作,無論讀操作還是寫操作,都需要經(jīng)歷調(diào)用reg2bus(),繼而發(fā)起總線事務(wù),而完成總線事務(wù)發(fā)回反饋之后,又需要調(diào)用bus2reg(),將總線的數(shù)據(jù)返回至寄存器操作層面。
3. reg/bus adapter的集成
?
?圖1 UVM寄存器環(huán)境系統(tǒng)模型(取自[2])
????????上圖為UVM寄存器環(huán)境系統(tǒng)模型示意圖,但是有一點(diǎn)容易被誤解的地方是,adapter其實(shí)是一個(gè)相對獨(dú)立的組件,regmodel和predictor分別通過不同的方式間接引用同一個(gè)adapter的對象,而不是像上圖一樣在regmodel和predictor中各有一個(gè)adapter。
? ? ? ? adapter通常是放在env中,然后predictor通過句柄的方式引用adapter的對象,regmodel則是通過map.set_sequencer()來建立與adapter對象的關(guān)聯(lián),如下圖所示:
????????以下為env中集成寄存器模型的代碼示例:
class i2c_env extends uvm_env;// top configuration and virtual interfacei2c_config cfg;virtual i2c_if vif;... // top register model and related componentsral_block_i2c rgm;apb_reg_adapter adapter;uvm_reg_predictor #(apb_transfer) predictor;`uvm_component_utils(i2c_env)function new (string name = "i2c_env", uvm_component parent);super.new(name, parent);endfunctionfunction void build_phase(uvm_phase phase);super.build_phase(phase);...if(!uvm_config_db #(ral_block_i2c)::get(this, "", "rgm", rgm)) begin`uvm_info("build_phase", "Unable to get ral_block_i2c from uvm_config_db and create a RGM locally", UVM_LOW)rgm = ral_block_i2c::type_id::create("rgm", this);rgm.build();rgm.lock_model();end...adapter = apb_reg_adapter::type_id::create("adapter", this);predictor = uvm_reg_predictor#(apb_transfer)::type_id::create("predictor", this);endfunction: build_phasefunction void connect_phase(uvm_phase phase);super.connect_phase(phase);...// register model integrationrgm.default_map.set_sequencer(apb_mst.sequencer, adapter);apb_mst.monitor.item_collected_port.connect(predictor.bus_in);predictor.map = rgm.default_map;predictor.adapter = adapter;endfunction: connect_phaseendclass?4.?bus2reg()和reg2bus() 是如何被調(diào)用?
????????UVM初學(xué)者很容易感到困惑的一個(gè)地方是,UVM驗(yàn)證平臺中很多函數(shù)只需要用戶實(shí)現(xiàn)它們,并不需要對其進(jìn)行調(diào)用,那實(shí)現(xiàn)它們干嗎呢?原因是UVM已經(jīng)偷偷地幫助你在需要的時(shí)候進(jìn)行了調(diào)用,所以用戶只管實(shí)現(xiàn)不管調(diào)用。回調(diào)函數(shù)都是屬于這一類。
? ? ? ? 具體一點(diǎn),bus2reg()和reg2bus()的調(diào)用是如何發(fā)生的呢?
????????如前所述,一旦發(fā)生了寄存器訪問操作,reg2bus()會(huì)被隱式地調(diào)用用以將抽象的寄存器操作(read(), write(),etc)轉(zhuǎn)換為bus transaction,然后該bus transaction將由對應(yīng)的sequencer轉(zhuǎn)發(fā)給bus driver,最后由bus driver生成接口波形驅(qū)動(dòng)到DUT接口上去,這一切都因?yàn)橐韵逻@條語句建立的關(guān)聯(lián)為基礎(chǔ),UVM自動(dòng)地在后臺為你把所有其它的事情都干了。
rgm.default_map.set_sequencer(apb_mst.sequencer, adapter);
? ? ? ? 同樣,發(fā)生寄存器訪問操作時(shí),bus monitor會(huì)將總線上觀測到的信號變化采樣并打包成bus transaction傳給predictor,然后preditor會(huì)調(diào)用adapter::bus2reg()將bus transaction再變回寄存器模型的抽象操作。為什么要這么做呢?這是因?yàn)閜redictor需要根據(jù)總線上監(jiān)測到的信號變化狀況來預(yù)測接下來DUT中的真實(shí)的寄存器值(actual value)將會(huì)發(fā)生什么變化,并將這個(gè)變化反饋給寄存器模型,寄存器模型則據(jù)此更新mirror value,使得mirror value保持與actual value同步。關(guān)于UVM寄存器模型的mirror value、actual value與desired value三者之間關(guān)系、區(qū)別以及同步等也是比較把初學(xué)者搞昏頭的,需要另文專門解釋。
4.1 bus2reg() 在哪里被調(diào)用?
????????查閱UVM庫的源代碼可以找到bus2reg在以下三個(gè)地方被調(diào)用(不知道還有沒有其它地方?待進(jìn)一步確認(rèn)):
????????bus2reg() called in uvm_reg_map:????????
task uvm_reg_map::do_bus_write (uvm_reg_item rw,uvm_sequencer_base sequencer,uvm_reg_adapter adapter);...if (adapter.provides_responses) beginuvm_sequence_item bus_rsp;uvm_access_e op;// TODO: need to test for right trans type, if not put back in qrw.parent.get_base_response(bus_rsp);adapter.bus2reg(bus_rsp,rw_access);endelse beginadapter.bus2reg(bus_req,rw_access);end...task uvm_reg_map::do_bus_read (uvm_reg_item rw,uvm_sequencer_base sequencer,uvm_reg_adapter adapter);...if (adapter.provides_responses) beginuvm_sequence_item bus_rsp;uvm_access_e op;// TODO: need to test for right trans type, if not put back in qrw.parent.get_base_response(bus_rsp);adapter.bus2reg(bus_rsp,rw_access);endelse beginadapter.bus2reg(bus_req,rw_access);end...????????bus2reg() called in predictor:
class uvm_reg_predictor #(type BUSTYPE=int) extends uvm_component;`uvm_component_param_utils(uvm_reg_predictor#(BUSTYPE))...// Variable: adapter//// The adapter used to convey the parameters of a bus operation in // terms of a canonical <uvm_reg_bus_op> datum.// The <uvm_reg_adapter> must be configured before the run phase.//uvm_reg_adapter adapter;...// Function- write//// not a user-level method. Do not call directly. See documentation// for the ~bus_in~ member.//virtual function void write(BUSTYPE tr);uvm_reg rg;uvm_reg_bus_op rw;if (adapter == null)`uvm_fatal("REG/WRITE/NULL","write: adapter handle is null") // In case they forget to set byte_enrw.byte_en = -1;adapter.bus2reg(tr,rw);rg = map.get_reg_by_offset(rw.addr, (rw.kind == UVM_READ));...? ? ? ? uvm_reg_predictor(UVM寄存器環(huán)境中的preditor為該class的直接實(shí)例)中有一個(gè)adapter類型的句柄(該句柄將在env中指向真正的adapter對象),而adapter.bus2reg()就在uvm_reg_predictor::write()中被調(diào)用。而如以上函數(shù)說明所示,uvm_reg_predictor::write()本身不是一個(gè)user-level方法,不能直接調(diào)用。這也印證了以上bus2reg()不需要用戶顯式調(diào)用的描述(甚至predictor中連調(diào)用bus2reg()的函數(shù)都不需要用戶直接調(diào)用。。。再往前會(huì)追溯到哪兒去呢?這里就暫時(shí)放一下,有空時(shí)再回頭來徹底刨根究底地追追看)
4.2?reg2bus()在哪里調(diào)用?
????????查閱UVM庫的源代碼可以找到reg2bus在以下地方被調(diào)用(不知道還有沒有其它地方?待進(jìn)一步確認(rèn)):
? ? ? ? reg2bus() called in uvm_reg_map:????????
task uvm_reg_map::do_bus_write (uvm_reg_item rw,uvm_sequencer_base sequencer,uvm_reg_adapter adapter);...// perform accessesforeach(accesses[i]) begin uvm_reg_bus_op rw_access=accesses[i]; uvm_sequence_item bus_req;adapter.m_set_item(rw);bus_req = adapter.reg2bus(rw_access);adapter.m_set_item(null);......task uvm_reg_map::do_bus_read (uvm_reg_item rw,uvm_sequencer_base sequencer,uvm_reg_adapter adapter);...// perform accessesforeach(accesses[i]) begin uvm_reg_bus_op rw_access=accesses[i]; uvm_sequence_item bus_req;uvm_reg_data_logic_t data; int unsigned curr_byte_; curr_byte_=rw_access.data;rw_access.data='0;adapter.m_set_item(rw);bus_req = adapter.reg2bus(rw_access);......4.3 小結(jié)
? ? ? ? 總之,如上所述,UVM在后臺偷偷地把很多的事情干了。
????????一方面,這也正是UVM的便捷和強(qiáng)大之處,所有這些UVM在后臺偷偷地干了的事情其實(shí)都是標(biāo)準(zhǔn)化的操作處理,不需要開發(fā)者再一一顯式地去處理,避免了無謂的重新發(fā)明輪子,使得驗(yàn)證開發(fā)者可以更加聚焦于高級事務(wù)。?
????????另一方面,這會(huì)使得初學(xué)者很不習(xí)慣,畢竟習(xí)慣了“所見即所得”,沒有看到的東西心里沒底啊,誰知道到底有沒有被執(zhí)行啊。從心里沒底到慢慢成竹在胸泰然自若,這是成長的必經(jīng)之路。
?主要參考文獻(xiàn):
【1】路科驗(yàn)證2022春季V2X課件
【2】UVM Register Environment (chipverify.com)
總結(jié)
以上是生活随笔為你收集整理的UVM寄存器模型:reg adapter实现和集成的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华为教父任正非的别样视野(转)
- 下一篇: maxmemory-policy