验证基础-随机约束与随机控制

目录​​​​​​​

随机约束和分布

约束

权重分布

约束块控制

内嵌约束

随机函数

数组约束

随机控制


随机约束和分布

        随着芯片体积增大、复杂度提高,定向测试已经无法满足验证的需求,随机测试的比例逐渐升高。定向测试能找到你认为可能存在的缺陷,而随机测试可以找到你想都没想到的缺陷。

        随机测试的环境要求比定向测试复杂,它除了需要激励,还需要参考模型在线比较,上百次的仿真不需要人为参与,它可以减少相当的代码,产生的激励也较定向测试更多样

        随机的约束不但可以指定数据的取值范围,还可以指定各个数值的随机权重分布

那么一般可以随机什么东西呢?

        1.器件配置:配置寄存器的值和系统信号。

        2.环境配置:随机化验证环境,例如合理的时钟和外部反馈信号。

        3.原始输入数据:例如数据包的长度、带宽,数据间的顺序。

        4.延时:握手信号之间的时序关系,例如 valid 和 ready ,req 和 ack 之间的时序关系。

        5.协议异常:如果反馈信号给出异常值,那么设计是否可以保持后续数据处理的稳定性呢?

        随机属性的声明,一般使用 rand 或者 randc 来表示它的随机属性,randc 和rand 的区别在于,randc 表示周期性的随机,即所有可能的值都赋过值后随机值才能重复。要注意 randrandc 使用的对象必须是类的成员变量,不能是静态变量。随机属性需要配合SV预定义的类随机函数 std::randomize() 使用。即只有通过声明rand变量,并且在后期通过对象调用randomize() 函数才可以随机化变量。约束 constraint 也同随机变量一起在类中声明。

        如上图,在定义类Packet的时候,给类中的成员变量下了rand和randc的属性声明,下随机声明的时候,通常还要伴随约束,也就是后面的constraint。Packet类里面没有new函数,这个是允许的,在类声明的时候没有内置new函数的时候系统会默认在new类时,给类里面的所有成员变量赋初值0。Packet p 这条语句不是创建一个对象 而是声明一个类的句柄,在initial语句块里面的p = new()才是创建了一个对象

        randomize()是一个随机函数,为类里所有的rand和randc类型的随机变量赋一个随机值,并且保证不违背所有有效的约束,随机成功了函数返回1,随机失败了返回0。

约束

        约束表达式的求解是由SV的约束求解器(constraintsolver)完成的。

        求解器能够选择满足约束的值,这个值是由SV的PRNG(伪随机数发生器 Pseudo random number generator)从一个初始值(seed)产生。只要改变种子的值,就可以改变CRT的行为。

        什么可以被约束?SV只能随机化2值数据类型, 但位可以是2值或者4值。这就是说,无法随机出X值和值,也无法随机化字符串。

        上面这个例子里,类Stim中,只有枚举类型 kind 和三个bit类型的len src和dst是随机的。其他都不是随机的。这里面 变量congestion_test不是随机的,所以我们可以通过外部控制congestion_test变量的取值来改变类内部随机变量的约束取值范围。

权重分布

        关键词 dist 可以在约束中用来产生随机数值的权重分布,这样某些值的选取机会要比其他值更大一些。dist 操作符带有一个值的列表以及相应的权重,中间用:=或者:/分开。值或权重可以是常数或者是变量。权重不用百分数表示,权重的和也不必是100。:=操作符表示值范围内的每一个值的权重是相同的。:/操作符表示权重要平均到值范围内的每一个值

        如下面例子解释: 

        inside 是常见的约束运算符,表示变量应该属于某一个值的集合,除非还存在其它约束,否则随机变量在集合里取值的概率是相等的。集合里也可以使用变量。

        还可以通过->或者if-else来让一个约束表达式在特定条件下有效。 

        我们要知道,约束块不像自上向下执行的程序性代码,它们是声明性的代码,是并行的,所有的约束表达式同时有效

        如果父类里面有约束,子类里面也有约束,并且子类继承了父类,那么在对子类里的变量进行随机化操作的时候,随机出来的变量既会满足子类里的约束也会满足父类里的约束条件

