Hardware/CPU/IntelCPU.cs
changeset 219 ce04404774d6
parent 201 958e9fe8afdf
child 236 763675f19ff4
     1.1 --- a/Hardware/CPU/IntelCPU.cs	Fri Oct 08 12:18:32 2010 +0000
     1.2 +++ b/Hardware/CPU/IntelCPU.cs	Sun Oct 10 16:57:11 2010 +0000
     1.3 @@ -36,16 +36,25 @@
     1.4  */
     1.5  
     1.6  using System;
     1.7 -using System.Collections.Generic;
     1.8 +using System.Globalization;
     1.9 +using System.Text;
    1.10  
    1.11  namespace OpenHardwareMonitor.Hardware.CPU {
    1.12    internal sealed class IntelCPU : GenericCPU {
    1.13  
    1.14 +    private enum Microarchitecture {
    1.15 +      Unknown,
    1.16 +      Core,
    1.17 +      Atom,
    1.18 +      Nehalem
    1.19 +    }
    1.20 +
    1.21      private readonly Sensor[] coreTemperatures;
    1.22      private readonly Sensor[] coreClocks;
    1.23      private readonly Sensor busClock;
    1.24  
    1.25 -    private readonly uint maxNehalemMultiplier;
    1.26 +    private readonly Microarchitecture microarchitecture;
    1.27 +    private readonly double timeStampCounterMultiplier;
    1.28  
    1.29      private const uint IA32_THERM_STATUS_MSR = 0x019C;
    1.30      private const uint IA32_TEMPERATURE_TARGET = 0x01A2;
    1.31 @@ -62,11 +71,13 @@
    1.32      public IntelCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
    1.33        : base(processorIndex, cpuid, settings) 
    1.34      {
    1.35 +      // set tjMax
    1.36        float[] tjMax;
    1.37        switch (family) {
    1.38          case 0x06: {
    1.39              switch (model) {
    1.40 -              case 0x0F: // Intel Core (65nm)
    1.41 +              case 0x0F: // Intel Core 2 (65nm)
    1.42 +                microarchitecture = Microarchitecture.Core;
    1.43                  switch (stepping) {
    1.44                    case 0x06: // B2
    1.45                      switch (coreCount) {
    1.46 @@ -85,9 +96,11 @@
    1.47                    default:
    1.48                      tjMax = Floats(85 + 10); break;
    1.49                  } break;
    1.50 -              case 0x17: // Intel Core (45nm)
    1.51 +              case 0x17: // Intel Core 2 (45nm)
    1.52 +                microarchitecture = Microarchitecture.Core;
    1.53                  tjMax = Floats(100); break;
    1.54                case 0x1C: // Intel Atom (45nm)
    1.55 +                microarchitecture = Microarchitecture.Atom;
    1.56                  switch (stepping) {
    1.57                    case 0x02: // C0
    1.58                      tjMax = Floats(90); break;
    1.59 @@ -100,6 +113,7 @@
    1.60                case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)
    1.61                case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)
    1.62                case 0x2C: // Intel Core i7 LGA1366 (32nm) 6 Core
    1.63 +                microarchitecture = Microarchitecture.Nehalem;
    1.64                  uint eax, edx;
    1.65                  tjMax = new float[coreCount];
    1.66                  for (int i = 0; i < coreCount; i++) {
    1.67 @@ -109,16 +123,39 @@
    1.68                    } else {
    1.69                      tjMax[i] = 100;
    1.70                    }
    1.71 -                }
    1.72 -                if (WinRing0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) {
    1.73 -                  maxNehalemMultiplier = (eax >> 8) & 0xff;
    1.74 -                }
    1.75 +                }                
    1.76                  break;
    1.77                default:
    1.78 -                tjMax = Floats(100); break;
    1.79 +                microarchitecture = Microarchitecture.Unknown;
    1.80 +                tjMax = Floats(100); 
    1.81 +                break;
    1.82              }
    1.83            } break;
    1.84 -        default: tjMax = Floats(100); break;
    1.85 +        default:
    1.86 +          microarchitecture = Microarchitecture.Unknown;
    1.87 +          tjMax = Floats(100); 
    1.88 +          break;
    1.89 +      }
    1.90 +
    1.91 +      // set timeStampCounterMultiplier
    1.92 +      switch (microarchitecture) {
    1.93 +        case Microarchitecture.Atom:
    1.94 +        case Microarchitecture.Core: {
    1.95 +            uint eax, edx;
    1.96 +            if (WinRing0.Rdmsr(IA32_PERF_STATUS, out eax, out edx)) {
    1.97 +              timeStampCounterMultiplier = 
    1.98 +                ((edx >> 8) & 0x1f) + 0.5 * ((edx >> 14) & 1);
    1.99 +            }
   1.100 +          } break;
   1.101 +        case Microarchitecture.Nehalem: {
   1.102 +            uint eax, edx;
   1.103 +            if (WinRing0.Rdmsr(MSR_PLATFORM_INFO, out eax, out edx)) {
   1.104 +              timeStampCounterMultiplier = (eax >> 8) & 0xff;
   1.105 +            }
   1.106 +          } break;
   1.107 +        default:
   1.108 +          timeStampCounterMultiplier = 1;
   1.109 +          break;
   1.110        }
   1.111  
   1.112        // check if processor supports a digital thermal sensor
   1.113 @@ -161,6 +198,18 @@
   1.114        };
   1.115      }
   1.116  
   1.117 +    public override string GetReport() {
   1.118 +      StringBuilder r = new StringBuilder();
   1.119 +      r.Append(base.GetReport());
   1.120 +
   1.121 +      r.Append("Time Stamp Counter Multiplier: ");
   1.122 +      r.AppendLine(timeStampCounterMultiplier.ToString(
   1.123 +        CultureInfo.InvariantCulture));
   1.124 +      r.AppendLine();
   1.125 +
   1.126 +      return r.ToString();
   1.127 +    }
   1.128 +
   1.129      public override void Update() {
   1.130        base.Update();
   1.131  
   1.132 @@ -188,27 +237,18 @@
   1.133          for (int i = 0; i < coreClocks.Length; i++) {
   1.134            System.Threading.Thread.Sleep(1);
   1.135            if (WinRing0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
   1.136 -            (UIntPtr)(1L << cpuid[i][0].Thread))) {
   1.137 -            if (maxNehalemMultiplier > 0) { // Core i3, i5, i7
   1.138 -              uint nehalemMultiplier = eax & 0xff;
   1.139 -              coreClocks[i].Value =(float)(nehalemMultiplier * 
   1.140 -                TimeStampCounterFrequency / maxNehalemMultiplier);
   1.141 -              newBusClock = 
   1.142 -                (float)(TimeStampCounterFrequency / maxNehalemMultiplier);
   1.143 -            } else { // Core 2
   1.144 -              uint multiplier = (eax >> 8) & 0x1f;
   1.145 -              uint maxMultiplier = (edx >> 8) & 0x1f;
   1.146 -              // factor = multiplier * 2 to handle non integer multipliers 
   1.147 -              uint factor = (multiplier << 1) | ((eax >> 14) & 1);
   1.148 -              uint maxFactor = (maxMultiplier << 1) | ((edx >> 14) & 1);
   1.149 -              if (maxFactor > 0) {
   1.150 -                coreClocks[i].Value = 
   1.151 -                  (float)(factor * TimeStampCounterFrequency / maxFactor);
   1.152 -                newBusClock = 
   1.153 -                  (float)(2 * TimeStampCounterFrequency / maxFactor);
   1.154 -              }
   1.155 -            }
   1.156 -          } else { // Intel Pentium 4
   1.157 +            (UIntPtr)(1L << cpuid[i][0].Thread))) 
   1.158 +          {
   1.159 +            newBusClock = 
   1.160 +              TimeStampCounterFrequency / timeStampCounterMultiplier;
   1.161 +            if (microarchitecture == Microarchitecture.Nehalem) {
   1.162 +              uint multiplier = eax & 0xff;
   1.163 +              coreClocks[i].Value = (float)(multiplier * newBusClock);
   1.164 +            } else {
   1.165 +              double multiplier = ((eax >> 8) & 0x1f) + 0.5 * ((eax >> 14) & 1);
   1.166 +              coreClocks[i].Value = (float)(multiplier * newBusClock);
   1.167 +            }            
   1.168 +          } else { 
   1.169              // if IA32_PERF_STATUS is not available, assume TSC frequency
   1.170              coreClocks[i].Value = (float)TimeStampCounterFrequency;
   1.171            }