system verilog语法(二)

随机约束

1、随机化是为了产生更多可能的驱动,因此在软件世界“class”一侧的运用更多,所以我们倾向于将相关数据有机整理在一个类的同时,用rand关键词来表明它们的随机属性。
randc表示周期随机性,即所有可能的值都赋过值后随机值才可能重复。

2、随机属性需要配合SV预定义的类随机函数std::randomize()使用。即只有通过声明rand变量,并且在后期通过对象调用randomize()函数才可以随机化变量。

3、约束constraint也同随机变量一起在类中声明。
SV只能随机化2值数据类型,但位可以是2值或4值。这即是说,无法随机化出X值和Z值,也无法随机化字符串。

3.1、关键词dist可以在约束中用来产生随机数值的权重分布,这样某些值的选取机会要比其他值更大一些。
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
}

3.2、inside是常见的约束运算符,表示变量应该属于某一个值的集合,除非还存在其他约束,否则随机变量在集合里取值的概率是相等的。集合里也可以使用变量。

3.3、可以通过->或者if-else来让一个约束表达式在特定时刻有效。

4、对于其它情况,例如根据不同需要,来选择使能哪些约束块,禁止哪些约束块的要求,可以使用内建的constraint_mode()函数打开或者关闭约束。

5、SV允许使用randomize() with来增加额外的约束,这和在类里增加约束是等效的,但同时要注意类内部约束和外部约束之间应该是协调的,如果出现互相违背的情况,那么随机数值求解会失败。

6、有时需要在调用randomize()之前或之后立即执行一些操作,例如在随机前设置类例的一些非随机变量(上下限、条件值、权重),或者在随机化之后需要计算随机数据的误差、分析和记录随机数据等。

SV提供了两个预定义的void类型函数pre_randomize()和post_randomize()函数。用户可以类中定义这两个函数,分别在其中定义随机化前的行为和随机化后的行为。

如果某个类中定义了pre_randomize()或者post_randomize()函数,那么对象在执行了randomize()之前或者之后会分别执行这两个函数。所以,pre_randomize()和post_randomize()可以看做是randomize()函数的回调函数(callback function)。

7、SV提供了一些常用的系统随机函数。这些随机函数可以直接调用来返回随机数值。
$random() 平均分布,返回32位有符号随机数。
$urandom()平均分布,返回32位无符号随机数。
$urandom_range() 在指定范围内的平均分布

8、随机化个别变量

class Rising;
  byte low; // Not random
  rand byte med, hi; // Random variable
  constraint up
    { low < med; med < hi; } 
endclass
initial begin
  Rising r;
  r = new();
  r.randomize(); // 随机化hi,但不改变low
  r.randomize(med); // 只随机化med
  r.randomize(low); // 只随机化low
end

9、在约束随机标量的同时,我们还可以对随机化数组进行约束。

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

SV可以利用foreach对数组的每一个元素进行约束,和直接写出对固定大小数组的每一个元素的约束相比,foreach要更简洁。

10、产生事务序列的另一个方法是使用SV的randsequence结构。这对于随机安排组织原子(atomic)测试序列很有帮助。

initial begin
  for (int i=0; i<15; i++) begin
    randsequence (stream)
      stream : cfg_read := 1 |
               io_read := 2 |
				  mem_read := 5;
      cfg_read : { cfg_read_task; } |
                 { cfg_read_task; } cfg_read;
      mem_read : { mem_read_task; } |
                 { mem_read_task; } mem_read;
      io_read : { io_read_task; } |
                { io_read_task; } io_read;
    endsequence
  end // for
end

我们可以使用randcase来建立随机决策树,但它带来的问题是没有变量可供追踪调试。

initial begin
  int len;
  randcase
    1: len = $urandom_range(0, 2); // 10%: 0, 1, or 2
    8: len = $urandom_range(3, 5); // 80%: 3, 4, or 5
    1: len = $urandom_range(6, 7); // 10%: 6 or 7
  endcase
  $display("len=%0d", len);
end

randsequence和randcase是针对轻量级的随机控制的应用。而我们可以通过定义随机类取代上述随机控制的功能,并且由于类的继承性使得在后期维护代码时更加方便。
randsequence的相关功能我们在协调激励组件和测试用例时,可能会用到。
randcase则对应着随机约束中的dist权重约束+if-else条件约束的组合。

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值