Skip to content

Commit b02c97b

Browse files
committed
feat: detect core type for AuthenticAMD
Currently enabling the "Core Type" option in AMD cpus results in an "unknown" label for each core. Implement detection of X3D cores and frequency cores by inspecting the cpu model name and L3 cache topology.
1 parent 392b56f commit b02c97b

3 files changed

Lines changed: 90 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu
349349
| `control=` | Sets up a unix socket with a specific name that can be connected to with mangohud-control.<br>I.e. `control=mangohud` or `control=mangohud-%p` (`%p` will be replaced by process id) |
350350
| `core_load_change` | Change the colors of cpu core loads, uses the same data from `cpu_load_value` and `cpu_load_change` |
351351
| `core_load` | Display load & frequency per core |
352-
| `core_type` | Display CPU core type per core. For Intel, it shows which cores are performance and efficient cores, for ARM it shows core codenames like A52, A53, A76, etc... |
352+
| `core_type` | Display CPU core type per core. For Intel, it shows which cores are performance and efficient cores; on AMD, it shows which cores are X3D or frequency cores; on ARM, it shows core codenames like A52, A53, A76 etc... |
353353
| `core_bars` | Change the display of `core_load` from numbers to vertical bars |
354354
| `cpu_load_change` | Change the color of the CPU load depending on load |
355355
| `cpu_load_color` | Set the colors for the gpu load change low, medium and high. e.g `cpu_load_color=0000FF,00FFFF,FF00FF` |

src/cpu.cpp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,8 @@ void CPUStats::get_cpu_cores_types() {
826826

827827
if (vendor == "GenuineIntel")
828828
get_cpu_cores_types_intel();
829+
else if (vendor == "AuthenticAMD")
830+
get_cpu_cores_types_amd();
829831
#endif
830832

831833
#if defined(__arm__) || defined(__aarch64__)
@@ -875,6 +877,92 @@ void CPUStats::get_cpu_cores_types_intel() {
875877
}
876878
}
877879

880+
void CPUStats::get_cpu_cores_types_amd() {
881+
static const char* LABEL_X3D = "X3D";
882+
static const char* LABEL_FREQ = "Freq";
883+
bool is_x3d_cpu = false;
884+
{
885+
std::ifstream cpuinfo(PROCCPUINFOFILE);
886+
for (std::string line; std::getline(cpuinfo, line);) {
887+
if (line.rfind("model name", 0) == 0) {
888+
is_x3d_cpu = line.find("X3D") != std::string::npos;
889+
break;
890+
}
891+
}
892+
}
893+
894+
std::string base_label = is_x3d_cpu ? LABEL_X3D : LABEL_FREQ;
895+
for (auto& cpu : m_cpuData)
896+
cpu.label = base_label;
897+
898+
SPDLOG_DEBUG("get_cpu_cores_types_amd: base label = {}", base_label);
899+
900+
std::map<int, unsigned long> ccd_l3_size;
901+
std::map<int, std::vector<size_t>> ccd_to_indices;
902+
903+
// enumerate CCDs and L3 sizes
904+
for (size_t i = 0; i < m_cpuData.size(); i++) {
905+
int cpu_id = m_cpuData[i].cpu_id;
906+
std::string base = "/sys/devices/system/cpu/cpu" + std::to_string(cpu_id);
907+
908+
std::string ccd_id_str = read_line(base + "/cache/index3/id");
909+
if (ccd_id_str.empty()) {
910+
SPDLOG_WARN("get_cpu_cores_types_amd: failed to read L3 cache id for cpu{}", cpu_id);
911+
continue;
912+
}
913+
914+
int ccd_id;
915+
try {
916+
ccd_id = std::stoi(ccd_id_str);
917+
} catch (...) {
918+
SPDLOG_WARN("get_cpu_cores_types_amd: invalid L3 cache id '{}' for cpu{}", ccd_id_str, cpu_id);
919+
continue;
920+
}
921+
922+
ccd_to_indices[ccd_id].push_back(i);
923+
924+
if (ccd_l3_size.count(ccd_id))
925+
continue;
926+
927+
std::string size_str = read_line(base + "/cache/index3/size");
928+
if (size_str.empty())
929+
continue;
930+
931+
unsigned long size_kb;
932+
try {
933+
size_kb = std::stoul(size_str);
934+
} catch (...) {
935+
continue;
936+
}
937+
938+
ccd_l3_size[ccd_id] = size_kb;
939+
}
940+
941+
// Single-CCD, use the base label
942+
if (ccd_l3_size.size() < 2)
943+
return;
944+
945+
// Compare CCDs L3 sizes
946+
auto max_it = std::max_element(ccd_l3_size.begin(), ccd_l3_size.end(),
947+
[](const auto& a, const auto& b) { return a.second < b.second; });
948+
auto min_it = std::min_element(ccd_l3_size.begin(), ccd_l3_size.end(),
949+
[](const auto& a, const auto& b) { return a.second < b.second; });
950+
951+
// All CCDs have the same L3 size, use base label
952+
if (max_it->second == min_it->second)
953+
return;
954+
955+
// Different L3 sizes per CCD, label which CCD is X3D
956+
for (auto& [ccd_id, indices] : ccd_to_indices) {
957+
std::string label = (ccd_id == max_it->first) ? LABEL_X3D : LABEL_FREQ;
958+
for (size_t idx : indices) {
959+
m_cpuData[idx].label = label;
960+
SPDLOG_DEBUG("get_cpu_cores_types_amd: cpu{} ccd{} -> {}",
961+
m_cpuData[idx].cpu_id, ccd_id, label);
962+
}
963+
}
964+
}
965+
878966
void CPUStats::get_cpu_cores_types_arm() {
879967
std::ifstream cpuinfo(PROCCPUINFOFILE);
880968

src/cpu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ class CPUStats
185185
void get_cpu_cores_types();
186186
void get_cpu_cores_types_intel();
187187
void get_cpu_cores_types_arm();
188+
void get_cpu_cores_types_amd();
188189

189190
const std::vector<CPUData>& GetCPUData() const {
190191
return m_cpuData;

0 commit comments

Comments
 (0)