1use 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
17pub mod memory;
19pub mod quantum;
21pub 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#[derive(Clone, Debug, Display, PartialEq, Serialize, JsonSchema)]
34pub enum Architecture {
35 #[display("AArch64")]
39 AArch64,
40 #[display("Ada Lovelace")]
45 AdaLovelace,
46 #[display("Agilex")]
50 Agilex,
51 #[display("Alchemist")]
56 Alchemist,
57 #[display("Ampere")]
62 Ampere,
63 #[display("Apple GPU (A14/A15)")]
65 AppleA14,
66 #[display("Apple GPU (A16/A17)")]
68 AppleA16,
69 #[display("Apple GPU (A18)")]
71 AppleA18,
72 #[display("Apple Efficiency Core")]
74 AppleEfficiencyCore,
75 #[display("Apple GPU (M1)")]
77 AppleM1,
78 #[display("Apple GPU (M2)")]
80 AppleM2,
81 #[display("Apple GPU (M3)")]
83 AppleM3,
84 #[display("Apple GPU (M4)")]
86 AppleM4,
87 #[display("Apple GPU (M5)")]
89 AppleM5,
90 #[display("Apple Performance Core")]
92 ApplePerformanceCore,
93 #[display("Artix")]
98 Artix,
99 #[display("Ascend 910")]
103 Ascend910,
104 #[display("Blackhole")]
109 Blackhole,
110 #[display("Blackwell")]
114 Blackwell,
115 #[display("C66x")]
119 C66x,
120 #[display("Carmel")]
126 Carmel,
127 #[display("CDNA1")]
132 Cdna1,
133 #[display("CDNA2")]
138 Cdna2,
139 #[display("CDNA3")]
144 Cdna3,
145 #[display("CDNA4")]
150 Cdna4,
151 #[display("CrossLink")]
163 CrossLink,
164 #[display("Cyclone V")]
168 CycloneV,
169 #[display("ECP5")]
174 Ecp5,
175 #[display("Ethos")]
179 Ethos,
180 #[display("Fermi")]
186 Fermi,
187 #[display("Gaudi2")]
191 Gaudi2,
192 #[display("Graphcore GC200")]
194 GraphcoreGc200,
195 #[display("Grace")]
199 Grace,
200 #[display("Hexagon")]
205 Hexagon,
206 #[display("Hopper")]
210 Hopper,
211 #[display("IA-64")]
215 Ia64,
216 #[display("iCE40")]
223 Ice40,
224 #[display("Inferentia")]
228 Inferentia,
229 #[display("Kepler")]
233 Kepler,
234 #[display("Kintex")]
236 Kintex,
237 #[display("LoongArch")]
241 LoongArch,
242 #[display("LPU")]
246 Lpu,
247 #[display("Maia")]
251 Maia,
252 #[display("Maxwell")]
256 Maxwell,
257 #[display("MIPS")]
263 Mips,
264 #[display("Nervana")]
268 Nervana,
269 #[display("Neural Engine")]
273 NeuralEngine,
274 #[display("Orin")]
280 Orin,
281 #[display("Pascal")]
285 Pascal,
286 #[display("PowerPC")]
293 PowerPc,
294 #[display("RDNA1")]
298 Rdna1,
299 #[display("RDNA2")]
303 Rdna2,
304 #[display("RDNA3")]
308 Rdna3,
309 #[display("RISC-V")]
316 RiscV,
317 #[display("SambaNova RDU")]
322 SambaNovaRdu,
323 #[display("Spartan")]
328 Spartan,
329 #[display("Stratix 10")]
333 Stratix10,
334 #[display("Stratix V")]
338 StratixV,
339 #[display("Tesla")]
345 Tesla,
346 #[display("Thor")]
352 Thor,
353 #[display("TPU v4")]
357 TpuV4,
358 #[display("TPU v5e")]
362 TpuV5e,
363 #[display("TPU v5p")]
367 TpuV5p,
368 #[display("TPU v6e")]
372 TpuV6e,
373 #[display("Trainium")]
378 Trainium,
379 #[display("Turing")]
383 Turing,
384 #[display("Versal")]
389 Versal,
390 #[display("Virtex UltraScale+")]
394 VirtexUltraScalePlus,
395 #[display("Volta")]
399 Volta,
400 #[display("Vera")]
404 Vera,
405 #[display("Wormhole")]
410 Wormhole,
411 #[display("WSE-2")]
415 Wse2,
416 #[display("WSE-3")]
420 Wse3,
421 #[display("x86")]
425 X86,
426 #[display("x86_64")]
430 X86_64,
431 #[display("Xe")]
433 Xe,
434 #[display("Xe2")]
438 Xe2,
439 #[display("Xe3")]
443 Xe3,
444 #[display("Xtensa")]
448 Xtensa,
449 #[display("z/Architecture")]
453 ZArch,
454 #[display("Zynq")]
458 Zynq,
459 #[display("{}", _0)]
461 Other(String),
462}
463#[derive(Clone, Debug, Display, Deserialize, PartialEq, Serialize, JsonSchema)]
465pub enum AcceleratorArchitecture {
466 #[display("Ascend 910")]
468 #[serde(alias = "ascend 910", alias = "Ascend910", alias = "ascend910")]
469 Ascend910,
470 #[display("Blackhole")]
472 #[serde(alias = "blackhole")]
473 Blackhole,
474 #[display("Gaudi2")]
476 #[serde(alias = "Gaudi 2", alias = "gaudi2", alias = "gaudi 2")]
477 Gaudi2,
478 #[display("Graphcore GC200")]
480 #[serde(alias = "graphcore gc200", alias = "GC200", alias = "gc200")]
481 GraphcoreGc200,
482 #[display("Inferentia")]
484 #[serde(alias = "inferentia")]
485 Inferentia,
486 #[display("LPU")]
488 #[serde(alias = "lpu", alias = "Language Processing Unit", alias = "language processing unit")]
489 Lpu,
490 #[display("Maia")]
492 #[serde(alias = "maia")]
493 Maia,
494 #[display("Nervana")]
496 #[serde(alias = "nervana")]
497 Nervana,
498 #[display("SambaNova RDU")]
500 #[serde(alias = "sambanova rdu", alias = "RDU", alias = "rdu")]
501 SambaNovaRdu,
502 #[display("TPU v4")]
504 #[serde(alias = "TPU v4", alias = "TPUv4", alias = "tpu v4", alias = "tpuv4")]
505 TpuV4,
506 #[display("TPU v5e")]
508 #[serde(alias = "TPU v5e", alias = "TPUv5e", alias = "tpu v5e", alias = "tpuv5e")]
509 TpuV5e,
510 #[display("TPU v5p")]
512 #[serde(alias = "TPU v5p", alias = "TPUv5p", alias = "tpu v5p", alias = "tpuv5p")]
513 TpuV5p,
514 #[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 #[display("Trainium")]
527 #[serde(alias = "trainium")]
528 Trainium,
529 #[display("Wormhole")]
531 #[serde(alias = "wormhole")]
532 Wormhole,
533 #[display("WSE-2")]
535 #[serde(alias = "wse2", alias = "WSE2", alias = "wse-2")]
536 Wse2,
537 #[display("WSE-3")]
539 #[serde(alias = "wse3", alias = "WSE3", alias = "wse-3")]
540 Wse3,
541 #[display("{}", _0)]
543 Other(String),
544}
545#[derive(Clone, Debug, Display, Deserialize, Serialize, JsonSchema)]
547pub enum Backend {
548 #[display("CUDA")]
550 Cuda,
551 #[display("DirectML")]
553 DirectMl,
554 #[display("HIP")]
556 Hip,
557 #[display("Metal")]
559 Metal,
560 #[display("oneAPI")]
562 OneApi,
563 #[display("OpenCL")]
565 OpenCl,
566 #[display("ROCm")]
568 RoCm,
569 #[display("SYCL")]
571 Sycl,
572 #[display("Vulkan")]
574 Vulkan,
575 #[display("WebGPU")]
577 WebGpu,
578 #[display("{}", _0)]
580 Other(String),
581}
582#[derive(Clone, Debug, Display, Deserialize, PartialEq, Serialize, JsonSchema)]
584pub enum SensorModality {
585 #[display("audio")]
587 #[serde(alias = "audio", alias = "acoustic", alias = "microphone", alias = "hydrophone")]
588 Audio,
589 #[display("chemical")]
591 #[serde(alias = "chemical", alias = "chem", alias = "gas", alias = "ph")]
592 Chemical,
593 #[display("depth")]
595 #[serde(alias = "depth", alias = "tof", alias = "time-of-flight", alias = "structured-light")]
596 Depth,
597 #[display("event")]
599 #[serde(alias = "event", alias = "event-camera", alias = "event camera", alias = "dvs")]
600 Event,
601 #[display("hyperspectral")]
603 #[serde(alias = "hyperspectral", alias = "hyper-spectral", alias = "hsi")]
604 Hyperspectral,
605 #[display("image")]
607 #[serde(alias = "image", alias = "camera", alias = "vision", alias = "thermal")]
608 Image,
609 #[display("inertial")]
611 #[serde(alias = "inertial", alias = "imu", alias = "accel", alias = "gyroscope")]
612 Inertial,
613 #[display("lidar")]
615 #[serde(alias = "lidar", alias = "li-dar")]
616 Lidar,
617 #[display("magnetic")]
619 #[serde(alias = "magnetic", alias = "magnetometer")]
620 Magnetic,
621 #[display("navigation")]
623 #[serde(alias = "navigation", alias = "gnss", alias = "gps")]
624 Navigation,
625 #[display("network-traffic")]
627 #[serde(alias = "network-traffic", alias = "network traffic", alias = "netflow", alias = "packet")]
628 NetworkTraffic,
629 #[display("pressure")]
631 #[serde(alias = "pressure", alias = "barometer")]
632 Pressure,
633 #[display("radar")]
635 #[serde(alias = "radar", alias = "sar")]
636 Radar,
637 #[display("rf")]
639 #[serde(alias = "rf", alias = "radio", alias = "spectrum")]
640 Radio,
641 #[display("seismic")]
643 #[serde(alias = "seismic", alias = "geophone")]
644 Seismic,
645 #[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 #[display("sonar")]
657 #[serde(alias = "sonar", alias = "acoustic-ranging")]
658 Sonar,
659 #[display("temperature")]
661 #[serde(alias = "temperature", alias = "temp", alias = "thermometer")]
662 Temperature,
663 #[display("ultrasonic")]
665 #[serde(alias = "ultrasonic", alias = "ultrasound")]
666 Ultrasonic,
667 #[display("webhook")]
669 #[serde(alias = "webhook", alias = "web hook", alias = "http-callback", alias = "http callback")]
670 Webhook,
671 #[display("{}", _0)]
673 Other(String),
674}
675#[derive(Clone, Debug, Display, Deserialize, PartialEq, Serialize, JsonSchema)]
677pub enum CpuArchitecture {
678 #[display("AArch64")]
680 #[serde(alias = "arm", alias = "aarch64", alias = "arm64")]
681 AArch64,
682 #[display("Carmel")]
688 #[serde(alias = "carmel", alias = "carmel cpu")]
689 Carmel,
690 #[display("Apple Efficiency Core")]
692 #[serde(alias = "Apple Efficiency Core", alias = "apple efficiency core", alias = "EfficiencyCore")]
693 EfficiencyCore,
694 #[display("Ethos")]
696 #[serde(alias = "ethos")]
697 Ethos,
698 #[display("Grace")]
704 #[serde(alias = "grace", alias = "grace cpu")]
705 Grace,
706 #[display("Hexagon")]
708 #[serde(alias = "hexagon")]
709 Hexagon,
710 #[display("IA-64")]
712 #[serde(alias = "ia64", alias = "IA64")]
713 Ia64,
714 #[display("LoongArch")]
716 #[serde(alias = "loongarch")]
717 LoongArch,
718 #[display("MIPS")]
720 #[serde(alias = "mips")]
721 Mips,
722 #[display("Neural Engine")]
724 #[serde(alias = "Neural Engine")]
725 NeuralEngine,
726 #[display("Apple Performance Core")]
728 #[serde(alias = "Apple Performance Core", alias = "apple performance core", alias = "PerformanceCore")]
729 PerformanceCore,
730 #[display("PowerPC")]
732 #[serde(alias = "powerpc")]
733 PowerPc,
734 #[display("RISC-V")]
736 #[serde(alias = "riscv", alias = "risc-v")]
737 RiscV,
738 #[display("Vera")]
742 #[serde(alias = "vera", alias = "vera cpu")]
743 Vera,
744 #[display("x86")]
746 #[serde(alias = "X86")]
747 X86,
748 #[display("x86_64")]
750 #[serde(alias = "x86_64", alias = "x86-64", alias = "amd64")]
751 X86_64,
752 #[display("z/Architecture")]
754 #[serde(alias = "z architecture", alias = "zarchitecture")]
755 ZArch,
756 #[display("{}", _0)]
758 Other(String),
759}
760#[derive(Clone, Debug, Display, Deserialize, PartialEq, Serialize, JsonSchema)]
762pub enum DspArchitecture {
763 #[display("C66x")]
765 #[serde(alias = "c66x")]
766 C66x,
767 #[display("Xtensa")]
769 #[serde(alias = "xtensa")]
770 Xtensa,
771 #[display("{}", _0)]
773 Other(String),
774}
775#[derive(Clone, Debug, Display, Deserialize, PartialEq, Serialize, JsonSchema)]
777pub enum FpgaArchitecture {
778 #[display("Agilex")]
780 #[serde(alias = "agilex")]
781 Agilex,
782 #[display("Artix")]
784 #[serde(alias = "artix")]
785 Artix,
786 #[display("CrossLink")]
788 #[serde(alias = "crosslink", alias = "cross-link")]
789 CrossLink,
790 #[display("Cyclone V")]
792 #[serde(alias = "cyclonev", alias = "cyclone v")]
793 CycloneV,
794 #[display("ECP5")]
796 #[serde(alias = "ecp5")]
797 Ecp5,
798 #[display("iCE40")]
800 #[serde(alias = "ice40", alias = "iCE40")]
801 Ice40,
802 #[display("Kintex")]
804 #[serde(alias = "kintex")]
805 Kintex,
806 #[display("Spartan")]
808 #[serde(alias = "spartan")]
809 Spartan,
810 #[display("Stratix 10")]
812 #[serde(alias = "stratix10", alias = "stratix 10")]
813 Stratix10,
814 #[display("Stratix V")]
816 #[serde(alias = "stratixv", alias = "stratix v")]
817 StratixV,
818 #[display("Versal")]
820 #[serde(alias = "versal")]
821 Versal,
822 #[display("Virtex UltraScale+")]
824 #[serde(alias = "virtex ultrascale+", alias = "virtexultrascaleplus", alias = "virtex ultrascale plus")]
825 VirtexUltraScalePlus,
826 #[display("Zynq")]
828 #[serde(alias = "zynq")]
829 Zynq,
830 #[display("{}", _0)]
832 Other(String),
833}
834#[derive(Clone, Debug, Display, Deserialize, PartialEq, Serialize, JsonSchema)]
841pub enum GpuArchitecture {
842 #[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 #[display("Alchemist")]
855 #[serde(alias = "alchemist", alias = "Arc", alias = "arc", alias = "DG2", alias = "dg2")]
856 Alchemist,
857 #[display("Ampere")]
859 #[serde(alias = "ampere", alias = "GA100", alias = "ga100", alias = "GA102", alias = "ga102")]
860 Ampere,
861 #[display("Apple GPU (A14/A15)")]
863 #[serde(alias = "Apple GPU (A14/A15)", alias = "apple gpu (a14/a15)", alias = "A14", alias = "a14")]
864 AppleA14,
865 #[display("Apple GPU (A16/A17)")]
867 #[serde(alias = "Apple GPU (A16/A17)", alias = "apple gpu (a16/a17)", alias = "A16", alias = "a16")]
868 AppleA16,
869 #[display("Apple GPU (A18)")]
871 #[serde(alias = "Apple GPU (A18)", alias = "apple gpu (a18)", alias = "A18", alias = "a18")]
872 AppleA18,
873 #[display("Apple GPU (M1)")]
875 #[serde(alias = "Apple GPU (M1)", alias = "apple gpu (m1)", alias = "M1", alias = "m1")]
876 AppleM1,
877 #[display("Apple GPU (M2)")]
879 #[serde(alias = "Apple GPU (M2)", alias = "apple gpu (m2)", alias = "M2", alias = "m2")]
880 AppleM2,
881 #[display("Apple GPU (M3)")]
883 #[serde(alias = "Apple GPU (M3)", alias = "apple gpu (m3)", alias = "M3", alias = "m3")]
884 AppleM3,
885 #[display("Apple GPU (M4)")]
887 #[serde(alias = "Apple GPU (M4)", alias = "apple gpu (m4)", alias = "M4", alias = "m4")]
888 AppleM4,
889 #[display("Apple GPU (M5)")]
891 #[serde(alias = "Apple GPU (M5)", alias = "apple gpu (m5)", alias = "M5", alias = "m5")]
892 AppleM5,
893 #[display("Blackwell")]
895 #[serde(alias = "blackwell", alias = "GB100", alias = "gb100", alias = "GB200", alias = "gb200")]
896 Blackwell,
897 #[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 #[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 #[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 #[display("CDNA4")]
937 #[serde(alias = "CDNA 4", alias = "cdna4", alias = "cdna 4", alias = "MI350", alias = "mi350")]
938 Cdna4,
939 #[display("Fermi")]
943 #[serde(alias = "fermi", alias = "GF100", alias = "gf100", alias = "GF110", alias = "gf110")]
944 Fermi,
945 #[display("Hopper")]
947 #[serde(alias = "hopper", alias = "GH100", alias = "gh100", alias = "GH200", alias = "gh200")]
948 Hopper,
949 #[display("Kepler")]
951 #[serde(alias = "kepler", alias = "GK110", alias = "gk110")]
952 Kepler,
953 #[display("Maxwell")]
955 #[serde(alias = "maxwell", alias = "GM200", alias = "gm200")]
956 Maxwell,
957 #[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 #[display("Pascal")]
975 #[serde(alias = "pascal", alias = "GP100", alias = "gp100")]
976 Pascal,
977 #[display("RDNA1")]
979 #[serde(alias = "RDNA1", alias = "RDNA 1", alias = "rdna1", alias = "RDNA1", alias = "rdna 1")]
980 Rdna1,
981 #[display("RDNA2")]
983 #[serde(alias = "RDNA2", alias = "RDNA 2", alias = "rdna2", alias = "RDNA2", alias = "rdna 2")]
984 Rdna2,
985 #[display("RDNA3")]
987 #[serde(alias = "RDNA3", alias = "RDNA 3", alias = "rdna3", alias = "RDNA3", alias = "rdna 3")]
988 Rdna3,
989 #[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 #[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 #[display("Turing")]
1021 #[serde(alias = "turing", alias = "TU102", alias = "tu102")]
1022 Turing,
1023 #[display("Volta")]
1025 #[serde(alias = "volta", alias = "GV100", alias = "gv100")]
1026 Volta,
1027 #[display("Xe")]
1029 #[serde(alias = "xe", alias = "Xe HPG", alias = "xe hpg", alias = "Xe-HPG", alias = "xe-hpg")]
1030 Xe,
1031 #[display("Xe2")]
1033 #[serde(alias = "Battlemage", alias = "battlemage", alias = "xe2")]
1034 Xe2,
1035 #[display("Xe3")]
1037 #[serde(alias = "Celestial", alias = "celestial", alias = "xe3")]
1038 Xe3,
1039 #[display("{}", _0)]
1041 Other(String),
1042}
1043#[derive(Clone, Debug, Serialize, JsonSchema)]
1045pub enum Resource {
1046 ASIC {
1050 #[serde(alias = "arch")]
1052 architecture: Option<CpuArchitecture>,
1053 count: Option<u32>,
1055 purpose: Option<String>,
1057 required: Option<bool>,
1059 vendor: Option<Vendor>,
1061 },
1062 CPU {
1064 #[serde(alias = "arch")]
1066 architecture: Option<CpuArchitecture>,
1067 cores: Option<u32>,
1069 count: Option<u32>,
1071 #[serde(alias = "ram")]
1073 memory: Option<Memory>,
1074 required: Option<bool>,
1076 threads: Option<u32>,
1078 vendor: Option<Vendor>,
1080 },
1081 DPU {
1085 #[serde(alias = "arch")]
1087 architecture: Option<CpuArchitecture>,
1088 count: Option<u32>,
1090 #[serde(alias = "mem")]
1092 memory: Option<Memory>,
1093 required: Option<bool>,
1095 vendor: Option<Vendor>,
1097 },
1098 DSP {
1102 #[serde(alias = "arch")]
1104 architecture: Option<DspArchitecture>,
1105 count: Option<u32>,
1107 #[serde(alias = "freq")]
1109 frequency: Option<u32>,
1110 required: Option<bool>,
1112 vendor: Option<Vendor>,
1114 },
1115 FPGA {
1121 #[serde(alias = "arch")]
1123 architecture: Option<FpgaArchitecture>,
1124 count: Option<u32>,
1126 logic_elements: Option<u32>,
1128 #[serde(alias = "mem")]
1130 memory: Option<Memory>,
1131 required: Option<bool>,
1133 vendor: Option<Vendor>,
1135 },
1136 GPU {
1138 #[serde(alias = "arch")]
1140 architecture: Option<GpuArchitecture>,
1141 backend: Option<Backend>,
1143 compute_capability: Option<f32>,
1145 count: Option<u32>,
1147 #[serde(alias = "vram")]
1149 memory: Option<Memory>,
1150 name: Option<String>,
1152 required: Option<bool>,
1154 vendor: Option<Vendor>,
1156 },
1157 NPU {
1161 #[serde(alias = "arch")]
1163 architecture: Option<AcceleratorArchitecture>,
1164 count: Option<u32>,
1166 #[serde(alias = "mem")]
1168 memory: Option<Memory>,
1169 required: Option<bool>,
1171 vendor: Option<Vendor>,
1173 },
1174 Neuromorphic {
1176 count: Option<u32>,
1178 #[serde(alias = "mem")]
1180 memory: Option<Memory>,
1181 model: Option<String>,
1183 neurons: Option<u64>,
1185 required: Option<bool>,
1187 synapses: Option<u64>,
1189 vendor: Option<Vendor>,
1191 },
1192 Quantum {
1194 count: Option<u32>,
1196 model: Option<Model>,
1198 paradigm: Option<Paradigm>,
1200 qubits: Option<u32>,
1202 required: Option<bool>,
1204 topology: Option<Topology>,
1206 vendor: Option<Vendor>,
1208 },
1209 Sensor {
1211 count: Option<u32>,
1213 modality: Option<Vec<SensorModality>>,
1215 model: Option<String>,
1217 #[serde(alias = "regime", alias = "quantum", alias = "quantumRegime", alias = "quantum regime")]
1219 quantum_regime: Option<Regime>,
1220 required: Option<bool>,
1222 #[serde(alias = "samplingRate", alias = "sampling_rate")]
1224 sampling_rate: Option<f32>,
1225 vendor: Option<Vendor>,
1227 },
1228 TPU {
1230 #[serde(alias = "arch")]
1232 architecture: Option<AcceleratorArchitecture>,
1233 count: Option<u32>,
1235 #[serde(alias = "mem")]
1237 memory: Option<Memory>,
1238 required: Option<bool>,
1240 vendor: Option<Vendor>,
1242 },
1243 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>("ed).ok().map(Architecture::from),
1252 serde_json::from_str::<GpuArchitecture>("ed).ok().map(Architecture::from),
1253 serde_json::from_str::<FpgaArchitecture>("ed).ok().map(Architecture::from),
1254 serde_json::from_str::<AcceleratorArchitecture>("ed).ok().map(Architecture::from),
1255 serde_json::from_str::<DspArchitecture>("ed).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 #[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;