_sprinkler_w0_throughput_bench.nx
buildroot/runtime/_sprinkler_w0_throughput_bench.nx
about
_sprinkler_w0_throughput_bench.nx -- W0 hardened-field embedded
workload baseline.
THE primary W0 (hardened field embedded) workload per
WORKLOAD_TARGETS.md. Sprinkler controller / soil-moisture
sensing / schedule-driven irrigation -- the smallest realistic
production workload the Nishi substrate must run efficiently on
a Cortex-M-class core (or eventually a Tier 0 Nishi-silicon
micro).
Operator cardinal 2026-05-26: "sprinkler systems and sensors and
all that as the hardened field use case".
Inner-loop shape (per sensor sample, sub-ms deadline):
raw = adc_read(soil_moisture_pin) (~1us simulated)
smoothed = ewma(prev_smoothed, raw, alpha) (1 multiply + 1 shift)
if smoothed < dry_threshold && schedule_allows(now):
valve_open()
elif smoothed > wet_threshold:
valve_close()
Bench: 1,000,000 sensor samples processed. No FP; everything
integer (Q12 for the EWMA fraction). Reports samples/sec +
per-sample latency in ns (target: sub-microsecond on bare metal).
Reference numbers for silicon-feedback ROI (W0 tier):
Arduino AVR @ 16 MHz, pure-C ~10K-50K samples/sec
Cortex-M0+ @ 48 MHz, pure-C ~500K samples/sec
Cortex-M4 @ 100 MHz, hand-tuned ~5M samples/sec
This bench, pure-NishiLang on x86_64 ~100M-1B samples/sec est
What this bench produces for silicon-feedback per
WORKLOAD_TARGETS.md per-tier ROI math:
- Per-sample latency (deterministic; the dominant W0 metric)
- Per-instruction attribution (rv64im_min_sim attribution
identifies whether the EWMA multiply or the schedule branch
or the comparator dominates -- the answer guides silicon)
Per [[feedback-honest-perf-verdict]]: this is the baseline.
dependencies 1 imports · 0 importers
imports: nx_syscalls.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 51 | const NX_SPK_N_SAMPLES: i64 = 1000000 // 1M samples |
| 54 | const NX_SPK_EWMA_ALPHA: i64 = 256 // 0.0625 * 4096 |
| 55 | const NX_SPK_EWMA_ONE_MA: i64 = 3840 // 0.9375 * 4096 |
| 56 | const NX_SPK_EWMA_SHIFT: i64 = 12 |
| 59 | const NX_SPK_DRY_THRESHOLD: i64 = 1500 // below = needs water |
| 60 | const NX_SPK_WET_THRESHOLD: i64 = 3000 // above = stop watering |
| 63 | const NX_SPK_SCHED_START_S: i64 = 21600 // 06:00:00 |
| 64 | const NX_SPK_SCHED_END_S: i64 = 28800 // 08:00:00 |
| 67 | const NX_SPK_VALVE_CLOSED: i64 = 0 |
| 68 | const NX_SPK_VALVE_OPEN: i64 = 1 |
functions
| 76 | func nx_spk_schedule_allows(current_s: i64) -> i64 called by 1: main |
| 88 | func nx_spk_ewma_update(prev: i64, raw: i64) -> i64 called by 1: main |
| 99 | func nx_spk_valve_decide(smoothed: i64, current_valve: i64, sched_on: i64) -> i64 called by 1: main |
| 121 | func main() -> i64 |