在SystemVerilog中,經(jīng)常會(huì)用到$cast對(duì)數(shù)據(jù)類(lèi)型進(jìn)行轉(zhuǎn)換,其實(shí)在實(shí)際使用過(guò)程中除了這種明擺著的數(shù)據(jù)類(lèi)型轉(zhuǎn)換外,SystemVerilog中還有一些“隱性”的數(shù)據(jù)類(lèi)型轉(zhuǎn)換,本文將通過(guò)示例說(shuō)明SystemVerilog中的數(shù)據(jù)類(lèi)型轉(zhuǎn)換。
在SystemVerilog中,類(lèi)型按照的兼容性分為5各層級(jí),分別是匹配(matching)、相同類(lèi)型(equivalent)、賦值兼容(assignment compatible)、轉(zhuǎn)換兼容(cast compatible)和不相同類(lèi)型(non-equivalent),其中匹配、相同類(lèi)型其實(shí)也屬于賦值兼容的一部分,所有的賦值兼容和所有的可以使用顯式轉(zhuǎn)換的不相同類(lèi)型都屬于可轉(zhuǎn)換類(lèi)型。
因此,可以知道,其實(shí)隱式轉(zhuǎn)換主要存在于匹配和相同的數(shù)據(jù)類(lèi)型之間,而顯式轉(zhuǎn)換存在于其他不同數(shù)據(jù)類(lèi)型或者賦值兼容的數(shù)據(jù)類(lèi)型之中。而隱式數(shù)據(jù)類(lèi)型轉(zhuǎn)換,顯式數(shù)據(jù)類(lèi)型轉(zhuǎn)換的主要區(qū)別是轉(zhuǎn)換是否“肉眼可見(jiàn)”,隱式轉(zhuǎn)換一般會(huì)“靜默”完成,而顯式需要用戶(hù)使用特殊的語(yǔ)法結(jié)構(gòu)才能實(shí)現(xiàn),下面通過(guò)示例具體看看兩種轉(zhuǎn)換的用法。
01? 隱 式 轉(zhuǎn) 換
隱式轉(zhuǎn)換一般情況下下表中的數(shù)據(jù)類(lèi)型變量相互之間進(jìn)行賦值時(shí)會(huì)自動(dòng)完成類(lèi)型轉(zhuǎn)換的,例如四值邏輯變量和二值邏輯邏輯變量之間的相互賦值、不同位寬變量之間的相互賦值等等。?
【示例】?
【仿真結(jié)果】?
示例中,將var4賦值為不定態(tài)之后在賦值給var3,雖然var4具有四值數(shù)據(jù)類(lèi)型,但是因?yàn)関ar3是二值數(shù)據(jù)類(lèi)型,當(dāng)var4賦值給var3時(shí),其中的不定態(tài)自動(dòng)轉(zhuǎn)換為了0,這個(gè)轉(zhuǎn)換過(guò)程是隱式自動(dòng)完成的。var2是一個(gè)byte類(lèi)型,為有符號(hào)數(shù),示例中其最高位為1,因?yàn)関ar4位寬比var2寬,所以再將其賦值給var4時(shí),需要對(duì)高位進(jìn)行補(bǔ)位操作,這時(shí)的補(bǔ)位操作將根據(jù)var2最高位的特點(diǎn)進(jìn)行補(bǔ)位,并且這個(gè)過(guò)程是隱式自動(dòng)完成的。其實(shí)在進(jìn)行具有上表中數(shù)據(jù)類(lèi)型特點(diǎn)的數(shù)據(jù)進(jìn)行隱式數(shù)據(jù)類(lèi)型轉(zhuǎn)換時(shí),為了避免這種“悄無(wú)聲息”的轉(zhuǎn)換發(fā)生,需要注意進(jìn)行操作的數(shù)據(jù)對(duì)象的以下幾點(diǎn): ü操作數(shù)的位寬; ü操作數(shù)的符號(hào)特性; ü操作數(shù)的數(shù)據(jù)類(lèi)型;
02? 顯 式 轉(zhuǎn) 換
顯示的類(lèi)型轉(zhuǎn)換主要有兩種方式,格式分別如下:
靜態(tài)轉(zhuǎn)換一般發(fā)生于編譯階段,在編譯階段完成類(lèi)型的檢查,而動(dòng)態(tài)轉(zhuǎn)換一般位于仿真運(yùn)行階段。下面將分別對(duì)兩種轉(zhuǎn)換進(jìn)行示例說(shuō)明。
2.1 static靜態(tài)轉(zhuǎn)換
靜態(tài)轉(zhuǎn)換不會(huì)對(duì)轉(zhuǎn)換值做檢查,在編譯階如果發(fā)生轉(zhuǎn)換失敗則會(huì)報(bào)錯(cuò),但是對(duì)于一般的“integer data types”之間在轉(zhuǎn)換是產(chǎn)生的截位等問(wèn)題則不會(huì)有相應(yīng)的警告信息。
【示例】?
【仿真結(jié)果】?
示例中,企圖將packet通過(guò)靜態(tài)轉(zhuǎn)換為int型,此時(shí)在代碼編譯階段已經(jīng)報(bào)錯(cuò),即不支持將class對(duì)象轉(zhuǎn)換為int型變量,其實(shí)在SystemVerilog中class對(duì)象不支持這種轉(zhuǎn)換,基本上所有的不以連續(xù)位方式進(jìn)行存儲(chǔ)的變量在使用靜態(tài)轉(zhuǎn)換是都會(huì)報(bào)錯(cuò)。關(guān)于具體轉(zhuǎn)換可查閱IEEE1800相關(guān)章節(jié)內(nèi)容。下面我們將分別示例常用的靜態(tài)轉(zhuǎn)換都有哪些。
2.1.1 類(lèi)型轉(zhuǎn)換
在SystemVerilog中,可以通過(guò)靜態(tài)轉(zhuǎn)換完成一些賦值兼容的數(shù)據(jù)類(lèi)型之間轉(zhuǎn)換,如果轉(zhuǎn)換的數(shù)據(jù)類(lèi)型賦值不兼容,將會(huì)產(chǎn)生一些不期望的結(jié)果,特別是在枚舉類(lèi)型和數(shù)據(jù)流中。數(shù)據(jù)類(lèi)型轉(zhuǎn)換的語(yǔ)法格式如下:
casting_type’(expression)
【示例】?
【仿真結(jié)果】?
示例中,給int型變量賦值為十進(jìn)制64,然后通過(guò)”string’(vart)”的方式將整數(shù)值64轉(zhuǎn)換成字符,此時(shí)的仿真結(jié)果將按照ASCII碼表中整數(shù)64對(duì)應(yīng)的字符進(jìn)行顯示,顯示的結(jié)果字符為”@”,在示例中實(shí)現(xiàn)了整數(shù)類(lèi)型與字符串類(lèi)型的轉(zhuǎn)換,當(dāng)然也可以進(jìn)行其他數(shù)據(jù)類(lèi)型之間的轉(zhuǎn)換,但是需要注意轉(zhuǎn)換數(shù)據(jù)類(lèi)型的賦值兼容性以及數(shù)據(jù)位寬和符號(hào)特性等問(wèn)題,否則轉(zhuǎn)換后的結(jié)果可能與期望不一致,所以,從安全性考慮,進(jìn)行建模時(shí)盡量采用統(tǒng)一的數(shù)據(jù)類(lèi)型之間的相互操作,盡量避免不同數(shù)據(jù)類(lèi)型之間的相互轉(zhuǎn)換。
2.1.2位寬轉(zhuǎn)換
在SystemVerilog中可以將一個(gè)表達(dá)式結(jié)果的位寬轉(zhuǎn)換為指定的位寬,這里需要注意不要轉(zhuǎn)換的表達(dá)式位于括號(hào)中,要轉(zhuǎn)換為的位寬必須為正數(shù),不能為0或者負(fù)數(shù)。其語(yǔ)法格式如下:
dst_size’(expression)
【示例】?
【仿真結(jié)果】?
示例中src_vector是8位寬,通過(guò)10’(src_vector)將src_vector位寬轉(zhuǎn)換為10位寬。當(dāng)然示例中的src_vector為無(wú)符號(hào)數(shù),無(wú)符號(hào)數(shù)在位寬擴(kuò)展時(shí)高位補(bǔ)0,如果src_vector為有符號(hào)數(shù),那么此時(shí)將src_vector轉(zhuǎn)換成寬位寬的數(shù)時(shí),此時(shí)需要注意該有符號(hào)數(shù)的符號(hào)位,此時(shí)的補(bǔ)位將會(huì)按照符號(hào)位進(jìn)行補(bǔ)位,如下例。
【示例】?
【仿真結(jié)果】?
示例中src_vector是8位寬byte有符號(hào)數(shù),通過(guò)10’(src_vector)將src_vector位寬轉(zhuǎn)換為10位寬,此時(shí)因?yàn)閟rc_vector為有符號(hào)數(shù),所以此時(shí)轉(zhuǎn)換時(shí)高位補(bǔ)位使用了其符號(hào)位進(jìn)行了補(bǔ)位,結(jié)果為10’b11_1010_1010。
2.1.3符號(hào)轉(zhuǎn)換
除了示例中通過(guò)靜態(tài)轉(zhuǎn)換可以轉(zhuǎn)換表達(dá)式結(jié)果位寬外,在SystemVerilog中還可以通過(guò)指定符號(hào)特性影響表達(dá)式結(jié)果的符號(hào)特性,其使用格式如下:
signed’(expression) 和unsigned’(expression)
【示例】?
【仿真結(jié)果】?
示例中,value0為有符號(hào)數(shù),并且初值為”-8”,首先將該數(shù)以二進(jìn)制和十進(jìn)制方式分別顯示,然后通過(guò)unsigned將value0的符號(hào)特性轉(zhuǎn)換為無(wú)符號(hào)數(shù),并且通過(guò)二進(jìn)制和十進(jìn)制方式分別顯示,顯示結(jié)果中,因?yàn)関alue0為32位數(shù),所以改變后其二進(jìn)制顯示將會(huì)保留未改變符號(hào)特性時(shí)數(shù)據(jù)在內(nèi)存中的存儲(chǔ)格式,但是此時(shí)十進(jìn)制顯示的結(jié)果就是該數(shù)轉(zhuǎn)換為無(wú)符號(hào)數(shù)后對(duì)應(yīng)的結(jié)果。其實(shí)除了上述使用靜態(tài)轉(zhuǎn)換實(shí)現(xiàn)符號(hào)特性的轉(zhuǎn)換外,在SystemVerilog中還可以通過(guò)系統(tǒng)函數(shù)$signed和$unsigned實(shí)現(xiàn)一樣的功能,再次就不再贅述了,大家可以將示例中的代碼進(jìn)行替換仿真。
2.2 dynamic動(dòng)態(tài)轉(zhuǎn)換
在SystemVerilog中,與靜態(tài)轉(zhuǎn)換對(duì)應(yīng)的是動(dòng)態(tài)轉(zhuǎn)換,動(dòng)態(tài)轉(zhuǎn)換可以通過(guò)使用系統(tǒng)方法$cast實(shí)現(xiàn)數(shù)據(jù)類(lèi)型的轉(zhuǎn)換,這個(gè)動(dòng)態(tài)轉(zhuǎn)換的過(guò)程相較于靜態(tài)轉(zhuǎn)換主要區(qū)別在于該轉(zhuǎn)換和檢查發(fā)生在仿真運(yùn)行階段。同時(shí)$cast在SystemVerilog中有兩種存在形式,這兩種形式的格式如下:
function int $cast(singular dest_var,singular src_exp);
和
task $cast(singular dest_var,singular src_exp);
兩種形式實(shí)現(xiàn)的功能都是將源表達(dá)式src_exp轉(zhuǎn)換給目標(biāo)變量dest_var,那么既生瑜何生亮,實(shí)現(xiàn)的功能都一樣,在具體使用時(shí)仿真工具或者用戶(hù)如何知道使用的是$cast的那種形式呢?下面我們通過(guò)示例說(shuō)明兩者使用上的差異。
2.2.1 $cast作為任務(wù)task
【示例】?
【仿真結(jié)果】?
示例中,雖然子類(lèi)scobj是從父類(lèi)cobj拓展派生而來(lái)的,兩個(gè)屬于不同的類(lèi)型,但是父類(lèi)句柄是可以直接指向子類(lèi)對(duì)象,子類(lèi)句柄是不能直接指向父類(lèi)對(duì)象的(關(guān)于句柄之間類(lèi)型轉(zhuǎn)換可參考《硅心思見(jiàn):【113】SystemVerilog中不同句柄之間的動(dòng)態(tài)類(lèi)型轉(zhuǎn)換》)。本示例中企圖通過(guò)$cast將子類(lèi)句柄sp指向父類(lèi)句柄指向的對(duì)象(此時(shí)父類(lèi)句柄指向?qū)ο蟮念?lèi)型為cobj),并且代碼的編譯已經(jīng)通過(guò),但是在程序運(yùn)行時(shí)調(diào)用$cast時(shí),檢測(cè)類(lèi)型不匹配,仿真器直接報(bào)錯(cuò)停止,并且給出報(bào)錯(cuò)信息。可以看到,示例中$cast的用法與task相同,都沒(méi)有返回值,仿真器會(huì)根據(jù)該方法使用的上下文確定該方法按照task進(jìn)行解析。
2.2.2?$cast作為函數(shù)function
【示例】?
【仿真結(jié)果】
示例中,兩次調(diào)用$cast,都將$cast賦值給了tmp,即此時(shí)$cast有返回值,根據(jù)上下文可以此時(shí)$cast被作為一個(gè)有返回值的方法,此時(shí)的$cast被仿真器按照f(shuō)unction解析處理。第一次調(diào)用$cast時(shí),因?yàn)樽宇?lèi)句柄sp指向父類(lèi)句柄p指向的對(duì)象(因?yàn)榇藭r(shí)父類(lèi)句柄指向?qū)ο蟮念?lèi)型為cobj),當(dāng)仿真運(yùn)行調(diào)用$cast時(shí)檢測(cè)到類(lèi)型不匹配,函數(shù)返回0給tmp,條件判斷語(yǔ)句根據(jù)tmp值執(zhí)行了對(duì)應(yīng)分支的$display語(yǔ)句,同時(shí)我們注意到仿真并沒(méi)有因?yàn)檫@次不匹配報(bào)出任何提示信息和停止仿真;第二次調(diào)用$cast時(shí),因?yàn)榫浔鷓指向子類(lèi)句柄sp指向的對(duì)象(父類(lèi)句柄可以直接指向子類(lèi)對(duì)象),當(dāng)仿真運(yùn)行調(diào)用$cast時(shí)檢測(cè)到類(lèi)型匹配兼容,函數(shù)返回1給tmp,條件判斷語(yǔ)句根據(jù)tmp值執(zhí)行了對(duì)應(yīng)分支的$display語(yǔ)句。
通過(guò)上述示例可以匯總?cè)缦聨c(diǎn):
ü當(dāng)將$cast作為任務(wù)使用時(shí),如果源對(duì)象的數(shù)據(jù)類(lèi)型與目的對(duì)象的數(shù)據(jù)類(lèi)型不匹配不兼容仿真時(shí)會(huì)報(bào)錯(cuò),并且仿真停止;
ü當(dāng)將$cast作為函數(shù)使用時(shí),如果源對(duì)象的數(shù)據(jù)類(lèi)型與目的對(duì)象的數(shù)據(jù)類(lèi)型不匹配不兼容仿真時(shí),該函數(shù)僅返回值0,并且仿真不會(huì)停止也不會(huì)給出任何提示,如果類(lèi)型兼容匹配,轉(zhuǎn)換成功,那么函數(shù)返回非零值;
ü$cast具體作為函數(shù)還是任務(wù),取決于用戶(hù)在編碼時(shí)按照如何的方式對(duì)$cast進(jìn)行使用,如果期望類(lèi)型不匹配不兼容時(shí)能夠給出信息并且停止仿真,那么用戶(hù)應(yīng)該像任務(wù)一樣使用$cast,如果想根據(jù)類(lèi)型轉(zhuǎn)換的結(jié)果進(jìn)行特定的操作并不自動(dòng)停止時(shí),那么用戶(hù)應(yīng)該像函數(shù)一樣使用$cast。
編輯:黃飛
評(píng)論
查看更多