Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
369 changes: 369 additions & 0 deletions docs/adr/ADR-095-on-esp32-temporal-modeling-sparse-attention.md

Large diffs are not rendered by default.

389 changes: 389 additions & 0 deletions docs/adr/ADR-096-aether-temporal-head-sparse-gqa.md

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions firmware/esp32-csi-node/components/ruv_temporal/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Per-component cargo config so `cargo build` picks the xtensa target
# without the caller having to remember `--target xtensa-esp32s3-none-elf`.
# CMakeLists.txt still passes --target explicitly for clarity.

[build]
target = "xtensa-esp32s3-none-elf"

# The esp toolchain ships precompiled core and alloc for
# xtensa-esp32s3-none-elf, so build-std is unnecessary and (as of the
# 2025-09-16 esp nightly) actively broken on portable_simd.
49 changes: 49 additions & 0 deletions firmware/esp32-csi-node/components/ruv_temporal/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# ESP-IDF component manifest for the ruv_temporal Rust staticlib (ADR-095).
#
# Build flow:
# - When CONFIG_CSI_TEMPORAL_HEAD_ENABLED is OFF (default): register an
# empty stub. main/temporal_task.c compiles the no-op shim path, no
# cargo, no Rust toolchain dependency. Default firmware build is
# unaffected.
# - When CONFIG_CSI_TEMPORAL_HEAD_ENABLED is ON: invoke
# `cargo +esp build --release --target xtensa-esp32s3-none-elf`,
# register the resulting libruv_temporal.a, and expose include/.
#
# add_custom_command is intentionally placed AFTER idf_component_register
# because ESP-IDF runs every component's CMakeLists.txt twice — once in
# script mode for dependency discovery (where add_custom_command is
# forbidden), and once for the actual build.

if(NOT CONFIG_CSI_TEMPORAL_HEAD_ENABLED)
# Feature disabled — register an empty component so the directory's
# mere existence doesn't break the build, but do NOT invoke cargo
# or pull include/ onto consumers' include paths (the C ABI header
# would advertise capabilities we cannot honour).
idf_component_register()
return()
endif()

set(RUV_TEMPORAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(RUV_TEMPORAL_TARGET "xtensa-esp32s3-none-elf")
set(RUV_TEMPORAL_PROFILE "release")
set(RUV_TEMPORAL_LIB
"${RUV_TEMPORAL_DIR}/target/${RUV_TEMPORAL_TARGET}/${RUV_TEMPORAL_PROFILE}/libruv_temporal.a")

idf_component_register(
SRCS "shim.c"
INCLUDE_DIRS "include"
PRIV_REQUIRES "esp_common"
)

# Custom command + target run only at build time, not in script mode.
add_custom_command(
OUTPUT "${RUV_TEMPORAL_LIB}"
WORKING_DIRECTORY "${RUV_TEMPORAL_DIR}"
COMMAND cargo +esp build --release --target ${RUV_TEMPORAL_TARGET}
COMMENT "Building ruv_temporal Rust staticlib for ${RUV_TEMPORAL_TARGET}"
VERBATIM
)
add_custom_target(ruv_temporal_rust_build ALL DEPENDS "${RUV_TEMPORAL_LIB}")

add_dependencies(${COMPONENT_LIB} ruv_temporal_rust_build)
target_link_libraries(${COMPONENT_LIB} INTERFACE "${RUV_TEMPORAL_LIB}")
218 changes: 218 additions & 0 deletions firmware/esp32-csi-node/components/ruv_temporal/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions firmware/esp32-csi-node/components/ruv_temporal/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[package]
name = "ruv_temporal"
version = "0.1.0"
edition = "2021"
license = "MIT"
description = "ESP32-S3 on-device temporal head for WiFi-DensePose (ADR-095, #513)"
publish = false

[lib]
crate-type = ["staticlib"]
name = "ruv_temporal"

# Don't get pulled into the v2 workspace — this crate cross-compiles to
# xtensa-esp32s3-none-elf, the workspace targets host x86_64.
[workspace]

[dependencies]
ruvllm_sparse_attention = { path = "../../../../vendor/ruvector/crates/ruvllm_sparse_attention", default-features = false, features = ["fp16"] }

# Minimal no_std + alloc plumbing. esp-alloc supplies a GlobalAlloc that
# punches through to ESP-IDF's heap_caps_malloc; critical-section provides
# the lock primitive linked_list_allocator wants on no_std targets.
esp-alloc = "0.8"
critical-section = "1"

[profile.release]
opt-level = "s"
lto = true
codegen-units = 1
panic = "abort"
strip = true

[profile.dev]
opt-level = 1
panic = "abort"
Loading
Loading