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();     //{}删除整个队列

 

posted @ 2021-06-23 10:15  验证cc  阅读(6090)  评论(0编辑  收藏  举报