Give a configuration class soft defaults that any test can override, and a subclass whose own default wins over its parent’s.
Hardware context: Reusable constrained traffic profiles for directed hardware corner cases. Override a preferred packet length while retaining the hardware legal range.
A burst’s protocol rules are hard: 1 to 16 beats, size at most 2. On top of them, most tests want the same everyday burst, 4 beats of 4 bytes, but any test must be able to ask for something else without its randomize() call failing.
Write two classes. burst_cfg extends the given burst_rules and makes 4 beats and size 2 the defaults. long_burst extends burst_cfg and makes 16 beats its default instead.
A soft constraint holds only when it can: a hard constraint, or a later soft one, wins over it. With burst_cfg, randomize() alone gives 4 beats of size 2; randomize() with { beats == 8; } gives 8 beats of size 2; beats == 20 still fails, because the protocol rule is hard.
Signals in the timeline
| Signal | Width | Role |
|---|---|---|
mode | 4 | input of each check |
Full specification
// The protocol rules: always hard.
class burst_rules;
rand bit [4:0] beats;
rand bit [1:0] size; // bytes per beat = 1 << size
constraint legal { beats inside {[1:16]}; size <= 2; }
endclass
class burst_cfg extends burst_rules;
// defaults
endclass
class long_burst extends burst_cfg;
// its own default
endclass
Each case builds one object, randomizes it once, possibly with an inline request, and reports whether the call succeeded and the beats and size it chose (both 0 on failure). Soft defaults make these values certain, so every case expects exact values.
Examples
Example 1
The defaults- Input
burst_cfg, plain randomize()
- Output
randomize_ok = yes, beats = 4, size = 2
Nothing conflicts with the soft constraints, so they hold: 4 beats, size 2.
Example 2
A test overrides one default- Input
burst_cfg with { beats == 8; }- Output
randomize_ok = yes, beats = 8, size = 2
The request conflicts with soft beats == 4, which is dropped. size keeps its default.
Example 3
The subclass’s default wins- Input
long_burst, plain randomize()
- Output
randomize_ok = yes, beats = 16, size = 2
Two soft rules on beats conflict; the later one, in the subclass, wins: 16 beats.
Constraints and contract
- Do not change burst_rules.
- Every default must give way to a test’s request.
- Keep both class names.
Hints
Hint 1
Which keyword turns a constraint into a preference that is dropped when it conflicts with something else?
Hint 2
Put both defaults in burst_cfg. long_burst then needs only one constraint of its own.
Hint 3
When two soft constraints conflict, the one declared later wins, and a subclass is declared after its parent.
What this judge verifies: Your classes are randomized with nine different test requests, each on three new objects, and the chosen values are checked exactly. Passing shows the defaults hold, give way to every request, and never override the protocol.
27 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