SystemVerilog: 动态数组

目录

 

1. 概要

2. 动态数组的声明

 3. 内存分配和初始化

4. 容量扩张

5. 动态数组的复制

6. 动态数组的删除

7. 代码例


1. 概要

        动态数组(Dynamic array),顾名思义,是一种其大小可以在运行中动态改变的非合并数组(unpacked array)。与之相对的是静态数组(Static array)的大小必须在变量声明时就固定下来,在运行时是不能改变的。由于这一根本特征的差异,两者的用途也截然不同。

        从内存分配的角度来看,静态数组的大小由于是从一开始就固定下来的,所以是在静态存储区(即所谓的栈)进行分配的,而动态数组由于是需要动态可变,因此是在堆(heap)中进行分配的(待确认)。

        动态数组只能有一个维度,而且不能被合并(can not be packed),换句话说只能是非合并数组。

        对动态数组的访问如果越界的话会导致运行时错误(run time error)。

        动态数组有以下三种方法(method):

  1. new[]
  2. size()
  3. delete()

2. 动态数组的声明

[data_type] [identifier_name] [];

变量名之后的’[]’就表示这个变量代表一个动态数组。变量名之前则为所存储的数据类型。例:

Bit[7:0] stack[];  // A dynamic array, whose element represents one byte

String names[];  // A dynamic array, whose element represents one string

 3. 内存分配和初始化

        动态数组在声明之后还没有真正分配内存,或者说此时它的容量大小为0。

        有两种分配内存的方法。

        第一种是调用new()方法,调用new()方法虽然分配了内存但是没有对内存进行初始化;

        第二种是利用列表直接进行初始化,当然其中已经隐含了内存分配

//declaration
bit [7:0] d_array1[];
int d_array2[];

//memory allocation
d_array1 = new[4]; //dynamic array of 4 elements
d_array2 = new[6]; //dynamic array of 6 elements

//array initialization
d_array1 = {0,1,2,3};
foreach(d_array2[j]) d_array2[j] = j;

        一个动态数组变量可以随时基于以上两种方法进行重新内存分配和初始化,如下节所示。

4. 容量扩张

//Change the length of the array after declaration/initialization
d_array1 = new[10]; //dynamic array of 10 elements

        以上语句中d_array1被重新分配了10个地址空间,d_array1中原有的数据被扔掉了。

        当然,用以下形式调用new()的话可以在扩充容量的同时保留d_array1中原有的数据.

//Allocate 6 new elements and retain values of 4 elements.
d_array1 = new[10](d_array1);

5. 动态数组的复制

        动态数组的复制的语法形式与上一节的扩容且保留原数据的调用方法相同,只不过生成的内存块赋给了新的一个变量。以下语句创建了d_array1的一个副本。

d_array2 = new[d_array1.size()](d_array1);

 

6. 动态数组的删除

         与C++中一样,用new()创建的动态数组需要用delete()方法进行删除。如果忘记了删除的话,会导致预料不到的内存泄漏,甚至会导致程序因为内存用量overflow而崩溃。因此,一个良好的习惯是,在不再需要的时候用delete()删除掉用new()创建的东西。

7. 代码例

module example;

reg [31:0] regArray_1[];
reg [31:0] regArray_2[];
reg [31:0] regArray_3[];
string names[];
  
initial
begin
    
    dynarray_init();    #100;    
    dynarray_copy();    #100;    
    dynarray_resize();  #100;    
    

    regArray_1.delete(); // Deleting all the elements of regArray_1, 
    // Display the size of the array after deletion
    $display ("\nSize of the regArray_1 after deletion-becoming 0-size array = %d",regArray_1.size());

    // Dynamic array for storing strings
    names = '{"systemverilog", "matlab", "python", "c++"};
    foreach(names[j]) begin
        $display ("names[%g] = %s", j, names[j]);
    end    
    
    #100 $finish;
end

