写在前面:冲冲冲

1.随机化验证策略

为什么使用随机化验证策略?

  • 设计复杂度提高之后,直接测试(定向测试)(directed testcase),没有办法通过穷举法验证所有矢量
  • 定向测试案例用于检查确定的设计属性,仅仅用于检查可以预期的错误
  • 定向测试方式跟测试时间是线性关系
  • 定向测试案例不能检查隐形的错误

解决办法:采用带约束的随机化测试(CRT),对输入的激励随机化

2.随机内容有哪些?

必须对DUT里的所有关键点都采用随机化的技术。
(1)RTL设计的配置:

  • 需要测试足够多

(2)环境的配置:

  • 随机化配置整个环境(输入数据数量、输出数据类型)

(3)原始输入数据:

  • 对输入数据进行随机化
  • 在输入数据的范围内进行随机化

(4)封装的输入数据:

  • 如果数据进行了一层层封装,不同的封装可以随机化,如TCP/IP

(5)协议异常、错误(error)和违规(violation):

  • 验证系统如何处理错误
  • 期望的错误类型,在随机的时间间隔里产生随机的错误类型,确保系统设计可以正确的处理这些错误

(6)时间延迟(时钟周期)

  • 根据协议要求随机插入时间延迟(latency)
  • 检查设计对时钟周期的敏感性
  • 不需要对建立时间和保持时间进行验证
  • 测试平台应该在每一个测试里都使用随机的、有效的延时,以便于发现设计中的Bug。

3.SV的随机化

  • 随机化允许用户自动生成随机的输入激励,用于验证功能
  • SV允许用户使用特定的约束,将随机输入的数据约束在有效的范围内
  • 必须在OOP(class)中指定随机约束

3.1带有随机变量的简单类

例子:简单的随机类

//SV绿皮书
//例6.1简单的随机类class packet;//随机变量,rand普通随机,randc循环随机//随机变量rand bit [31:0] src, dst, data[8]; //周期性随机变量randc bit [7:0] kind;    //src的约束,表示随机时src介于10和15之间//如果不加约束,src每个数据出现的概率为1/256constraint c {src > 10;src < 15;}
endclassPacket p;initial begin// 创建一个对象p=new(); //随机化约束一般写在class中,用点的方式去调用assert (p.randomize());//用断言检查随机化,随机化成功,函数返回1;失败返回0else $fatal(0,“Packet::randomize failed”); //随机化失败,函数返回0,并显示错误信息transmit (p);
end

这个实例中,包括普通随机数rand、循环随机数randc、约束constraint、randomize等,记住这个例子。

  • rand 修饰符,表示每次随机化这个类时,这些变量都会赋一个值(类似抽签,抽完放回去继续抽)。
  • randc修饰符,表示周期随机性,即所有可能的值赋过值后随机值才可能重复(类似抽签,抽完不放回继续抽)
  • constraint约束是一组用来确定变量的值的范围的关系表达式,表达式的值永远为真。约束表达式放在{…}括号中,而没有放在begin和end之间,因为这段代码是声明性质,而不是程序性质。
  • randomize()函数在遇到约束方面的问题时返回0。本例使用断言来检查randomize函数的结果,并使用$fatal来终止仿真。针对不同的仿真工具,需使用相应的选项来使断言能够终止仿真过程

在这里,我们需要明确几个问题:

  • 在类中指定约束
  • 不能在类的构造函数中随机化对象,因为在随机化前可能需要打开或关闭约東、改变权重,甚至添加新的约束。构造函数用来初始化对象的变量,不能在这里调用 randomi ze()函数。
  • 类里的所有变量都应该是随机的( random)和公有的( public),这样测试平台才能最大程度地控制DUT。

4.随机化的约束

4.1约束解释器

  • 解析约束的关系
  • 相同的种子(seed)生成相同的随机数;使用不同的种子,可以生成一组不同的随机数
  • 不同EDA工具厂商的约束解析器是定制的

