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随机化的更多相关文章

  1. SV中的随机化

    SV搭建testbench的关键概念:CRT(constraint random test),测试集的随机化. 由于对象class由数据和操作组成,所以对数据的随机化一般放在一个class内.(对环境 ...

  2. SV randomize

    randomize中的变量只支持2-state的values,不支持4-states. randc类型的变量不能被约束在solve------before的语句中. constraint可以被定义在c ...

  3. SV中的数据类型

    Verilog-1995中规定的数据类型有:变量(reg), 线网(wire), 32位有符号数(integer), 64位无符号数(time), 浮点数(real). SV扩展了reg类型为logi ...

  4. APP漏洞扫描用地址空间随机化

    APP漏洞扫描用地址空间随机化 前言 我们在前文<APP漏洞扫描器之本地拒绝服务检测详解>了解到阿里聚安全漏洞扫描器有一项静态分析加动态模糊测试的方法来检测的功能,并详细的介绍了它在针对本 ...

  5. 《HelloGitHub月刊》第06期

    前言 <HelloGitHub>月刊做到第06期了(已经做了6个月了),在GitHub上获得了100+的stars,虽然不多,但是我很知足了,说明有人觉得这个项目是有价值的.同时园子中的' ...

  6. iOS系列 基础篇 06 标签和按钮 (Label & Button)

    iOS系列 基础篇 06 标签和按钮 (Label & Button) 目录: 标签控件 按钮控件 小结 标签和按钮是两个常用的控件,下面咱们逐一学习. 1. 标签控件 使用Single Vi ...

  7. javaSE基础06

    javaSE基础06 一.匿名对象 没有名字的对象,叫做匿名对象. 1.2匿名对象的使用注意点: 1.我们一般不会用匿名对象给属性赋值的,无法获取属性值(现阶段只能设置和拿到一个属性值.只能调用一次方 ...

  8. 异步编程系列06章 以Task为基础的异步模式(TAP)

    p { display: block; margin: 3px 0 0 0; } --> 写在前面 在学异步,有位园友推荐了<async in C#5.0>,没找到中文版,恰巧也想提 ...

  9. 挣值管理(PV、EV、AC、SV、CV、SPI、CPI) 记忆

    挣值管理法中的PV.EV.AC.SV.CV.SPI.CPI这些英文简写相信把大家都搞得晕头转向的.在挣值管理法中,需要记忆理解的有三个参数:PV.AC.EV.     PV:计划值,在即定时间点前计划 ...

随机推荐

  1. NR / 5G - MAC Overview

  2. Keras学习系列——神经网络层组件

    对Keras提供的对各种层的抽象进行相对全面的概括 1 基础常用层 名称 作用 原型参数 Dense 实现全连接层 Dense(units,activation,use_bias=True, kern ...

  3. 使用chrome控制台调试js代码

    1.打开控制台(空白页签即可) 2.将控制台在独立页打开(点击控制台右上角的三个点图标,然后点击如下图中的图标) 3.创建脚本编辑页面 4.页面区域说明 5.花键+回车之行代码 6.常用命令介绍 6. ...

  4. CSS选择器有哪些?选择器的优先级如何排序?

    CSS选择器分类: CSS的选择器分类可以分为三大类:id选择器,类选择器,标签选择器. 用法如下: 选择器   e.g. 说明 id选择器 #id #header 选择id="header ...

  5. OpenLayers 6 学习笔记2 WMS服务避坑记录

    心血来潮,花1小时安装软件写代码+复习api,顺便熟悉一波wms 再次强化认知了wms获取要素的能力没有wfs强,有待考究 原文链接(转载请声明@秋意正寒  博客园/知乎/B站/csdn/小专栏):h ...

  6. linux下tar命令解压到指定的目录

    linux下tar命令解压到指定的目录 : #tar zxvf xx.tar.gz -C /xx//把根目录下的xx.tar.gz解压到/xx/下,前提要保证存在/xx这个目录 这个和cp命令有点不同 ...

  7. 重新安装python后,原来在虚拟环境里的django项目启动报错:dyld: Library not loaded: @executable_path/../.Python Referenced from: /Users/mac/.virtualenvs/WYGBlog-env/bin/python Reason: image not found

    因为当你创建一个虚拟环境的时候,一些软链接创建到原来的python上. 当用Homebrew更新python后,原来软连接对应的python已经不存在了. 因此需要把软链接指向新的python. 解决 ...

  8. 学习 Vim 命令总结

    学习 Vim 命令总结 可以使用 vscode-vim 扩展,但是要注意一些ctrl+字母的快捷键会无效,必须去掉冲突的快捷键 esc 回到普通模式 i 普通模式进入插入模式 : 进入命令模式 :wa ...

  9. python基础之字典功能

    python中字典是个很重要的功能,使用键值(key-value)存储,具有极快的查找速度.值得注意的是,字典的key要为不可变对象,比如字符串.字母,但不能是可变的,比如列表等. 1.字典的定义: ...

  10. [CF1311B] WeirdSort

    Solution 按照 \(p[i]\) 进行分段,如果某个 \(k\) 不存在 \(p[i]=k\),那么就把 \(i,i+1\) 分割开 处理出每一段的左端点和右端点 进而处理出每段的最小值和最大 ...