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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
use crate::Result;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[cfg(target_os = "linux")]
use std::process::Command;
/// TPU vendor information
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum TPUVendor {
Google,
Intel,
Groq,
Cerebras,
Unknown(String),
}
impl std::fmt::Display for TPUVendor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
TPUVendor::Google => write!(f, "Google"),
TPUVendor::Intel => write!(f, "Intel"),
TPUVendor::Groq => write!(f, "Groq"),
TPUVendor::Cerebras => write!(f, "Cerebras"),
TPUVendor::Unknown(name) => write!(f, "{name}"),
}
}
}
/// TPU generation and architecture
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum TPUArchitecture {
GoogleTPUv2,
GoogleTPUv3,
GoogleTPUv4,
GoogleTPUv5,
GoogleCoralEdge,
IntelHabanaGaudi,
IntelHabanaGaudi2,
IntelHabanaGoya,
GroqLPU,
CerebrasWSE,
Unknown(String),
}
/// TPU connection type
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum TPUConnectionType {
CloudTPU, // Google Cloud TPU
PCIe, // PCIe card
USB, // USB device (Edge TPU)
M2, // M.2 module
Network, // Network-attached
Unknown,
}
/// TPU information structure
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TPUInfo {
/// TPU vendor
pub vendor: TPUVendor,
/// TPU model name
pub model_name: String,
/// TPU architecture/generation
pub architecture: TPUArchitecture,
/// Connection type
pub connection_type: TPUConnectionType,
/// Performance in TOPS (Tera Operations Per Second)
pub tops_performance: Option<f32>,
/// Memory size in GB
pub memory_gb: Option<f32>,
/// Memory bandwidth in GB/s
pub memory_bandwidth_gbps: Option<f32>,
/// Number of cores/processing units
pub core_count: Option<u32>,
/// Driver version
pub driver_version: Option<String>,
/// Firmware version
pub firmware_version: Option<String>,
/// Device ID
pub device_id: Option<String>,
/// Supported frameworks
pub supported_frameworks: Vec<String>,
/// Power consumption in watts
pub power_consumption: Option<f32>,
/// Operating temperature in Celsius
pub temperature: Option<f32>,
/// Clock frequency in MHz
pub clock_frequency: Option<u32>,
/// Supported data types
pub supported_dtypes: Vec<String>,
/// Additional capabilities
pub capabilities: HashMap<String, String>,
}
impl TPUInfo {
/// Query all available TPUs in the system
pub fn query_all() -> Result<Vec<TPUInfo>> {
let mut tpus = Vec::new();
// Detect various TPU types
tpus.extend(Self::detect_google_tpus()?);
tpus.extend(Self::detect_intel_habana()?);
tpus.extend(Self::detect_edge_tpus()?);
tpus.extend(Self::detect_groq_lpus()?);
tpus.extend(Self::detect_cerebras_wse()?);
Ok(tpus)
}
/// Detect Google TPUs (Cloud and Edge)
fn detect_google_tpus() -> Result<Vec<TPUInfo>> {
let mut tpus = Vec::new();
// Check for Google Cloud TPU via environment
if let Ok(tpu_name) = std::env::var("TPU_NAME") {
// Parse TPU version from name or metadata
let (architecture, tops, memory_gb) = Self::parse_google_tpu_specs(&tpu_name);
tpus.push(TPUInfo {
vendor: TPUVendor::Google,
model_name: format!("Google Cloud TPU ({tpu_name})"),
architecture,
connection_type: TPUConnectionType::CloudTPU,
tops_performance: Some(tops),
memory_gb: Some(memory_gb),
memory_bandwidth_gbps: Some(600.0), // Typical for TPU v4
core_count: Some(2), // Typical core count
driver_version: Self::get_tpu_driver_version(),
firmware_version: None,
device_id: Some(tpu_name),
supported_frameworks: vec![
"TensorFlow".to_string(),
"JAX".to_string(),
"PyTorch/XLA".to_string(),
],
power_consumption: Some(200.0), // Estimated
temperature: None,
clock_frequency: Some(1000), // ~1GHz
supported_dtypes: vec![
"bfloat16".to_string(),
"float32".to_string(),
"int8".to_string(),
"int32".to_string(),
],
capabilities: HashMap::from([
("matrix_units".to_string(), "true".to_string()),
("vector_units".to_string(), "true".to_string()),
("scalar_units".to_string(), "true".to_string()),
]),
});
}
Ok(tpus)
}
fn parse_google_tpu_specs(tpu_name: &str) -> (TPUArchitecture, f32, f32) {
if tpu_name.contains("v5") {
(TPUArchitecture::GoogleTPUv5, 275.0, 16.0)
} else if tpu_name.contains("v4") {
(TPUArchitecture::GoogleTPUv4, 275.0, 32.0)
} else if tpu_name.contains("v3") {
(TPUArchitecture::GoogleTPUv3, 123.0, 16.0)
} else if tpu_name.contains("v2") {
(TPUArchitecture::GoogleTPUv2, 45.0, 8.0)
} else {
(TPUArchitecture::GoogleTPUv4, 275.0, 32.0) // Default to v4
}
}
/// Detect Google Coral Edge TPUs
fn detect_edge_tpus() -> Result<Vec<TPUInfo>> {
let tpus = Vec::new();
#[cfg(target_os = "linux")]
{
// Check for Edge TPU via USB
if let Ok(output) = Command::new("lsusb").output() {
let output_str = String::from_utf8_lossy(&output.stdout);
for line in output_str.lines() {
if line.contains("18d1") && line.contains("9302") { // Google Edge TPU USB
tpus.push(TPUInfo {
vendor: TPUVendor::Google,
model_name: "Google Coral Edge TPU".to_string(),
architecture: TPUArchitecture::GoogleCoralEdge,
connection_type: TPUConnectionType::USB,
tops_performance: Some(4.0), // 4 TOPS at INT8
memory_gb: None, // Uses host memory
memory_bandwidth_gbps: Some(2.0), // USB 3.0 bandwidth
core_count: Some(1),
driver_version: Self::get_edge_tpu_driver_version(),
firmware_version: None,
device_id: Some("18d1:9302".to_string()),
supported_frameworks: vec![
"TensorFlow Lite".to_string(),
"PyCoral".to_string(),
"OpenVINO".to_string(),
],
power_consumption: Some(2.0), // ~2W
temperature: None,
clock_frequency: Some(500), // ~500MHz
supported_dtypes: vec![
"int8".to_string(),
"uint8".to_string(),
],
capabilities: HashMap::from([
("quantized_only".to_string(), "true".to_string()),
("edge_optimized".to_string(), "true".to_string()),
]),
});
}
}
}
// Check for Edge TPU via PCIe (M.2 or Mini PCIe)
if let Ok(output) = Command::new("lspci").output() {
let output_str = String::from_utf8_lossy(&output.stdout);
for line in output_str.lines() {
if line.contains("Coral") || (line.contains("Google") && line.contains("Edge")) {
tpus.push(TPUInfo {
vendor: TPUVendor::Google,
model_name: "Google Coral Edge TPU (PCIe)".to_string(),
architecture: TPUArchitecture::GoogleCoralEdge,
connection_type: TPUConnectionType::M2,
tops_performance: Some(4.0),
memory_gb: None,
memory_bandwidth_gbps: Some(8.0), // PCIe bandwidth
core_count: Some(1),
driver_version: Self::get_edge_tpu_driver_version(),
firmware_version: None,
device_id: None,
supported_frameworks: vec![
"TensorFlow Lite".to_string(),
"PyCoral".to_string(),
],
power_consumption: Some(2.5), // Slightly higher for PCIe
temperature: None,
clock_frequency: Some(500),
supported_dtypes: vec![
"int8".to_string(),
"uint8".to_string(),
],
capabilities: HashMap::from([
("quantized_only".to_string(), "true".to_string()),
("edge_optimized".to_string(), "true".to_string()),
("pcie_interface".to_string(), "true".to_string()),
]),
});
}
}
}
}
Ok(tpus)
}
/// Detect Intel Habana accelerators
fn detect_intel_habana() -> Result<Vec<TPUInfo>> {
let tpus = Vec::new();
#[cfg(target_os = "linux")]
{
// Check for Habana devices via sysfs
if std::path::Path::new("/sys/class/accel").exists() {
if let Ok(entries) = std::fs::read_dir("/sys/class/accel") {
for entry in entries.flatten() {
if let Some(name) = entry.file_name().to_str() {
if name.starts_with("accel") {
// Try to determine if it's Habana
let device_path = format!("/sys/class/accel/{}/device", name);
if let Ok(vendor) = std::fs::read_to_string(format!("{}/vendor", device_path)) {
if vendor.trim() == "0x1da3" { // Intel vendor ID for Habana
if let Ok(device) = std::fs::read_to_string(format!("{}/device", device_path)) {
let (model_name, architecture, tops) = match device.trim() {
"0x1000" => ("Intel Habana Gaudi", TPUArchitecture::IntelHabanaGaudi, 400.0),
"0x1020" => ("Intel Habana Gaudi2", TPUArchitecture::IntelHabanaGaudi2, 800.0),
"0x1050" => ("Intel Habana Goya", TPUArchitecture::IntelHabanaGoya, 100.0),
_ => ("Intel Habana Device", TPUArchitecture::IntelHabanaGaudi, 400.0),
};
tpus.push(TPUInfo {
vendor: TPUVendor::Intel,
model_name: model_name.to_string(),
architecture,
connection_type: TPUConnectionType::PCIe,
tops_performance: Some(tops),
memory_gb: Some(32.0), // Typical for Gaudi
memory_bandwidth_gbps: Some(2400.0), // HBM2E bandwidth
core_count: Some(8), // Typical core count
driver_version: Self::get_habana_driver_version(),
firmware_version: None,
device_id: Some(device.trim().to_string()),
supported_frameworks: vec![
"PyTorch".to_string(),
"TensorFlow".to_string(),
"ONNX Runtime".to_string(),
"Habana SynapseAI".to_string(),
],
power_consumption: Some(350.0), // High performance = high power
temperature: None,
clock_frequency: Some(1300), // ~1.3GHz
supported_dtypes: vec![
"float32".to_string(),
"bfloat16".to_string(),
"float16".to_string(),
"int8".to_string(),
],
capabilities: HashMap::from([
("matrix_multiply_engine".to_string(), "true".to_string()),
("tensor_processor_core".to_string(), "true".to_string()),
("high_bandwidth_memory".to_string(), "true".to_string()),
]),
});
}
}
}
}
}
}
}
}
}
Ok(tpus)
}
// Placeholder implementations for other vendors
fn detect_groq_lpus() -> Result<Vec<TPUInfo>> {
// Note: Groq LPU detection requires Groq SDK and runtime
Ok(Vec::new())
}
fn detect_cerebras_wse() -> Result<Vec<TPUInfo>> {
// Note: Cerebras WSE detection requires Cerebras SDK and runtime
Ok(Vec::new())
}
// Helper functions for driver version detection
fn get_tpu_driver_version() -> Option<String> {
// Try to get TensorFlow version with TPU support
#[cfg(target_os = "linux")]
{
if let Ok(output) = Command::new("python3")
.args(["-c", "import tensorflow; print(tensorflow.__version__)"])
.output()
{
if output.status.success() {
return Some(format!("TensorFlow {}", String::from_utf8_lossy(&output.stdout).trim()));
}
}
}
None
}
/// Get TPU vendor
pub fn vendor(&self) -> &TPUVendor {
&self.vendor
}
/// Get TPU model name
pub fn model_name(&self) -> &str {
&self.model_name
}
/// Get TPU architecture
pub fn architecture(&self) -> &TPUArchitecture {
&self.architecture
}
/// Get performance in TOPS
pub fn tops_performance(&self) -> Option<f32> {
self.tops_performance
}
/// Check if TPU supports a specific framework
pub fn supports_framework(&self, framework: &str) -> bool {
self.supported_frameworks.iter()
.any(|f| f.to_lowercase().contains(&framework.to_lowercase()))
}
/// Check if TPU supports a specific data type
pub fn supports_dtype(&self, dtype: &str) -> bool {
self.supported_dtypes.iter()
.any(|d| d.to_lowercase() == dtype.to_lowercase())
}
}