寄存器模型的常規(guī)方法
mirrored、 desired 和 actual value
在應(yīng)用寄存器模型時(shí), 除了利用它的寄存器信息, 還可以利用它來(lái)跟蹤寄存器的值。
跟蹤寄存器的值, 一方面是建立 mirrored value, 另一方面是為建立 desired value。
寄存器模型中的每一個(gè)寄存器都應(yīng)該有兩個(gè)值,一個(gè)是鏡像值(mirrored value),一個(gè)是期望值 (desired value) 。期望值是先利用寄存器模型修改軟件對(duì)象值, 而后利用該值更新硬件值;鏡像值是表示當(dāng)前硬件的已知狀態(tài)值。鏡像值往往由模型預(yù)測(cè)給出,關(guān)于預(yù)測(cè),在前門(mén)訪問(wèn)時(shí)通過(guò)觀察總線或在后門(mén)訪問(wèn)時(shí)通過(guò)自動(dòng)預(yù)測(cè)等方式來(lái)給出鏡像值。
然而,鏡像值有可能與硬件實(shí)際值 (hardware actual value)不一致,例如狀態(tài)寄存器的鏡像值就無(wú)法與硬件實(shí)際值保持同步更新。另外, 如果其他訪問(wèn)寄存器的通路修改了寄存器, 那么可能由于那一路總線沒(méi)有被監(jiān)測(cè), 導(dǎo)致寄存器的鏡像值未得到及時(shí)更新。
UVM 提供了兩種用來(lái)跟蹤寄存器值的方式, 我們將其分為自動(dòng)預(yù)測(cè) (auto prediction)和顯式預(yù)測(cè) (explicit)。如果讀者想使用自動(dòng)預(yù)測(cè)的方式,還需要調(diào)用函數(shù) uvm_reg_map: :set_auto_predict () 。兩種預(yù)測(cè)方式的顯著差別在于, 顯式預(yù)測(cè)對(duì)寄存器數(shù)值預(yù)測(cè)更為準(zhǔn)確, 我們可以通過(guò)下面對(duì)兩種模式的分析得出具體原因。
自動(dòng)預(yù)測(cè) (auto prediction) :如果讀者沒(méi)有在環(huán)境中集成獨(dú)立的 predictor, 而是利用寄存器的操作來(lái)自動(dòng)記錄每一次寄存器的讀寫(xiě)數(shù)值, 并在后臺(tái)自動(dòng)調(diào)用 predict()方法的話, 則這種方式稱為自動(dòng)預(yù)測(cè)。這種方式簡(jiǎn)單有效, 然而需要注意, 如果出現(xiàn)其他一些sequence 直接在總線層面上,對(duì)寄存器進(jìn)行操作(跳過(guò)寄存器級(jí)別的 write()/read()操作), 或通過(guò)其他總線來(lái)訪問(wèn)寄存器等這些額外的情況, 都無(wú)法自動(dòng)得到寄存器的鏡像值和預(yù)期值。
顯式預(yù)測(cè) (explicit prediction):更為可靠的一種方式是在物理總線上通過(guò)監(jiān)視器來(lái)捕捉總線事務(wù), 并將捕捉到的事務(wù)傳遞給外部例化的 predictor (預(yù)測(cè)器),該 predictor 由 UVM 參數(shù)化類(lèi) uvm_reg_predictor 例化并集成在頂層環(huán)境中。 如下圖, 在集成的過(guò)程中需要將 adapter 與 map 的句柄也一并傳遞給 predictor, 同時(shí)將 monitor 采集的事務(wù)通過(guò) analysis port 接入到 predictor一側(cè)。這種集成關(guān)系可以使得 monitor一旦捕捉到有效事務(wù), 會(huì)發(fā)送給 predictor, 再由其利用adapter 的橋接方法, 實(shí)現(xiàn)事務(wù)信息轉(zhuǎn)換, 并將轉(zhuǎn)化后的寄存器模型有關(guān)信息更新到 map 中。默認(rèn)情況下,系統(tǒng)將采用顯式預(yù)測(cè)的方式, 這就要求集成到環(huán)境中的總線 UVC monitor 需要具備捕捉事務(wù) 的功能和對(duì)應(yīng)的 analysis port, 以便于同 predictor 連接。
關(guān)于 predictor 在頂層環(huán)境中的集成, 讀者可以通過(guò)下面的一段例碼片段來(lái)掌握集成時(shí)的幾個(gè)要素:
class mcdf_bus_env extends uvm_env; mcdf_bus_agent agent; mcdf_rgm rgm; reg2mcdf_adapter reg2mcdf; uvm_reg_predictor #(mcdf_bus_trans) mcdf2reg_predictor; `uvm_component_utils(mcdf_bus_env) ... function void build_phase(uvm_phase phase); agent=mcdf_bus_agent::create("agent", this); if(!uvm_config_db#(mcdf_rgm)::get(this, "", "rgm", rgm)) begin `uvm_info("GETRGM", "no top-down RGM handle is assigned", UVM_LOW) rgm = mcdf_rgm::create("rgm", this); `uvm_info("NEWRGM", "created rgm instance locally", UVM_LOW) end rgm. build() ; reg2mcdf = reg2mcdf_adapter::create("reg2mcdf"); mcdf2reg_predictor = uvm_reg_predictor#(mcdf_bus_trans)::type_ id: : create ("mcdf2reg_predcitor", this); mcdf2reg_predictor.map = rgm.map; mcdf2reg_predictor.adapter = reg2mcdf; endfunction function void connect_phase(uvm_phase phase); rgm.map.set_sequencer(agent.sequencer, reg2mcdf); agent.monitor.ap.connect(mcdf2reg_predictor.bus_in); endfunction endclass
uvm_reg的訪問(wèn)方法
在給出寄存器模型的常見(jiàn)應(yīng)用模式之前,首先從下表中更全面地了解uvm_reg_ block、 uvm_reg 和uvm_reg_ field 三個(gè)類(lèi)提供的用于訪問(wèn)寄存器的方法。
uvm_reg_ sequence 提供的方法(均是針對(duì)寄存器對(duì)象的, 而不是寄存器塊或寄存器域)如下表。
結(jié)合mirrored value、 desired value 和 actual value, 我們需要理解這4種方法在調(diào)用時(shí), 三種數(shù)值的變化時(shí)序關(guān)系:
? 對(duì)于前門(mén)訪問(wèn)的 read()和 write(),在總線事務(wù)完成時(shí), 鏡像值和期望值才會(huì)更新為與總線上相同的值,這種預(yù)測(cè)方式是顯式預(yù)測(cè)。
? 對(duì)于 peek()和 poke(), 以及后門(mén)訪問(wèn)模式下的 read()和 write(),由于不通過(guò)總線,默認(rèn)采取自動(dòng)預(yù)測(cè)的方式,因此在方法調(diào)用返回后,鏡像值和期望值也相應(yīng)修改。
關(guān)于 reset()和 get_reset()的用法, 下面也給出部分例碼。例如硬件在復(fù)位觸發(fā)時(shí), 會(huì)將內(nèi)部寄存器值復(fù)位, 而寄存器模型在捕捉到復(fù)位事件時(shí), 為了保持同硬件行為一致, 也應(yīng)當(dāng)對(duì)其復(fù)位。這里注意的是, 復(fù)位的對(duì)象是寄存器模型, 而不是硬件。
@(negedge p_sequencer.vif.rstn);
rgm. reset(); / / register block reset for mirrored value and desired value
rgm.chnl0_ctrl_reg.reset(); // register level reset
rgm.chnl0_ctrl_reg.pkt_len.reset(); // register field reset
在復(fù)位之后, 用戶也可以通過(guò)讀取寄存器模型的復(fù)位值(與寄存器描述文件一致), 與前門(mén)訪問(wèn)獲取的寄存器復(fù)位值進(jìn)行比較, 以此判斷硬件各個(gè)寄存器的復(fù)位值是否按照寄存器描述去實(shí)現(xiàn)。這里的 get_reset()方法指的也是寄存器模型的復(fù)位值, 而不是硬件。
// register model reset value get and check
rstval = rgm.chnl0_ctrl_reg. get_reset() ;
rgm.chnl0_ctrl_reg.read (status, data, UVM_BACKDOOR, .parent(this));
if(rstval != data)
`uvm_error ("RSTERR", "reset value read is not the desired reset value")
mirror()方法與 read()方法類(lèi)似, 也可以選擇前門(mén)訪問(wèn)或后門(mén)訪問(wèn), 不同的是, mirror()不會(huì)返回讀回的數(shù)值, 但是會(huì)將對(duì)應(yīng)的鏡像值修改。在修改鏡像值之前, 用戶還可以選擇是否將讀回的值與模型中的原鏡像值進(jìn)行比較。下面的例碼在更新鏡像值之前, 首先將讀回的值與上一次鏡像值做了比對(duì), 隨后再更新鏡像值。比如, 對(duì)于配置寄存器, 可以采用這種方法來(lái)檢查上一次的配置是否生效, 又或者對(duì)于狀態(tài)寄存器可以選擇只更新鏡像值不做比較, 這是因?yàn)闋顟B(tài)寄存器隨時(shí)可能被硬件內(nèi)部邏輯修改。
// get register value and check
rgm.chnl0_ctrl_reg.mirror(status, UVM_CHECK, UVM_FRONTDOOR,parent(this));
下面的方法是運(yùn)用 set()和 update()對(duì)寄存器做批量修改。首先 set()方法的對(duì)象是寄存器模型自身,通過(guò)set()可以修改期望值, 而在寄存器配置時(shí)不妨先對(duì)其模型隨機(jī)化,再配置個(gè)別寄存器或域, 當(dāng)寄存器的期望值與鏡像值不相同時(shí),可以通過(guò)update()方法來(lái)將不相同的寄存器通過(guò)前門(mén)訪問(wèn)或后門(mén)訪問(wèn)的方式做全部修改。
這種 set()和 update()的方式較 write()和 poke()的寫(xiě)寄存器方式更為靈活的是,它可以實(shí)現(xiàn)隨機(jī)化寄存器配置值(先隨機(jī)化寄存器模型,后將隨機(jī)值結(jié)合某些域的指定值寫(xiě)入到寄存器),繼而模擬更多不可預(yù)知的寄存器應(yīng)用場(chǎng)景。另外,update()強(qiáng)大的批量操作寄存器功能使得修改寄存器更為便捷。
// randomize register model, set register/field value and update to // hardware actual value void'(rgm. chnlO_ctrl_reg. randomize()); rgm.chnlO ctrl reg.pkt len.set('h3); rgm.chnlO ctrl reg. update (status, UVM FRONTDOOR, .parent (this)); void'(rgm.chnll_ctrl_reg.randomize()); rgm. chnl0_ctrl_reg. set ('h22); rgm.update(status, UVM FRONTDOOR, .parent(this));
mem與reg的聯(lián)系和差別
UVM寄存器模型也可以用來(lái)對(duì)存儲(chǔ)建模。uvm_mem 類(lèi)可以用來(lái)模擬RW (讀寫(xiě))、 RO(只讀)和WO(只寫(xiě))類(lèi)型的存儲(chǔ),并且可以配置存儲(chǔ)模型的數(shù)據(jù)寬度和地址范圍。uvm_mem不同于uvm_reg 的地方在于,考慮到物理存儲(chǔ)一旦映射到 uvm_mem 會(huì)帶來(lái)更大的資源消耗,因此 uvm_mem 并不支待預(yù)測(cè)和影子存儲(chǔ)(shadow storage) 功能, 即沒(méi)有鏡像值和期望值。
uvm_mem 可以提供的功能就是利用自帶的方法去訪問(wèn)硬件存儲(chǔ), 相比于直接利用硬件總線 UVC進(jìn)行訪問(wèn),這么做的好處在于:
? 類(lèi)似于寄存器模型訪問(wèn)寄存器,利用存儲(chǔ)模型訪問(wèn)硬件存儲(chǔ)便于維護(hù)和復(fù)用。
? 在訪問(wèn)過(guò)程中,可以利用模型的地址范圍來(lái)測(cè)試硬件的地址范圍是否全部覆蓋。
? 由于 uvm_mem 也同時(shí)提供前門(mén)訪問(wèn)和后門(mén)訪問(wèn),這使得存儲(chǔ)測(cè)試可以考慮先通過(guò)后門(mén)訪問(wèn)預(yù)先加載存儲(chǔ)內(nèi)容,而后通過(guò)前門(mén)訪問(wèn)讀取存儲(chǔ)內(nèi)容,繼而做數(shù)據(jù)比對(duì),這樣做不但節(jié)省時(shí)間,同時(shí)也在測(cè)試方式上保持了一致性。同時(shí)這種方式相比于傳統(tǒng)前后測(cè)試方式(利用系統(tǒng)函數(shù)或仿真器函數(shù)實(shí)現(xiàn)存儲(chǔ)加載),要在UVM測(cè)試框架中更為統(tǒng)一。
與 uvm_reg 相比, uvm_mem不但擁有常規(guī)的訪問(wèn)方法read() 、 write()、peek()和 poke(),也提供了 burst_read()和 burst_write() 。之所以額外提供這兩種方法, 不但是為了可以更高速地通過(guò)物理總線的BURST方式連續(xù)存儲(chǔ),也是為了盡可能貼合實(shí)際訪問(wèn)存儲(chǔ)中的場(chǎng)景。要實(shí)現(xiàn)BURST訪問(wèn)形式, 需要考慮下面這些因素:
? 目前掛載的總線UVC是否支持BURST形式訪問(wèn),例如APB不能支持BURST訪問(wèn)模式。
? 與 read()、 write()方法相比,burst_read()和 burst_write()的參數(shù)列表中的一項(xiàng)uvm_reg_ data _t value[]采用的是數(shù)組形式, 不再是單一變量, 即表示用戶可以傳遞多個(gè)數(shù)據(jù)。而在后臺(tái),這些數(shù)據(jù)首先需要裝載到 uvm_reg_item 對(duì)象中,裝載時(shí) value 數(shù)組可以直接寫(xiě)入, 另外兩個(gè)成員需要分別指定為 element_kind = UVM_MEM , kind = UVM_BURST_READ。
? 在 adapter 實(shí)現(xiàn)中, 也需要考慮到存儲(chǔ)模型 BURST 訪問(wèn)的情形, 實(shí)現(xiàn)4 種訪問(wèn)類(lèi)型(uvm _access_ e) 的轉(zhuǎn)換,即UVM_READ、UVM_WRITE、UVM_BURS_READ 和UVM_BURST_ WRITE。對(duì)于 UVM_READ 和 UVM_WRITE 的橋接, 已經(jīng)在寄存器模型訪問(wèn)中實(shí)現(xiàn), 而 UVM_BURST_READ 和 UVM_BURST_WRITE的轉(zhuǎn)換,往往需要考慮寫(xiě)入的數(shù)據(jù)長(zhǎng)度,例如長(zhǎng)度是否是 4、 8、 16 或其他。比如 AHB 總線, 支持連續(xù) 4 個(gè)、8 個(gè)、 16 個(gè)數(shù)據(jù)的讀寫(xiě) (INCR4 、 INCR8、 INCR16), 但是如果數(shù)據(jù)長(zhǎng)度不是這些固定長(zhǎng)度時(shí), adapter 還需要自己處理來(lái)實(shí)現(xiàn) INCR 的連續(xù)訪問(wèn)方式。
? 此外還需要考慮不同總線的其他控制參數(shù), 例如 AHB 支持 WRAP 模式, AXI 支持out-of-order 模式等, 如果想要將更多的總線控制封裝在 adapter 的橋接功能里, 需要將更多的配置作為擴(kuò)展配置, 在調(diào)用訪問(wèn)方法時(shí)作為擴(kuò)展信息類(lèi),傳入到形式參數(shù)uvm_object_extension。待傳入后, adapter 將可以在橋接方法中抽取出擴(kuò)展信息類(lèi),作為更準(zhǔn)確的協(xié)議訪問(wèn)的限定依據(jù)。
? 對(duì)于更為復(fù)雜的 BURST 形式, 如果需要實(shí)現(xiàn)更多的協(xié)議配置要求, 那么筆者推薦直接在總線 UVC 層面去驅(qū)動(dòng)。這樣做的靈活性更大, 且更能充分全面的測(cè)試存儲(chǔ)接口的協(xié)議層完備性。因此, 驗(yàn)證師在為存儲(chǔ)模型訪問(wèn)實(shí)現(xiàn) adapter 方法時(shí), 需要考慮的是, uvm_mem 層面的方法應(yīng)該盡員便捷、必要的參數(shù)應(yīng)該少量, 以便于使用和維護(hù);而另一方面, 如果要首先測(cè)試存儲(chǔ)接口協(xié)議, 則應(yīng)該在總線 UVC 的層面上完成更充分的驗(yàn)證。
內(nèi)建sequences
不少有經(jīng)驗(yàn)的 UVM 用戶可能會(huì)忽略 UVM 針對(duì)寄存器模型內(nèi)建的(built-in) 一些sequence, 實(shí)際上, 將這些自建的序列作為驗(yàn)證項(xiàng)目開(kāi)始前的健康檢查必選項(xiàng), 對(duì)整個(gè)項(xiàng)目的平穩(wěn)運(yùn)行會(huì)有不小的貢獻(xiàn)。
這是因?yàn)椋陧?xiàng)目的開(kāi)始階段,設(shè)計(jì)內(nèi)部的邏輯尚不穩(wěn)定,驗(yàn)證師要跟上設(shè)計(jì)的進(jìn)度,可以展開(kāi)驗(yàn)證的部分無(wú)外乎是系統(tǒng)控制信號(hào)(時(shí)鐘、復(fù)位、 電源)和寄存器的驗(yàn)證。在項(xiàng)目早期,寄存器模型的驗(yàn)證可以為后期各個(gè)功能點(diǎn)驗(yàn)證打下良好的基礎(chǔ)。比如,通過(guò)內(nèi)建的寄存器序列可以實(shí)現(xiàn)完善的寄存器復(fù)位值檢查,又比如檢查讀寫(xiě)寄存器的讀寫(xiě)功能是否正常等。
不過(guò)有一些寄存器即便可以測(cè)試, 也建議將其作為例外而過(guò)濾出去, 例如一些重要的系統(tǒng)控制信號(hào)(時(shí)鐘、復(fù)位、電源), 當(dāng)寫(xiě)入某些值以后, 會(huì)使得系統(tǒng)全部或局部復(fù)位、時(shí)鐘也可能被關(guān)閉 , 這就可能阻礙寄存器的下一步檢查。所以 UVM 提供了一些特殊域, 用來(lái)禁止sequence 檢查這些寄存器或存儲(chǔ)。接下來(lái),我們從下表來(lái)分別瀏覽整理出的寄存器和存儲(chǔ)相關(guān)的自建sequence 。
寄存器模型內(nèi)建序列
存儲(chǔ)器模型內(nèi)建序列
接下來(lái)我們給出一段例碼,來(lái)演示如何利用內(nèi)建序列完成MCDF寄存器測(cè)試一開(kāi)始的健康檢查。下面的例碼分別添加了 uvm_reg_ hw _reset_ seq、 uvm_reg_ bit_ bash_ seq和 uvm _reg_ access_ seq 來(lái)測(cè)試寄存器模型, 從代碼的整潔性來(lái)看, 用戶并不需要額外再添加什么, 這種使用方式非常方便, 且又能完成寄存器的大規(guī)模集成測(cè)試。
mcdf_rgm rgm; `uvm_object_utils(mcdf_example_seq) `uvm_declare_p_sequencer(mcdf_bus_sequencer) ... task body(); uvm_status_e status; uvm_reg_data_t data; uvm_reg_hw_reset_seq reg_rst_seq = new(); uvm_reg_bit_bash_seq reg_bit_bash_seq = new(); uvm_reg_access_seq reg_acc_seq = new(); if (! uvm_config_db# (mcdf_rgm)::get (null, get_full_name (), "rgm", rgm)) begin `uvm_error("GETRGM", "no top-down RGM handle is assigned") end // wait reset asserted and release @(negedge p_sequencer.vif.rstn); @(posedge p_sequencer.vif.rstn); `uvm_info ("BLTINSEQ", "register reset sequence started", UVM LOW) reg_rst_seq.model = rgm; reg_rst_seq.start(m_sequencer); `uvm_info ("BLTINSEQ", "register reset sequence finished", UVM_LOW) `uvm_info("BLTINSEQ", "register bit bash sequence started", UVM_LOW) //reset hardware register and register model reg_bit_bash_seq.model = rgm; reg_bit_bash_seq.start(m_sequencer); `uvm_info("BLTINSEQ", "register bit bash sequence finished", UVM_LOW) `uvm_info("BLTINSEQ", "register access sequence started", UVM_LOW) //reset hardware register and register model reg_acc_seq.model = rgm; `uvm info ("BLTINSEQ", "register access sequence finished", UVM LOW ) endtask endclass如果想將一些寄存器排除在某些內(nèi)建序列測(cè)試范圍之外, 可以額外添加上面列表中提到的“禁止域名 ”。由于 uvm_reg_block 和 uvm_reg 均是 uvm_object 類(lèi)而不是 uvm_ component 類(lèi),所以可以使用 uvm_resource_ db 來(lái)配置 “ 禁止域名 “。下面的代碼摘自 mcdf_rgm::build()方法, 這相當(dāng)于寄存器模型在自己的建立階段設(shè)定了一些屬性。當(dāng)然, uvm_resource_ db 的配置也可以在更高層指定, 只不過(guò)考慮到 uvm_resource_ db 不具備層次化的覆蓋屬性, 我們建議只在 一個(gè)地方進(jìn)行 “ 禁止域名 ” 的配置。
class mcdf_rgm extends uvm_reg_block; ... virtual function build(); // disable built-in seq attributes uvm_resource_db#(bit)::set ({"REG::", this. chnlO stat reg. get full name () } , NO REG ACCESS TEST", 1); uvm_resource_db# (bit)::set ({ "REG: : ", this. chnll stat reg.get full name () } , "NO REG ACCESS TEST", 1); uvm_resource_db#(bit):: set ({"REG: : ", this. chnl2 stat reg. get full name () } , "NO REG ACCESS TEST", l); endfunction endclass
審核編輯:劉清
-
寄存器
+關(guān)注
關(guān)注
31文章
5336瀏覽量
120229 -
UVM
+關(guān)注
關(guān)注
0文章
182瀏覽量
19167 -
uvc
+關(guān)注
關(guān)注
1文章
127瀏覽量
14527
原文標(biāo)題:IC學(xué)霸筆記 | UVM寄存器模型的常規(guī)方法
文章出處:【微信號(hào):IC修真院,微信公眾號(hào):IC修真院】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論