4.2约束constraint

需要使用包含一个或多个约束表达式的约束块定义激励向量间的关系,SV会选择满足所有表达式的随机值。
每个表达式至少有一个变量必须是rand或randc类型的随机变量,如:

误例:没有随机变量的约束

//SV绿皮书
//例6.2没有随机变量的约束class Child;bit [31:0] age;//错误,应该使用rand或randcconstraint c_teenager{age>12;age<20;}
endclass

正例:受约束的随机类

//SV绿皮书
//例6.3受约束的随机类
class Stim;const bit [31:0] CONGEST_ADDR=42;typedef enum {READ, WRITE, CONTROL} Stim_e;randc stim_e kind; //枚举变量rand 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}else src inside {0, [2:10], [100:107]};}
endclass

分析下这个实例:

  • 在一个表达式中最多只能使用一个关系操作符(<、<=、==、>=、>),如:
  • //SV绿皮书
    //例6.4不正确的排序约束
    class order;rand bit [7:0] lo,med,hi;constraint bad {lo<med<hi;}//错误的做法
    endclass将上面修改,就正确了
    //例6.6固定顺序的约束
    class order;rand bit [7:0] lo,med,hi;constraint bad {lo<med;med<hi;}//只能用二进制约束?
    endclass
  • 暂留

4.3权重分布

数值分布操作符:dist操作符

  • 给部分数值增加权重,这样某些值的选取机会要比其他值更大一些。

测试案例需要相关的数值;为了测试结果指定一定的数值分布

  • 两个操作符:  := 或:/

:=操作符表示指定的数值具有相同的分布权重

:/ 操作符表示指定的数值均分重权

  • 值或权重可以是常数或变量。值可以是一个值或值的范围,例如[lo:hi]。
  • 权重更不用百分比表示,权重的和也不必是100。
  • randc关键字申明的随机变量不能设置权重(因为是周期循环随机)

实例:静态改变权重

//SV绿皮书
//例6.7使用dist的权重随机分布
rand int src,dst;
constraint c_dist {src dist {0:=40,[1:3]:=60};//src的值可能是0、1、2、3,其中0的权重是40,其他的权重是60dst dist {0:/40, [1:3]:/60};//src的值可能是0、1、2、3,其中0的权重是40,其他的权重和是60
}

这段代码的权重分布如下:

4.4集合(set)成员和inside运算符

inside {} 运算符:产生一个值的集合。SV在值的集合里取随机值时,各个值的选取机会是相等的。

实例:inside的使用

//SV绿皮书
//例6.9随机值的集合
rand int c; //随机变量
int lo, hi; //作为上限和下限的非随机变量
constraint c_range {c inside {[lo:hi]}; // lo < = c 并且 c < = hi
}
  • 此处,应该满足lo<hi,否则导致约束错误。
  • 可以把inside的约束看成foreach约束

实例:使用“$”指定最大值和最小值

//SV绿皮书
//例6.10使用“$”指定最大值和最小值
rand bit [6:0] b; //0 < = b < = 127
rand bit [5:0] e; // 0 < = e < = 63
constraint c_range {b inside {[$ : 4],[20 : $]}; //0 < = b < = 4 || 20 < = b < = 127e inside {[$ : 4],[20 : $]}; //0 < = e < = 4 || 20 < = e < = 63
}

实例:随机集合约束的取反(!取反操作符)

//SV绿皮书
//例6.11 随机集合约束的取反
constraint c_range {!(c inside {[lo:hi]}) ;//c < lo 或 c > hi
}

实例:在集合里使用数组

//SV绿皮书
//例6.12使用数组的随机集合约束
rand int f;
int fib[5]='{1,2,3,5,8};
constraint c_fibonacci{f inside fib;
}上面的例子还可以扩展成下面这种格式://例6.13等价的约束
constraint c_fibonacci{(f = = fib[0])||  //f = =1(f = = fib[1])||  //f= =2(f = = fib[2])||  //f= =3(f = = fib[3])||  //f= =5(f = = fib[4]);   // f= =8
}

