Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu
| `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) |
| `core_load_change` | Change the colors of cpu core loads, uses the same data from `cpu_load_value` and `cpu_load_change` |
| `core_load` | Display load & frequency per core |
| `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... |
| `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... |
| `core_bars` | Change the display of `core_load` from numbers to vertical bars |
| `cpu_load_change` | Change the color of the CPU load depending on load |
| `cpu_load_color` | Set the colors for the gpu load change low, medium and high. e.g `cpu_load_color=0000FF,00FFFF,FF00FF` |
Expand Down
86 changes: 86 additions & 0 deletions src/cpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,8 @@ void CPUStats::get_cpu_cores_types() {

if (vendor == "GenuineIntel")
get_cpu_cores_types_intel();
else if (vendor == "AuthenticAMD")
get_cpu_cores_types_amd();
#endif

#if defined(__arm__) || defined(__aarch64__)
Expand Down Expand Up @@ -875,6 +877,90 @@ void CPUStats::get_cpu_cores_types_intel() {
}
}

void CPUStats::get_cpu_cores_types_amd() {
static const char* LABEL_X3D = "X3D";
static const char* LABEL_FREQ = "Freq";
static auto const is_x3d_cpu = []() -> bool {
std::ifstream cpuinfo(PROCCPUINFOFILE);
for (std::string line; std::getline(cpuinfo, line);) {
if (starts_with(line, "model name") and line.find("X3D") != std::string::npos)
return true;
}
return false;
}();

static auto const base_label = is_x3d_cpu ? LABEL_X3D : LABEL_FREQ;

SPDLOG_DEBUG("get_cpu_cores_types_amd: base label = {}", base_label);

std::map<int, unsigned long> ccd_l3_size;
std::map<int, std::vector<size_t>> ccd_to_indices;

// enumerate CCDs and L3 sizes
for (size_t i = 0; i < m_cpuData.size(); i++) {
auto& cpu = m_cpuData[i];
cpu.label = base_label;
int cpu_id = cpu.cpu_id;
auto const base = "/sys/devices/system/cpu/cpu" + std::to_string(cpu_id);

auto const ccd_id_str = read_line(base + "/cache/index3/id");
if (ccd_id_str.empty()) {
SPDLOG_WARN("get_cpu_cores_types_amd: failed to read L3 cache id for cpu{}", cpu_id);
continue;
}

int ccd_id;
try {
ccd_id = std::stoi(ccd_id_str);
} catch (...) {
SPDLOG_WARN("get_cpu_cores_types_amd: invalid L3 cache id '{}' for cpu{}", ccd_id_str, cpu_id);
continue;
}

ccd_to_indices[ccd_id].push_back(i);

if (ccd_l3_size.count(ccd_id))
continue;

auto const size_str = read_line(base + "/cache/index3/size");
if (size_str.empty())
continue;

unsigned long size_kb;
try {
size_kb = std::stoul(size_str);
} catch (...) {
continue;
}

ccd_l3_size[ccd_id] = size_kb;
}

// Single-CCD, use the base label
if (ccd_l3_size.size() < 2)
return;

// Compare CCDs L3 sizes
auto max_it = std::max_element(ccd_l3_size.begin(), ccd_l3_size.end(),
[](const auto& a, const auto& b) { return a.second < b.second; });
auto min_it = std::min_element(ccd_l3_size.begin(), ccd_l3_size.end(),
[](const auto& a, const auto& b) { return a.second < b.second; });

// All CCDs have the same L3 size, use base label
if (max_it->second == min_it->second)
return;

// Different L3 sizes per CCD, label which CCD is X3D
for (auto& [ccd_id, indices] : ccd_to_indices) {
std::string label = (ccd_id == max_it->first) ? LABEL_X3D : LABEL_FREQ;
for (size_t idx : indices) {
m_cpuData[idx].label = label;
SPDLOG_DEBUG("get_cpu_cores_types_amd: cpu{} ccd{} -> {}",
m_cpuData[idx].cpu_id, ccd_id, label);
}
}
}

void CPUStats::get_cpu_cores_types_arm() {
std::ifstream cpuinfo(PROCCPUINFOFILE);

Expand Down
1 change: 1 addition & 0 deletions src/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ class CPUStats
void get_cpu_cores_types();
void get_cpu_cores_types_intel();
void get_cpu_cores_types_arm();
void get_cpu_cores_types_amd();

const std::vector<CPUData>& GetCPUData() const {
return m_cpuData;
Expand Down