systemverilog--动态数组、关联数组和队列的区别
动态数组
动态数组,和名字的字面解释一样,可以动态调整空间大小的数组,动态数组在编译时不指定空间的大小,只有在程序运行是才分配空间,这也就要求在代码中需要 new[ ] 来设定动态数组的空间大小。
1.1 动态数组的声明方法:
data_type array_name [];
1.2 动态数组的三种内置方法:
new[]操作符用来设置或改变数组的尺寸。
integer addr[]; // 声明动态数组 addr = new[100]; // 产生具有100个元素的数组 ... // 加倍数组的尺寸,但保留以前的值。 addr = new[200](addr);
size()内建方法返回数组的当前尺寸。
int j = addr.size; addr = new[addr.size()*4] (addr); // 将addr数组的尺寸扩大为4倍
delete()内建方法清空数组的所有元素以便产生一个空数组(零尺寸)。
int ab [] = new[N]; // 产生一个尺寸为N的临时数组 // 使用ab ab.delete; // 删除数据内容 $display("%d", ab.size); // 打印0
1.3动态数组的使用示例:
int dyn[], d2[]; //声明动态数组 initial begin dyn = new[5]; //分配5个元素的空间内存 foreach(dyn[j]) dyn[j] = j;//对元素进行初始化 d2 = dyn; //复制一个动态数组,这是d2会自动调用new函数 d2[0] = 5; //修改复制值 $display(dyn[0],d2[0]); //显示数字(0和5) dyn = new[20](dyn); //分配20个整数值并进行复制 dyn = new[100]; //分配100个新的整数值,旧值不复存在 dyn = dyn.delete(); //删除所有元素,此时数组大小为0 end
关联数组
关联数组:保存稀疏型的数据。与其他数组不同的是,关联数组有利于使用零散的存储空间,如下图所示,关联数组存储数据并不是连续的存储空间。当集合的尺寸是未知的或者数据空间紧缺的时候,联合数组则是更好的选择。联合数组在使用之前不会分配任何存储空间,并且索引表达式不再被限制成integral表达式,而是可以具有任何数据类型。
2.1关联数组的声明:
integer i_array[*]; // 整数关联数组(未指定索引) bit [20:0] array_b[string]; // 21位向量的关联数组,使用字符串类型作为索引 event ev_array[myClass]; // 事件类型的关联数组,使用类myClass索引
2.2关联数组的内置方法:
num()方法返回关联数组中条目的数目。如果数组是空数组,那么它返回0。
int imem[*]; imem[2'b3] = 1; imem[16'hffff] = 2; imem[4'b1000] = 3; $display("%0d entries\n", imem.num); // 打印"3 entries"
delete()方法删除特定索引的条目。如果试图删除的条目不存在,该方法不会发布警告信息。 如果没有指定索引,delete()方法删除数组的所有元素。
int map[string]; map["hello"] = 1; map["sad"] = 2; map["world"] = 3; map.delete("sad"); // 从"map"中删除索引为"sad"的条目 map.delete; // 删除关联数组"map"中的所有条目
exists()函数检查对于指定数组中是否存在指定索引的元素。如果元素存在则返回1,否则返回0。
if (map.exists("hello")) map["hello"] += 1; else map["hello"] = 0;
first()方法将指定的索引变量赋值为关联数组中第一个(最小的)索引的值。如果数组是空的则返回0,否则返回1。
string s; if (map.first(s)) $display("First entry is : map[%s] = %0d\n", s, map[s]);
last()方法将指定的索引变量赋值为关联数组中最后一个(最大的)索引的值。如果数组是空的则返回0,否则返回1。
string s; if (map.last(s)) $display("Last entry is : map[%s] = %0d\n", s, map[s]);
next()方法寻找索引值大于指定索引的条目。如果存在下一个条目,索引变量被赋值为下一个条目的索引,并且函数返回1。否则,索引不会发生变化,函数返回0。
string s; if (map.first(s)) do $display("%s : %d\n", s, map[s]); while (map.next(s));
prev()函数寻找索引小于指定索引的条目。如果存在前一个条目,索引变量被赋值为前一个条目的索引,并且函数返回1。否则,索引不会发生变化,并且函数返回0。
string s; if (map.last(s)) do $display("%s : %d\n", s, map[s]); while (map.prev(s));
2.3关联数组使用示例:
initial begin bit [63:0] assoc[int],idx =1; // Initialize widely scatteredvalues repeat (64) begin assoc[idx] =idx; idx = idx << 1; end // Step through all index values withforeach foreach (assoc[i]) $display("assoc[%h]= %h", i, assoc[i]); // Step through all index values withfunctions if (assoc.first(idx)) begin // Get first index do $display("assoc[%h]=%h",idx, assoc[idx]); while (assoc.next(idx)); // Get next index end // Find and delete the first element assoc.first(idx); assoc.delete(idx); $display("The array now has %0delements", assoc.num); end
队列
队列是一个相同元素的可变尺寸的有序集合。队列能够以常量时间访问它的所有元素,也能够以常量时间在队列的尾部和头部插入和删除元素。队列中的每一个元素都通过一个序号来标识,这个序号代表了元素在队列内的位置,0代表第一个元素,$代表最后一个元素。队列类似于一个一维的非压缩数组,它可以自动地增长和缩减。因此,与数组一样,队列可以使用索引、串联、分片、相等操作符进行处理。
3.1队列的声明
byte q1[$]; // 一个字节队列 string names[$] = {"Bob"}; // 具有一个元素的字符串队列 integer Q[$] = {3, 2, 7}; // 一个被初始化成三个元素的整数队列 bit q2[$:255]; // 一个最大尺寸为256的位队列
3.2队列的内置方法
size()方法返回队列中元素的数目。如果队列是空的,它返回0。
for (int j=0; j<q.size; j++) $display(q[j]);
insert()方法在指定的索引位置插入指定的元素。
Q.insert(i, e)等效于Q = {Q[0:i-1], e, Q[i,$]}
delete()方法删除指定索引位置的元素。
Q.delete(i)等价于Q = {Q[0:i-1], Q[i+1,$]}
pop_front()方法删除并返回队列的第一个元素。
e = Q.pop_front()等价于:e = Q[0]; Q = Q[1,$]
pop_back()方法删除并返回队列的最后一个元素。
e = Q.pop_back()等价于:e = Q[$]; Q = Q[0,$-1]
push_front()方法在队列的前端插入指定的元素。
Q.push_front(e)等价于:Q = {e, Q}
push_back()方法在队列的尾部插入指定的元素。
Q.push_back(e)等价于:Q = {Q, e}
3.3队列的使用示例:
int j = 1; int q[$] = {3,4}; //队列的常量不需要使用单引号' int q2[$]= {0,2,5}; initial begin q2.insert(1,j); //{0,1,2,5}在2之前插入1 q2.insert(3,q); //{0,1,2,3,4,5}在q2中插入一个队列 q2.delete(1); //{0,2,3,4,5}删除第一个元素 //下面的操作执行速度很快 q.push_front(6);//{6,0,2,3,4,5}在队列前面插入 j = q.pop_back; //{6,0,2,3,4} j = 5 q.push_back(8); //{6,0,2,3,4,8}在队列末尾插入 j = q.pop_front;//{0,2,3,4,8} j = 6 foreach(q[i])begin $display(q[i]); end q.delete(); //{}删除整个队列