导图社区 sv-W8随机约束
约束表达式的求解是由SV的约束求解器(constraint solver)完成的 求解器能够选择满足约束的值,这个值是由SV的PRNG伪随机数发生器从一个初始值seed产生。只要改变种子的值,就可以改变C...
编辑于2022-11-07 18:07:25 陕西随机约束
概述
设计变大,产生完整激励变得困难;定向激励无法满足要求;模块之间复杂度增加
随机约束测试
产生意想不到的测试向量,通过回归测试、替换随机种子的方式来提高单位测试用例的覆盖率收集效率
随机测试使得环境复杂度增加、更易集成复用
随机约束
产生一个随机数
利用系统函数
独立随机数
std::andomize()
$urandom()
32位无符号随机数
$urandom_range(maxval,minval=0)
产生max和min之间的数
随机约束
“约束”
“载体”:类
随机变量
任何类中的整形(bit/byte/int)变量
定长数组、动态数组、关联数组和队列
动态数组和队列的长度需要加以约束
非组合型成员
rand、randc类型
非组合型结构体
句柄
该句柄指向对象中的随机变量也会被一并随机
rand类型
带有随机变量的实例
简单类
class packet rand bit [31:0] src ,dst data[4]; rand bit [7:0] kind; constraint cstr { src > 10; src < 15 } function void print(); $display("src is %0d\n dst is %0d\n kind is %0d\n data is %p", src, dst , kind, data) endfunction endclass module tb; pcaket p; ;//声明句柄 initial begin p = new();//例化 $display("before randomize"); p.print(); p.randomize();//随机化 $display("after randomize"); p.print(); end endmodule
结构体
tybedef struct{ rand bit [31:0] src; rand bit [31:0] dst; rand bit [31:0] data[4]; rand bit [7:0] kind; }packet_t module tb2; //rand packet_t pkt;模块里不能用rand packet_t pkt; initial begin //pkt.randomize(); 调用函数方式为类的,结构体不可以这么用 $display("before randomize packet struct ::src is %0d\n dst is %0d\n kind is %0d\n data is %p", pkt.src, pkt.dst , pkt.kind, pkt.data) //in-line/dynamic/temporary constraint std::randomize(pkt) with {pkt.src > 10 ;pkt.src <15}; $display("after randomize packet struct ::src is %0d\n dst is %0d\n kind is %0d\n data is %p",pkt.src, pkt.dst , pkt.kind, pkt.data) end endmodule
类调用结构体
class packet2; rand packet_t pkt; function void print(); $display("src is %0d\n dst is %0d\n kind is %0d\n data is %p", src, dst , kind, data) endfunction endclass module tb4; pcaket p; initial begin p = new(); $display("before randomize"); p.print(); p.randomize(); $display("after randomize"); p.print(); end endmodule
模块
module tb3; bit [31:0] src; bit [31:0] dst; bit [31:0] data[4]; bit [7:0] kind; initial begin $display("before randomize packet struct ::src is %0d\n dst is %0d\n kind is %0d\n data is %p", src, dst , kind, data) std::randomize(src, dst, data, kind); // src = $urandom(); // dst = $urandom(); // data[0] = $urandom(); // .. // data[3] = $urandom(); // kind = $urandom(); $display("after randomize packet struct ::src is %0d\n dst is %0d\n kind is %0d\n data is %p",src, dst , kind, data) end endmodule
修饰符rand和randc
rand:表示在可生成的范围内,每个值的可能性相同
每次随机化在一副新的扑克牌中抽取
randc:其值将会随机并遍历其可取值范围
下次随机化在上次抽取剩下的牌中抽取,等待新一轮开始时,同一数字才会出现
约束块constraint
定义变量之间的相互关系
成员集合:约束块支持整形通过set操作符来设置他们的可取值范围
权重分布:设置取值时的权重
“=”:权重相同
“/”:权重平均分配
唯一标识unique
使随即后的变量之间不会有相同的数值
条件约束
if-else or ->
迭代约束
foreach
数组的缩减方法
函数调用
软约束
情况1: module tb5; class packet_a; rand int length; constraint cstr{length inside {[5:15]};} endclass class packet_b extends packet_a; rand int length; constraint cstr {length inside {[10:20]};}//约束同名,运行时子类覆盖父类的约束 endclass initial begin packet_b pkt = new(); repeat(100) begin if(pkt.randomize()) $display("pkt.length is %0d",pkt.length) else $erro("randomize failure") end endmodule 情况2: module tb5; class packet_a; rand int length; constraint cstr1{length inside {[5:15]};} endclass class packet_b extends packet_a; rand int length; constraint cstr2{length inside {[10:20]};}//约束不同名,子类和父类的约束均需要满足,若约束条件之间冲突,则会出现随机失败(两者都是硬约束) endclass .... endmodule 情况3: module tb5; class packet_a; rand int length; constraint cstr1{soft ength inside {[5:15]};} endclass class packet_b extends packet_a; rand int length; constraint cstr2{length inside {[16:20]};}//follow 硬约束cstr2; endclass ... endmodule 情况4: module tb5; class packet_a; rand int length; constraint cstr{soft length inside {[5:15]};} endclass class packet_b extends packet_a; rand int length; constraint cstr {soft length inside {[10:20]};} endclass initial begin packet_b pkt = new(); repeat(100) begin if(pkt.randomize() with {soft length inside{[21:25]};}) $display("pkt.length is %0d",pkt.length) //约束条件就近 else $erro("randomize failure") end endmodule
带有soft描述的约束
指定变量的默认值和权重
外部约束对同一变量做二次约束时,硬约束可以覆盖,而软约束会导致随即失败
随机方法randomize
module tb6; class simplesum; rand bit[7:0] x,y; bit[8:0] z; constraint cstr{ z == x+y; } endclass initial begin simplesum ss = new(); repeat(10 )begin 情况1:if (ss.randomize())等同于(x,y) .. //z=0 x=y=0 情况2:if (ss.randomize(x,y,z)) .. //x,y,z均会被随机化 情况3:if (ss.randomize(z)) .. //x,y有rand属性,但没有被randomize,x=y=0 z=0 else $erro end end endmodule
随机化成功返回1,失败返回0
内嵌约束
指向模糊
local::的域索引
情况1: module tb7; class packet1; rand bit[7:0] x; constraint cstr {soft x == 5;} endclass class packet2; bit [7:0] x=10; function int get_rand_x(input bit[7:0] x=20); packet1 pkt =new(); pkt.randomize with {x == x}; return pkt.x; endfunction endclass initial begin packet2 pkt = new(); $display("pkt.x = %0d",pkt.get_rand_x()); //x=5 end endmodule 情况2: module tb7; class packet1; rand bit[7:0] x; constraint cstr {soft x == 5;} endclass class packet2; bit [7:0] x=10; function int get_rand_x(input bit[7:0] x=20); packet1 pkt =new(); pkt.randomize with {x == local::x}; return pkt.x; endfunction endclass initial begin packet2 pkt = new(); $display("pkt.x = %0d",pkt.get_rand_x()); //x=10 end endmodule 情况3: module tb7; class packet1; rand bit[7:0] x; constraint cstr {soft x == 5;} endclass class packet2; bit [7:0] x=10; function int get_rand_x(input bit[7:0] x=20); packet1 pkt =new(); pkt.randomize with {x == local::this.x}; return pkt.x; endfunction endclass initial begin packet2 pkt = new(); $display("pkt.x = %0d",pkt.get_rand_x()); //输出x的默认值x=20 end endmodule 情况4: module tb7; class packet1; rand bit[7:0] x; constraint cstr {soft x == 5;} endclass class packet2; bit [7:0] x=10; function int get_rand_x(input bit[7:0] x=20); packet1 pkt =new(); pkt.randomize with {x == local::this.x}; return pkt.x; endfunction endclass initial begin packet2 pkt = new(); $display("pkt.x = %0d",pkt.get_rand_x(30)); //x=30 end endmodule
指向明确
随机控制rand_mode
packet.rand_mode(0)
所有的rand变量不参与随机变化
packet.src.rand_mode(1)
类packet中的src变化
约束控制constraint_mode
内嵌变量控制
在使用类的随机化函数randomize()时,如果伴有参数,那么只会随机化这些变量,而其余变量无论是否之前被声明为rand/randc,都将不会参与到随机化中。