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

一、随机数函数

  1. $random()——平均分布,返回32位有符号随机数
  2. $urandom()——平均分布,返回32位无符号随机数
  3. $urandom_range()——指定范围内的平均分布
  4. $dist_exponential()——指数衰落
  5. $dist_normal()——钟型分布
  6. $dist_poisson()——钟型分布
  7. $dist_uniform()——平均分布

二、约束的技巧和技术

1、使用变量的约束

使用变量设定上限的约束

class bounds;
	rand int size;
	int max_size = 100;
	constraint c_size{
		size inside {[1:max_size]};
	}
endclass

带有权重变量的dist约束

typedef enum{READ8,READ16,READ32} read_e;
class ReadCommands;
	rand read_e read_cmd;
	//可以通过修改权重,来改变命令产生的概率,置0的话相当于禁止某些命令的产生
	int read8_wt = 1, read16_wt = 1, read32_wt = 1;
	constraint c_read{
		read_cmd dist {
			READ8:=read8_wt,
			READ16:=read16_wt,
			READ32:=read32_wt
		};
	}
endclass

2、使用非随机值

可以设置固定激励值,来得到想要的结果。设定的固定激励值可以违反相关的约束。

用rand_mode禁止变量的随机化

class Packet;
	rand bit[7:0] length,payload[];
	constraint c_valid {
		length > 0;
		payload.size == length;
	}
	
	function void display(string msg);
		$display("\n% s", msg);
		$write("Packet len=%0d,payload size=%0d,bytes=",length, payload.size());
		for(int i = 0; (i < 4 && i < payload.size(); i++)
			$write("%0d",payload[i]);
		$display;
	endfunction
endclass

Packet p;
initial begin
	p = new();
	assert(p.randomize());
	p.display("Simple randomize");

	p.length.rand_mode(0);		//设置包长为非随机值
	p.length = 42;		//设置包长为常数
	assert(p.randomize()); 		//然后再随机化payload
	p.display("Randomize with rand_mode");
end

3、用约束检查值的有效性

在随机化一个对象并改变它的变量的值后,可以通过检查值是否遵守约束来检查对象是否仍然有效。

4、随机化个别变量

随机化类里的一部分变量

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
	r.randomize(med);		//随机化med
	r.randomize(low);		//也可以传递一个非随机变量,随机化low

5、打开或关闭约束

可以使用条件操作符->或者if-else来构建由非随机变量控制的约束。

把条件约束当成case语句使用

class Instruction;
	typedef enum{NOP,HALT,CLR,NOT} opcode_e;
	rand opcode_e opcode;
	bit[1:0] n_operands;
	...
	constraint c_operands{
		if(n_operands == 0)
			opcode == NOP || opcode == HALT;
		else if(n_operands == 1)
			opcode == CLR || opcode == NOP;
		...
	}
endclass

使用constraint_mode打开或关闭约束

//当约束表达式越来越多,越来越复杂时,通常对每一种指令建立一套独立的约束,在使用时关闭其他所有的约束。

class Instruction;
	typedef enum{NOP,HALT,CLR,NOT} opcode_e;
	rand opcode_e opcode;
	bit[1:0] n_operands;
	...
	constraint c_no_operands{
			opcode == NOP || opcode == HALT;
			}
			
	constraint c_one_operand{
			opcode == CLR || opcode == NOP;
			}
endclass

Instruction instr;
initial begin
	instr = new();
	//产生没有操作数的指令
	instr.constraint_mode(0);		//关闭所有的约束
	instr.c_no_operands.constraint_mode(1);
	assert(instre.randomize());
	//产生只有一个操作数的指令
	instr.constraint_mode(0);
	instr.c_one_operands.constraint_mode(1);
	assert(instr.randomize());
end

三、迭代和数组约束

1、数组的大小

约束动态数组的大小

class dyn_size;
	rand logic[31:0] d[];
	constraint d_size{
		d.size() inside {[1:10]};
		}
endclass

2、元素的和

随机脉冲类

parameter MAX_TRANSFER_LEN = 10;

class StrobePat;
	rand bit strobe[MAX_TRANSFER_LEN];
	constraint c_set_four{
		strobe.sum() == 4'h4;
		}
endclass

initial begin
	StrobePat sp;
	int count = 0;
	sp = new();
	assert(sp.randomize());
	foreach(sp.strobe[i]) begin
		@bus.cb;
		bus.cb.strobe <= sp.strobe[i];
		if(sp.strobe[i])
			bus.cb.data <= data[count++];
	end
end

3、产生具有唯一元素值的数组

使用foreach产生唯一的元素值

//循环产生过多的独立的约束,会降低仿真的速度
class UniqueSlow;
	rand int[7:0] ua[64];
	constraint c{
		foreach(ua[i])
			foreach(ua[j])
				if(i!=j)
					ua[a]!=ua[j];
	}
endclass

使用randc辅助类产生唯一的元素值

class randc8;	
	randc bit[7:0] val;
enclass

class LittleUniqueArray;
	bit[7:0] ua[64];		//每一个元素具有唯一值的数组

	function void pre_randomize;
		randc8 rc8;
		rc8 = new();
		foreach(ua[i]) begin
			assert(rc8.randomize());
			ua[i] = rc8.val;
		end
	endfunction
endclass

唯一值的发生器

class RandRange;
	randc bit[15:0] value;
	int max_value;
	
	function new(int max_value = 10);
		this.max_value = max_value;
	endfunction

	constraint c_max_value{
		value < max_value;
		}
endclass

产生元素具有唯一值的随机数组的类

class UniqueArray;
	int max_array_size,max_value;
	rand bit[7:0] a[];		//每个元素具有唯一值的数组
	
	constraint c_size{
		a.size() inside {[1:max_array_size]};
		}
		
	function new(int max_array_size = 2, max_value = 2);
		this.max_array_size = max_array_size;
		//如果max_value小于数组的大小,说明数组里有重复的值,要调整max_value
		if(max_value < max_array_size)
			this.max_value = max_array_size;
		else
			this.max_value = max_value;
	endfunction
	
	//为数组a[]填充唯一值
	function void post_randomize;
		RandcRange rr;
		rr = new(max_value);
		foreach(a[i]) begin
			assert(rr.randomize());
			a[i] = rr.value;
		end
	endfunction
	
	function void display();
		$write("Size: % 3d:", a.size());
		foreach(a[i])
			$write("%4d", a[i]);
		$display;
	endfunction
endclass

program automatic test;
	UniqueArray ua;
	initial begin
		ua = new(50);
		repeat(10) begin
			assert(ua.randomize());
			ua,display();
		end
endprogram

4、随机化句柄数组

和整数数组不同的是,句柄数组需要在随机化前分配所有的元素,因为随机求解器不会创建对象。在随机化时,动态句柄数组的大小可以保持不变或者减小,但是不能增加。

parameter MAX_SIZE = 10;

class RandStuff;
	rand int value;
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
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值