Overview
Processor stimulus generation is the creation of instruction-level test inputs for processor or instruction set simulator (ISS) verification. In the coverage-guided fuzzing workflow described by Verifying Instruction Set Simulators using Coverage-guided Fuzzing, stimulus generation is the first step: a fuzzer generates a testset, and the resulting tests are then used to verify an ISS under test by comparing its execution results with one or more reference ISSs.[C1]
The generated stimulus is not limited to preselected legal programs. The workflow considers all possible instructions and instruction sequences, including illegal instructions, with the explicit goal of checking uncommon and error cases.[C2]
Stimulus representation
The stimulus is represented as a binary instruction bytestream. In the described implementation, an ELF template contains an empty section created via a linker script; the instruction bytestream is then inserted into that section using objcopy --update-section.[C3]
This representation lets the fuzzer mutate raw instruction bytes while still producing an executable artifact that can be run by the ISS under test and by reference ISSs.
ISA-aware mutation
The cited approach adds a custom mutator tailored for ISS verification. The mutator scans forward through the bytestream and applies local mutations until it reaches the end. At each step, it randomly chooses between two mutation styles:[C4]
- Opcode injection. The mutator selects a random instruction and injects that instruction's opcode bits at the current byte position, overwriting existing data. This ensures that a legal instruction opcode is present while leaving parameter fields—such as source registers, destination registers, and immediate values—to remain randomized by the fuzzer. The mutator may also inject a randomly selected special immediate value.[C5]
- Constrained sequence injection. The mutator selects a constrained instruction sequence and injects it into the bytestream, overwriting existing data.[C6]
For example, the paper describes RISC-V ADDI as a 32-bit instruction whose destination register, source register, and immediate are encoded in parameter bit fields, while the remaining opcode bits identify the instruction. Injecting only opcode bits preserves randomized operands while steering the byte stream toward decodable instructions.[C5]
Constrained instruction sequences
A constrained sequence is a list of concrete instructions in which some parameters are fixed and others remain randomized. One example is a two-instruction sequence used to load a large constant by loading lower and upper halves separately, because only small immediates can typically be encoded in a single instruction. In that sequence, the destination register is constrained to be the same across both instructions, while the actual value is randomized or selected from a set of special values.[C7]
The paper states that such sequences are defined by the verification engineer and can be specialized for each instruction set.[C7]
Coverage feedback and observability
Stimulus generation is guided by coverage. The approach defines generic functional coverage metrics for registers and immediates, covering both instruction structure and operand values.[C8] Operand-value metrics require register or immediate parameters to take special values such as MIN, -1, 0, 1, and MAX; for unsigned immediates, negative values are omitted.[C9]
To collect functional coverage, the ISS execution step is instrumented with begin-fcov-trace and end-fcov-trace calls placed before and after instruction execution. These trace functions receive the fetched instruction, the decoded operation, and a read-only snapshot of register values. Using both pre- and post-execution traces captures source register values before execution and destination register values after execution; immediate values are available because they are encoded in the instruction.[C10]
Role in ISS verification
After stimulus generation, the generated testset is executed on the ISS under test and on reference ISSs. Execution-result mismatches are analyzed rather than automatically treated as bugs, because configuration differences—such as memory size or mapped peripherals—can cause legitimate behavioral differences, for example when a load/store succeeds on one ISS and fails on another.[C11]
Related work
The concept is used by the paper Verifying Instruction Set Simulators using Coverage-guided Fuzzing, which applies coverage-guided fuzzing, custom instruction mutations, functional coverage metrics, and reference-ISS comparison to RISC-V ISS verification.[C12]