nxpu_backend_arm_ethos/
support.rs1use nxpu_backend_core::{OperatorSupport, PerformanceTier, Precision};
4
5pub struct EthosU55Support;
7
8pub struct EthosU65Support;
10
11const ETHOS_NATIVE_INT8: &[&str] = &[
12 "Conv",
13 "MatMul",
14 "Add",
15 "MaxPool",
16 "AveragePool",
17 "Relu",
18 "Reshape",
19 "Concat",
20];
21
22const ETHOS_EMULATED_INT8: &[&str] = &[
23 "Mul",
24 "Sub",
25 "Sigmoid",
26 "Tanh",
27 "Softmax",
28 "BatchNormalization",
29 "Transpose",
30];
31
32pub(crate) const U65_NATIVE_INT16: &[&str] = &["Conv", "MatMul", "Add", "Relu"];
34
35impl OperatorSupport for EthosU55Support {
36 fn op_support(&self, op_name: &str, precision: Precision) -> PerformanceTier {
37 match precision {
38 Precision::Int8 => {
39 if ETHOS_NATIVE_INT8.contains(&op_name) {
40 PerformanceTier::Native
41 } else if ETHOS_EMULATED_INT8.contains(&op_name) {
42 PerformanceTier::Emulated
43 } else {
44 PerformanceTier::Unsupported
45 }
46 }
47 _ => {
49 if ETHOS_NATIVE_INT8.contains(&op_name) || ETHOS_EMULATED_INT8.contains(&op_name) {
50 PerformanceTier::Emulated
51 } else {
52 PerformanceTier::Unsupported
53 }
54 }
55 }
56 }
57
58 fn hardware_name(&self) -> &str {
59 "Arm Ethos-U55"
60 }
61
62 fn native_ops(&self) -> &[&str] {
63 ETHOS_NATIVE_INT8
64 }
65
66 fn emulated_ops(&self) -> &[&str] {
67 ETHOS_EMULATED_INT8
68 }
69}
70
71impl OperatorSupport for EthosU65Support {
72 fn op_support(&self, op_name: &str, precision: Precision) -> PerformanceTier {
73 match precision {
74 Precision::Int8 => {
75 if ETHOS_NATIVE_INT8.contains(&op_name) {
76 PerformanceTier::Native
77 } else if ETHOS_EMULATED_INT8.contains(&op_name) {
78 PerformanceTier::Emulated
79 } else {
80 PerformanceTier::Unsupported
81 }
82 }
83 Precision::F16 => {
85 if U65_NATIVE_INT16.contains(&op_name) {
86 PerformanceTier::Native
87 } else if ETHOS_NATIVE_INT8.contains(&op_name)
88 || ETHOS_EMULATED_INT8.contains(&op_name)
89 {
90 PerformanceTier::Emulated
91 } else {
92 PerformanceTier::Unsupported
93 }
94 }
95 _ => {
96 if ETHOS_NATIVE_INT8.contains(&op_name) || ETHOS_EMULATED_INT8.contains(&op_name) {
97 PerformanceTier::Emulated
98 } else {
99 PerformanceTier::Unsupported
100 }
101 }
102 }
103 }
104
105 fn hardware_name(&self) -> &str {
106 "Arm Ethos-U65"
107 }
108
109 fn native_ops(&self) -> &[&str] {
110 ETHOS_NATIVE_INT8
111 }
112
113 fn emulated_ops(&self) -> &[&str] {
114 ETHOS_EMULATED_INT8
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[test]
123 fn u55_native_int8() {
124 let s = EthosU55Support;
125 assert_eq!(
126 s.op_support("Conv", Precision::Int8),
127 PerformanceTier::Native
128 );
129 assert_eq!(
130 s.op_support("MatMul", Precision::Int8),
131 PerformanceTier::Native
132 );
133 assert_eq!(
134 s.op_support("Relu", Precision::Int8),
135 PerformanceTier::Native
136 );
137 }
138
139 #[test]
140 fn u55_emulated_int8() {
141 let s = EthosU55Support;
142 assert_eq!(
143 s.op_support("Sigmoid", Precision::Int8),
144 PerformanceTier::Emulated
145 );
146 }
147
148 #[test]
149 fn u55_f16_emulated() {
150 let s = EthosU55Support;
151 assert_eq!(
152 s.op_support("Conv", Precision::F16),
153 PerformanceTier::Emulated
154 );
155 }
156
157 #[test]
158 fn u65_f16_native_for_core_ops() {
159 let s = EthosU65Support;
160 assert_eq!(
161 s.op_support("Conv", Precision::F16),
162 PerformanceTier::Native
163 );
164 assert_eq!(
165 s.op_support("MatMul", Precision::F16),
166 PerformanceTier::Native
167 );
168 }
169
170 #[test]
171 fn u65_f16_emulated_for_others() {
172 let s = EthosU65Support;
173 assert_eq!(
174 s.op_support("Sigmoid", Precision::F16),
175 PerformanceTier::Emulated
176 );
177 }
178
179 #[test]
180 fn unknown_op_unsupported() {
181 assert_eq!(
182 EthosU55Support.op_support("FakeOp", Precision::Int8),
183 PerformanceTier::Unsupported
184 );
185 assert_eq!(
186 EthosU65Support.op_support("FakeOp", Precision::Int8),
187 PerformanceTier::Unsupported
188 );
189 }
190
191 #[test]
192 fn hardware_names() {
193 assert_eq!(EthosU55Support.hardware_name(), "Arm Ethos-U55");
194 assert_eq!(EthosU65Support.hardware_name(), "Arm Ethos-U65");
195 }
196
197 #[test]
198 fn u55_bf16_emulated() {
199 let s = EthosU55Support;
200 assert_eq!(
201 s.op_support("Conv", Precision::BF16),
202 PerformanceTier::Emulated
203 );
204 }
205
206 #[test]
207 fn u55_f32_unknown_unsupported() {
208 let s = EthosU55Support;
209 assert_eq!(
210 s.op_support("FakeOp", Precision::F32),
211 PerformanceTier::Unsupported
212 );
213 }
214
215 #[test]
216 fn u65_bf16_emulated() {
217 let s = EthosU65Support;
218 assert_eq!(
219 s.op_support("Conv", Precision::BF16),
220 PerformanceTier::Emulated
221 );
222 }
223
224 #[test]
225 fn u65_f32_emulated() {
226 let s = EthosU65Support;
227 assert_eq!(
228 s.op_support("Conv", Precision::F32),
229 PerformanceTier::Emulated
230 );
231 }
232
233 #[test]
234 fn u65_f16_unsupported() {
235 let s = EthosU65Support;
236 assert_eq!(
237 s.op_support("FakeOp", Precision::F16),
238 PerformanceTier::Unsupported
239 );
240 }
241
242 #[test]
243 fn u65_int8_emulated() {
244 let s = EthosU65Support;
245 assert_eq!(
246 s.op_support("Sigmoid", Precision::Int8),
247 PerformanceTier::Emulated
248 );
249 }
250}