我是靠谱客的博主 笑点低斑马,最近开发中收集的这篇文章主要介绍随机化策略——随机变量rand、约束constraint、权重dist、随机数产生示例一、随机变量类型二、随机化约束操作三、启动随机化——randomize( )函数四、关闭或打开随机变量与约束——rand_mode( )和constraint_mode( )五、代码示例——随机数产生、权重的应用,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

  • 一、随机变量类型
    • 1.1.rand与randc随机变量
    • 1.2.constraint指定约束范围
  • 二、随机化约束操作
    • 2.1.关系操作符约束(>、<、=、>=、<=)
    • 2.2.范围操作符约束(inside)
    • 2.3.权重分布约束(dist)
    • 2.4.条件约束(if-else; ->)
    • 2.5.双向约束
    • 2.6.Onehot约束
    • 2.7.内嵌约束randomize ( )with{ }
    • 2.8.solve...before约束——改变数值出现的机率(见下一章)
  • 三、启动随机化——randomize( )函数
  • 四、关闭或打开随机变量与约束——rand_mode( )和constraint_mode( )
  • 五、代码示例——随机数产生、权重的应用

为什么要采用随机化验证策略?

  随机化策略指的是:激励随机化,配置随机化等。

  1)、对于较大的验证空间,随机化策略可以使验证有条件趋于量化流程,达到以时间换空间的效果。
  2)、使用随机化产生激励,可以很容易的在短时间内产生大量的随机激励,随机激励可以达到我们工程师可能会忽略的地方,相对于固定的激励(难以覆盖较大的可激励空间),随机化的激励可以用更为抽象的数据包传输,简化数据场景,更能验证出DUT可能隐藏的错误,提高验证的完备性

  所谓配置随机化指的是,测试平台配置的随机化。可配置的测试平台可以为DUT创造出多种模拟的运行环境,而且这种模拟的环境越多越好。比如DUT具有一个I2C Master接口,那么测试平台应该具有提供1个到多个Master和slave的能力。

  其实之所以需要随机化是因为工程师的思维总是具有局限性,不可能想到所有的测试情况。就算想到了所有的情况,那么也不可能付诸实践。比如要测试一个32位的加法器,如果要全部覆盖则需要2的33次方个定向的testcase。这是无论如何也做不到的。如果使用大量的随机测试,只要部分验证通过,我们就可以认为验证通过。

一、随机变量类型

随机化变量以及随机约束都只能在类class中声明

1.1.rand与randc随机变量

  1)、使用关键字rand声明随机变量,随机变量的值在指定范围内均匀分布;如果不添加约束,随机变量可以是指定有效范围内的任何值。

rand  bit[7:0]  y;      //y为8bit无符号整形数,取值范围:0~255,  每个数出现的概率都为1/256

  2)、使用关键字randc声明周期性随机变量,取值按照声明的有效范围周期性出现,且数据类型只可以是bit或者enum型。

randc  bit[1:0]  y;      //y为2bit无符号整形数,取值范围:0~3,      在一个周期内必然会产生0、1、2、3四个数,顺序不定

1.2.constraint指定约束范围

  使用关键字constraint来添加约束语句块,指定随机变量的取值范围,或者各个变量之间的相互关系。

  • 约束块不像是自上而下执行的程序性代码,它们是声明性代码,是并行的,所有的约束表达式同时有效。

在这里插入图片描述

二、随机化约束操作

2.1.关系操作符约束(>、<、=、>=、<=)

在这里插入图片描述

2.2.范围操作符约束(inside)

在这里插入图片描述

2.3.权重分布约束(dist)

在这里插入图片描述
在这里插入图片描述

2.4.条件约束(if-else; ->)

  ->操作符可以产生和case操作符类似效果的语句块,可以用于枚举类型的表达式。->与if-else约束可以相互转化。
在这里插入图片描述
在这里插入图片描述