实例:在inside约束中有重复的值

//SV绿皮书
//例6.14在inside约束中有重复的值
module Randomization_6_14();
class Weighted;  //定义一个类rand int val;int array[]='{1,1,2,3,5,8,8,8,8,8};//声明了数组,并填入数组constraint c {val inside array;}   //inside,在数组中取值
endclassWeighted W;       //声明一个句柄
initial beginint count[9],maxx[$];W=new();        //创建一个对象repeat(2000)beginassert (W.randomize());//断言判断随机化约束,成功返回1,失败返回0//count[w.val]++;//统计值的个数count[W.val]+=1;endmaxx=count.max();//获取最大值//输出值的分布foreach(count[i])if(count[i]) begin$write("count[%0d]=%5d",i,count[i]);repeat(count[i]*40/maxx[0]) $write("* ");$display;end
end
endmodule

上面这段代码的仿真结果如下:

Compiler version I-2014.03; Runtime version I-2014.03;  Aug 17 07:42 2020
count[1]=  443* * * * * * * * * * * * * * * * *
count[2]=  192* * * * * * *
count[3]=  178* * * * * * *
count[5]=  195* * * * * * *
count[8]=  992* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * V C S   S i m u l a t i o n   R e p o r t

为什么和书中例6.15的仿真结果不一样,值得思考!

实例:从数组中取出随机值

//SV绿皮书module Randomization_6_16();//例6.16从数组中取出随机值的类
class Days;         //定义一个类typedef enum {SUN,MON,TUE,WED,THU,FRI,SAT} days_e;days_e choices[$];rand days_e choice;constraint cday {choice inside choices;}
endclass//例6.17从数组中取出随机值
initial beginDays days;          //声明一个句柄days=new();         //创建一个对象days.choices={Days::SUN,Days::SAT};assert (days.randomize());//断言判断随机化约束,成功返回1,失败返回0$display("Radom weekend day %s\n",days.choice.name);//name函数返回的是枚举值的字符串days.choices={Days::MON,Days::TUE,Days::WED,Days::THU,Days::FRI};assert (days.randomize());//断言判断随机化约束,成功返回1,失败返回0$display("Radom weekend day %s\n",days.choice.name);
end
endmodule

仿真结果:

Radom weekend day SUNRadom weekend day WED

实例:使用randc随机地选取数组的值

//SV绿皮书
//例6.18使用randc随机地选取数组的值
module Randomization_6_18();class RandcInside;         //定义一个类int array[];             //待选取的值randc bit [15:0] index;  //指向数组的指针function new(input int a[]);//构造、初始化array=a;endfunctionfunction int pick;          //返回刚取出的值return array[index];endfunctionconstraint c_size{index<array.size;}
endclassinitial beginRandcInside ri;               //声明一个句柄ri=new('{1,3,5,7,9,11,13});   //创建一个对象并初始化repeat(ri.array.size)beginassert(ri.randomize());     //断言$display("Picked %2d [%0d]",ri.pick(),ri.index);end
end
endmodule

仿真结果:

Compiler version I-2014.03; Runtime version I-2014.03;  Aug 17 08:29 2020
Picked  3 [1]
Picked 13 [6]
Picked 11 [5]
Picked  1 [0]
Picked  5 [2]
Picked  7 [3]
Picked  9 [4]V C S   S i m u l a t i o n   R e p o r t

4.5条件约束

约束语句提供了两种语法用于声明条件关系->和if-else

总结,也可以用下面这种方式等价表示:

  • mode == small -> len < 10;
    mode == large -> len > 100;//下面这种方式与上面等价,推荐使用上面的方式
    if(mode == small)len<10;
    else if (mode == large)len>100;
  • rand bit [3:0] a,b;
    constraint c {(a==0) -> b==1;}//下面这种方式与上面等价,推荐使用上面的方式
    rand bit [3:0] a,b;
    if(a==0) b==1;