task dynarray_init();

    $display("\ndynarray_initialization() ... ");

    // Declaration only doesn't allocate memory to dynamic array.
    // Currently, the above regArray has size of 0.
    $display("Before Memory Allocation");
    $display("\tSize of regArray_1 %0d",regArray_1.size());
    $display("\tSize of regArray_2 %0d",regArray_2.size());    

    // Initialization of dynamic array.
    $display ("\nDemonstrating the initialization of dynamic array ...");
    regArray_1 = '{0,1,2,3,4}; //{0,1,2,3,4} is also OK, what is the difference?
    $display("regArray_1 expected value: 0,1,2,3,4");
    foreach(regArray_1[j]) begin
        $display ("%d: %d" , j, regArray_1[j]);
    end
         
    // Re-initialize values for regArray_1
    regArray_1 = new [6];      
    $display ("\nnew() doesn’t do the value initialization...");
    for ( int i = 0 ; i < regArray_1.size(); i ++ )
        $display ("regArray_1[%g] = %d" , i, regArray_1[i]);
        
    foreach(regArray_1[j]) regArray_1[j] = j+10;
    $display("\nregArray_1 expected value: 10,11,12,13,14,15");
    for ( int i = 0 ; i < regArray_1.size(); i ++ )
        $display ("regArray_1[%g] = %d" , i, regArray_1[i]);

endtask

task dynarray_copy();

    $display("\ndynarray_copy() ... ");
    
    // copy regArray_1 to regArray_2
    regArray_2 = new[regArray_1.size()] (regArray_1);    
    $display("\nregArray_2 expected value equals to regArray_1, because it is copied from regArray_1");
    foreach(regArray_2[i])
        $display ("regArray_2[%g] = %d" , i, regArray_2[i]);

    // Another method of copy. Different from C++!
    regArray_3 = regArray_1;
        
    $display("\nregArray_3 expected value equals to regArray_1, because it is copied from regArray_1");
    foreach(regArray_3[i]) begin    
        $display ("regArray_3[%g] = %d" , i, regArray_3[i]);
    end
    regArray_3[3] = 100;
    regArray_3[5] = 1000;
    $display("\nModify regArray_3 doesn't affect regArray_1");
    foreach(regArray_3[i]) begin    
        $display ("regArray_1[%g] = %d, regArray_3[%g] = %d" , i, regArray_1[i], i, regArray_3[i]);
    end    

    $display("\nA different method to print the content of the array...");
    $display("regArray_1 = %p",regArray_1);
    $display("regArray_3 = %p",regArray_3);
    
endtask

task dynarray_resize();
    
    regArray_1 = {0,1,2,3,4}; //'{0,1,2,3,4} is also OK, what is the difference?
    $display ("\nBefore resizing...");
    foreach(regArray_1[i])
        $display ("regArray_1[%g]: %d" , i, regArray_1[i]);        
    // Resize the dynamic array, with the old contents of regArray are retained/inherited.
    regArray_1 = new[regArray_1.size() + 5](regArray_1);
    $display ("\nAfter resizing, the first 10 elements of regArray_1 are retained:");
    foreach(regArray_1[i])
        $display ("regArray_1[%g]: %d" , i, regArray_1[i]);        

endtask

endmodule

 运行后会得到结果如下所示:

dynarray_initialization() ... 
Before Memory Allocation
    Size of regArray_1 0
    Size of regArray_2 0

Demonstrating the initialization of dynamic array ...
regArray_1 expected value: 0,1,2,3,4
          0:          0
          1:          1
          2:          2
          3:          3
          4:          4

new() doesn’t do the value initialization...
regArray_1[0] =          x
regArray_1[1] =          x
regArray_1[2] =          x
regArray_1[3] =          x
regArray_1[4] =          x
regArray_1[5] =          x

regArray_1 expected value: 10,11,12,13,14,15
regArray_1[0] =         10
regArray_1[1] =         11
regArray_1[2] =         12
regArray_1[3] =         13
regArray_1[4] =         14
regArray_1[5] =         15

dynarray_copy() ... 

regArray_2 expected value equals to regArray_1, because it is copied from regArray_1
regArray_2[0] =         10
regArray_2[1] =         11
regArray_2[2] =         12
regArray_2[3] =         13
regArray_2[4] =         14
regArray_2[5] =         15

regArray_3 expected value equals to regArray_1, because it is copied from regArray_1
regArray_3[0] =         10
regArray_3[1] =         11
regArray_3[2] =         12
regArray_3[3] =         13
regArray_3[4] =         14
regArray_3[5] =         15

Modify regArray_3 doesn't affect regArray_1
regArray_1[0] =         10, regArray_3[0] =         10
regArray_1[1] =         11, regArray_3[1] =         11
regArray_1[2] =         12, regArray_3[2] =         12
regArray_1[3] =         13, regArray_3[3] =        100
regArray_1[4] =         14, regArray_3[4] =         14
regArray_1[5] =         15, regArray_3[5] =       1000

