目录

1. 前言

2. 约束语法

  2.1 约束表达式

  2.2 权重约束

  2.3 条件约束

  2.4 双向约束

  2.5 内嵌约束

  2.6 数组约束

3.约束的使用

  3.1 使用非随机值(rand_mode)

  3.2 随机化个别变量

  3.3 打开/关闭约束(constraint_mode)

  3.4 pre_randomize和post_randomize的使用

4. 随机化函数


1. 前言

    针对复杂的设计,仅依靠定向测试已不能够完全覆盖所有的代码逻辑。因此需要采用受约束的随机测试法(Constrain Random Test)来自动产生非定向测试集。

2. 约束语法

  2.1 约束表达式

       只可对由位组成的变量(整数、位矢量)进行随机化,字符串不可进行随机。

       变量随机化包含三部分,一是采用(rand or randc)进行变量定义;二是采用constraint关键字对变量进行约束;三是采用randomize函数生成随机值。rand和randc关键字区别如下:

rand:每次随机化时,这个变量都会生成一个值,相邻两次两次随机可能会产生一样的值;

randc:周期随机性,当该变量所有可能的值都产生过后,下次随机才会产生一样的值;

        约束的表达式如示例,注意要检查随机化的结果,随机化失败,变量可能会生成未知的值。

class packet;
    rand logic [3:0] src,dst;  
    randc logic [9:0] data;
    constrain rand_cons {
             src > 0;
             src < 10;
             dst > 0;
    }
    constrain randc_cons {
             data > 100;
    }
endclass

module test_tb;
    packet p;
    initial begin
        p = new();
        assert(p.randromize()); //随机化成功则返回1,否则返回0触发断言

    end
endmodule

除此以外,还可将数学运算加进约束,示例:

class packet;
    rand logic [9:0] addr;  
    rand logic [4:0] odd_dat, even_dat;
    constrain addr_cons {
        addr % 8 == 0;
    }
    constrain dat_cons {
        odd_dat %2 == 1;
        even_dat %2 == 0;
    }
endclass

  2.2 权重约束

       通过使用dist操作符生成不同权重的随机值,dist操作符后面跟一个值或范围,中间用:=或:/分开。两个符号的区别如下:

:=   表示值范围内的每一个值的权重是一样的;

:/    表示权重均分到值范围内的每一个值;

注意dist后的权重和不一定是100。inside操作符生成权重相同的随机值。示例如下:

class packet;
    rand logic [4:0] src,dst;
    rand logic [9:0] addr;
    constrain addr_cons {
        src dist {0:=40, [1:3]:=60};
        //src=0, 概率为40/220
        //src=1, 概率为60/220
        //src=2, 概率为60/220
        //src=3, 概率为60/220
    }
    constrain dst_cons {
        dst dist {0:/40, [1:3]:/60};
        //dst=0, 概率为40/100
        //dst=1, 概率为20/100
        //dst=2, 概率为20/100
        //dst=3, 概率为20/100
    }
    constrain addr_cons {
        addr inside {[$:10],[100:$]}; //$表示最大值,最小值
        //每个值概率一样
    }

endclass

  2.3 条件约束

    通过 "->" 和 "if-else" 操作符让约束块只在某种条件下有效,示例如下:

class packet;
    bit  en;
    rand logic [1:0] src,dst;
    rand logic [1:0] addr;
 
    constrain src_dst_cons {
        (src==0) -> dst==0; //表示src=0的时候,dst只能取0
    }
    constrain addr_cons {
        if (en !=0 ) {
          src inside {[1:3]}; //表示en不等于0时,src在1~3里随机
          dst inside {[1:3]};
        }
        else {
            src == 0;
            dst == 0;
        }   
    }

使用solve...before约束引导概率分布(只适用于rand操作符),示例如下:

class packet;
    rand bit x;
    rand logic [1:0] y;
 
    constrain rand_cons {
        (x==0) -> y==3; 
    }
    constrain xy_cons {
        (x==0) -> y==3; 
        solve x before y; //表示先驱x的值,再取y的值
    }
endclass

rand_cons约束条件下,当x=0,y只能为3;而x=1,y可取0,1,2,3四种组合,所以共有5种组合,每种组合概率相同,均为1/5;如下表:

