Real stimulus is rarely a handful of scalars. Packets carry variable-length payloads, descriptors form lists, and bursts are streams of related transactions. Each is described as constraints and solved in one randomize() call.
The decision table maps the classic puzzle phrases to their tool. Each row points at the lesson that teaches it.
Puzzle phrase | Tool | Lesson |
|---|---|---|
Ordered / sorted | Guarded | |
Exactly K / at most K |
| |
All different |
| |
No two adjacent equal | Guarded | |
One-hot / one special | Count | |
Total / budget / checksum | Widened |
Lesson | Builds | PacketFIFO |
|---|---|---|
Size bounds, the size-first solve order, and the always-bound rule. | None | |
Per-element rules, guarded neighbour relations, and multidimensional iteration. | Payload bytes match | |
Budgets, checksums, the sum width trap, and the counting idiom. | A correct check byte | |
All-distinct arrays, the permutation recipe, and unique versus randc. | None | |
Construct-then-randomize, one call versus a loop, and traffic shaping. | A burst with idle gaps |
Verilator 5.048 runs most of this, with gaps the lessons name where they matter: unique only on fixed-size arrays, size() and sum() not together on a dynamic array, and arrays of rand handles ignored. The full list is on What the Open Simulators Run.
A size bound on data.size() and a foreach rule keeping each byte inside [8'h20:8'h7E], both in one randomize() call.