A different method to print the content of the array...
regArray_1 = '{'ha, 'hb, 'hc, 'hd, 'he, 'hf}
regArray_3 = '{'ha, 'hb, 'hc, 'h64, 'he, 'h3e8}

Before resizing...
regArray_1[0]:          0
regArray_1[1]:          1
regArray_1[2]:          2
regArray_1[3]:          3
regArray_1[4]:          4

After resizing, the first 10 elements of regArray_1 are retained:
regArray_1[0]:          0
regArray_1[1]:          1
regArray_1[2]:          2
regArray_1[3]:          3
regArray_1[4]:          4
regArray_1[5]:          x
regArray_1[6]:          x
regArray_1[7]:          x
regArray_1[8]:          x
regArray_1[9]:          x

Size of the regArray_1 after deletion-becoming 0-size array =           0
names[0] = systemverilog
names[1] = matlab
names[2] = python
names[3] = c++

 

相关文章:

SystemVerilog: 仿真验证知识点点滴滴

 

[Reference]

[1] http://www.asicguru.com/system-verilog/tutorial/dynamic-array/74/

[2] Systemverilog Dynamic Array - Verification Guide

 

 

  • 12
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
SystemVerilog的听课学习笔记,包括讲义截取、知识点记录、注意事项等细节的标注。 目录如下: 第一章 SV环境构建常识 1 1.1 数据类型 1 四、二值逻辑 4 定宽数组 9 foreach 13 动态数组 16 队列 19 关联数组 21 枚举类型 23 字符串 25 1.2 过程块和方法 27 initial和always 30 function逻辑电路 33 task时序电路 35 动态 静态变量 39 1.3 设计例化和连接 45 第二章 验证的方法 393 动态仿真 395 静态检查 397 虚拟模型 403 硬件加速 405 效能验证 408 性能验证 410 第三章 SV组件实现 99 3.1 接口 100 什么是interface 101 接口的优势 108 3.2 采样和数据驱动 112 竞争问题 113 接口中的时序块clocking 123 利于clocking的驱动 133 3.3 测试的开始和结束 136 仿真开始 139 program隐式结束 143 program显式结束 145 软件域program 147 3.4 调试方法 150 第四章 验证的计划 166 4.1 计划概述 166 4.2 计划的内容 173 4.3 计划的实现 185 4.4 计划的进程评估 194 第五章 验证的管理 277 6.1 验证的周期检查 277 6.2 管理三要素 291 6.3 验证的收敛 303 6.4 问题追踪 314 6.5 团队建设 321 6.6 验证的专业化 330 第六章 验证平台的结构 48 2.1 测试平台 49 2.2 硬件设计描述 55 MCDF接口描述 58 MCDF接口时序 62 MCDF寄存器描述 65 2.3 激励发生器 67 channel initiator 72 register initiator 73 2.4 监测器 74 2.5 比较器 81 2.6 验证结构 95 第七章 激励发生封装:类 209 5.1 概述 209 5.2 类的成员 233 5.3 类的继承 245 三种类型权限 protected/local/public 247 this super 253 成员覆盖 257 5.4 句柄的使用 263 5.5 包的使用 269 第八章 激励发生的随机化 340 7.1 随机约束和分布 340 权重分布 353 条件约束 355 7.2 约束块控制 358 7.3 随机函数 366 7.4 数组约束 373 7.5 随机控制 388 第九章 线程与通信 432 9.1 线程的使用 432 9.2 线程的控制 441 三个fork...join 443 等待衍生线程 451 停止线程disable 451 9.3 线程的通信 458 第十章 进程评估:覆盖率 495 10.1 覆盖率类型 495 10.2 功能覆盖策略 510 10.3 覆盖组 516 10.4 数据采样 524 10.5 覆盖选项 544 10.6 数据分析 550 第十一章 SV语言核心进阶 552 11.1 类型转换 552 11.2 虚方法 564 11.3 对象拷贝 575 11.4 回调函数 584 11.5 参数化的类 590 第十二章 UVM简介 392 8.2 UVM简介 414 8.3 UVM组件 420 8.4 UVM环境 425

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

笨牛慢耕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值