'Way to pick random addresses from dynamic ranges in SV constraints
I have a requirement to pick random addresses from a set of predefined ranges in Systemverilog
program test;
int unsigned q[$], rSz;
typedef struct {
int unsigned from, till;
} range_t;
initial begin
range_t ranges[$];
ranges.push_back('{from: 'h10, till: 'h1F});
ranges.push_back('{from: 'h30, till: 'h3F});
ranges.push_back('{from: 'h50, till: 'h5F});
rSz = ranges.size();
$displayh(rSz, ranges);
repeat (10) begin
std::randomize(q) with {
q.size() inside {[4:8]};
foreach (q[i]) {
q[i] inside {[ranges[0].from: ranges[0].till]} ||
q[i] inside {[ranges[1].from: ranges[1].till]} ||
q[i] inside {[ranges[2].from: ranges[2].till]} ;
}
};
$displayh(q);
end
end
endprogram : test
It works fine if I have a fixed number of ranges that I can hard-code.
But the number of ranges itself is dynamic, I can not hard-code the ranges as in the foreach loop.
I can't use a nested foreach as the statements in the inner loop will be treated as individual constraints and fail with each other as the ranges are non-overlapping.
All I could come up with is something like below where I use the ranges in order and then shuffle at the end.
program test;
int unsigned q[$], rSz;
typedef struct {
int unsigned from, till;
} range_t;
initial begin
range_t ranges[$];
ranges.push_back('{from: 'h10, till: 'h1F});
ranges.push_back('{from: 'h30, till: 'h3F});
ranges.push_back('{from: 'h50, till: 'h5F});
rSz = ranges.size();
$displayh(rSz, ranges);
repeat (10) begin
std::randomize(q) with {
q.size() inside {[4:8]};
foreach (q[i]) {
q[i] inside {[ranges[i % rSz].from: ranges[i % rSz].till]};
}
};
q.shuffle();
$displayh(q);
end
end
endprogram : test
Is there a better way of doing this in general?
I am looking for something like foreach-or where all lines in loop are or-ed instead of and-ed - if that explains the requirement.
Solution 1:[1]
Most people are familiar with the sum() array reduction method, but there are also or(), and(), and xor() reduction methods as well.
module test;
int unsigned q[$], rSz;
typedef struct {
int unsigned from, till;
} range_t;
initial begin
range_t ranges[$];
ranges.push_back('{from: 'h10, till: 'h1F});
ranges.push_back('{from: 'h30, till: 'h3F});
ranges.push_back('{from: 'h50, till: 'h5F});
rSz = ranges.size();
$displayh(rSz,, ranges);
repeat (10) begin
assert(std::randomize(q) with {
q.size() inside {[4:8]};
foreach (q[i])
ranges.or(range) with (q[i] inside {[range.from: range.till]});
});
$displayh(q);
end
end
endmodule: test
See section 7.12.3 Array reduction methods in the IEEE 1800-2017 SystemVerilog LRM.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | dave_59 |
