# DiffTest Software Check Flow

This document describes the software-side checking path after hardware transport delivers probe data to the C++ runtime.

## Overview

```
Emulator starts (main.cpp)
  │
  ▼
Init: argument parsing → memory/devices → DiffTest → reference model
  │
  ▼
Main loop: tick()
  │
  ├─ DPI-C callbacks write DUT state into diffstate buffer
  │
  ▼
difftest_step()
  │
  ├─ difftest_set_dut()   ← fetch current DUT state from buffer
  ├─ optional: query / trace step
  │
  ▼
Per-core: Difftest::step()
  │
  ├─ step reference model
  ├─ check_all(): run all checkers
  │
  ▼
Result: STATE_OK / STATE_DIFF (mismatch) / TRAP
```

## Detailed Check Flow

### 1. DPI-C Data Landing

The hardware side writes probe data to the C++ `diffstate` buffer via DPI-C functions (`v_difftest_*`, generated by [`DPIC.scala`](../src/main/scala/DPIC.scala)).

- Without batch: each bundle is written individually
- With batch: entire packet is written, then unpacked on C++ side

Buffer management: [`diffstate.cpp`](../src/test/csrc/difftest/diffstate.cpp)

### 2. difftest_step()

The core step function, implemented in [`difftest.cpp`](../src/test/csrc/difftest/difftest.cpp):

1. **`difftest_set_dut()`**: sets the current DUT state from the diffstate buffer
2. **`difftest_query_step()`** (optional): advances the query framework
3. **Per-core `difftest[i]->step()`**: performs single-core checking

### 3. Difftest::step() (Per-Core Check)

In `Difftest::step()` within [`difftest.cpp`](../src/test/csrc/difftest/difftest.cpp):

1. Handle replay logic (if enabled)
2. Step the reference model (based on commit info)
3. Call **`check_all()`**: runs all checkers sequentially
4. Returns status: `STATE_OK`, `STATE_DIFF` (mismatch), `STATE_ERROR`, or trap code

### 4. Checkers

Checkers are located in [`checkers/`](../src/test/csrc/difftest/checkers):

| Checker File | What It Checks |
|-------------|---------------|
| `instructions.cpp` | Committed instruction register value comparison |
| `load.cpp` | Load events |
| `store.cpp` | Store events |
| `traps.cpp` | Traps and exceptions |
| `tlb.cpp` | TLB events |
| `refill.cpp` | Refill events |
| `sync_states.cpp` | CSR and other synchronized state comparison |
| `globalmem.cpp` | Global memory consistency |

When a mismatch is detected, the checker prints detailed DUT/REF state diagnostics and aborts the simulation.

## DPI-C Interface Generation

[`DPIC.scala`](../src/main/scala/DPIC.scala) auto-generates a DPI-C function for each bundle type:

- Single bundle mode: generates `DPIC[T]` module with function name `v_difftest_<bundlename>`
- Batch mode: generates `DPICBatch` module for whole-packet transport
- `DPIC.collect()` outputs `difftest-dpic.h` and `difftest-dpic.cpp`

## Reference Model

The reference model interface is implemented in [`refproxy.cpp`](../src/test/csrc/difftest/refproxy.cpp):

- Loads the reference model `.so` via `dlopen()`
- Resolves function symbols dynamically via `dlsym()` (`ref_init`, `ref_step`, `ref_regcpy`, etc.)
- Build-time selection via `REF=Nemu` or `REF=Spike`
- Runtime path via `--diff <ref.so>`; `--no-diff` skips comparison

Key reference model API:
- `ref_init()` / `ref_init_v2()`: initialization
- `ref_step()`: step one instruction
- `ref_regcpy()`: register state copy (DUT → REF or REF → DUT)
- `ref_set_ramsize()`: set RAM size

## Initialization Flow

`difftest_init()` (in [`difftest.cpp`](../src/test/csrc/difftest/difftest.cpp)):

1. Initialize optional perf, IOTrace, and query helpers
2. Initialize diffstate buffer
3. Optionally initialize golden memory ([`goldenmem.cpp`](../src/test/csrc/difftest/goldenmem.cpp))
4. Create one `Difftest` object per core
5. Create and initialize the reference model proxy
6. Register exit/signal handlers

## Backend Differences

Software checking logic is mostly shared across backends; only process wrappers differ:

| Backend | Entry Directory |
|---------|----------------|
| EMU | [`src/test/csrc/emu/`](../src/test/csrc/emu) (main.cpp → emu.cpp) |
| simv (VCS top) | [`src/test/csrc/vcs/`](../src/test/csrc/vcs) |
| FPGA host | [`src/test/csrc/fpga/`](../src/test/csrc/fpga) |
