Pick the kind of burst first, then solve the rest, so writes are half the traffic instead of one in nine.
Hardware context: Constraint-solver bias in burst and command generators. Balance mode selection without changing which transactions are legal.
A burst is a write of exactly one beat, or a read of 1 to 8 beats. randomize() picks uniformly among the legal solutions, and there are nine: one write and eight reads. So only about one burst in nine is a write, and the write path is barely tested.
Write balanced_randomize(b), which randomizes b so that writes and reads are equally likely, while every burst still obeys the class’s constraint. Choose is_write first with a separate random call, then randomize b with that choice. Return 0 if a call fails.
Over 120 calls, between 40 and 80 must be writes, every read length from 1 to 8 must appear, and every write must have one beat.
Signals in the timeline
| Signal | Width | Role |
|---|---|---|
seed | 32 | input of each check |
Full specification
class burst;
rand bit is_write;
rand bit [3:0] beats;
constraint shape { if (is_write) beats == 1; else beats inside {[1:8]}; }
endclass
function automatic bit balanced_randomize(burst b);
Each case seeds the object and the calling process, calls balanced_randomize 120 times, and reports whether the writes are near half, the beat counts seen for reads and for writes, and the number of failed or illegal results.
A random choice of your own (std::randomize or $urandom_range) is seeded by the calling process, so the case seeds that too.
Examples
Example 1
A balanced mix- Input
seed = 53001, 120 calls
- Output
writes_near_half = yes, read_beats_seen = {1, 2, 3, 4, 5, 6, 7, 8}, write_beats_seen = {1}, failed_or_illegal = 0
Between 40 and 80 writes, all eight read lengths, and every write has one beat.
Example 2
Another seed- Input
seed = 7, 120 calls
- Output
writes_near_half = yes, read_beats_seen = {1, 2, 3, 4, 5, 6, 7, 8}, write_beats_seen = {1}, failed_or_illegal = 0
A second fixed seed. The bands are wide, so a correct solution passes at every regression seed; a fair coin could in principle fall outside them, but a plain randomize() falls far outside.
Example 3
A third seed- Input
seed = 424242, 120 calls
- Output
writes_near_half = yes, read_beats_seen = {1, 2, 3, 4, 5, 6, 7, 8}, write_beats_seen = {1}, failed_or_illegal = 0
A plain randomize() would give about 13 writes here, far below 40.
Constraints and contract
- Do not change the class.
- Every burst must satisfy the class constraint.
- Keep the function signature.
Hints
Hint 1
Count the legal (is_write, beats) pairs. How likely is a write if each pair is equally likely?
Hint 2
If you decide is_write yourself, with a fair coin, the solver only has to pick beats.
Hint 3
std::randomize(w) gives a random bit w. Then use randomize() with { is_write == w; }.
What this judge verifies: Your function is called 120 times at each of four seeds, and the mix, the read lengths and every write are checked. Passing shows a balanced mix that obeys the constraint, not an exact distribution.
4 checks on Verilator · local server. Run the examples first, then check the full regression. The suite is local and inspectable. A passing result establishes the tested cases, not a proof for all possible inputs.
See all 5 steps and the final capstone