4.6双向约束

  • 约束语句是并行的声明性语句(declarative),不是过程化语句(procedural)
  • 所有的约束表达式同时生效
//SV绿皮书
//例6.21双向约束
rand logic [15:0] r,s,t;
constraint c_bidir{r < t;s == r;t < 30;s > 25;
}

这段代码的约束范围为:25<s==r<t<30

对这个双向约束的求解如下:

r s t
A 26 26 27
B 26 26 28
C 26 26 29

D

27 27 28
E 27 27 29
F 28 28 29

4.7解的概率

没有约束的类

//SV绿皮书
//例6.24没有约束的类
class Unconstrained;rand bit x;       //0或1randc bit [1:0] y;//0,1,2或3
endclass

没有约束的类的概率是相等的,如下:

带有关系操作的类

//SV绿皮书
//例6.25带有关系操作的类
class Unconstrained;rand bit x;       //0或1randc bit [1:0] y;//0,1,2或3
constraint c_xy{(x==0) -> y==0;
}
endclass

带有关系操作的类的解如下(注意对比上一个例子):

带有关系操作和约束的类

//SV绿皮书
//例6.26带有关系操作和约束的类
class Unconstrained;rand bit x;       //0或1randc bit [1:0] y;//0,1,2或3
constraint c_xy{y > 0;(x==0) -> y==0;
}
endclass

使用solve...before约束引导概率分布(这个不太懂!)

//SV绿皮书
//例6.27带有关系操作和约束的类
class Unconstrained;rand bit x;       //0或1randc bit [1:0] y;//0,1,2或3
constraint c_xy{(x==0) -> y==0;solve x before y;
}
endclass

4.8控制多个约束块

使用rand_mode()函数可以关闭随机变量

  • 随机变量处于非激活状态,表示该变量不能声明为rand或randc
  • rand_mode()函数是SV的内建函数,不能被覆盖
  • 0-OFF:将随机变量设置为非激活状态( inactive),不能通过 randomize0函数进行随机化
  • 1- ON :将随机变量设置为激活状态( active),可以通过调用 randomize()函数随机产生数据

通过 constraint_mode()函数激活或关闭约束

  • 非激活状态的约束不能通过调用 randomize0函数随机化
  • 所有的约束初始状态都是激活状态
  • constraint_mode()函数是SV内建的函数,不能被覆盖
  • 0-OFF:将约束块设置为非激活状态( inactive), randomize0函数将不起作用
  • 1- ON :将约束块设置为激活状态( active), randomize()函数将起作用
//SV绿皮书
//例6.28使用constraint_mode函数
class Packet;rand int length;constraint c_short {length inside {[1:32]};}constraint c_long {length inside {[1000:1023]};}
endclassPacket p;
initial beginp=new();//通过禁止c_short约束产生长包p.c_short.constraint_mode(0);assert (p.randomize());transmit (p);//通过禁止所有的约束,然后使能短包约束来产生短包//then enabling only the short constraintp.constraint_mode(0);p.c_short.constraint_mode(1);assert (p.randomize());transmit (p);
end

写在最后:练习最重要!

