Chap 6 Randomization
Chap 6 Randomization
Introduction to randomization
What to randomize?
A simple class with random variables
Weighted distributions
Conditional constraints
Solution probabilities
Controlling constraints
Constraint tips and techniques
Common Randomization Problems
Iterative and Array Constraints
Atomic Stimulus Gen vs Scenario Gen
Random Device Configuration
Chapter 6: Randomization
Directed testing:
Checks only anticipated bugs
Scales poorly as requirements change
Little upfront work
Linear progress
Random testing:
Checks unanticipated bugs
Scales well as requirements change
More upfront work
Better than linear progress
100%
Random
Testing
Test Plan
Completion
Directed
Testing
Chapter
Time 6 Copyright 2011 G. Tumbush, C. Spear v1.4
6.1 Introduction
A testbench based on randomization is a shotgun
The features you are trying to test is the target
Features
# src = 0, dst =
0, ...
10
11
Constraint Exercise 1
Write the SystemVerilog code for the following items:
1) Create a class Exercise1 containing two variables, 8-bit data
and 4-bit address. Create a constraint block that keeps address to
3 or 4.
2) In an initial block, construct an Exercise1 object and
randomize it. Check the status from randomization.
12
Constraint Exercise 1
Write the SystemVerilog code for the following items:
1) Create a class Exercise1 containing two variables, 8-bit data and 4-bit address.
Create a constraint block that keeps address to 3 or 4.
2) In an initial block, construct an Exercise1 object and randomize it. Check the status
from randomization.
class Exercise1;
rand bit [7:0] data;
rand bit [3:0] address;
constraint address_c {
address > 2;
address < 5;
}
endclass
// or
((address==3) || (address==4));
// or
address inside {[3:4]};
initial begin
Exercise1 MyExercise1;
MyExercise1 = new;
`SV_RAND_CHECK(MyExercise1.randomize());
`SV_RAND_CHECK(MyExercise1.randomize());
$display("data = %0d, address = %0d", MyExercise1.data,
`SV_RAND_CHECK(MyExercise1.randomize());
$display("data = %0d, address = %0d", MyExercise1.data,
`SV_RAND_CHECK(MyExercise1.randomize());
$display("data = %0d, address = %0d", MyExercise1.data,
`SV_RAND_CHECK(MyExercise1.randomize());
$display("data = %0d, address = %0d", MyExercise1.data,
end
MyExercise1.address);
MyExercise1.address);
13
lo=20,
lo=114,
lo=186,
lo=214,
med=224,
med=39,
med=148,
med=223,
hi=164
hi=189
hi=161
hi=201
14
15
constraint c_dist {
src dist {0:=40, [1:3]:=60};
dst dist {0:/40, [1:3]:/60};
}
:= operator indicates the weight is the same for all values
:/ operator indicates the weight is distributed across all values
Chapter 6 Copyright 2011 G. Tumbush, C. Spear v1.4
16
40 + 60 + 60 +60 = 220
src = 0, weight = 40/220 =18%
src = 1, weight = 60/220 =27%
src = 2, weight = 60/220 =27%
src = 3, weight = 60/220 =27%
17
[1:3]:/60} ;}
18
class BusOp;
0
1
2
typedef enum {BYTE, WORD, LWRD} length_e;
rand length_e len;
bit [31:0] w_byte=1, w_word=3, w_lwrd=5;
constraint c_len {
len dist {BYTE := w_byte,
WORD := w_word,
LWRD := w_lwrd};
}
endclass
classBusOp;
typedefenum{BYTE,WORD,LWRD}length_e;
randlength_elen;
bit[31:0]w_byte=1,w_word=3,w_lwrd=5;
constraintc_len{
lendist{BYTE:=w_byte,
WORD:=w_word,
LWRD:=w_lwrd};
}
endclass//BusOp
BusOp myBusOp;
# len = 0
# len = 1
# len = 2
# len = 2
# len = 0
initial begin
myBusOp = new();
$display("len = %0b", myBusOp.len);
void'(myBusOp.randomize());
$display("len = %0b", myBusOp.len);
void'(myBusOp.randomize());
$display("len = %0b", myBusOp.len);
void'(myBusOp.randomize());
$display("len = %0b", myBusOp.len);
void'(myBusOp.randomize());
$display("len = %0b", myBusOp.len);
end
19
Constraint Exercise 2
Modify the solution for Exercise 1 to create a new class
Exercise2 so that:
1. data is always equal to 5
2. Probability of address = 4d0 is 10%
3. Probability of address being between [1:14] is 80%
4. Probability of address = 4d15 is 10%
Demonstrate its usage by generating 20 new data and address
values and check for error.
20
Constraint Exercise 2
package my_package;
class Exercise2;
rand bit [7:0] data;
rand bit [3:0] address;
constraint data_c{data == 5;}
constraint address_dist {
address dist{0:=10, [1:14]:/80, 15:=10};
}
function void print_all;
$display("data = %d, address = %d", data, address);
endfunction
endclass // Exercise2
endpackage
# data =
# data =
# data =
# data =
# data =
# data =
# data =
# data =
# data =
# data =
# data =
# data =
# data =
# data =
# data =
# data =
# data =
# data =
# data =
# data =
initial begin
Exercise2 MyExercise2;
repeat (20) begin
MyExercise2 = new;
`SV_RAND_CHECK(MyExercise2.randomize());
MyExercise2.print_all();
end
end
Chapter 6 Copyright 2011 G. Tumbush, C. Spear v1.4
endprogram
5, address = 2
5, address = 12
5, address = 7
5, address = 4
5, address = 14
5, address = 15
5, address = 7
5, address = 10
5, address = 8
5, address = 1
5, address = 6
5, address = 15
5, address = 15
5, address = 1
5, address = 12
5, address = 3
5, address = 15
5, address = 8
5, address = 10
5, address = 7
21
equivalent
Using the ! operator can exclude ranges
constraint c_range {
!(c inside{[lo:hi]});
}
22
23
count[1]=
count[2]=
count[3]=
count[5]=
count[8]=
3943
4054
3922
4094
3987
**************************************
***************************************
**************************************
****************************************
**************************************
Questasim to compile
# count[1]=10075 ****************************************
# count[8]= 9925 ***************************************
24
#
#
#
#
#
#
Values
listed
timesSAT};
in array still occur with same
days.choices
= { multiple
Days:: SUN, Days::
Now SUN listed
and SAT in
choices
choices queue = '{MON, TUE,
as// value
once
in queue
array:
$display("choices queue = %p", days.choices);
`SV_RAND_CHECK(days.randomize());
$display("Random weekend day %s\n", days.choice.name());
days.choices = {Days::MON, Days::TUE, Days::WED, Days::THU, Days::FRI};
$display("choices queue = %p", days.choices);
`SV_RAND_CHECK(days.randomize());
$display("Random week day %s\n", days.choice.name());
end
25
Solution
26
constraint mode_c {
if (mode == small)
len < 10;
else if (mode == large)
len > 100;
}
{(a==1)->(b==0)};
equivalent
{if (a==1) b==0;}
equivalent
Solution
a
(mode==small)
b
(mode==large)
Comment
mode == small or
mode == large
{!(a==1) || (b==0);}
equivalent
{(a==0) || (b==0);}
27
28
(e==1) =false
(e==1)=true
(d==1)=false
true
true
(d==1)=true
false
true
29
constraint c_stim {
len < 1000;
len > 0;
if (congestion_test) {
dst inside {[CONGEST_ADDR-10:CONGEST_ADDR+10]};
src == CONGEST_ADDR;
}
else
src inside {0, [2:10], [100:107]};
}
endclass
Chapter 6 Copyright 2011 G. Tumbush, C. Spear v1.4
30
31
Solution
Probability
1/8
1/8
1/8
1/8
1/8
1/8
1/8
1/8
32
6.5.2 Implication
class Imp1;
rand bit x;
rand bit [1:0] y;
constraint c_xy {
(x==0) -> y==0;
}
endclass
Solution
Probability
1/2
1/8
1/8
1/8
1/8
(y==0)=false
(y==0)=true
(x==0)=false
true
true
(x==0)=true
false
true
33
Solution
Probability
1/3
1/3
1/3
34
Solution
Probability
1/2
1/8
1/8
1/8
1/8
35
solve y before x;
When y = 1, 2, or 3, X must be 1. When y = 0, x can be 0 or 1.
class Imp1;
rand bit x;
rand bit [1:0] y;
constraint c_xy {
(x==0)->y==0;
solve y before x;
}
endclass
Solution
Probability
1/8
1/8
1/4
1/4
1/4
36
Solution
Probability
37
class MemTrans;
rand bit x;
rand bit [1:0] y;
constraint c_xy {
y inside{[x:3]};
solve x before y;
}
endclass
Solution
Probability
1/8
1/8
1/8
1/8
1/6
1/6
1/6
Probability of x = 1 is
Probability of y = 0 as not inside 1:3
Probability of y = 1, 2, 3 is 1/3
Total = 1/2 * 1/3 = 1/6
Chapter 6 Copyright 2011 G. Tumbush, C. Spear v1.4
38
class Packet
rand bit [31:0] length;
constraint c_short {length inside {[1:32]};}
constraint c_long {length inside {[1000:1023]};}
endclass
Packet p:
initial begin
p=new();
p.c_short.constraint_mode(0);
`SV_RAND_CHECK(p.randomize());
transmit(p);
....
...
p.constraint_mode(0);
p.c_short.constraint_mode(1);
`SV_RAND_CHECK(p.randomize());
transmit(p);
end // initial
39
40
41
42
43
6.9 pre_randomize/post_randomize
Implicitly called before/after every call to randomize()
void function
Cannot consume time.
Can only call other functions.
Does not return a value
Overload to add your functionality
post_randomize() is good for cleaning up
$dist_exponential (seed_expression, mean_expression)
mean_expression parameter causes the average value of the return value to
approach the mean. The mean_expression must be an integer greater than
zero (0).
44
6.9 pre_randomize/post_randomize
module sample6p35_tb();
class Bathtub;
int value;
int WIDTH = 50, DEPTH = 6, seed = 1;
function void pre_randomize();
value = $dist_exponential(seed, DEPTH);
if (value > WIDTH) value = WIDTH;
if ($urandom_range(1))
value = WIDTH - value;
$display("value = %0d", value);
endfunction // pre_randomize
endclass // Bathtub
Bathtub bathtub;
initial begin
bathtub = new();
80
70
60
50
40
30
20
10
0
0
10
20
30
40
50
60
repeat(250)
bathtub.pre_randomize;
end
endmodule // sample6p35_tb
45
class Packet;
rand bit [31:0] length;
int max_length= 100;
constraint c_length {
length inside {[1:max_length]};
}
endclass
initial begin
Packet p1 = new();
p1.max_length = 200;
p1.randomize();
end
Chapter 6 Copyright 2011 G. Tumbush, C. Spear v1.4
46
random
class Packet;
rand bit [7:0] length;
constraint c_length{length > 0;}
..... // Other constraints depending on length
endclass
initial begin
Packet p = new();
`SV_RAND_CHECK(p.randomize());
Make length nonrandom
p.length.rand_mode(0);
Create an invalid length
p.length = 0;
`SV_RAND_CHECK(p.randomize());
Value for length will be
p.rand_mode(0);
included in constraint solution
end
Chapter 6 Copyright 2011 G. Tumbush, C. Spear v1.4
47
...Randomization failed
`define SV_RAND_CHECK(r) \
do begin \
if (!(r)) begin \
$display("%s:%0d: Randomization failed \"%s\"", \
`__FILE__, `__LINE__, `"r`"); \
$finish; \
end \
Chapter 6 Copyright 2011 G. Tumbush, C. Spear v1.4
end while (0)
48
49
50
51
52
53
8%4 = 1000
& 0011
0000
54
elements from 1 to 8
sum =
sum =
sum =
see
95
20
40
20
8
54
55
`define SV_RAND_CHECK(r) \
do begin \
if (!(r)) begin \
$display("%s:%0d: Randomization failed \"%s\"", \
`__FILE__, `__LINE__, `"r`"); \
$finish; \
# sum= 137, val= 137
end \
# sum= 519, val=
1
end while (0)
# sum= 81, val= 81
# sum= 408, val= 158
typedef int unsigned uint;
module slide55_tb();
test t1();
endmodule // slide55_tb
program automatic test;
class good_sum5;
rand uint len[];
constraint c_len {foreach (len[i])
len[i] inside {[1:255]};
len.sum < 1024;
len.size() inside {[1:8]};}
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
sum= 624,
sum=1003,
sum= 142,
sum= 520,
sum= 135,
sum= 719,
sum= 798,
sum= 100,
sum= 529,
sum= 251,
sum= 879,
sum=1001,
sum= 763,
sum= 160,
sum= 702,
sum= 516,
val=
val=
val=
val=
val=
val=
val=
val=
val=
val=
val=
val=
val=
val=
val=
val=
48
184
142
93
135
115
23
26
214
251
132
13
209
88
184
25
146
199
16
157
18
245
51
7
141
110
225
190
216
175
22
60
181
164
64
60
74
179
140
134
220
132
113
228
2
61
175
53
217
218
166
11
70
158
188
32
47
180
4
241
201
252
244
117
165
205
156
93
66
47
24
32
17
37
6
74
151
18
136
75
119
good_sum5 c;
initial begin
c = new();
repeat (20) begin
`SV_RAND_CHECK(c.randomize());
c.display();
end
end
endprogram
56
57
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
#
RandArray ra;
initial begin
ra = new();
`SV_RAND_CHECK(ra.randomize());
foreach (ra.array[i])
$display("ra.array[%2d]: ",i, ra.array[i].value);
end
endmodule // sample6p67
ra.array[ 0]:
ra.array[ 1]:
ra.array[ 2]:
ra.array[ 3]:
ra.array[ 4]:
ra.array[ 5]:
ra.array[ 6]:
ra.array[ 7]:
ra.array[ 8]:
ra.array[ 9]:
ra.array[10]:
ra.array[11]:
ra.array[12]:
ra.array[13]:
ra.array[14]:
ra.array[15]:
3507107891
4013053989
2773609279
528996684
3476166007
3634918746
1796308729
1730985904
1222782346
1298121202
1119090603
4220722116
1074911065
1269454440
2256144349
806154056
59
60
package my_package;
parameter int HEIGHT = 10;
parameter int WIDTH = 10;
parameter int PERCENT_WHITE = 20;
typedef enum bit {BLACK, WHITE} colors_t;
class Screen;
rand colors_t pixels [HEIGHT] [WIDTH];
constraint colors_c {foreach (pixels[i,j]) pixels[i][j] dist { BLACK :=100-PERCENT_WHITE,
WHITE := PERCENT_WHITE};
// or
// constraint colors_c {(pixels.sum() with (item.sum() with (int'(item))) == PERCENT_WHITE);}
// This function is not necessary for the in-class solution
function void print_screen;
int
count = 0;
foreach (pixels[i])
$display("%p", pixels[i]);
foreach (pixels[i,j])
count += pixels[i][j];
$display("Num of pixels=WHITE = %0d", count);
endfunction //
endclass
endpackage
`default_nettype none
program automatic test;
import my_package::*;
Screen my_screen;
initial begin
my_screen=new();
`SV_RAND_CHECK(my_screen.randomize());
my_screen.print_screen;
end
endprogram
Chapter 6 Copyright 2011 G. Tumbush, C. Spear v1.4
61
62
module slide63_tb();
import my_package::*;
Transaction t;
initial begin
for (int i=0;i<=50;i++) begin
t = new();
`SV_RAND_CHECK (t.randomize());
t.print_all;
end
end
endmodule // slide63_tb
package my_package;
typedef enum {READ, WRITE} rw_t;
class Transaction;
rw_t old_rw;
rand rw_t rw;
rand bit [31:0] addr, data;
constraint rw_c{if (old_rw == WRITE) rw != WRITE;};
function void post_randomize;
old_rw = rw;
endfunction //
function void print_all;
$display("addr = %d, data = %d, rw = %s", addr,data, rw);
endfunction
endclass
endpackage
64
initial begin
t=new();
for (int i=0;i<=50;i++) begin
`SV_RAND_CHECK (t.randomize());
t.print_all;
end
end
#
#
#
#
#
#
#
#
#
rw
rw
rw
rw
rw
rw
rw
rw
rw
=
=
=
=
=
=
=
=
=
READ
WRITE
READ
READ
READ
WRITE
WRITE
WRITE
WRITE
#
#
#
#
#
#
#
#
rw
rw
rw
rw
rw
rw
rw
rw
=
=
=
=
=
=
=
=
READ
WRITE
READ
WRITE
READ
WRITE
READ
READ
65
class Transaction;
rand rw_t rw;
rand bit [31:0] addr, data;
endclass
class RandTransaction;
rand Transaction trans_array[];
constraint rw_c {foreach (trans_array[i])
if ((i>0) && (trans_array[i-1].rw == WRITE))
trans_array[i].rw != WRITE;}
function new();
trans_array = new[TESTS];
foreach (trans_array[i])
trans_array[i] = new();
endfunction;
endclass
Chapter 6 Copyright 2011 G. Tumbush, C. Spear v1.4
66
module slide66_tb();
parameter TESTS = 5;
typedef enum {READ, WRITE} rw_t;
class Transaction;
rand rw_t rw;
rand bit [31:0] addr, data;
endclass
#
#
#
#
#
#
#
#
#
#
i
i
i
i
i
i
i
i
i
i
=
=
=
=
=
=
=
=
=
=
0,
1,
2,
3,
4,
0,
1,
2,
3,
4,
class RandTransaction;
rand Transaction trans_array[];
constraint rw_c {foreach (trans_array[i])
if ((i>0) && (trans_array[i-1].rw == WRITE))
trans_array[i].rw != WRITE;}
rw
rw
rw
rw
rw
rw
rw
rw
rw
rw
=
=
=
=
=
=
=
=
=
=
'{rw:READ,
'{rw:READ,
'{rw:READ,
'{rw:READ,
'{rw:READ,
'{rw:READ,
'{rw:READ,
'{rw:READ,
'{rw:READ,
'{rw:READ,
addr:0, data:0}
addr:0, data:0}
addr:0, data:0}
addr:0, data:0}
addr:0, data:0}
addr:806154056, data:1796290893}
addr:3362437678, data:3276263896}
addr:2421260686, data:815502112}
addr:3293998593, data:1926967213}
addr:3933255193, data:2450738056}
function new();
trans_array = new[TESTS];
foreach (trans_array[i]) begin
trans_array[i] = new();
end
endfunction;
endclass
RandTransaction t;
initial begin
t = new();
foreach(t.trans_array[i])
$display("i = %0d, rw = %p",i, t.trans_array[i]);
`SV_RAND_CHECK(t.randomize());
foreach(t.trans_array[i])
$display("i = %0d, rw = %p",i, t.trans_array[i]);
end
endmodule
Chapter 6 Copyright 2011 G. Tumbush, C.
Spear v1.4
67
6.14.4 Randsequence
SystemVerilog introduces the randsequence construct
Uses a Backus-Naur Form (BNF) like syntax to describe the grammar
of the transaction
initial begin
for (int i=0; i<15; i++) begin
randsequence (stream)
stream : cfg_read := 1 | weights
io_read := 2 |
mem_read := 5 ;
cfg_read : { cfg_read_task; } |
{ cfg_read_task; } cfg_read;
mem_read : { mem_read_task; } |
{ mem_read_task; } mem_read;
io_read : { io_read_task; } |
{ io_read_task; } io_read;
endsequence
end
end
68
69
70
//
//
//
//
71
72
73