SV_11_随机约束
摘要:约束驱动的测试生产允许用户为功能验证自动生成测试,随机测试比传统的、直接的测试方法更有效,随机测试可以找到直接测试难以覆盖的内容。SV允许用户声明随机约束,由求解器处理约束,生产满足约束的随机值。
- verilog使用$random产生随机整数,默认32位;
- SV添加了rand变量、randc变量、randomize()方法以及randomize_mode()的随机开关等。
1. 随机变量
SV可以随机化SV支持的所有变量;
数组也可以进行随机化声明;
1.1两种变量类型
- rand:随机平均分布;
- randc:随机周期出现
- 随机循环遍历范围内的所有值;
- 变量只能是reg或enum类型;
- 最大位数为16位,数值范围为0-65535。
1 typedef enum { UNICAST=11, MULTICAST, BROADCAST} pkt_type; 2 3 program rand_ex; 4 class frame_t; 5 rand pkt_type ptype; 6 rand integer len; 7 randc bit [1:0] no_repeat; 8 rand bit [7:0] payload []; 9 // Constraint the members 10 constraint legal { 11 len >= 2; 12 len <= 5; 13 payload.size() == len; 14 } 15 function string getType(pkt_type ltype); 16 begin 17 case(ltype) 18 UNICAST : getType = "UNICAST"; 19 MULTICAST : getType = "MULTICAST"; 20 BROADCAST : getType = "BROADCAST"; 21 default : getType = "UNKNOWN"; 22 endcase 23 end 24 endfunction 25 // Print the members of the class 26 task print(); 27 begin 28 integer i =0; 29 $write("Packet type %s\n",getType(ptype)); 30 $write("Size of frame is %0d\n",len); 31 if (payload.size() > 0) begin 32 $write("Payload is "); 33 for (i=0; i < len; i++) begin 34 $write(" %2x",payload[i]); 35 end 36 $write("\n"); 37 end 38 $write("no_repeat is %d\n",no_repeat); 39 end 40 endtask 41 endclass 42 43 initial begin 44 frame_t frame = new(); 45 integer j = 0; 46 // Print frame before randomize 47 $write("-------------------------------\n"); 48 frame.print(); 49 $write("-------------------------------\n"); 50 for (j = 0 ; j < 10;j++) begin 51 if (frame.randomize() == 1) begin 52 // Print frame after randomize 53 frame.print(); 54 end else begin 55 $write("Failed to randomize frame\n"); 56 end 57 $write("-------------------------------\n"); 58 end 59 end 60 endprogram 61 62 //compile result 63 ------------------------------- 64 Packet type UNKNOWN 65 Size of frame is x 66 no_repeat is 0 67 ------------------------------- 68 Packet type MULTICAST 69 Size of frame is 3 70 Payload is 0b df 40 71 no_repeat is 0 72 ------------------------------- 73 Packet type BROADCAST 74 Size of frame is 3 75 Payload is fa 4e 15 76 no_repeat is 1 77 ------------------------------- 78 Packet type BROADCAST 79 Size of frame is 5 80 Payload is c4 aa c4 cf 4f 81 no_repeat is 2 82 -------------------------------
2. randomize()
- constraint_mode()
- rand_mode()
- randmize() with
- pre_randomize()
- post_randomize()
2.1 constraint_mode()
- constraint_mode():控制随机约束的开启,初始状态都是激活的;
1 task object[.constraint_identifier]::constraint_mode( bit on_off ); 2 or 3 function int object.constraint_identifier::constraint_mode();
1 typedef enum {UNICAST=11,MULTICAST,BROADCAST} pkt_type; 2 3 program constaint_mode_ex; 4 class frame_t; 5 rand pkt_type ptype; 6 rand integer len; 7 rand bit [7:0] payload []; 8 constraint common { 9 payload.size() == len; 10 } 11 // Constraint the members 12 constraint unicast { 13 len <= 2; 14 ptype == UNICAST; 15 } 16 // Constraint the members 17 constraint multicast { 18 len >= 3; 19 len <= 4; 20 ptype == MULTICAST; 21 } 22 function string getType(pkt_type ltype); 23 begin 24 case(ltype) 25 UNICAST : getType = "UNICAST"; 26 MULTICAST : getType = "MULTICAST"; 27 BROADCAST : getType = "BROADCAST"; 28 default : getType = "UNKNOWN"; 29 endcase 30 end 31 endfunction 32 // Print the members of the class 33 task print() ; 34 begin 35 integer i =0; 36 $write("Packet type %s\n",getType(ptype)); 37 $write("Size of frame is %0d\n",len); 38 if (payload.size() > 0) begin 39 $write("Payload is "); 40 for (i=0; i < len; i++) begin 41 $write(" %2x",payload[i]); 42 end 43 $write("\n"); 44 end 45 end 46 endtask 47 endclass 48 49 initial begin 50 frame_t frame = new(); 51 integer j = 0; 52 $write("-------------------------------\n"); 53 // Do contraint for Unicast frame 54 frame.multicast.constraint_mode(0); 55 if (frame.multicast.constraint_mode() == 0) begin 56 if (frame.randomize() == 1) begin 57 frame.print(); 58 end else begin 59 $write("Failed to randomize frame\n"); 60 end 61 end else begin 62 $write("Failed to disable constraint multicast\n"); 63 end 64 $write("-------------------------------\n"); 65 // Check the status of constraint multicast 66 $write ("Constraint state of multicast is %0d\n", 67 frame.multicast.constraint_mode()); 68 $write("-------------------------------\n"); 69 // Now disable the unitcast and enable multicast 70 frame.unicast.constraint_mode(0); 71 frame.multicast.constraint_mode(1); 72 if (frame.randomize() == 1) begin 73 frame.print(); 74 end else begin 75 $write("Failed to randomize frame\n"); 76 end 77 $write("-------------------------------\n"); 78 end 79 endprogram 80 81 //compile result 82 ------------------------------- 83 Packet type UNICAST 84 Size of frame is 1 85 Payload is 7d 86 ------------------------------- 87 Constraint state of multicast is 0 88 ------------------------------- 89 Packet type MULTICAST 90 Size of frame is 3 91 Payload is df 40 f7 92 -------------------------------
2.2 rand_mode()
- 控制随机的开启,初始状态都是激活的;rand_mode()可作为函数进行调用。
1 task object[.random_variable]::rand_mode( bit on_off ); 2 or 3 function int object.random_variable::rand_mode();
1 program rand_mode_ex; 2 class frame_t; 3 rand bit [7:0] src_addr; 4 rand bit [7:0] dst_addr; 5 task print(); 6 begin 7 $write("Source address %2x\n",src_addr); 8 $write("Destination address %2x\n",dst_addr); 9 end 10 endtask 11 endclass 12 13 initial begin 14 frame_t frame = new(); 15 integer j = 0; 16 $write("-------------------------------\n"); 17 $write("Without Randomize Value\n"); 18 frame.print(); 19 $write("-------------------------------\n"); 20 $write("With Randomize Value\n"); 21 j = frame.randomize(); 22 frame.print(); 23 $write("-------------------------------\n"); 24 $write("With Randomize OFF and Randomize\n"); 25 frame.rand_mode(0); 26 j = frame.randomize(); 27 frame.print(); 28 $write("-------------------------------\n"); 29 $write("With Randomize ON and Randomize\n"); 30 frame.rand_mode(1); 31 j = frame.randomize(); 32 frame.print(); 33 $write("-------------------------------\n"); 34 $write("With Randomize OFF on dest addr and Randomize\n"); 35 frame.dst_addr.rand_mode(0); 36 j = frame.randomize(); 37 frame.print(); 38 $write("-------------------------------\n"); 39 end 40 endprogram 41 42 //compile result 43 Without Randomize Value 44 Source address 00 45 Destination address 00 46 ------------------------------- 47 With Randomize Value 48 Source address 36 49 Destination address 3c 50 ------------------------------- 51 With Randomize OFF and Randomize 52 Source address 36 53 Destination address 3c 54 ------------------------------- 55 With Randomize ON and Randomize 56 Source address 7d 57 Destination address e2 58 ------------------------------- 59 With Randomize OFF on dest addr and Randomize 60 Source address 0b 61 Destination address e2 62 -------------------------------
2.3 randomize() with
- 用于在调用randomize()类方法的时候声明一个内联约束;
- 内联约束的形式与对象约束形式相同;
- 内联约束与对象约束一起应用。
1 inline_constraint _declaration ::= 2 class_variable_identifier . randomize [ 3 ( [ variable_identifier_list | null ] ) ] 4 with constraint_block
1 program randomize_with; 2 class frame_t; 3 rand bit [7:0] src_addr; 4 rand bit [7:0] dst_addr; 5 constraint c { 6 src_addr <= 127; 7 dst_addr >= 128; 8 } 9 task print(); 10 begin 11 $write("Source address %2x\n",src_addr); 12 $write("Destination address %2x\n",dst_addr); 13 end 14 endtask 15 endclass 16 17 18 initial begin 19 frame_t frame = new(); 20 integer i = 0; 21 $write("-------------------------------\n"); 22 $write("Randomize Value\n"); 23 i = frame.randomize(); 24 frame.print(); 25 $write("-------------------------------\n"); 26 $write("Randomize with Value\n"); 27 i = frame.randomize() with { 28 src_addr > 100; 29 dst_addr < 130; 30 dst_addr > 128; 31 }; 32 frame.print(); 33 $write("-------------------------------\n"); 34 end 35 endprogram 36 37 //compile result 38 ------------------------------- 39 Randomize Value 40 Source address 02 41 Destination address ab 42 ------------------------------- 43 Randomize with Value 44 Source address 79 45 Destination address 81 46 -------------------------------
2.3 pre/post_randomize()
每个类都会包含pre/post_randomize()函数,在每次randomize()之前之后都会调用。
- 当object.randomize()被调用时,它首先对object及其所有启用的随机对象调用pre_randomize()。然后递归地调用super.pre_randomize()。然后递归调用super.post_randomize()来执行操作;
- 可以重载任何类中的pre_randomize()来执行初始化,设置前提条件;可以重载任何类中的post_randomize()来执行清理、打印诊断和检查随机对象的后置条件。
1 program pre_post_randomize; 2 3 class frame_t; 4 rand bit [7:0] data; 5 bit parity; 6 constraint c { 7 data > 0; 8 } 9 function void pre_randomize(); 10 begin 11 $write("pre_randomize : Value of data %b and parity %b\n",data,parity); 12 end 13 endfunction 14 function void post_randomize(); 15 begin 16 parity = ^data; 17 $write("post_randomize : Value of data %b and parity %b\n",data,parity); 18 end 19 endfunction 20 endclass 21 22 initial begin 23 frame_t frame = new(); 24 integer i = 0; 25 $write("-------------------------------\n"); 26 $write("Randomize Value\n"); 27 $write("-------------------------------\n"); 28 i = frame.randomize(); 29 $write("-------------------------------\n"); 30 end 31 endprogram 32 33 //compile result 34 35 ------------------------------- 36 Randomize Value 37 ------------------------------- 38 pre_randomize : Value of data 00000000 and parity 0 39 post_randomize : Value of data 00000110 and parity 0 40 -------------------------------
3. constraint blocks
- inclusive and exclusive (set membership)
- distribution
- conditional constraint
- foreach
3.1 set membership
- inclusive:inside { set [ set] };
- exclusive:!( expression inside { set [ set ] } );
1 program set_membership; 2 class frame_t; 3 rand bit [7:0] src_port; 4 rand bit [7:0] des_port; 5 constraint c { 6 // inclusive 7 src_port inside { [8'h0:8'hA],8'h14,8'h18 }; 8 // exclusive 9 !(des_port inside { [8'h4:8'hFF] }); 10 } 11 function void post_randomize(); 12 begin 13 $display("src port : %0x",src_port); 14 $display("des port : %0x",des_port); 15 end 16 endfunction 17 endclass 18 19 initial begin 20 frame_t frame = new(); 21 integer i,j = 0; 22 for (j=0;j < 4; j++) begin 23 $display("-------------------------------"); 24 $display("Randomize Value"); 25 $display("-------------------------------"); 26 i = frame.randomize(); 27 end 28 $display("-------------------------------"); 29 end 30 endprogram 31 32 //compile result 33 ------------------------------- 34 Randomize Value 35 ------------------------------- 36 src port : 3 37 des port : 2 38 ------------------------------- 39 Randomize Value 40 ------------------------------- 41 src port : 0 42 des port : 2 43 ------------------------------- 44 Randomize Value 45 ------------------------------- 46 src port : 18 47 des port : 3 48 ------------------------------- 49 Randomize Value 50 ------------------------------- 51 src port : 2 52 des port : 0 53 -------------------------------
3.2 distributions constraints
权重分布
1 2 constraint_block ::= 3 ... 4 | expression dist { dist_list } ; 5 dist_list ::= dist_item { , dist_item } 6 dist_item ::= value_range [ dist_weight ] 7 dist_weight ::= 8 := expression 9 | :/ expression 10 dist_item ::= 11 value_range := expression 12 | value_range :/ expression 13 expression_or_dist ::= expression [ dist { dist_list } ]
- := weight (直接指定权重);
- :/ weight (所有元素平均分配权重);
1 program distribution; 2 class frame_t; 3 rand bit [7:0] src_port; 4 rand bit [7:0] des_port; 5 rand bit [15:0] length; 6 constraint len { 7 length dist { 8 [64 : 127 ] := 10, 9 [128 : 511 ] := 10, 10 [512 : 2048] := 10 11 }; 12 } 13 constraint src { 14 src_port dist { 15 0 := 1, 16 1 := 1, 17 2 := 5, 18 4 := 1 19 }; 20 } 21 constraint des { 22 des_port dist { 23 [0 : 5 ] :/ 5, 24 [6 : 100 ] := 1, 25 [101 : 200 ] := 1, 26 [201 : 255 ] := 1 27 }; 28 } 29 30 function void post_randomize(); 31 begin 32 $display("src port : %0x",src_port); 33 $display("des port : %0x",des_port); 34 $display("length : %0x",length); 35 end 36 endfunction 37 endclass 38 39 initial begin 40 frame_t frame = new(); 41 integer i,j = 0; 42 for (j=0;j < 4; j++) begin 43 $display("-------------------------------"); 44 $display("Randomize Value"); 45 $display("-------------------------------"); 46 i = frame.randomize(); 47 end 48 $display("-------------------------------"); 49 end 50 51 endprogram 52 //compile result 53 54 ------------------------------- 55 Randomize Value 56 ------------------------------- 57 src port : 0 58 des port : 36 59 length : bd 60 ------------------------------- 61 Randomize Value 62 ------------------------------- 63 src port : 2 64 des port : 5e 65 length : 43b 66 ------------------------------- 67 Randomize Value 68 ------------------------------- 69 src port : 2 70 des port : 83 71 length : 4fe 72 ------------------------------- 73 Randomize Value 74 ------------------------------- 75 src port : 2 76 des port : e4 77 length : 6d9 78 -------------------------------
3.3 Implication constraints
两种约束条件声明:
- =>
- if - else
1 program conditional_con; 2 class frame_t; 3 typedef enum {RUNT,NORMAL,OVERSIZE} size_t; 4 rand bit [15:0] length; 5 rand size_t size; 6 7 constraint frame_sizes { 8 size == NORMAL -> { 9 length dist { 10 [64 : 127 ] := 10, 11 [128 : 511 ] := 10, 12 [512 : 1500] := 10 13 }; 14 } 15 if (size == RUNT) { 16 length >= 0; 17 length <= 63; 18 } else if (size == OVERSIZE) { 19 length >= 1501; 20 length <= 5000; 21 } 22 } 23 function void post_randomize(); 24 begin 25 $display("length : %0d",length); 26 case(size) 27 RUNT : $display ("Frame size_t is RUNT"); 28 NORMAL : $display ("Frame size_t is NORMAL"); 29 OVERSIZE : $display ("Frame size_t is OVERSIZE"); 30 endcase 31 end 32 endfunction 33 endclass 34 35 initial begin 36 frame_t frame = new(); 37 integer i,j = 0; 38 for (j=0;j < 4; j++) begin 39 $write("-------------------------------\n"); 40 $write("Randomize Value\n"); 41 i = frame.randomize(); 42 end 43 $write("-------------------------------\n"); 44 end 45 46 endprogram 47 48 //compile result 49 50 ------------------------------- 51 Randomize Value 52 length : 4948 53 Frame size_t is OVERSIZE 54 ------------------------------- 55 Randomize Value 56 length : 4317 57 Frame size_t is OVERSIZE 58 ------------------------------- 59 Randomize Value 60 length : 1774 61 Frame size_t is OVERSIZE 62 ------------------------------- 63 Randomize Value 64 length : 610 65 Frame size_t is NORMAL 66 -------------------------------
3.4 Iterative constraints
迭代约束条件允许使用循环变量和索引表达式以参数化的方式约束数组变量
- foreach 构造器指定对数组元素的迭代。
1 program iterative_con; 2 class frame_t; 3 rand bit [15:0] data []; 4 5 constraint frame_sizes { 6 data.size inside {[1:10]}; 7 foreach (data[i]) 8 data[i] == i; 9 } 10 function void post_randomize(); 11 begin 12 $display("length : %0d", data.size()); 13 for (integer i = 0; i < data.size(); i++) begin 14 $write ("%2x ",data[i]); 15 end 16 $write("\n"); 17 end 18 endfunction 19 endclass 20 21 initial begin 22 frame_t frame = new(); 23 integer i,j = 0; 24 for (j=0;j < 4; j++) begin 25 $write("-------------------------------\n"); 26 $write("Randomize Value\n"); 27 i = frame.randomize(); 28 end 29 $write("-------------------------------\n"); 30 end 31 32 endprogram 33 34 //compile result 35 36 ------------------------------- 37 Randomize Value 38 length : 4 39 00 01 02 03 40 ------------------------------- 41 Randomize Value 42 length : 2 43 00 01 44 ------------------------------- 45 Randomize Value 46 length : 8 47 00 01 02 03 04 05 06 07 48 ------------------------------- 49 Randomize Value 50 length : 9 51 00 01 02 03 04 05 06 07 08 52 -------------------------------
4. Variable Ordering
- 求解者必须确保所选的随机值在合法值组合上具有一定的值分布。
- SV提供了solve before 关键字;
1 program ordering; 2 class frame_t; 3 rand bit zero; 4 rand bit [15:0] data []; 5 6 constraint frame_sizes { 7 solve zero before data.size; 8 zero -> data.size == 0; 9 data.size inside {[0:10]}; 10 foreach (data[i]) 11 data[i] == i; 12 13 } 14 function void post_randomize(); 15 begin 16 $display("length : %0d", data.size()); 17 $write ("zero:%2x \n",zero); 18 for (integer i = 0; i < data.size(); i++) begin 19 $write ("%2x ",data[i]); 20 end 21 $write("\n"); 22 end 23 endfunction 24 endclass 25 26 initial begin 27 frame_t frame = new(); 28 integer i,j = 0; 29 for (j=0;j < 4; j++) begin 30 $write("-------------------------------\n"); 31 $write("Randomize Value\n"); 32 i = frame.randomize(); 33 end 34 $write("-------------------------------\n"); 35 end 36 37 endprogram 38 39 //compile result 40 # KERNEL: ------------------------------- 41 # KERNEL: Randomize Value 42 # KERNEL: length : 0 43 # KERNEL: zero: 1 44 # KERNEL: 45 # KERNEL: ------------------------------- 46 # KERNEL: Randomize Value 47 # KERNEL: length : 1 48 # KERNEL: zero: 0 49 # KERNEL: 00 50 # KERNEL: ------------------------------- 51 # KERNEL: Randomize Value 52 # KERNEL: length : 0 53 # KERNEL: zero: 1 54 # KERNEL: 55 # KERNEL: ------------------------------- 56 # KERNEL: Randomize Value 57 # KERNEL: length : 3 58 # KERNEL: zero: 0 59 # KERNEL: 00 01 02 60 # KERNEL: -------------------------------
5. randcase
randcase 语句指定了一个语句块,引入case语句对权重进行分支操作。
1 module randcase_statement; 2 3 task do_randcase(); 4 begin 5 randcase 6 20 : begin 7 $write ("What should I do ? \n"); 8 end 9 20 : begin 10 $write ("Should I work\n"); 11 end 12 20 : begin 13 $write ("Should I watch Movie\n"); 14 end 15 40 : begin 16 $write ("Should I complete tutorial\n"); 17 end 18 endcase 19 end 20 endtask 21 22 initial begin 23 repeat(10) begin 24 // You need to run for more iteration to 25 // get proper distribution 26 do_randcase(); 27 end 28 $finish; 29 end 30 endmodule 31 32 //compile result 33 34 Should I watch Movie 35 Should I complete tutorial 36 Should I watch Movie 37 What should I do ? 38 Should I complete tutorial 39 Should I watch Movie 40 Should I complete tutorial 41 Should I complete tutorial 42 Should I work 43 Should I watch Movie
浙公网安备 33010602011771号