《SystemVerilog验证测试平台编写指南》学习笔记——随机化(二)

一、解的概率

1、没有约束的类

没有约束的两个随机变量

class Unconstrainted;
	rand bit x;		//0或1
	rand bit[1:0] y		//0,1,2,3
endclass

在这里插入图片描述

2、关系操作

带有关系操作的类

class Imp1;
	rand bit x;		//0或1
	rand bit[1:0] y		//0,1,2,3
	
	constraint c_xy{
		(x == 0) -> y == 0;
	}
endclass

在这里插入图片描述

3、关系操作和双向约束

带有关系操作和约束的类

class Imp2;
	rand bit x;		//0或1
	rand bit[1:0] y		//0,1,2,3
	
	constraint c_xy{
		y > 0;		//因为双向,所以x值不可能为0
		(x == 0) -> y == 0;
	}
endclass
/*
关系操作规定x==0时,y的值为0,但是y==0时,对x的值没有约束。
由于关系操作是双向的,如果y的值为非0值,那么x的值将为1。
*/

在这里插入图片描述

4、使用solve…before约束引导概率分布

使用solve…before和关系操作的类

class SolveBefore;
	rand bit x;		//0或1
	rand bit[1:0] y		//0,1,2,3
	
	constraint c_xy{
		(x == 0) -> y == 0;
		slove x before y;		//不会改变解的个数,只会改变各个值得概率分布
	}

二、控制多个约束块

一个类可以包含多个约束块,可以把不同的约束块用于不同的测试。在运行期间,可以使用内建的constraint_mode()函数打开或关闭约束。可以用handle.constrain.constraint_mode()控制一个约束块,用handle.constraint_mode()控制对象的所有约束。

使用constraint_mode()函数

class Packet;
	rand int length;
	constraint c_short{length inside {[1:32]};}
	constraint c_long{length inside {[1000:1023]};}
endclass

Packet p;
initial begin
	p = new();
	
	//通过禁止c_short约束产生长包
	p.c_short.constraint_mode(0);
	assert(p.randomize());

	transmit(p);

	//通过禁止所有的约束,然后使能短包约束来产生短包
	p.constraint_mode(0);
	p.c_short.constraint_mode(1);
	assert(p.randomize());

	transmit(p);
end

三、有效性约束

设置多个约束以保证随机激励的正确性是一种很好的随机化技术,也成为有效性约束。

使用有效性约束检查写命令的数据字长

class Transaction;
	rand enum{BYTE,WORD,LWRD,QWRD} length;
	rand enum{READ,WRITE,RMW,INTR} opc;

	constraint valid_RMW_LWRD{
		(opc == RMW) -> length == LWRD;
	}
endclass

四、内嵌约束

SV中允许使用randomize() with来添加额外的约束,这和类里增加约束是等效的。

class Transaction;
	rand bit[31:0] addr,data;
	constraint c1{addr inside {[0:100],[1000:2000]};}
endclass

Transaction t;
initial begin
	t = new();
	//addr范围:50-100,1000-1500,data<10;
	assert(t.randomize() with {addr >= 50; addr <= 1500; data < 10;});		//相当于在原来的约束范围内新加了一个约束范围
	driveBus(t);
	//强制addr取固定值,data>10
	assert(t.randomize() with (addr == 2000; data > 10;));
	driveBus(t);
end
/*
在with{}语句里,SV使用了类的作用域,是addr而不是t.addr
*/

五、pre_randomize和post_randomize函数

有时候需要在调用randomize()之前或之后立即执行一些操作,可以使用两个特殊的void类型的pre_randomize和post_randomize函数。

1、构造浴缸型分布

某些应用里需要产生非线性的随机分布。如短包或长包比中等长度的包更容易发现缓冲器溢出类型的错误。可以通过详细描述的dist约束构造浴缸型的分布。
在这里插入图片描述

构造浴缸型分布

class Bathtub;
	int value;		//浴缸型分布的随机变量
	int WIDTH = 50, DEPTH = 4, seed = 1;

	function void pre_randomize();
		//计算指数曲线
		value = $dist_exponential(seed,DEPTH);		//非线性分布的函数
		if(value > WIDTH)
			value = WIDTH;
		
		//把这一个点随机地放在左边或右边的曲线上
		if($urandom_range(1))
			value = WIDTH - value;
	endfunction
endclass

2、关于void函数

因为pre_randomize和post_randomize函数只能调用其他函数,不能调用消耗时间的任务,所以在执行randomize()函数的期间无法产生一段延时。如果想调试随机化过程中出现的问题,可以调用预先准备好的void类型的显示程序来显示中间结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值