sv包的意義(package)

轉(zhuǎn)自(https://blog.eetop.cn/blog-1561828-2316833.html
SV語(yǔ)言提供了一種在多個(gè)module、interface和program之中共享parameter、data、type、task、function、class等等的方法,即利用package(包)的方式來(lái)實(shí)現(xiàn)。如果用上面裝修一個(gè)大房子(MCDF testbench)來(lái)看的話(huà),我們喜歡將不同模塊的類(lèi)定義歸整到不同的package中。這么做的好處在于將同一簇相關(guān)的類(lèi)組織在了單一的名字空間(namespace)下,使得分屬于不同模塊驗(yàn)證環(huán)境的類(lèi)首先來(lái)自于不同的package,這樣可以通過(guò)package來(lái)區(qū)別類(lèi)的歸屬問(wèn)題。

1 我們來(lái)看看這樣一個(gè)實(shí)際的問(wèn)題吧,register和arbiter的verifier給自己的package定義是這樣的。

package regs_pkg;
  `include "stimulator.sv"
  `include "monitor.sv"
  `include "chker.sv"
  `include "env.sv"
endpackage
package arb_pkg;
  `include "stimulator.sv"
  `include "monitor.sv"
  `include "chker.sv"
  `include "env.sv"
endpackage

兩位verifier在各自的package regs_pkg和arb_pkg中都定義了4個(gè)與模塊驗(yàn)證相關(guān)的類(lèi)即stimulator、monitor、checker和env。而在這兩個(gè)package中同名的類(lèi),實(shí)際上內(nèi)容是不相同的,實(shí)現(xiàn)的也是不同的功能。如果我們將這些重名的類(lèi)歸屬到不同的package中編譯,有沒(méi)有問(wèn)題呢?會(huì)不會(huì)發(fā)生重名的編譯沖突?讀者不需要為此擔(dān)心,package允許你做的,就是將單一的全局名字空間分隔開(kāi)來(lái),這樣如果要使用不同package中的同名類(lèi),他們需要強(qiáng)調(diào)要使用哪一個(gè)package中的。譬如下面這個(gè)例子:

module mcdf_tb;
regs_pkg::monitor mon1 = new();
arb_pkg::monitor mon2 = new();
endmodule

盡管在regs_pkg和arb_pkg中都存在著一個(gè)名字為monitor的類(lèi),我們可以在引用類(lèi)名的時(shí)候通過(guò)域名索引“::”操作符的方式來(lái)顯式指出所引用的類(lèi)monitor具體來(lái)自于哪一個(gè)package,這樣便能很好地通過(guò)不同名的package來(lái)管理同名的類(lèi)。從這個(gè)簡(jiǎn)單的例子來(lái)看,package這個(gè)容器可以對(duì)類(lèi)名做一個(gè)隔離的作用。那么,有的讀者可能會(huì)在pakcage(包)和library(庫(kù))之間有混淆,我們來(lái)看看它們的聯(lián)系和區(qū)別:
package更多的意義在于將軟件(類(lèi)、類(lèi)型、方法等)封裝在不同的命名空間中,以此來(lái)與全局的命名空間進(jìn)行隔離。package需要額外定義,容納各種數(shù)據(jù)、方法和類(lèi)。
library是編譯的產(chǎn)物,在沒(méi)有介紹軟件之前,硬件(module、interface、program)都會(huì)編譯到庫(kù)中,如果不指定編譯庫(kù)的話(huà),會(huì)被編譯進(jìn)入默認(rèn)的庫(kù)中。從容納的類(lèi)型來(lái)看,庫(kù)既可以容納硬件類(lèi)型,也可以容納軟件類(lèi)型,例如類(lèi)和方法,也包括package。
從上面的聯(lián)系來(lái)看,不同package之間可能存在著同名的類(lèi),不同的library之間也可能存在著同名的module(硬件)或者package(軟件)。如果像上面的例子,遇到了不同package中同名的類(lèi),那么用戶(hù)可以通過(guò)“::”來(lái)顯式調(diào)用具體哪個(gè)package中的類(lèi);如果遇到的是不同library中,有同名的module或者package等,那么應(yīng)該怎么解決呢?常見(jiàn)的方式是通過(guò)HDL語(yǔ)言的config文件(VHDL、Verilog、SV均有該特性)來(lái)指定具體模塊從哪個(gè)library中選取。默認(rèn)情況下,采取的是“就近原則”,即調(diào)用該重名模塊的上層模塊位于哪個(gè)library,則仿真器會(huì)優(yōu)先從該library中尋找該模塊。這個(gè)原則,對(duì)于package也是適用的,即使用該重名package的module或者interface會(huì)優(yōu)先尋找它們所在的library。如果用戶(hù)想讓其優(yōu)先搜尋非默認(rèn)的庫(kù),那么需要在config文件中指定尋找的庫(kù)名和順序。
在編譯package時(shí),需要注意的是,不應(yīng)該有同名的package存在。那么,當(dāng)類(lèi)和方法并沒(méi)有被封裝在某個(gè)package時(shí),它們會(huì)被編譯到哪兒去了呢?實(shí)際上,仿真器仍然會(huì)將它們編譯到默認(rèn)的package中。但是,只有與該文件放置在一起的module才能識(shí)別和引用到它,至于該文件之外的module要想辦法引用到這些類(lèi)和方法,則沒(méi)有什么好的辦法了。所以,如果像讓你的類(lèi)和方法被更多的人使用,更方便的共享,一個(gè)基本方式就是首先將它們組織到一個(gè)package中。
此外,對(duì)于編譯的module、interface和package這些硬件和軟件,會(huì)進(jìn)入哪一個(gè)library呢?如果沒(méi)有額外的指定,它們都會(huì)被編譯到默認(rèn)library(work)中。因此,在默認(rèn)庫(kù)中,各個(gè)module是互相認(rèn)識(shí)的,當(dāng)然module也認(rèn)識(shí)同一個(gè)library中的package。如果要使用其他library中的module或者package,那么一個(gè)config文件是一項(xiàng)好的選擇。

2 接下來(lái)是關(guān)于定義package的一些好的建議:

在創(chuàng)建package的時(shí)候,已經(jīng)在指定包名稱(chēng)的時(shí)候隱含地指定了包的默認(rèn)路徑,即包文件所在的路徑。如果有其它要被包含在包內(nèi)的文件在默認(rèn)路徑之外,需要在編譯包的時(shí)候加上額外制定的搜尋路徑選項(xiàng)“+incdir+PATH”。
如果遵循package的命名習(xí)慣,不但我們要求定義的package名稱(chēng)獨(dú)一無(wú)二,其內(nèi)部定義的類(lèi)也應(yīng)該盡可能地獨(dú)一無(wú)二。例如,上面的例子中,regs_pkg和arb_pkg中有同名的類(lèi),這些類(lèi)如果攜帶類(lèi)名的前綴,那么后面的處理會(huì)變得更容易一些。從下面這個(gè)例子可以發(fā)現(xiàn),如果不同package中定義的類(lèi)名也不相同時(shí),在頂層的引用也可以通過(guò)“import pkg_name::*”的形式,來(lái)表示在module mcdf_tb中引用的類(lèi)如果在當(dāng)前域(mcdf內(nèi)部)中沒(méi)有定義的話(huà),會(huì)搜尋regs_pkg和arb_pkg中定義的所有類(lèi)型,又由于它們各自包含的類(lèi)名不相同,因此也無(wú)需擔(dān)心下面的搜尋會(huì)遇到同名類(lèi)發(fā)生沖突的問(wèn)題。

package regs_pkg;
  `include "regs_stm.sv"
  `include "regs_mon.sv"
  `include "regs_chk.sv"
  `include "regs_env.sv"
endpackage
package arb_pkg;
  `include "arb_stm.sv"
  `include "arb_mon.sv"
  `include "arb_chk.sv"
  `include "arb_env.sv"
endpackage
module mcdf_tb;
import regs_pkg::*;
import arb_pkg::*;
regs_mon mon1= new();
arb_mon mon2 = new();
endmodule

本文最后的部分是關(guān)于使用package的一些注意事項(xiàng):
用戶(hù)可以在module、interface或者program中來(lái)引用package。
如果是”import pkg_name::*“,則代表的是該package中定義的類(lèi)型可能會(huì)在module等內(nèi)部有效可見(jiàn)。只有當(dāng)module等無(wú)法在內(nèi)部索引到正確地類(lèi)型時(shí),才會(huì)轉(zhuǎn)而去package中去搜尋,如果索引到了那么該package中的這個(gè)類(lèi)型則變得在module中可見(jiàn)。

package a_pkg;
  class mon;
  endclass
endpackage
module module1;
class mon;
endclass
import a_pkg::*;
mon mon1 = new(); // 已經(jīng)有內(nèi)部mon定義,因此不會(huì)搜尋a_pkg
endmodule

如果用戶(hù)使用了“import pkg_name::type_name”,則表示直接讓package_name::type_name類(lèi)型在module等內(nèi)部變?yōu)榭梢?jiàn),那么此時(shí)需要注意的是,module內(nèi)部不應(yīng)該再有其它同名的類(lèi)型定義,避免發(fā)生同名類(lèi)型定義的沖突。