2.5.双向约束

  约束块不像是自上而下执行的程序性代码,它们是声明性代码,是并行的,所有的约束表达式同时有效。如果你用inside操作符约束变量的取值范围为[10:50],然后用另一个约束表达式约束变量必须大于20,SV对这两个约束同时求解,最终限定变量的范围是21~50.

  SV的约束是双向的,这代表它会同时计算所有随机变量的约束,增加或删除任何一个约束都有可能对随机变量的取值产生影响。看下例:
在这里插入图片描述
在这里插入图片描述

2.6.Onehot约束

  对于多bit变量,有时需要所有bit位都有toggle以保证cover所有场景,这就要求约束相关变量为onehot类型,SV提供了位向量系统函数$countones函数来统计变量中1的个数,用户可以通过施加约束来实现该操作。

class onehot_const;
	rand bit[31:0]   dvfs_freq_vote_en;

	constraint fv_en_onehot_c{
	           $countones(dvfs_freq_vote_en[31:0]) == 1;
    }
endclass

  此外,SV还提供了其它系统函数,如$countbits(expression, control_bit {, control_bit})、$onehot (expression)、$onehot0(expression)、$isunknown (expression),其作用如下:

  • $countones(expression):统计expr中1的个数,等价于$conutbits(expression, '1),返回统计值
  • $countbits(expression, control_bit {, control_bit}) : 统计expr中指定的control_bit(0/1/x/z)的数量,返回统计值;
  • $onehot (expression) :判断expr是否为onehot类型,如果是,则返回真,否者返回假;
  • $onehot0(expression) :判断expr中至少有一位为高,如果是,则返回真,否者返回假;
  • $isunknown (expression):判断某个变量是否含有x态或者z态,如果有,则返回真,否者返回假。

2.7.内嵌约束randomize ( )with{ }

  随着测试的进行,面对的约束越来越多,它们会相互作用,最终产生难以预测的结果;用来使能和禁止这些约束的代码也会增加测试的复杂度。

  很多测试只会在代码的一个地方随机化对象,SV允许使用randomise( )with{}来增加额外的约束,这和在类里面增加约束是等效的。看下例:
在这里插入图片描述
注意:在with{}语句里,SV使用了类的作用域,所以在上例中使用了addr变量,而不是t.addr。

在使用randomise()with语句时常犯的错误就是使用()而不是{}内嵌的约束。记住,约束块应该使用{},内嵌约束也应该使用{},{}用于声明性的代码。

2.8.solve…before约束——改变数值出现的机率(见下一章)

三、启动随机化——randomize( )函数

  • 调用randomize( )函数可以为对象中的所有随机变量赋值,随机变量的值要符合约束;
  • randomize( )函数成功时,返回1,失败时返回0。如果随机变量没有添加约束,那么产生的值是有效范围内的任何值。

在这里插入图片描述

四、关闭或打开随机变量与约束——rand_mode( )和constraint_mode( )

  • constraint_mode()函数打开或关闭约束,是SV内建的类,非激活状态下的约束在调用randomize()函数时将失效;
  • 所有的约束初始状态都处于激活状态;
含义描述
0OFF约束语句块设为非激活态(INACTIVE),constraint约束将不起作用
1ON约束语句块设为激活态(ACTIVE),constraint约束将起作用
class  packet();
    rand  int   src, dst;
    constraint   filter {src>2*dst;}
endclass

function int toggle_rand(Packet p);
    if(p.filter.constraint_mode() == 1)
       p.filter.constraint_mode(0);      //关闭约束
    else
       p.filter.constraint_mode(1);      //打开约束
    toggle_rand = p.randomize();      //随机化返回函数值
endfunction
  • rand_mode()函数可以打开或关闭随机变量,是SV内建的类,随机变量处于非激活态时,表示该变量不被声明为rand或者randc
含义描述
0OFF随机变量设为非激活态(INACTIVE),不能通过randomize()函数随机化赋值
1ON随机变量设为激活态(ACTIVE),可以通过randomize()函数随机化赋值
class  Packet();
    rand  int   src, dst;
endclass

int   r;
Packet  packet_a = new;
packet_a.rand_mode(0);          //将Packet类中的两个随机变量设置为非激活态,即src与dst变为非随机变量,不能通过randomize函数赋值
packet_a.src.rand_mode(1);     //将Packet类中的src设置为激活态,可以通过randomize函数进行赋值
r=packet_a.dst.rand_mode();    //读取dst变量的激活状态

五、代码示例——随机数产生、权重的应用

1. 权重dist应用实例如下:
program distribution;
  class frame_t;
    rand bit [7:0] src_port;
    rand bit [7:0] des_port;
    rand bit [15:0] length;
    constraint len {
      length dist {
        [64  :  127 ] := 10,
        [128 :  511 ] := 10,
        [512 :  2048] := 10
      };
    }
    constraint src {
      src_port dist {
        0  := 1,
        1  := 1,
        2  := 5,
        4  := 1
      };
    }
    constraint des {
      des_port dist {
        [0   : 5   ] :/ 5,
        [6   : 100 ] := 1,
        [101 : 200 ] := 1,
        [201 : 255 ] := 1
      };
    }

    function void post_randomize();
      begin
        $display("src port : %0x",src_port);
        $display("des port : %0x",des_port);
        $display("length   : %0x",length);
      end
    endfunction
  endclass

  initial begin
    frame_t frame = new();
    integer i,j = 0;
    for (j=0;j < 4; j++) begin
      $display("-------------------------------");
      $display("Randomize Value");
      $display("-------------------------------");
      i = frame.randomize();
    end
    $display("-------------------------------");

打印结果如下:
	
 -------------------------------
 Randomize Value
 -------------------------------
 src port : 0
 des port : 36
 length   : bd
 -------------------------------
 Randomize Value
 -------------------------------
 src port : 2
 des port : 5e
 length   : 43b
 -------------------------------
 Randomize Value
 -------------------------------
 src port : 2
 des port : 83
 length   : 4fe
 -------------------------------
 Randomize Value
 -------------------------------
 src port : 2
 des port : e4
 length   : 6d9
 -------------------------------

2.  使用randc变量 ———— 随机产生1-10(1-100,1-10000)的随机数,且各个数字只出现一次;
program automatic dist10;
  class transaction;
    randc bit[31:0]    data;
    
    constraint data_c{ data >0; 
                       data <= 10;} 
                       
    function void post_randomize() ;
      $display("***%0d",data) ;
    endfunction
  endclass

initial begin
  transaction  tr=new();
  for(int i=0; i<10; i++)begin
    tr.randomize();
  end
end

endprogram

打印结果如下:
***4
***8
***9
***5
***3
***7
***2
***6
***10
***1

3. 使用数组函数shuffle ———— 随机产生1-10(1-100,1-10000)的随机数,且各个数字只出现一次
program gen_data;
  bit[31:0] a[10];     //定义容量为10的数组;

  initial begin
    for(int i=0; i<10; i++) begin
      a[i] = i;
    end

    a.shuffle() ;   //乱序处理
    for(int i=0; i<10; i++) begin
      $display("data= %0d", a[i]);
    end
  end

endprogram

打印结果如下:
data=8;
data=6;
data=7;
data=9;
data=5;
data=0;
data=1;
data=4;
data=2;
data=3;

参考:https://blog.csdn.net/weixin_34357962/article/details/85713203

最后

以上就是笑点低斑马为你收集整理的随机化策略——随机变量rand、约束constraint、权重dist、随机数产生示例一、随机变量类型二、随机化约束操作三、启动随机化——randomize( )函数四、关闭或打开随机变量与约束——rand_mode( )和constraint_mode( )五、代码示例——随机数产生、权重的应用的全部内容,希望文章能够帮你解决随机化策略——随机变量rand、约束constraint、权重dist、随机数产生示例一、随机变量类型二、随机化约束操作三、启动随机化——randomize( )函数四、关闭或打开随机变量与约束——rand_mode( )和constraint_mode( )五、代码示例——随机数产生、权重的应用所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(34)

评论列表共有 0 条评论

立即
投稿
返回
顶部