Skip to content
STIMSMITH

Control and Status Registers

Concept WIKI v12 · 7/10/2026

Control and Status Registers (CSRs) are RISC-V architectural registers that control and hold processor state. CSRs are part of the architectural state and play a central role in modern RISC-V processor verification: ProcessorFuzz uses CSR transitions as HDL-agnostic coverage feedback; UVM-based verification environments verify CSRs alongside other core blocks; retirement-level lockstep co-simulation adds CSRs to the state-mask progression to exercise privilege and exception handling; and research systems such as SNAP use new CSRs as hardware/OS configuration interfaces for fuzzing instrumentation.

Control and Status Registers

Control and Status Registers (CSRs) are RISC-V architectural registers that "contain additional information about the results of instructions in the CPU," and which are "in charge of controlling and holding the state of the processor." As a core component of the Architectural State, CSRs are visible at the ISA level alongside the program counter (PC), general-purpose registers (GPRs), and memory contents relevant to execution.

In RISC-V, CSR access and the execution of privileged instructions are gated by the current privilege level: User (U) for unprivileged applications, Supervisor (S) for operating systems, and Machine (M) for full hardware control and low-level operations. Only M is required to be implemented, but most non-embedded RISC-V CPUs implement all three.

Beyond their role in the RISC-V architectural state, CSRs are also used in research systems as a hardware/OS configuration interface. SNAP, for example, introduces new CSRs as configuration interfaces between the hardware and the OS for its fuzzing instrumentation; each new SNAP CSR is 8 bytes in size with explicit access permissions.

CSR verification in UVM-based environments for RISC-V cores

A 2025 IJEDR project ("Verification Of Risc-V Core Blocks Using Uvm") developed a UVM-based verification environment for major RISC-V core blocks, including the Instruction Fetch Unit (IFU), Instruction Decode Unit (IDU), Execute Unit (ALU, MUL/DIV), Load-Store Unit (LSU), Register File, Control and Status Registers (CSR), Pipeline and Hazard Unit, and Interrupt/Exception Unit. Each block is verified individually and in integration using UVM components (sequence, sequencer, driver, monitor, scoreboard, and coverage collector) that generate constrained-random instruction streams, drive transactions, and compare DUT outputs against a reference model.

The same project lists "Control and Status Registers (CSRs)" among the RISC-V core blocks targeted by the verification plan, alongside the IFU, Decode Unit, Execution Unit, Register File, Load/Store Unit (LSU), and Branch Prediction Unit. Verification of these blocks relies on SystemVerilog Assertions (SVA) for protocol compliance and corner-case detection, an architectural reference model (e.g., Spike or a custom ISA model) with a scoreboard to compare expected and actual outputs at transaction or instruction granularity, and pipeline checks for forwarding, stalling, and flushing.

According to the project's results, all targeted units — IFU, IDU, Execute Unit, LSU, Register File, CSR, Pipeline, and Exception Unit — were verified against the RISC-V specification using constrained-random testing, assertions, and a reference model. Functional and assertion coverage goals were achieved, and critical corner-case bugs were identified and resolved.

The toolchain used by this project consists of SystemVerilog with the UVM 1.2 / 1.1d (IEEE 1800.2) library, ModelSim / QuestaSim as the simulator, Visual Studio Code as the recommended editor, and QuestaSim's built-in waveform viewer.

CSRs in retirement-level lockstep co-simulation

Lockstep co-simulation runs the RTL alongside a validated reference model and checks architectural state at each instruction retirement, so mismatches are reported immediately and debugging focuses exactly at the point of failure. CSRs are one of the categories of architectural state captured at each retire event, alongside PC and GPRs.

The lockstep flow supports a configurable state mask that lets verification scale from early RTL bring-up to final sign-off. A typical progression is:

  • PC-only checks for early bring-up.
  • PC plus GPRs for control and datapath validation.
  • Adding CSRs to exercise the privilege and exception handling.
  • Selected memory regions or the complete architectural state when sign-off confidence is required.

Because the comparison is performed at retirement rather than against transient pipeline state, lockstep comparison surfaces issues such as CSR side effects, privilege transitions, or subtle ordering errors that trace-based flows or self-checking tests may miss. Each failure maps to a specific retire index and instruction, making reruns deterministic and root-cause analysis faster.

