RACE Constraint Solver
Overview
The RACE Constraint Solver is the default constraint solver used in the VCS constrained-random verification environment. It is invoked when SystemVerilog randomize() calls are made on classes whose constraint sets are expressed in the standard SystemVerilog constraint syntax. In a typical VCS flow, RACE is one of two selectable solver modes, the other being a BDD (Binary Decision Diagram) solver that elaborates the entire solution space of a randomize() call before selecting a solution and caches it for subsequent calls.
Solver Mode and Selection
RACE is the out-of-the-box solver used when no alternative solver mode is requested. The BDD solver is invoked explicitly, and is most appropriate when:
- The same
randomize()call occurs many times (so that the cached solution space can be reused), - The randomize problem does not take excessive memory, and
- The architecture of the problem suits BDD-style elaboration (as is the case with many CPU opcode generation workloads).
Performance Characteristics
Runtime
In published comparisons between a single-class stimulus architecture and a multiple-class stimulus architecture for x86 opcode generation, the RACE solver scaled well with the new architecture. The multiple-class implementation was faster for both solvers and for both opcodes that were benchmarked. Specifically, the default RACE solver exhibited a 4x speedup on the multiple-class architecture, while the BDD solver exhibited a 2x speedup.
Memory
The memory footprint of RACE is typically smaller than that of the BDD solver and is not generally a limiting factor. Because the BDD solver elaborates the entire solution space of the randomize() call before selecting a solution, it can consume large amounts of memory; this memory cost is amortized through caching across subsequent calls. Comparative memory measurements for opcode generation have therefore been reported for the BDD solver only, on the basis that RACE memory usage is not the bottleneck.
Interaction with Profiling
RACE solver activity is observable through the VCS Constraint Profiler, which is shipped with VCS to analyze randomize() performance. Profile outputs include:
- Cumulative randomize CPU runtime,
- Individual randomize CPU runtime,
- Individual partition CPU runtime, and
- Memory data per randomize call (most relevant for BDD-mode runs).
The VCS 2009.12 release added a testcase extraction feature that automatically extracts the slowest partition from each randomize() call, supporting root-cause analysis of RACE and BDD solver hot-spots identified by the profiler.
Typical Use Cases
The RACE solver is the workhorse solver for general constrained-random stimulus generation. Published use cases for the VCS constraint solver (RACE and BDD) include generation of x86 microcode stimuli for verification of AMD microcode, where the input is partitioned by opcode category. By first selecting the opcode category and only then randomizing the fields governed by the category-specific constraints, the effective constraint set presented to the solver is significantly reduced — in one published implementation the new architecture had 7x fewer constraints than the original — improving both speed and memory consumption without sacrificing distribution or test-level control.
Comparison with the BDD Solver
| Aspect | RACE (default) | BDD |
|---|---|---|
| Default selection | Yes | Opt-in |
| Memory usage | Typically smaller; not a limiting factor | Can be large; entire solution space is elaborated and cached |
Repeated randomize() of same problem |
No solution-space caching | Solution space cached to speed up subsequent calls |
| Speedup on multiple-class opcode architecture (published) | 4x | 2x |
| Profiling with VCS Constraint Profiler | Supported | Supported (memory data especially relevant) |
Related Concepts
- VCS Constraint Profiler — Tool used to profile RACE and BDD solver behavior (cumulative CPU runtime, per-call runtime, per-partition runtime, and memory data).
- Hierarchical Constrained-Random Stimulus Generation — Technique that structures the constraint problem hierarchically (e.g., choosing an opcode category before randomizing category-specific fields) so that the solver, including RACE, sees a smaller constraint set.