У меня есть требование выбирать случайные адреса из набора предопределенных диапазонов в 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
Он отлично работает, если у меня есть фиксированное количество диапазонов, которые я могу жестко закодировать.
Но само количество диапазонов динамическое, я не могу хардкодить диапазоны как в цикле foreach
.
Я не могу использовать nested foreach
, так как операторы во внутреннем цикле будут рассматриваться как отдельные ограничения и не работать друг с другом, поскольку диапазоны не перекрываются.
Все, что я мог придумать, это что-то вроде ниже, где я использую диапазоны по порядку, а затем перемешиваю в конце.
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
Есть ли лучший способ сделать это в целом?
Я ищу что-то вроде foreach-or
, где все строки в цикле or-ed
вместо and-ed
- если это объясняет требование.
Большинство людей знакомы с методом сокращения массива sum()
, но существуют также методы сокращения or()
, and()
и xor()
.
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
См. раздел 7.12.3 Методы сокращения массива в IEEE 1800-2017 SystemVerilog LRM.
Потрясающий dave_59. Работает как шарм, и спасибо, что дали мне новую перспективу, о которой всегда забывают.