The methodology is built on the RISC-V Verification Interface (RVVI), an open standard interface for exchanging retire, state, and event information between the RTL, testbench, and reference models. RVVI makes it easier to integrate lockstep comparison with existing SV/UVM scoreboards and coverage and to introduce asynchronous events such as interrupts, debug requests, and exceptions at arbitrary retire points while keeping runs reproducible. Synopsys VCS is used as the RTL simulator, ImperasDV (via Synopsys partnership) provides the reference model and lockstep methodology, and the Verdi debug platform is used to inspect mismatches, retire indices, and architectural-state differences with waveform correlation.

CSR transitions as coverage feedback in ProcessorFuzz

ProcessorFuzz is a hardware fuzzer whose coverage metric is CSR-transition coverage: a test input is considered interesting when it causes a new transition in a monitored CSR, on the rationale that "transitions in CSRs indicate a new processor state." ProcessorFuzz is HDL-agnostic and does not require any instrumentation in the processor design, so it supports a wide range of RTL designs written in different hardware description languages.

Transition map and trace comparison

During a fuzzing session, ProcessorFuzz maintains a transition map. When CSR-transition tuples are created, the map is queried to check whether the detected transition is new or a duplicate. A tuple containing a new transition is added to the map while marking the current test input as interesting. The transition map is empty at the beginning of a fuzzing session and is maintained throughout the session. ProcessorFuzz also includes the mnemonic of the instruction in the tuple in order to ignore repetitive transitions that are triggered by different operands of the same instruction.

If the Transition Update (TU) component determines that the current input results in a unique CSR transition, ProcessorFuzz launches RTL simulation and generates an extended RTL trace log. It then compares that RTL trace log with the extended ISA trace log; any difference is treated as a potential processor-design bug requiring further investigation. If the input does not produce a unique CSR transition, ProcessorFuzz discards it and proceeds to the next fuzzing iteration.

The separation of frm and fflags from the rest of the CSRs is intended to separate floating-point operations from other CSR transitions. This separation matters because, for example, both floating-point division and floating-point square-root instructions can trigger the same fflags transition in the RISC-V ISA due to invalid operations, yet only the invalid operation of a floating-point division instruction might actually contain a bug.

CSR trace extraction

ProcessorFuzz's implementation has two main steps: generating an extended trace log using an ISA simulator and building the TU component. For trace generation, the authors extended the Spike open-source ISA simulator to store the values of monitored CSRs. The reported Spike instrumentation overhead was 0.4% in lines of C++ code and 0.15% runtime overhead. RTL simulation in the evaluation used Verilator. The ProcessorFuzz evaluation reused DIFUZZRTL's mutation engine so that the comparison focused on coverage feedback mechanisms (register coverage versus CSR-transition coverage) rather than on input-generation mechanisms.

Selected CSRs in ProcessorFuzz

As a reference point, the RISC-V ISA defines up to 4096 CSRs. For its RISC-V implementation, ProcessorFuzz selected a subset of CSRs and CSR fields using two criteria:

  • C1 — selects CSRs that hold historical state (e.g., values that record what happened during or before a trap), so that distinct states are recorded.
  • C2 — selects CSRs whose fields can hold different values for different inputs and that affect program execution, so that changing the field changes processor behavior.

Apart from these two criteria, CSR selection can be further limited depending on the desired scope of verification.

Selected privileged CSRs and fields include:

  • mstatus.xIE (C2) — controls the global interrupt-enable bit for privilege x, where x = {M, S, U}.
  • mstatus.xPIE (C1) — holds the value of the interrupt-enable bit active prior to a trap for privilege mode x.
  • mstatus.xPP (C1) — holds the previous privilege mode active prior to a trap taken to privilege mode x.
  • mstatus.XS (C1) — contains the state of additional user-mode extensions.
  • mstatus.FS (C1) — contains the state of the floating-point unit.
  • mstatus.MPRV (C2) — controls the privilege mode in which memory operations are performed.
  • mstatus.SUM (C2) — controls permission for supervisor-mode access to user memory.
  • mstatus.MXR (C2) — controls the privilege with which loads access virtual memory.
  • mstatus.TVM (C2) — controls the ability to edit virtual-memory configuration from supervisor mode.
  • mstatus.TW (C2) — controls the privilege modes in which WFI is allowed to execute.
  • mstatus.TSR (C2) — provides the ability to trigger a trap when SRET executes in supervisor mode.
  • mstatus.xXL (C2) — controls integer-register width for privilege mode x, where x = {S, U}.
  • mstatus.SD (C1) — indicates the combined state of mstatus.FS and mstatus.XS for context switches.
  • {m,s}cause (C1) — contains the trap cause when a trap is taken into machine or supervisor mode.
  • medeleg (C2) — decides what exception types are delegated to supervisor mode from machine mode.
  • {m,s}counteren (C2) — controls availability of hardware performance-monitoring counters for supervisor or user mode.

