天天看點

《UVM實戰》——3.1節uvm_component與uvm_object

本節書摘來自華章社群《uvm實戰》一書中的第3章,第3.1節uvm_component與uvm_object,作者 張 強,更多章節内容可以通路雲栖社群“華章社群”公衆号檢視

第3章

uvm 基 礎

3.1 uvm_component與uvm_object

component與object是uvm中兩大最基本的概念,也是初學者最容易混淆的兩個概念。本節将介紹uvm_object與uvm_component的差別和聯系。

3.1.1 uvm_component派生自uvm_object

通過對第2章搭建的驗證平台的學習,讀者應對uvm有了較直覺的認識,不少讀者會認為uvm_component與uvm_object是兩個對等的概念。當建立一個類的時候,比如定義一個sequence類,一個driver類,要麼這個類派生自uvm_component(或者uvm_component的派生類,如uvm_driver),要麼這個類派生自uvm_object(或者uvm_object的派生類,如uvm_sequence),似乎uvm_object與uvm_component是對等的概念,其實不然。

uvm_object是uvm中最基本的類,讀者能想到的幾乎所有的類都繼承自uvm_object,包括uvm_component。uvm_component派生自uvm_object這個事實會讓很多人驚訝,而這個事實說明了uvm_component擁有uvm_object的特性,同時又有自己的一些特質。但是uvm_component的一些特性,uvm_object則不一定具有。這是面向對象程式設計中經常用到的一條規律。

uvm_component有兩大特性是uvm_object所沒有的,一是通過在new的時候指定parent參數來形成一種樹形的組織結構,二是有phase的自動執行特點。圖3-1列出了uvm中常用類的繼承關系。

從圖中可以看出,從uvm_object派生出了兩個分支,所有的uvm樹的結點都是由uvm_component組成的,隻有基于uvm_component派生的類才可能成為uvm樹的結點;最左邊分支的類或者直接派生自uvm_object的類,是不可能以結點的形式出現在uvm樹上的。

《UVM實戰》——3.1節uvm_component與uvm_object

3.1.2 常用的派生自uvm_object的類

既然uvm_object是最基本的類,那麼其能力恰恰也是最差的,當然了,其擴充性也是最好的。恰如一個嬰兒,其能力很差,但是可以把其盡量培養成書法家、藝術家等。

到目前為止uvm_object依然是一個相當抽象的類。驗證平台中用到的哪些類會派生自uvm_object?答案是除了派生自uvm_component類之外的類,幾乎所有的類都派生自uvm_object。換個說法,除了driver、monitor、agent、model、scoreboard、env、test之外的幾乎所有的類,本質上都是uvm_object,如sequence、sequence_item、transaction、config等。

如果讀者現在依然對uvm_object很迷茫的話,那麼舉一個更加通俗點的例子,uvm_object是一個分子,用這個分子可以搭建成許許多多的東西,如既可以搭建成動物,還可以搭建成植物,更加可以搭建成沒有任何意識的岩石、空氣等。uvm_component就是由其搭建成的一種進階生命,而sequence_item則是由其搭建成的血液,它流通在各個進階生命(uvm_component)之間,sequence則是衆多sequence_item的組合,config則是由其搭建成的用于規範進階生命(uvm_component)行為方式的準則。

在驗證平台中經常遇到的派生自uvm_object的類有:

uvm_sequence_item:讀者定義的所有的transaction要從uvm_sequence_item派生。transaction就是封裝了一定資訊的一個類,本書中的my_transaction就是将一個mac幀中的各個字段封裝在了一起,包括目的位址、源位址、幀類型、幀的資料、fcs校驗和等。driver從sequencer中得到transaction,并且把其轉換成端口上的信号。從圖3-1中可以看出,雖然uvm中有一個uvm_transaction類,但是在uvm中,不能從uvm_transaction派生一個transaction,而要從uvm_sequence_item派生。事實上,uvm_sequence_item是從uvm_transaction派生而來的,是以,uvm_sequence_item相比uvm_transaction添加了很多實用的成員變量和函數/任務,從uvm_sequence_item直接派生,就可以使用這些新增加的成員變量和函數/任務。

uvm_sequence:所有的sequence要從uvm_sequence派生一個。sequence就是sequence_item的組合。sequence直接與sequencer打交道,當driver向sequencer索要資料時,sequencer會檢查是否有sequence要發送資料。當發現有sequence_item待發送時,會把此sequence_item交給driver。

config:所有的config一般直接從uvm_object派生。config的主要功能就是規範驗證平台的行為方式。如規定driver在讀取總線時位址信号要持續幾個時鐘,片選信号從什麼時候開始有效等。這裡要注意config與config_db的差別。在上一章中已經見識了使用config_db進行參數配置,這裡的config其實指的是把所有的參數放在一個object中,如10.5節所示。然後通過config_db的方式設定給所有需要這些參數的component。

除了上面幾種類是派生自uvm_object外,還有下面幾種:

uvm_reg_item:它派生自uvm_sequence_item,用于register model中。

uvm_reg_map、uvm_mem、uvm_reg_field、uvm_reg、uvm_reg_file、uvm_reg_block等與寄存器相關的衆多的類都是派生自uvm_object,它們都是用于register model。

