moel@1
|
1 |
/*
|
moel@1
|
2 |
|
moel@344
|
3 |
This Source Code Form is subject to the terms of the Mozilla Public
|
moel@344
|
4 |
License, v. 2.0. If a copy of the MPL was not distributed with this
|
moel@344
|
5 |
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
moel@1
|
6 |
|
moel@344
|
7 |
Copyright (C) 2009-2011 Michael Möller <mmoeller@openhardwaremonitor.org>
|
moel@344
|
8 |
|
moel@1
|
9 |
*/
|
moel@1
|
10 |
|
moel@1
|
11 |
using System;
|
moel@1
|
12 |
using System.Collections.Generic;
|
moel@166
|
13 |
using System.Globalization;
|
moel@1
|
14 |
using System.Text;
|
moel@1
|
15 |
|
moel@1
|
16 |
namespace OpenHardwareMonitor.Hardware.CPU {
|
moel@1
|
17 |
|
moel@266
|
18 |
internal class CPUGroup : IGroup {
|
moel@266
|
19 |
private readonly List<GenericCPU> hardware = new List<GenericCPU>();
|
moel@1
|
20 |
|
moel@195
|
21 |
private readonly CPUID[][][] threads;
|
moel@1
|
22 |
|
moel@167
|
23 |
private static CPUID[][] GetProcessorThreads() {
|
moel@1
|
24 |
|
moel@90
|
25 |
List<CPUID> threads = new List<CPUID>();
|
moel@90
|
26 |
for (int i = 0; i < 32; i++) {
|
moel@90
|
27 |
try {
|
moel@90
|
28 |
threads.Add(new CPUID(i));
|
moel@167
|
29 |
} catch (ArgumentOutOfRangeException) { }
|
moel@90
|
30 |
}
|
moel@1
|
31 |
|
moel@90
|
32 |
SortedDictionary<uint, List<CPUID>> processors =
|
moel@90
|
33 |
new SortedDictionary<uint, List<CPUID>>();
|
moel@90
|
34 |
foreach (CPUID thread in threads) {
|
moel@90
|
35 |
List<CPUID> list;
|
moel@90
|
36 |
processors.TryGetValue(thread.ProcessorId, out list);
|
moel@90
|
37 |
if (list == null) {
|
moel@90
|
38 |
list = new List<CPUID>();
|
moel@90
|
39 |
processors.Add(thread.ProcessorId, list);
|
moel@90
|
40 |
}
|
moel@90
|
41 |
list.Add(thread);
|
moel@90
|
42 |
}
|
moel@90
|
43 |
|
moel@90
|
44 |
CPUID[][] processorThreads = new CPUID[processors.Count][];
|
moel@90
|
45 |
int index = 0;
|
moel@90
|
46 |
foreach (List<CPUID> list in processors.Values) {
|
moel@90
|
47 |
processorThreads[index] = list.ToArray();
|
moel@90
|
48 |
index++;
|
moel@90
|
49 |
}
|
moel@90
|
50 |
return processorThreads;
|
moel@90
|
51 |
}
|
moel@90
|
52 |
|
moel@195
|
53 |
private static CPUID[][] GroupThreadsByCore(IEnumerable<CPUID> threads) {
|
moel@90
|
54 |
|
moel@90
|
55 |
SortedDictionary<uint, List<CPUID>> cores =
|
moel@90
|
56 |
new SortedDictionary<uint, List<CPUID>>();
|
moel@90
|
57 |
foreach (CPUID thread in threads) {
|
moel@90
|
58 |
List<CPUID> coreList;
|
moel@90
|
59 |
cores.TryGetValue(thread.CoreId, out coreList);
|
moel@90
|
60 |
if (coreList == null) {
|
moel@90
|
61 |
coreList = new List<CPUID>();
|
moel@90
|
62 |
cores.Add(thread.CoreId, coreList);
|
moel@90
|
63 |
}
|
moel@90
|
64 |
coreList.Add(thread);
|
moel@90
|
65 |
}
|
moel@90
|
66 |
|
moel@90
|
67 |
CPUID[][] coreThreads = new CPUID[cores.Count][];
|
moel@90
|
68 |
int index = 0;
|
moel@90
|
69 |
foreach (List<CPUID> list in cores.Values) {
|
moel@90
|
70 |
coreThreads[index] = list.ToArray();
|
moel@90
|
71 |
index++;
|
moel@90
|
72 |
}
|
moel@90
|
73 |
return coreThreads;
|
moel@1
|
74 |
}
|
moel@1
|
75 |
|
moel@165
|
76 |
public CPUGroup(ISettings settings) {
|
moel@1
|
77 |
|
moel@90
|
78 |
CPUID[][] processorThreads = GetProcessorThreads();
|
moel@90
|
79 |
this.threads = new CPUID[processorThreads.Length][][];
|
moel@1
|
80 |
|
moel@90
|
81 |
int index = 0;
|
moel@90
|
82 |
foreach (CPUID[] threads in processorThreads) {
|
moel@90
|
83 |
if (threads.Length == 0)
|
moel@90
|
84 |
continue;
|
moel@90
|
85 |
|
moel@90
|
86 |
CPUID[][] coreThreads = GroupThreadsByCore(threads);
|
moel@1
|
87 |
|
moel@191
|
88 |
this.threads[index] = coreThreads;
|
moel@1
|
89 |
|
moel@90
|
90 |
switch (threads[0].Vendor) {
|
moel@90
|
91 |
case Vendor.Intel:
|
moel@165
|
92 |
hardware.Add(new IntelCPU(index, coreThreads, settings));
|
moel@1
|
93 |
break;
|
moel@90
|
94 |
case Vendor.AMD:
|
moel@90
|
95 |
switch (threads[0].Family) {
|
moel@90
|
96 |
case 0x0F:
|
moel@165
|
97 |
hardware.Add(new AMD0FCPU(index, coreThreads, settings));
|
moel@90
|
98 |
break;
|
moel@90
|
99 |
case 0x10:
|
moel@251
|
100 |
case 0x11:
|
moel@301
|
101 |
case 0x12:
|
moel@271
|
102 |
case 0x14:
|
moel@301
|
103 |
case 0x15:
|
moel@165
|
104 |
hardware.Add(new AMD10CPU(index, coreThreads, settings));
|
moel@90
|
105 |
break;
|
moel@90
|
106 |
default:
|
moel@191
|
107 |
hardware.Add(new GenericCPU(index, coreThreads, settings));
|
moel@90
|
108 |
break;
|
moel@90
|
109 |
} break;
|
moel@1
|
110 |
default:
|
moel@191
|
111 |
hardware.Add(new GenericCPU(index, coreThreads, settings));
|
moel@1
|
112 |
break;
|
moel@101
|
113 |
}
|
moel@101
|
114 |
|
moel@101
|
115 |
index++;
|
moel@1
|
116 |
}
|
moel@1
|
117 |
}
|
moel@90
|
118 |
|
moel@1
|
119 |
public IHardware[] Hardware {
|
moel@1
|
120 |
get {
|
moel@1
|
121 |
return hardware.ToArray();
|
moel@1
|
122 |
}
|
moel@1
|
123 |
}
|
moel@1
|
124 |
|
moel@167
|
125 |
private static void AppendCpuidData(StringBuilder r, uint[,] data,
|
moel@167
|
126 |
uint offset)
|
moel@167
|
127 |
{
|
moel@1
|
128 |
for (int i = 0; i < data.GetLength(0); i++) {
|
moel@1
|
129 |
r.Append(" ");
|
moel@166
|
130 |
r.Append((i + offset).ToString("X8", CultureInfo.InvariantCulture));
|
moel@1
|
131 |
for (int j = 0; j < 4; j++) {
|
moel@1
|
132 |
r.Append(" ");
|
moel@166
|
133 |
r.Append(data[i, j].ToString("X8", CultureInfo.InvariantCulture));
|
moel@1
|
134 |
}
|
moel@1
|
135 |
r.AppendLine();
|
moel@1
|
136 |
}
|
moel@1
|
137 |
}
|
moel@1
|
138 |
|
moel@1
|
139 |
public string GetReport() {
|
moel@125
|
140 |
if (threads == null)
|
moel@125
|
141 |
return null;
|
moel@125
|
142 |
|
moel@1
|
143 |
StringBuilder r = new StringBuilder();
|
moel@90
|
144 |
|
moel@1
|
145 |
r.AppendLine("CPUID");
|
moel@1
|
146 |
r.AppendLine();
|
moel@1
|
147 |
|
moel@90
|
148 |
for (int i = 0; i < threads.Length; i++) {
|
moel@1
|
149 |
|
moel@90
|
150 |
r.AppendLine("Processor " + i);
|
moel@18
|
151 |
r.AppendLine();
|
moel@90
|
152 |
r.AppendFormat("Processor Vendor: {0}{1}", threads[i][0][0].Vendor,
|
moel@90
|
153 |
Environment.NewLine);
|
moel@90
|
154 |
r.AppendFormat("Processor Brand: {0}{1}", threads[i][0][0].BrandString,
|
moel@90
|
155 |
Environment.NewLine);
|
moel@90
|
156 |
r.AppendFormat("Family: 0x{0}{1}",
|
moel@166
|
157 |
threads[i][0][0].Family.ToString("X", CultureInfo.InvariantCulture),
|
moel@166
|
158 |
Environment.NewLine);
|
moel@166
|
159 |
r.AppendFormat("Model: 0x{0}{1}",
|
moel@166
|
160 |
threads[i][0][0].Model.ToString("X", CultureInfo.InvariantCulture),
|
moel@166
|
161 |
Environment.NewLine);
|
moel@166
|
162 |
r.AppendFormat("Stepping: 0x{0}{1}",
|
moel@166
|
163 |
threads[i][0][0].Stepping.ToString("X", CultureInfo.InvariantCulture),
|
moel@166
|
164 |
Environment.NewLine);
|
moel@90
|
165 |
r.AppendLine();
|
moel@90
|
166 |
|
moel@90
|
167 |
r.AppendLine("CPUID Return Values");
|
moel@90
|
168 |
r.AppendLine();
|
moel@90
|
169 |
for (int j = 0; j < threads[i].Length; j++)
|
moel@90
|
170 |
for (int k = 0; k < threads[i][j].Length; k++) {
|
moel@90
|
171 |
r.AppendLine(" CPU Thread: " + threads[i][j][k].Thread);
|
moel@90
|
172 |
r.AppendLine(" APIC ID: " + threads[i][j][k].ApicId);
|
moel@90
|
173 |
r.AppendLine(" Processor ID: " + threads[i][j][k].ProcessorId);
|
moel@90
|
174 |
r.AppendLine(" Core ID: " + threads[i][j][k].CoreId);
|
moel@90
|
175 |
r.AppendLine(" Thread ID: " + threads[i][j][k].ThreadId);
|
moel@90
|
176 |
r.AppendLine();
|
moel@90
|
177 |
r.AppendLine(" Function EAX EBX ECX EDX");
|
moel@90
|
178 |
AppendCpuidData(r, threads[i][j][k].Data, CPUID.CPUID_0);
|
moel@90
|
179 |
AppendCpuidData(r, threads[i][j][k].ExtData, CPUID.CPUID_EXT);
|
moel@90
|
180 |
r.AppendLine();
|
moel@90
|
181 |
}
|
moel@18
|
182 |
}
|
moel@90
|
183 |
return r.ToString();
|
moel@1
|
184 |
}
|
moel@1
|
185 |
|
moel@266
|
186 |
public void Close() {
|
moel@266
|
187 |
foreach (GenericCPU cpu in hardware) {
|
moel@266
|
188 |
cpu.Close();
|
moel@266
|
189 |
}
|
moel@266
|
190 |
}
|
moel@1
|
191 |
}
|
moel@1
|
192 |
}
|