System verilog constraints take up lot of simulation time if not used
properly.
Let me try to illustrate it with an example.
Take a scenario where we need to generate unique address ( for burst traffic )
each time we randomize.
Configuration is as follows....
1. Page - 4096 ( 4K)
2. Address range - 63: 0
3. Align signal is used to take either offset range ( range starts from offset
value to the end of the page )
or to take the whole page as a burst ( 4096 in our case ).
align == 1 -> no page offset
align == 0 -> some page offset
Since the address is 64 bits and Page is 12 bits, I took a variable page_num (
64 -12 = 52 sized vector ) to represent the pages that can be addressed with
the address range ( 63:0 ).
Lets take 2 approaches to prove our point ( to pick the random address )
1. With Constraints
2. Without using constraints
CASE 1 :
In this case, we simply used a queue to push all the used page numbers in post
randomize.
For constraints we used unique keyword to make sure that we do not repeat the
same value.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 | class address_selector;
rand bit [51:0] page_num;
rand bit [11:0] page_offset;
rand bit align;
bit [51:0] used_pages[$];
constraint c_addr {
unique { used_pages, page_num };
}
constraint c_align {
solve align before page_offset;
(align == 1) -> page_offset == 0;
}
function void post_randomize();
used_pages.push_back(page_num);
endfunction: post_randomize
endclass: address_selector
module top;
address_selector as;
int transfer_size = 1024 * 1000; // Size of 1000K
initial begin
as = new;
while (transfer_size > 0) begin
void'(as.randomize());
transfer_size = transfer_size - (4096 - as.page_offset);
$display("TRANSFER SIZE:%0x ALIGN:%0d ADDR:%0x PAGE:%0x OFFSET:%0x",transfer_size,as.align, {as.page_num,as.page_offset},as.page_num,as.page_offset);
end
end
endmodule
|
Simulation results:
V C S S i m u l a t i o n R e p o r t
Time:
0
CPU Time: 143.710 seconds; Data structure size: 0.0Mb
Sat
Aug 22 04:39:05 2020
CPU time: .134 seconds to compile + .023 seconds
to elab + .392 seconds to link + 144.630 seconds in simulation
CASE 2:
In this case, we used an associative array instead of queue.
We removed the constraint for generating unique page numbers, instead we used
logic to look for the address used ( page_num) inside the post_randomize()
function.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 | class address_selector;
rand bit [51:0] page_num;
rand bit [11:0] page_offset;
rand bit align;
bit [51:0] used_pages[*];
constraint c_align {
solve align before page_offset;
(align == 1) -> page_offset == 0;
}
function void post_randomize();
while(used_pages.exists(page_num)) begin
std::randomize(page_num);
end
used_pages[page_num] = 1;
endfunction: post_randomize
endclass: address_selector
module top;
address_selector as;
int transfer_size = 1024 * 1000;// 128 * 1024 * 100000;
initial begin
as = new;
while (transfer_size > 0) begin
void'(as.randomize());
transfer_size = transfer_size - (4096 - as.page_offset);
$display("TRANSFER SIZE:%0x ALIGN:%0d ADDR:%0x PAGE:%0x OFFSET:%0x",transfer_size,as.align, {as.page_num,as.page_offset},as.page_num,as.page_offset);
end
end
endmodule
|
Simulation results :
V C S S i m u l a t i o n R e p o r t
Time:
0
CPU Time: 0.430 seconds; Data structure size:
0.0Mb
Sat Aug 22 04:39:35 2020
CPU time: .141 seconds to compile +
.022 seconds to elab + .460 seconds to link + .568 seconds in simulation
Conclusion :
See the difference 143 seconds vs .430 seconds.
For smaller address ranges, it doesn't make much of a difference, but for
larger footprints it does show a significant improvement in the simulation
times.