moel@1: /* moel@1: moel@1: Version: MPL 1.1/GPL 2.0/LGPL 2.1 moel@1: moel@1: The contents of this file are subject to the Mozilla Public License Version moel@1: 1.1 (the "License"); you may not use this file except in compliance with moel@1: the License. You may obtain a copy of the License at moel@1: moel@1: http://www.mozilla.org/MPL/ moel@1: moel@1: Software distributed under the License is distributed on an "AS IS" basis, moel@1: WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License moel@1: for the specific language governing rights and limitations under the License. moel@1: moel@1: The Original Code is the Open Hardware Monitor code. moel@1: moel@1: The Initial Developer of the Original Code is moel@1: Michael Möller . moel@266: Portions created by the Initial Developer are Copyright (C) 2009-2011 moel@1: the Initial Developer. All Rights Reserved. moel@1: moel@1: Contributor(s): moel@1: moel@1: Alternatively, the contents of this file may be used under the terms of moel@1: either the GNU General Public License Version 2 or later (the "GPL"), or moel@1: the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), moel@1: in which case the provisions of the GPL or the LGPL are applicable instead moel@1: of those above. If you wish to allow use of your version of this file only moel@1: under the terms of either the GPL or the LGPL, and not to allow others to moel@1: use your version of this file under the terms of the MPL, indicate your moel@1: decision by deleting the provisions above and replace them with the notice moel@1: and other provisions required by the GPL or the LGPL. If you do not delete moel@1: the provisions above, a recipient may use your version of this file under moel@1: the terms of any one of the MPL, the GPL or the LGPL. moel@1: moel@1: */ moel@1: moel@1: using System; moel@1: using System.Collections.Generic; moel@166: using System.Globalization; moel@1: using System.Text; moel@1: moel@1: namespace OpenHardwareMonitor.Hardware.CPU { moel@1: moel@266: internal class CPUGroup : IGroup { moel@266: private readonly List hardware = new List(); moel@1: moel@195: private readonly CPUID[][][] threads; moel@1: moel@167: private static CPUID[][] GetProcessorThreads() { moel@1: moel@90: List threads = new List(); moel@90: for (int i = 0; i < 32; i++) { moel@90: try { moel@90: threads.Add(new CPUID(i)); moel@167: } catch (ArgumentOutOfRangeException) { } moel@90: } moel@1: moel@90: SortedDictionary> processors = moel@90: new SortedDictionary>(); moel@90: foreach (CPUID thread in threads) { moel@90: List list; moel@90: processors.TryGetValue(thread.ProcessorId, out list); moel@90: if (list == null) { moel@90: list = new List(); moel@90: processors.Add(thread.ProcessorId, list); moel@90: } moel@90: list.Add(thread); moel@90: } moel@90: moel@90: CPUID[][] processorThreads = new CPUID[processors.Count][]; moel@90: int index = 0; moel@90: foreach (List list in processors.Values) { moel@90: processorThreads[index] = list.ToArray(); moel@90: index++; moel@90: } moel@90: return processorThreads; moel@90: } moel@90: moel@195: private static CPUID[][] GroupThreadsByCore(IEnumerable threads) { moel@90: moel@90: SortedDictionary> cores = moel@90: new SortedDictionary>(); moel@90: foreach (CPUID thread in threads) { moel@90: List coreList; moel@90: cores.TryGetValue(thread.CoreId, out coreList); moel@90: if (coreList == null) { moel@90: coreList = new List(); moel@90: cores.Add(thread.CoreId, coreList); moel@90: } moel@90: coreList.Add(thread); moel@90: } moel@90: moel@90: CPUID[][] coreThreads = new CPUID[cores.Count][]; moel@90: int index = 0; moel@90: foreach (List list in cores.Values) { moel@90: coreThreads[index] = list.ToArray(); moel@90: index++; moel@90: } moel@90: return coreThreads; moel@1: } moel@1: moel@165: public CPUGroup(ISettings settings) { moel@1: moel@90: CPUID[][] processorThreads = GetProcessorThreads(); moel@90: this.threads = new CPUID[processorThreads.Length][][]; moel@1: moel@90: int index = 0; moel@90: foreach (CPUID[] threads in processorThreads) { moel@90: if (threads.Length == 0) moel@90: continue; moel@90: moel@90: CPUID[][] coreThreads = GroupThreadsByCore(threads); moel@1: moel@191: this.threads[index] = coreThreads; moel@1: moel@90: switch (threads[0].Vendor) { moel@90: case Vendor.Intel: moel@165: hardware.Add(new IntelCPU(index, coreThreads, settings)); moel@1: break; moel@90: case Vendor.AMD: moel@90: switch (threads[0].Family) { moel@90: case 0x0F: moel@165: hardware.Add(new AMD0FCPU(index, coreThreads, settings)); moel@90: break; moel@90: case 0x10: moel@251: case 0x11: moel@271: case 0x14: moel@165: hardware.Add(new AMD10CPU(index, coreThreads, settings)); moel@90: break; moel@90: default: moel@191: hardware.Add(new GenericCPU(index, coreThreads, settings)); moel@90: break; moel@90: } break; moel@1: default: moel@191: hardware.Add(new GenericCPU(index, coreThreads, settings)); moel@1: break; moel@101: } moel@101: moel@101: index++; moel@1: } moel@1: } moel@90: moel@1: public IHardware[] Hardware { moel@1: get { moel@1: return hardware.ToArray(); moel@1: } moel@1: } moel@1: moel@167: private static void AppendCpuidData(StringBuilder r, uint[,] data, moel@167: uint offset) moel@167: { moel@1: for (int i = 0; i < data.GetLength(0); i++) { moel@1: r.Append(" "); moel@166: r.Append((i + offset).ToString("X8", CultureInfo.InvariantCulture)); moel@1: for (int j = 0; j < 4; j++) { moel@1: r.Append(" "); moel@166: r.Append(data[i, j].ToString("X8", CultureInfo.InvariantCulture)); moel@1: } moel@1: r.AppendLine(); moel@1: } moel@1: } moel@1: moel@1: public string GetReport() { moel@125: if (threads == null) moel@125: return null; moel@125: moel@1: StringBuilder r = new StringBuilder(); moel@90: moel@1: r.AppendLine("CPUID"); moel@1: r.AppendLine(); moel@1: moel@90: for (int i = 0; i < threads.Length; i++) { moel@1: moel@90: r.AppendLine("Processor " + i); moel@18: r.AppendLine(); moel@90: r.AppendFormat("Processor Vendor: {0}{1}", threads[i][0][0].Vendor, moel@90: Environment.NewLine); moel@90: r.AppendFormat("Processor Brand: {0}{1}", threads[i][0][0].BrandString, moel@90: Environment.NewLine); moel@90: r.AppendFormat("Family: 0x{0}{1}", moel@166: threads[i][0][0].Family.ToString("X", CultureInfo.InvariantCulture), moel@166: Environment.NewLine); moel@166: r.AppendFormat("Model: 0x{0}{1}", moel@166: threads[i][0][0].Model.ToString("X", CultureInfo.InvariantCulture), moel@166: Environment.NewLine); moel@166: r.AppendFormat("Stepping: 0x{0}{1}", moel@166: threads[i][0][0].Stepping.ToString("X", CultureInfo.InvariantCulture), moel@166: Environment.NewLine); moel@90: r.AppendLine(); moel@90: moel@90: r.AppendLine("CPUID Return Values"); moel@90: r.AppendLine(); moel@90: for (int j = 0; j < threads[i].Length; j++) moel@90: for (int k = 0; k < threads[i][j].Length; k++) { moel@90: r.AppendLine(" CPU Thread: " + threads[i][j][k].Thread); moel@90: r.AppendLine(" APIC ID: " + threads[i][j][k].ApicId); moel@90: r.AppendLine(" Processor ID: " + threads[i][j][k].ProcessorId); moel@90: r.AppendLine(" Core ID: " + threads[i][j][k].CoreId); moel@90: r.AppendLine(" Thread ID: " + threads[i][j][k].ThreadId); moel@90: r.AppendLine(); moel@90: r.AppendLine(" Function EAX EBX ECX EDX"); moel@90: AppendCpuidData(r, threads[i][j][k].Data, CPUID.CPUID_0); moel@90: AppendCpuidData(r, threads[i][j][k].ExtData, CPUID.CPUID_EXT); moel@90: r.AppendLine(); moel@90: } moel@18: } moel@90: return r.ToString(); moel@1: } moel@1: moel@266: public void Close() { moel@266: foreach (GenericCPU cpu in hardware) { moel@266: cpu.Close(); moel@266: } moel@266: } moel@1: } moel@1: }