0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

带你了解SystemVerilog中的关联数组

sanyue7758 来源:硅芯思见 2023-06-09 09:46 次阅读

在SystemVerilog中,我们知道可以使用动态数组实现数组元素个数的动态分配,即随用随分,其中元素在数组中的索引是连续的,但是如果要实现数组元素访问时不采用连续索引的话,采用动态数组和定宽数组就不是很合适,容易造成空间的浪费,为此在SystemVerilog中引入了关联数组(Associative Array),实现了一种查找表,该查找表的索引可以根据用户需要指定,不限于整形,其内存空间直到使用时才会分配,即只针对写入的元素分配存储空间,其使用方式类似于Perl等其他语言中的哈希结构

关联数组与其他数组表面上的不同主要体现在数组的索引上,非关联数组的索引一般都是整型变量,而关联数组的索引可以是任何的数据类型。

下面我们将通过示例说明关联数组是如何定义和常用的方法如何使用。

1 关联数组的声明格式

关联数组采用在方括号中放置数据类型的形式来进行声明,其格式如下:

data_type array_name [index_type];

其中

data_type :指定的是数组成员数据类型,可以是定宽数组允许的任何类型;

array_name:指定关联数组的名字,符合标识符命名规则,当然每个公司命名规范可能不一样;

index_type:关联数组索引的数据类型,如果指定了索引数据类型,那么对于数组元素访问时索引就必须要匹配指定的索引数据类型。同时索引的类型也可以使用通配符,此时对于同一数组中元素索引时,索引的数据类型就可以不一样;

下面主要针对不同的index_type和关联数组中常用到的方法进行示例说明。

2 关联数组不同的索引类型

2.1 index_type为string

【示例】

44f5ea0c-0610-11ee-962d-dac502259ad0.png

仿真结果】

451491c8-0610-11ee-962d-dac502259ad0.png

示例中定义了两个数组,arr1数组的索引类型为string,数组中每个元素的类型为int,再给arr1初始化时,通过“键:值对”实现对应元素的初始化,arr1[First]的值为’hAB,arr2[Second]的值为’hCD,在访问arr1中的元素时,也可以如示例中通过索引“First”和“Second”来访问。通过该示例,对于关联数组中特定索引元素的空间分配赋值可以通过{index:value} 方式实现。

2.2 index_type为class

【示例】

45250c1a-0610-11ee-962d-dac502259ad0.png

【仿真结果】

45425216-0610-11ee-962d-dac502259ad0.png

示例中,声明的关联数组arr的索引类型为packet(class),packet声明了三个句柄,pkt1和pkt2都指向了创建的对象,pkt3为空句柄null,通过数组名.[句柄]的方式实现了对于特定句柄作为索引的数组元素的赋值操作。示例中,通过foreach遍历数组中所有元素,通过仿真结果可以看到其中所有的赋值操作都赋值成功。这里有一点需要注意,尽管句柄pkt3为null,对其的赋值操作仍然是成功的,但是需要注意的是,如果再声明一个pkt4空句柄,并且在“arr[pkt3] = ‘hC”之后给arr[pkt4]赋值为”’hD”,那么对arr[pkt3]中的值将会被覆盖掉,这是因为pkt3和pkt4的值相同都是null,所以后续如果进行对数组的遍历访问操作,访问的结果还是只能访问到三个元素,而不是四个,即对于索引类型为class的关联数组,关联数组的索引句柄可以为null,且所有句柄值为null的数组元素指向同一个值。同时通过示例注意到,关联数组中元素在使用foreach进行遍历时,并不是按照数组元素初始化的顺序进行输出的,而是根据索引类型排列相对顺序的。

2.3 index_type不能为4值逻辑变量

【示例】

455346c0-0610-11ee-962d-dac502259ad0.png

【仿真结果】

4568ddd2-0610-11ee-962d-dac502259ad0.png

示例中,L4_type为自定义的两位logic类型,因为logic具有(0、1、x、z四种),数组arr的索引类型使用的就是L4_type,在给数组中元素进行初始化时,使用“2’hx”和“2’hz”作为索引,此时进行仿真时会产生提示信息(不同仿真工具产生的信息级别不同),通过foreach遍历数组,数组中并不包含对于索引为“2’hx”和“2’hz”的数组元素,即关联数组的数组索引不能为“x”和“z”

2.4 index_type为*

如果index_type没有指定类型,而是使用通配符“*”时,虽然貌似通配符可以匹配任何类型,但是在SystemVerilog中,此时的“通配符*”只能匹配任何的integral数据类型(参见IEEE1800-2017 6.11),对于其他非integral类型不能用于匹配!

【示例】

457a2916-0610-11ee-962d-dac502259ad0.png

【仿真结果】

4595de54-0610-11ee-962d-dac502259ad0.png

示例中,关联数组arr声明索引类型时使用了“*”,在initial块中,将句柄pkt作为数组的索引进行赋值操作。对上述代码编译时仿真器报错,这主要是因为class不属于SystemVerilog中定义的integral类型。那么index_type为“*”的关联数组中索引的类型是不是必须要一致呢?看下例。

