mirror of
https://github.com/Dr-Noob/cpufetch.git
synced 2026-03-25 07:50:40 +01:00
382 lines
23 KiB
C
382 lines
23 KiB
C
#include <stdbool.h>
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <inttypes.h>
|
||
|
||
#include "uarch.h"
|
||
#include "../common/global.h"
|
||
|
||
// Data not available
|
||
#define NA -1
|
||
|
||
typedef uint32_t ISA;
|
||
|
||
struct uarch {
|
||
MICROARCH uarch;
|
||
ISA isa;
|
||
char* uarch_str;
|
||
char* isa_str;
|
||
// int32_t process; process depends on SoC
|
||
};
|
||
|
||
enum {
|
||
ISA_ARMv6,
|
||
ISA_ARMv6_T2,
|
||
ISA_ARMv6_KZ,
|
||
ISA_ARMv6_K,
|
||
ISA_ARMv7_A,
|
||
ISA_ARMv8_A,
|
||
ISA_ARMv8_A_AArch32,
|
||
ISA_ARMv8_1_A,
|
||
ISA_ARMv8_2_A,
|
||
ISA_ARMv8_3_A,
|
||
ISA_ARMv8_4_A,
|
||
ISA_ARMv8_5_A,
|
||
ISA_ARMv8_6_A,
|
||
ISA_ARMv9_A
|
||
};
|
||
|
||
static const ISA isas_uarch[] = {
|
||
[UARCH_ARM1136] = ISA_ARMv6,
|
||
[UARCH_ARM1156] = ISA_ARMv6_T2,
|
||
[UARCH_ARM1176] = ISA_ARMv6_KZ,
|
||
[UARCH_ARM11MPCORE] = ISA_ARMv6_K,
|
||
[UARCH_CORTEX_A5] = ISA_ARMv7_A,
|
||
[UARCH_CORTEX_A7] = ISA_ARMv7_A,
|
||
[UARCH_CORTEX_A8] = ISA_ARMv7_A,
|
||
[UARCH_CORTEX_A9] = ISA_ARMv7_A,
|
||
[UARCH_CORTEX_A12] = ISA_ARMv7_A,
|
||
[UARCH_CORTEX_A15] = ISA_ARMv7_A,
|
||
[UARCH_CORTEX_A17] = ISA_ARMv7_A,
|
||
[UARCH_CORTEX_A32] = ISA_ARMv8_A_AArch32,
|
||
[UARCH_CORTEX_A35] = ISA_ARMv8_A,
|
||
[UARCH_CORTEX_A53] = ISA_ARMv8_A,
|
||
[UARCH_CORTEX_A55r0] = ISA_ARMv8_2_A,
|
||
[UARCH_CORTEX_A55] = ISA_ARMv8_2_A,
|
||
[UARCH_CORTEX_A57] = ISA_ARMv8_A,
|
||
[UARCH_CORTEX_A65] = ISA_ARMv8_2_A,
|
||
[UARCH_CORTEX_A72] = ISA_ARMv8_A,
|
||
[UARCH_CORTEX_A73] = ISA_ARMv8_A,
|
||
[UARCH_CORTEX_A75] = ISA_ARMv8_2_A,
|
||
[UARCH_CORTEX_A76] = ISA_ARMv8_2_A,
|
||
[UARCH_CORTEX_A77] = ISA_ARMv8_2_A,
|
||
[UARCH_CORTEX_A78] = ISA_ARMv8_2_A,
|
||
[UARCH_CORTEX_A510] = ISA_ARMv9_A,
|
||
[UARCH_CORTEX_A710] = ISA_ARMv9_A,
|
||
[UARCH_CORTEX_A715] = ISA_ARMv9_A,
|
||
[UARCH_CORTEX_X1] = ISA_ARMv8_2_A,
|
||
[UARCH_CORTEX_X2] = ISA_ARMv9_A,
|
||
[UARCH_CORTEX_X3] = ISA_ARMv9_A,
|
||
[UARCH_NEOVERSE_N1] = ISA_ARMv8_2_A,
|
||
[UARCH_NEOVERSE_E1] = ISA_ARMv8_2_A,
|
||
[UARCH_NEOVERSE_V1] = ISA_ARMv8_4_A,
|
||
[UARCH_BRAHMA_B15] = ISA_ARMv7_A, // Same as Cortex-A15
|
||
[UARCH_BRAHMA_B53] = ISA_ARMv8_A, // Same as Cortex-A53
|
||
[UARCH_THUNDERX] = ISA_ARMv8_A,
|
||
[UARCH_THUNDERX2] = ISA_ARMv8_1_A,
|
||
[UARCH_TAISHAN_V110] = ISA_ARMv8_2_A,
|
||
[UARCH_TAISHAN_V120] = ISA_ARMv8_2_A, // Not confirmed
|
||
[UARCH_TAISHAN_V200] = ISA_ARMv8_2_A, // Not confirmed
|
||
[UARCH_DENVER] = ISA_ARMv8_A,
|
||
[UARCH_DENVER2] = ISA_ARMv8_A,
|
||
[UARCH_CARMEL] = ISA_ARMv8_A,
|
||
[UARCH_XGENE] = ISA_ARMv8_A, // https://en.wikichip.org/wiki/apm/x-gene
|
||
[UARCH_SCORPION] = ISA_ARMv7_A, // https://www.geektopia.es/es/product/qualcomm/snapdragon-s3-apq8060/
|
||
[UARCH_KRAIT] = ISA_ARMv7_A,
|
||
[UARCH_KYRO] = ISA_ARMv8_A,
|
||
[UARCH_FALKOR] = ISA_ARMv8_A,
|
||
[UARCH_SAPHIRA] = ISA_ARMv8_3_A,
|
||
[UARCH_EXYNOS_M1] = ISA_ARMv8_A,
|
||
[UARCH_EXYNOS_M2] = ISA_ARMv8_A,
|
||
[UARCH_EXYNOS_M3] = ISA_ARMv8_A,
|
||
[UARCH_EXYNOS_M4] = ISA_ARMv8_2_A,
|
||
[UARCH_EXYNOS_M5] = ISA_ARMv8_2_A,
|
||
[UARCH_ICESTORM] = ISA_ARMv8_5_A, // https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/Support/AArch64TargetParser.def
|
||
[UARCH_FIRESTORM] = ISA_ARMv8_5_A,
|
||
[UARCH_BLIZZARD] = ISA_ARMv8_6_A, // https://github.com/llvm/llvm-project/blob/main/llvm/unittests/TargetParser/TargetParserTest.cpp
|
||
[UARCH_AVALANCHE] = ISA_ARMv8_6_A, // https://github.com/llvm/llvm-project/blob/main/llvm/unittests/TargetParser/TargetParserTest.cpp
|
||
[UARCH_SAWTOOTH] = ISA_ARMv8_6_A, // https://github.com/llvm/llvm-project/blob/main/llvm/unittests/TargetParser/TargetParserTest.cpp
|
||
[UARCH_EVEREST] = ISA_ARMv8_6_A, // https://github.com/llvm/llvm-project/blob/main/llvm/unittests/TargetParser/TargetParserTest.cpp
|
||
[UARCH_PJ4] = ISA_ARMv7_A,
|
||
[UARCH_XIAOMI] = ISA_ARMv8_A,
|
||
};
|
||
|
||
static char* isas_string[] = {
|
||
[ISA_ARMv6] = "ARMv6",
|
||
[ISA_ARMv6_T2] = "ARMv6T2",
|
||
[ISA_ARMv6_KZ] = "ARMv6KZ",
|
||
[ISA_ARMv6_K] = "ARMv6K",
|
||
[ISA_ARMv7_A] = "ARMv7",
|
||
[ISA_ARMv8_A] = "ARMv8",
|
||
[ISA_ARMv8_A_AArch32] = "ARMv8 AArch32",
|
||
[ISA_ARMv8_1_A] = "ARMv8.1",
|
||
[ISA_ARMv8_2_A] = "ARMv8.2",
|
||
[ISA_ARMv8_3_A] = "ARMv8.3",
|
||
[ISA_ARMv8_4_A] = "ARMv8.4",
|
||
[ISA_ARMv8_5_A] = "ARMv8.5",
|
||
[ISA_ARMv8_6_A] = "ARMv8.6",
|
||
[ISA_ARMv9_A] = "ARMv9"
|
||
};
|
||
|
||
#define UARCH_START if (false) {}
|
||
#define CHECK_UARCH(arch, cpu, im_, p_, v_, r_, str, uarch, vendor) \
|
||
else if (im_ == im && p_ == p && (v_ == NA || v_ == v) && (r_ == NA || r_ == r)) fill_uarch(arch, cpu, str, uarch, vendor);
|
||
#define UARCH_END else { printBugCheckRelease("Unknown microarchitecture detected: IM=0x%X P=0x%X V=0x%X R=0x%X", im, p, v, r); \
|
||
fill_uarch(arch, cpu, "Unknown", UARCH_UNKNOWN, CPU_VENDOR_UNKNOWN); }
|
||
|
||
void fill_uarch(struct uarch* arch, struct cpuInfo* cpu, char* str, MICROARCH u, VENDOR vendor) {
|
||
arch->uarch = u;
|
||
arch->isa = isas_uarch[arch->uarch];
|
||
cpu->cpu_vendor = vendor;
|
||
|
||
arch->uarch_str = emalloc(sizeof(char) * (strlen(str)+1));
|
||
strcpy(arch->uarch_str, str);
|
||
|
||
arch->isa_str = emalloc(sizeof(char) * (strlen(isas_string[arch->isa])+1));
|
||
strcpy(arch->isa_str, isas_string[arch->isa]);
|
||
}
|
||
|
||
/*
|
||
* Codes are based on pytorch/cpuinfo, more precisely:
|
||
* - https://github.com/pytorch/cpuinfo/blob/main/src/arm/uarch.c
|
||
* Other sources:
|
||
* - https://elixir.bootlin.com/linux/latest/source/arch/arm64/include/asm/cputype.h
|
||
* - https://elixir.bootlin.com/linux/latest/source/arch/arm/include/asm/cputype.h
|
||
* - https://github.com/AsahiLinux/m1n1/blob/main/src/chickens.c
|
||
*/
|
||
struct uarch* get_uarch_from_midr(uint32_t midr, struct cpuInfo* cpu) {
|
||
struct uarch* arch = emalloc(sizeof(struct uarch));
|
||
uint32_t im = midr_get_implementer(midr);
|
||
uint32_t p = midr_get_part(midr);
|
||
uint32_t v = midr_get_variant(midr);
|
||
uint32_t r = midr_get_revision(midr);
|
||
|
||
// ----------------------------------------------------------------------- //
|
||
// IM: Implementer //
|
||
// P: Part //
|
||
// V: Variant //
|
||
// R: Revision //
|
||
// ----------------------------------------------------------------------- //
|
||
// IM P V R //
|
||
UARCH_START
|
||
CHECK_UARCH(arch, cpu, 'A', 0xB36, NA, NA, "ARM1136", UARCH_ARM1136, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xB56, NA, NA, "ARM1156", UARCH_ARM1156, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xB76, NA, NA, "ARM1176", UARCH_ARM1176, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xB02, NA, NA, "ARM11 MPCore", UARCH_ARM11MPCORE, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xC05, NA, NA, "Cortex-A5", UARCH_CORTEX_A5, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xC07, NA, NA, "Cortex-A7", UARCH_CORTEX_A7, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xC08, NA, NA, "Cortex-A8", UARCH_CORTEX_A8, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xC09, NA, NA, "Cortex-A9", UARCH_CORTEX_A9, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xC0C, NA, NA, "Cortex-A12", UARCH_CORTEX_A12, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xC0E, NA, NA, "Cortex-A17", UARCH_CORTEX_A17, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xC0D, NA, NA, "Cortex-A12", UARCH_CORTEX_A12, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xC0F, NA, NA, "Cortex-A15", UARCH_CORTEX_A15, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD01, NA, NA, "Cortex-A32", UARCH_CORTEX_A32, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD03, NA, NA, "Cortex-A53", UARCH_CORTEX_A53, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD04, NA, NA, "Cortex-A35", UARCH_CORTEX_A35, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD05, NA, 0, "Cortex-A55", UARCH_CORTEX_A55r0, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD05, NA, NA, "Cortex-A55", UARCH_CORTEX_A55, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD06, NA, NA, "Cortex-A65", UARCH_CORTEX_A65, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD07, NA, NA, "Cortex-A57", UARCH_CORTEX_A57, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD08, NA, NA, "Cortex-A72", UARCH_CORTEX_A72, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD09, NA, NA, "Cortex-A73", UARCH_CORTEX_A73, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD0A, NA, NA, "Cortex-A75", UARCH_CORTEX_A75, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD0B, NA, NA, "Cortex-A76", UARCH_CORTEX_A76, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD0C, NA, NA, "Neoverse N1", UARCH_NEOVERSE_N1, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD0D, NA, NA, "Cortex-A77", UARCH_CORTEX_A77, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD0E, NA, NA, "Cortex-A76", UARCH_CORTEX_A76, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD40, NA, NA, "Neoverse V1", UARCH_NEOVERSE_V1, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD41, NA, NA, "Cortex-A78", UARCH_CORTEX_A78, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD44, NA, NA, "Cortex-X1", UARCH_CORTEX_X1, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD46, NA, NA, "Cortex‑A510", UARCH_CORTEX_A510, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD47, NA, NA, "Cortex‑A710", UARCH_CORTEX_A710, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD48, NA, NA, "Cortex-X2", UARCH_CORTEX_X2, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD4A, NA, NA, "Neoverse E1", UARCH_NEOVERSE_E1, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD4D, NA, NA, "Cortex-A715", UARCH_CORTEX_A715, CPU_VENDOR_ARM)
|
||
CHECK_UARCH(arch, cpu, 'A', 0xD4E, NA, NA, "Cortex-X3", UARCH_CORTEX_X3, CPU_VENDOR_ARM)
|
||
|
||
CHECK_UARCH(arch, cpu, 'B', 0x00F, NA, NA, "Brahma B15", UARCH_BRAHMA_B15, CPU_VENDOR_BROADCOM)
|
||
CHECK_UARCH(arch, cpu, 'B', 0x100, NA, NA, "Brahma B53", UARCH_BRAHMA_B53, CPU_VENDOR_BROADCOM)
|
||
CHECK_UARCH(arch, cpu, 'B', 0x516, NA, NA, "ThunderX2", UARCH_THUNDERX2, CPU_VENDOR_CAVIUM)
|
||
|
||
CHECK_UARCH(arch, cpu, 'C', 0x0A0, NA, NA, "ThunderX", UARCH_THUNDERX, CPU_VENDOR_CAVIUM)
|
||
CHECK_UARCH(arch, cpu, 'C', 0x0A1, NA, NA, "ThunderX 88XX", UARCH_THUNDERX, CPU_VENDOR_CAVIUM)
|
||
CHECK_UARCH(arch, cpu, 'C', 0x0A2, NA, NA, "ThunderX 81XX", UARCH_THUNDERX, CPU_VENDOR_CAVIUM)
|
||
CHECK_UARCH(arch, cpu, 'C', 0x0A3, NA, NA, "ThunderX 81XX", UARCH_THUNDERX, CPU_VENDOR_CAVIUM)
|
||
CHECK_UARCH(arch, cpu, 'C', 0x0AF, NA, NA, "ThunderX2 99XX", UARCH_THUNDERX2, CPU_VENDOR_CAVIUM)
|
||
|
||
CHECK_UARCH(arch, cpu, 'H', 0xD01, NA, NA, "TaiShan v110", UARCH_TAISHAN_V110, CPU_VENDOR_HUAWEI) // Kunpeng 920 series
|
||
CHECK_UARCH(arch, cpu, 'H', 0xD02, 2, 2, "TaiShan v120", UARCH_TAISHAN_V120, CPU_VENDOR_HUAWEI) // Kiring 9000S Big cores (https://github.com/Dr-Noob/cpufetch/issues/259)
|
||
CHECK_UARCH(arch, cpu, 'H', 0xD02, NA, NA, "TaiShan v200", UARCH_TAISHAN_V200, CPU_VENDOR_HUAWEI) // Kunpeng 930 series (found in openeuler: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/XQCV7NX2UKRIUWUFKRF4PO3QENCOUFR3)
|
||
CHECK_UARCH(arch, cpu, 'H', 0xD40, NA, NA, "Cortex-A76", UARCH_CORTEX_A76, CPU_VENDOR_ARM) // Kirin 980 Big/Medium cores -> Cortex-A76
|
||
CHECK_UARCH(arch, cpu, 'H', 0xD42, NA, NA, "TaiShan v120", UARCH_TAISHAN_V120, CPU_VENDOR_HUAWEI) // Kiring 9000S Small Cores (https://github.com/Dr-Noob/cpufetch/issues/259)
|
||
|
||
CHECK_UARCH(arch, cpu, 'N', 0x000, NA, NA, "Denver", UARCH_DENVER, CPU_VENDOR_NVIDIA)
|
||
CHECK_UARCH(arch, cpu, 'N', 0x003, NA, NA, "Denver2", UARCH_DENVER2, CPU_VENDOR_NVIDIA)
|
||
CHECK_UARCH(arch, cpu, 'N', 0x004, NA, NA, "Carmel", UARCH_CARMEL, CPU_VENDOR_NVIDIA)
|
||
|
||
CHECK_UARCH(arch, cpu, 'P', 0x000, NA, NA, "Xgene", UARCH_XGENE, CPU_VENDOR_APM)
|
||
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x00F, NA, NA, "Scorpion", UARCH_SCORPION, CPU_VENDOR_QUALCOMM)
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x02D, NA, NA, "Scorpion", UARCH_KRAIT, CPU_VENDOR_QUALCOMM)
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x04D, 1, 0, "Krait 200", UARCH_KRAIT, CPU_VENDOR_QUALCOMM)
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x04D, 1, 4, "Krait 200", UARCH_KRAIT, CPU_VENDOR_QUALCOMM)
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x04D, 2, 0, "Krait 300", UARCH_KRAIT, CPU_VENDOR_QUALCOMM)
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x06F, 0, 1, "Krait 200", UARCH_KRAIT, CPU_VENDOR_QUALCOMM)
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x06F, 0, 2, "Krait 200", UARCH_KRAIT, CPU_VENDOR_QUALCOMM)
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x06F, 1, 0, "Krait 300", UARCH_KRAIT, CPU_VENDOR_QUALCOMM)
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x06F, 2, 0, "Krait 400", UARCH_KRAIT, CPU_VENDOR_QUALCOMM) // Snapdragon 800 MSMxxxx
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x06F, 2, 1, "Krait 400", UARCH_KRAIT, CPU_VENDOR_QUALCOMM) // Snapdragon 801 MSMxxxxPRO
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x06F, 3, 1, "Krait 450", UARCH_KRAIT, CPU_VENDOR_QUALCOMM)
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x201, NA, NA, "Kryo Silver", UARCH_KYRO, CPU_VENDOR_QUALCOMM) // Qualcomm Snapdragon 821: Low-power Kryo "Silver"
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x205, NA, NA, "Kryo Gold", UARCH_KYRO, CPU_VENDOR_QUALCOMM) // Qualcomm Snapdragon 820 & 821: High-performance Kryo "Gold"
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x211, NA, NA, "Kryo Silver", UARCH_KYRO, CPU_VENDOR_QUALCOMM) // Qualcomm Snapdragon 820: Low-power Kryo "Silver"
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x800, 10, NA, "Kryo 260 / 280 Gold", UARCH_CORTEX_A73, CPU_VENDOR_ARM) // Kryo 260 / Kryo 280 "Gold"
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x801, 10, NA, "Kryo 260 / 280 Silver", UARCH_CORTEX_A53, CPU_VENDOR_ARM) // Kryo 260 / 280 "Silver"
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x802, NA, NA, "Kryo 385 Gold", UARCH_CORTEX_A75, CPU_VENDOR_ARM) // High-performance Kryo 385 "Gold" -> Cortex-A75
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x803, NA, NA, "Kryo 385 Silver", UARCH_CORTEX_A55r0, CPU_VENDOR_ARM) // Low-power Kryo 385 "Silver" -> Cortex-A55r0
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x804, NA, NA, "Kryo 485 Gold", UARCH_CORTEX_A76, CPU_VENDOR_ARM) // High-performance Kryo 485 "Gold" / "Gold Prime" -> Cortex-A76
|
||
CHECK_UARCH(arch, cpu, 'Q', 0x805, NA, NA, "Kryo 485 Silver", UARCH_CORTEX_A55, CPU_VENDOR_ARM) // Low-performance Kryo 485 "Silver" -> Cortex-A55
|
||
CHECK_UARCH(arch, cpu, 'Q', 0xC00, NA, NA, "Falkor", UARCH_FALKOR, CPU_VENDOR_QUALCOMM)
|
||
CHECK_UARCH(arch, cpu, 'Q', 0xC01, NA, NA, "Saphira", UARCH_SAPHIRA, CPU_VENDOR_QUALCOMM)
|
||
|
||
CHECK_UARCH(arch, cpu, 'S', 0x001, 1, NA, "Exynos M1", UARCH_EXYNOS_M1, CPU_VENDOR_SAMSUNG) // Exynos 8890
|
||
CHECK_UARCH(arch, cpu, 'S', 0x001, 4, NA, "Exynos M2", UARCH_EXYNOS_M2, CPU_VENDOR_SAMSUNG) // Exynos 8895
|
||
CHECK_UARCH(arch, cpu, 'S', 0x002, 1, NA, "Exynos M3", UARCH_EXYNOS_M3, CPU_VENDOR_SAMSUNG) // Exynos 9810
|
||
CHECK_UARCH(arch, cpu, 'S', 0x003, 1, NA, "Exynos M4", UARCH_EXYNOS_M4, CPU_VENDOR_SAMSUNG) // Exynos 9820
|
||
CHECK_UARCH(arch, cpu, 'S', 0x004, 1, NA, "Exynos M5", UARCH_EXYNOS_M5, CPU_VENDOR_SAMSUNG) // Exynos 9820 (this one looks wrong at uarch.c ...)
|
||
|
||
CHECK_UARCH(arch, cpu, 'p', 0x663, 1, NA, "Xiaomi", UARCH_XIAOMI, CPU_VENDOR_PHYTIUM) // From a fellow contributor (https://github.com/Dr-Noob/cpufetch/issues/125)
|
||
// Also interesting: https://en.wikipedia.org/wiki/FeiTeng_(processor)
|
||
|
||
CHECK_UARCH(arch, cpu, 'a', 0x022, NA, NA, "Icestorm", UARCH_ICESTORM, CPU_VENDOR_APPLE)
|
||
CHECK_UARCH(arch, cpu, 'a', 0x023, NA, NA, "Firestorm", UARCH_FIRESTORM, CPU_VENDOR_APPLE)
|
||
CHECK_UARCH(arch, cpu, 'a', 0x024, NA, NA, "Icestorm", UARCH_ICESTORM, CPU_VENDOR_APPLE) // https://github.com/Dr-Noob/cpufetch/issues/263
|
||
CHECK_UARCH(arch, cpu, 'a', 0x025, NA, NA, "Firestorm", UARCH_FIRESTORM, CPU_VENDOR_APPLE) // https://github.com/Dr-Noob/cpufetch/issues/263
|
||
CHECK_UARCH(arch, cpu, 'a', 0x030, NA, NA, "Blizzard", UARCH_BLIZZARD, CPU_VENDOR_APPLE)
|
||
CHECK_UARCH(arch, cpu, 'a', 0x031, NA, NA, "Avalanche", UARCH_AVALANCHE, CPU_VENDOR_APPLE)
|
||
CHECK_UARCH(arch, cpu, 'a', 0x048, NA, NA, "Sawtooth", UARCH_SAWTOOTH, CPU_VENDOR_APPLE)
|
||
CHECK_UARCH(arch, cpu, 'a', 0x049, NA, NA, "Everest", UARCH_EVEREST, CPU_VENDOR_APPLE)
|
||
|
||
CHECK_UARCH(arch, cpu, 'V', 0x581, NA, NA, "PJ4", UARCH_PJ4, CPU_VENDOR_MARVELL)
|
||
CHECK_UARCH(arch, cpu, 'V', 0x584, NA, NA, "PJ4B-MP", UARCH_PJ4, CPU_VENDOR_MARVELL)
|
||
|
||
UARCH_END
|
||
|
||
return arch;
|
||
}
|
||
|
||
bool is_ARMv8_or_newer(struct cpuInfo* cpu) {
|
||
return cpu->arch->isa == ISA_ARMv8_A ||
|
||
cpu->arch->isa == ISA_ARMv8_A_AArch32 ||
|
||
cpu->arch->isa == ISA_ARMv8_1_A ||
|
||
cpu->arch->isa == ISA_ARMv8_2_A ||
|
||
cpu->arch->isa == ISA_ARMv8_3_A ||
|
||
cpu->arch->isa == ISA_ARMv8_4_A ||
|
||
cpu->arch->isa == ISA_ARMv8_5_A ||
|
||
cpu->arch->isa == ISA_ARMv8_6_A ||
|
||
cpu->arch->isa == ISA_ARMv9_A;
|
||
}
|
||
|
||
bool has_fma_support(struct cpuInfo* cpu) {
|
||
// Arm A64 Instruction Set Architecture
|
||
// https://developer.arm.com/documentation/ddi0596/2021-12/SIMD-FP-Instructions
|
||
return is_ARMv8_or_newer(cpu);
|
||
}
|
||
|
||
int get_vpus_width(struct cpuInfo* cpu) {
|
||
// If the CPU has NEON, width can be 64 or 128 [1].
|
||
// In >= ARMv8, NEON are 128 bits width [2]
|
||
// If the CPU has SVE/SVE2, width can be between 128-2048 [3],
|
||
// so we must check the exact width depending on
|
||
// the exact chip (Neoverse V1 uses 256b implementations.)
|
||
//
|
||
// [1] https://en.wikipedia.org/wiki/ARM_architecture_family#Advanced_SIMD_(Neon)
|
||
// [2] https://developer.arm.com/documentation/102474/0100/Fundamentals-of-Armv8-Neon-technology
|
||
// [3] https://www.anandtech.com/show/16640/arm-announces-neoverse-v1-n2-platforms-cpus-cmn700-mesh/5
|
||
|
||
MICROARCH ua = cpu->arch->uarch;
|
||
switch(ua) {
|
||
case UARCH_NEOVERSE_V1:
|
||
return 256;
|
||
default:
|
||
if (cpu->feat->SVE && cpu->feat->cntb > 0) {
|
||
return cpu->feat->cntb * 8;
|
||
}
|
||
else if (cpu->feat->NEON) {
|
||
if(is_ARMv8_or_newer(cpu)) {
|
||
return 128;
|
||
}
|
||
else {
|
||
return 64;
|
||
}
|
||
}
|
||
else {
|
||
return 32;
|
||
}
|
||
}
|
||
}
|
||
|
||
int get_number_of_vpus(struct cpuInfo* cpu) {
|
||
MICROARCH ua = cpu->arch->uarch;
|
||
|
||
switch(ua) {
|
||
case UARCH_EVEREST: // Just a guess, needs confirmation.
|
||
case UARCH_FIRESTORM: // [https://dougallj.github.io/applecpu/firestorm-simd.html]
|
||
case UARCH_AVALANCHE: // [https://en.wikipedia.org/wiki/Comparison_of_ARM_processors]
|
||
case UARCH_CORTEX_X1: // [https://www.anandtech.com/show/15813/arm-cortex-a78-cortex-x1-cpu-ip-diverging/3]
|
||
case UARCH_CORTEX_X2: // [https://www.anandtech.com/show/16693/arm-announces-mobile-armv9-cpu-microarchitectures-cortexx2-cortexa710-cortexa510/2]
|
||
case UARCH_CORTEX_X3: // [https://www.hwcooling.net/en/cortex-x3-the-new-fastest-arm-core-architecture-analysis: "The FPU and SIMD unit of the core still has four pipelines"]
|
||
case UARCH_NEOVERSE_V1: // [https://en.wikichip.org/wiki/arm_holdings/microarchitectures/neoverse_v1]
|
||
return 4;
|
||
case UARCH_SAWTOOTH: // Needs confirmation, rn this is the best we know: https://mastodon.social/@dougall/111118317031041336
|
||
case UARCH_EXYNOS_M3: // [https://www.anandtech.com/show/12361/samsung-exynos-m3-architecture]
|
||
case UARCH_EXYNOS_M4: // [https://en.wikichip.org/wiki/samsung/microarchitectures/m4#Block_Diagram]
|
||
case UARCH_EXYNOS_M5: // [https://en.wikichip.org/wiki/samsung/microarchitectures/m5]
|
||
return 3;
|
||
case UARCH_ICESTORM: // [https://dougallj.github.io/applecpu/icestorm-simd.html]
|
||
case UARCH_BLIZZARD: // [https://en.wikipedia.org/wiki/Comparison_of_ARM_processors]
|
||
case UARCH_TAISHAN_V110:// [https://www-file.huawei.com/-/media/corp2020/pdf/publications/huawei-research/2022/huawei-research-issue1-en.pdf]: "128-bit x 2 for single precision"
|
||
case UARCH_TAISHAN_V120:// Not confirmed, asssuming same as v110
|
||
case UARCH_TAISHAN_V200:// Not confirmed, asssuming same as v110
|
||
case UARCH_CORTEX_A57: // [https://www.anandtech.com/show/8718/the-samsung-galaxy-note-4-exynos-review/5]
|
||
case UARCH_CORTEX_A72: // [https://www.anandtech.com/show/10347/arm-cortex-a73-artemis-unveiled/2]
|
||
case UARCH_CORTEX_A73: // [https://www.anandtech.com/show/10347/arm-cortex-a73-artemis-unveiled/2]
|
||
case UARCH_CORTEX_A75: // [https://www.anandtech.com/show/11441/dynamiq-and-arms-new-cpus-cortex-a75-a55/3]
|
||
case UARCH_CORTEX_A76: // [https://www.anandtech.com/show/12785/arm-cortex-a76-cpu-unveiled-7nm-powerhouse/3]
|
||
case UARCH_CORTEX_A77: // [https://fuse.wikichip.org/news/2339/arm-unveils-cortex-a77-emphasizes-single-thread-performance]
|
||
case UARCH_CORTEX_A78: // [https://fuse.wikichip.org/news/3536/arm-unveils-the-cortex-a78-when-less-is-more]
|
||
case UARCH_EXYNOS_M1: // [https://www.anandtech.com/show/12361/samsung-exynos-m3-architecture]
|
||
case UARCH_EXYNOS_M2: // [https://www.anandtech.com/show/12361/samsung-exynos-m3-architecture]
|
||
case UARCH_NEOVERSE_N1: // [https://en.wikichip.org/wiki/arm_holdings/microarchitectures/neoverse_n1#Individual_Core]
|
||
case UARCH_CORTEX_A710: // [https://chipsandcheese.com/2023/08/11/arms-cortex-a710-winning-by-default/]: Fig in Core Overview. Table in Instruction Scheduling and Execution
|
||
case UARCH_CORTEX_A715: // [https://www.hwcooling.net/en/arm-introduces-new-cortex-a715-core-architecture-analysis/]: "the numbers of ALU and FPU execution units themselves >
|
||
return 2;
|
||
case UARCH_NEOVERSE_E1: // [https://www.anandtech.com/show/13959/arm-announces-neoverse-n1-platform/5]
|
||
// A510 is integrated as part of a Complex. Normally, each complex would incorporate two Cortex-A510 cores.
|
||
// Each complex incorporates a single VPU with 2 ports, so for each A510 there is theoretically 1 port.
|
||
case UARCH_CORTEX_A510: // [https://en.wikichip.org/wiki/arm_holdings/microarchitectures/cortex-a510#Vector_Processing_Unit_.28VPU.29]
|
||
return 1;
|
||
default:
|
||
// ARMv6
|
||
// ARMv7
|
||
// Remaining UARCH_CORTEX_AXX
|
||
// Old Snapdragon (e.g., Scorpion, Krait, etc)
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
char* get_str_uarch(struct cpuInfo* cpu) {
|
||
return cpu->arch->uarch_str;
|
||
}
|
||
|
||
MICROARCH get_uarch(struct uarch* arch) {
|
||
return arch->uarch;
|
||
}
|
||
|
||
void free_uarch_struct(struct uarch* arch) {
|
||
free(arch->uarch_str);
|
||
free(arch);
|
||
}
|