Selected unprivileged CSRs include:

  • frm (C2) — controls the dynamic rounding mode for floating-point operations.
  • fflags (C1) — holds accrued exceptions from floating-point operations.

CSRs excluded from monitoring in ProcessorFuzz

ProcessorFuzz also identifies CSRs that are not monitored and gives reasons for excluding them.

Excluded because they hold a constant value during testing (Privileged): misa (reports the CPU capabilities of a hart), mhartid (contains the integer ID of the hardware thread running the code), {m,s}tvec (contains the trap handler base address and vector configuration for machine or supervisor mode), satp (controls supervisor-mode address translation and protection). PMP: pmpcfg (contains the physical memory protection configuration), pmpaddr (contains the physical memory protection addresses).

Excluded because they are not supported by the testing infrastructureInterrupt: {m,s}ip (reports pending interrupts in machine or supervisor mode), {m,s}ie (controls what interrupts are enabled in machine or supervisor mode), mideleg (decides what types of interrupts are delegated from machine mode to supervisor mode). Debug Extension: dcsr (contains the configuration and status of debug extension), dpc (holds the program counter of the next instruction to be executed before entering debug mode), dscratch (optional scratch register that holds temporary values). Trigger: tselect (controls which trigger is accessible through the other trigger registers), tdata1-3 (holds trigger-specific data). Vector Extension: vstart (holds the index of the first element to be executed by a vector instruction), vxsat (holds the saturation flag for fixed-point operations), vxrm (controls the rounding mode used in the vector extension).

Excluded as diagnostic-only CSRsHPC: mcountinhibit (controls which hardware performance-monitoring counters are allowed to increment), cycle (holds the elapsed cycle count of the CPU), instret (holds the number of retired instruction count), hpmevent (hardware performance-monitoring event selector), hpmcounter (performance-monitoring counter of the event selected by hpmevent). Privileged: {m,s}tval (hold the exception-specific information when a trap is taken to machine or supervisor mode), mscratch (holds a pointer to the machine mode context space while the hart executes in lower privilege), {m,s}epc (contains the PC of an instruction that caused an exception for machine or supervisor mode), sscratch (holds a pointer to the supervisor mode context space while the hart executes in user mode). These are described as containing information that assists designers during hardware-bug analysis rather than revealing the fundamental issue.

CSRs as a hardware/OS configuration interface in SNAP

SNAP is a hardware-assisted software fuzzer that introduces new CSRs as configuration interfaces between the hardware and the OS so that a fuzzer running on top of the system can configure the hardware and collect low-level information to construct input feedback. Each new SNAP CSR is 8 bytes in size with explicit access permissions.

The new SNAP CSRs include:

  • BitmapBase and BitmapSize — set the base address and size of the coverage bitmap.
  • TraceEn — enables hardware tracing.
  • TraceStartAddr and TraceEndAddr — define region-specific feedback when needed.
  • LbqAddr[0-31] and LbqStatus — store the branch target addresses and prediction results of the last 32 branches by default; these are read-only, as the kernel is not required to modify them.

Each Last Branch Queue (LBQ) entry is wired to a defined CSR so that its information can be accessed from software after each fuzzing execution using a CSR read instruction. To interface with the LBQ, SNAP relies on these CSRs; branch information (target address and prediction result) is retrieved through the branch resolution path from the branch unit, where branch prediction is resolved.

In addition, software-side access to SNAP's CSRs is mediated by custom, user-friendly system calls that allow a fuzzer to configure the hardware (for example, to enable the branch record only, or to request dedicated fuzzing on specific code regions or program features), and to retrieve results such as the last-executed branches to debug a program near a crash site.

CSRs in Cascade: exercised through intricate program generation

Cascade is a CPU fuzzer that, unlike ProcessorFuzz, does not rely on coverage feedback: instead, it generates intricate programs whose instructions are picked so as to exercise a rich set of RISC-V functionality. The programs generated by Cascade "support exceptions without (necessarily) causing termination, data flow-dependent privilege transitions, complex FPU (Floating-Point Unit) operations, and operations under randomized Control and Status Registers (CSRs) exploring different operational states of the CPU." Cascade is also described as supporting "complex FPU operations and CSR interactions."

Instruction picking and CSR-related interactions

Cascade groups instructions into categories and picks them hierarchically: a category is chosen first, then a specific instruction within that category, with both choices randomized. Some groups of instructions are conditioned by architectural state — for example, all floating-point instructions will be conditioned by whether an FPU is present and activated.