约束块控制

        一个类可以包含多个约束块。可以把不同约束块用于不同测试。使用constraint_mode()函数来控制。

        一般情况下,各个约束块之间的约束内容是互相协调不违背的,因此通过随机函数产生随机数可以找到合适的解。

        对于其它情况,例如根据不同需要,来选择使用哪些约束块,禁止哪些约束块的要求,可以使用内建的 constraint_mode( ) 函数打开或者关闭。可以用 handle.constraint.contraint_mode( ) 控制一个约束块,用handle.constraint_mode()控制对象的所有约束。

内嵌约束

        伴随着复杂的约束,它们之间会相互作用,最终产生难以预测的结果,用来使能和禁止这些约束的代码也会增加测试的复杂性。

        SV允许使用randomize() with 来增加额外的约束这和在类里增加约束是等效的。 

        在类里面约束块中,对地址的约束前面有一个关键词soft,代表该对地址的约束属于一个软约束,当外部的约束和该约束冲突的时候,取外面的约束有效。

随机函数

        有时需要在调用randomize()之前或之后立即执行一些操作,例如在随机前设置类例的一些非随机变量(上下限、条件值、权重),或者在随机化之后需要计算随机数据的误差、分析和记录随机数据等。

        SV提供了两个预定义的 void 类型函数 pre_randomize()  post_randomize() 函数。用户可以在类中定义这两个函数,分别在其中定义随机化前的行为和随机化后的行为。如果某个类中定义了 pre_randomize() 或者 post_randomize() 函数,那么对象在执行了randomize()之前或者之后会分别执行这两个函数。可以把这两个函数认为是 randomize() 函数的回调函数(callback function)

SV提供了一些常用的系统随机函数,这些随机函数可以直接调用来返回随机值。

        ※ $random( ) 平均分布,返回32位有符号随机数。

        ※ $urandom( ) 平均分布,返回32位无符号随机数。

        ※ $urandom_range( A,B) 在指定范围内的平均分布。

        在调用randomize( )时可以传递变量的一个子集,这样只随机化类里的几个变量。只有参数列表里的变量才会被随机化,其它变量会被当做状态变量而不会被随机化

        这里要注意的是:这种应用针对的是类里所有被指定或者没有被指定rand的变量都可以作为randomize()的参数而被随机化。 

数组约束

        约束动态数组的大小: 

多数情况下,数组的大小应该给定范围,防止生成过大体积的数组或者空数组。

        SV可以利用foreach对数组的每一个元素进行约束,和直接写出对固定大小数组的每一个元素的约束相比,foreach更加简洁。针对动态数组,foreach更适合于非固定大小数组中每个元素的约束。

         使用foreach产生递增的数组元素的值: 

        产生具有唯一元素值的数组:

        产生随机数组的元素:

        在上面的例子中,array[]是一个存放句柄的动态数组,function new函数的目的,就是让动态数组中的每个元素的句柄,都有指向对象,这样在随机化ra的时候,随机操作传递到对array随机,然后因为array数组里的句柄都有指向的对象,对象里面的变量也是有rand属性的,再对其进行随机。如果没有这么一个new操作,那么array数组中存放的句柄没有指向对象,也就是悬空状态,那么在randomize的时候,就会报错,因为句柄悬空,没有对象可以随机。

随机控制

        随机序列,产生事务序列的一个方法是使用SV的randsequence结构。

        stream是这个序列的入口,先进入stream,进入之后,会根据cfg_read(1/8权重)、io_read(2/8权重)、mem_read(5/8)的权重不同来进入不同的序列语句。安排随机序列。randsequence除了可以产生一个随机的过程以外,还能生成一个比较复杂的随机序列。

使用 randcase 来建立随机决策树。

        randsequencerandcase是针对轻量级的随机控制的应用。而我们可以通过定义随机类来取代上述随机控制的功能,并且由于类的继承性使得后期代码的维护更加方便。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

不吃葱的酸菜鱼

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

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

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

打赏作者

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

抵扣说明:

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

余额充值