> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/a16z/jolt/llms.txt
> Use this file to discover all available pages before exploring further.

# RISC-V Emulation

> Learn how Jolt's tracer emulates RISC-V programs to generate execution traces

## Overview

The **tracer** is Jolt's RISC-V emulator that executes guest programs and produces detailed execution traces. It serves as the first stage in the proving pipeline, converting a compiled RISC-V ELF binary into a sequence of `Cycle` structs that capture every instruction executed.

## Role in the Proving System

The tracer is the foundation of Jolt's zkVM:

1. **Input**: Takes a RISC-V ELF binary (RV64IMAC instruction set) and program inputs
2. **Execution**: Emulates the program instruction-by-instruction, tracking all state changes
3. **Output**: Produces a `Vec<Cycle>` execution trace and final memory state
4. **Handoff**: The execution trace becomes input to witness generation in the next stage

## Architecture

### Core Components

**Emulator** (`tracer/src/emulator/`)

* Full RISC-V CPU emulation with registers, memory management unit (MMU), and program counter
* Supports both 32-bit and 64-bit XLEN modes
* Handles compressed (16-bit) and standard (32-bit) instruction formats

**Instruction Set** (`tracer/src/instruction/`)

* Complete RV64IMAC instruction implementations
* Virtual instruction extensions for optimized cryptographic operations (via jolt-inlines)
* Instruction normalization and decoding

**Memory Management**

* Memory layout configuration for inputs, outputs, bytecode, and advice regions
* Address remapping for efficient constraint checking
* I/O device (`JoltDevice`) tracking program inputs, outputs, panic state

### Execution Trace Format

Each `Cycle` in the trace represents a single instruction execution and contains:

* Program counter (PC)
* Instruction opcode and operands
* Register reads and writes
* Memory accesses (address, value)
* Instruction-specific metadata (e.g., virtual sequence remaining for inlined instructions)

## Lazy Tracing

Jolt uses **lazy trace generation** to reduce memory overhead:

```rust theme={null}
pub struct LazyTraceIterator {
    lazy_tracer: CheckpointingTracer,
}
```

* Traces are generated on-demand via iterator pattern
* Checkpointing support for parallel proving
* Avoids materializing the entire trace in memory upfront

### Checkpointing

For large programs, the tracer can save periodic checkpoints:

* Each checkpoint captures emulator state at a specific cycle count
* Enables parallel proof generation by splitting trace into chunks
* Checkpoints can independently regenerate their trace segment

## Bytecode Preprocessing

The tracer preprocesses bytecode for efficient constraint checking:

**PC Mapping** (`bytecode/mod.rs`)

* Maps physical instruction addresses to virtual PC values
* Handles inline instruction sequences (multi-cycle operations)
* Prepends a no-op instruction at PC=0 for padding

**Alignment**

* Instructions must be aligned to `ALIGNMENT_FACTOR_BYTECODE` boundaries
* Pads bytecode to next power of 2 for efficient polynomial encoding

## Integration with Proving System

The execution trace flows into witness generation:

1. **Trace → Witness Polynomials**:
   * PC values → bytecode lookup polynomials
   * Register reads/writes → register checking polynomials
   * Memory accesses → RAM checking polynomials
   * Instruction flags → instruction lookup polynomials

2. **Memory State**:
   * Initial memory: bytecode + inputs + advice
   * Final memory: outputs + termination/panic bits
   * Used to derive RAM checking constraints

## Key Files

* `tracer/src/lib.rs`: Main trace generation functions (`trace`, `trace_lazy`, `trace_checkpoints`)
* `tracer/src/emulator/`: RISC-V CPU emulator implementation
* `tracer/src/instruction/`: Instruction set implementations
* `jolt-core/src/zkvm/bytecode/`: Bytecode preprocessing and PC mapping

## Performance Considerations

* **Lazy evaluation**: Traces generated on-demand reduce peak memory
* **Checkpointing overhead**: Tracking memory state adds \~10-20% overhead
* **Parallel proving**: Checkpoints enable splitting large traces across workers
* **ELF decoding**: Bytecode extraction happens once during setup

## Next Steps

* [Witness Generation](/architecture/overview): How traces become committed polynomials
* [RAM Checking](/architecture/ram): Memory consistency verification
* [Instruction Lookups](/architecture/instruction-execution): Proving instruction correctness
