ruvector_sparse_inference/precision/
lanes.rs1use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
9pub enum PrecisionLane {
10 Bit3,
14
15 Bit5,
19
20 Bit7,
24
25 Float32,
27}
28
29impl PrecisionLane {
30 pub fn bits(&self) -> u8 {
32 match self {
33 Self::Bit3 => 3,
34 Self::Bit5 => 5,
35 Self::Bit7 => 7,
36 Self::Float32 => 32,
37 }
38 }
39
40 pub fn value_range(&self) -> (i32, i32) {
42 match self {
43 Self::Bit3 => (-4, 3), Self::Bit5 => (-16, 15), Self::Bit7 => (-64, 63), Self::Float32 => (i32::MIN, i32::MAX),
47 }
48 }
49
50 pub fn bytes_per_element(&self) -> f32 {
52 match self {
53 Self::Bit3 => 0.5, Self::Bit5 => 1.0, Self::Bit7 => 1.0, Self::Float32 => 4.0,
57 }
58 }
59
60 pub fn default_scale(&self) -> f32 {
62 match self {
63 Self::Bit3 => 0.25, Self::Bit5 => 0.0625, Self::Bit7 => 0.015625, Self::Float32 => 1.0,
67 }
68 }
69
70 pub fn allows_memory_writes(&self) -> bool {
72 matches!(self, Self::Bit7 | Self::Float32)
73 }
74
75 pub fn is_event_driven(&self) -> bool {
77 matches!(self, Self::Bit5 | Self::Bit7)
78 }
79}
80
81impl Default for PrecisionLane {
82 fn default() -> Self {
83 Self::Bit7 }
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize)]
89pub struct LaneConfig {
90 pub default_lane: PrecisionLane,
92
93 pub bit3_tick_budget_us: u64,
95
96 pub bit5_max_updates: usize,
98
99 pub min_stability_steps: usize,
101
102 pub novelty_threshold: f32,
104
105 pub drift_persistence_threshold: usize,
107
108 pub confidence_threshold: f32,
110
111 pub escalation_budget: f32,
113
114 pub auto_lane_selection: bool,
116}
117
118impl Default for LaneConfig {
119 fn default() -> Self {
120 Self {
121 default_lane: PrecisionLane::Bit5, bit3_tick_budget_us: 100, bit5_max_updates: 10, min_stability_steps: 5, novelty_threshold: 0.3, drift_persistence_threshold: 3, confidence_threshold: 0.7, escalation_budget: 1.0, auto_lane_selection: true,
130 }
131 }
132}
133
134#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
136pub enum HardwareTarget {
137 Esp32,
139 V0Appliance,
141 Desktop,
143 Fpga,
145}
146
147impl HardwareTarget {
148 pub fn supported_lanes(&self) -> Vec<PrecisionLane> {
150 match self {
151 Self::Esp32 => vec![PrecisionLane::Bit3],
152 Self::V0Appliance => vec![PrecisionLane::Bit3, PrecisionLane::Bit5, PrecisionLane::Bit7],
153 Self::Desktop => vec![PrecisionLane::Bit3, PrecisionLane::Bit5, PrecisionLane::Bit7, PrecisionLane::Float32],
154 Self::Fpga => vec![PrecisionLane::Bit7],
155 }
156 }
157
158 pub fn default_lane(&self) -> PrecisionLane {
160 match self {
161 Self::Esp32 => PrecisionLane::Bit3,
162 Self::V0Appliance => PrecisionLane::Bit5,
163 Self::Desktop => PrecisionLane::Bit7,
164 Self::Fpga => PrecisionLane::Bit7,
165 }
166 }
167}
168
169#[cfg(test)]
170mod tests {
171 use super::*;
172
173 #[test]
174 fn test_lane_bits() {
175 assert_eq!(PrecisionLane::Bit3.bits(), 3);
176 assert_eq!(PrecisionLane::Bit5.bits(), 5);
177 assert_eq!(PrecisionLane::Bit7.bits(), 7);
178 assert_eq!(PrecisionLane::Float32.bits(), 32);
179 }
180
181 #[test]
182 fn test_lane_ranges() {
183 assert_eq!(PrecisionLane::Bit3.value_range(), (-4, 3));
184 assert_eq!(PrecisionLane::Bit5.value_range(), (-16, 15));
185 assert_eq!(PrecisionLane::Bit7.value_range(), (-64, 63));
186 }
187
188 #[test]
189 fn test_memory_write_permission() {
190 assert!(!PrecisionLane::Bit3.allows_memory_writes());
191 assert!(!PrecisionLane::Bit5.allows_memory_writes());
192 assert!(PrecisionLane::Bit7.allows_memory_writes());
193 assert!(PrecisionLane::Float32.allows_memory_writes());
194 }
195
196 #[test]
197 fn test_hardware_targets() {
198 assert_eq!(HardwareTarget::Esp32.supported_lanes(), vec![PrecisionLane::Bit3]);
199 assert!(HardwareTarget::Desktop.supported_lanes().contains(&PrecisionLane::Float32));
200 }
201}