1. 程式人生 > >UVM暫存器篇之八:暫存器模型的場景應用(終)

UVM暫存器篇之八:暫存器模型的場景應用(終)

本文轉自:http://www.eetop.cn/blog/html/28/1561828-6266225.html

如何檢查暫存器模型

在瞭解了暫存器模型的常規方法之後,我們需要考慮如何利用這些方法來檢查暫存器、以及協助檢查硬體設計的邏輯和資料比對。要知道,在軟體實現硬體驅動和韌體層時,也會實現類似暫存器模型映象值的方法,即在暫存器配置的底層函式中,同時也宣告一些全域性的影子暫存器(shadow register)。這些影子暫存器的功能就是暫存當時寫入暫存器的值,而在後期使用時,如果這些暫存器是非易失的(non-volatile),那麼便可以省略讀取暫存器的步驟,轉而使用影子暫存器的值,這麼做的好處在於響應更迅速,而不再通過若干個時鐘週期的匯流排發起和響應,但另外一方面這麼做的前提同我們測試暫存器模型的目的是一樣的,即暫存器的寫入值可以準確地反映在硬體中的暫存器上。

 

利用暫存器模型的另外一個場景時,在對資料通路的硬體做資料比對時,需要及時地知道當時的硬體配置狀況,而利用暫存器模型的映象值可以實現實時地讀取,而不需要從前門訪問。也許讀者會有別的選擇,為什麼不從後門訪問呢?毫無疑問,後門訪問也可以在零時刻內完成,只是這麼做會省略檢查暫存器的步驟,即假設暫存器模型的映象值同硬體中的暫存器真實值保持一致。只有這麼做,也才能為後期軟體開發時使用影子暫存器掃清可能的硬體缺陷。

 

因此,暫存器模型不但可以用來檢查硬體的暫存器,也可以用來配合scoreboard實時檢查DUT的功能。用來檢查暫存器時,結合上一節的常規方法和例碼,我們總結出可以有下面幾種可行的方式:

  • 從前門寫,並且從前門讀。這種方式最為常見,但無法檢查地址是否正確對映,下面的前門與後門混合操作的方式可以保證地址的對映檢查。

  • 從前門寫,再從後門讀。即利用write()實現前門寫,再使用read()或者peek()從後門讀。

  • 從後門寫,再從前門讀。即利用write()或者poke()從後門寫,再利用read()從前門讀。

  • 對於一些狀態暫存器,也可以考慮由硬體自身訊號驅動更新其實際值,先用peek()來獲取(並且會呼叫predict()方法來更新映象值),再呼叫mirror()方法來從前門訪問並且與之前更新的映象值比較。

  • 上面的這些方法,在暫存器模型的內建序列中都已經實現。與內建序列相比,自建序列可以更靈活,更貼近需求,但需要消耗更多的人力;內建序列使用簡單,是全自動化的方式,但考慮到一些特殊的暫存器,在實現自建序列測試前,使用者需要對一些暫存器設定“禁止域名”來將其排除在特定的暫存器檢查方式之外。

 

在配合scoreboard實施檢查DUT的功能時,需要注意如下幾點:

  • 無論是將暫存器模型通過config_db層次化配置,還是間接通過封裝在配置物件(configuration object)中的暫存器模型控制代碼,都需要scoreboard可以索引到暫存器模型。

  • 在讀取暫存器或者暫存器域的值時,使用者需要加以區分。不少初學者預設uvm_reg類中應該對應有類似value的成員來表徵其對應硬體暫存器的值,然而並沒有。要知道,uvm_reg並不是暫存器模型的最小切分單元,uvm_reg_field才是。所以,uvm_reg可以理解為uvm_reg_field的容器,一個uvm_reg可以包含多個順序排列的uvm_reg_field。在取值時,使用者可以使用uvm_reg_field的成員value直接訪問,但路桑更建議使用uvm_reg類和uvm_reg_field類都具備的外部介面函式get_mirrored_value()。

 

功能覆蓋率實現

在測試暫存器以及設計的某些功能配置模式時,我們也需要統計測試了的配置情況。就MCDF暫存器模型來看,除了測試暫存器本身,我們還需要考慮在不同的配置模式下,設計的資料處理、仲裁等功能是否正確,所以我們需要安置功能覆蓋率covergroup在暫存器模型中。由於暫存器描述檔案的結構化,我們可以通過擴充暫存器模型生成器(register model generator)的功能,使得其生成的暫存器模型也可以自動包含各個暫存器域的功能覆蓋率採集。UVM的暫存器模型已經內建了一些方法用來使能對應的covergroup,同時在呼叫read()或者read()方法時,會自動呼叫covergroup::sample()的方法來完成收集收據。接下來我們就給出兩種可供選擇的方式,來實現暫存器功能覆蓋率收集。

 

內部自動收集模式

