Hardware/CPU/CPUGroup.cs
author moel.mich
Sun, 08 May 2011 22:10:13 +0000
changeset 279 6bce967ba1b5
parent 266 2687ac753d90
child 301 d14ce71cef44
permissions -rw-r--r--
Fixed the bus and core clock reading on AMD family 10h model Ah CPUs. The new "Core Performance Boost" feature of these CPUs resulted in very low accuracy of the bus speed (and as a consequence also an inaccurate TSC multiplier). This fixed Issue 205.
moel@1
     1
/*
moel@1
     2
  
moel@1
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@1
     4
moel@1
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@1
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@1
     7
  the License. You may obtain a copy of the License at
moel@1
     8
 
moel@1
     9
  http://www.mozilla.org/MPL/
moel@1
    10
moel@1
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@1
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@1
    13
  for the specific language governing rights and limitations under the License.
moel@1
    14
moel@1
    15
  The Original Code is the Open Hardware Monitor code.
moel@1
    16
moel@1
    17
  The Initial Developer of the Original Code is 
moel@1
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@266
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2011
moel@1
    20
  the Initial Developer. All Rights Reserved.
moel@1
    21
moel@1
    22
  Contributor(s):
moel@1
    23
moel@1
    24
  Alternatively, the contents of this file may be used under the terms of
moel@1
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@1
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@1
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@1
    28
  of those above. If you wish to allow use of your version of this file only
moel@1
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@1
    30
  use your version of this file under the terms of the MPL, indicate your
moel@1
    31
  decision by deleting the provisions above and replace them with the notice
moel@1
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@1
    33
  the provisions above, a recipient may use your version of this file under
moel@1
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@1
    35
 
moel@1
    36
*/
moel@1
    37
moel@1
    38
using System;
moel@1
    39
using System.Collections.Generic;
moel@166
    40
using System.Globalization;
moel@1
    41
using System.Text;
moel@1
    42
moel@1
    43