xy概率
031/5
101/5
111/5
121/5
131/5

 xy_cons约束条件下,先取x的随机值,x=0/1的概率均为1/2;在确定有的取值,概率如下表:

xy概率
031/2*1=1/2
101/2*1/4=1/8
111/2*1/4=1/8
121/2*1/4=1/8
131/2*1/4=1/8

  2.4 双向约束

多个随机变量可以双向约束,示例如下:

class packet;
    rand logic [4:0] x, y, z;
    constrain xyz_cons {
        x < y;
        y > 5;
        z < x;
        x > 1;
    }
endclass

  2.5 内嵌约束

    通过randomize() with语句实现内嵌约束,示例如下:

class packet;
    rand logic [3:0] addr;  
    rand logic [9:0] data;
    constrain addr_cons {
             addr inside {[0:9], [13:15]};
    }
endclass

module test_tb;
    packet p;
    initial begin
        p = new();
        assert(p.randromize() with {addr == 0;
                                    data > 100;}); // 强制addr=0,data>10
        assert(p.randromize() with {addr > 5;
                                    data > 20;}); 

    end
endmodule

  2.6 数组约束

    对数组的和、深度和每个值的范围进行约束,示例如下:

class packet;
    rand logic [4:0] len[];
    constrain len_cons {
        len.size() inside {[5:10]};
        len.sum < 50;
        foreach (len[i])
            len[i] inside {[1:4]};
    }
endclass

3.约束的使用

  3.1 使用非随机值(rand_mode)

      经过一段时间的随机化后,有些变量的某些值还没有随机到,可以通过rand_mode函数将这些变量设置为固定值,示例如下:

class packet;
    rand logic [3:0] addr;  
    rand logic [9:0] data;
    constrain addr_cons {
             addr inside {[0:9], [13:15]};
    }
endclass

module test_tb;
    packet p;
    initial begin
        p = new();
        assert(p.randromize());
        ...
        p.data.rand_mode(0);
        p.data = 541;
        assert(p.randromize()); //生成的data值固定为541,addr随机

    end
endmodule

  3.2 随机化个别变量

     只对类中的某几个变量进行随机,示例如下:

class packet;
    rand logic [3:0] addr;  
    rand logic [9:0] data;
    constrain addr_cons {
             addr inside {[0:9], [13:15]};
    }
endclass

module test_tb;
    packet p;
    initial begin
        p = new();
        assert(p.randromize(addr)); //随机化addr
        assert(p.randromize(data)); //随机化data
    end
endmodule

  3.3 打开/关闭约束(constraint_mode)

采用constraint_mode函数将某些变量的约束关掉,示例如下:

class packet;
    rand logic [3:0] addr;  
    rand logic [9:0] data;
    constrain addr_cons {
             addr inside {[0:9], [13:15]};
    }
    constrain data_cons {
             data inside {[10:105]};
    }
endclass

module test_tb;
    packet p;
    initial begin
        p = new();
        p.constraint_mode(0); //关闭所有变量的约束 
        p.addr_cons.constraint_mode(1); //打开addr的约束 
        assert(p.randromize());
    end
endmodule

  3.4 pre_randomize和post_randomize的使用

    pre_randomize和post_randomize为void类型函数,不需要单独调用。无返回值,不能消耗时间,不能有阻塞操作,可以由用户重写。类随机化的执行顺序为:

pre_randomize() -> randomize() -> post_randomize()

因此可以在pre_randomize函数里设置一些约束权重,约束上下限等,在post_randomize函数里计算一些随机数据等。示例如下:

class packet;
	rand bit[7:0] x,y,z;
	bit en = 0;
	constrain xyz_cons {
		if(a==0)
			z==x+y;
		else
			z==x;
	}
	function void pre_randomize();
		en = 1;
	endfunction
	function void post_randomize();
		z = y;
	endfunction
endclass

module test_tb;
	packet p;
	initial begin
	    p = new();
        assert(p.randomize());
	end
endmodule

4. 随机化函数

随机化函数功能
$random()平均分布,返回32位有符号随机数
$urandom()平均分布,返回32位无符号随机数
$urandom_range()指定范围内的平均分布,必须指定上限,下限可选
$dist_exponential()指数衰落
$dist_normal()钟型分布
$dist_poisson()钟型分布
$dist_uniform()平均分布

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