Everything in constrained-random verification starts with three primitives: the rand and randc qualifiers, the randomize solver call, and the seeding machinery. randomize is a solver call, not an assignment: it commits a full legal solution and returns 1, or commits nothing and returns 0.
Classic bug | What you see | The fix |
|---|---|---|
Unchecked return | A contradiction returns 0, and the test sends the previous packet again | Check every call: |
Null nested handle | A | Build nested objects in |
Seed instability | An added fork or object shifts later seeds, so yesterday's failing seed passes | Build objects in a fixed order, or seed them by name |
Lesson | Covers | Path |
|---|---|---|
Uniform draws, cyclic permutations, periods and slot burning. | Required | |
Return checks, solve sets, check-only mode and field lists. | Required | |
Class randomize, std::randomize with and $urandom_range. | Recommended | |
Pre and post hooks, one global solve and the super-call rule. | Recommended | |
Null handles that are skipped, and object arrays built before the solve. | Recommended | |
Stream hierarchy, creation-order shifts, reseeding and replay. | Recommended |
Path: Required is the core first pass for this part, Recommended is for most learners, and Optional is reference, specialist depth or revision.
None. A failed solve commits nothing, so every field keeps its prior value. The test must check the return value and must not drive the stale transaction into the design.