When picking a cf-ambiguous instruction (one that may be either still or hopping depending on register values, or that is unconditionally hopping but whose destination depends on register values — beq and lw are cf-ambiguous, while add and illegal instructions are not), Cascade chooses immediately whether it must be still or hopping. Cascade also biases operand selection by giving higher probabilities to registers recently used as outputs.

Exceptions and privilege switches are modeled as simple hopping instructions, which "can only be picked under certain architectural conditions" that are generated by the mechanism explained in Section 5 of the Cascade paper. The combination of initial static data with a diverse stream of random instructions ultimately produces the complex data flow that includes CSR-modified transitions.

CSR mismatches: a known limitation of Cascade's coverage

Because Cascade executes its code sequences in machine mode and surfaces CSR value mismatches between the intermediate and ultimate programs, it can detect CSR-related bugs that user-space differential frameworks cannot. However, the RISCover authors observe that "even after 14 days of fuzzing, Cascade only find[s] CSR value mismatches without security implications" on the openC906 and openC910, while RISCover — which excludes CSRs during fuzzing since they "can produce arbitrary differences and are partially privileged" — discovers security-relevant bugs on the same cores. Cascade additionally does not embed illegal encodings such as the GhostWrite vulnerability or the custom C906 halting instructions, nor vector instructions, into its sequences.

CSRs in RISCover: explicit exclusion

RISCover takes the opposite position from ProcessorFuzz and a narrower position than Cascade: it is a differential CPU testing framework for closed-source RISC-V CPUs that runs in user space, requires no source code, no golden model, and no privileged execution. Because RISCover cannot rely on monitored CSR values from a reference RTL design, CSR-modifying instructions create problems for its differential comparison.

Concretely, RISCover's instruction-exclusion filter removes CSR-based instructions from its generated sequences, because such instructions "can change the behavior of instructions on the current core" and would introduce false-positive differences. RISCover explicitly carves out two exceptions: the frcsr and fscsr instructions, which read and modify the Floating-Point Control and Status Register (fcsr). These are permitted because fcsr is part of the CPU's well-defined architectural state. Coverage of the remaining CSRs is left to future work.

This design choice was highlighted as one of the reasons RISCover's findings differ from the RTL fuzzer Cascade. Cascade executes its code sequences in machine mode and surfaces CSR value mismatches, but RISCover does not detect such mismatches because it excludes CSRs during fuzzing — both because CSRs can produce arbitrary differences and because they are partially privileged.

Evaluation contexts

ProcessorFuzz was evaluated on three real-world open-source RISC-V processors: Rocket (a Chisel-based in-order RISC-V core generated using the Rocket Chip SoC Generator), BOOM, and BlackParrot. The authors relied on a set of six bugs previously reported by DIFUZZRTL for the BOOM processor to perform a head-to-head bug-finding comparison. Spike was used as a reference model to verify the correct behavior of Rocket. ProcessorFuzz triggered ground-truth bugs 1.23× faster on average than DIFUZZRTL, exposed eight new bugs across the three RISC-V cores, and exposed one new bug in a reference model; all nine newly exposed bugs were confirmed by the corresponding project developers.

Cascade was evaluated on six real-world RISC-V CPUs of different complexities and ISA extensions: VexRiscv, PicoRV32, Kronos, CVA6, Rocket, and BOOM. Compared to state-of-the-art fuzzers TheHuzz and DifuzzRTL, Cascade achieves the same coverage 28.2× and 97× faster, respectively. Cascade discovers 37 new bugs (29 new CVEs) in 5 of these 6 designs — more than all the state-of-the-art CPU fuzzers combined — and additionally found a critical bug in the popular Yosys synthesizer that results in a wrong netlist. To make bug-triggering programs tractable, Cascade relies on automated program reduction, iteratively applying minor in-place modifications to reduce the program to a minimal bug-triggering form while preserving the sufficient bug-triggering CPU state.

For fuzzing throughput, RISCover reproduces Cascade's sweet spot of around 10,000 instructions per sequence. The openC906 and openC910 are even slower to simulate than BOOM (the slowest core Cascade evaluated), achieving only 110 and 26 fuzzing instructions per second respectively, compared to 556 for BOOM, because these softcores come with a much larger non-minimal SoC and are therefore bigger and more complex. RISCover's sequence generation reproduces 22 of 23 user-space-triggerable bugs that Cascade found on the openC906 and openC910.

