randomize()
在上一页中,我们看到了randomize()方法的基本用法。 Systemverilog中的randomize()方法具有以下扩展名。
constraint_mode()
rand_mode()
randomize() with
pre_randomize()
post_randomize()
constraint_mode()
Systemverilog提供了预定义的constraint_mode()方法来控制约束是有效的还是无效的。所有约束最初都是有效的。
Syntax
task object[.constraint_identifier]::constraint_mode( bit on_off );
or
function int object.constraint_identifier::constraint_mode();
【1】object_name是在其中定义约束块的对象的名称;
【2】constraint_identifier是要对其执行操作的约束块的名称;
【3】1(ON)将指定的约束块设置为活动状态,以便在随后对randomize()方法的调用中强制执行;
【4】0(OFF)将指定的约束块设置为非活动状态,以便在随后对randomize()方法的调用中不强制执行;
【5】如果指定的约束块在类层次结构中不存在,将发出编译器错误。
当我们想随机化为不同配置编码的类时,constraint_mode方法非常有用。下面的示例显示我们可以使用约束模式。
Example : 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
-------------------------------
Packet type UNICAST
Size of frame is 1
Payload is 7d
-------------------------------
Constraint state of multicast is 0
-------------------------------
Packet type MULTICAST
Size of frame is 3
Payload is df 40 f7
-------------------------------
rand_mode()
Systemverilog提供了预定义的rand_mode()方法来控制随机变量是活动的还是非活动的。 当随机变量处于非活动状态时,将其视为未声明为rand或randc。 所有随机变量最初都是活动的。
Syntax
task object[.random_variable]::rand_mode( bit on_off );
or
function int object.random_variable::rand_mode();
【1】object:object是任何产生定义随机变量的对象句柄的表达式。
【2】random_variable:random_variable是对其应用操作的随机变量的名称。 如果未指定(仅当作为任务调用时才允许),则该操作将应用于指定对象内的所有随机变量。
【3】1(ON):将指定的变量设置为活动状态,以便在随后对randomize()方法的调用中将它们随机化。
【4】0 OFF:将指定的变量设置为无效,以便在随后调用randomize()方法时不会将它们随机化。
当作为函数调用时,rand_mode()返回指定随机变量的当前活动状态。如果变量处于活动状态(ON),则返回1;如果变量处于非活动状态(OFF),则返回0。
Example : 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
You could download file rand_mode_ex.sv here
space.gif
../images/main/4blue_dots_bullets.gif Simulation Output : rand_mode()
space.gif
-------------------------------
Without Randomize Value
Source address 00
Destination address 00
-------------------------------
With Randomize Value
Source address 36
Destination address 3c
-------------------------------
With Randomize OFF and Randomize
Source address 36
Destination address 3c
-------------------------------
With Randomize ON and Randomize
Source address 7d
Destination address e2
-------------------------------
With Randomize OFF on dest addr and Randomize
Source address 0b
Destination address e2
-------------------------------
randomize()with
此构造允许在调用randomize()类方法的点声明内联约束。 这些其他约束具有与随机类中声明的约束类型和形式相同的约束类型。 内联约束与对象约束一起应用。 类定义中的原始约束不必更改。
Syntax
inline_constraint _declaration ::=
class_variable_identifier . randomize [
( [ variable_identifier_list | null ] ) ]
with constraint_block
[1]class_variable_identifier:是实例化对象的名称。
[2]未命名的constraint_block包含要与在类中声明的对象约束一起应用的其他嵌入式约束。
Example : randomize with
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
-------------------------------
Randomize Value
Source address 02
Destination address ab
-------------------------------
Randomize with Value
Source address 79
Destination address 81
pre_randomize()和post_randomize()
每个类都包含内置的pre_randomize()和post_randomize()任务,它们在计算新的随机值之前和之后由randomize()自动调用。
Syntax
function void pre_randomize();
function void post_randomize();
调用obj.randomize()时,它首先对obj及其启用的所有随机对象成员都调用pre_randomize()。 然后Pre_randomize()递归调用super.pre_randomize()。
然后Post_randomize()递归调用super.post_randomize()。 您可以在任何类中重载pre_randomize()来执行初始化和设置对象随机化之前的前提条件。
您可以在任何类中重载post_randomize()来执行清理,打印诊断并在对象随机化后检查后置条件。
参考文献:
Example : pre/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
-------------------------------
Randomize Value
-------------------------------
pre_randomize : Value of data 00000000 and parity 0
post_randomize : Value of data 00000110 and parity 0
-------------------------------
【1】http://www.asic-world.com/systemverilog/random_constraint2.html#randomize()