路科V0P19P22随机变量-随机约束-约束控制-任务和函数
随机变量
- 随着设计越来越大,要产生完整的激励来测试设计的功能变得越来越困难;
- 定向激励的测试方法已经无法满足检查功能完整性的要求;
- Soc集成度提高带来的模块之间交互的复杂性也指数提高,验证工程师无法预测用户使用过程中发生什么样的情况;
概述:
- 随机-约束: 构成目前动态仿真验证的主流方法;
- 随机约束测试:CRT, constrained-random test,即能够产生感兴趣的、想不到的测试向量,通过回归测试、替换随机种子的方式来提高单位测试用例的覆盖率收集效率;
- 随机测试带来的负担是验证环境的复杂度提高,不再只需要发送激励的组件,还包括监测器、比较器等;
- 对环境复杂度还包括环境的复用和测试的复用,带来组件封装要求,使得代码量增大;
产生一个随机数
利用系统函数产生一个随机数
randomize
函数产生随机数,如果随机成功,返回1,否则0;- 通过系统函数
std::randomize()
对一些变量完成随机化,即产生随机数并赋值给这些向量; - 还有一些其他的系统函数:
$urandom()
产生一个32位无符号的随机数;$urandom_range(max_val, minval=0)
, 可以生成介于maxval和minval之间的随机数;
1 | module stim; |
系统有机的组织随机变量
- 比起独立的产生随机数,在向DUT产生随机激励时,为了符合协议、满足测试需求,还需要添加一些约束;
- 这些约束会使得变量朝着希望他们变化的方向去随机;
- 这些约束也会对变量和变量之间的关系生效;
- 需要一个载体去容纳变量和他们之间的约束;
- 这个载体是类,类的成员变量可以声明“随机”属性,用rand或者randc表示;
随机变量
- 任何类中的整型(bit、byte、int)变量都可以声明为rand、randc;
- 定长数组、动态数组、关联数组和队列都可以声明为rand、randc;
- 可以对动态数组和队列的长度加以约束;
- 指向对象的句柄,也可以声明为rand,不能randc,随机时该句柄指向的对象中的随机变量会一起被随机化;
- 非组合型结构体可以声明为rand,非组合型的成员也可以声明为rand、randc;
1 | rand bit [7:0] len; |
rand和randc
- rand: 表示在可生成范围内,每个值得可能性是相同的–>每次都是有放回!!
rand bit [7:0] y;
- randc: 它的值会随机,并且遍历可取值范围,–>无放回!!
随机约束
带有随机约束的简单类
1 | class Packet; |
约束块
- 有用的激励不仅会约束随机变量,变量之间也存在互相约束关系;
- 没有约束的随机变量会包含很多无效的和非法的值,会使得有效激励变得低效;
- 类需要用一个或者多个约束块来描述变量之间的关系;
- 约束块支持整型通过
inside
操作符来设置可取值的范围;
1 | rand integer x,y,z; |
权重分布
- 除了成员集合设置,约束块也支持设置可取值的同事为其设置随机时的权重;
:=
: 表示每个值的权重都是相同的;:/
: 表示权重会平均分配到每一个值;
1 | x dist { [100:102] := 1, 200 := 2, 300 := 5}; // 权重分布:1 1 1 2 5 |
唯一标识
unique
: 可以用来约束一组变量,使得其随机后变量之间不会有相同的数值;
1 | rand byte a[5]; |
条件约束
- 可以使用
if-else
或者->
操作符表示条件约束;
1 | constraint c1 { |
迭代约束
foreach
可以用来迭代约束数组中的元素,这些数组可以是定长数组、动态数组、关联数组或者队列;
1 | class C; |
- 也可以用数组的缩减方法进行迭代约束
1 | class C; |
函数调用
- 有时候,在一些表达式中不能简单的描述约束,比如计算一个组合数组中的’1’;
- 可以写成一个函数,然后约束调用这个函数;
1 | function int count_ones (bit [9:0] w); |
软约束 和 硬约束
- 为了防止约束冲突时执行失败,分为软约束和硬约束;
soft
: soft描述的约束是软,没有soft是硬;- 如果用户在使用时,制订了外部约束对同一个变量做了二次约束,或者用户定义了子类,也对同一个变量做了二次约束,那么硬约束可以覆盖软约束,不会导致随机失败;
1 | class Packet; |
约束控制
随机方法
- 类的声明中的随机变量,需要伴随类的句柄的调用randomize(),这是SV的内建方法
virtual function int randomize();
- 随机化成功返回1,否则0;
- 随机化之前需要先对对象完成例化,例化时没有随机的过程;
内嵌约束
- 在调用
randomize()
时伴随with
,称为内嵌约束;
1 | class C; |
local域指向
- 同名的变量处于不同的域中,可能出现指向模糊,可以使用上文的方法;
- 也可以使用
local::
域索引到方式;
1 | class C; |
随机控制
rand_mode
可以用来使能或者禁止成员变量的随机属性;- 当随机模式被禁止时,就相当于一个普通变量了;
- 可以禁止某个变量的随机模式,也可以对整个对象调用
rand_mode
进行控制;
constraint_mode()
用来关闭或者使能约束块;
1 | task object[.random_variable]::rand_mode(bit on_off); |
内嵌变量控制
- 一个有意思的点,如果在
randomize()
中有参数,则只会对这个参数进行随机化,别的就算是rand也不随机化了;
任务和函数
概述
- function和task都是提高代码复用性和整洁度;
- function:
- 首要目的在于为运算表达式提供返回值,便于简化原有代码,提高维护性;
- void函数无返回值;
- 一个function只能有一个返回值,所以函数可以作为表达式的操作数,因为就一个值;
- 函数的参数方向可以声明为:input、output、inout、ref
- 函数可以调用函数,但是必须立即返回,不能阻塞等待!
- 函数返回方式有两种,一个是return直接返回,一个是将值或者表达式赋给函数的同名变量;
- 区别在于return会立即返回,但是赋值同名变量之后,后续的代码还会执行下去;
- 可以对有返回值的函数进行类型转换,
void'(func1)
,这时候用不到函数的返回值;
- task:
- 同样的参数列表指名四个方向;
- task无返回值!
- task可以用来消耗仿真时间,内置一些阻塞语句;
- 可以使用return立刻结束task;
- task可以调用task和function,但是function只能调用function,不能调用task;
1 | logic red; |
参数传递
- input : 在方法调用时,属于值传递,在传递的过程中,外部变量的值经过拷贝,赋值给输入参数;
- output、inout都是值传递,发生在方法调用和返回时;
- ref参数不会传递值拷贝,而是将变量指针传递到方法中,所以方法内部的操作会影响到外部的变量;
- 为了避免外部传入的ref参数被方法修改,可以添加const修饰符;
- SV允许在声明输入参数时,指定参数的默认值;
- 除了按照参数位置传递参数,SV也允许像module例化一样,用参数名字映射的方式传递参数;
1 | task read(int j=0, int k, int data=1); |
路科V0P19P22随机变量-随机约束-约束控制-任务和函数
https://dustofstars.github.io/IC验证/路科V0/路科v0p19p22随机变量-随机约束-约束控制-任务和函数/