【示例】

45aa2f80-0610-11ee-962d-dac502259ad0.png

【仿真结果】

45b9e8da-0610-11ee-962d-dac502259ad0.png

示例中,关联数组arr在声明时index_type为“*”,并且在通过不同类型的索引对数组arr中相应元素进行了赋值操作,并且将这些元素通过不同类型的索引都打印了出了。虽然这些索引的类型不同,但是这些类型有一个共同点都属于SystemVerilog中的integral类型,可见关联数组的索引如果为“*”的话,在通过不同类型索引给数组元素赋值时,这些索引必须都是integral类型。

其实从一个侧面可以体会到,SystemVerilog中所有的integral类型在某种程度上可以相互转换,类似于C语言中的不同数据类型之间的自动转换一样。另外,可能有人会问,为什么对于这个数组打印消息是不使用foreach结构呢?请看下例。

【示例】不能使用foreach结构

45c96f4e-0610-11ee-962d-dac502259ad0.png

【仿真结果】

45dd6724-0610-11ee-962d-dac502259ad0.png

示例中,关联数组arr声明时其中index_type使用了“*”,然后给arr中相关元素通过不同的索引类型进行了赋值初始化操作,最后企图使用foreach遍历arr时报错,正如报错信息显示,当关联数组声明时索引为“*”,那么该数组不能使用使用foreach对该数组进行遍历

3 关联数组常用方法

关联数组中在使用时常会使用一些内建的方法,这些常用的方法如下表所示,

方法名 作用
num()/size() functionint num();
function int size();
返回当前数组元素个数
delete(index) function void delete([input index]);
删除指定索引的数组元素
exists(index) function int exists(input index);
检查指定索引的数组元素是否存在,如果存在返回1,否则为0
first(var) function int first(ref index);
将数组第一个元素的索引赋给变量var
last(var) function int last(ref index);
将数组最后一个元素的索引赋给变量var
next(var) function int next(ref index);
将数组当前元素的下一个元素的索引赋给变量var
prev(var) function int prev(ref index);
将数组当前元素的上一个元素的索引赋给变量var

那么,关联数组的这些方法如何使用呢?下面通过示例了解下。

【示例】num(),exists(),delete(index)

45f7d6e0-0610-11ee-962d-dac502259ad0.png

【仿真结果】

461d17d4-0610-11ee-962d-dac502259ad0.png

示例中,通过“数组名.num()”的方式获取到当前数组中元素的个数。然后通过foreach遍历了数组中所有的元素。通过“数组名.exists(索引号)”的方式,可以检测数组中是否存在指定索引的元素。

当通过“数组名.delete(索引号)”的方式可以删除数组中指定索引号的数组元素,示例中通过arr.delete(1)删除了数组中索引号为“1”的元素后,再次调用arr.exists(1)检查数组中是否还存在索引号为“1”的元素,通过仿真结果可以看到,数组中索引号为“1”的元素已经被删除。

这里需要注意,示例中使用的三个方法的格式分别是:“数组名.num()”、“数组名.exists(索引号)”和“数组名.delete(索引序号)”,其中delete后也可以不带索引号,此时将会将整个数组“清空”!另外,在使用时一定要注意,关联数组如果不对其进行任何有效写入时,数组的大小时为0。、,即关联数组在使用之前是不会耗费存储空间的。

【示例】first(),next()

4629e662-0610-11ee-962d-dac502259ad0.png

【仿真结果】

464b8452-0610-11ee-962d-dac502259ad0.png

示例中,在initial过程块中,首先通过“数组名.first(变量名)”的方式将数组arr中第一个(最小)索引的值赋给给定的索引变量temp(注意变量类型与数组索引类型一致),但是此时arr中没有任何元素,所以此时通过数组名调用“arr.first(temp)”方法返回0,即输出“1st entry does not exist!”。

通过for循环对数组进行初始化,之后再次“arr.first(temp)”,因为数组中有元素,所以first()方法返回非零,同时将初始化后数组中第一个(最小)索引赋值给temp。

然后通过“arr.next(temp)”获取比给定的索引值(temp)大的最小索引值,如果存在下一项,则将下一项的索引赋给索引变量temp,因为给定的temp此时值为0,所以next()方法调用后,将数组下一个元素的索引赋给了变量temp,所以仿真结果此时输出temp值变为了1.示例的最后do...while()循环将first()和next()配合使用,有效地遍历数组。

这里需要注意,示例中使用的方法的格式分别是:“数组名.first(索引变量)”和“数组名.next(索引变量)”。

【示例】

465dbba4-0610-11ee-962d-dac502259ad0.png

【仿真结果】

467c2396-0610-11ee-962d-dac502259ad0.png

示例中,在initial过程块中,首先通过for循环对数组进行初始化,之后执行“arr.last(temp)”,因为数组中有元素,所以last()方法返回非零,同时将初始化后数组中最后(最大)索引赋值给temp。

