目录
摘要:约束驱动的测试生产允许用户为功能验证自动生成测试,随机测试比传统的、直接的测试方法更有效,随机测试可以找到直接测试难以覆盖的内容。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