SystemVerilog学习 (9)——随机化

目录

一、概述

二、随机化

2.1、如何简单地产生一个随机数

2.1.1 利用系统函数产生随机数

2.1.2 urandom()

2.2、什么需要随机化

2.3、随机约束

2.3.1 rand 和 randc 

2.3.2 随机约束的使用

2.3.3 约束块

三、总结


一、概述

        随着设计变得越来越大,要产生一个完整的激励集来测试设计的功能也变得越来越困难了。 定向激励的测试方法早已经无法满足检查功能完整性的要求。
        解决的办法是采用受约束的随机测试法(CRT)自动产生测试集。 随机约束测试(CRT,Constrained-Random Test)即能够产生你感兴趣的、你想不到的的测试向量,通过回归测试、替换随机种子的方式来提高单位测试用例的覆盖率收集效率。
        CRT由两部分组成:使用随机的数据流为DUT 产生输入的测试代码,以及伪随机数发生器(PRNG)的种子( seed)。只要改变种子的值﹐就可以改变CRT的行为。这样仅仅通过改变种子的值,就可以调整每次测试,使得每次测试可以达到很多次定向测试的效果。这种方法还可以产生更多的和定向测试等效的测试集。
        你可能会觉得这些随机测试有点像投掷飞镖,怎么才能知道是否覆盖了设计的所有方面?通常激励空间是非常大的,以至于无法用for循环来产生各种可能的输入,所以必须采用产生子集的方式来解决这个问题。在之后的内容中,我们将会学习如何用功能覆盖率来确定验证的进度。

二、随机化

2.1、如何简单地产生一个随机数

2.1.1 利用系统函数产生随机数

         通过系统函数std::randomize()对一些变量即可完成随机化,或者理解为产生随机数并赋予这些变量 。

2.1.2 urandom()

  • $urandom(),可以生成一个32位的无符号随机数。
  • $urandom_range(maxval, minval=0),可以生成一个 maxval与minval 之间的数。

2.2、什么需要随机化

        当谈到使用随机化的方式就行验证的时候,相信大家第一时间想到地都是随机化产生地数据,这种方式看起来非常简单,只需要调用$randm()函数就实现了,但是这种方式找bug的能力非常有限,只能找到一些数据路径方面的bug,这种设计方式的本质还是基于定向测试的方法。一般来说,大型的bug都存在与控制路径中,因此,对于DUT里所有的关键点都要采用随机化的方式。随机化使得控制路径里的每一个分支都可能被测试。

        我们需要考虑设计输入的各个方能,例如:

  1. 器件配置
  2. 环境配置
  3. 原始输入数据
  4. 封装后的输入数据
  5. 协议异常
  6. 延时
  7. 事务状态
  8. 错误(error)和违规(violation)

2.3、随机约束

         比起以上我们独立地生成一些随机数,在面向DUT的随机激励发生过程中,为了符合协议、满足测试需求,我们还需要添加一些 “约束” 。 这些“约束”会使得变量朝着希望他们变化的方向去随机。 不但如此,这些约束也会对变量与变量之间的关系生效, 因此,我们需要一个“载体”去容纳这些变量以及它们之间的约束。 这个“载体”即是类,而类的成员变量均可声明为“随机”属性,用 rand或者randc来表示。

2.3.1 rand 和 randc 

  • 对于rand修饰符,表示在可生成的范围内,每个值的可能性是相同的。 
  • 对于randc修饰符,它的值将会随机并且遍历其可取值范围。

        简单说就是randc的c可以解读成cycle,使用randc的时候会循环遍历一遍所有的取值。

2.3.2 随机约束的使用

  •  任何类中的整形(bit/byte/int)变量都可以声明为 rand/randc
  •  定长数组、动态数组、关联数组和队列都可以声明为 rand/randc,可以对动态数组和队列的长度加以约束
  •  指向对象的句柄成员,也可以声明为rand(不能被声明为 randc),随机时该句柄指向对象中的随机变量也会一并被随机
  •  非组合型结构体可以声明为rand,非组合型的成员可以声明为 rand/randc

        下图给出了一个带有随机变量的简单类

2.3.3 约束块

         有用的激励不仅仅是随机值,变量之间也有着相互关系。 没有约束的随机变量会包含许多无效的和非法的值,这会使得有效激励的产生变得低效。因此,我们 需要用包含一个或多个约束表达式的约束块定义这些相互关系。

         约束块支持整形通过set操作符来设置它们的可取值范围

rand integer x, y, z; 
constraint c1 {x inside {3, 5, [9:15], [24:32], [y:2*y], z};} 

rand integer a, b, c; 
constraint c2 {a inside {b, c};} 

integer fives[4] = '{ 5, 10, 15, 20 }; 
rand integer v; 
constraint c3 { v inside {fives}; }

        此外, 除了成员集合设置,约束块也支持设置可取值的同时也为其设置随机时的权重。 

  • 对于:=操作符,它们表示每一个值的权重是相同的; 
  • 对于:/操作符,它们表示权重会平均分配到每一个值。 

         unique可以用来约束一组变量,使得其在随机后变量之间不会有相同的数值。还有的地方可以使用if-else或者->操作符来表示条件约束; foreach可以用来迭代约束数组中的元素,这些数组可以是定长数组、动态数组、关联数组或者队列。

         在没有soft描述时的约束,我们称之为硬约束,而带有soft描述的则是软约束。软约束用来指定变量的默认值和权重。如果用户在使用时,指定了外部约束对同一个变量做二次约束,或者用 户定义了子类,也对同一个变量做二次约束时,那么硬约束可以“覆盖” 软约束,并且不会导致随机数产生的失败。

三、总结

        CRT是产生验证复杂设计所需激励的唯一可行的方法。SystemVerilog 提供了很多种产生随机激励的方法,本章展示了其中的一些实现方法。
        测试必须是灵活的,允许你既可以使用产生的缺省值,也可以约束或修改缺省值以实现最终目标。在建立测试平台前务必事先规划,留出足够的“钩子",这样才能在不修改现有代码的情况下控制测试平台。

### 实现 SystemVerilog 中浮点数的随机化SystemVerilog 中处理浮点数的随机化可以通过使用 `real` 类型变量并结合约束条件来完成。为了确保生成有效的浮点数值,可以利用内置的数据类型转换以及随机化机制。 下面是一个简单的例子展示如何在一个类中定义带有随机属性的浮点成员: ```systemverilog class FloatRandomizer; real float_value; // 构造函数初始化对象 function new(); this.float_value = 0.0; endfunction // 定义随机化方法 function void randomize_float(int min_exponent=-127, int max_exponent=128); bit [63:0] bits; // 创建一个范围内的指数部分 randcase 1 : begin bits[62:52] = $urandom_range(min_exponent + 1023, max_exponent + 1023); end default : ; endcase // 设置符号位为正或负 bits[63] = $random() % 2; // 填充尾数部分(假设规范化) for (int i = 51; i >= 0; i--) { bits[i] = $random() % 2; } // 将比特串转回成实数形式 this.float_value = $bitstobits(real'(bits)); endfunction endclass ``` 此代码片段展示了通过设置 IEEE 754 标准下的二进制表示法中的各个字段——符号、指数和尾数——来自动生成合法的双精度浮点数[^1]。请注意,在实际应用中可能还需要考虑特殊值如 NaNs 和无穷大等情况。 对于更复杂的场景,比如需要满足特定分布的概率密度函数(PDF),则建议采用第三方库或者工具支持更为精确地控制随机过程。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

apple_ttt

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

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

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

打赏作者

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

抵扣说明:

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

余额充值