06-SV随机化
1、受约束的随机测试法(CRT)
随着设计变得越来越大,要产生一个完整的激励集来测试设计的功能变得越来越困难。解决的办法是采用受约束的随机测试法自动产生测试集。CRT环境比定向测试的环境复杂,不仅需要产生激励,还需要通过参考模型、传输函数或其他方法预测输出结果。然而只要准备好了这个环境,就可以运行上百次的仿真而无需手工检查结果,从而提高工作效率,这也是CRT的优势:用CPU时间来换取人工检查的时间。
2、SV中的随机化
rand修饰符:表示每次堆积化这个类时,这些变量都会赋一个值。
randc修饰符:表示周期随机性,即所有可能的值都赋过值后随机化值才可能重复。
约束:一组用来确定变量的值的范围的关系表达式,表达式的值永远为真。约束的表达式放在括号“{ }”中。
randomize()函数在遇到约束方面的问题时返回0.
不能在类的构造函数里随机化对象,类里的所有变量都应该是随机的和公有的,这样测试平台才能最大程度地控制DUT。
3、约束
使用约束来定义各个变量的相互关系以产生有用的激励。
约束块包含若干个表达式,在一个表达式中最多只能使用一个关系操作符(<,<=,==,>=,>)
权重分布:使用dist操作符,如 src dist {0:=40,[1:3]:=60},这表示0的权重是40,1,2,3的权重都是60,总权重为220. dst dist {0:/40,[1:3]:/60},这表示0的权重是40,1,2,3三个值的总权重为60. 值和权重可以是常数或变量,设为变量可以动态改变权重。
集合成员和inside运算符:可以用inside运算符产生一个值的集合,各个值的选取机会相等。c inside {[2:6]} ,这表示2<=c<=6。在inside约束中即使有重复的值,各个值的概率也是均等的。
在集合里使用数组:把集合里的值保存到数组里后就可以使用这些值了。
条件约束:让一个约束表达式只在某些时候才有效。例如,一条总线支持字节、字和长字的读操作,但只支持长字的写操作。“->”操作符可以产生和case操作符效果类似的语句块,它可以用于枚举类型的表达式,“if-else”适合于“真-假”类型的表达式。“A->B”表示满足A的情况下执行B
双向约束:SV的约束是双向的,这表示它会同时计算所有的随机变量的约束。增加或删除任一个变量的约束都会直接或间接影响所有相关变量值的选取。“->”和“if-else”也是双向的,如{(a==1)->(b==0)}约束下有 (a,b)=(0,0)、(a,b)=(0,1)、(a,b)=(1,0)这三种情况,a==1时对b有约束,但b==0时对a没有约束。
4、解的概率
使用solve……before约束引导概率分布:使用该约束不会改变解的个数,只会改变各个值的概率分布。不要过度使用solve……before,会降低速度
5、控制多个约束块
一个类可以包含多个约束块,在运行期间,可以使用内建函数打开或者关闭约束。handle.constrain.constraint_mode()控制一个约束块的开启(1)或关闭(0);handle.constraint_mode()控制对象的所有约束。
6、有效性约束
设置多个约束以保证随机激励的正确性。例如,总线的“读-修改-写”命令只允许操作字数据长度。
rand enum {BYTE,WORD,LWRD,QWRD} length;
rand enum {READ,WRITE,RMW,INTR} opc;
constraint valid_RWM_LWRD{
(opc==RMW)->length==LWRD;
}
7、内嵌约束
随着测试的进行,你面对的约束越来越多。它们会相互作用,最终产生难以预测的结果;用来使能和禁止这些约束的代码也会增加测试的复杂性。很多测试只会在代码的一个地方随机化对象。SV允许使用randomize() with来增加额外的约束,这和在类里增加约束是等效的。一般是在带约束的基类上进一步增加约束。如:
constraint c1 {addr inside {[0:100],[1000:2000]};}
t.randomize() with {addr >=50; addr <= 1500;};
8、pre_randomize和post_randomize函数
可以在随机化之前设置类里的一些非随机变量,或者随机化之后计算随机数据的误差校正位。
9、随机数函数
(1)$random()——平均分布,返回32位有符号随机数
(2)$urandom()——平均分布,返回32位无符号随机数
(3)$urandom_range()——在制定范围内的平均分布,如a=$urandom_range(3,10)
10、约束的技巧和技术
(1)使用变量的约束:如改变变量范围的上下限,改变权重变量的dist分布
(2)使用非随机值:使用rand_mode函数可以把变量设置为非随机变量。如:
rand bit [7:0] length,payload[];
assert (p.randomize());
p.length.rand_mode(); //设置包长为非随机值
p.length=42; //设置包长为常数
assert (p.randomize());
(3)随机化个别变量
在调用randomize()函数时可以只传递变量的一个子集,这样就只会随机化类里的几个变量。只有参数列表里的变量才会被随机化,其他变量会被当做状态变量而不会被随机化。
(4)打开或关闭约束
可以使用条件操作符(->或if-else)来构建由非随机变量控制的约束。
也可以使用constraint_mode()打开或关闭约束。
(5)在测试过程中使用内嵌约束
当新的约束是对缺省约束的补充时,可以使用randomize() with内嵌的约束语句使约束的作用范围局部化。
(6)在测试过程中使用外部约束
函数的函数体可以在函数的外部定义,同样,约束的约束体也可以在类的外部定义。可以在一个文件里定义一个类,这个类只有一个空的约束,然后在不同的测试里定义这个约束的不同版本以产生不同的激励。
program automatioc test;
include "packet.sv" constraint Packet::c_external {length==1;}
11、数组约束
(1)约束动态数组的大小
rand logic [31:0] d[];
constraint d_size {d.size() inside {[1:10]};}
(2)约束数组元素的和
rand bit strob [10];
constraint c_set_four {strob.sum()==4'h4;}
(3)约束数组和队列的每一个元素
下面的例子随机化一个长度[1:8]的数组,数组元素和小于1024:
rand [9:0] len[]; //因为1024为10bit数,因此len的元素至少为10bit,和的位宽与元素的一样
constraint c_len { foreach (len[i])
len[i] inside {[1:255]};
len.sum < 1024; //1024为10bit数
len.size() inside {[1:8]};}
(4)使用randc可以辅助产生唯一的元素值的数组
12、随机控制
在程序性语句里使用randcase,例如:
randcase
1:len=$urandom_range(0,2); //10%:0,1,2
9:len=$urandom_range(3,5): // 90%:3,4,5
endcase
13、代码示例
(1)类定义
package class_define;
//简单约束
class Packet;
rand bit [:] src,dst,data[];
rand bit a,b;
//设置约束
constraint c {
src <;
} // -> 类似case语句
constraint c2 {
(a==)->(b==); //(a,b)=(1,0)或者(0,0)或者(0,1)
b>; //现在只有(0,1)这一种情况 }
endclass:Packet //inside 和 指定权重的随机化
class Stim;
typedef enum {READ,WRITE,CONTROL} stim_e;
randc stim_e kind;
rand bit [:] len,src,dst;
bit c_stim_control;
bit [:] kind_weight=; constraint c_stim {
if(c_stim_control){
src inside {[:]};
}
else src inside {[:]}; //使用权重随机化
kind dist { READ := ,
WRITE := - kind_weight,
CONTROL := kind_weight
};
}
// 运行过程打开或关闭约束
constraint c1 {
len == ;
}
constraint c2 {
len == ;
} endclass:Stim //让集合中的数只被取一次
class RandcInside;
int array[]; //待选取的值
randc bit [:] index; //指向数组的指针
function automatic new(input int a[]); //构造,初始化
array = a;
endfunction
function int pick; //返回刚选取出来的值
return array[index];
endfunction
constraint c_size {index<array.size;} endclass:RandcInside //随机化数组,各个元素的值为1-255,和为1024
//注意:SV默认和的位宽与加数位宽一样,为了
//避免溢出,加数位宽为10bit
class array_random;
rand bit [:] len[];
constraint c_len {
foreach (len[i])
len[i] inside {[:]};
len.sum < ;
len.size() inside {[:]};
} function void display();
$write("sum=%4d,val=",len.sum);
foreach(len[i]) $write("%4d",len[i]);
$display;
endfunction:display endclass:array_random endpackage:class_define
(2)测试program
import class_define::*;
program test6;
initial begin
Packet p;
RandcInside ri;
Stim st;
array_random ar;
p = new();
ri = new('{1,3,5,7,9,11,13});
st = new();
ar = new(); // ========== 简单测试 =============
// ========== 条件约束 =============
// ========== 内嵌约束 =============
$display("====== class Packet ========");
assert (p.randomize())
else $fatal(,"Packet::randomize failed");
$display("p.src=%0d,p.a=%0d,p.b=%0d",p.src,p.a,p.b);
assert (p.randomize() with {src>;}); // 添加一个内嵌测试,8<src<10
$display("p.src=%0d,p.a=%0d,p.b=%0d",p.src,p.a,p.b); // ========== 带条件的约束、带权重的约束、
// ========== 运行过程打开或关闭约束 =============
$display("====== class Stim ======");
st.constraint_mode(); //关闭所有约束
st.c1.constraint_mode(); //开启c1约束
st.c_stim.constraint_mode(); //开启c_stim约束
st.c_stim_control = ; //改变c_stim的控制模式
st.kind_weight = ; // 改变kind变量的分配权重
assert(st.randomize());
$display("st.len=%0d,st.src=%0d,st.kind=%s",st.len,st.src,st.kind.name); st.constraint_mode(); //关闭所有约束
st.c2.constraint_mode(); //开启c2约束
st.c_stim.constraint_mode(); //开启c_stim约束
st.c_stim_control = ; //改变c_stim的控制模式
st.kind_weight = ; // 改变kind变量的分配权重
assert(st.randomize());
$display("st.len=%0d,st.src=%0d,st.kind=%s",st.len,st.src,st.kind.name); //让集合中的数只被取一次
$display("====== class RandcInside ======");
repeat (ri.array.size) begin
assert(ri.randomize());
$display("Picked %2d [%0d]",ri.pick(),ri.index);
end //随机化数组
$display("====== class array_random ======");
assert(ar.randomize());
ar.display(); end endprogram:test6
(3)输出
# ====== class Packet ========
# p.src=,p.a=,p.b=
# p.src=,p.a=,p.b=
# ====== class Stim ======
# st.len=,st.src=,st.kind=CONTROL
# st.len=,st.src=,st.kind=WRITE
# ====== class RandcInside ======
# Picked []
# Picked []
# Picked []
# Picked []
# Picked []
# Picked []
# Picked []
# ====== class array_random ======
# sum= ,val=
06-SV随机化的更多相关文章
- SV中的随机化
SV搭建testbench的关键概念:CRT(constraint random test),测试集的随机化. 由于对象class由数据和操作组成,所以对数据的随机化一般放在一个class内.(对环境 ...
- SV randomize
randomize中的变量只支持2-state的values,不支持4-states. randc类型的变量不能被约束在solve------before的语句中. constraint可以被定义在c ...
- SV中的数据类型
Verilog-1995中规定的数据类型有:变量(reg), 线网(wire), 32位有符号数(integer), 64位无符号数(time), 浮点数(real). SV扩展了reg类型为logi ...
- APP漏洞扫描用地址空间随机化
APP漏洞扫描用地址空间随机化 前言 我们在前文<APP漏洞扫描器之本地拒绝服务检测详解>了解到阿里聚安全漏洞扫描器有一项静态分析加动态模糊测试的方法来检测的功能,并详细的介绍了它在针对本 ...
- 《HelloGitHub月刊》第06期
前言 <HelloGitHub>月刊做到第06期了(已经做了6个月了),在GitHub上获得了100+的stars,虽然不多,但是我很知足了,说明有人觉得这个项目是有价值的.同时园子中的' ...
- iOS系列 基础篇 06 标签和按钮 (Label & Button)
iOS系列 基础篇 06 标签和按钮 (Label & Button) 目录: 标签控件 按钮控件 小结 标签和按钮是两个常用的控件,下面咱们逐一学习. 1. 标签控件 使用Single Vi ...
- javaSE基础06
javaSE基础06 一.匿名对象 没有名字的对象,叫做匿名对象. 1.2匿名对象的使用注意点: 1.我们一般不会用匿名对象给属性赋值的,无法获取属性值(现阶段只能设置和拿到一个属性值.只能调用一次方 ...
- 异步编程系列06章 以Task为基础的异步模式(TAP)
p { display: block; margin: 3px 0 0 0; } --> 写在前面 在学异步,有位园友推荐了<async in C#5.0>,没找到中文版,恰巧也想提 ...
- 挣值管理(PV、EV、AC、SV、CV、SPI、CPI) 记忆
挣值管理法中的PV.EV.AC.SV.CV.SPI.CPI这些英文简写相信把大家都搞得晕头转向的.在挣值管理法中,需要记忆理解的有三个参数:PV.AC.EV. PV:计划值,在即定时间点前计划 ...
随机推荐
- node基础 day1
js为什么能在浏览器中运行 浏览器内部存在一个js解析器,解析ECMAscript 把引擎从浏览器中抽离出来,不再依赖浏览器,作为一个软件安装在电脑上,在命令行里面, 这个软件就是node node ...
- docker-enter 安装
github : https://github.com/sequenceiq/docker-enter [root@localhost ~]# docker run --rm -v /usr/loca ...
- 一篇文章带你搞定 ElasticSearch 术语
这篇文章主要介绍 ElasticSearch 的基本概念,学习文档.索引.集群.节点.分片等概念,同时会将 ElasticSearch 和关系型数据库做简单的类比,还会简单介绍 REST API 的使 ...
- POJ 1753 Flip Game 暴力 深搜
Flip Game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 59468 Accepted: 24750 Descr ...
- Centos7之firewall配置命令
firewalld的基本使用 查看状态:systemctl status firewalld 启动:systemctl start firewalld 停止:systemctl stop firewa ...
- mybatis 测试输出SQL语句到控制台配置
1: mybatis-config.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE ...
- NFS服务配置 Linux
两台机器: NFS服务器:192.168.1.100 (我的是Ubuntu系统) 客户机:192.168.1.123 (保证两台机器互相可以ping通) 需求:在NFS服务器上创建一个共享文件夹/ho ...
- springboot + mybatis 支持oracle和mysql切换含源码
1.springboot 启动类加入bean 如下 // DatabaseIdProvider元素主要是为了支持不同的数据库@Beanpublic DatabaseIdProvider getData ...
- 浅谈Javascript中的原型、原型链、继承
构造函数,原型,实例三者的关系 构造函数: 构造函数是创建对象的一种常用方式, 其他创建对象的方式还包括工厂模式, 原型模式, 对象字面量等.我们来看一个简单的构造函数: function Produ ...
- JAVA面向对象 - 抽象类、接口
抽象类 用abstract关键字来修饰一个类时,这个类就叫抽象类,用abstract关键字来修饰一个方式时,这个方法就是抽象方法.当一个类继承的父类是抽象类的话,需要我们把抽象类中的所有抽象方法全部实 ...