system verilog 第二章翻译 下载本文

具有3个类似bytes元素的数组。其存放形式如图2.3所示。使用一个下标,可以得到一个字的数据barray[2]。是用两个下标可以得到一个字节的数据barray[0][3],使用3个下标,可以访问到单个比特位barray[0][1][6]。逐一数组声明中在变量名后面指定了数组的大小,barray[3],这个维度是非合并的,所以在使用该数组时至少有一个下标。

例2.18中的最后一行在两个合并数组间实现复制。由于操作是以bit为单位进行的,所以即使数组维度不同也可以复制。

2.2.8 合并数组和非合并数组的选择

到底使用合并数组还是非合并数组呢?当需要和标量进行相互转换时,使用合并数组会更方便。如:可能需要以字节或字为单元对存储单元进行操作。图2.3中所示的barray可以满足这一要求。任何数组类型都可以合并,包括动态数组、队列和关联数组,2.3-2.5节中会有进一步介绍。

如果需要等待数组中的变化,则必须使用合并数组。当测试平台需要通过存储器数据的变化来唤醒时,有@操作符,但这只能用于标量或者合并数组,在例2.18中,可以把1w和barray[0]用作敏感信号,但却不能用整个的barray数组,除非把它扩展成:@(barray[0] or barray[1] or barray[2])。

2.3 动态数组

前面介绍的基本的Verilog数组类型都是定宽数组,宽度在编译时就确定了。但是如果直到运行程序前还不知道数组宽度呢?System Verilog提供了动态数组类型,可以在仿真时,分配空间或调整宽度,这样在仿真中就可以使用最小的存储量。

动态数组在声明时使用空下标。说明数组的宽度在编译时不给出,而在程序运行时指定。数组开始是空的,所以必须调用new[]操作符来分配空间,同时在方括号中传递数组宽度。可以把数组名传给new[]构造符,并把已有数组的值复制到新数组里,如例2.19所示。

在例2.19中,A行调用new[5]分配了5个元素,动态数组dyn于是有了5个整型元素。B行把数组的索引值赋给相应的元素。C行分配了另一个数组并把dyn数组的元素复制进去。D行和E行显示了数组dyn和d2是相互独立的。E行首先分配了20了新元素并把原来的dyn数组复制给开始的5个元素,然后释放他原有的5个元素所占的空间,所以最终dyn指向了一个具有20个元素的数组。例2.19最后调用new[]分配了100个元素,但是并不复制原有的值,原有的20个元素随即被释放。最后H行删除了dyn数组。

系统函数$size的返回值是数组的宽度。动态数组有一些内建的子程序,例如delete和size。

如果想声明一个常数但是不想统计元素的个数,可以用动态数组并使用常量数组进行赋值。在例2.20中声明的mask数组中具有9个8bit元素,System Verilog会自动统计元素的个数,这比声明一个定宽数组然后不小心错指宽度为8好。

只要基本数据类型相同,如都是int,定宽数组和动态数组之间就可以互相赋值。在元素数目相同的情况下,可以把动态数组的值复制到定宽数组。

当你把一个定宽数组复制给一个动态数组时,System Verilog会调用构造函数new[]来分配空间并复制数值。

2.4 队列

System Verilog引进了一种新的数据类型—队列,结合了链表和数组的优点。队列和链表相似,可以在一个队列中的任何地方增加或删除元素,这类操作在性能上损失小。队列和数组相似,可以通过索引实现对任一元素的访问,而不需要像链表那样去遍历目标元素之前的所有元素。

队列的声明使用带有美元符号的下标:[$]。队列元素的标号从0到$。例2.22说明了如何在队列中增加和删除元素。队列的常量只有大括号而没有数组常量中开头的单引号。

System Verilog的队列类似于标准模板库(standard template library)中的双端队列。通过增加元素来创建队列,System Verilog会分配额外的空间以便能够迅速插入新元素。新元素增加超过原有空间的容量时,System Verilog会自动分配更多空间。其结果是可以扩大缩小队列,但是不用像动态数组那样在性能上付出很大代价,System Verilog会随时记录闲置的空间。注意不要对队列使用构造函数new[]。

我们可以使用字下标串联来替代方法。如果把$放在一个范围表达式的左边,那么$将代表最小值,例如[$:2]。如果$放在表达式右边,则代表最大值,如将例2.23中初始化的第一行里的[1:$]就表示[1:2]。

队列中的元素是连续存放的,所以在队列的前面或后面存取数据非常方便。无论队列有多大,这种操作的时间耗费是一样的。在队列的中间增加或者删除元素需要对已存在的数据进行搬移以便腾出空间。相应操作的时间耗费会随着队列的大小线性增加。

2.5 关联数组

如果只需偶尔创建一个大容量的数组,动态数组已经足够,如果需要更大的容量,System Verilog提供了关联数组类型,用来保存稀疏矩阵的元素。这意味着当对一个非常大的地址空间进行寻址时,System Verilog只为实际写入的元素分配空间。图2.4中,关联数组只保留0?3、42、1000、4521和200000等位置上的值。这样,用来存放这些值得空间比有200000个条目的定宽或动态数组所占用的空间要小很多。

仿真器可以采用树或者哈希表的形式来存放关联数组,但有一定的额外开销。当保存索引值比较分散的数组时,如使用32bits或64bits地址作为索引的数据包,这种额外开销显然是可以接受的。

关联数组采用在方括号中放置数据类型的形式来进行声明,例如[int]或[packet]。例2.24说明了关联数组的生命,初始化和遍历过程。

例2.24中的关联数组assoc具有稀疏分布的元素1,2,4,8,16等等。简单的for循环不能遍历该数组,需要使用foreach循环遍历数组。如果想控制的更好,可以在do while中使用first和next函数。这些函数可以修改索引参数的值,然后根据数组是否为空返回0或1.

和perl语言中的哈希数组相类似,关联数组也可以使用字符串索引进行寻址。例2.25