第六章:随机化
Posted xuqing125
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第六章:随机化相关的知识,希望对你有一定的参考价值。
随着设计变得越来越复杂,要想产生一个完整的激励集来测试设计的功能也变得越来越困难。采用受约束的随机测试法(CRT)自动产生测试集是目前的一种主要的方法。CRT由两部分组成:使用随机的数据流为DUT产生输入的测试代码,以及伪随机数发生器的种子。
6.1 什么需要随机化
在产生随机化的激励时,我们最容易想到的就是使用$random函数。但是这种方法找bug的能力是十分有限的,它只能找到数据路径的问题,或者是bit级别的错误。从某种意义上讲,这种方法还是基于定向测试。那些具有挑战性的bug大都在控制路径里面。因此,必须对DUT里所有关键点都采用随机化技术。随机化使控制路径里每一个分支都可能被测试。你需要考虑设计输入下列的各个方面。
- 器件配置
- 环境配置
- 原始输入数据
- 封装后的输入数据
- 协议异常
- 延时
- 事务状态
错误和违规
6.2 SystemVerilog中的随机化
基于OOP使用SystemVerilog中的随机激励产生是最有效的。首先,建立一个具有一组相关的随机变量的类,然后用随机函数为这些变量赋随机值,你可以用约束来限制这些随机值的范围,使他们是有效的值,也可以某些专用的功能。
- rand:每次随机化这个类,这些变量都会赋一个值。就好像掷骰子,每掷一次就产生一个新的数字。
- randc:表示周期性随机。就好像从一副牌里一张一张地、随机抽出所有的牌,洗牌后再按另一个顺序随机地抽出牌。
- constraint:约束的条件放在{}里面,而不是begin---end里面。
- randomize():函数遇到约束方面的问题时,返回0.如果随机化成功则返回1.
- assert:判断随机化有没有成功。
$fatal:用来结束仿真。
注意:
1、不能在类的构造函数里随机化对象。
2、constraint中受到约束的变量必须是声明成rand或者randc类型。6.2.1 简单的表达式
在一个表达式中最多只能使用一个关系操作符。
class order; rand bit[7:0] lo,med,hi; constraint bad {lo<med<hi;} endclass
lo<med<hi会被划分成(lo<med)<hi,(lo<med)会得到一个布尔函数值0或1,然后与hi相比较。显然结果并不是我们想要的。正确的写法如下:
class order; rand bit[7:0] lo,med,hi; constraint good {lo<med; med<hi;} endclass
6.2.2 权重分布
dist操作符允许产生权重分布,这样的话某些值得选取机会就会比其他值大一些。- :=表示值范围内的每一个值得权重是相同的。
- :/表示权重要均分到值范围内的每一个值。
值可以是一个值,也可以是一个范围,例如[lo:hi]
class test; rand int src,dst; constraint c { src dist {0:=40,[1:3]:=60;} dst dist {0:/40,[1,3]:/60;} } endclass
src=0 40/220
src=1 60/220
src=2 60/220
src=3 60/220
dst=0 40/100
dst=1 20/100
dst=2 20/100
dst=3 20/1006.2.3 集合成员和inside运算符
可以用inside运算符产生一个值的集合。
class test; rand int src; constraint c { src inside {[0:3]}; } endclass
- inside {lo:hi};lo<hi,否则的话为空集;
- $,可以代表取值范围的最大值和最小值;
!取反操作符可以选取集合范围之外的数据;
6.2.4 在集合里使用数组
对数组里面的每一个值的取值的概率都相等。
6.2.5 条件约束
通常约束块里所有的约束表达式都是有效的,但怎样才能只让一个表达式在某些情况下有效呢?SystemVerilog支持两种关系操作符:->和if-else。
class BusOp; ...... constraint c {(io_space_mode) -> addr[31]==1‘b1; }
if-else并不是包含在begin-end块中,而是放在constraint的{}中。
6.2.6双向约束
约束块并不想自上而下执行的程序性代码,它们是声明性代码,是并行的,所有的约束表达式同时有效。
就算是在条件约束中,if-else语句中,并不是if中的语句成立才执行才执行下一条语句,而是所有的语句事先都已经知道。6.3 解的概率
提到随机,那么概率必然与之相随。SystemVerilog并不能保证求解器能够给出确定的解,但是我们可以干预解得概率分布。
6.4 控制多个约束块
在一个类中可以包含多个约束块。那么我们应该如何去控制这些约束呢?
在运行期间,可以使用constraint_mode()函数来打开或者关闭约束。class Test; rand int src; constraint c { src inside {[0:3]}; } constraint c_1 { dst inside {[0:3]}; } endclass Test t; initial begin t=new(); t.c.constraint_mode(0);//关闭c assert(t.randomize()); t.constraint_mode(0); //关闭所有的限制c和dst t.c_1.constraint_mode(1);//打开c_1这个约束
- t.c.constraint_mode(0);//关闭c
- t.constraint_mode(0); //关闭所有的限制c和dst
t.c_1.constraint_mode(1);//打开c_1这个约束
6.5 内嵌约束
SystemVerilog允许使用randomize()with来增加额外的约束,这和在类里增加约束是等效的。
class Test; rand int src; constraint c { src inside {[0:3]}; } endclass Test t; initial begin t=new(); assert(randomize() with {src>2}); end
注意:在此处,with{}语句里面类似于作用域,但是使用了变量src而不是t.src.
以上是关于第六章:随机化的主要内容,如果未能解决你的问题,请参考以下文章