如果暫存器模型生成器可以一併生成covergroup和對應的方法,我們就可以考慮是否例化這些covergroup、以及何時收集這些資料。從例碼中摘出的ctrl_reg暫存器擴充的定義部分來看,value_cg是用來收集暫存器中所有的域(包含reserved只讀區域),而要例化value_cg、以及何時採集資料,我們需要在實現的過程中考慮下面幾點:

  • 由於covergroup在此模式下可以自動生成,並且在使能的情況下,可以在每次read()、write()方法後呼叫。那麼從例化時的記憶體消耗、以及每次採集時的記憶體消耗,從上百的暫存器內建的covergroup聯動的情況出發,是否例化、是否使能取樣資料都需要考慮。這裡給出的建議是,在驗證前期,可以不例化covergroup,保證更好的資源利用;在驗證後期需要採集功能覆蓋率時,再考慮例化、使能取樣。

  • 上面談到的例化,在ctrl_reg中時在其構建函式中,通過has_coverage()來判斷是否需要例化的。該方法會查詢成員ctrl_reg::m_has_cover,是否具備特定的覆蓋率型別,而該成員在例化時,已經賦予了初值UVM_CVR_ALL,即包含所有覆蓋率型別,因此,value_cg可以例化。

  • 在新擴充的sample()和sample_values()兩個方法時,使用者也需要注意。sample()可以理解為read()、write()方法的回撥函式,使用者需要填充該方法,使得可以保證自動取樣資料。sample_values()是供使用者外部呼叫的方法,在一些特定的事件觸發時,例如中斷、復位等場景,使用者可以在外部通過監聽具體事件來主動呼叫該方法,即ctrl_reg::sampel_values()。

  • 在sample_values()方法中,可以通過get_coverage()方法來判斷是否允許進行覆蓋率取樣。使用者可能容易將has_coverage()與get_coverage()等方法混淆,就這兩個方法而言,前者指的是是否具備對應的covergroup,後者指的是是否允許使用對應的covergroup進行取樣。UVM將方法設計的如此多樣(或者說別出心裁),在這兒我們要體會它的良苦用心,即對是否例化、以及是否取樣做雙重的管理,以此來儘量降低由於覆蓋率取樣對驗證環境執行效率的負面影響。與這些方法類屬的方法還包括有set_coverage()和include_coverage(),讀者可以參考原始碼或者類手冊。

 

 

 

 

藉助於暫存器描述檔案的良好格式,暫存器模型生成器都可以通過模板的形式來生成可以控制例化和取樣的暫存器模型。如果使用者自己在開發暫存器模型生成器時,也可以考慮是否通過上述參考的變數形式來控制,或者在生成時匯入一些特定的編譯導向(compiler directive),例如`ifndef的語句塊來判斷是否需要將暫存器的covergroup進行編譯。這些方法的目的都是為了更靈活的選擇是否需要例化並採樣資料,以此來保證模擬效能。

 

事件觸發外部收集模式

自動收集覆蓋率的形式,不夠靈活,而且不是很貼合實際場景。不靈活的地方在於,它預設會取樣所有的域,包括那些保留域(reserved field),又或者對某一個域,為2位時,它會自動分配bin_0、bin_1、bin_2和bin_3來對應4個可能的值,殊不知可能val_3是違法的(illeagal bin),又或者取樣上述的狀態暫存器中的域fifo_avail[7:0],那麼是否要採集從0到63的所有可能值才能保證此域的完備性呢?另外,不貼合實際場景的地方在於,它不夠“智慧”,無法組合出更有意義的運用場景,例如在實際場景下,我們需要考慮3個通道是否同時使能、同時關閉、又或者有的使能有的關閉這種組合情形?3個通道在使能時,是否考慮到了不同優先順序、相同優先順序、又或者兩個通道相同優先順序、一個通道不同優先順序的情況?例如這種組合的場景,我們更應該在後期測試時考慮是否覆蓋到。因此,路桑建議,更貼合實際的、可作為覆蓋率驗收標準的covergroup定義還當採取自定義的形式,一方面來限定感興趣的域和值、一方面來指定感興趣的取樣事件,即在合適的事件、來觸發取樣,通過這種方式,最後可以形成暫存器功能覆蓋率驗證完備性的簽收標準。

 

下面,我們就著之前的例碼,自定義一個覆蓋率類,其中嵌入了對應的covergroup,以及指定的取樣事件。這段例碼中,定義了類mcdf_coverage,繼承於uvm_subscriber,這麼做的便利在於先聽準備了一副“耳朵”,用來訂閱從其它地方傳來的資訊。這裡的資訊稍後來自於mcdf_bus_monitor,來接資訊的方式也將通過mcdf_bus_monitor的uvm_analysis_port,發往mcdf_coverage的uvm_analysis_export。在mcdf_coverage::reg_value_cg的覆蓋率定義中,不但指定了對各個暫存器感興趣的域和值範圍,也將各個相關的coverpoint進行cross組合,構成更復雜的場景實現要求。在覆蓋率的採集事件中,我們就利用了mcdf_bus_monitor監聽到的前門訪問讀寫事件來作為觸發事件,對資料進行取樣。當然,這種取樣的方式也可以擴充套件,通過內建其它的可同步的元件,例如uvm_event對中斷等特殊事件進行暫存器取樣。