package a_pkg;
  class mon;
  endclass
endpackage
module module1;
class mon;
endclass
import a_pkg::mon;
mon mon1 = new(); // 同時(shí)有內(nèi)部mon定義和引入a_pkg::mon,發(fā)生同名類(lèi)型沖突
endmodule

如果在package a_pkg中import了package b_pkg::type_b,那么在module1中import a_pkg::*時(shí),無(wú)法引用到type_b。因?yàn)閍_pkg只是使得b_pkg::type_b在a_pkg域中可見(jiàn)并加以使用,并未定義在a_pkg中。所以,用戶(hù)需要牢記一點(diǎn)的是,import操作使得類(lèi)型可見(jiàn)的域只是調(diào)用該import時(shí)當(dāng)前的域。例如下面的例子中,a_pkg中可見(jiàn)b_pkg::b_mon,但是module1則無(wú)法可見(jiàn)a_pkg::b_mon。

package b_pkg;
  class b_mon;
  endclass
endpackage
package a_pkg;
  import b_pkg::b_mon;
  class a_mon;
  endclass
endpackage
module module1;
import a_pkg::*;
a_mon mon1 = new(); // a_mon可見(jiàn)
b_mon mon2 = new(); // b_mon不可見(jiàn)
endmodule

要解決上面的問(wèn)題,用戶(hù)可以使用export來(lái)讓b_mon在a_pkg中得到二次定義。從下面這個(gè)例子中可以發(fā)現(xiàn),a_pkg中需要額外使用export來(lái)讓b_pkg::b_mon在a_pkg得到定義。因此,在module1中import a_pkg::*,可以搜尋到a_pkg中的a_mon和b_mon兩種類(lèi)型。

