SV学习(8)——随机约束和分布、约束块控制
SV学习(8)——随机约束和分布、约束块控制
- 1. 随即约束和分布
- 1.1. 为什么需要随机?
- 1.2. 要随机做什么?
- 1.3. 声明随机变量的类
- 1.4. 什么是约束
- 1.5. 权重分布
- 1.6. 集合成员和inside运算符
- 1.7. 条件约束
- 1.8. 双向约束
- 2. 约束块控制
- 2.1. 打开或关闭约束
- 2.1.1. constraint_mode()
- 2.1.2. rand_mode()
- 2.2. 内嵌约束
- 3. 补充
- 内嵌约束(指向模糊)
1. 随即约束和分布
1.1. 为什么需要随机?
- 芯片体积增大,复杂度日渐提高,传统定向测试已经无法满足验证的需求,而随机测试的比例逐渐提高;
- 定向测试能找到你认为可能存在缺陷,而随机测试可以找到连你都没想想到的缺陷;
- 随机测试相对于定向测试可以减少相当多的代码量,而产生的激励较定向测试也更加多样;
1.2. 要随机做什么?
- 器件配置:通过寄存器和系统信号
- 换镜配置:随机化验证环境,例如合理的时钟和外部反馈信号
- 原始输入数据:例如MCDF数据包的长度、带宽、数据间的顺序
- 延时:握手信号之间的时序关系,例如valid和ready,req和ack之间的时序关系
- 协议异常:如果反馈信号给出异常,那么设计是否可以保持后续数据处理的稳定性呢
1.3. 声明随机变量的类
- 随机变量只能在class中声明,rand和randc都只能修饰类的成员变量
- rand,表示每次随机化这个类时,这些变量都会赋一个值,每次随机的概率都是一样的
- randc,周期随机性,即所有可能出现的值都赋过值后随机值才可能重复
- 随机属性需要配合SV预定义的类随机函数std::randomize()使用。即只有通过声明rand变量,并且在后期通过对象调用randomize()函数才可以随机化变量
- 约束constraint也同随机变量一起在类中声明
class Packet;// the random variablesrand bit [31: 0] src, dst, data[8];randc bit [ 7: 0] kind;// limit the value for srcconstraint c {src > 10;src < 15;}
endclassPacket p;
initial beginp = new(); // creat a packetassert (p.randomize()) else$fatal(0, "Packet::randomize failed");transmit(p);
end
1.4. 什么是约束
- 约束表达式的求解是由SV的约束求解器(constraint solver)完成的
- 求解器能够选择满足约束的值,这个值是由SV的PRNG伪随机数发生器从一个初始值seed产生。只要改变种子的值,就可以改变CTR的行为
- SV标准定义了表达式的含义以及产生的合法值,但没有规定求解器计算约束的准确顺序。也就是说,不同仿真器对于同一个约束类和种子值求解出的数值可能是不相同的
- 什么可以被约束?SV只能随机化2值数据类型,但位可以是2值或4值。也就是说,无法随机化出X值和Z值,也无法随机化字符串
class data;rand bit [2:0] month;rand bit [4:0] day;rand int year;constraint c_data {month inside {[1:12]};day inside {[1:31]};year inside {[2010:2030]};}
endclass
【Q】下面哪些解是约束求解器合理的随机数值组合?
A. month = 2, day = 31, year = 2017
B. month = 1, day = 30, year = 2020
C. month = 10, day = 31, year = 2022
D. month = 7, day = 31, year = 2045
【An】
C. month是3bit,能表示的范围是[0:7]
D. 年限不符
class Stim;const bit [31: 0] CONGEST_ADDR = 42;typedef enum {READ, WRITE, CONTROL} stim_e;randc stim_e kind; // enumerated varrand bit [31: 0] len, src, dst;bit congestion_test;constraint c_stim {len < 1000;len > 0;if (congestion_test) {dst inside {[CONGEST_ADDR-100 : CONGEST_ADDR+100]};src == CONGEST_ADDR;}elsesrc inside {0, [2:10], [100:107]}; }
endclass
const是为了避免变量被赋值
1.5. 权重分布
- 关键词dist可以在约束中用来产生随机数值的权重分布,这样某些值的选取机会要比其他值更大些
- dist操作符带有一个值的列表以及相应的权重,中间用 : = 或 : / 分开。值或权重可以是常数或者变量,可以使用权重变量来随时改变值的概率分布,甚至可以把权重设为0,从而删除一个值
- 权重不用百分比表示,权重的和也不必是100
- : = 操作符表示值范围内的每一个值的权重是相同的,: / 操作符表示权重要平均分到值范围内的每一个值
rand int src, dst;
constraint c_dist {src dist {0:=40, [1:3]:=60}; // 产生40个单位的0,1-3每个数产生60个,共产生220个// src = 1, weight = 40/220// src = 2, weight = 60/220// src = 3, weight = 60/220// src = 4, weight = 60/220dst dist {0:/40, [1:3]:/60}; // 产生40个单位的0,1-3每个数总共产生60个,共产生100个数// dst = 0, weight = 40/100// dst = 1, weight = 20/100// dst = 2, weight = 20/100// dst = 3, weight = 20/100
}
1.6. 集合成员和inside运算符
- inside表示变量应该属于某一个值的集合,除非还存在其他约束,否则随机变量在集合里取值的概率是相等的。集合里也可以使用变量
rand int c;
int lo, hi;
constraint c_range {c inside {[lo:hi]}; // lo <= c && c <= hi
}
- 使用“$”指定最大值和最小值
rand bit [6:0] b; // 0~127
rand bit [5:0] e; // 0~63
constraint c_range {b inside {[$:4], [20,$]}; // 0 <= b <= 4 || 20 <=b <= 127e inside {[$:4], [20,$]}; // 0 <= e <= 4 || 20 <=e <= 127
}
使用inside约束从重复的值序列里选出随机值,并打印出各种值的分布,从中可以看出咯咯直的选取的概率:
class Weighted;rand int val;int array[] = '{1, 1, 2, 3, 5, 8, 8, 8, 8, 8};constraint c {val inside array;}
endclassmodule test;
Weighted w;
initial beginint count[9], maxx[$];w = new();repeat(2000) beginassert(w.randomize());count[w.val]++;endmaxx = count.max();foreach(count[i])if(count[i]) begin$write("count[%0d] = %5d", i, count[i]);$display;end
endendmodule
1.7. 条件约束
- 可以通过 -> 或者 if-else 来让一个约束表达式在特定时刻有效
class BusOp;...constraint c_io {(io_space_mode) -> addr[31] == 1'b1;}
endclass
class BusOp;...constraint c_len_rw {if (op == READ)len inside {[BYTE:LWRD]};elselen == LWRD;}
endclass
1.8. 双向约束
- 约束是声明性代码,是并行的,所有的约束表达式同时有效(单个约束块里多个约束条件和多个约束块都是并行的)
- 子类继承父类后,子类的约束不能和父类冲突
2. 约束块控制
3.22补充:
前面说过随机变量需要容器装起来再使用,也就是类,结构体里面也能声明rand变量,但是不能放约束
9.2再补充一下
interface中的变量也可以赋随机值:不能用rand关键字指定,否则编译报错;可以在interface中这么用:
2.1. 打开或关闭约束
2.1.1. constraint_mode()
class Packet;rand int length;constraint c_short {length inside {[1:32]};}constraint c_long {length inside {[1000:1023]};}
endclassmodule test;Packet P;initial beginp = new();p.c_short.constraint_mode(0);//关闭c_short约束assert (p.randomize());transmit(p);p.constraint_mode(0);//关闭类中所有约束p.c_short.constraint_mode(1);//打开c_short约束transmit(p);end
endmodule
- constraint_mode(0):关闭约束
- constraint_mode(1):打开约束
- 非激活状态下的约束在调用randomize()函数时将失效
- 若PRNG伪随机数发生器找不到合适的解,即约束冲突,里面所有的变量默认都是0,此次随机失败
- 上述代码,不关闭两个约束,在tb创建对象后,然后打印p.length,编译不会报错,仿真结果为0;不关闭两个约束,在tb创建对象后,调用randomize()类随机函数,编译不会报错,因为randomize()返回值为0,仿真时提示有错
2.1.2. rand_mode()
- 用来打开或关闭随机变量
- 非激活状态下,给表示该变量不被声明为rand或者randc,不能通过randomize()函数随机化赋值
class Packet();rand int src, dst;
endclassint r;
Packet packet_a = new;
packet_a.rand_mode(0); //将Packet类中的两个随机变量设置为非激活态,即src与dst变为非随机变量,不能通过randomize函数赋值
packet_a.src.rand_mode(1); //将Packet类中的src设置为激活态,可以通过randomize函数进行赋值
r=packet_a.dst.rand_mode(); //读取dst变量的激活状态
2.2. 内嵌约束
- SV允许使用randomize() with来增加额外的约束,这和在类里增加约束是等效的,但同时要注意类内部约束和外部约束之间不要冲突,如果出现互相违背的情况,那么随机数值求解会失败
class Transaction;rand bit [31: 0] addr, data;constraint c1 {soft addr inside {[0:100], [1000:2000]};}
endclassmodule test;Transaction t;initial begint = new();// addr is 50-100, 1000-1500, data < 10assert(t.randomize() with {addr >= 50; addr <= 1500; data <10;});driveBus(t);// force addr to a specific value, data > 10assert(t.randomize() with {addr == 2000; data <10;});driveBus(t);end
endmodule
【Q】
如果assert(t.randomize() with {addr inside [200:300]; data inside [10:20];});,那么哪个值是合理的随机数值?
A. 报错,10
B. 报错,报错
C. 200,10
D. 0,10
【An】
选C。
对于任何一个约束冲突、不满足,此次随机的addr、data都没办法做求解,全部失败。但是添加了soft关键词,软约束,当外部的约束或其他的约束和原本的约束叠加在一起的时候有冲突,那么soft处的优先级更低,其他地方的优先,没报错
3. 补充
内嵌约束(指向模糊)
class C1;rand integer x;
endclassclass C2;integer x;integer y;task diot (C1 f, integer x, integer z);int result;result = f.randomize() with {x < y + z;}endtask
endclass
result = f.randomize() with {x < y + z;}
因为内嵌约束是关于类C1的句柄f所指的对象,x对应的是C1里的x。
使用local::x可以索引到函数传参的x。
使用local::this.x可以索引到C2的x。
SV学习(8)——随机约束和分布、约束块控制相关推荐
- SV学习笔记—变量及数组随机化约束常犯的错误
目录 1.有符号变量导致的随机化错误 2.变量溢出导致的随机化错误 3.数组的约束 3.1约束数组的size函数 3.2约束数组的sum函数 4.数组约束常犯错误 4.1有符号变量导致的错误 4.2溢 ...
- SystemVerilog学习笔记5——随机约束和分布
目录 随机约束和分布 为何需要随机? 为何需要约束? 需要随机什么? 声明随机变量的类 什么是约束? 权重分布 约束块控制 打开或关闭约束 内嵌约束 随机函数 数组约束 数组的属性约束 随机化句柄数组 ...
- SV 学习笔记(四)随机与约束
文章目录 一.随机约束与分布 1.1 随机变量 1.2 约束 1.2.1 数值分布约束 1.2.2 权重分布约束:dist 1.2.3 条件约束 1.2.4 双向约束 1.3 约束块控制 1.3.1 ...
- SV-随机约束和分布-自用
随机约束和分布 随机化就是为了能更好的测试,找到连自己都没想到的缺陷 随机化是为了产生更多可能的驱动,在 Class 中使用 在类中使用rand/randc表明随机属性,constraint约束一起声 ...
- 实战:k8s之拓扑分布约束-2022.2.19
目录 文章目录 目录 实验环境 实验软件 1.Pod 拓扑分布约束 2.使用规范 3.单个拓扑约束 4.多个拓扑约束 5.与NodeSelector /NodeAffinity一起使用 6.集群默认约 ...
- 【MySQL8.0学习笔记】约束:主键约束、自增长约束、非空约束、唯一性约束、默认约束与零填充约束
本文对MySQL数据库的约束相关知识进行了归纳总结,包括主键约束.自增长约束.非空约束.唯一性约束.默认约束与零填充约束. 本专栏长期更新,敬请关注. 文章目录 1 MySQL约束简介 2 主键约束 ...
- 九、MySQL常见约束相关知识总结 学习笔记 + 强化复习(六大约束)
常见约束: 一.含义:一种限制,用于限制表中的数据,为了保证表中的数据的准确和可靠性 二.分类:六大约束 1.NOT NULL:非空,用于保证该字段的值不能为空 比如姓名.学号等 2.DEFAULT: ...
- 《SQL高级应用和数据仓库基础(MySQL版)》学习笔记 ·003【表的约束、表的CRUD操作(DDL语句)】
文章目录 一.表的约束 1.约束类型 2.添加约束 二.表的CRUD操作(DDL语句) 1.C(Create):创建 2.R(Retrieve):查询 3.U(Update):更新 4.D(Delet ...
- SQL Server2008创建约束图解 唯一性约束
SQL Server2008创建约束图解 复习一下数据库的约束 机房收费系统个人重构版开始了,但在设计数据库时遇到了写小麻烦,主要是数据库中约束的应用,以前在学习数据库时进行了总结,在刚开始学习时使用 ...
最新文章
- apache 局域网访问
- 在融通一年多来,海哥一直在分享看过的比较不错的文章,借花献佛下
- clear在CSS中的妙用
- [机器学习笔记]Note8--机器学习应用建议
- 收集常用的.net开源项目
- 浅析几种常见RAID模式。DVI接口种类!以及18针24针的区别!
- 简易PDF电子书书签制作
- UML基础(八)--构件图
- php 常见的视频格式转换
- 直击AI场景化实践:在部分行业可取代人工
- NCM格式如何转换为Mp3(简单快速)
- throw在java用法_throw()使用小结
- 土豆网终于忍不住了,开始了影视站转型。
- Kubernetes 1.14 发布,31 项功能增强
- node+express实现文件上传功能
- mysql高德地图设计_基于高德开放平台Map Lab的数据可视化
- Vue.js函数的生命周期
- Love Story
- 关于leetcode刷题详细介绍
- 项目管理培训资料(第一讲+第二讲,持续更新中.....)
热门文章
- 用Python解矩阵方程——Sympy模块
- html5中检测网络状态的方法,前端js监听浏览器网络变化
- 百万在线:大型游戏服务端开发
- matlab 分水岭法,分水岭算法Matlab实现——三种方法 | 学步园
- 阅读笔记03——魔鬼搭讪学
- QNET:APP弱网络测试专家
- valgrnd调试详解
- word嵌入对象依损坏_出错提示“Word 未能写某些嵌入对象,因为内容或磁盘空间不足”...
- C++——输入、输出和文件
- tadb.exe、sjk_daemon.exe导致 adb.exe启动失败