mirror of
https://github.com/openhardwaremonitor/openhardwaremonitor
synced 2025-08-22 09:57:20 +00:00
205 lines
6.5 KiB
C#
205 lines
6.5 KiB
C#
/*
|
|
|
|
This Source Code Form is subject to the terms of the Mozilla Public
|
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
Copyright (C) 2009-2020 Michael Möller <mmoeller@openhardwaremonitor.org>
|
|
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Text;
|
|
|
|
namespace OpenHardwareMonitor.Hardware.CPU {
|
|
|
|
internal class CPUGroup : IGroup {
|
|
private readonly List<GenericCPU> hardware = new List<GenericCPU>();
|
|
|
|
private readonly CPUID[][][] threads;
|
|
|
|
private static CPUID[][] GetProcessorThreads() {
|
|
|
|
List<CPUID> threads = new List<CPUID>();
|
|
for (int i = 0; i < ThreadAffinity.ProcessorGroupCount; i++) {
|
|
for (int j = 0; j < 64; j++) {
|
|
try {
|
|
if (!ThreadAffinity.IsValid(GroupAffinity.Single((ushort)i, j)))
|
|
continue;
|
|
var cpuid = CPUID.Get(i, j);
|
|
if (cpuid != null)
|
|
threads.Add(cpuid);
|
|
} catch (ArgumentOutOfRangeException) {
|
|
}
|
|
}
|
|
}
|
|
|
|
SortedDictionary<uint, List<CPUID>> processors =
|
|
new SortedDictionary<uint, List<CPUID>>();
|
|
foreach (CPUID thread in threads) {
|
|
List<CPUID> list;
|
|
processors.TryGetValue(thread.ProcessorId, out list);
|
|
if (list == null) {
|
|
list = new List<CPUID>();
|
|
processors.Add(thread.ProcessorId, list);
|
|
}
|
|
list.Add(thread);
|
|
}
|
|
|
|
CPUID[][] processorThreads = new CPUID[processors.Count][];
|
|
int index = 0;
|
|
foreach (List<CPUID> list in processors.Values) {
|
|
processorThreads[index] = list.ToArray();
|
|
index++;
|
|
}
|
|
return processorThreads;
|
|
}
|
|
|
|
private static CPUID[][] GroupThreadsByCore(IEnumerable<CPUID> threads) {
|
|
|
|
SortedDictionary<uint, List<CPUID>> cores =
|
|
new SortedDictionary<uint, List<CPUID>>();
|
|
foreach (CPUID thread in threads) {
|
|
List<CPUID> coreList;
|
|
cores.TryGetValue(thread.CoreId, out coreList);
|
|
if (coreList == null) {
|
|
coreList = new List<CPUID>();
|
|
cores.Add(thread.CoreId, coreList);
|
|
}
|
|
coreList.Add(thread);
|
|
}
|
|
|
|
CPUID[][] coreThreads = new CPUID[cores.Count][];
|
|
int index = 0;
|
|
foreach (List<CPUID> list in cores.Values) {
|
|
coreThreads[index] = list.ToArray();
|
|
index++;
|
|
}
|
|
return coreThreads;
|
|
}
|
|
|
|
public CPUGroup(ISettings settings) {
|
|
|
|
CPUID[][] processorThreads = GetProcessorThreads();
|
|
this.threads = new CPUID[processorThreads.Length][][];
|
|
|
|
int index = 0;
|
|
foreach (CPUID[] threads in processorThreads) {
|
|
if (threads.Length == 0)
|
|
continue;
|
|
|
|
CPUID[][] coreThreads = GroupThreadsByCore(threads);
|
|
|
|
this.threads[index] = coreThreads;
|
|
|
|
switch (threads[0].Vendor) {
|
|
case Vendor.Intel:
|
|
hardware.Add(new IntelCPU(index, coreThreads, settings));
|
|
break;
|
|
case Vendor.AMD:
|
|
switch (threads[0].Family) {
|
|
case 0x0F:
|
|
hardware.Add(new AMD0FCPU(index, coreThreads, settings));
|
|
break;
|
|
case 0x10:
|
|
case 0x11:
|
|
case 0x12:
|
|
case 0x14:
|
|
case 0x15:
|
|
case 0x16:
|
|
hardware.Add(new AMD10CPU(index, coreThreads, settings));
|
|
break;
|
|
case 0x17:
|
|
hardware.Add(new AMD17CPU(index, coreThreads, settings));
|
|
break;
|
|
default:
|
|
hardware.Add(new GenericCPU(index, coreThreads, settings));
|
|
break;
|
|
} break;
|
|
default:
|
|
hardware.Add(new GenericCPU(index, coreThreads, settings));
|
|
break;
|
|
}
|
|
|
|
index++;
|
|
}
|
|
}
|
|
|
|
public IHardware[] Hardware {
|
|
get {
|
|
return hardware.ToArray();
|
|
}
|
|
}
|
|
|
|
private static void AppendCpuidData(StringBuilder r, uint[,] data,
|
|
uint offset)
|
|
{
|
|
for (int i = 0; i < data.GetLength(0); i++) {
|
|
r.Append(" ");
|
|
r.Append((i + offset).ToString("X8", CultureInfo.InvariantCulture));
|
|
for (int j = 0; j < 4; j++) {
|
|
r.Append(" ");
|
|
r.Append(data[i, j].ToString("X8", CultureInfo.InvariantCulture));
|
|
}
|
|
r.AppendLine();
|
|
}
|
|
}
|
|
|
|
public string GetReport() {
|
|
if (threads == null)
|
|
return null;
|
|
|
|
StringBuilder r = new StringBuilder();
|
|
|
|
r.AppendLine("CPUID");
|
|
r.AppendLine();
|
|
|
|
for (int i = 0; i < threads.Length; i++) {
|
|
|
|
r.AppendLine("Processor " + i);
|
|
r.AppendLine();
|
|
r.AppendFormat("Processor Vendor: {0}{1}", threads[i][0][0].Vendor,
|
|
Environment.NewLine);
|
|
r.AppendFormat("Processor Brand: {0}{1}", threads[i][0][0].BrandString,
|
|
Environment.NewLine);
|
|
r.AppendFormat("Family: 0x{0}{1}",
|
|
threads[i][0][0].Family.ToString("X", CultureInfo.InvariantCulture),
|
|
Environment.NewLine);
|
|
r.AppendFormat("Model: 0x{0}{1}",
|
|
threads[i][0][0].Model.ToString("X", CultureInfo.InvariantCulture),
|
|
Environment.NewLine);
|
|
r.AppendFormat("Stepping: 0x{0}{1}",
|
|
threads[i][0][0].Stepping.ToString("X", CultureInfo.InvariantCulture),
|
|
Environment.NewLine);
|
|
r.AppendLine();
|
|
|
|
r.AppendLine("CPUID Return Values");
|
|
r.AppendLine();
|
|
for (int j = 0; j < threads[i].Length; j++)
|
|
for (int k = 0; k < threads[i][j].Length; k++) {
|
|
r.AppendLine(" CPU Group: " + threads[i][j][k].Group);
|
|
r.AppendLine(" CPU Thread: " + threads[i][j][k].Thread);
|
|
r.AppendLine(" APIC ID: " + threads[i][j][k].ApicId);
|
|
r.AppendLine(" Processor ID: " + threads[i][j][k].ProcessorId);
|
|
r.AppendLine(" Core ID: " + threads[i][j][k].CoreId);
|
|
r.AppendLine(" Thread ID: " + threads[i][j][k].ThreadId);
|
|
r.AppendLine();
|
|
r.AppendLine(" Function EAX EBX ECX EDX");
|
|
AppendCpuidData(r, threads[i][j][k].Data, CPUID.CPUID_0);
|
|
AppendCpuidData(r, threads[i][j][k].ExtData, CPUID.CPUID_EXT);
|
|
r.AppendLine();
|
|
}
|
|
}
|
|
return r.ToString();
|
|
}
|
|
|
|
public void Close() {
|
|
foreach (GenericCPU cpu in hardware) {
|
|
cpu.Close();
|
|
}
|
|
}
|
|
}
|
|
}
|