重新调整一下进度规划,每天按七个视频的量看绿皮书,书和视频的关系大概是视频=80%书,学习的话还是看书好,看的时候脑子里会有问题,问题会进一步带自己深入去想,是主动思考;看视频容易被带过,是被动思考。想起考研的时候拼命刷视频,最后考得并不好,还总是安慰自己做了很多事。
今天学习的是第六章随机化前两个点:随机约束和分布+约束块控制
介绍完随机和约束的概念后进入语法学习
- 在class类中进行随机
- 用rand和randc声明随机变量,可以是数组
- randomize函数实现随机化
- constraint 名 {} 定义约束块
- 随机变量名 dist {} 声明权重
- 内部约束和外部约束
- 使用内建constraint_mode()决定打开和关闭哪些约束块
- 用randomize() with{约束条件}来增加额外的约束,属于外部约束,等效于在类里面增加内部约束,注意协调
为什么要随机?
答:定向测试只能找到我们认为可能存在的缺陷,不足以找出我们想不到的缺陷。随机测试使用少量的代码,产生更多的激励。随机化是为了产生更多可能的驱动
为什么要约束?
不约束的随机,产生有效激励的同时也会产生无效和非法的激励
要随机的是什么?
- 器件配置
- 环境配置
- 原始输入数据
- 封装后的输入数据
- 协议异常
- 延时
- 事务状态
- 错误和违规
声明随机变量的类
将相关数据整理在一个类,用rand关键词来表明随机属性,randc表示周期随机性,即所有可能的值都赋过后随机值才能重复;随机属性需要配合类随机函数std::randomize()。
只有通过声明rand变量,并且在后期通过对象调用函数randomize()才可以随机化变量
约束constraint也喝随机变量一起在类中声明
class packet;
rand bit [31:0] src, dst, data[8];
rand bit [7:0] kind;
constraint c {src>10; src<15;}
endclass
packet p;
initial begin
p=new();
assert (p.randomize()) else
$fatal(0,"packet::randomize failed");
transmit(p);
end
- 在类中声明随机变量,用constraint约束随机变量的范围,必须满足所有约束条件才能随机化成功
- 句柄.randomize()才是随机化,为所有随机变量赋一个随机值。返回1/0代表随机化成功/失败
- 不能在类的构造函数里随机化对象,构造函数是用来初始化对象的变量
- 类里所有变量都应该是random随机和public共有的
声明随机变量
rand/randc 数据类型(bit) [ 数据:宽度] 数据名1,数据名2;
rand类似放回的抽球,randc是不放回的抽球
至少要有一个变量是rand和randc
约束块
constraint 约束名 {表达式1; 表达式2}
一个表达式最多只能使用一个关系操作符
限定范围可以用大小写,也可以用:随机变量名 inside {[范围1],[范围2],或者是指定的数}
表达式可以是if_else结构,其中可以加入非随机变量,也可以给随机变量==表达式赋值
约束块是声明性代码,是并行的
约束是双向进行的,会同时计算所有随机变量的约束
权重分布
- 随机变量名 dist {指定的数:=权重1,[范围1]:=权重2}
- :=表示范围内的每个数各自占有权重2
- :/表示范围内的每个数平分权重2
集合成员和inside
- 可以用非随机变量将约束范围参数化,比如int a,b;
- 可以用$来代替取值范围的边界,比如b inside {[$:4],[20:$]};
- 可以用取反操作符!对约束取反,选择集合之外的值
在集合里面使用数组
- 声明随机变量和数组后就可以直接inside: f inside fib;
- 上面表达式也可以拆分成f==fib[具体位] || 再加逻辑或
- 就算队列中有重复的数,每个独立的数的取值概率是一样的
- 可以从数组中取出随机值的类
- 可以从数组中取出随机值,先声明例化句柄,利用句柄.动态数组={类::枚举中的数};给动态数组赋值,然后句柄.随机化
条件约束
用- >或者if _else令一个约束表达式在特定时刻有效
(io_space_mode)- > addr[31]==1’b1; 等价于
if(op==read) len inside {[byte:lwrd]}; else len==lwrd;
编写出易于修改的CRT技巧
- OPP技术扩展原始类(未学)
- 用变量设定上下限
- 用带有权重变量的dist约束,也就是把权重变成变量,随时修改
- 用rand_mode函数禁止变量的随机化,也就是使用非随机值
约束块控制
-
一个类可以包含多个约束块
-
使用内建constraint_mode()决定打开和关闭哪些约束块:
句柄.约束块名.constraint_mode(0/1);——也可以直接句柄.constraint_mode(0/1)
0表示关闭,1表示打开,不加约束块名就直接操作整个类里面的约束块
内嵌约束
- 上述的控制约束块开关的语句会增加测试的复杂性,不利于团队协作,需要考虑类的开放封闭原则OCP
- 用randomize() with{约束条件}来增加额外的约束,属于外部约束,等效于在类里面增加内部约束,注意协调
- 内部约束如果在最前面加上soft软约束,表示出现约束的冲突时,这个约束的优先级低,其他约束优先