RISCover was evaluated on closed-source RISC-V CPUs including the T-Head C906, C908, and C910, and the SpacemiT X60, as well as on the open-source designs openC906 and openC910 (the open-source cores T-Head claims are used in the C906 and C910), and on the BOOM core as a comparison point. RISCover's most severe finding is the GhostWrite vulnerability.

SNAP was prototyped on Amazon EC2 F1 controlled by FireSim, an open-source FPGA-accelerated full-system hardware simulation platform that simulates RTL designs with cycle-accurate system components by enabling FPGA-hosted peripherals and system-level interface models, including a last-level cache (LLC) and DDR3 memory. SNAP was synthesized and operated at the default clock frequency of LargeBoomConfig, which is applicable to existing CPU architectures without significant design changes. SNAP's evaluation configuration used the RISC-V BOOM processor with an 8-wide fetch front-end, 16 RAS & 512 BTB entries, a gshare branch predictor, 3-wide decode/dispatch, 96 ROB entries, 100 int & 96 floating point registers, 24 load queue & 24 store queue entries, and 24 BUQ & 32 LBQ entries.

LINKED ENTITIES

1 links

CITATIONS

10 sources
10 citations
[1] CSRs are in charge of controlling and holding the state of the processor, and transitions in CSRs indicate a new processor state. ProcessorFuzz: Guiding Processor Fuzzing using Control and Status Registers
[2] Architectural state visible at the ISA level includes the program counter (PC), general-purpose registers (GPRs), control and status registers (CSRs), and memory contents relevant to execution. RISC-V Lockstep Co-Simulation: Retirement-Level Step-and-Compare for Faster Verification & Debug
[3] Lockstep co-simulation captures architectural state at each instruction retirement and reports mismatches immediately at the point of failure. RISC-V Lockstep Co-Simulation: Retirement-Level Step-and-Compare for Faster Verification & Debug
[4] The lockstep state mask typically progresses from PC-only checks, to PC plus GPRs, to adding CSRs to exercise privilege and exception handling, and finally to selected memory regions or the complete architectural state. RISC-V Lockstep Co-Simulation: Retirement-Level Step-and-Compare for Faster Verification & Debug
[5] Lockstep comparison surfaces CSR side effects, privilege transitions, and subtle ordering errors that traces or self-checks may miss. RISC-V Lockstep Co-Simulation: Retirement-Level Step-and-Compare for Faster Verification & Debug
[6] RVVI is an open standard interface for exchanging retire, state, and event information between the RTL, testbench, and reference models. RISC-V Lockstep Co-Simulation: Retirement-Level Step-and-Compare for Faster Verification & Debug
[7] A 2025 IJEDR project verifies the CSR block of a RISC-V core alongside the IFU, IDU, Execute Unit, LSU, Register File, Pipeline, and Exception/Interrupt Unit using a UVM-based testbench with constrained-random stimulus, assertions, an architectural reference model, and a scoreboard. Verification Of Risc-V Core Blocks Using Uvm
[8] The IJEDR project's toolchain comprises SystemVerilog with the UVM 1.2 / 1.1d (IEEE 1800.2) library, ModelSim / QuestaSim as the simulator, Visual Studio Code as the editor, and QuestaSim's built-in waveform viewer. Verification Of Risc-V Core Blocks Using Uvm
[9] ProcessorFuzz uses CSR-transition coverage as its coverage metric, on the rationale that transitions in CSRs indicate a new processor state, and is HDL-agnostic without requiring processor instrumentation. ProcessorFuzz: Guiding Processor Fuzzing using Control and Status Registers
[10] SNAP introduces new 8-byte CSRs as hardware/OS configuration interfaces for fuzzing instrumentation, including BitmapBase, BitmapSize, TraceEn, TraceStartAddr, TraceEndAddr, and the LbqAddr[0-31] / LbqStatus registers wired to LBQ entries. Hardware Support to Improve Fuzzing Performance and Precision

VERSION HISTORY

v12 · 7/10/2026 · minimax/minimax-m3 (current)
v11 · 7/6/2026 · minimax/minimax-m3
v10 · 7/5/2026 · minimax/minimax-m3
v9 · 6/14/2026 · minimax/minimax-m3
v8 · 6/14/2026 · minimax/minimax-m3
v7 · 6/11/2026 · minimax/minimax-m3
v6 · 6/11/2026 · minimax/minimax-m3
v5 · 6/8/2026 · gpt-5.5
v4 · 6/6/2026 · minimax/minimax-m3
v3 · 6/6/2026 · minimax/minimax-m3
v2 · 5/29/2026 · gpt-5.5
v1 · 5/28/2026 · gpt-5.5