SV随机化Randomization相关推荐

  1. 区组随机化-Block randomization、分组隐匿、双盲

    首先,分清楚一个概念:抽样和随机化 抽样sampling是从整体抽出一部分样本.随机化randomization是将样本分到不同的组,使得各组covariate-adaptive,即组间均衡可比 1, ...

  2. SV实验3 子系统验证和测试点划分

    文章目录 Testbench结构 划分测试功能点 仿真命令 之前学习的一些验证要素: 验证环境按隔离的概念,分为硬件DUT,软件testbench和接口interface: 验证阶段分为建立阶段(bu ...

  3. MCDF实验_lab4(4)

    目录 一.框架图 二.代码分析 reg_chnl reg_trans,传输的数据包 reg_generator reg_driver reg_monitor reg_agent fmt_pkg fmt ...

  4. IUS tcl cmd

    Incisive simulator中的command-line language基于TCL. Ncsim> command [-modifier] [-options] [arguments] ...

  5. SV复习(五)随机化

    目录 0. 基础 1. 随机化方法 2. Constraint 3. inside 4. dist 5. 条件约束 6. foreach 约束 7. disable constraint 7. sta ...

  6. 关闭aslr oracle,地址空间布局随机化 (Address Space Layout Randomization, ASLR)

    地址空间布局随机化 (Address Space Layout Randomization, ASLR) ASLR 是 Oracle Solaris 系统的一种功能,利用此功能可以随机生成进程地址空间 ...

  7. SV学习笔记—变量及数组随机化约束常犯的错误

    目录 1.有符号变量导致的随机化错误 2.变量溢出导致的随机化错误 3.数组的约束 3.1约束数组的size函数 3.2约束数组的sum函数 4.数组约束常犯错误 4.1有符号变量导致的错误 4.2溢 ...

  8. 一起来学孟德尔随机化(Mendelian Randomization)

    孟德尔随机化最近实在是太火了,想不关注都不行,最近也花了点时间研究了一下,和大家分享一下,共同学习. 什么是孟德尔随机化? 在19世纪,孟德尔用豌豆花作为实验材料,通过对豌豆花颜色.形状等特征的观察和 ...

  9. SV学习笔记—随机化约束的概率

    1.没有约束的类 x可能是0/1,y可能是0/1/2/3,是rand随机,每个数的概率相等: 运行800次,从结果看每个数出现的概率确实是1/8 2.关系操作 运行800次,从结果看,各个出现的值是1 ...

最新文章

  1. ACMNO.48 01字串
  2. codeblocks安装及使用教程(手把手傻瓜式教学)
  3. javascript 数字的常用方法
  4. Swift iOS : WebView缓存图片的方法
  5. jQuery制作动态酷效果总结
  6. 存储过程,游标和触发器实例
  7. cov(m[, y, rowvar, bias, ddof, fweights, …])
  8. (Ios 实战) 自定义UITableView
  9. 29.3. phpMyAdmin - MySQL web administration tool
  10. 【android高级编程】简答题汇总
  11. 姑娘美丽人体日志博客_60个美丽诱人的博客设计
  12. 微信小程序云开发教程-手把手:小程序数据库设计
  13. SJT生成排列(清华OJ)
  14. 苹果快捷键怎么调出来_iPhone手机没有声音怎么办?
  15. 影创科技助力云南首例MR混合现实肝脏手术成功实施
  16. SQL性能优化以及性能测试
  17. uniapp 上传图片 + 预览图片 + 删除图片
  18. 用Java写一个年薪计算器,助你简单完成大量税前税后总薪计算量
  19. csdn markdown编辑器设置字体大小和颜色换行
  20. 如何检验计算机主板的好坏,怎么判断笔记本主板、CPU硬件好坏? 查看电脑配置的教程...

热门文章

  1. c语言数组旋转90度,输入n*n的字符矩阵,把它旋转90度后输出??用c语言写,拜托了,急啊!!...
  2. 栈的应用--数制转换(十进制数转换为二进制、八进制、十六进制)
  3. 通过计算器引发对二进制、十六进制、bit、byte、字(word)、KB的概念的思考
  4. 考勤不是非得按指纹 刷脸操作更亲民!
  5. matlab 谐振峰,数字均衡器
  6. NVIDIA for Linux error :Dkms 的一些问题解决办法(gcc/g++的升级降级问题)
  7. java农行接口通讯代码_农行TrustPayClient-Java接口文档(参考)
  8. 苹果台式机回收平台如何选择
  9. 【学堂上新】用Lua打造类型系统:typesys
  10. 我在她心中到底是什么呢?