Randomization

cpptb separates random value generation from constrained transaction solving. Both use deterministic, test-owned random streams, but they solve different authoring problems:

Need

Use

Compare complete cpptb and pure-SV authoring styles

Side-by-side examples

Pick values, shuffle data, or generate packed bits

test.random()

Describe legal relationships between transaction fields

Randomized

Add membership, weighting, defaults, or runtime modes

Policies and composite fields

Prove coupled constraints or diagnose an unsatisfiable model

Solver backends

Measure exercised behavior with explicit sampling

Functional coverage

Reproduce failures across concurrent processes

Seeds and replay

Randomization is stimulus construction only. It does not drive a signal, start a clock, wait for an edge, or advance simulation time.

Start with values

For most sequences, ordinary value generation is the smallest useful API:

enum : uint8_t { Read, Write, Flush, Fence };

Task<void> packet_sequence(Dut dut, TestContext& test) {
    auto& random = test.random();
    constexpr std::array<uint8_t, 4> opcodes{Read, Write, Flush, Fence};
    constexpr std::array length_mix{
        weighted(64u, 5), weighted(256u, 3), weighted(1500u, 1)};

    for (uint32_t transaction = 0; transaction < 1000; ++transaction) {
        const uint32_t address =
            random.randint<uint32_t>(0x1000, 0x1fff);
        const uint8_t opcode = random.choice(opcodes);
        const uint32_t length = random.weighted_choice(length_mix);
        const Bits<256> payload = random.randbits<256>();

        co_await drive_packet(dut, address, opcode, length, payload);
    }
}

Use this style when values can be generated directly and legality is easy to see in the sequence. See Random value generation for the complete API.

Feature guide

Feature

API

Guide

Runnable framework comparison

Exact cpptb and pure-SV peers

Examples

Inclusive integral range

random.randint<T>(minimum, maximum)

Value generation

Select or shuffle values

choice(), weighted_choice(), shuffle()

Value generation

Arbitrary-width packed value

random.randbits<Width>()

Value generation

Scalar randomized field

Rand<T>

Constrained transactions

Nonrepeating finite cycle

RandC<T>

Constrained transactions

Per-call legality

test.randomize_with(item, expression)

Constrained transactions

Values and ranges

inside(), range()

Policies and composition

Weighted solve policy

dist(), weighted()

Policies and composition

Preferred default

soft_constraint()

Policies and composition

Runtime mode switch

ConstraintHandle

Policies and composition

Nested transaction

Randomized(parent, name)

Policies and composition

Fixed array or packed field

RandArray<T, N>, RandBits<Width>

Policies and composition

Adaptive dependency-free solving

AdaptiveConstraintBackend

Solvers and diagnostics

Direct sampling control

RandomSearchBackend

Solvers and diagnostics

Coupled constraint solving

Z3RandomBackend

Solvers and diagnostics

Functional coverage

Covergroup<T>, Coverpoint<T>

Functional coverage

Seed and process replay

--seed, CPPTB_RANDOM_SEED

Reproducibility

Design boundaries

The randomization layer is intentionally independent of the simulator and scheduler. It can be used in a coroutine, reference model, monitor helper, or plain C++ unit test. Solver dependencies are optional, and selecting another backend does not change the authored transaction class.

The current composite fields are fixed RandArray<T, N> arrays and RandBits<Width> packed values constrained through 32-bit words. Dynamic random arrays, a complete clone of the SystemVerilog constraint language, coverage-guided solving, and solve before ordering are not currently part of the API. Functional coverage is deliberately separate from stimulus and does not steer randomization.

Performance qualification

Random APIs have exact C++ and pure-SystemVerilog benchmark peers. The pairs consume the same versioned random stream, drive the same DUT transactions, and must produce the same response checksum before timing is considered:

make feature-test FEATURE=random_stimulus
make feature-test FEATURE=constrained_packet
make feature-test FEATURE=constraint_extensions
make feature-test FEATURE=coverage_sampling

See Performance for current measurements and the 1.10x C++/pure-SV guard.