本文首發(fā)于微信公眾號“芯片學堂”敢朱,作者JKZHAN
在計算機編程語言中,集合類型(collection)的數(shù)據(jù)結構都是非常重要的恶耽。這里集合的概念指的是能夠將多個數(shù)據(jù)對象整合到一起進行管理和操作的復合數(shù)據(jù)類型舞丛。
數(shù)組(array)构捡,是比較重要的、基礎的、具有代表性的集合類型枚赡。在大部分編程語言中氓癌,數(shù)組具有一致性、有序性和不可變性贫橙。一致性指的是元素類型一致贪婉;有序性指的是元素排列順序確定,可通過下標索引卢肃;不可變性指的是長度不可變疲迂。多說一句,在現(xiàn)代編程語言中莫湘,往往有多樣的集合類型突破了這幾個性質尤蒿,主要是為了提供編程便利和保證硬件安全。
SystemVerilog相比于Verilog提供了功能更加豐富的數(shù)組類型幅垮,包括定長數(shù)組(Fixed-size Array)腰池、動態(tài)數(shù)組(Dynamic Array)、關聯(lián)數(shù)組(Associative Array)忙芒,還有為多維數(shù)組的切片索引提供方便而做區(qū)分的合并數(shù)組(Packed Array)和非合并數(shù)組(Unpacked Array)示弓。
01 定長數(shù)組和動態(tài)數(shù)組
定長數(shù)組在聲明的時候就必須指定數(shù)組的長度(緊湊聲明)或者上下邊界(完整聲明)沥曹。這樣在仿真程序編譯完成之后苟蹈,系統(tǒng)需要為其分配的內存空間大小就是已知的、確定的。
動態(tài)數(shù)組在聲明的時候不需要指定數(shù)組長度甘桑,而是在原來指定長度的中括號中留空。注意不是用$符號歹叮,$符號是用來聲明另一種叫隊列的集合類型用的跑杭。但是在使用動態(tài)數(shù)組之前,需要使用構造函數(shù)(new)對動態(tài)數(shù)組進行定長實例化咆耿。
換句話說德谅,定長數(shù)組和動態(tài)數(shù)組其實都是“定長”的,當系統(tǒng)為其分配空間之后萨螺,該空間大小就固定下來了窄做。它們的區(qū)別只是定長數(shù)組在仿真程序編譯的時候就已經確定,而動態(tài)數(shù)組可以在仿真運行時再根據(jù)上下文確定長度然后實例化慰技。所以椭盏,我個人覺得將它們分別叫數(shù)組的靜態(tài)初始化和動態(tài)初始化會更合適一些。
在有些編程語言中吻商,會存在“不定長”和“變長數(shù)組”的數(shù)組類型掏颊,即內存空間分配之后還可以變化。這種數(shù)組在本質上是這么實現(xiàn)的,當你需要改變長度的時候乌叶,系統(tǒng)會動態(tài)給你創(chuàng)建一個新的數(shù)組盆偿,然后將舊數(shù)組的值賦值過去,最后將舊的數(shù)組空間回收准浴。這種數(shù)據(jù)結構是低效的事扭。說到底,數(shù)組依然具有不可變性乐横。
02 常被用作查找表的關聯(lián)數(shù)組
上面介紹的定長數(shù)組和動態(tài)數(shù)組處理連續(xù)變量集合的時候是很有用的句旱。然而當你要存儲的數(shù)據(jù)量未知,或者是要保存稀疏矩陣的元素時晰奖,就應該選擇關聯(lián)數(shù)組了谈撒。
關聯(lián)數(shù)組有兩大特性。第一匾南,關聯(lián)數(shù)組的元素在被使用之前不會消耗內存資源啃匿;第二,關聯(lián)數(shù)組的索引可以是任何數(shù)據(jù)類型蛆楞。所以說溯乒,關聯(lián)數(shù)組的特性非常適合做查找表,類似于Python中的字典類型豹爹,是一種典型的鍵-值(key-value)模式裆悄。關聯(lián)數(shù)組在內存中的存放自然也是離散的,這一點非常關鍵臂聋。
關聯(lián)數(shù)組的聲明語法是:data_type array_id [index_type]光稼;其中data_type確定數(shù)組元素的類型,array_id是數(shù)組的名字孩等,index_type是索引的類型艾君。至于數(shù)組的使用,建議使用foreach進行循環(huán)遍歷肄方,它會自動遍歷到已經存在的那些元素冰垄;還可以使用關聯(lián)數(shù)組的delete、first权她、exists等內建方法虹茶。
有一個地方需要注意,當你通過一個不存在的索引去訪問關聯(lián)數(shù)組的時候隅要,是會返回數(shù)組類型的默認值的蝴罪,可能不是你想象中的邊界溢出然后報個錯。
03 合并數(shù)組和非合并數(shù)組
合不合并這個概念跟前面講的幾種數(shù)組類型不是在一個維度上拾徙。合并和非合并實際上是多維向量為了方便不同的訪問場景而衍生出來的切片分段的組織方式洲炊。在存儲方式上是有區(qū)別的:合并的部分原則上是連續(xù)比特存放的,非合并的部分就不一定了。
再說一下聲明方式就可以舉個例子了暂衡。在聲明數(shù)組時询微,如果將數(shù)組的維度寫到數(shù)組名的前面,表示這部分合并狂巢;如果將數(shù)組的維度寫到數(shù)組名后面撑毛,表示這部分非合并。
舉一個經典的例子唧领,memory的聲明:logic [31:0] my_mem [1024]藻雌;這個例子中,數(shù)組名是my_mem斩个,寫在它前面的維度是[31:0]胯杭,這一部分是合并的,即每32bit就連續(xù)存放在一塊受啥;寫在它后面的維度是[1024](這里跟寫成[0:1023]的形式是一樣的哈)做个,這部分是非合并的,即這1024組32bit不一定是連續(xù)存放的滚局。當我們進行訪問my_mem[520]的時候居暖,就可以直接讀出來第520個字。
總結一下藤肢,合并和非合并是數(shù)據(jù)集合的一種組織方式太闺,方便存儲管理,方便使用者訪問嘁圈。所以在聲明多維數(shù)組的時候省骂,建議是根據(jù)應用場景來決定怎么合并。
參考文獻
[1]IEEE Standard Association. "IEEE Standard for SystemVerilog-Unified Hardware Design, Specification, and Verification Language." (2013).
[2] Horstmann, Cay S., and Gary Cornell. Core Java : Volume I Fundamentals. Prentice Hall PTR, 2000.