1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
//! A safe, `no_std` Rust API for machine-learning inference on Cortex-M
//! microcontrollers, built on [IREE](https://iree.dev)'s bare-metal C runtime.
//!
//! The runtime half of IREE (loading a compiled model and invoking it) is
//! wrapped in six RAII types ([`Arena`], [`Instance`], [`Device`], [`Context`],
//! [`Tensor`], [`Error`]) so leaks and double-frees are compile-time
//! impossibilities and every fallible call returns a [`Result`] carrying the
//! real IREE status message. See the repository for a complete firmware
//! example and the model-compilation workflow.
// `Error` inlines a 192-byte IREE status message buffer, so `Result` Err
// variants are large. Deliberate: this is `no_std` with no global allocator,
// and the most important error to report is allocator exhaustion, so the
// message must not itself allocate. The fallible calls here are millisecond
// FFI operations; a ~200-byte move on the error path is noise.
/// Embed a compiled `.vmfb` as a 64-byte-aligned `&'static [u8]`.
///
/// IREE's FlatBuffer verifier requires the module header to be aligned, and,
/// critically, the rodata segments (model weights) inside are only used
/// *in place* when they meet HAL buffer alignment (64 bytes). An underaligned
/// module silently falls back to staging copies through the device queue,
/// which costs RAM and deadlocks the bare-metal single-threaded HAL. A plain
/// `include_bytes!` (1-byte aligned) guarantees neither; use this for any
/// embedded model.
/// Hand out a unique `&'static mut` to a static, at most once per call site.
///
/// The initialiser must be a const expression: the value is a real `static`,
/// living in `.bss`/`.data` like any other, so a multi-kilobyte arena costs
/// no stack to create (passing such a buffer *by value* through an
/// initialiser, as cell-based abstractions do, can overflow a small MCU
/// stack before the move is elided). A second take of the same call site
/// panics rather than aliasing the `&mut`.
///
/// # Panics
///
/// Panics on a second take of the same call site, and in any concurrent race
/// all but one taker panics.
///
/// # Target requirements
///
/// The guard uses an atomic swap, available on Cortex-M3 and above
/// (thumbv7/thumbv8); it is not available on thumbv6m (Cortex-M0/M0+).
///
/// ```
/// let heap: &'static mut [u8; 1024] = iree_embedded::singleton!([u8; 1024] = [0; 1024]);
/// heap[0] = 1;
/// ```
/// Declare the query entry point of a statically linked IREE executable
/// library and yield it as a [`LibraryQueryFn`].
///
/// `iree-compile --iree-hal-target-backends=llvm-cpu` with static-library
/// output produces an object file plus a header naming its query function
/// (for example `my_model_linked_library_query`). Link the object into the
/// firmware and pass the symbol here; give the result to
/// [`Device::local_sync_static`](crate::Device::local_sync_static).
///
/// # Contract
///
/// `$sym` must name the query function of an IREE static library, emitted by
/// `iree-compile` alongside the object file (the `*_library_query` symbol in
/// its generated header). The macro declares, it cannot verify: naming any
/// other symbol misdeclares its ABI, and invoking the device on it is
/// undefined behaviour.
///
/// ```ignore
/// let device = Device::local_sync_static(
/// &arena,
/// &[iree_embedded::link_kernels!(my_model_linked_library_query)],
/// )?;
/// ```
/// Provide the libc stubs a bare-metal newlib link expects, sized for this
/// crate's allocation model.
///
/// Emits `_sbrk` returning failure: the IREE runtime allocates exclusively
/// from the [`Arena`], so the libc heap must never grow. Invoke once at
/// module scope in the firmware binary:
///
/// ```ignore
/// iree_embedded::libc_stubs!();
/// ```
pub use ;
pub use ;
pub use ;
pub use Instance;
pub use check;
pub use ;
pub use Tensor;