Write bare-metal benchmarks and run fault injection campaigns on the FIM server.
-
Get from your supervisor:
- SSH private key file (e.g.,
fim-YOUR_USERNAME) - Server IP (e.g.,
SERVER_IP) - Your username (e.g.,
YOUR_USERNAME)
- SSH private key file (e.g.,
-
Save the key:
cp fim-YOUR_USERNAME ~/.ssh/fim-YOUR_USERNAME chmod 600 ~/.ssh/fim-YOUR_USERNAME
-
Create your config:
cp config.yaml.example config.yaml
-
Edit
config.yaml:user: YOUR_USERNAME server: SERVER_IP ssh_key: ~/.ssh/fim-YOUR_USERNAME port: 8765
-
Test connection:
ssh -i ~/.ssh/fim-YOUR_USERNAME fim-YOUR_USERNAME@SERVER_IP 'fim-run list'
One command does everything — upload, build, golden run, fault injection, download results:
./run.sh benchmarks/mmult -n 20Options:
-n, --injections N Number of fault injections (default: 20)
--fault TYPE register or memory (default: register)
--workers N Parallel QEMU instances (default: 1)
--arch ARCH riscv64 or aarch64 (default: riscv64)
--seed N PRNG seed for reproducibility (default: 42)
Results are saved to results/ on your machine. Server is cleaned automatically.
Copy the template:
cp -r benchmarks/template benchmarks/my_algoEdit benchmarks/my_algo/main.c:
#include "fim_exit.h"
#define N 64
volatile int result[N];
int main(void) {
int input[N];
for (int i = 0; i < N; i++) input[i] = i;
fim_init(); /* fault injection window starts */
for (int i = 0; i < N; i++) {
result[i] = input[i] * input[i] + 1;
}
fim_exit(0); /* fault injection window ends */
}Edit benchmarks/my_algo/fim.yaml:
observable_outputs:
comparison: "exact"
variables:
- name: "result"Run:
./run.sh benchmarks/my_algo -n 50-
fim_init()/fim_exit(0)bracket the code under test. Faults are only injected between these markers. -
Global
volatilevariables are how FIM detects SDC. Declare outputs asvolatile int result[N]at file scope. -
fim.yamllists observable variables. Types are auto-detected from the ELF. Just list names. -
No stdlib. This runs bare-metal on QEMU. You get
<stdint.h>and that's it. Noprintf, nomalloc. -
Initialize before
fim_init(). Setup arrays and constants before the injection window.
For benchmarks that communicate via serial (e.g., robot arm with PyBullet):
- Add a
requirements.txtwith Python dependencies - Add
serial_ptyandserial_feeder_cmdtofim.yaml:
timeout: 120
observable_outputs:
variables:
- name: "tau"
- name: "posicion"
serial_pty: true
serial_feeder_cmd: "python3 {benchmark_dir}/feeder.py --pty {pty}"The server auto-installs requirements and runs the feeder alongside QEMU.
./upload.sh benchmarks/my_algo # upload only
./download-results.sh # list past results
./download-results.sh --all # download all resultsFIM-client/
config.yaml # your server connection
run.sh # upload + build + run + download
upload.sh # upload benchmark to server
download-results.sh # pull results
build.sh # local cross-compile (optional)
sdk/ # FIM SDK (don't modify)
include/fim_exit.h
src/fim_instrumentation.c
riscv64/ # startup + linker
aarch64/
benchmarks/
template/ # copy this to start
mmult/ # 16x16 matrix multiply
fibonacci/ # Fibonacci sequence
bitcount/ # Hamming weight
checksum/ # XOR reduction
robot_arm/ # PID controller with PyBullet feeder
results/ # campaign results (local)
| Outcome | Meaning |
|---|---|
| MASKED | Fault had no effect on the result |
| SDC | Silent Data Corruption — wrong result, undetected |
| DETECTED | Benchmark's own error detection caught the fault |
| CRASH | Program crashed |
| TIMEOUT | Execution exceeded time limit |