Hardware Fault Injection in YOLOv8

Published in VLSI Design Group, Carnegie Mellon University, 2026

Work in progress. More details to come!
Code and full results: mg-04/yolov8-project

A PyTorch fault-injection framework for YOLOv8n, used to find which weights and layers need protection in a secure-FPGA + Jetson deployment. It flips single bits in FP32 weights (memory faults) and activations (buffer and compute faults), then separates silent corruption from detectable corruption.


Method

  • Target: YOLOv8n after BatchNorm fusion, 64 conv layers, ~3.1M parameters, evaluated on COCO
  • Fault sites: weights, persistent activation faults, and transient (single-inference) activation faults
  • Campaign: 64 layers × 16 targets × 6 bit positions × 3 sites = 18,432 injections
  • Outcomes per image:
    • DUE: NaN/Inf in the output, detectable at runtime
    • SDC: clean-looking output with lost, phantom, or misclassified objects, not detectable
    • Benign / masked: detections unchanged or only slightly shifted

Key Findings

  • One bit carries the risk. Bit 30, the FP32 exponent MSB, accounts for ~93% of random-fault risk. Flipping it scales a typical weight by \(2^{128}\)
  • Weight faults are silent; activation faults are loud. At bit 30, weight faults are 83% SDC and 6% DUE, while activation faults are 23% SDC and 31% DUE
  • Every other bit is undetectable. NaN/Inf appears only at bit 30, so faults at other bits never show up in the output
  • The classification head is the most sensitive part of the network under every fault type


Detect Head

Three scales, two branches. Numbers are the per-image SDC rate under a bit-30 fault: W = weight fault, A = persistent activation fault. Red = most sensitive, green = least.

flowchart LR
    classDef hi fill:#c0392b,stroke:#7b241c,color:#fff
    classDef mid fill:#d68910,stroke:#9c640c,color:#fff
    classDef lo fill:#1e8449,stroke:#145a32,color:#fff
    classDef io fill:#5d6d7e,stroke:#34495e,color:#fff,stroke-dasharray:3 3
    P3(["P3 s8<br/>block 15"]) --> CV3
    P4(["P4 s16<br/>block 18"]) --> CV3
    P5(["P5 s32<br/>block 21"]) --> CV3
    P3 --> CV2
    P4 --> CV2
    P5 --> CV2
    CV3["cv3 · class branch<br/>W 98 · A 50<br/>MOST SENSITIVE"] --> OUT["out<br/>84 x 8400"]
    CV2["cv2 · box branch<br/>W 42 · A 0"] --> DFL["dfl · 16 params<br/>W 30 · A 0"] --> OUT
    class CV3 hi
    class CV2,DFL lo
    class P3,P4,P5,OUT io

The class branch (cv3) and the box branch (cv2) see the same inputs at the same depth, yet have opposite sensitivity. A corrupted class score poisons the NMS ranking for the whole image, while a corrupted box coordinate only misplaces one detection.