uvm_phase:它派生自uvm_object,其主要作用為控制uvm_component的行為方式,使得uvm_component平滑地在各個不同的phase之間依次運轉。

除了這些之外,其實還有很多。不過其他的一些并不那麼重要,這裡不再一一列出。

3.1.3 常用的派生自uvm_component的類

與uvm_object相比,派生自uvm_component的類比較少,且在上一章的驗證平台中已經全部用到過。

uvm_driver:所有的driver都要派生自uvm_driver。driver的功能主要就是向sequencer索要sequence_item(transaction),并且将sequence_item裡的資訊驅動到dut的端口上,這相當于完成了從transaction級别到dut能夠接受的端口級别資訊的轉換。與uvm_component相比,uvm_driver多了如下幾個成員變量:

代碼清單 3-1

來源:uvm源代碼

3.1.4 與uvm_object相關的宏

在uvm中與uvm_object相關的factory宏有如下幾個:

uvm_object_utils:它用于把一個直接或間接派生自uvm_object的類注冊到factory中。

uvm_object_param_utils:它用于把一個直接或間接派生自uvm_object的參數化的類注冊到factory中。所謂參數化的類,是指類似于如下的類:

代碼清單 3-7

答案是不會出現任何問題,這樣的寫法完全正确,可以盡情使用。

uvm_object_param_utils_begin:與uvm_object_utils_begin宏一樣,隻是它适用于參數化的且其中某些成員變量要使用field_automation機制實作的類。

uvm_object_utils_end:它總是與uvm_object_*_begin成對出現,作為factory注冊的結束标志。

3.1.5 與uvm_component相關的宏

在uvm中與uvm_component相關的factory宏有如下幾個:

uvm_component_utils:它用于把一個直接或間接派生自uvm_component的類注冊到factory中。

uvm_component_param_utils:它用于把一個直接或間接派生自uvm_component的參數化的類注冊到factory中。

uvm_component_utils_begin:這個宏與uvm_object_utils_begin相似,它用于同時需要使用factory機制和field_automation機制注冊的類。在類似于my_transaction這種類中使用field_automation機制可以讓人了解,可是在component中使用field_automation機制有必要嗎?uvm_component派生自uvm_object,是以對于object擁有的如compare、print函數都可以直接使用。但是filed_automation機制對于uvm_component來說最大的意義不在于此,而在于可以自動地使用config_db來得到某些變量的值。具體的可以參考3.5.3節的介紹。

uvm_component_param_utils_begin:與uvm_component_utils_begin宏一樣,隻是它适用于參數化的,且其中某些成員變量要使用field_automation機制實作的類。

uvm_component_utils_end:它總是與uvm_component_*_begin成對出現,作為factory注冊的結束标志。

3.1.6 uvm_component的限制

uvm_component是從uvm_object派生來的。從理論上來說,uvm_component應該具有uvm_object的所有的行為特征。但是,由于uvm_component是作為uvm樹的結點存在的,這一特性使得它失去了uvm_object的某些特征。

在uvm_object中有clone函數,它用于配置設定一塊記憶體空間,并把另一個執行個體複制到這塊新的記憶體空間中。clone函數的使用方式如下:

代碼清單 3-9

3.1.7 uvm_component與uvm_object的二進制結構

為什麼uvm中會分成uvm_component與uvm_object兩大類呢?從古至今,人類在探索世界的時候,總是在不斷尋找規律,并且通過尋找到的規律來把所遇到的事物、所看到的現象分類。因為世界太複雜,隻有把有共性的萬物分類,進而按照類别來認識萬物,這樣才能大大降低人類認識世界的難度。比如世界的生命有千萬種,但是隻有動物和植物兩類。遇到一個生命的時候,人們會不自覺地判斷它是一個動物還是植物,并且把動物或植物的特性預加到這種生命的身上,接下來用動物或者植物的方法來研究這個生命,進而加快對于這個生命的認知過程。

uvm很明顯吸收了這種哲學,先分類,然後分别管理。想像一下,假如uvm中不分uvm_object與uvm_component,所有的東西都是uvm_object,那是多麼恐怖的一件事情?這相當于直接與分子打交道!廢時廢力,不易于使用。

systemverilog作為一門程式設計語言,相當于提供了最基本的原子,其使用起來相當麻煩。為了減少這種麻煩,uvm出現了。但是假如uvm中全部都是uvm_object的話,也就是全部都是分子,分子雖然比原子好用一些,但是依然處于普通人的承受範圍之外。隻有把分子組合成一個又一個生命體的時候,用起來才會比較順手。

uvm_component那麼好用,為什麼不把所有的東西都做成uvm_component的形式呢?因為uvm_component是進階生命體,有其自己鮮明的特征。驗證平台中并不是所有的東西都有這種鮮明的特征。一個簡單的例子:uvm_component在整個仿真中是一直存在的,但是假如要發送一個transaction(激勵)給dut,此transaction(激勵)可能隻需要幾毫秒就可以發送完。發送完了,此transaction(激勵)的生命周期幾乎就結束了,根本沒有必要在整個仿真中一直持續下去。生命是多樣化的,要既允許uvm_component這樣的進階生命存在,也要允許transaction這種如流星一閃而逝的東西存在。

繼續閱讀