然后通过“arr.prev(temp)”获取比给定的索引值(temp)小的最大索引值,如果存在上一项,则将上一项的索引赋给索引变量temp,因为调用last(temp)方法后给temp的值为3,所以prev()方法调用后,将数组上一个元素的索引赋给了变量temp,所以仿真结果此时输出索引为temp的数组元素的值输出.示例的最后将last()和prev()配合使用可以有效地遍历数组

这里需要注意,示例中使用的方法的格式分别是:“数组名.last(索引变量)”和“数组名.prev(索引变量)”。

上述first()、next()、last()和prev()这些方法在使用的时候一定要注意,如果关联数组索引类型为“*”的话,这些方法不能使用。





审核编辑:刘清

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 仿真器
    +关注

    关注

    14

    文章

    988

    浏览量

    82998
  • Verilog
    +关注

    关注

    28

    文章

    1327

    浏览量

    109312
  • C语言
    +关注

    关注

    180

    文章

    7534

    浏览量

    128835

原文标题:敲黑板,带你了解SystemVerilog中的关联数组

文章出处:【微信号:处芯积律,微信公众号:处芯积律】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    转一篇Systemverilog的一个牛人总结

    () ;//释放空间l 队列在队列增加或删除元素比较方便。l 关联数组当你需要建立一个超大容量的数组关联数组,存放稀疏矩阵的值。表示方
    发表于 08-27 14:50

    求职宝典:寒武纪2019笔试题

    。(2)动态数组:可以在仿真时分配空间或者调整宽度,这样在仿真中就可以使用最小的存储量。在声明时,其下标为空[ ],使用new[ ]操作符来分配空间。(3)关联数组SystemVerilog提供
    发表于 12-24 11:55

    PHP数组排序

    数组排序(6个) sort() - 以升序对数组排序rsort() - 以降序对数组排序 reversal sort)asort() - 根据值,以升序对关联数组进行排序(associ
    发表于 11-04 07:48

    基于本体的软件工程关联数据的自动构建

    针对目前在分布异构的大规模软件开发中难以高效地知晓信息和发现知识的问题,将语义网引入软件工程领域,对多源异构数据进行细粒度语义关联,提出本体构建、关联抽取和发现的方法,实现基于本体的软件工程关联数
    发表于 12-22 17:03 0次下载
    基于本体的软件工程<b class='flag-5'>关联数</b>据的自动构建

    带你深入了解示波器

    带你深入了解示波器
    发表于 02-07 14:26 18次下载

    物联网是什么,一文带你了解物联网

    一篇文章带你了解物联网
    的头像 发表于 03-23 14:16 3373次阅读

    SystemVerilog数组的赋值、索引和切片

    数组可以作为参数传递给子程序,当数组作为值传递给子程序时,会将这个数组复制一份传递给子程序。
    的头像 发表于 10-20 10:13 3913次阅读

    SystemVerilog中的操作方法

    SystemVerilog提供了几个内置方法来支持数组搜索、排序等功能。
    的头像 发表于 10-31 10:10 1841次阅读

    SystemVerilog中的关联数组

    关联数组实际上是一种查找表,内存空间直到被使用时才会分配,每个数据项都会有一个特定的“键(索引)”,索引的类型不局限于整型。
    的头像 发表于 10-31 10:12 2745次阅读

    SystemVerilog中可以嵌套的数据结构

    SystemVerilog中除了数组、队列和关联数组等数据结构,这些数据结构还可以嵌套。
    的头像 发表于 11-03 09:59 1229次阅读

    网络和变量的未压缩数组

    SystemVerilog有两种类型的数组:压缩数组和非压缩数组。压缩数组是连续存储的位的集合,通常称为向量。非压缩
    的头像 发表于 02-09 14:50 497次阅读
    网络和变量的未压缩<b class='flag-5'>数组</b>

    使用SystemVerilog解决数组问题

    数独是一种非常流行的游戏,数独本质上也是一个约束问题,所以我们可以让SystemVerilog的约束求解器来帮助我们解决。 约束求解器的精妙之处就是,我们只描述约束限制,繁重的数值生成工作由工具来帮我们完成。 你只需“既要...又要...”,其他的让下人干吧。
    的头像 发表于 03-08 14:06 975次阅读

    一些有趣的数组相关的SystemVerilog约束

    我们在工作中常常会针对数组施加各式的约束,下面列举一下有趣的Systemverilog数组约束示例。
    的头像 发表于 03-08 13:12 625次阅读

    一些有趣的数组相关的SystemVerilog约束

    我们在工作中常常会针对数组施加各式的约束,下面列举一下有趣的**Systemverilog数组约束**示例
    的头像 发表于 05-30 11:13 451次阅读

    随机抽取SV数组中的一个元素方法实现

    如果想从一个关联数组中随机选取一个元素,需要逐个访问它之前的元素,原因是没办法能够直接访问到第N个元素。上面的程序示范了如何从一个以整数值作为索引**的关联数组中随机选取一个元素。
    的头像 发表于 03-21 10:11 161次阅读
    随机抽取SV<b class='flag-5'>数组</b>中的一个元素方法实现