5.3.2 Balance mode frequency

EasyImplementVerilator · local serverReview the topic

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

SignalWidthRole
seed32input of each check
Full specification
The class (given)
class burst;
  rand bit       is_write;
  rand bit [3:0] beats;
  constraint shape { if (is_write) beats == 1; else beats inside {[1:8]}; }
endclass
What you write
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
Your code SystemVerilogSaved locally
Ln 1, Col 1Tab indents · Ctrl/⌘ + Enter runs samples
Not run yet

A balanced mix

Input
seed = 53001, 120 calls
Expected 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.

Run samples executes all 3 example checks. Check all tests runs 4 checks.

Verilator · local server