Skip to main content

acorn/schema/hardware/
mod.rs

1//! Hardware resource, architecture, and vendor types
2use crate::prelude::*;
3use crate::schema::research_activity::aspect::Modality;
4use crate::util::constants::gpu::{
5    NVIDIA_CC_AMPERE_80_PATTERNS, NVIDIA_CC_BLACKWELL_100_PATTERNS, NVIDIA_CC_BLACKWELL_103_PATTERNS, NVIDIA_CC_FERMI_21_GT_SUFFIXES,
6    NVIDIA_CC_FERMI_21_PATTERNS, NVIDIA_CC_FERMI_21_QUADRO_SUFFIXES, NVIDIA_CC_KEPLER_32_PATTERNS, NVIDIA_CC_KEPLER_35_PATTERNS,
7    NVIDIA_CC_MAXWELL_50_PATTERNS, NVIDIA_CC_MAXWELL_52_PATTERNS, NVIDIA_CC_PASCAL_60_PATTERNS, NVIDIA_CC_TESLA_11_GTS_SUFFIXES,
8    NVIDIA_CC_TESLA_11_GT_SUFFIXES, NVIDIA_CC_TESLA_11_PATTERNS, NVIDIA_CC_TESLA_11_QUADRO_SUFFIXES, NVIDIA_CC_TESLA_12_GT_SUFFIXES,
9    NVIDIA_CC_TESLA_12_PATTERNS, NVIDIA_CC_TESLA_12_QUADRO_SUFFIXES, NVIDIA_CC_TESLA_13_PATTERNS, NVIDIA_CC_TESLA_13_QUADRO_SUFFIXES,
10};
11use crate::util::{contains_any, contains_any_with_prefix};
12use derive_more::Display;
13use schemars::JsonSchema;
14use serde::{Deserialize, Serialize};
15use validator::{Validate, ValidationErrors};
16
17/// Memory types and (de)serialization for hardware resources
18pub mod memory;
19/// Quantum computing paradigms and hardware definitions
20pub mod quantum;
21/// Vendor types and vendor-aware trait
22pub mod vendor;
23pub use memory::{Memory, MemoryUnit};
24pub use quantum::{Model, Paradigm, Regime, Topology};
25use vendor::validate_vendor;
26pub use vendor::{Vendor, Vendored};
27
28/// Unified hardware architecture identifier
29///
30/// This enum provides a single type that can represent any hardware architecture
31/// across all resource types (CPU, GPU, FPGA, accelerators, DSPs). Each variant
32/// corresponds to one of the typed architecture enums.
33#[derive(Clone, Debug, Display, PartialEq, Serialize, JsonSchema)]
34pub enum Architecture {
35    /// 64-bit ARM instruction set
36    ///
37    /// See <https://developer.arm.com/documentation/102374/0103/> for more information
38    #[display("AArch64")]
39    AArch64,
40    /// NVIDIA Ada Lovelace architecture (RTX 40xx)
41    /// > Designed to provide revolutionary performance for ray tracing and AI-based neural graphics
42    ///
43    /// See <https://www.nvidia.com/en-us/geforce/ada-lovelace-architecture/> for more information
44    #[display("Ada Lovelace")]
45    AdaLovelace,
46    /// Intel Agilex [`Resource::FPGA`]
47    ///
48    /// See <https://www.intel.com/content/www/us/en/homepage.html> for more information
49    #[display("Agilex")]
50    Agilex,
51    /// Intel Alchemist graphics architecture (Xe-HPG)
52    /// > High-performance graphics architecture designed for discrete GPUs
53    ///
54    /// See [Introduction to the Xe-HPG Architecture](https://www.intel.com/content/www/us/en/developer/articles/technical/introduction-to-the-xe-hpg-architecture.html) for more information
55    #[display("Alchemist")]
56    Alchemist,
57    /// NVIDIA (2020) Ampere architecture (A100, RTX 30xx)
58    /// > Designed for AI, HPC, and graphics workloads
59    ///
60    /// See <https://www.nvidia.com/en-us/data-center/ampere-architecture/> for more information
61    #[display("Ampere")]
62    Ampere,
63    /// Apple GPU architecture (A14/A15 Bionic)
64    #[display("Apple GPU (A14/A15)")]
65    AppleA14,
66    /// Apple GPU architecture (A16/A17 Bionic)
67    #[display("Apple GPU (A16/A17)")]
68    AppleA16,
69    /// Apple GPU architecture (A18/A18 Pro)
70    #[display("Apple GPU (A18)")]
71    AppleA18,
72    /// Apple efficiency core (big/little architecture)
73    #[display("Apple Efficiency Core")]
74    AppleEfficiencyCore,
75    /// Apple GPU architecture (M1 series)
76    #[display("Apple GPU (M1)")]
77    AppleM1,
78    /// Apple GPU architecture (M2 series)
79    #[display("Apple GPU (M2)")]
80    AppleM2,
81    /// Apple GPU architecture (M3 series)
82    #[display("Apple GPU (M3)")]
83    AppleM3,
84    /// Apple GPU architecture (M4 series)
85    #[display("Apple GPU (M4)")]
86    AppleM4,
87    /// Apple GPU architecture (M5 series)
88    #[display("Apple GPU (M5)")]
89    AppleM5,
90    /// Apple performance core (big/little architecture)
91    #[display("Apple Performance Core")]
92    ApplePerformanceCore,
93    /// Xilinx Artix [`Resource::FPGA`] family
94    /// > Cost and transceiver optimized
95    ///
96    /// See <https://www.amd.com/en/products/adaptive-socs-and-fpgas/fpga/artix-7.html> for more information
97    #[display("Artix")]
98    Artix,
99    /// Huawei Ascend 910 AI accelerator
100    ///
101    /// See <https://www.huawei.com/en/> for more information
102    #[display("Ascend 910")]
103    Ascend910,
104    /// Tenstorrent Blackhole AI accelerator
105    /// > PCIe boards that are infinitely scalable and designed for high performance AI processing — features 16 big RISC-V cores and up to 32GB of GDDR6 memory per chip
106    ///
107    /// See <https://tenstorrent.com/hardware/cards> for more information
108    #[display("Blackhole")]
109    Blackhole,
110    /// NVIDIA Blackwell architecture (RTX 50xx, B100)
111    ///
112    /// See <https://www.nvidia.com/en-us/data-center/technologies/blackwell-architecture/> for more information
113    #[display("Blackwell")]
114    Blackwell,
115    /// Texas Instruments C66x [`Resource::DSP`]
116    ///
117    /// See [C66x DSP CPU and Instruction Set](https://www.nvidia.com/en-us/data-center/technologies/blackwell-architecture/) for more information
118    #[display("C66x")]
119    C66x,
120    /// NVIDIA Carmel CPU architecture
121    ///
122    /// Custom ARMv8.2 CPU core used in Jetson Xavier series (AGX Xavier, Xavier NX)
123    ///
124    /// See <https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/> for more information
125    #[display("Carmel")]
126    Carmel,
127    /// AMD CDNA 1 microarchitecture (MI100)
128    /// > Dedicated compute architecture underlying AMD Instinct™ GPUs and APUs
129    ///
130    /// See <https://www.amd.com/en/technologies/cdna.html> for more information
131    #[display("CDNA1")]
132    Cdna1,
133    /// AMD CDNA 2 microarchitecture (MI250)
134    /// > Dedicated compute architecture underlying AMD Instinct™ GPUs and APUs
135    ///
136    /// See <https://www.amd.com/en/technologies/cdna.html> for more information
137    #[display("CDNA2")]
138    Cdna2,
139    /// AMD CDNA 3 microarchitecture (MI300)
140    /// > Dedicated compute architecture underlying AMD Instinct™ GPUs and APUs
141    ///
142    /// See <https://www.amd.com/en/technologies/cdna.html> for more information
143    #[display("CDNA3")]
144    Cdna3,
145    /// AMD CDNA 4 microarchitecture (MI350)
146    /// > Dedicated compute architecture underlying AMD Instinct™ GPUs and APUs
147    ///
148    /// See <https://www.amd.com/en/technologies/cdna.html> for more information
149    #[display("CDNA4")]
150    Cdna4,
151    /// Lattice CrossLink [`Resource::FPGA`]
152    /// > Low power FPGA featuring hardened MIPI[^mipi] D-PHY[^dphy], LVDS[^lvds], SLVS[^slvs], subLVDS[^sublvds], & Open LDI[^openldi] bridging
153    ///
154    /// [^mipi]: Mobile Industry Processor Interface (a standards body/spec family)
155    /// [^dphy]: A specific MIPI-defined physical layer (often just called "MIPI D-PHY") rather than a word-by-word acronym expansion in practice
156    /// [^lvds]: Low-Voltage Differential Signaling
157    /// [^slvs]: Scalable Low-Voltage Signaling
158    /// [^sublvds]: Sub Low-Voltage Differential Signaling (a lower-swing LVDS variant used in imaging)
159    /// [^openldi]: Open LVDS Display Interface (Open LDI / OpenLDI)
160    ///
161    /// See <https://www.latticesemi.com/products/fpgaandcpld/crosslink> for more information
162    #[display("CrossLink")]
163    CrossLink,
164    /// Intel/Altera Cyclone V [`Resource::FPGA`]
165    ///
166    /// See <https://www.intel.com/content/www/us/en/homepage.html> for more information
167    #[display("Cyclone V")]
168    CycloneV,
169    /// Lattice ECP5 [`Resource::FPGA`]
170    /// > Lattice mid-range FPGA family
171    ///
172    /// See <https://www.latticesemi.com/products/fpgaandcpld/ecp5> for more information
173    #[display("ECP5")]
174    Ecp5,
175    /// ARM Ethos [`Resource::NPU`]
176    ///
177    /// See <https://www.arm.com/products/silicon-ip-cpu/ethos/ethos-u85> for more information
178    #[display("Ethos")]
179    Ethos,
180    /// NVIDIA Fermi microarchitecture (Tesla 20xx, GeForce 4xx/5xx, 2010)
181    ///
182    /// Compute capability 2.x
183    ///
184    /// See <https://developer.nvidia.com/cuda-gpus> for more information
185    #[display("Fermi")]
186    Fermi,
187    /// Intel Habana Gaudi2 AI accelerator
188    ///
189    /// See <[The Habana Gaudi2 Processor for Deep Learning](https://www.intel.com/content/www/us/en/developer/articles/technical/habana-gaudi2-processor-for-deep-learning.html) for more information
190    #[display("Gaudi2")]
191    Gaudi2,
192    /// Graphcore Colossus GC200 / IPU architecture (2018-2019)
193    #[display("Graphcore GC200")]
194    GraphcoreGc200,
195    /// NVIDIA Grace CPU architecture
196    ///
197    /// See <https://www.nvidia.com/en-us/data-center/grace-cpu/> for more information
198    #[display("Grace")]
199    Grace,
200    /// Qualcomm Hexagon processor NPU
201    /// > Purpose-built for AI, powers advanced gen AI models and cutting-edge gen AI experiences while maintaining best-in-class power efficiency
202    ///
203    /// See https://www.qualcomm.com/processors/hexagon> for more information
204    #[display("Hexagon")]
205    Hexagon,
206    /// NVIDIA Hopper architecture (H100, H200)
207    ///
208    /// See <https://www.nvidia.com/en-us/data-center/technologies/hopper-architecture/> for more information
209    #[display("Hopper")]
210    Hopper,
211    /// Intel Itanium architecture (IA-64)
212    ///
213    /// See [WIkipedia](https://en.wikipedia.org/wiki/Itanium) for more information
214    #[display("IA-64")]
215    Ia64,
216    /// Lattice iCE40 LP/HX/UltraPlus [`Resource::FPGA`]
217    /// > Low-Power, High-Performance FPGA with Small [^BGA] package for the thinnest devices
218    ///
219    /// [^BGA]: Ball Grid Array (BGA) is a type of surface-mount packaging used for integrated circuits, where the connections are made through an array of solder balls on the underside of the package rather than traditional pins. This allows for a smaller footprint and better thermal performance, making it ideal for compact devices.
220    ///
221    /// See <https://www.latticesemi.com/products/fpgaandcpld/ice40> for more information
222    #[display("iCE40")]
223    Ice40,
224    /// Amazon Inferentia AI inference chip
225    ///
226    /// See <https://aws.amazon.com/ai/machine-learning/inferentia/> for more information
227    #[display("Inferentia")]
228    Inferentia,
229    /// NVIDIA (2012) Kepler [`Resource::GPU`] architecture (GK-series)
230    ///
231    /// See [Tuning CUDA Applications for Kepler](https://docs.nvidia.com/cuda/archive/9.2/kepler-tuning-guide/index.html#nvidia-kepler-compute-architecture) for more information
232    #[display("Kepler")]
233    Kepler,
234    /// Xilinx Kintex FPGA family
235    #[display("Kintex")]
236    Kintex,
237    /// LoongArch (Chinese CPU ISA)
238    ///
239    /// See [Wikipedia](https://en.wikipedia.org/wiki/Loongson#LoongArch) for more information
240    #[display("LoongArch")]
241    LoongArch,
242    /// Groq Language Processing Unit
243    ///
244    /// See <https://groq.com/lpu-architecture> for more information
245    #[display("LPU")]
246    Lpu,
247    /// Microsoft Maia AI accelerator
248    ///
249    /// See <https://news.microsoft.com/maia-200/> for more information
250    #[display("Maia")]
251    Maia,
252    /// NVIDIA (2014) Maxwell [`Resource::GPU`] architecture (GM-series)
253    ///
254    /// See <https://developer.nvidia.com/maxwell-compute-architecture> for more information
255    #[display("Maxwell")]
256    Maxwell,
257    /// [^MIPS] instruction set architecture
258    ///
259    /// [^MIPS]: Microprocessor without Interlocked Pipeline Stages (MIPS) is a RISC (Reduced Instruction Set Computer) architecture developed in the 1980s.
260    ///
261    /// See [Wikipedia](https://en.wikipedia.org/wiki/MIPS_architecture) for more information
262    #[display("MIPS")]
263    Mips,
264    /// Intel Nervana neural processor (NNP-I / NNP-T)
265    ///
266    /// See <https://www.intel.com/content/www/us/en/homepage.html> for more information
267    #[display("Nervana")]
268    Nervana,
269    /// Apple Neural Engine
270    ///
271    /// See [Apple Machine Learning Research - The Apple Neural Engine](https://machinelearning.apple.com/research/neural-engine-transformers#the-apple-neuralengine) for more information
272    #[display("Neural Engine")]
273    NeuralEngine,
274    /// NVIDIA Orin system-on-chip (Jetson AGX Orin, Orin NX, Orin Nano)
275    ///
276    /// Ampere-based GPU integrated in the Jetson Orin family. Compute capability 8.7
277    ///
278    /// See <https://developer.nvidia.com/cuda-gpus> for more information
279    #[display("Orin")]
280    Orin,
281    /// NVIDIA (2016) Pascal [`Resource::GPU`] microarchitecture (GP-series)
282    ///
283    /// See <https://www.nvidia.com/en-us/data-center/pascal-gpu-architecture/> for more information
284    #[display("Pascal")]
285    Pascal,
286    /// IBM PowerPC architecture
287    /// > RISC [^ISA] created in 1991
288    ///
289    /// [^ISA]: Instruction Set Architecture (ISA)
290    ///
291    /// See [Wikipedia](https://en.wikipedia.org/wiki/PowerPC) for more information
292    #[display("PowerPC")]
293    PowerPc,
294    /// AMD RDNA 1 architecture (RX 5xxx)
295    ///
296    /// See <https://www.amd.com/en/technologies/rdna.html> for more information
297    #[display("RDNA1")]
298    Rdna1,
299    /// AMD RDNA 2 architecture (RX 6xxx)
300    ///
301    /// See <https://www.amd.com/en/technologies/rdna.html> for more information
302    #[display("RDNA2")]
303    Rdna2,
304    /// AMD RDNA 3 architecture (RX 7xxx)
305    ///
306    /// See <https://www.amd.com/en/technologies/rdna.html> for more information
307    #[display("RDNA3")]
308    Rdna3,
309    /// [^RISC]-V open [^ISA]
310    ///
311    /// [^RISC]: Reduced Instruction Set Computer (RISC)
312    /// [^ISA]: Instruction Set Architecture (ISA)
313    ///
314    /// See <https://riscv.org/> for more information
315    #[display("RISC-V")]
316    RiscV,
317    /// SambaNova Reconfigurable Dataflow Unit (RDU) architecture
318    /// > Fifth-generation chip purpose-built for agentic inference
319    ///
320    /// See <https://sambanova.ai/products/rdu-ai-chips> for more information
321    #[display("SambaNova RDU")]
322    SambaNovaRdu,
323    /// Xilinx Spartan [`Resource::FPGA`] family
324    /// > I/O Optimization with High Performance-per-Watt
325    ///
326    /// See <https://www.amd.com/en/products/adaptive-socs-and-fpgas/fpga/spartan-7.html> for more information
327    #[display("Spartan")]
328    Spartan,
329    /// Intel Stratix 10 [`Resource::FPGA`] family
330    ///
331    /// See <https://www.intel.com/content/www/us/en/homepage.html> for more information
332    #[display("Stratix 10")]
333    Stratix10,
334    /// Intel/Altera Stratix V [`Resource::FPGA`]
335    ///
336    /// See <https://www.intel.com/content/www/us/en/homepage.html> for more information
337    #[display("Stratix V")]
338    StratixV,
339    /// NVIDIA Tesla microarchitecture (G80, GT200, pre-Fermi, 2006-2009)
340    ///
341    /// Compute capability 1.x. Covers G80, G92, G94, G96, G200, GT21x families
342    ///
343    /// See <https://developer.nvidia.com/cuda-gpus> for more information
344    #[display("Tesla")]
345    Tesla,
346    /// Jetson Thor system-on-chip (Jetson T5000, T4000)
347    ///
348    /// Next-generation Jetson embedded GPU. Compute capability 11.0
349    ///
350    /// See <https://developer.nvidia.com/cuda-gpus> for more information
351    #[display("Thor")]
352    Thor,
353    /// Google [`Resource::TPU`] v4
354    ///
355    /// See <https://docs.cloud.google.com/tpu/docs/v4> for more information
356    #[display("TPU v4")]
357    TpuV4,
358    /// Google [`Resource::TPU`] v5e
359    ///
360    /// See <https://docs.cloud.google.com/tpu/docs/v5e> for more information
361    #[display("TPU v5e")]
362    TpuV5e,
363    /// Google [`Resource::TPU`] v5p
364    ///
365    /// See <https://docs.cloud.google.com/tpu/docs/v5p> for more information
366    #[display("TPU v5p")]
367    TpuV5p,
368    /// Google [`Resource::TPU`] v6e ("Trillium")
369    ///
370    /// See <https://cloud.google.com/tpu/docs/v6e> for more information
371    #[display("TPU v6e")]
372    TpuV6e,
373    /// Amazon Trainium AI accelerator
374    /// > Purpose-built for high-performance, cost-efficient AI at scale
375    ///
376    /// See <https://aws.amazon.com/ai/machine-learning/trainium/> for more information
377    #[display("Trainium")]
378    Trainium,
379    /// NVIDIA (2018) Turing architecture (RTX 20xx)
380    ///
381    /// See <https://www.nvidia.com/en-us/geforce/turing/> for more information
382    #[display("Turing")]
383    Turing,
384    /// AMD/Xilinx Versal adaptive compute acceleration platform
385    /// > Heterogeneous acceleration from cloud to edge
386    ///
387    /// See <https://www.amd.com/en/products/adaptive-socs-and-fpgas/versal.html> for more information
388    #[display("Versal")]
389    Versal,
390    /// AMD/Xilinx Virtex UltraScale+ [`Resource::FPGA`]
391    ///
392    /// See <https://www.amd.com/en/products/adaptive-socs-and-fpgas/fpga/virtex-ultrascale-plus.html> for more information
393    #[display("Virtex UltraScale+")]
394    VirtexUltraScalePlus,
395    /// NVIDIA Volta architecture (V100)
396    ///
397    /// See <https://www.nvidia.com/en-us/data-center/volta-gpu-architecture/> for more information
398    #[display("Volta")]
399    Volta,
400    /// NVIDIA Vera CPU architecture
401    ///
402    /// See <https://www.nvidia.com/en-us/data-center/cpu/> for more information
403    #[display("Vera")]
404    Vera,
405    /// Tenstorrent Wormhole AI accelerator
406    /// > Flexible, scalable processors built with Tensix Cores™. Each includes a compute unit, network-on-chip, local cache and "baby RISC-V" cores, coalescing in powerful data movement through the chip.
407    ///
408    /// See <https://tenstorrent.com/hardware/cards#Wormhole> for more information
409    #[display("Wormhole")]
410    Wormhole,
411    /// Cerebras Wafer-Scale Engine 2 (WSE-2)
412    ///
413    /// See <https://www.cerebras.ai/chip> for more information
414    #[display("WSE-2")]
415    Wse2,
416    /// Cerebras Wafer-Scale Engine 3 (WSE-3)
417    ///
418    /// See <https://www.cerebras.ai/chip> for more information
419    #[display("WSE-3")]
420    Wse3,
421    /// 32-bit x86 instruction set
422    ///
423    /// See [Wikipedia](https://en.wikipedia.org/wiki/X86) for more information
424    #[display("x86")]
425    X86,
426    /// x86-64 instruction set (Intel/AMD)
427    ///
428    /// See [Wikipedia](https://en.wikipedia.org/wiki/X86-64) for more information
429    #[display("x86_64")]
430    X86_64,
431    /// Intel Xe graphics architecture
432    #[display("Xe")]
433    Xe,
434    /// Intel Xe2 graphics architecture (Battlemage)
435    ///
436    /// See <https://www.intel.com/content/www/us/en/homepage.html> for more information
437    #[display("Xe2")]
438    Xe2,
439    /// Intel Xe3 graphics architecture (Celestial)
440    ///
441    /// See <https://www.intel.com/content/www/us/en/homepage.html> for more information
442    #[display("Xe3")]
443    Xe3,
444    /// Cadence Tensilica Xtensa [`Resource::DSP`]
445    ///
446    /// See <https://www.cadence.com/en_US/home/tools/ip/tensilica-ip.html> for more information
447    #[display("Xtensa")]
448    Xtensa,
449    /// IBM z/Architecture mainframe
450    ///
451    /// See <https://www.ibm.com/us-en> for more information
452    #[display("z/Architecture")]
453    ZArch,
454    /// AMD/Xilinx Zynq SoC [`Resource::FPGA`]
455    ///
456    /// See <https://www.amd.com/en/products/adaptive-socs-and-fpgas/soc.html> for more information
457    #[display("Zynq")]
458    Zynq,
459    /// Other or unspecified architecture
460    #[display("{}", _0)]
461    Other(String),
462}
463/// AI accelerator architectures
464#[derive(Clone, Debug, Display, Deserialize, PartialEq, Serialize, JsonSchema)]
465pub enum AcceleratorArchitecture {
466    /// Huawei Ascend 910 AI accelerator
467    #[display("Ascend 910")]
468    #[serde(alias = "ascend 910", alias = "Ascend910", alias = "ascend910")]
469    Ascend910,
470    /// Tenstorrent Blackhole AI accelerator
471    #[display("Blackhole")]
472    #[serde(alias = "blackhole")]
473    Blackhole,
474    /// Intel Habana Gaudi2 AI accelerator
475    #[display("Gaudi2")]
476    #[serde(alias = "Gaudi 2", alias = "gaudi2", alias = "gaudi 2")]
477    Gaudi2,
478    /// Graphcore Colossus GC200 / IPU architecture (2018-2019)
479    #[display("Graphcore GC200")]
480    #[serde(alias = "graphcore gc200", alias = "GC200", alias = "gc200")]
481    GraphcoreGc200,
482    /// Amazon Inferentia AI inference chip
483    #[display("Inferentia")]
484    #[serde(alias = "inferentia")]
485    Inferentia,
486    /// Groq Language Processing Unit
487    #[display("LPU")]
488    #[serde(alias = "lpu", alias = "Language Processing Unit", alias = "language processing unit")]
489    Lpu,
490    /// Microsoft Maia AI accelerator
491    #[display("Maia")]
492    #[serde(alias = "maia")]
493    Maia,
494    /// Intel Nervana neural processor (NNP-I / NNP-T, 2010s)
495    #[display("Nervana")]
496    #[serde(alias = "nervana")]
497    Nervana,
498    /// SambaNova Reconfigurable Dataflow Unit (RDU) architecture (2020s)
499    #[display("SambaNova RDU")]
500    #[serde(alias = "sambanova rdu", alias = "RDU", alias = "rdu")]
501    SambaNovaRdu,
502    /// Google TPU v4
503    #[display("TPU v4")]
504    #[serde(alias = "TPU v4", alias = "TPUv4", alias = "tpu v4", alias = "tpuv4")]
505    TpuV4,
506    /// Google TPU v5e
507    #[display("TPU v5e")]
508    #[serde(alias = "TPU v5e", alias = "TPUv5e", alias = "tpu v5e", alias = "tpuv5e")]
509    TpuV5e,
510    /// Google TPU v5p
511    #[display("TPU v5p")]
512    #[serde(alias = "TPU v5p", alias = "TPUv5p", alias = "tpu v5p", alias = "tpuv5p")]
513    TpuV5p,
514    /// Google TPU v6e ("Trillium")
515    #[display("TPU v6e")]
516    #[serde(
517        alias = "TPU v6e",
518        alias = "TPUv6e",
519        alias = "tpu v6e",
520        alias = "tpuv6e",
521        alias = "Trillium",
522        alias = "trillium"
523    )]
524    TpuV6e,
525    /// Amazon Trainium AI accelerator
526    #[display("Trainium")]
527    #[serde(alias = "trainium")]
528    Trainium,
529    /// Tenstorrent Wormhole AI accelerator
530    #[display("Wormhole")]
531    #[serde(alias = "wormhole")]
532    Wormhole,
533    /// Cerebras Wafer-Scale Engine 2 (WSE-2)
534    #[display("WSE-2")]
535    #[serde(alias = "wse2", alias = "WSE2", alias = "wse-2")]
536    Wse2,
537    /// Cerebras Wafer-Scale Engine 3 (WSE-3)
538    #[display("WSE-3")]
539    #[serde(alias = "wse3", alias = "WSE3", alias = "wse-3")]
540    Wse3,
541    /// Other or unspecified accelerator architecture
542    #[display("{}", _0)]
543    Other(String),
544}
545/// GPU compute backend or API
546#[derive(Clone, Debug, Display, Deserialize, Serialize, JsonSchema)]
547pub enum Backend {
548    /// NVIDIA CUDA parallel computing platform
549    #[display("CUDA")]
550    Cuda,
551    /// Microsoft DirectML
552    #[display("DirectML")]
553    DirectMl,
554    /// AMD HIP (CUDA-compatible layer)
555    #[display("HIP")]
556    Hip,
557    /// Apple Metal graphics and compute API
558    #[display("Metal")]
559    Metal,
560    /// Intel oneAPI
561    #[display("oneAPI")]
562    OneApi,
563    /// Khronos OpenCL open standard
564    #[display("OpenCL")]
565    OpenCl,
566    /// AMD ROCm open compute platform
567    #[display("ROCm")]
568    RoCm,
569    /// Intel oneAPI SYCL
570    #[display("SYCL")]
571    Sycl,
572    /// Khronos Vulkan graphics and compute API
573    #[display("Vulkan")]
574    Vulkan,
575    /// W3C WebGPU API
576    #[display("WebGPU")]
577    WebGpu,
578    /// Other or unspecified backend
579    #[display("{}", _0)]
580    Other(String),
581}
582/// Sensor modalities for hardware resources
583#[derive(Clone, Debug, Display, Deserialize, PartialEq, Serialize, JsonSchema)]
584pub enum SensorModality {
585    /// Acoustic sensing such as microphones and hydrophones
586    #[display("audio")]
587    #[serde(alias = "audio", alias = "acoustic", alias = "microphone", alias = "hydrophone")]
588    Audio,
589    /// Chemical sensing such as gas composition or pH
590    #[display("chemical")]
591    #[serde(alias = "chemical", alias = "chem", alias = "gas", alias = "ph")]
592    Chemical,
593    /// Depth sensing such as time-of-flight and structured light
594    #[display("depth")]
595    #[serde(alias = "depth", alias = "tof", alias = "time-of-flight", alias = "structured-light")]
596    Depth,
597    /// Event-based vision sensors
598    #[display("event")]
599    #[serde(alias = "event", alias = "event-camera", alias = "event camera", alias = "dvs")]
600    Event,
601    /// Hyperspectral sensing across many narrow wavelength bands
602    #[display("hyperspectral")]
603    #[serde(alias = "hyperspectral", alias = "hyper-spectral", alias = "hsi")]
604    Hyperspectral,
605    /// Imaging modalities such as RGB cameras and thermal imagers
606    #[display("image")]
607    #[serde(alias = "image", alias = "camera", alias = "vision", alias = "thermal")]
608    Image,
609    /// Inertial measurement sensing (accelerometer/gyroscope)
610    #[display("inertial")]
611    #[serde(alias = "inertial", alias = "imu", alias = "accel", alias = "gyroscope")]
612    Inertial,
613    /// Light detection and ranging
614    #[display("lidar")]
615    #[serde(alias = "lidar", alias = "li-dar")]
616    Lidar,
617    /// Magnetic field sensing
618    #[display("magnetic")]
619    #[serde(alias = "magnetic", alias = "magnetometer")]
620    Magnetic,
621    /// Position and navigation sensing (e.g., GNSS)
622    #[display("navigation")]
623    #[serde(alias = "navigation", alias = "gnss", alias = "gps")]
624    Navigation,
625    /// Network traffic telemetry and packet-level sensing
626    #[display("network-traffic")]
627    #[serde(alias = "network-traffic", alias = "network traffic", alias = "netflow", alias = "packet")]
628    NetworkTraffic,
629    /// Pressure sensing
630    #[display("pressure")]
631    #[serde(alias = "pressure", alias = "barometer")]
632    Pressure,
633    /// Radio detection and ranging
634    #[display("radar")]
635    #[serde(alias = "radar", alias = "sar")]
636    Radar,
637    /// General RF sensing and spectrum observation
638    #[display("rf")]
639    #[serde(alias = "rf", alias = "radio", alias = "spectrum")]
640    Radio,
641    /// Seismic sensing for ground motion and vibration
642    #[display("seismic")]
643    #[serde(alias = "seismic", alias = "geophone")]
644    Seismic,
645    /// Server-side event stream sensing from server push channels
646    #[display("server-side-event")]
647    #[serde(
648        alias = "server-side-event",
649        alias = "server side event",
650        alias = "server-sent-event",
651        alias = "server sent event",
652        alias = "sse"
653    )]
654    ServerSideEvent,
655    /// Sonar sensing using reflected acoustic waves
656    #[display("sonar")]
657    #[serde(alias = "sonar", alias = "acoustic-ranging")]
658    Sonar,
659    /// Temperature sensing
660    #[display("temperature")]
661    #[serde(alias = "temperature", alias = "temp", alias = "thermometer")]
662    Temperature,
663    /// Ultrasonic sensing using high-frequency acoustic waves
664    #[display("ultrasonic")]
665    #[serde(alias = "ultrasonic", alias = "ultrasound")]
666    Ultrasonic,
667    /// Webhook event stream sensing from HTTP callbacks
668    #[display("webhook")]
669    #[serde(alias = "webhook", alias = "web hook", alias = "http-callback", alias = "http callback")]
670    Webhook,
671    /// Other or unspecified sensor modality
672    #[display("{}", _0)]
673    Other(String),
674}
675/// CPU instruction set architectures
676#[derive(Clone, Debug, Display, Deserialize, PartialEq, Serialize, JsonSchema)]
677pub enum CpuArchitecture {
678    /// 64-bit ARM instruction set
679    #[display("AArch64")]
680    #[serde(alias = "arm", alias = "aarch64", alias = "arm64")]
681    AArch64,
682    /// NVIDIA Carmel CPU architecture
683    ///
684    /// Custom ARMv8.2 CPU core used in Jetson Xavier series (AGX Xavier, Xavier NX)
685    ///
686    /// See <https://www.nvidia.com/en-us/autonomous-machines/embedded-systems/> for more information
687    #[display("Carmel")]
688    #[serde(alias = "carmel", alias = "carmel cpu")]
689    Carmel,
690    /// Apple-specific efficiency core (big/little architecture)
691    #[display("Apple Efficiency Core")]
692    #[serde(alias = "Apple Efficiency Core", alias = "apple efficiency core", alias = "EfficiencyCore")]
693    EfficiencyCore,
694    /// ARM Ethos NPU (integrated in some ARM CPUs)
695    #[display("Ethos")]
696    #[serde(alias = "ethos")]
697    Ethos,
698    /// NVIDIA Grace architecture
699    ///
700    /// Used in [DGX Spark](https://www.nvidia.com/en-us/products/workstations/dgx-spark/) machine
701    ///
702    /// See <https://www.nvidia.com/en-us/data-center/grace-cpu-superchip/> for more information
703    #[display("Grace")]
704    #[serde(alias = "grace", alias = "grace cpu")]
705    Grace,
706    /// Qualcomm Hexagon processor (integrated in Snapdragon)
707    #[display("Hexagon")]
708    #[serde(alias = "hexagon")]
709    Hexagon,
710    /// Intel Itanium architecture (IA-64)
711    #[display("IA-64")]
712    #[serde(alias = "ia64", alias = "IA64")]
713    Ia64,
714    /// LoongArch (Chinese CPU ISA)
715    #[display("LoongArch")]
716    #[serde(alias = "loongarch")]
717    LoongArch,
718    /// MIPS instruction set architecture
719    #[display("MIPS")]
720    #[serde(alias = "mips")]
721    Mips,
722    /// Apple Neural Engine (integrated in Apple silicon)
723    #[display("Neural Engine")]
724    #[serde(alias = "Neural Engine")]
725    NeuralEngine,
726    /// Apple-specific performance core (big/little architecture)
727    #[display("Apple Performance Core")]
728    #[serde(alias = "Apple Performance Core", alias = "apple performance core", alias = "PerformanceCore")]
729    PerformanceCore,
730    /// IBM PowerPC architecture
731    #[display("PowerPC")]
732    #[serde(alias = "powerpc")]
733    PowerPc,
734    /// RISC-V open instruction set architecture
735    #[display("RISC-V")]
736    #[serde(alias = "riscv", alias = "risc-v")]
737    RiscV,
738    /// NVIDIA Vera architecture
739    ///
740    /// See <https://www.nvidia.com/en-us/data-center/grace-cpu-superchip/> for more information
741    #[display("Vera")]
742    #[serde(alias = "vera", alias = "vera cpu")]
743    Vera,
744    /// 32-bit x86 instruction set
745    #[display("x86")]
746    #[serde(alias = "X86")]
747    X86,
748    /// x86-64 instruction set (Intel/AMD)
749    #[display("x86_64")]
750    #[serde(alias = "x86_64", alias = "x86-64", alias = "amd64")]
751    X86_64,
752    /// IBM z/Architecture mainframe
753    #[display("z/Architecture")]
754    #[serde(alias = "z architecture", alias = "zarchitecture")]
755    ZArch,
756    /// Other or unspecified CPU architecture
757    #[display("{}", _0)]
758    Other(String),
759}
760/// DSP architectures
761#[derive(Clone, Debug, Display, Deserialize, PartialEq, Serialize, JsonSchema)]
762pub enum DspArchitecture {
763    /// Texas Instruments C66x DSP
764    #[display("C66x")]
765    #[serde(alias = "c66x")]
766    C66x,
767    /// Cadence Tensilica Xtensa DSP
768    #[display("Xtensa")]
769    #[serde(alias = "xtensa")]
770    Xtensa,
771    /// Other or unspecified DSP architecture
772    #[display("{}", _0)]
773    Other(String),
774}
775/// FPGA architecture families used by [`Resource::FPGA`] resources
776#[derive(Clone, Debug, Display, Deserialize, PartialEq, Serialize, JsonSchema)]
777pub enum FpgaArchitecture {
778    /// Intel Agilex FPGA
779    #[display("Agilex")]
780    #[serde(alias = "agilex")]
781    Agilex,
782    /// Xilinx Artix FPGA family (2010s)
783    #[display("Artix")]
784    #[serde(alias = "artix")]
785    Artix,
786    /// Lattice CrossLink FPGA
787    #[display("CrossLink")]
788    #[serde(alias = "crosslink", alias = "cross-link")]
789    CrossLink,
790    /// Intel/Altera Cyclone V FPGA
791    #[display("Cyclone V")]
792    #[serde(alias = "cyclonev", alias = "cyclone v")]
793    CycloneV,
794    /// Lattice ECP5 FPGA
795    #[display("ECP5")]
796    #[serde(alias = "ecp5")]
797    Ecp5,
798    /// Lattice iCE40 FPGA
799    #[display("iCE40")]
800    #[serde(alias = "ice40", alias = "iCE40")]
801    Ice40,
802    /// Xilinx Kintex FPGA family (2010s)
803    #[display("Kintex")]
804    #[serde(alias = "kintex")]
805    Kintex,
806    /// Xilinx Spartan FPGA family (modern 2010s+ variants)
807    #[display("Spartan")]
808    #[serde(alias = "spartan")]
809    Spartan,
810    /// Intel Stratix 10 FPGA family (2016-2017)
811    #[display("Stratix 10")]
812    #[serde(alias = "stratix10", alias = "stratix 10")]
813    Stratix10,
814    /// Intel/Altera Stratix V FPGA
815    #[display("Stratix V")]
816    #[serde(alias = "stratixv", alias = "stratix v")]
817    StratixV,
818    /// AMD/Xilinx Versal adaptive compute acceleration platform
819    #[display("Versal")]
820    #[serde(alias = "versal")]
821    Versal,
822    /// AMD/Xilinx Virtex UltraScale+ FPGA
823    #[display("Virtex UltraScale+")]
824    #[serde(alias = "virtex ultrascale+", alias = "virtexultrascaleplus", alias = "virtex ultrascale plus")]
825    VirtexUltraScalePlus,
826    /// AMD/Xilinx Zynq SoC FPGA
827    #[display("Zynq")]
828    #[serde(alias = "zynq")]
829    Zynq,
830    /// Other or unspecified FPGA architecture
831    #[display("{}", _0)]
832    Other(String),
833}
834/// GPU graphics microarchitectures
835///
836/// Vendor-specific GPU architectures are defined in the [`vendor`] module.
837///
838/// This enum provides backward-compatible JSON deserialization for all GPU
839/// architectures. The variants map to their respective vendor enums.
840#[derive(Clone, Debug, Display, Deserialize, PartialEq, Serialize, JsonSchema)]
841pub enum GpuArchitecture {
842    /// NVIDIA Ada Lovelace microarchitecture (RTX 40xx)
843    #[display("Ada Lovelace")]
844    #[serde(
845        alias = "Ada",
846        alias = "ada",
847        alias = "Ada Lovelace",
848        alias = "ada lovelace",
849        alias = "ada-lovelace",
850        alias = "ada_lovelace"
851    )]
852    AdaLovelace,
853    /// Intel Alchemist graphics architecture (Xe-HPG)
854    #[display("Alchemist")]
855    #[serde(alias = "alchemist", alias = "Arc", alias = "arc", alias = "DG2", alias = "dg2")]
856    Alchemist,
857    /// NVIDIA Ampere microarchitecture (A100, RTX 30xx)
858    #[display("Ampere")]
859    #[serde(alias = "ampere", alias = "GA100", alias = "ga100", alias = "GA102", alias = "ga102")]
860    Ampere,
861    /// Apple GPU architecture (A14/A15 Bionic)
862    #[display("Apple GPU (A14/A15)")]
863    #[serde(alias = "Apple GPU (A14/A15)", alias = "apple gpu (a14/a15)", alias = "A14", alias = "a14")]
864    AppleA14,
865    /// Apple GPU architecture (A16/A17 Bionic)
866    #[display("Apple GPU (A16/A17)")]
867    #[serde(alias = "Apple GPU (A16/A17)", alias = "apple gpu (a16/a17)", alias = "A16", alias = "a16")]
868    AppleA16,
869    /// Apple GPU architecture (A18/A18 Pro)
870    #[display("Apple GPU (A18)")]
871    #[serde(alias = "Apple GPU (A18)", alias = "apple gpu (a18)", alias = "A18", alias = "a18")]
872    AppleA18,
873    /// Apple GPU architecture (M1 series)
874    #[display("Apple GPU (M1)")]
875    #[serde(alias = "Apple GPU (M1)", alias = "apple gpu (m1)", alias = "M1", alias = "m1")]
876    AppleM1,
877    /// Apple GPU architecture (M2 series)
878    #[display("Apple GPU (M2)")]
879    #[serde(alias = "Apple GPU (M2)", alias = "apple gpu (m2)", alias = "M2", alias = "m2")]
880    AppleM2,
881    /// Apple GPU architecture (M3 series)
882    #[display("Apple GPU (M3)")]
883    #[serde(alias = "Apple GPU (M3)", alias = "apple gpu (m3)", alias = "M3", alias = "m3")]
884    AppleM3,
885    /// Apple GPU architecture (M4 series)
886    #[display("Apple GPU (M4)")]
887    #[serde(alias = "Apple GPU (M4)", alias = "apple gpu (m4)", alias = "M4", alias = "m4")]
888    AppleM4,
889    /// Apple GPU architecture (M5 series)
890    #[display("Apple GPU (M5)")]
891    #[serde(alias = "Apple GPU (M5)", alias = "apple gpu (m5)", alias = "M5", alias = "m5")]
892    AppleM5,
893    /// NVIDIA Blackwell microarchitecture (RTX 50xx, B100)
894    #[display("Blackwell")]
895    #[serde(alias = "blackwell", alias = "GB100", alias = "gb100", alias = "GB200", alias = "gb200")]
896    Blackwell,
897    /// AMD CDNA 1 microarchitecture (MI100)
898    #[display("CDNA1")]
899    #[serde(
900        alias = "CDNA 1",
901        alias = "cdna1",
902        alias = "cdna 1",
903        alias = "MI100",
904        alias = "mi100",
905        alias = "Arcturus",
906        alias = "arcturus"
907    )]
908    Cdna1,
909    /// AMD CDNA 2 microarchitecture (MI250)
910    #[display("CDNA2")]
911    #[serde(
912        alias = "CDNA 2",
913        alias = "cdna2",
914        alias = "cdna 2",
915        alias = "MI200",
916        alias = "mi200",
917        alias = "MI250",
918        alias = "mi250",
919        alias = "Aldebaran",
920        alias = "aldebaran"
921    )]
922    Cdna2,
923    /// AMD CDNA 3 microarchitecture (MI300)
924    #[display("CDNA3")]
925    #[serde(
926        alias = "CDNA 3",
927        alias = "cdna3",
928        alias = "cdna 3",
929        alias = "MI300",
930        alias = "mi300",
931        alias = "Aqua Vanjaram",
932        alias = "aqua vanjaram"
933    )]
934    Cdna3,
935    /// AMD CDNA 4 microarchitecture (MI350)
936    #[display("CDNA4")]
937    #[serde(alias = "CDNA 4", alias = "cdna4", alias = "cdna 4", alias = "MI350", alias = "mi350")]
938    Cdna4,
939    /// NVIDIA Fermi microarchitecture (Tesla 20xx, GeForce 4xx/5xx, 2010)
940    ///
941    /// Compute capability 2.x
942    #[display("Fermi")]
943    #[serde(alias = "fermi", alias = "GF100", alias = "gf100", alias = "GF110", alias = "gf110")]
944    Fermi,
945    /// NVIDIA Hopper microarchitecture (H100, H200)
946    #[display("Hopper")]
947    #[serde(alias = "hopper", alias = "GH100", alias = "gh100", alias = "GH200", alias = "gh200")]
948    Hopper,
949    /// NVIDIA Kepler GPU microarchitecture (GK-series, 2012)
950    #[display("Kepler")]
951    #[serde(alias = "kepler", alias = "GK110", alias = "gk110")]
952    Kepler,
953    /// NVIDIA Maxwell GPU microarchitecture (GM-series, 2014)
954    #[display("Maxwell")]
955    #[serde(alias = "maxwell", alias = "GM200", alias = "gm200")]
956    Maxwell,
957    /// NVIDIA Orin system-on-chip (Jetson AGX Orin, Orin NX, Orin Nano)
958    ///
959    /// Ampere-based GPU integrated in the Jetson Orin family. Compute capability 8.7
960    #[display("Orin")]
961    #[serde(
962        alias = "orin",
963        alias = "Jetson Orin",
964        alias = "jetson orin",
965        alias = "AGX Orin",
966        alias = "agx orin",
967        alias = "Orin NX",
968        alias = "orin nx",
969        alias = "Orin Nano",
970        alias = "orin nano"
971    )]
972    Orin,
973    /// NVIDIA Pascal GPU microarchitecture (GP-series, 2016)
974    #[display("Pascal")]
975    #[serde(alias = "pascal", alias = "GP100", alias = "gp100")]
976    Pascal,
977    /// AMD RDNA 1 microarchitecture (RX 5xxx)
978    #[display("RDNA1")]
979    #[serde(alias = "RDNA1", alias = "RDNA 1", alias = "rdna1", alias = "RDNA1", alias = "rdna 1")]
980    Rdna1,
981    /// AMD RDNA 2 microarchitecture (RX 6xxx)
982    #[display("RDNA2")]
983    #[serde(alias = "RDNA2", alias = "RDNA 2", alias = "rdna2", alias = "RDNA2", alias = "rdna 2")]
984    Rdna2,
985    /// AMD RDNA 3 microarchitecture (RX 7xxx)
986    #[display("RDNA3")]
987    #[serde(alias = "RDNA3", alias = "RDNA 3", alias = "rdna3", alias = "RDNA3", alias = "rdna 3")]
988    Rdna3,
989    /// NVIDIA Tesla microarchitecture (G80, GT200, pre-Fermi, 2006-2009)
990    ///
991    /// Compute capability 1.x. Covers G80, G92, G94, G96, G200, GT21x families
992    #[display("Tesla")]
993    #[serde(
994        alias = "tesla",
995        alias = "G80",
996        alias = "g80",
997        alias = "G92",
998        alias = "g92",
999        alias = "GT200",
1000        alias = "gt200",
1001        alias = "GT21x",
1002        alias = "gt21x"
1003    )]
1004    Tesla,
1005    /// Jetson Thor system-on-chip (Jetson T5000, T4000)
1006    ///
1007    /// Next-generation Jetson embedded GPU. Compute capability 11.0
1008    #[display("Thor")]
1009    #[serde(
1010        alias = "thor",
1011        alias = "Jetson Thor",
1012        alias = "jetson thor",
1013        alias = "Jetson T5000",
1014        alias = "jetson t5000",
1015        alias = "Jetson T4000",
1016        alias = "jetson t4000"
1017    )]
1018    Thor,
1019    /// NVIDIA Turing microarchitecture (RTX 20xx)
1020    #[display("Turing")]
1021    #[serde(alias = "turing", alias = "TU102", alias = "tu102")]
1022    Turing,
1023    /// NVIDIA Volta microarchitecture (V100)
1024    #[display("Volta")]
1025    #[serde(alias = "volta", alias = "GV100", alias = "gv100")]
1026    Volta,
1027    /// Intel Xe graphics architecture
1028    #[display("Xe")]
1029    #[serde(alias = "xe", alias = "Xe HPG", alias = "xe hpg", alias = "Xe-HPG", alias = "xe-hpg")]
1030    Xe,
1031    /// Intel Xe2 graphics architecture (Battlemage)
1032    #[display("Xe2")]
1033    #[serde(alias = "Battlemage", alias = "battlemage", alias = "xe2")]
1034    Xe2,
1035    /// Intel Xe3 graphics architecture (Celestial)
1036    #[display("Xe3")]
1037    #[serde(alias = "Celestial", alias = "celestial", alias = "xe3")]
1038    Xe3,
1039    /// Other or unspecified GPU architecture
1040    #[display("{}", _0)]
1041    Other(String),
1042}
1043/// Enumeration for hardware resources used by technology
1044#[derive(Clone, Debug, Serialize, JsonSchema)]
1045pub enum Resource {
1046    /// Application-specific integrated circuit (ASIC)
1047    ///
1048    /// A custom-designed chip built to perform one particular function or a narrow set of functions, rather than acting as a general-purpose processor like a CPU or GPU
1049    ASIC {
1050        /// ASIC architecture or design family
1051        #[serde(alias = "arch")]
1052        architecture: Option<CpuArchitecture>,
1053        /// Number of ASICs required (if applicable)
1054        count: Option<u32>,
1055        /// Intended purpose of the ASIC (e.g., "Bitcoin mining", "video encoding")
1056        purpose: Option<String>,
1057        /// Whether this resource is required
1058        required: Option<bool>,
1059        /// Hardware vendor or designer
1060        vendor: Option<Vendor>,
1061    },
1062    /// Central processing unit (CPU) for "classical" computing
1063    CPU {
1064        /// Instruction set architecture
1065        #[serde(alias = "arch")]
1066        architecture: Option<CpuArchitecture>,
1067        /// Number of physical cores required (if applicable)
1068        cores: Option<u32>,
1069        /// Number of CPUs required (if applicable)
1070        count: Option<u32>,
1071        /// Minimum RAM (if applicable)
1072        #[serde(alias = "ram")]
1073        memory: Option<Memory>,
1074        /// Whether this resource is required
1075        required: Option<bool>,
1076        /// Number of threads required (if applicable)
1077        threads: Option<u32>,
1078        /// Hardware vendor (e.g., Intel, AMD, ARM)
1079        vendor: Option<Vendor>,
1080    },
1081    /// Data processing unit (DPU)
1082    ///
1083    /// A programmable processor optimized for data movement, networking, and infrastructure tasks, offloading them from the CPU
1084    DPU {
1085        /// DPU architecture or product family
1086        #[serde(alias = "arch")]
1087        architecture: Option<CpuArchitecture>,
1088        /// Number of DPUs required (if applicable)
1089        count: Option<u32>,
1090        /// On-chip memory (if applicable)
1091        #[serde(alias = "mem")]
1092        memory: Option<Memory>,
1093        /// Whether this resource is required
1094        required: Option<bool>,
1095        /// Hardware vendor (e.g., NVIDIA, Intel, AMD)
1096        vendor: Option<Vendor>,
1097    },
1098    /// Digital signal processor (DSP)
1099    ///
1100    /// A specialized microprocessor optimized to perform fast mathematical operations on digital signals in real time
1101    DSP {
1102        /// DSP architecture
1103        #[serde(alias = "arch")]
1104        architecture: Option<DspArchitecture>,
1105        /// Number of DSPs required (if applicable)
1106        count: Option<u32>,
1107        /// Clock frequency in MHz (if applicable)
1108        #[serde(alias = "freq")]
1109        frequency: Option<u32>,
1110        /// Whether this resource is required
1111        required: Option<bool>,
1112        /// Hardware vendor (e.g., Qualcomm, Texas Instruments)
1113        vendor: Option<Vendor>,
1114    },
1115    /// Field-programmable gate array (FPGA)
1116    ///
1117    /// A reconfigurable integrated circuit that lets you implement custom digital hardware circuits after manufacturing, rather than having a fixed function like a CPU or ASIC
1118    ///
1119    /// See [`FpgaArchitecture`] for supported architecture families.
1120    FPGA {
1121        /// FPGA architecture or product family
1122        #[serde(alias = "arch")]
1123        architecture: Option<FpgaArchitecture>,
1124        /// Number of FPGAs required (if applicable)
1125        count: Option<u32>,
1126        /// Number of logic elements or LUTs available
1127        logic_elements: Option<u32>,
1128        /// Block RAM (if applicable)
1129        #[serde(alias = "mem")]
1130        memory: Option<Memory>,
1131        /// Whether this resource is required
1132        required: Option<bool>,
1133        /// Hardware vendor (e.g., Intel, AMD)
1134        vendor: Option<Vendor>,
1135    },
1136    /// Graphics processing unit (GPU)
1137    GPU {
1138        /// GPU microarchitecture
1139        #[serde(alias = "arch")]
1140        architecture: Option<GpuArchitecture>,
1141        /// Compute backend or API
1142        backend: Option<Backend>,
1143        /// NVIDIA CUDA compute capability (e.g., 8.0 for A100)
1144        compute_capability: Option<f32>,
1145        /// Number of GPUs required (if applicable)
1146        count: Option<u32>,
1147        /// VRAM (if applicable)
1148        #[serde(alias = "vram")]
1149        memory: Option<Memory>,
1150        /// GPU model name (e.g., "H100", "RTX 4090")
1151        name: Option<String>,
1152        /// Whether this resource is required
1153        required: Option<bool>,
1154        /// Hardware vendor (e.g., NVIDIA, AMD, Intel)
1155        vendor: Option<Vendor>,
1156    },
1157    /// Neural processing unit (NPU)
1158    ///
1159    /// A specialized chip designed for the matrix multiplication calculations that most AI models rely on
1160    NPU {
1161        /// NPU architecture
1162        #[serde(alias = "arch")]
1163        architecture: Option<AcceleratorArchitecture>,
1164        /// Number of NPUs required (if applicable)
1165        count: Option<u32>,
1166        /// On-chip SRAM (if applicable)
1167        #[serde(alias = "mem")]
1168        memory: Option<Memory>,
1169        /// Whether this resource is required
1170        required: Option<bool>,
1171        /// Hardware vendor (e.g., Qualcomm, Apple, Intel)
1172        vendor: Option<Vendor>,
1173    },
1174    /// Neuromorphic compute
1175    Neuromorphic {
1176        /// Number of neuromorphic chips required (if applicable)
1177        count: Option<u32>,
1178        /// On-chip memory (if applicable)
1179        #[serde(alias = "mem")]
1180        memory: Option<Memory>,
1181        /// Chip model name (e.g., "Loihi 2", "TrueNorth", "SpiNNaker2")
1182        model: Option<String>,
1183        /// Neuron capacity per chip (if applicable)
1184        neurons: Option<u64>,
1185        /// Whether this resource is required
1186        required: Option<bool>,
1187        /// Synapse capacity per chip (if applicable)
1188        synapses: Option<u64>,
1189        /// Hardware vendor (e.g., Intel, IBM)
1190        vendor: Option<Vendor>,
1191    },
1192    /// Quantum computing (e.g., NISQ, etc.)
1193    Quantum {
1194        /// Number of QPUs required (if applicable)
1195        count: Option<u32>,
1196        /// Chip or system model name (e.g., "Eagle", "Heron", "Sycamore")
1197        model: Option<Model>,
1198        /// Computing paradigm or modality
1199        paradigm: Option<Paradigm>,
1200        /// Number of qubits (physical or logical, as applicable)
1201        qubits: Option<u32>,
1202        /// Whether this resource is required
1203        required: Option<bool>,
1204        /// Qubit connectivity topology (e.g., "heavy-hex", "all-to-all")
1205        topology: Option<Topology>,
1206        /// Hardware vendor (e.g., IBM, Google, IonQ)
1207        vendor: Option<Vendor>,
1208    },
1209    /// Sensor hardware for data acquisition and measurement
1210    Sensor {
1211        /// Number of sensors required (if applicable)
1212        count: Option<u32>,
1213        /// Sensor modalities (e.g., image, lidar, radar, temperature)
1214        modality: Option<Vec<SensorModality>>,
1215        /// Sensor model name (e.g., "FLIR Boson", "Velodyne VLP-16")
1216        model: Option<String>,
1217        /// Quantum sensing regime when the sensor relies on quantum effects
1218        #[serde(alias = "regime", alias = "quantum", alias = "quantumRegime", alias = "quantum regime")]
1219        quantum_regime: Option<Regime>,
1220        /// Whether this resource is required
1221        required: Option<bool>,
1222        /// Sampling rate in Hz (if applicable)
1223        #[serde(alias = "samplingRate", alias = "sampling_rate")]
1224        sampling_rate: Option<f32>,
1225        /// Hardware vendor (e.g., FLIR, Velodyne, Bosch)
1226        vendor: Option<Vendor>,
1227    },
1228    /// Tensor processing unit (TPU)
1229    TPU {
1230        /// TPU generation
1231        #[serde(alias = "arch")]
1232        architecture: Option<AcceleratorArchitecture>,
1233        /// Number of TPU chips required (if applicable)
1234        count: Option<u32>,
1235        /// High-bandwidth memory (if applicable)
1236        #[serde(alias = "mem")]
1237        memory: Option<Memory>,
1238        /// Whether this resource is required
1239        required: Option<bool>,
1240        /// Hardware vendor (e.g., Google)
1241        vendor: Option<Vendor>,
1242    },
1243    /// Unknown, unspecified, or otherwise unclassified resource
1244    Other(String),
1245}
1246impl Architecture {
1247    fn from_str(s: &str) -> Self {
1248        let normalized = s.trim();
1249        let quoted = format!("\"{normalized}\"");
1250        [
1251            serde_json::from_str::<CpuArchitecture>(&quoted).ok().map(Architecture::from),
1252            serde_json::from_str::<GpuArchitecture>(&quoted).ok().map(Architecture::from),
1253            serde_json::from_str::<FpgaArchitecture>(&quoted).ok().map(Architecture::from),
1254            serde_json::from_str::<AcceleratorArchitecture>(&quoted).ok().map(Architecture::from),
1255            serde_json::from_str::<DspArchitecture>(&quoted).ok().map(Architecture::from),
1256        ]
1257        .into_iter()
1258        .flatten()
1259        .next()
1260        .unwrap_or_else(|| Architecture::Other(normalized.to_string()))
1261    }
1262}
1263impl From<String> for Architecture {
1264    fn from(s: String) -> Self {
1265        Architecture::from_str(&s)
1266    }
1267}
1268impl From<&str> for Architecture {
1269    fn from(s: &str) -> Self {
1270        Architecture::from_str(s)
1271    }
1272}
1273impl From<CpuArchitecture> for Architecture {
1274    fn from(value: CpuArchitecture) -> Self {
1275        match value {
1276            | CpuArchitecture::AArch64 => Architecture::AArch64,
1277            | CpuArchitecture::Carmel => Architecture::Carmel,
1278            | CpuArchitecture::Ethos => Architecture::Ethos,
1279            | CpuArchitecture::Grace => Architecture::Grace,
1280            | CpuArchitecture::Ia64 => Architecture::Ia64,
1281            | CpuArchitecture::LoongArch => Architecture::LoongArch,
1282            | CpuArchitecture::Mips => Architecture::Mips,
1283            | CpuArchitecture::NeuralEngine => Architecture::NeuralEngine,
1284            | CpuArchitecture::PerformanceCore => Architecture::ApplePerformanceCore,
1285            | CpuArchitecture::EfficiencyCore => Architecture::AppleEfficiencyCore,
1286            | CpuArchitecture::PowerPc => Architecture::PowerPc,
1287            | CpuArchitecture::Hexagon => Architecture::Hexagon,
1288            | CpuArchitecture::RiscV => Architecture::RiscV,
1289            | CpuArchitecture::Vera => Architecture::Vera,
1290            | CpuArchitecture::X86 => Architecture::X86,
1291            | CpuArchitecture::X86_64 => Architecture::X86_64,
1292            | CpuArchitecture::ZArch => Architecture::ZArch,
1293            | CpuArchitecture::Other(s) => Architecture::Other(s),
1294        }
1295    }
1296}
1297impl From<&CpuArchitecture> for Architecture {
1298    fn from(value: &CpuArchitecture) -> Self {
1299        match value {
1300            | CpuArchitecture::AArch64 => Architecture::AArch64,
1301            | CpuArchitecture::Carmel => Architecture::Carmel,
1302            | CpuArchitecture::Ethos => Architecture::Ethos,
1303            | CpuArchitecture::Grace => Architecture::Grace,
1304            | CpuArchitecture::Ia64 => Architecture::Ia64,
1305            | CpuArchitecture::LoongArch => Architecture::LoongArch,
1306            | CpuArchitecture::Mips => Architecture::Mips,
1307            | CpuArchitecture::NeuralEngine => Architecture::NeuralEngine,
1308            | CpuArchitecture::PerformanceCore => Architecture::ApplePerformanceCore,
1309            | CpuArchitecture::EfficiencyCore => Architecture::AppleEfficiencyCore,
1310            | CpuArchitecture::PowerPc => Architecture::PowerPc,
1311            | CpuArchitecture::Hexagon => Architecture::Hexagon,
1312            | CpuArchitecture::RiscV => Architecture::RiscV,
1313            | CpuArchitecture::Vera => Architecture::Vera,
1314            | CpuArchitecture::X86 => Architecture::X86,
1315            | CpuArchitecture::X86_64 => Architecture::X86_64,
1316            | CpuArchitecture::ZArch => Architecture::ZArch,
1317            | CpuArchitecture::Other(s) => Architecture::Other(s.clone()),
1318        }
1319    }
1320}
1321impl From<DspArchitecture> for Architecture {
1322    fn from(value: DspArchitecture) -> Self {
1323        match value {
1324            | DspArchitecture::C66x => Architecture::C66x,
1325            | DspArchitecture::Xtensa => Architecture::Xtensa,
1326            | DspArchitecture::Other(s) => Architecture::Other(s),
1327        }
1328    }
1329}
1330impl From<&DspArchitecture> for Architecture {
1331    fn from(value: &DspArchitecture) -> Self {
1332        match value {
1333            | DspArchitecture::C66x => Architecture::C66x,
1334            | DspArchitecture::Xtensa => Architecture::Xtensa,
1335            | DspArchitecture::Other(s) => Architecture::Other(s.clone()),
1336        }
1337    }
1338}
1339impl From<AcceleratorArchitecture> for Architecture {
1340    fn from(value: AcceleratorArchitecture) -> Self {
1341        match value {
1342            | AcceleratorArchitecture::Ascend910 => Architecture::Ascend910,
1343            | AcceleratorArchitecture::Blackhole => Architecture::Blackhole,
1344            | AcceleratorArchitecture::Gaudi2 => Architecture::Gaudi2,
1345            | AcceleratorArchitecture::GraphcoreGc200 => Architecture::GraphcoreGc200,
1346            | AcceleratorArchitecture::Inferentia => Architecture::Inferentia,
1347            | AcceleratorArchitecture::Lpu => Architecture::Lpu,
1348            | AcceleratorArchitecture::Maia => Architecture::Maia,
1349            | AcceleratorArchitecture::Nervana => Architecture::Nervana,
1350            | AcceleratorArchitecture::SambaNovaRdu => Architecture::SambaNovaRdu,
1351            | AcceleratorArchitecture::TpuV4 => Architecture::TpuV4,
1352            | AcceleratorArchitecture::TpuV5e => Architecture::TpuV5e,
1353            | AcceleratorArchitecture::TpuV5p => Architecture::TpuV5p,
1354            | AcceleratorArchitecture::TpuV6e => Architecture::TpuV6e,
1355            | AcceleratorArchitecture::Trainium => Architecture::Trainium,
1356            | AcceleratorArchitecture::Wormhole => Architecture::Wormhole,
1357            | AcceleratorArchitecture::Wse2 => Architecture::Wse2,
1358            | AcceleratorArchitecture::Wse3 => Architecture::Wse3,
1359            | AcceleratorArchitecture::Other(s) => Architecture::Other(s),
1360        }
1361    }
1362}
1363impl From<&AcceleratorArchitecture> for Architecture {
1364    fn from(value: &AcceleratorArchitecture) -> Self {
1365        match value {
1366            | AcceleratorArchitecture::Ascend910 => Architecture::Ascend910,
1367            | AcceleratorArchitecture::Blackhole => Architecture::Blackhole,
1368            | AcceleratorArchitecture::Gaudi2 => Architecture::Gaudi2,
1369            | AcceleratorArchitecture::GraphcoreGc200 => Architecture::GraphcoreGc200,
1370            | AcceleratorArchitecture::Inferentia => Architecture::Inferentia,
1371            | AcceleratorArchitecture::Lpu => Architecture::Lpu,
1372            | AcceleratorArchitecture::Maia => Architecture::Maia,
1373            | AcceleratorArchitecture::Nervana => Architecture::Nervana,
1374            | AcceleratorArchitecture::SambaNovaRdu => Architecture::SambaNovaRdu,
1375            | AcceleratorArchitecture::TpuV4 => Architecture::TpuV4,
1376            | AcceleratorArchitecture::TpuV5e => Architecture::TpuV5e,
1377            | AcceleratorArchitecture::TpuV5p => Architecture::TpuV5p,
1378            | AcceleratorArchitecture::TpuV6e => Architecture::TpuV6e,
1379            | AcceleratorArchitecture::Trainium => Architecture::Trainium,
1380            | AcceleratorArchitecture::Wormhole => Architecture::Wormhole,
1381            | AcceleratorArchitecture::Wse2 => Architecture::Wse2,
1382            | AcceleratorArchitecture::Wse3 => Architecture::Wse3,
1383            | AcceleratorArchitecture::Other(s) => Architecture::Other(s.clone()),
1384        }
1385    }
1386}
1387impl From<FpgaArchitecture> for Architecture {
1388    fn from(value: FpgaArchitecture) -> Self {
1389        match value {
1390            | FpgaArchitecture::Agilex => Architecture::Agilex,
1391            | FpgaArchitecture::Artix => Architecture::Artix,
1392            | FpgaArchitecture::CrossLink => Architecture::CrossLink,
1393            | FpgaArchitecture::CycloneV => Architecture::CycloneV,
1394            | FpgaArchitecture::Ecp5 => Architecture::Ecp5,
1395            | FpgaArchitecture::Ice40 => Architecture::Ice40,
1396            | FpgaArchitecture::Kintex => Architecture::Kintex,
1397            | FpgaArchitecture::Spartan => Architecture::Spartan,
1398            | FpgaArchitecture::Stratix10 => Architecture::Stratix10,
1399            | FpgaArchitecture::StratixV => Architecture::StratixV,
1400            | FpgaArchitecture::Versal => Architecture::Versal,
1401            | FpgaArchitecture::VirtexUltraScalePlus => Architecture::VirtexUltraScalePlus,
1402            | FpgaArchitecture::Zynq => Architecture::Zynq,
1403            | FpgaArchitecture::Other(s) => Architecture::Other(s),
1404        }
1405    }
1406}
1407impl From<&FpgaArchitecture> for Architecture {
1408    fn from(value: &FpgaArchitecture) -> Self {
1409        match value {
1410            | FpgaArchitecture::Agilex => Architecture::Agilex,
1411            | FpgaArchitecture::Artix => Architecture::Artix,
1412            | FpgaArchitecture::CrossLink => Architecture::CrossLink,
1413            | FpgaArchitecture::CycloneV => Architecture::CycloneV,
1414            | FpgaArchitecture::Ecp5 => Architecture::Ecp5,
1415            | FpgaArchitecture::Ice40 => Architecture::Ice40,
1416            | FpgaArchitecture::Kintex => Architecture::Kintex,
1417            | FpgaArchitecture::Spartan => Architecture::Spartan,
1418            | FpgaArchitecture::Stratix10 => Architecture::Stratix10,
1419            | FpgaArchitecture::StratixV => Architecture::StratixV,
1420            | FpgaArchitecture::Versal => Architecture::Versal,
1421            | FpgaArchitecture::VirtexUltraScalePlus => Architecture::VirtexUltraScalePlus,
1422            | FpgaArchitecture::Zynq => Architecture::Zynq,
1423            | FpgaArchitecture::Other(s) => Architecture::Other(s.clone()),
1424        }
1425    }
1426}
1427impl From<GpuArchitecture> for Architecture {
1428    fn from(value: GpuArchitecture) -> Self {
1429        match value {
1430            | GpuArchitecture::AdaLovelace => Architecture::AdaLovelace,
1431            | GpuArchitecture::Alchemist => Architecture::Alchemist,
1432            | GpuArchitecture::Ampere => Architecture::Ampere,
1433            | GpuArchitecture::Blackwell => Architecture::Blackwell,
1434            | GpuArchitecture::Cdna1 => Architecture::Cdna1,
1435            | GpuArchitecture::Cdna2 => Architecture::Cdna2,
1436            | GpuArchitecture::Cdna3 => Architecture::Cdna3,
1437            | GpuArchitecture::Cdna4 => Architecture::Cdna4,
1438            | GpuArchitecture::Fermi => Architecture::Fermi,
1439            | GpuArchitecture::Hopper => Architecture::Hopper,
1440            | GpuArchitecture::Kepler => Architecture::Kepler,
1441            | GpuArchitecture::Maxwell => Architecture::Maxwell,
1442            | GpuArchitecture::Orin => Architecture::Orin,
1443            | GpuArchitecture::Pascal => Architecture::Pascal,
1444            | GpuArchitecture::Rdna1 => Architecture::Rdna1,
1445            | GpuArchitecture::Rdna2 => Architecture::Rdna2,
1446            | GpuArchitecture::Rdna3 => Architecture::Rdna3,
1447            | GpuArchitecture::Tesla => Architecture::Tesla,
1448            | GpuArchitecture::Thor => Architecture::Thor,
1449            | GpuArchitecture::Turing => Architecture::Turing,
1450            | GpuArchitecture::Volta => Architecture::Volta,
1451            | GpuArchitecture::Xe => Architecture::Xe,
1452            | GpuArchitecture::Xe2 => Architecture::Xe2,
1453            | GpuArchitecture::Xe3 => Architecture::Xe3,
1454            | GpuArchitecture::AppleA14 => Architecture::AppleA14,
1455            | GpuArchitecture::AppleA16 => Architecture::AppleA16,
1456            | GpuArchitecture::AppleA18 => Architecture::AppleA18,
1457            | GpuArchitecture::AppleM1 => Architecture::AppleM1,
1458            | GpuArchitecture::AppleM2 => Architecture::AppleM2,
1459            | GpuArchitecture::AppleM3 => Architecture::AppleM3,
1460            | GpuArchitecture::AppleM4 => Architecture::AppleM4,
1461            | GpuArchitecture::AppleM5 => Architecture::AppleM5,
1462            | GpuArchitecture::Other(s) => Architecture::Other(s),
1463        }
1464    }
1465}
1466impl From<&GpuArchitecture> for Architecture {
1467    fn from(value: &GpuArchitecture) -> Self {
1468        match value {
1469            | GpuArchitecture::AdaLovelace => Architecture::AdaLovelace,
1470            | GpuArchitecture::Alchemist => Architecture::Alchemist,
1471            | GpuArchitecture::Ampere => Architecture::Ampere,
1472            | GpuArchitecture::Blackwell => Architecture::Blackwell,
1473            | GpuArchitecture::Cdna1 => Architecture::Cdna1,
1474            | GpuArchitecture::Cdna2 => Architecture::Cdna2,
1475            | GpuArchitecture::Cdna3 => Architecture::Cdna3,
1476            | GpuArchitecture::Cdna4 => Architecture::Cdna4,
1477            | GpuArchitecture::Fermi => Architecture::Fermi,
1478            | GpuArchitecture::Hopper => Architecture::Hopper,
1479            | GpuArchitecture::Kepler => Architecture::Kepler,
1480            | GpuArchitecture::Maxwell => Architecture::Maxwell,
1481            | GpuArchitecture::Orin => Architecture::Orin,
1482            | GpuArchitecture::Pascal => Architecture::Pascal,
1483            | GpuArchitecture::Rdna1 => Architecture::Rdna1,
1484            | GpuArchitecture::Rdna2 => Architecture::Rdna2,
1485            | GpuArchitecture::Rdna3 => Architecture::Rdna3,
1486            | GpuArchitecture::Tesla => Architecture::Tesla,
1487            | GpuArchitecture::Thor => Architecture::Thor,
1488            | GpuArchitecture::Turing => Architecture::Turing,
1489            | GpuArchitecture::Volta => Architecture::Volta,
1490            | GpuArchitecture::Xe => Architecture::Xe,
1491            | GpuArchitecture::Xe2 => Architecture::Xe2,
1492            | GpuArchitecture::Xe3 => Architecture::Xe3,
1493            | GpuArchitecture::AppleA14 => Architecture::AppleA14,
1494            | GpuArchitecture::AppleA16 => Architecture::AppleA16,
1495            | GpuArchitecture::AppleA18 => Architecture::AppleA18,
1496            | GpuArchitecture::AppleM1 => Architecture::AppleM1,
1497            | GpuArchitecture::AppleM2 => Architecture::AppleM2,
1498            | GpuArchitecture::AppleM3 => Architecture::AppleM3,
1499            | GpuArchitecture::AppleM4 => Architecture::AppleM4,
1500            | GpuArchitecture::AppleM5 => Architecture::AppleM5,
1501            | GpuArchitecture::Other(s) => Architecture::Other(s.clone()),
1502        }
1503    }
1504}
1505
1506impl<'de> Deserialize<'de> for Architecture {
1507    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1508    where
1509        D: serde::de::Deserializer<'de>,
1510    {
1511        struct ArchitectureVisitor;
1512        impl<'de> serde::de::Visitor<'de> for ArchitectureVisitor {
1513            type Value = Architecture;
1514            fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1515                formatter.write_str("an architecture string (e.g. 'x86_64', 'Ampere', 'Versal')")
1516            }
1517            fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Architecture, E> {
1518                Ok(Architecture::from_str(value))
1519            }
1520        }
1521        deserializer.deserialize_str(ArchitectureVisitor)
1522    }
1523}
1524impl From<&SensorModality> for Modality {
1525    fn from(value: &SensorModality) -> Self {
1526        match value {
1527            | SensorModality::Audio => Modality::Audio,
1528            | SensorModality::Image | SensorModality::Event | SensorModality::Depth => Modality::Video,
1529            | SensorModality::Lidar
1530            | SensorModality::Radar
1531            | SensorModality::Radio
1532            | SensorModality::NetworkTraffic
1533            | SensorModality::Webhook
1534            | SensorModality::Hyperspectral
1535            | SensorModality::Seismic
1536            | SensorModality::ServerSideEvent
1537            | SensorModality::Sonar
1538            | SensorModality::Inertial
1539            | SensorModality::Magnetic
1540            | SensorModality::Navigation
1541            | SensorModality::Pressure
1542            | SensorModality::Temperature
1543            | SensorModality::Ultrasonic
1544            | SensorModality::Chemical
1545            | SensorModality::Other(_) => Modality::Signal,
1546        }
1547    }
1548}
1549impl From<SensorModality> for Modality {
1550    fn from(value: SensorModality) -> Self {
1551        (&value).into()
1552    }
1553}
1554impl<'de> Deserialize<'de> for Resource {
1555    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1556    where
1557        D: serde::de::Deserializer<'de>,
1558    {
1559        struct ResourceVisitor;
1560        impl<'de> serde::de::Visitor<'de> for ResourceVisitor {
1561            type Value = Resource;
1562            fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1563                formatter.write_str(r#"a resource string (e.g. "CPU") or object (e.g. {"CPU": {...}})"#)
1564            }
1565            fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Resource, E> {
1566                match value {
1567                    | "ASIC" | "asic" => Ok(Resource::ASIC {
1568                        architecture: None,
1569                        count: Some(1),
1570                        purpose: None,
1571                        required: None,
1572                        vendor: None,
1573                    }),
1574                    | "CPU" | "cpu" => Ok(Resource::CPU {
1575                        architecture: None,
1576                        cores: None,
1577                        count: Some(1),
1578                        memory: None,
1579                        required: None,
1580                        threads: None,
1581                        vendor: None,
1582                    }),
1583                    | "DPU" | "dpu" => Ok(Resource::DPU {
1584                        architecture: None,
1585                        count: Some(1),
1586                        memory: None,
1587                        required: None,
1588                        vendor: None,
1589                    }),
1590                    | "DSP" | "dsp" => Ok(Resource::DSP {
1591                        architecture: None,
1592                        count: Some(1),
1593                        frequency: None,
1594                        required: None,
1595                        vendor: None,
1596                    }),
1597                    | "FPGA" | "fpga" => Ok(Resource::FPGA {
1598                        architecture: None,
1599                        count: Some(1),
1600                        logic_elements: None,
1601                        memory: None,
1602                        required: None,
1603                        vendor: None,
1604                    }),
1605                    | "GPU" | "gpu" => Ok(Resource::GPU {
1606                        architecture: None,
1607                        backend: None,
1608                        compute_capability: None,
1609                        count: Some(1),
1610                        memory: None,
1611                        name: None,
1612                        required: None,
1613                        vendor: None,
1614                    }),
1615                    | "NPU" | "npu" => Ok(Resource::NPU {
1616                        architecture: None,
1617                        count: Some(1),
1618                        memory: None,
1619                        required: None,
1620                        vendor: None,
1621                    }),
1622                    | "Neuromorphic" | "neuromorphic" => Ok(Resource::Neuromorphic {
1623                        count: Some(1),
1624                        memory: None,
1625                        model: None,
1626                        neurons: None,
1627                        required: None,
1628                        synapses: None,
1629                        vendor: None,
1630                    }),
1631                    | "Quantum" | "quantum" => Ok(Resource::Quantum {
1632                        count: Some(1),
1633                        model: None,
1634                        paradigm: None,
1635                        qubits: None,
1636                        required: None,
1637                        topology: None,
1638                        vendor: None,
1639                    }),
1640                    | "Sensor" | "sensor" => Ok(Resource::Sensor {
1641                        count: Some(1),
1642                        modality: None,
1643                        model: None,
1644                        quantum_regime: None,
1645                        sampling_rate: None,
1646                        required: None,
1647                        vendor: None,
1648                    }),
1649                    | "TPU" | "tpu" => Ok(Resource::TPU {
1650                        architecture: None,
1651                        count: Some(1),
1652                        memory: None,
1653                        required: None,
1654                        vendor: None,
1655                    }),
1656                    | other => Ok(Resource::Other(other.to_string())),
1657                }
1658            }
1659            fn visit_map<M: serde::de::MapAccess<'de>>(self, mut map: M) -> Result<Resource, M::Error> {
1660                let next_key_result: Result<Option<String>, M::Error> = map.next_key();
1661                match next_key_result {
1662                    | Ok(Some(tag)) => match tag.as_str() {
1663                        | "ASIC" => {
1664                            #[derive(Deserialize)]
1665                            struct F {
1666                                #[serde(alias = "arch")]
1667                                architecture: Option<CpuArchitecture>,
1668                                #[serde(default = "default_count")]
1669                                count: Option<u32>,
1670                                purpose: Option<String>,
1671                                required: Option<bool>,
1672                                vendor: Option<Vendor>,
1673                            }
1674                            let next_value_result: Result<F, M::Error> = map.next_value();
1675                            match next_value_result {
1676                                | Ok(f) => Ok(Resource::ASIC {
1677                                    architecture: f.architecture,
1678                                    count: f.count,
1679                                    purpose: f.purpose,
1680                                    required: f.required,
1681                                    vendor: f.vendor,
1682                                }),
1683                                | Err(why) => Err(why),
1684                            }
1685                        }
1686                        | "CPU" => {
1687                            #[derive(Deserialize)]
1688                            struct F {
1689                                #[serde(alias = "arch")]
1690                                architecture: Option<CpuArchitecture>,
1691                                cores: Option<u32>,
1692                                #[serde(default = "default_count")]
1693                                count: Option<u32>,
1694                                memory: Option<Memory>,
1695                                required: Option<bool>,
1696                                threads: Option<u32>,
1697                                vendor: Option<Vendor>,
1698                            }
1699                            let next_value_result: Result<F, M::Error> = map.next_value();
1700                            match next_value_result {
1701                                | Ok(f) => Ok(Resource::CPU {
1702                                    architecture: f.architecture,
1703                                    cores: f.cores,
1704                                    count: f.count,
1705                                    memory: f.memory,
1706                                    required: f.required,
1707                                    threads: f.threads,
1708                                    vendor: f.vendor,
1709                                }),
1710                                | Err(why) => Err(why),
1711                            }
1712                        }
1713                        | "DPU" => {
1714                            #[derive(Deserialize)]
1715                            struct F {
1716                                #[serde(alias = "arch")]
1717                                architecture: Option<CpuArchitecture>,
1718                                #[serde(default = "default_count")]
1719                                count: Option<u32>,
1720                                memory: Option<Memory>,
1721                                required: Option<bool>,
1722                                vendor: Option<Vendor>,
1723                            }
1724                            let next_value_result: Result<F, M::Error> = map.next_value();
1725                            match next_value_result {
1726                                | Ok(f) => Ok(Resource::DPU {
1727                                    architecture: f.architecture,
1728                                    count: f.count,
1729                                    memory: f.memory,
1730                                    required: f.required,
1731                                    vendor: f.vendor,
1732                                }),
1733                                | Err(why) => Err(why),
1734                            }
1735                        }
1736                        | "DSP" => {
1737                            #[derive(Deserialize)]
1738                            struct F {
1739                                #[serde(alias = "arch")]
1740                                architecture: Option<DspArchitecture>,
1741                                #[serde(default = "default_count")]
1742                                count: Option<u32>,
1743                                frequency: Option<u32>,
1744                                required: Option<bool>,
1745                                vendor: Option<Vendor>,
1746                            }
1747                            let next_value_result: Result<F, M::Error> = map.next_value();
1748                            match next_value_result {
1749                                | Ok(f) => Ok(Resource::DSP {
1750                                    architecture: f.architecture,
1751                                    count: f.count,
1752                                    frequency: f.frequency,
1753                                    required: f.required,
1754                                    vendor: f.vendor,
1755                                }),
1756                                | Err(why) => Err(why),
1757                            }
1758                        }
1759                        | "FPGA" => {
1760                            #[derive(Deserialize)]
1761                            struct F {
1762                                #[serde(alias = "arch")]
1763                                architecture: Option<FpgaArchitecture>,
1764                                #[serde(default = "default_count")]
1765                                count: Option<u32>,
1766                                logic_elements: Option<u32>,
1767                                memory: Option<Memory>,
1768                                required: Option<bool>,
1769                                vendor: Option<Vendor>,
1770                            }
1771                            let next_value_result: Result<F, M::Error> = map.next_value();
1772                            match next_value_result {
1773                                | Ok(f) => Ok(Resource::FPGA {
1774                                    architecture: f.architecture,
1775                                    count: f.count,
1776                                    logic_elements: f.logic_elements,
1777                                    memory: f.memory,
1778                                    required: f.required,
1779                                    vendor: f.vendor,
1780                                }),
1781                                | Err(why) => Err(why),
1782                            }
1783                        }
1784                        | "GPU" => {
1785                            #[derive(Deserialize)]
1786                            struct F {
1787                                #[serde(alias = "arch")]
1788                                architecture: Option<GpuArchitecture>,
1789                                backend: Option<Backend>,
1790                                compute_capability: Option<f32>,
1791                                #[serde(default = "default_count")]
1792                                count: Option<u32>,
1793                                memory: Option<Memory>,
1794                                name: Option<String>,
1795                                required: Option<bool>,
1796                                vendor: Option<Vendor>,
1797                            }
1798                            let next_value_result: Result<F, M::Error> = map.next_value();
1799                            match next_value_result {
1800                                | Ok(f) => Ok(Resource::GPU {
1801                                    architecture: f.architecture,
1802                                    backend: f.backend,
1803                                    compute_capability: f.compute_capability,
1804                                    count: f.count,
1805                                    memory: f.memory,
1806                                    name: f.name,
1807                                    required: f.required,
1808                                    vendor: f.vendor,
1809                                }),
1810                                | Err(why) => Err(why),
1811                            }
1812                        }
1813                        | "NPU" => {
1814                            #[derive(Deserialize)]
1815                            struct F {
1816                                #[serde(alias = "arch")]
1817                                architecture: Option<AcceleratorArchitecture>,
1818                                #[serde(default = "default_count")]
1819                                count: Option<u32>,
1820                                memory: Option<Memory>,
1821                                required: Option<bool>,
1822                                vendor: Option<Vendor>,
1823                            }
1824                            let next_value_result: Result<F, M::Error> = map.next_value();
1825                            match next_value_result {
1826                                | Ok(f) => Ok(Resource::NPU {
1827                                    architecture: f.architecture,
1828                                    count: f.count,
1829                                    memory: f.memory,
1830                                    required: f.required,
1831                                    vendor: f.vendor,
1832                                }),
1833                                | Err(why) => Err(why),
1834                            }
1835                        }
1836                        | "Neuromorphic" => {
1837                            #[derive(Deserialize)]
1838                            struct F {
1839                                #[serde(default = "default_count")]
1840                                count: Option<u32>,
1841                                #[serde(alias = "mem")]
1842                                memory: Option<Memory>,
1843                                model: Option<String>,
1844                                neurons: Option<u64>,
1845                                required: Option<bool>,
1846                                synapses: Option<u64>,
1847                                vendor: Option<Vendor>,
1848                            }
1849                            let next_value_result: Result<F, M::Error> = map.next_value();
1850                            match next_value_result {
1851                                | Ok(f) => Ok(Resource::Neuromorphic {
1852                                    count: f.count,
1853                                    memory: f.memory,
1854                                    model: f.model,
1855                                    neurons: f.neurons,
1856                                    required: f.required,
1857                                    synapses: f.synapses,
1858                                    vendor: f.vendor,
1859                                }),
1860                                | Err(why) => Err(why),
1861                            }
1862                        }
1863                        | "Quantum" => {
1864                            #[derive(Deserialize)]
1865                            struct F {
1866                                #[serde(default = "default_count")]
1867                                count: Option<u32>,
1868                                model: Option<Model>,
1869                                paradigm: Option<Paradigm>,
1870                                qubits: Option<u32>,
1871                                required: Option<bool>,
1872                                topology: Option<Topology>,
1873                                vendor: Option<Vendor>,
1874                            }
1875                            let next_value_result: Result<F, M::Error> = map.next_value();
1876                            match next_value_result {
1877                                | Ok(f) => Ok(Resource::Quantum {
1878                                    count: f.count,
1879                                    model: f.model,
1880                                    paradigm: f.paradigm,
1881                                    qubits: f.qubits,
1882                                    required: f.required,
1883                                    topology: f.topology,
1884                                    vendor: f.vendor,
1885                                }),
1886                                | Err(why) => Err(why),
1887                            }
1888                        }
1889                        | "Sensor" => {
1890                            #[derive(Deserialize)]
1891                            struct F {
1892                                #[serde(default = "default_count")]
1893                                count: Option<u32>,
1894                                modality: Option<Vec<SensorModality>>,
1895                                model: Option<String>,
1896                                #[serde(alias = "quantumRegime", alias = "quantum regime")]
1897                                quantum_regime: Option<Regime>,
1898                                #[serde(alias = "samplingRateHz", alias = "sampling_rate")]
1899                                sampling_rate_hz: Option<f32>,
1900                                required: Option<bool>,
1901                                vendor: Option<Vendor>,
1902                            }
1903                            let next_value_result: Result<F, M::Error> = map.next_value();
1904                            match next_value_result {
1905                                | Ok(f) => Ok(Resource::Sensor {
1906                                    count: f.count,
1907                                    modality: f.modality,
1908                                    model: f.model,
1909                                    quantum_regime: f.quantum_regime,
1910                                    sampling_rate: f.sampling_rate_hz,
1911                                    required: f.required,
1912                                    vendor: f.vendor,
1913                                }),
1914                                | Err(why) => Err(why),
1915                            }
1916                        }
1917                        | "TPU" => {
1918                            #[derive(Deserialize)]
1919                            struct F {
1920                                #[serde(alias = "arch")]
1921                                architecture: Option<AcceleratorArchitecture>,
1922                                #[serde(default = "default_count")]
1923                                count: Option<u32>,
1924                                memory: Option<Memory>,
1925                                required: Option<bool>,
1926                                vendor: Option<Vendor>,
1927                            }
1928                            let next_value_result: Result<F, M::Error> = map.next_value();
1929                            match next_value_result {
1930                                | Ok(f) => Ok(Resource::TPU {
1931                                    architecture: f.architecture,
1932                                    count: f.count,
1933                                    memory: f.memory,
1934                                    required: f.required,
1935                                    vendor: f.vendor,
1936                                }),
1937                                | Err(why) => Err(why),
1938                            }
1939                        }
1940                        | other => {
1941                            let next_value_result: Result<serde::de::IgnoredAny, M::Error> = map.next_value();
1942                            match next_value_result {
1943                                | Ok::<serde::de::IgnoredAny, M::Error>(_) => Ok(Resource::Other(other.to_string())),
1944                                | Err(why) => Err(why),
1945                            }
1946                        }
1947                    },
1948                    | Ok(None) => Err(serde::de::Error::custom("expected resource variant key")),
1949                    | Err(why) => Err(why),
1950                }
1951            }
1952        }
1953        deserializer.deserialize_any(ResourceVisitor)
1954    }
1955}
1956impl Validate for Resource {
1957    fn validate(&self) -> Result<(), ValidationErrors> {
1958        validate_vendor(self)
1959    }
1960}
1961impl Resource {
1962    fn is_spark(&self) -> bool {
1963        match self {
1964            | Resource::GPU {
1965                name: Some(name),
1966                architecture: Some(architecture),
1967                ..
1968            } => {
1969                let value = name.to_lowercase();
1970                *architecture == GpuArchitecture::Blackwell && ["spark", "gb10", "dgx spark"].iter().any(|term| value.contains(term))
1971            }
1972            | _ => false,
1973        }
1974    }
1975    fn name(&self) -> Option<String> {
1976        match self {
1977            | Resource::GPU { name: Some(name), .. } => Some(name.to_lowercase().replace(' ', "")),
1978            | _ => None,
1979        }
1980    }
1981    /// Returns compute value (major, minor) which defines the hardware features and supported instructions for each NVIDIA GPU architecture
1982    ///
1983    /// Values come from the official [NVIDIA CUDA GPU compute capability page](https://developer.nvidia.com/cuda/gpus) (and [this page](https://developer.nvidia.com/cuda/gpus/legacy) for legacy GPUs)
1984    ///
1985    /// Returns `None` for non-NVIDIA GPUs or unrecognized models.
1986    #[allow(dead_code)]
1987    pub fn compute_value(&self) -> Option<(u8, u8)> {
1988        match &self.vendor() {
1989            | Some(Vendor::Nvidia) => match self.architecture() {
1990                | Some(Architecture::Blackwell) => {
1991                    if self.is_spark() {
1992                        Some((12, 1))
1993                    } else if let Some(v) = self.name() {
1994                        if contains_any(NVIDIA_CC_BLACKWELL_103_PATTERNS, &v) {
1995                            Some((10, 3))
1996                        } else if contains_any(NVIDIA_CC_BLACKWELL_100_PATTERNS, &v) {
1997                            Some((10, 0))
1998                        } else {
1999                            Some((12, 0))
2000                        }
2001                    } else {
2002                        Some((12, 0))
2003                    }
2004                }
2005                | Some(Architecture::Hopper) => Some((9, 0)),
2006                | Some(Architecture::AdaLovelace) => Some((8, 9)),
2007                | Some(Architecture::Thor) => Some((11, 0)),
2008                | Some(Architecture::Orin) => Some((8, 7)),
2009                | Some(Architecture::Ampere) => {
2010                    if let Some(v) = self.name() {
2011                        if contains_any(NVIDIA_CC_AMPERE_80_PATTERNS, &v) {
2012                            Some((8, 0))
2013                        } else {
2014                            Some((8, 6))
2015                        }
2016                    } else {
2017                        Some((8, 6))
2018                    }
2019                }
2020                | Some(Architecture::Turing) => Some((7, 5)),
2021                | Some(Architecture::Volta) => {
2022                    if let Some(v) = self.name() {
2023                        if v.contains("xavier") {
2024                            Some((7, 2))
2025                        } else {
2026                            Some((7, 0))
2027                        }
2028                    } else {
2029                        Some((7, 0))
2030                    }
2031                }
2032                | Some(Architecture::Pascal) => {
2033                    if let Some(v) = self.name() {
2034                        if v.contains("tx2") {
2035                            Some((6, 2))
2036                        } else if contains_any(NVIDIA_CC_PASCAL_60_PATTERNS, &v) {
2037                            Some((6, 0))
2038                        } else {
2039                            Some((6, 1))
2040                        }
2041                    } else {
2042                        Some((6, 1))
2043                    }
2044                }
2045                | Some(Architecture::Maxwell) => {
2046                    if let Some(v) = self.name() {
2047                        if v.contains("jetson") && v.contains("nano") {
2048                            Some((5, 3))
2049                        } else if contains_any(NVIDIA_CC_MAXWELL_52_PATTERNS, &v) {
2050                            Some((5, 2))
2051                        } else if contains_any(NVIDIA_CC_MAXWELL_50_PATTERNS, &v) || (v.contains("gtx") && v.contains("750")) {
2052                            Some((5, 0))
2053                        } else {
2054                            Some((5, 2))
2055                        }
2056                    } else {
2057                        Some((5, 2))
2058                    }
2059                }
2060                | Some(Architecture::Kepler) => {
2061                    if let Some(v) = self.name() {
2062                        if v.contains("k80") {
2063                            Some((3, 7))
2064                        } else if contains_any(NVIDIA_CC_KEPLER_35_PATTERNS, &v) {
2065                            Some((3, 5))
2066                        } else if contains_any(NVIDIA_CC_KEPLER_32_PATTERNS, &v) {
2067                            Some((3, 2))
2068                        } else {
2069                            Some((3, 0))
2070                        }
2071                    } else {
2072                        Some((3, 0))
2073                    }
2074                }
2075                | Some(Architecture::Fermi) => {
2076                    if let Some(v) = self.name() {
2077                        if contains_any(NVIDIA_CC_FERMI_21_PATTERNS, &v)
2078                            || contains_any_with_prefix(&v, "quadro", NVIDIA_CC_FERMI_21_QUADRO_SUFFIXES)
2079                            || contains_any_with_prefix(&v, "gt", NVIDIA_CC_FERMI_21_GT_SUFFIXES)
2080                        {
2081                            Some((2, 1))
2082                        } else {
2083                            Some((2, 0))
2084                        }
2085                    } else {
2086                        Some((2, 0))
2087                    }
2088                }
2089                | Some(Architecture::Tesla) => {
2090                    if let Some(v) = self.name() {
2091                        if contains_any(NVIDIA_CC_TESLA_13_PATTERNS, &v) || contains_any_with_prefix(&v, "quadro", NVIDIA_CC_TESLA_13_QUADRO_SUFFIXES)
2092                        {
2093                            Some((1, 3))
2094                        } else if contains_any(NVIDIA_CC_TESLA_12_PATTERNS, &v)
2095                            || contains_any_with_prefix(&v, "quadro", NVIDIA_CC_TESLA_12_QUADRO_SUFFIXES)
2096                            || contains_any_with_prefix(&v, "gt", NVIDIA_CC_TESLA_12_GT_SUFFIXES)
2097                        {
2098                            Some((1, 2))
2099                        } else if contains_any(NVIDIA_CC_TESLA_11_PATTERNS, &v)
2100                            || contains_any_with_prefix(&v, "quadro", NVIDIA_CC_TESLA_11_QUADRO_SUFFIXES)
2101                            || contains_any_with_prefix(&v, "gts", NVIDIA_CC_TESLA_11_GTS_SUFFIXES)
2102                            || contains_any_with_prefix(&v, "gt", NVIDIA_CC_TESLA_11_GT_SUFFIXES)
2103                        {
2104                            Some((1, 1))
2105                        } else {
2106                            Some((1, 0))
2107                        }
2108                    } else {
2109                        Some((1, 0))
2110                    }
2111                }
2112                | _ => None,
2113            },
2114            | _ => None,
2115        }
2116    }
2117}
2118fn default_count() -> Option<u32> {
2119    Some(1)
2120}
2121
2122#[cfg(test)]
2123mod tests;