namespace OpenHardwareMonitor.Hardware.CPU {
moel@1
    44
moel@266
    45
  internal class CPUGroup : IGroup {
moel@266
    46
    private readonly List<GenericCPU> hardware = new List<GenericCPU>();
moel@1
    47
moel@195
    48
    private readonly CPUID[][][] threads;
moel@1
    49
moel@167
    50
    private static CPUID[][] GetProcessorThreads() {
moel@1
    51
moel@90
    52
      List<CPUID> threads = new List<CPUID>();
moel@90
    53
      for (int i = 0; i < 32; i++) {
moel@90
    54
        try {
moel@90
    55
          threads.Add(new CPUID(i));
moel@167
    56
        } catch (ArgumentOutOfRangeException) { }
moel@90
    57
      }
moel@1
    58
moel@90
    59
      SortedDictionary<uint, List<CPUID>> processors =
moel@90
    60
        new SortedDictionary<uint, List<CPUID>>();
moel@90
    61
      foreach (CPUID thread in threads) {
moel@90
    62
        List<CPUID> list;
moel@90
    63
        processors.TryGetValue(thread.ProcessorId, out list);
moel@90
    64
        if (list == null) {
moel@90
    65
          list = new List<CPUID>();
moel@90
    66
          processors.Add(thread.ProcessorId, list);
moel@90
    67
        }
moel@90
    68
        list.Add(thread);
moel@90
    69
      }
moel@90
    70
moel@90
    71
      CPUID[][] processorThreads = new CPUID[processors.Count][];
moel@90
    72
      int index = 0;
moel@90
    73
      foreach (List<CPUID> list in processors.Values) {
moel@90
    74
        processorThreads[index] = list.ToArray();
moel@90
    75
        index++;
moel@90
    76
      }
moel@90
    77
      return processorThreads;
moel@90
    78
    }
moel@90
    79
moel@195
    80
    private static CPUID[][] GroupThreadsByCore(IEnumerable<CPUID> threads) {
moel@90
    81
moel@90
    82
      SortedDictionary<uint, List<CPUID>> cores = 
moel@90
    83
        new SortedDictionary<uint, List<CPUID>>();
moel@90
    84
      foreach (CPUID thread in threads) {
moel@90
    85
        List<CPUID> coreList;
moel@90
    86
        cores.TryGetValue(thread.CoreId, out coreList);
moel@90
    87
        if (coreList == null) {
moel@90
    88
          coreList = new List<CPUID>();
moel@90
    89
          cores.Add(thread.CoreId, coreList);
moel@90
    90
        }
moel@90
    91
        coreList.Add(thread);
moel@90
    92
      }
moel@90
    93
moel@90
    94
      CPUID[][] coreThreads = new CPUID[cores.Count][];
moel@90
    95
      int index = 0;
moel@90
    96
      foreach (List<CPUID> list in cores.Values) {
moel@90
    97
        coreThreads[index] = list.ToArray();
moel@90
    98
        index++;
moel@90
    99
      }
moel@90
   100
      return coreThreads;
moel@1
   101
    }
moel@1
   102
moel@165
   103
    public CPUGroup(ISettings settings) {
moel@1
   104
moel@90
   105
      CPUID[][] processorThreads = GetProcessorThreads();
moel@90
   106
      this.threads = new CPUID[processorThreads.Length][][];
moel@1
   107
moel@90
   108
      int index = 0;
moel@90
   109
      foreach (CPUID[] threads in processorThreads) {
moel@90
   110
        if (threads.Length == 0)
moel@90
   111
          continue;
moel@90
   112
            
moel@90
   113
        CPUID[][] coreThreads = GroupThreadsByCore(threads);
moel@1
   114
moel@191
   115
        this.threads[index] = coreThreads;
moel@1
   116
moel@90
   117
        switch (threads[0].Vendor) {
moel@90
   118
          case Vendor.Intel:
moel@165
   119
            hardware.Add(new IntelCPU(index, coreThreads, settings));
moel@1
   120
            break;
moel@90
   121
          case Vendor.AMD:
moel@90
   122
            switch (threads[0].Family) {
moel@90
   123
              case 0x0F:
moel@165
   124
                hardware.Add(new AMD0FCPU(index, coreThreads, settings));
moel@90
   125
                break;
moel@90
   126
              case 0x10:
moel@251
   127
              case 0x11:
moel@271
   128
              case 0x14:
moel@165
   129
                hardware.Add(new AMD10CPU(index, coreThreads, settings));
moel@90
   130
                break;
moel@90
   131
              default:
moel@191
   132
                hardware.Add(new GenericCPU(index, coreThreads, settings));
moel@90
   133
                break;
moel@90
   134
            } break;
moel@1
   135
          default:
moel@191
   136
            hardware.Add(new GenericCPU(index, coreThreads, settings));
moel@1
   137
            break;
moel@101
   138
        }
moel@101
   139
moel@101
   140
        index++;
moel@1
   141
      }
moel@1
   142
    }
moel@90
   143
    
moel@1
   144
    public IHardware[] Hardware {
moel@1
   145
      get {
moel@1
   146
        return hardware.ToArray();
moel@1
   147
      }
moel@1
   148
    }
moel@1
   149
moel@167
   150
    private static void AppendCpuidData(StringBuilder r, uint[,] data, 
moel@167
   151
      uint offset) 
moel@167
   152
    {
moel@1
   153
      for (int i = 0; i < data.GetLength(0); i++) {
moel@1
   154
        r.Append(" ");
moel@166
   155
        r.Append((i + offset).ToString("X8", CultureInfo.InvariantCulture));
moel@1
   156
        for (int j = 0; j < 4; j++) {
moel@1
   157
          r.Append("  ");
moel@166
   158
          r.Append(data[i, j].ToString("X8", CultureInfo.InvariantCulture));
moel@1
   159
        }
moel@1
   160
        r.AppendLine();
moel@1
   161
      }
moel@1
   162
    }
moel@1
   163
moel@1
   164
    public string GetReport() {
moel@125
   165
      if (threads == null)
moel@125
   166
        return null;
moel@125
   167
      
moel@1
   168
      StringBuilder r = new StringBuilder();
moel@90
   169
      
moel@1
   170
      r.AppendLine("CPUID");
moel@1
   171
      r.AppendLine();
moel@1
   172
moel@90
   173
      for (int i = 0; i < threads.Length; i++) {
moel@1
   174
moel@90
   175
        r.AppendLine("Processor " + i);
moel@18
   176
        r.AppendLine();
moel@90
   177
        r.AppendFormat("Processor Vendor: {0}{1}", threads[i][0][0].Vendor,
moel@90
   178
          Environment.NewLine);
moel@90
   179
        r.AppendFormat("Processor Brand: {0}{1}", threads[i][0][0].BrandString,
moel@90
   180
          Environment.NewLine);
moel@90
   181
        r.AppendFormat("Family: 0x{0}{1}", 
moel@166
   182
          threads[i][0][0].Family.ToString("X", CultureInfo.InvariantCulture), 
moel@166
   183
          Environment.NewLine);
moel@166
   184
        r.AppendFormat("Model: 0x{0}{1}",
moel@166
   185
          threads[i][0][0].Model.ToString("X", CultureInfo.InvariantCulture), 
moel@166
   186
          Environment.NewLine);
moel@166
   187
        r.AppendFormat("Stepping: 0x{0}{1}",
moel@166
   188
          threads[i][0][0].Stepping.ToString("X", CultureInfo.InvariantCulture), 
moel@166
   189
          Environment.NewLine);
moel@90
   190
        r.AppendLine();
moel@90
   191
moel@90
   192
        r.AppendLine("CPUID Return Values");
moel@90
   193
        r.AppendLine();
moel@90
   194
        for (int j = 0; j < threads[i].Length; j++)
moel@90
   195
          for (int k = 0; k < threads[i][j].Length; k++) {
moel@90
   196
            r.AppendLine(" CPU Thread: " + threads[i][j][k].Thread);
moel@90
   197
            r.AppendLine(" APIC ID: " + threads[i][j][k].ApicId);
moel@90
   198
            r.AppendLine(" Processor ID: " + threads[i][j][k].ProcessorId);
moel@90
   199
            r.AppendLine(" Core ID: " + threads[i][j][k].CoreId);
moel@90
   200
            r.AppendLine(" Thread ID: " + threads[i][j][k].ThreadId);
moel@90
   201
            r.AppendLine();
moel@90
   202
            r.AppendLine(" Function  EAX       EBX       ECX       EDX");
moel@90
   203
            AppendCpuidData(r, threads[i][j][k].Data, CPUID.CPUID_0);
moel@90
   204
            AppendCpuidData(r, threads[i][j][k].ExtData, CPUID.CPUID_EXT);
moel@90
   205
            r.AppendLine();
moel@90
   206
          }
moel@18
   207
      }
moel@90
   208
      return r.ToString(); 
moel@1
   209
    }
moel@1
   210
moel@266
   211
    public void Close() {
moel@266
   212
      foreach (GenericCPU cpu in hardware) {
moel@266
   213
        cpu.Close();
moel@266
   214
      }
moel@266
   215
    }
moel@1
   216
  }
moel@1
   217
}