Skip to content

Inline the RV32 step into the result-only run loop - #335

Open
mfiumara wants to merge 2 commits into
mikroverk:mainfrom
schematik-engineering:c6-speed-lever-2-main
Open

mfiumara wants to merge 2 commits into
mikroverk:mainfrom
schematik-engineering:c6-speed-lever-2-main

Conversation

@mfiumara

@mfiumara mfiumara commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

What and why

On the C3 and C6 (and P4, same core) the result-only run loop calls the RV32 interpreter's step_outcome out of line for every instruction, and that call builds the full observing facts (fetch bytes, length, kind, control) that the result-only caller then throws away. Inlining it lets the compiler drop those facts in the loop.

  1. Inline the step (dd72abaa, riscv-rv32/src/exec.rs, +3/−1): #[inline(always)] on step_outcome, #[inline] → #[inline(always)] on exec_insn, one comment. No change to fetch, retirement, cycles, traps, IRQs, device accesses or budgets; no new state or API.
  2. Differential test riscv-rv32/tests/result_only.rs: observing step, result-only step and one-instruction run compared field by field on all CPU state and RAM.
  3. EX263 row in docs/experiments.md and the receipt in docs/evidence/c6-step-facts/ (CPU table added in 483777b9, docs only).

Based on main 04f07602; no stack dependency. Against the other open PRs it conflicts only in the docs/experiments.md row append (#290).

CPU

Measured on dd72abaa against main 04f07602 (2026-11-01, 1 warmup + 7 alternating pairs, user CPU at 0.01 s resolution, load 1.65–2.33, console SHA-256 identical within each workload):

Workload Median delta Candidate slower Flagged
C6 display starter (Waveshare C6 LCD 1.47, 10 emulated s) −9.29% 0/7 no
C6 hello −2.08% 3/7 no

Per-pair tables are in the receipt. Earlier, on old main bd0dbd1a with a retirement-probe build: starter −10.41% (0/7), hello +0.00% (3/7).

Verification

  1. result_only.rs (release): 49,152 compressed encodings, 16,384 deterministic full-width words and 77 directed instruction/state combinations; passes on main too (it's a preservation test, not a speed oracle).
  2. Mutations: 5/5 killed, none by a compile error. Removing either inline request fails the native codegen gate; dropping retirement or doubling cycles fails the differential test; dropping the observing fetch bytes fails the existing fetch-window test.
  3. Rust 1.99.0, on dd72abaa: native and WASM Clippy -D warnings; ROM workspace tests 1,460 passed / 0 failed; plain 1,396 passed / 95 ignored; WASM build and eight demos (hello c3-hello c6-hello c6-energy-scan c6-contiki c6-contiki-net c6-rpl-net panel); evidence privacy check; git diff --check clean.
  4. Equal work vs main 04f07602 (untimed, native release --bins, ROM boot, 10 emulated s). Scheduler work, IRQ lines/sources and console from the unprobed binaries; retirement from a separate post-run reporting build whose selected hot symbols match the unprobed one (128/128 main, 130/130 PR):
Workload Chip Retired (main = PR) Scheduler insns IRQs Console SHA256
hello C3 3,181,874 1,600,000,000 1,009 6dd87f0ce7e0…
hello/delay C6 3,657,500 1,600,000,000 1,010 d5d1f41f315b…
display starter C6 373,050,392 1,600,000,000 10,346 1e6395a895a9…
  1. Codegen vs main (aarch64, rustc 1.99.0, release, normalised): of 134 selected symbols 113 are identical; the 21 changed/added/removed are RV32 C3/C6/P4 run, modeled and step functions. Machine<C3/C6>::run_unmodeled change layout as the step moves into them (C3 1,060 → 1,040, C6 1,065 → 1,058 static ops); the outlined C6 step_outcome (1,853 ops) is gone. Bus, IRQ, decode, Xtensa and the classic/S3 run loops are identical.
  2. WASM, every named function with resolved types: 2,784 identical, 19 changed, 30 added, 30 removed. 25 added/removed pairs match by suffix-normalised body hash and 8 changes are suffix-only; the rest are RV32 core and C3/C6/P4 machine execution. No outlined step_outcome left (main has five, called from ten sites). Size 4,065,319 → 4,133,209 bytes (+1.67%), gzip -n 1,142,241 → 1,165,704 (+2.05%).

Limits

The CPU table covers C6 only; C3 and P4 share the changed loop layout and are not timed. C6 hello (~0.47 s/run) sits near the 0.01 s timer resolution. Retirement is not read from the timed binary. WASM gets bigger and is not timed here; no browser claim.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mfiumara
mfiumara marked this pull request as ready for review November 1, 2026 02:27
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mfiumara

mfiumara commented Nov 1, 2026

Copy link
Copy Markdown
Collaborator Author

CPU table for dd72abaa vs main 04f07602, now in the receipt (483777b9, docs only). 1 warmup + 7 alternating pairs, user CPU (/usr/bin/time -l), macOS AArch64, rustc 1.99.0 release, load 1.65–2.33; every run stopped at 1,600,000,000 scheduler insns with identical console SHA-256 within its workload.

  1. C6 display starter (Waveshare C6 LCD 1.47, 10 emulated s)
Pair Base user s Candidate user s Delta
1 3.12 2.83 -9.29%
2 3.12 2.91 -6.73%
3 3.12 2.82 -9.62%
4 3.31 2.98 -9.97%
5 3.29 3.03 -7.90%
6 3.24 2.81 -13.27%
7 3.17 2.88 -9.15%

Median -9.29%, slower 0/7, not flagged.

  1. C6 hello
Pair Base user s Candidate user s Delta
1 0.48 0.47 -2.08%
2 0.46 0.47 +2.17%
3 0.47 0.46 -2.13%
4 0.48 0.47 -2.08%
5 0.46 0.49 +6.52%
6 0.47 0.48 +2.13%
7 0.47 0.46 -2.13%

Median -2.08%, slower 3/7, not flagged.

  1. Limits: 0.01 s resolution puts hello (~0.47 s/run) near the noise floor; C3, P4 and WASM were not timed.

@joakimeriksson

Copy link
Copy Markdown
Member

Review of head 483777b9. Thanks, Mattia. The code change is two attributes and the C6 starter gain looks real, so most of what follows is about the receipt.

What I checked:

  • The change is exact by construction. Core::run (riscv-rv32/src/core.rs:31-37) calls exec::step, which is step_outcome(..).result(). Inlining does not change which path a caller takes or what it executes. Observers that need every instruction still go through Machine::step_core → Core::step → step_outcome with all the facts, and block observers still go through step_blocks → Core::run. Interrupt sampling, block_break, the boundary bloom and the quantum logic are the same code as before.
  • Exact work against main 04f07602, native release on both sides, console SHA-256 plus the full stderr minus the wall-time line: c3-hello 30 s, c6-hello 30 s, c6-wifi-station 14 s, p4-hello 12 s, and p4-hello-rev3-smp 12 s (core1 4,315,278,285 insns on both sides). All identical. A 0.02 s c6-hello run with --trace gives the same 3.2M trace lines on both sides, so the per-instruction observer still sees every instruction.
  • Mutation: I dropped retired_count += 1 and result_only.rs failed. It fails at its own retirement assertion (line 51), though, not in the comparison. All three paths run the same function, so the comparison can only catch a future split between them. That is fine as a guard, but it is not evidence for this change.
  • Gate (Rust 1.99.1): native Clippy and wasm32 jit-tests Clippy are clean. The workspace tests with ROMs, --include-ignored --skip external_, give 1,460 passed and 0 failed, which matches your number. check-evidence-privacy.mjs passes and git diff --check is clean.
  • Privacy, checked by hand: the scripts and JSON contain no host paths, user names or hostnames. Every path is passed in as an argument. Nothing to redact.

Asks:

  1. must: the two WASM JSON files break the evidence size rule. wasm-functions.json is 984,174 bytes and wasm-compare.json is 399,893 bytes. Together they are 24,662 of the PR's 26,443 added lines, and they would be the two largest files under docs/evidence/. docs/evidence/README.md:6 says to keep each evidence file below 50 KB. They also add little. 2,784 rows of wasm-functions.json are "identical" rows that carry the same hash twice. wasm-compare.json is a superseded raw-body comparison: it reports 1,065 "changed" functions (index shifts), which looks like a contradiction of the 19 in the headline until you read README line 68. Please keep the counts and only the 79 non-identical rows from wasm-functions.json (about 22 KB with hashes, 11 KB without), and keep the two module SHA-256 values and sizes in the README. Drop wasm-compare.json and compare-wasm.py; the reproduction steps don't use them anyway.
  2. must: rebase. git merge-tree against main 9fdeb323 conflicts in docs/experiments.md: Skip the timer prescaler division below the divisor #290 has merged, and both PRs append a row at the same place. EX263 is still a free ID.
  3. should: cite EX249 in the EX263 row and say what differs. EX249 (Inline C6 instruction fetch and RV32 decode into the step #310) inlined the C6 fetch and both RV32 decoders into step_outcome, which took the C6 copy from 915 to 1,854 instructions. That 1,853-op outlined body is exactly what this PR now inlines into Core::run. AGENTS.md asks for that cross-reference. Something like: "EX249 inlined the callees into the step; EX263 inlines the step into its callers. Still no decoded-block cache for RV32 (unlike EX003/EX125)." The aliases could also name Core::run, exec::step, "result-only run loop" and run_unmodeled, so that a search finds it.
  4. should: the forced inline reaches the observing and modeled paths too, untimed. #[inline(always)] on step_outcome (riscv-rv32/src/exec.rs:77-79) copies the whole interpreter into every caller, not only the result-only one. Your codegen.json shows this. C3 step_core goes from 463 to 2,069 ops and C6 step_core from 465 to 4,350. C6 Machine::run (5,363) is split into newly outlined run_modeled (3,215) and run_until_cycle (4,615); run_until_cycle drives the C6 802.15.4 network nodes, Cooja and the P4 coprocessor lock-step. In WASM, step_core_modeled and step_blocks change, and the module grows by 67,890 bytes (+1.67%, +23 KB gzipped). The speed claim covers only the result-only loop. Could you force the inline only where it pays? For example, an #[inline(always)] inner body used by exec::step, with step_outcome left as a single outlined copy for Core::step. Your codegen gate would show whether the result-only loop still loses the outlined call. If that doesn't keep the gain, say in the row that the observing, modeled and run_until_cycle paths change codegen without being timed.
  5. should: CPU receipt. Only C6 is timed. C6 hello ran 10 emulated seconds, about 0.47 s per run at 0.01 s resolution, where cpu_pairs.py uses 30 s. The per-pair data exists only as README tables; it doesn't record which side ran first in each pair or the load per pair (docs/evidence/README.md:17 asks for run order). Please commit the paired JSON. Our run below covers c3-hello, c6-hello, c6-wifi-station and p4-hello, with s3-hello and pocket-tank as Xtensa controls; you can put it next to yours.
  6. low: codegen.py leftovers. The docstring calls it the "EX168 RV32 result-only codegen gate", but EX168 is the Xtensa dispatch diet (line 2). Line 29 is a note to self ("the previous pattern does not match main"), and gate is computed at line 36 and then again inside result.
  7. low: the differential test covers neither CLIC nor RV32F. setup always uses Cpu::new_rv32imac() with clic = false and no F, so the P4 paths (clic_take, mintthresh, FP loads/stores and mstatus.FS) are never compared, even though P4 codegen changes. One CLIC-mode setup and one misa.F setup would be cheap.
  8. low: receipt wording. The "Scheduler insns" column (README line 26) is the --max-seconds budget, so it is equal by construction; label it that way or drop it. The directory is called c6-step-facts, but the change covers all three RV32 chips.

CPU pairs (our run). cpu_pairs.py from docs/evidence/p4-cpu as on 04f07602, and for p4-hello our copy with a p4-hello workload (the web/wasm/fw/p4-hello.json images, 30 s; script SHA-256 f0b6e70a…). New = 483777b9, base = 04f07602 (the PR's base). Both trees were extracted with git archive into sibling directories with paths of the same length and built with cargo build --release --bins, rustc 1.99.1 (58cf8f9c3 2026-10-13), aarch64-apple-darwin. Machine: Apple M5 Max (18 cores), macOS 27.0.1. Each run of the script started only with the 1-minute load below 5 and nothing building; later workloads in the same run started wherever the load was, as the last column shows (up to 5.71). ROMs: esp-rom-elfs 20260528 (tools/fetch-rom-elfs.sh). One warmup pair, then 7 alternating pairs per workload, from the base tree's root. User CPU comes from rusage at 0.01 s resolution, so on the 0.25 s and 0.39 s workloads one tick is 2.5–4%.

workload base median (range) new median (range) change new slower instructions, console load before → after
c3-hello (30 s) 2.510 s (2.480–2.610) 2.500 s (2.450–2.740) -0.4% 2/7 identical in all 16 runs 4.88 → 5.29
c6-hello (30 s) 1.550 s (1.510–1.580) 1.540 s (1.510–1.640) -0.7% 2/7 identical in all 16 runs 5.29 → 5.06
c6-wifi-station (14 s) 1.020 s (1.010–1.040) 1.020 s (1.000–1.030) +0.0% 1/7 identical in all 16 runs 5.06 → 4.90
s3-hello (30 s) 0.240 s (0.240–0.250) 0.250 s (0.240–0.260) +4.2% 3/7 identical in all 16 runs 4.90 → 5.71
pocket-tank (8 s) 7.370 s (7.340–7.410) 7.350 s (7.300–7.420) -0.3% 2/7 identical in all 16 runs 5.71 → 5.07
p4-hello (30 s) 15.620 s (15.470–15.810) 15.560 s (15.410–15.640) -0.4% 1/7 identical in all 16 runs 4.97 → 5.66

Nothing is flagged (new slower in at least 6 of 7 pairs, or ranges that don't overlap). Instructions and console are identical in every run.

No RV32 workload moves outside the noise: c3-hello −0.4%, c6-hello −0.7%, c6-wifi-station 0.0%, p4-hello −0.4%, with new slower in at most 2 of 7 pairs. Your C6 starter gain is on a workload outside the repo, so this run neither confirms nor contradicts it. s3-hello's +4.2% is one 0.01 s tick on a 0.24 s median, in 3 of 7 pairs, on an Xtensa control this PR doesn't touch.

JSON below. The only edit is the ROM directory written as $ESP32SIM_ROM_DIR: 335-483777b9-04f07602.json raw SHA-256 06677522…, sanitized edd1f281…; 335-483777b9-04f07602-extra.json raw SHA-256 5220a915…, sanitized 882746f5….

335-483777b9-04f07602.json
{
 "started": "2026-11-01T23:17:37+0100",
 "pairs": 7,
 "workloads": {
  "c3-hello": {
   "command": [
    "esp32sim-c3",
    "--boot",
    "rom",
    "--rom",
    "$ESP32SIM_ROM_DIR/esp32c3_rev3_rom.elf",
    "--flash-mb",
    "4",
    "--bootloader",
    "web/wasm/fw/public/c3-hello-bootloader.bin",
    "--ptable",
    "web/wasm/fw/public/c3-hello-ptable.bin",
    "--app",
    "web/wasm/fw/public/c3-hello_world.bin",
    "--max-seconds",
    "30",
    "--no-dump"
   ],
   "load_before": [
    4.87890625,
    7.1953125,
    8.05126953125
   ],
   "runs": [
    {
     "user_s": 2.5,
     "insns": [
      4800000000
     ],
     "console_sha256": "3b9d8d3eb053a97670f11896674e70ffc968fd7a803cb2cdc5c051414af94efd",
     "exit": 0,
     "side": "new",
     "pair": "warmup",
     "order": "N->B"
    },
    {
     "user_s": 2.49,
     "insns": [
      4800000000
     ],
     "console_sha256": "3b9d8d3eb053a97670f11896674e70ffc968fd7a803cb2cdc5c051414af94efd",
     "exit": 0,
     "side": "base",
     "pair": "warmup",
     "order": "N->B"
    },
    {
     "user_s": 2.58,
     "insns": [
      4800000000
     ],
     "console_sha256": "3b9d8d3eb053a97670f11896674e70ffc968fd7a803cb2cdc5c051414af94efd",
     "exit": 0,
     "side": "base",
     "pair": "pair1",
     "order": "B->N"
    },
    {
     "user_s": 2.49,
     "insns": [
      4800000000
     ],
     "console_sha256": "3b9d8d3eb053a97670f11896674e70ffc968fd7a803cb2cdc5c051414af94efd",
     "exit": 0,
     "side": "new",
     "pair": "pair1",
     "order": "B->N"
    },
    {
     "user_s": 2.51,
     "insns": [
      4800000000
     ],
     "console_sha256": "3b9d8d3eb053a97670f11896674e70ffc968fd7a803cb2cdc5c051414af94efd",
     "exit": 0,
     "side": "new",
     "pair": "pair2",
     "order": "N->B"
    },
    {
     "user_s": 2.49,
     "insns": [
      4800000000
     ],
     "console_sha256": "3b9d8d3eb053a97670f11896674e70ffc968fd7a803cb2cdc5c051414af94efd",
     "exit": 0,
     "side": "base",
     "pair": "pair2",
     "order": "N->B"
    },
    {
     "user_s": 2.5,
     "insns": [
      4800000000
     ],
     "console_sha256": "3b9d8d3eb053a97670f11896674e70ffc968fd7a803cb2cdc5c051414af94efd",
     "exit": 0,
     "side": "base",
     "pair": "pair3",
     "order": "B->N"
    },
    {
     "user_s": 2.5,
     "insns": [
      4800000000
     ],
     "console_sha256": "3b9d8d3eb053a97670f11896674e70ffc968fd7a803cb2cdc5c051414af94efd",
     "exit": 0,
     "side": "new",
     "pair": "pair3",
     "order": "B->N"
    },
    {
     "user_s": 2.46,
     "insns": [
      4800000000
     ],
     "console_sha256": "3b9d8d3eb053a97670f11896674e70ffc968fd7a803cb2cdc5c051414af94efd",
     "exit": 0,
     "side": "new",
     "pair": "pair4",
     "order": "N->B"
    },
    {
     "user_s": 2.51,
     "insns": [
      4800000000
     ],
     "console_sha256": "3b9d8d3eb053a97670f11896674e70ffc968fd7a803cb2cdc5c051414af94efd",
     "exit": 0,
     "side": "base",
     "pair": "pair4",
     "order": "N->B"
    },
    {
     "user_s": 2.61,
     "insns": [
      4800000000
     ],
     "console_sha256": "3b9d8d3eb053a97670f11896674e70ffc968fd7a803cb2cdc5c051414af94efd",
     "exit": 0,
     "side": "base",
     "pair": "pair5",
     "order": "B->N"
    },
    {
     "user_s": 2.45,
     "insns": [
      4800000000
     ],
     "console_sha256": "3b9d8d3eb053a97670f11896674e70ffc968fd7a803cb2cdc5c051414af94efd",
     "exit": 0,
     "side": "new",
     "pair": "pair5",
     "order": "B->N"
    },
    {
     "user_s": 2.5,
     "insns": [
      4800000000
     ],
     "console_sha256": "3b9d8d3eb053a97670f11896674e70ffc968fd7a803cb2cdc5c051414af94efd",
     "exit": 0,
     "side": "new",
     "pair": "pair6",
     "order": "N->B"
    },
    {
     "user_s": 2.51,
     "insns": [
      4800000000
     ],
     "console_sha256": "3b9d8d3eb053a97670f11896674e70ffc968fd7a803cb2cdc5c051414af94efd",
     "exit": 0,
     "side": "base",
     "pair": "pair6",
     "order": "N->B"
    },
    {
     "user_s": 2.48,
     "insns": [
      4800000000
     ],
     "console_sha256": "3b9d8d3eb053a97670f11896674e70ffc968fd7a803cb2cdc5c051414af94efd",
     "exit": 0,
     "side": "base",
     "pair": "pair7",
     "order": "B->N"
    },
    {
     "user_s": 2.74,
     "insns": [
      4800000000
     ],
     "console_sha256": "3b9d8d3eb053a97670f11896674e70ffc968fd7a803cb2cdc5c051414af94efd",
     "exit": 0,
     "side": "new",
     "pair": "pair7",
     "order": "B->N"
    }
   ],
   "load_after": [
    5.29150390625,
    7.01123046875,
    7.943359375
   ],
   "summary": {
    "base_median_s": 2.51,
    "new_median_s": 2.5,
    "change_pct": -0.4,
    "base_range_s": [
     2.48,
     2.61
    ],
    "new_range_s": [
     2.45,
     2.74
    ],
    "new_slower_pairs": 2,
    "identical_work_and_console": true,
    "insns": [
     4800000000
    ],
    "console_sha256": "3b9d8d3eb053a97670f11896674e70ffc968fd7a803cb2cdc5c051414af94efd"
   }
  },
  "c6-hello": {
   "command": [
    "esp32sim-c6",
    "--boot",
    "rom",
    "--rom",
    "$ESP32SIM_ROM_DIR/esp32c6_rev0_rom.elf",
    "--flash-mb",
    "4",
    "--bootloader",
    "web/wasm/fw/public/c6-hello-bootloader.bin",
    "--ptable",
    "web/wasm/fw/public/c6-hello-ptable.bin",
    "--app",
    "web/wasm/fw/public/c6-hello_world.bin",
    "--max-seconds",
    "30",
    "--no-dump"
   ],
   "load_before": [
    5.29150390625,
    7.01123046875,
    7.943359375
   ],
   "runs": [
    {
     "user_s": 1.5,
     "insns": [
      4800000000
     ],
     "console_sha256": "bd69fbb9ac5c677337a293c1ec0ff7941306eec82c499290917a7c42360f86ad",
     "exit": 0,
     "side": "new",
     "pair": "warmup",
     "order": "N->B"
    },
    {
     "user_s": 1.53,
     "insns": [
      4800000000
     ],
     "console_sha256": "bd69fbb9ac5c677337a293c1ec0ff7941306eec82c499290917a7c42360f86ad",
     "exit": 0,
     "side": "base",
     "pair": "warmup",
     "order": "N->B"
    },
    {
     "user_s": 1.58,
     "insns": [
      4800000000
     ],
     "console_sha256": "bd69fbb9ac5c677337a293c1ec0ff7941306eec82c499290917a7c42360f86ad",
     "exit": 0,
     "side": "base",
     "pair": "pair1",
     "order": "B->N"
    },
    {
     "user_s": 1.56,
     "insns": [
      4800000000
     ],
     "console_sha256": "bd69fbb9ac5c677337a293c1ec0ff7941306eec82c499290917a7c42360f86ad",
     "exit": 0,
     "side": "new",
     "pair": "pair1",
     "order": "B->N"
    },
    {
     "user_s": 1.56,
     "insns": [
      4800000000
     ],
     "console_sha256": "bd69fbb9ac5c677337a293c1ec0ff7941306eec82c499290917a7c42360f86ad",
     "exit": 0,
     "side": "new",
     "pair": "pair2",
     "order": "N->B"
    },
    {
     "user_s": 1.58,
     "insns": [
      4800000000
     ],
     "console_sha256": "bd69fbb9ac5c677337a293c1ec0ff7941306eec82c499290917a7c42360f86ad",
     "exit": 0,
     "side": "base",
     "pair": "pair2",
     "order": "N->B"
    },
    {
     "user_s": 1.53,
     "insns": [
      4800000000
     ],
     "console_sha256": "bd69fbb9ac5c677337a293c1ec0ff7941306eec82c499290917a7c42360f86ad",
     "exit": 0,
     "side": "base",
     "pair": "pair3",
     "order": "B->N"
    },
    {
     "user_s": 1.54,
     "insns": [
      4800000000
     ],
     "console_sha256": "bd69fbb9ac5c677337a293c1ec0ff7941306eec82c499290917a7c42360f86ad",
     "exit": 0,
     "side": "new",
     "pair": "pair3",
     "order": "B->N"
    },
    {
     "user_s": 1.51,
     "insns": [
      4800000000
     ],
     "console_sha256": "bd69fbb9ac5c677337a293c1ec0ff7941306eec82c499290917a7c42360f86ad",
     "exit": 0,
     "side": "new",
     "pair": "pair4",
     "order": "N->B"
    },
    {
     "user_s": 1.54,
     "insns": [
      4800000000
     ],
     "console_sha256": "bd69fbb9ac5c677337a293c1ec0ff7941306eec82c499290917a7c42360f86ad",
     "exit": 0,
     "side": "base",
     "pair": "pair4",
     "order": "N->B"
    },
    {
     "user_s": 1.57,
     "insns": [
      4800000000
     ],
     "console_sha256": "bd69fbb9ac5c677337a293c1ec0ff7941306eec82c499290917a7c42360f86ad",
     "exit": 0,
     "side": "base",
     "pair": "pair5",
     "order": "B->N"
    },
    {
     "user_s": 1.53,
     "insns": [
      4800000000
     ],
     "console_sha256": "bd69fbb9ac5c677337a293c1ec0ff7941306eec82c499290917a7c42360f86ad",
     "exit": 0,
     "side": "new",
     "pair": "pair5",
     "order": "B->N"
    },
    {
     "user_s": 1.64,
     "insns": [
      4800000000
     ],
     "console_sha256": "bd69fbb9ac5c677337a293c1ec0ff7941306eec82c499290917a7c42360f86ad",
     "exit": 0,
     "side": "new",
     "pair": "pair6",
     "order": "N->B"
    },
    {
     "user_s": 1.51,
     "insns": [
      4800000000
     ],
     "console_sha256": "bd69fbb9ac5c677337a293c1ec0ff7941306eec82c499290917a7c42360f86ad",
     "exit": 0,
     "side": "base",
     "pair": "pair6",
     "order": "N->B"
    },
    {
     "user_s": 1.55,
     "insns": [
      4800000000
     ],
     "console_sha256": "bd69fbb9ac5c677337a293c1ec0ff7941306eec82c499290917a7c42360f86ad",
     "exit": 0,
     "side": "base",
     "pair": "pair7",
     "order": "B->N"
    },
    {
     "user_s": 1.52,
     "insns": [
      4800000000
     ],
     "console_sha256": "bd69fbb9ac5c677337a293c1ec0ff7941306eec82c499290917a7c42360f86ad",
     "exit": 0,
     "side": "new",
     "pair": "pair7",
     "order": "B->N"
    }
   ],
   "load_after": [
    5.06005859375,
    6.81640625,
    7.845703125
   ],
   "summary": {
    "base_median_s": 1.55,
    "new_median_s": 1.54,
    "change_pct": -0.65,
    "base_range_s": [
     1.51,
     1.58
    ],
    "new_range_s": [
     1.51,
     1.64
    ],
    "new_slower_pairs": 2,
    "identical_work_and_console": true,
    "insns": [
     4800000000
    ],
    "console_sha256": "bd69fbb9ac5c677337a293c1ec0ff7941306eec82c499290917a7c42360f86ad"
   }
  },
  "c6-wifi-station": {
   "command": [
    "esp32sim-c6",
    "--rom",
    "$ESP32SIM_ROM_DIR/esp32c6_rev0_rom.elf",
    "--boot",
    "rom",
    "--flash-mb",
    "4",
    "--console",
    "usb",
    "--no-dump",
    "--bootloader",
    "web/wasm/fw/public/c6-wifi-bootloader.bin",
    "--ptable",
    "web/wasm/fw/public/c6-wifi-ptable.bin",
    "--app",
    "web/wasm/fw/public/c6-wifi_station.bin",
    "--wifi",
    "ssid=esp32sim,psk=esp32sim-pass",
    "--net",
    "none",
    "--max-seconds",
    "14"
   ],
   "load_before": [
    5.06005859375,
    6.81640625,
    7.845703125
   ],
   "runs": [
    {
     "user_s": 0.99,
     "insns": [
      2240000000
     ],
     "console_sha256": "75b99af7d413ac5dcfd7d610c3f7360b004460e9d14493416b6c5f4533690601",
     "exit": 0,
     "side": "new",
     "pair": "warmup",
     "order": "N->B"
    },
    {
     "user_s": 1.03,
     "insns": [
      2240000000
     ],
     "console_sha256": "75b99af7d413ac5dcfd7d610c3f7360b004460e9d14493416b6c5f4533690601",
     "exit": 0,
     "side": "base",
     "pair": "warmup",
     "order": "N->B"
    },
    {
     "user_s": 1.01,
     "insns": [
      2240000000
     ],
     "console_sha256": "75b99af7d413ac5dcfd7d610c3f7360b004460e9d14493416b6c5f4533690601",
     "exit": 0,
     "side": "base",
     "pair": "pair1",
     "order": "B->N"
    },
    {
     "user_s": 1.02,
     "insns": [
      2240000000
     ],
     "console_sha256": "75b99af7d413ac5dcfd7d610c3f7360b004460e9d14493416b6c5f4533690601",
     "exit": 0,
     "side": "new",
     "pair": "pair1",
     "order": "B->N"
    },
    {
     "user_s": 1.03,
     "insns": [
      2240000000
     ],
     "console_sha256": "75b99af7d413ac5dcfd7d610c3f7360b004460e9d14493416b6c5f4533690601",
     "exit": 0,
     "side": "new",
     "pair": "pair2",
     "order": "N->B"
    },
    {
     "user_s": 1.03,
     "insns": [
      2240000000
     ],
     "console_sha256": "75b99af7d413ac5dcfd7d610c3f7360b004460e9d14493416b6c5f4533690601",
     "exit": 0,
     "side": "base",
     "pair": "pair2",
     "order": "N->B"
    },
    {
     "user_s": 1.02,
     "insns": [
      2240000000
     ],
     "console_sha256": "75b99af7d413ac5dcfd7d610c3f7360b004460e9d14493416b6c5f4533690601",
     "exit": 0,
     "side": "base",
     "pair": "pair3",
     "order": "B->N"
    },
    {
     "user_s": 1.0,
     "insns": [
      2240000000
     ],
     "console_sha256": "75b99af7d413ac5dcfd7d610c3f7360b004460e9d14493416b6c5f4533690601",
     "exit": 0,
     "side": "new",
     "pair": "pair3",
     "order": "B->N"
    },
    {
     "user_s": 1.01,
     "insns": [
      2240000000
     ],
     "console_sha256": "75b99af7d413ac5dcfd7d610c3f7360b004460e9d14493416b6c5f4533690601",
     "exit": 0,
     "side": "new",
     "pair": "pair4",
     "order": "N->B"
    },
    {
     "user_s": 1.03,
     "insns": [
      2240000000
     ],
     "console_sha256": "75b99af7d413ac5dcfd7d610c3f7360b004460e9d14493416b6c5f4533690601",
     "exit": 0,
     "side": "base",
     "pair": "pair4",
     "order": "N->B"
    },
    {
     "user_s": 1.02,
     "insns": [
      2240000000
     ],
     "console_sha256": "75b99af7d413ac5dcfd7d610c3f7360b004460e9d14493416b6c5f4533690601",
     "exit": 0,
     "side": "base",
     "pair": "pair5",
     "order": "B->N"
    },
    {
     "user_s": 1.02,
     "insns": [
      2240000000
     ],
     "console_sha256": "75b99af7d413ac5dcfd7d610c3f7360b004460e9d14493416b6c5f4533690601",
     "exit": 0,
     "side": "new",
     "pair": "pair5",
     "order": "B->N"
    },
    {
     "user_s": 1.0,
     "insns": [
      2240000000
     ],
     "console_sha256": "75b99af7d413ac5dcfd7d610c3f7360b004460e9d14493416b6c5f4533690601",
     "exit": 0,
     "side": "new",
     "pair": "pair6",
     "order": "N->B"
    },
    {
     "user_s": 1.04,
     "insns": [
      2240000000
     ],
     "console_sha256": "75b99af7d413ac5dcfd7d610c3f7360b004460e9d14493416b6c5f4533690601",
     "exit": 0,
     "side": "base",
     "pair": "pair6",
     "order": "N->B"
    },
    {
     "user_s": 1.02,
     "insns": [
      2240000000
     ],
     "console_sha256": "75b99af7d413ac5dcfd7d610c3f7360b004460e9d14493416b6c5f4533690601",
     "exit": 0,
     "side": "base",
     "pair": "pair7",
     "order": "B->N"
    },
    {
     "user_s": 1.02,
     "insns": [
      2240000000
     ],
     "console_sha256": "75b99af7d413ac5dcfd7d610c3f7360b004460e9d14493416b6c5f4533690601",
     "exit": 0,
     "side": "new",
     "pair": "pair7",
     "order": "B->N"
    }
   ],
   "load_after": [
    4.90478515625,
    6.6943359375,
    7.78369140625
   ],
   "summary": {
    "base_median_s": 1.02,
    "new_median_s": 1.02,
    "change_pct": 0.0,
    "base_range_s": [
     1.01,
     1.04
    ],
    "new_range_s": [
     1.0,
     1.03
    ],
    "new_slower_pairs": 1,
    "identical_work_and_console": true,
    "insns": [
     2240000000
    ],
    "console_sha256": "75b99af7d413ac5dcfd7d610c3f7360b004460e9d14493416b6c5f4533690601"
   }
  },
  "s3-hello": {
   "command": [
    "esp32sim",
    "--boot",
    "rom",
    "--rom",
    "$ESP32SIM_ROM_DIR/esp32s3_rev0_rom.elf",
    "--board",
    "none",
    "--bootloader",
    "web/wasm/fw/public/hello-bootloader.bin",
    "--ptable",
    "web/wasm/fw/public/hello-ptable.bin",
    "--app",
    "web/wasm/fw/public/hello_world.bin",
    "--max-seconds",
    "30",
    "--no-dump"
   ],
   "load_before": [
    4.90478515625,
    6.6943359375,
    7.78369140625
   ],
   "runs": [
    {
     "user_s": 0.25,
     "insns": [
      11990305,
      6798164
     ],
     "console_sha256": "04d4912461cbf19e2d2af0a61885991156d7ebdde8641f2d64d9b219b5ff47d3",
     "exit": 0,
     "side": "new",
     "pair": "warmup",
     "order": "N->B"
    },
    {
     "user_s": 0.25,
     "insns": [
      11990305,
      6798164
     ],
     "console_sha256": "04d4912461cbf19e2d2af0a61885991156d7ebdde8641f2d64d9b219b5ff47d3",
     "exit": 0,
     "side": "base",
     "pair": "warmup",
     "order": "N->B"
    },
    {
     "user_s": 0.24,
     "insns": [
      11990305,
      6798164
     ],
     "console_sha256": "04d4912461cbf19e2d2af0a61885991156d7ebdde8641f2d64d9b219b5ff47d3",
     "exit": 0,
     "side": "base",
     "pair": "pair1",
     "order": "B->N"
    },
    {
     "user_s": 0.25,
     "insns": [
      11990305,
      6798164
     ],
     "console_sha256": "04d4912461cbf19e2d2af0a61885991156d7ebdde8641f2d64d9b219b5ff47d3",
     "exit": 0,
     "side": "new",
     "pair": "pair1",
     "order": "B->N"
    },
    {
     "user_s": 0.24,
     "insns": [
      11990305,
      6798164
     ],
     "console_sha256": "04d4912461cbf19e2d2af0a61885991156d7ebdde8641f2d64d9b219b5ff47d3",
     "exit": 0,
     "side": "new",
     "pair": "pair2",
     "order": "N->B"
    },
    {
     "user_s": 0.25,
     "insns": [
      11990305,
      6798164
     ],
     "console_sha256": "04d4912461cbf19e2d2af0a61885991156d7ebdde8641f2d64d9b219b5ff47d3",
     "exit": 0,
     "side": "base",
     "pair": "pair2",
     "order": "N->B"
    },
    {
     "user_s": 0.24,
     "insns": [
      11990305,
      6798164
     ],
     "console_sha256": "04d4912461cbf19e2d2af0a61885991156d7ebdde8641f2d64d9b219b5ff47d3",
     "exit": 0,
     "side": "base",
     "pair": "pair3",
     "order": "B->N"
    },
    {
     "user_s": 0.24,
     "insns": [
      11990305,
      6798164
     ],
     "console_sha256": "04d4912461cbf19e2d2af0a61885991156d7ebdde8641f2d64d9b219b5ff47d3",
     "exit": 0,
     "side": "new",
     "pair": "pair3",
     "order": "B->N"
    },
    {
     "user_s": 0.26,
     "insns": [
      11990305,
      6798164
     ],
     "console_sha256": "04d4912461cbf19e2d2af0a61885991156d7ebdde8641f2d64d9b219b5ff47d3",
     "exit": 0,
     "side": "new",
     "pair": "pair4",
     "order": "N->B"
    },
    {
     "user_s": 0.24,
     "insns": [
      11990305,
      6798164
     ],
     "console_sha256": "04d4912461cbf19e2d2af0a61885991156d7ebdde8641f2d64d9b219b5ff47d3",
     "exit": 0,
     "side": "base",
     "pair": "pair4",
     "order": "N->B"
    },
    {
     "user_s": 0.25,
     "insns": [
      11990305,
      6798164
     ],
     "console_sha256": "04d4912461cbf19e2d2af0a61885991156d7ebdde8641f2d64d9b219b5ff47d3",
     "exit": 0,
     "side": "base",
     "pair": "pair5",
     "order": "B->N"
    },
    {
     "user_s": 0.25,
     "insns": [
      11990305,
      6798164
     ],
     "console_sha256": "04d4912461cbf19e2d2af0a61885991156d7ebdde8641f2d64d9b219b5ff47d3",
     "exit": 0,
     "side": "new",
     "pair": "pair5",
     "order": "B->N"
    },
    {
     "user_s": 0.24,
     "insns": [
      11990305,
      6798164
     ],
     "console_sha256": "04d4912461cbf19e2d2af0a61885991156d7ebdde8641f2d64d9b219b5ff47d3",
     "exit": 0,
     "side": "new",
     "pair": "pair6",
     "order": "N->B"
    },
    {
     "user_s": 0.25,
     "insns": [
      11990305,
      6798164
     ],
     "console_sha256": "04d4912461cbf19e2d2af0a61885991156d7ebdde8641f2d64d9b219b5ff47d3",
     "exit": 0,
     "side": "base",
     "pair": "pair6",
     "order": "N->B"
    },
    {
     "user_s": 0.24,
     "insns": [
      11990305,
      6798164
     ],
     "console_sha256": "04d4912461cbf19e2d2af0a61885991156d7ebdde8641f2d64d9b219b5ff47d3",
     "exit": 0,
     "side": "base",
     "pair": "pair7",
     "order": "B->N"
    },
    {
     "user_s": 0.25,
     "insns": [
      11990305,
      6798164
     ],
     "console_sha256": "04d4912461cbf19e2d2af0a61885991156d7ebdde8641f2d64d9b219b5ff47d3",
     "exit": 0,
     "side": "new",
     "pair": "pair7",
     "order": "B->N"
    }
   ],
   "load_after": [
    5.712890625,
    6.83203125,
    7.82568359375
   ],
   "summary": {
    "base_median_s": 0.24,
    "new_median_s": 0.25,
    "change_pct": 4.17,
    "base_range_s": [
     0.24,
     0.25
    ],
    "new_range_s": [
     0.24,
     0.26
    ],
    "new_slower_pairs": 3,
    "identical_work_and_console": true,
    "insns": [
     11990305,
     6798164
    ],
    "console_sha256": "04d4912461cbf19e2d2af0a61885991156d7ebdde8641f2d64d9b219b5ff47d3"
   }
  },
  "pocket-tank": {
   "command": [
    "esp32sim",
    "--boot",
    "rom",
    "--rom",
    "$ESP32SIM_ROM_DIR/esp32s3_rev0_rom.elf",
    "--board",
    "waveshare-amoled18-v2",
    "--flash-mb",
    "16",
    "--psram-mb",
    "8",
    "--bootloader",
    "web/wasm/fw/public/pocket-tank-bootloader.bin",
    "--ptable",
    "web/wasm/fw/public/pocket-tank-ptable.bin",
    "--app",
    "web/wasm/fw/public/pocket-tank.bin",
    "--flash-at",
    "0x290000=web/wasm/fw/local/model_q4.bin",
    "--max-seconds",
    "8",
    "--no-dump"
   ],
   "load_before": [
    5.712890625,
    6.83203125,
    7.82568359375
   ],
   "runs": [
    {
     "user_s": 7.4,
     "insns": [
      1115772031,
      946151715
     ],
     "console_sha256": "1d1d57f7c150bcaf169c57bd1f050f5b86cb5550b121480254bcaa616d201bd8",
     "exit": 0,
     "side": "new",
     "pair": "warmup",
     "order": "N->B"
    },
    {
     "user_s": 7.45,
     "insns": [
      1115772031,
      946151715
     ],
     "console_sha256": "1d1d57f7c150bcaf169c57bd1f050f5b86cb5550b121480254bcaa616d201bd8",
     "exit": 0,
     "side": "base",
     "pair": "warmup",
     "order": "N->B"
    },
    {
     "user_s": 7.4,
     "insns": [
      1115772031,
      946151715
     ],
     "console_sha256": "1d1d57f7c150bcaf169c57bd1f050f5b86cb5550b121480254bcaa616d201bd8",
     "exit": 0,
     "side": "base",
     "pair": "pair1",
     "order": "B->N"
    },
    {
     "user_s": 7.35,
     "insns": [
      1115772031,
      946151715
     ],
     "console_sha256": "1d1d57f7c150bcaf169c57bd1f050f5b86cb5550b121480254bcaa616d201bd8",
     "exit": 0,
     "side": "new",
     "pair": "pair1",
     "order": "B->N"
    },
    {
     "user_s": 7.42,
     "insns": [
      1115772031,
      946151715
     ],
     "console_sha256": "1d1d57f7c150bcaf169c57bd1f050f5b86cb5550b121480254bcaa616d201bd8",
     "exit": 0,
     "side": "new",
     "pair": "pair2",
     "order": "N->B"
    },
    {
     "user_s": 7.37,
     "insns": [
      1115772031,
      946151715
     ],
     "console_sha256": "1d1d57f7c150bcaf169c57bd1f050f5b86cb5550b121480254bcaa616d201bd8",
     "exit": 0,
     "side": "base",
     "pair": "pair2",
     "order": "N->B"
    },
    {
     "user_s": 7.35,
     "insns": [
      1115772031,
      946151715
     ],
     "console_sha256": "1d1d57f7c150bcaf169c57bd1f050f5b86cb5550b121480254bcaa616d201bd8",
     "exit": 0,
     "side": "base",
     "pair": "pair3",
     "order": "B->N"
    },
    {
     "user_s": 7.35,
     "insns": [
      1115772031,
      946151715
     ],
     "console_sha256": "1d1d57f7c150bcaf169c57bd1f050f5b86cb5550b121480254bcaa616d201bd8",
     "exit": 0,
     "side": "new",
     "pair": "pair3",
     "order": "B->N"
    },
    {
     "user_s": 7.42,
     "insns": [
      1115772031,
      946151715
     ],
     "console_sha256": "1d1d57f7c150bcaf169c57bd1f050f5b86cb5550b121480254bcaa616d201bd8",
     "exit": 0,
     "side": "new",
     "pair": "pair4",
     "order": "N->B"
    },
    {
     "user_s": 7.34,
     "insns": [
      1115772031,
      946151715
     ],
     "console_sha256": "1d1d57f7c150bcaf169c57bd1f050f5b86cb5550b121480254bcaa616d201bd8",
     "exit": 0,
     "side": "base",
     "pair": "pair4",
     "order": "N->B"
    },
    {
     "user_s": 7.39,
     "insns": [
      1115772031,
      946151715
     ],
     "console_sha256": "1d1d57f7c150bcaf169c57bd1f050f5b86cb5550b121480254bcaa616d201bd8",
     "exit": 0,
     "side": "base",
     "pair": "pair5",
     "order": "B->N"
    },
    {
     "user_s": 7.34,
     "insns": [
      1115772031,
      946151715
     ],
     "console_sha256": "1d1d57f7c150bcaf169c57bd1f050f5b86cb5550b121480254bcaa616d201bd8",
     "exit": 0,
     "side": "new",
     "pair": "pair5",
     "order": "B->N"
    },
    {
     "user_s": 7.31,
     "insns": [
      1115772031,
      946151715
     ],
     "console_sha256": "1d1d57f7c150bcaf169c57bd1f050f5b86cb5550b121480254bcaa616d201bd8",
     "exit": 0,
     "side": "new",
     "pair": "pair6",
     "order": "N->B"
    },
    {
     "user_s": 7.34,
     "insns": [
      1115772031,
      946151715
     ],
     "console_sha256": "1d1d57f7c150bcaf169c57bd1f050f5b86cb5550b121480254bcaa616d201bd8",
     "exit": 0,
     "side": "base",
     "pair": "pair6",
     "order": "N->B"
    },
    {
     "user_s": 7.41,
     "insns": [
      1115772031,
      946151715
     ],
     "console_sha256": "1d1d57f7c150bcaf169c57bd1f050f5b86cb5550b121480254bcaa616d201bd8",
     "exit": 0,
     "side": "base",
     "pair": "pair7",
     "order": "B->N"
    },
    {
     "user_s": 7.3,
     "insns": [
      1115772031,
      946151715
     ],
     "console_sha256": "1d1d57f7c150bcaf169c57bd1f050f5b86cb5550b121480254bcaa616d201bd8",
     "exit": 0,
     "side": "new",
     "pair": "pair7",
     "order": "B->N"
    }
   ],
   "load_after": [
    5.06884765625,
    6.2158203125,
    7.4443359375
   ],
   "summary": {
    "base_median_s": 7.37,
    "new_median_s": 7.35,
    "change_pct": -0.27,
    "base_range_s": [
     7.34,
     7.41
    ],
    "new_range_s": [
     7.3,
     7.42
    ],
    "new_slower_pairs": 2,
    "identical_work_and_console": true,
    "insns": [
     1115772031,
     946151715
    ],
    "console_sha256": "1d1d57f7c150bcaf169c57bd1f050f5b86cb5550b121480254bcaa616d201bd8"
   }
  }
 },
 "finished": "2026-11-01T23:21:04+0100"
}
335-483777b9-04f07602-extra.json
{
 "started": "2026-11-01T23:26:13+0100",
 "pairs": 7,
 "workloads": {
  "p4-hello": {
   "command": [
    "esp32sim-p4",
    "--rom",
    "$ESP32SIM_ROM_DIR/esp32p4_rev0_rom.elf",
    "--boot",
    "rom",
    "--flash-mb",
    "2",
    "--bootloader",
    "web/wasm/fw/public/p4-hello-bootloader.bin",
    "--ptable",
    "web/wasm/fw/public/p4-hello-ptable.bin",
    "--app",
    "web/wasm/fw/public/p4-hello_world.bin",
    "--max-seconds",
    "30",
    "--no-dump"
   ],
   "load_before": [
    4.970703125,
    5.33544921875,
    6.6337890625
   ],
   "runs": [
    {
     "user_s": 15.84,
     "insns": [
      10800000000,
      0
     ],
     "console_sha256": "3d24ec4ac730ed8f8843eda1997dea9cf115707ce7832196076a8a6730842be5",
     "exit": 0,
     "side": "new",
     "pair": "warmup",
     "order": "N->B"
    },
    {
     "user_s": 15.71,
     "insns": [
      10800000000,
      0
     ],
     "console_sha256": "3d24ec4ac730ed8f8843eda1997dea9cf115707ce7832196076a8a6730842be5",
     "exit": 0,
     "side": "base",
     "pair": "warmup",
     "order": "N->B"
    },
    {
     "user_s": 15.47,
     "insns": [
      10800000000,
      0
     ],
     "console_sha256": "3d24ec4ac730ed8f8843eda1997dea9cf115707ce7832196076a8a6730842be5",
     "exit": 0,
     "side": "base",
     "pair": "pair1",
     "order": "B->N"
    },
    {
     "user_s": 15.41,
     "insns": [
      10800000000,
      0
     ],
     "console_sha256": "3d24ec4ac730ed8f8843eda1997dea9cf115707ce7832196076a8a6730842be5",
     "exit": 0,
     "side": "new",
     "pair": "pair1",
     "order": "B->N"
    },
    {
     "user_s": 15.56,
     "insns": [
      10800000000,
      0
     ],
     "console_sha256": "3d24ec4ac730ed8f8843eda1997dea9cf115707ce7832196076a8a6730842be5",
     "exit": 0,
     "side": "new",
     "pair": "pair2",
     "order": "N->B"
    },
    {
     "user_s": 15.65,
     "insns": [
      10800000000,
      0
     ],
     "console_sha256": "3d24ec4ac730ed8f8843eda1997dea9cf115707ce7832196076a8a6730842be5",
     "exit": 0,
     "side": "base",
     "pair": "pair2",
     "order": "N->B"
    },
    {
     "user_s": 15.52,
     "insns": [
      10800000000,
      0
     ],
     "console_sha256": "3d24ec4ac730ed8f8843eda1997dea9cf115707ce7832196076a8a6730842be5",
     "exit": 0,
     "side": "base",
     "pair": "pair3",
     "order": "B->N"
    },
    {
     "user_s": 15.64,
     "insns": [
      10800000000,
      0
     ],
     "console_sha256": "3d24ec4ac730ed8f8843eda1997dea9cf115707ce7832196076a8a6730842be5",
     "exit": 0,
     "side": "new",
     "pair": "pair3",
     "order": "B->N"
    },
    {
     "user_s": 15.61,
     "insns": [
      10800000000,
      0
     ],
     "console_sha256": "3d24ec4ac730ed8f8843eda1997dea9cf115707ce7832196076a8a6730842be5",
     "exit": 0,
     "side": "new",
     "pair": "pair4",
     "order": "N->B"
    },
    {
     "user_s": 15.79,
     "insns": [
      10800000000,
      0
     ],
     "console_sha256": "3d24ec4ac730ed8f8843eda1997dea9cf115707ce7832196076a8a6730842be5",
     "exit": 0,
     "side": "base",
     "pair": "pair4",
     "order": "N->B"
    },
    {
     "user_s": 15.51,
     "insns": [
      10800000000,
      0
     ],
     "console_sha256": "3d24ec4ac730ed8f8843eda1997dea9cf115707ce7832196076a8a6730842be5",
     "exit": 0,
     "side": "base",
     "pair": "pair5",
     "order": "B->N"
    },
    {
     "user_s": 15.49,
     "insns": [
      10800000000,
      0
     ],
     "console_sha256": "3d24ec4ac730ed8f8843eda1997dea9cf115707ce7832196076a8a6730842be5",
     "exit": 0,
     "side": "new",
     "pair": "pair5",
     "order": "B->N"
    },
    {
     "user_s": 15.52,
     "insns": [
      10800000000,
      0
     ],
     "console_sha256": "3d24ec4ac730ed8f8843eda1997dea9cf115707ce7832196076a8a6730842be5",
     "exit": 0,
     "side": "new",
     "pair": "pair6",
     "order": "N->B"
    },
    {
     "user_s": 15.62,
     "insns": [
      10800000000,
      0
     ],
     "console_sha256": "3d24ec4ac730ed8f8843eda1997dea9cf115707ce7832196076a8a6730842be5",
     "exit": 0,
     "side": "base",
     "pair": "pair6",
     "order": "N->B"
    },
    {
     "user_s": 15.81,
     "insns": [
      10800000000,
      0
     ],
     "console_sha256": "3d24ec4ac730ed8f8843eda1997dea9cf115707ce7832196076a8a6730842be5",
     "exit": 0,
     "side": "base",
     "pair": "pair7",
     "order": "B->N"
    },
    {
     "user_s": 15.56,
     "insns": [
      10800000000,
      0
     ],
     "console_sha256": "3d24ec4ac730ed8f8843eda1997dea9cf115707ce7832196076a8a6730842be5",
     "exit": 0,
     "side": "new",
     "pair": "pair7",
     "order": "B->N"
    }
   ],
   "load_after": [
    5.6591796875,
    5.4609375,
    6.34375
   ],
   "summary": {
    "base_median_s": 15.62,
    "new_median_s": 15.56,
    "change_pct": -0.38,
    "base_range_s": [
     15.47,
     15.81
    ],
    "new_range_s": [
     15.41,
     15.64
    ],
    "new_slower_pairs": 1,
    "identical_work_and_console": true,
    "insns": [
     10800000000,
     0
    ],
    "console_sha256": "3d24ec4ac730ed8f8843eda1997dea9cf115707ce7832196076a8a6730842be5"
   }
  }
 },
 "finished": "2026-11-01T23:30:26+0100"
}

Merge after 1 and 2, ideally 3 and 4 as well.

@joakimeriksson

Copy link
Copy Markdown
Member

Thanks for this. The code change is two attributes (#[inline(always)] on step_outcome and exec_insn), so it cannot change behaviour, and the new differential test is a useful guard. I merged it with current main (a57c5e0) locally. riscv-rv32/src/exec.rs merges cleanly with the P4 CLINT-mode change from e292c82, and cargo test --release -p riscv-rv32 -p esp32c3 -p esp32c6 passes on the merge.

Conflict. Only docs/experiments.md conflicts: main added EX264 on the same lines. Please keep both rows (EX263 is still free).

should: evidence size. Almost all of the +26k lines are two per-function hash tables: wasm-functions.json (17,183 lines, 984 KB) and wasm-compare.json (7,479 lines, 400 KB). Most of their rows say "identical", and the scripts and pinned revisions can regenerate both. AGENTS.md asks for curated evidence, so please keep only the changed, added and removed rows plus the totals (or gzip the full tables). Also, compare-wasm.py and compare_wat.py seem to do overlapping jobs, so one of them could go. The privacy check passes, and I found no paths, hostnames or names in the receipt.

should: timing coverage. The change also alters C3 and P4 codegen (and WASM size grows by 1.67%), but only C6 was timed. CONTRIBUTING's Speed section asks for c3-hello too. Please add c3-hello. Please also re-time c6-hello at 30 emulated seconds: at about 0.47 s per run with 0.01 s resolution, the −2.08% result (3/7 slower) can't be told apart from noise. A short WASM check (headless Chrome or Node on c6-hello) would cover the size growth. The display starter result (−9.29%, 0/7 slower) is convincing.

low. The differential test never sets cpu.clic, so it doesn't cover the CLIC paths in step_outcome, including main's new CLINT-mode delivery. Adding one clic = true mode with mtvec in mode 0 and mode 3 would cover them.

Interaction with #356 (decoded RV32 blocks). That PR rewrites the same exec_insn lines: exec_insn becomes an #[inline] wrapper around a new exec_insn_inline, which is #[inline(always)]. Whichever PR lands second gets a small textual conflict there. The gains don't overlap: #356 only enables blocks when the bus exposes page_versions(), and in that PR only the S31 does. C3, C6 and P4 keep going through exec::step, which calls step_outcome, so this PR's gain stays. On the S31, forcing step_outcome inline also inlines it into the block engine's step_one fallback, so we would re-time the S31 run after the rebase.

Happy to merge once the experiments row is rebased and the evidence is trimmed. The timing additions can come in the same push.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants