SV 学习笔记(四)随机与约束

一、随机约束与分布

1.1 随机变量

>只能在class中声明随机变量
>rand: 随机变量关键字
>randc: 周期性随机性,范围内不可重复
>a.randomize(): 随机化
class Packet;
	rand  bit [31:0] src, dst, data[8] ;
	randc bit [7 :0] kind;
	constraint C{src > 10 ;
				 src < 15;}
endclass

Packet p;
initial begin
	P=new();
	assert (p.randomize()) //返回1,随机化成功,返回0,随机化失败
	else
		$fatal(0,"Packet:: randomize failed");
	transmit(p) ;
end

1.2 约束

class date;
rand bit [3:0] month;
rand bit [4:0] day ;
rand int year ;
constraint C_date {
	month inside { [1:12]} ;
	day inside { [1:31]} ;
	year inside { [2010:2030] } ;
endclass

1.2.1 数值分布约束

  1. constraint c_stim { len < 1000; len > 0;}
  2. constraint c_stim { len inside { [0,1000] };}
  3. up/down
class Stim;
	const bit [31:0] CONGEST_ADDR=42;//常量
	typedef enum {READ, WRITE, CONTROL} stim_e ;//枚举类型
	randc stim_e kind; //随机变量
	Enumerated var rand bit [31:0] len, src, dst;//随机变量
	bit congestion test;
	constraint c_stim {
		len < 1000;
		len > 0;//可以改为len inside {[0,1000]};
		if (congestion_test) {//非随机可以置于约束里
			dst inside { [CONGEST_ADDR-100 : CONGEST_ADDR+100]};
			//inside表示内部,花括号表示范围,中括号表示集合
			src == CONGEST_ ADDR ;
		}
		else
			src inside {0, [2:10], [100:107]};
	} ;
endclass

1.2.2 权重分布约束:dist

“ : = ”每一个值的权重相同
“ : / ”每一个值的权重平分

rand int src, dst;
constraint c_dist {
src dist {0:=40, [1:3] :=60} ;
// src = 0,weight = 40/220
// src = 1,weight = 60/220
// src = 2,weight = 60/220
// src = 3, weight = 60/220
dst dist {0:/40, [1:3] :/60} ;
// dst = 0, weight = 40/100
// dst = 1,weight = 20/100
// dst = 2, weight = 20/100
// dst = 3, weight = 20/100

使用"$"指定最大值和最小值

randbit[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<= 127
	e inside {[$:4], [20:$}; //0 <= e <= 4 || 20 <= e<= 63
}

1.2.3 条件约束

>通过->来让一个约束表达式在特定时刻有效
>if-else
class BusOp ;
...
	constraint c_io {
		(io_space_mode) ->//如果成立,执行后面语句,相当于if
			addr[31] == 1'b1 ;
	}
class BusOp;
constraint C_len_rw {
	if (op == READ)
		len inside { [BYTE : LWRD]} ;
	else
		len == LWRD ;
}

1.2.4 双向约束

>约束条件不是自上而下的,删改任何约束都会影响输出序列
>约束会被继承
rand logic [15:0] r, s, t;
constraint C_bidir {
			r<t;
			s==r;
			t<30;
			s>25;}

1.3 约束块控制

1.3.1 打开和关闭约束

>p.c.constraint_mode()有条件的打开和关闭约束
class Packet;
	rand int length; 
	constraint c_short {length inside {[1:32]}; }
	constraint c_1ong  {length inside {[1000:1023]}; }//有冲突的两个约束
endclass

Packet P;
initial begin
	P=new();
	// Create a long packet by disabling short constraint
	P.c_short.constraint_mode(0) ;//关掉一个约束
	assert (P.randomize()) ;//返回1,随机化成功,返回0,随机化失败
	transmit(P) ;
	// Create a short packet by disabling all constraints then enabling only the short constraint
	P.constraint_mode(0);
	P.c_short.constraint_mode(1);
	assert(P.randomize());
	transmit(p) ;
end

1.3.2 内嵌约束

复杂的约束会相互作用,constraint_mode使能和禁止约束代码

1.3.3 额外约束

randomize() with增加额外的约束;
内部约束与外部约束应该协调
soft为软约束,其他约束优先

class Transaction; 
	rand bit [31 :0] addr, data ;
	constraint c1 {	soft addr inside{ [0:100], [1000:2000]} ;}//**soft**软约束,其他约束优先
endclass
Transaction t;
initial begin
	t=new();
	// addr is 50-100 ,
	// 1000-1500, data < 10
	assert(t.randomize() with{addr >= 50; addr <= 1500; data < 10;}) ;
	driveBus(t) ;
	// force addr to a specific
	// value, data > 10
	assert (t.randomize() with	{addr==2000;data>10;});
	driveBus (t) ;
end

二、随机函数

2.1 内置随机函数

pre_randomize()->randomize();->post_randomize()
内置回调函数,在调用randomize之前或之后立即执行的操作用这两个函数

2.2 随机数函数

>$random()平均分布,返回32位有符号随机数
>$urandom()平均分布,返回32位无符号随机数
>$urandom_range()在指定范围内平均分布

2.3 随机化个别变量

>随机化只会随机化在调用randomize()时传递的变量,其它变量不会被随机化
>所有约束仍然有效
class Rising;
	byte low;
	rand byte med, hi;
	constraint up {low < med; med < hi}
endclass
initial begin
	Rising r;
	r = new();
	r.randomize();//随机化med和hi,但不改变low; 0;2;5
	r.randomize(med);//只随机化med;			  0;3;5
	r.randomize(low);//只随机化low			   ;3;5

三、数组约束

3.1 数组的大小约束

>多数情况下,数组大小应该给出约束 s.size()
class dyn_size;
	rand logic [31:0] d[];
	constraint d_size {s.size() inside {[1:10]};
endclass

3.2 数组的属性约束

>约束中结合数组其它方法
>sum(); product(); and(); or(); xor()

3.3 数组的元素约束

>foreach: 对数组每个元素进行约束
class good_sum5;
	rand uint len[];
	constriant c_len{
		foreach (len[i]) 
			len[i] inside{[1:255]};
		len.sum() < 1024;
		len.size() inside{[1:8]};
	}
endclass

3.4 产生唯一元素值的数组

foreach与rand 产生唯一元素值的数组

class UniqueSlow;
	rand bit[7:0] ua[64];
	constraint c {
		foreach(ua[i])//对数组每个元素操作
			foreach(ua[j])
				if(i != j)//除了元素自己
					ua[i] != ua[j];//和其他元素比较
	}
endclass

randc 产生唯一元素值的数组

class randc8;
	randc bit[7:0] val;
endclass
class LittleUniqueArray;
	bit [7:0] ua[64];//没有用rand修饰
	function void pre_randomize();//再调用randomize()函数时实际是调用的这个函数
		randc8 rc8;
		rc8 = new();//同一个对象
		foreach(ua[i]) begin
			assert(rc8.randomize());
			ua[i] = rc8.val;//将val中的64/256给ua
		end
	endfunction
endclass
//unique 产生唯一元素值的数组

3.5 随机化句柄数组

句柄被声明为rand时,表示两层含义:

  1. 句柄为rand,句柄指向的对象也会被随机化,因此句柄不能悬空;
  2. 句柄指向对象里有没有变量也被rand修饰
parameter MAX_SIZE = 10;
class RandStuff;
	bit[1:0] value = 1;//不是随机变量,随机化句柄不会改变value的值;改为rand修饰时,在随机化句柄时也会随机化该值
endclass
class RandArray;
	rand RandStuff array[];//定义一个随机化数组变量
	constraint c {
		array.size() inside {[1:MAX_SIZE]};}
	function new();//构造函数里,实例化数组中每个句柄指向的实例
		//分配最大容量
		array = new[MAX_SIZE];
		foreach(array[i])
			array[i] = new();
	endfunction	
endclass

RandArray ra;
initial begin
	ra = new();//构造数组与对象
	//随机化数组
	assert(ra.randomize());//必须要指向对象才能随机化成功
	foreach(ra.array[i])
		$display(ra.array[i].value);
end

四、随机控制

4.1 随机序列

randsequence产生事物序列

initial begin
	for(int i = 0; i < 15; i++) begin
		randsequence(stream)//stream为入口,stream下进入其他入口,但进入到权重不同
			stream: cfg_read := 1 |
					io_read  := 2 |
					mem_read := 5;
			cfg_read: {cfg_read_task;} |//一般继续该任务
					  {cfg_read_task;} cfg_read;//或继续执行cfg_read
			mem_read: {mem_read_task;} |
					  {mem_read_task;} mem_read;
			io_read:  {io_read_task;}  |
					  {io_read_task;}  io_read;
		endsequence;
	end
end

4.2 随机控制

randcase 建立随机决策树,但没有变量可供追踪调试

initial begin
	int len;
	randcase
		1: len = $urandom_range(0,2);// 10%权重进入该语句
		8: len = $urandom_range(3,5);
		1: len = $urandom_range(6,7);
	endcase
	$display("len = %0d",len);
end
  • 3
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小鱼爱学习,每天好心情

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值