package b_pkg;
  class b_mon;
  endclass
endpackage
package a_pkg;
  import b_pkg::b_mon;
  export b_pkg::b_mon;
  class a_mon;
  endclass
endpackage
module module1;
import a_pkg::*;
a_mon mon1 = new();
b_mon mon2 = new();
endmodule

用戶(hù)使用到的系統(tǒng)函數(shù)和任務(wù),例如stop()、randomize()等等凡是帶有“$”符號(hào)的方法,另外一種調(diào)用的方式是std::method,例如std::randomize()。這隱含地是所有的系統(tǒng)方法都是預(yù)定義在一個(gè)稱(chēng)之為std包中的。用戶(hù)只能使用這些包內(nèi)的方法和類(lèi)型,無(wú)法二次對(duì)std包做出修改和添加。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、模塊模式簡(jiǎn)介 ??前面介紹了find_package有兩種搜索包的模式(參考find_package介紹[ht...
    Domibaba閱讀 4,860評(píng)論 0 0
  • 軟件是由代碼組成的。為了復(fù)用代碼,代碼的組織出現(xiàn)了不同層次的抽象和實(shí)現(xiàn),如 Module(模塊),包(Packag...
    人世間閱讀 34,612評(píng)論 5 45
  • sorted()也是一個(gè)高階函數(shù)。用sorted()排序的關(guān)鍵在于實(shí)現(xiàn)一個(gè)映射函數(shù)。 函數(shù)作為返回值 高階函數(shù)除了...
    jbb_43b0閱讀 394評(píng)論 0 0
  • Swift Package Manager(Swift 包管理器,一般簡(jiǎn)稱(chēng) SwiftPM 或 SPM)是蘋(píng)果官方...
    HotPotCat閱讀 5,727評(píng)論 0 8
  • Distutils可以用來(lái)在Python環(huán)境中構(gòu)建和安裝額外的模塊。新的模塊可以是純Python的,也可以...
    MiracleJQ閱讀 3,250評(píng)論 0 1

友情鏈接更多精彩內(nèi)容