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