Refactored the CPU classes and added a GenericCPU class.
authormoel.mich
Mon, 20 Sep 2010 19:28:25 +0000
changeset 1916545fa3ae298
parent 190 d3a54e407737
child 192 ad190510cddd
Refactored the CPU classes and added a GenericCPU class.
Hardware/CPU/AMD0FCPU.cs
Hardware/CPU/AMD10CPU.cs
Hardware/CPU/CPUGroup.cs
Hardware/CPU/GenericCPU.cs
Hardware/CPU/IntelCPU.cs
OpenHardwareMonitorLib.csproj
     1.1 --- a/Hardware/CPU/AMD0FCPU.cs	Sat Sep 18 19:56:39 2010 +0000
     1.2 +++ b/Hardware/CPU/AMD0FCPU.cs	Mon Sep 20 19:28:25 2010 +0000
     1.3 @@ -35,39 +35,21 @@
     1.4   
     1.5  */
     1.6  
     1.7 -using System;
     1.8 -using System.Globalization;
     1.9 +namespace OpenHardwareMonitor.Hardware.CPU {
    1.10 +  internal sealed class AMD0FCPU : GenericCPU {
    1.11  
    1.12 -namespace OpenHardwareMonitor.Hardware.CPU {
    1.13 -  internal sealed class AMD0FCPU : Hardware, IHardware {
    1.14 -
    1.15 -    private string name;
    1.16 -
    1.17 -    private int processorIndex;
    1.18      private uint pciAddress;
    1.19 -
    1.20      private Sensor[] coreTemperatures;    
    1.21  
    1.22 -    private Sensor totalLoad;
    1.23 -    private Sensor[] coreLoads;
    1.24 -
    1.25 -    private CPULoad cpuLoad;
    1.26 -
    1.27      private const ushort PCI_AMD_VENDOR_ID = 0x1022;
    1.28      private const ushort PCI_AMD_0FH_MISCELLANEOUS_DEVICE_ID = 0x1103;
    1.29      private const uint THERMTRIP_STATUS_REGISTER = 0xE4;
    1.30      private const byte THERM_SENSE_CORE_SEL_CPU0 = 0x4;
    1.31      private const byte THERM_SENSE_CORE_SEL_CPU1 = 0x0;
    1.32  
    1.33 -    public AMD0FCPU(int processorIndex, CPUID[][] cpuid, ISettings settings) {
    1.34 -
    1.35 -      this.processorIndex = processorIndex;
    1.36 -      this.name = cpuid[0][0].Name;
    1.37 -
    1.38 -      int coreCount = cpuid.Length;
    1.39 -
    1.40 -      totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this, settings);
    1.41 -        
    1.42 +    public AMD0FCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
    1.43 +      : base(processorIndex, cpuid, settings) 
    1.44 +    {
    1.45        float offset = -49.0f;
    1.46  
    1.47        // AM2+ 65nm +21 offset
    1.48 @@ -93,40 +75,19 @@
    1.49          coreTemperatures = new Sensor[0];
    1.50        }
    1.51  
    1.52 -      coreLoads = new Sensor[coreCount];
    1.53 -      for (int i = 0; i < coreCount; i++) 
    1.54 -        coreLoads[i] = new Sensor("Core #" + (i + 1), i + 1,
    1.55 -          SensorType.Load, this, settings);     
    1.56 -
    1.57 -      cpuLoad = new CPULoad(cpuid);
    1.58 -      if (cpuLoad.IsAvailable) {
    1.59 -        foreach (Sensor sensor in coreLoads)
    1.60 -          ActivateSensor(sensor);
    1.61 -        ActivateSensor(totalLoad);
    1.62 -      }
    1.63 -
    1.64        pciAddress = WinRing0.FindPciDeviceById(PCI_AMD_VENDOR_ID,
    1.65          PCI_AMD_0FH_MISCELLANEOUS_DEVICE_ID, (byte)processorIndex);
    1.66  
    1.67        Update();                   
    1.68      }
    1.69  
    1.70 -    public override string Name {
    1.71 -      get { return name; }
    1.72 -    }
    1.73 -
    1.74 -    public override Identifier Identifier {
    1.75 -      get { 
    1.76 -        return new Identifier("amdcpu", 
    1.77 -          processorIndex.ToString(CultureInfo.InvariantCulture)); 
    1.78 -      }
    1.79 -    }
    1.80 -
    1.81 -    public override HardwareType HardwareType {
    1.82 -      get { return HardwareType.CPU; }
    1.83 +    protected override uint[] GetMSRs() {
    1.84 +      return new uint[] { };
    1.85      }
    1.86  
    1.87      public override void Update() {
    1.88 +      base.Update();
    1.89 +
    1.90        if (pciAddress != 0xFFFFFFFF) {
    1.91          for (uint i = 0; i < coreTemperatures.Length; i++) {
    1.92            if (WinRing0.WritePciConfigDwordEx(
    1.93 @@ -144,13 +105,7 @@
    1.94            }
    1.95          }
    1.96        }
    1.97 -
    1.98 -      if (cpuLoad.IsAvailable) {
    1.99 -        cpuLoad.Update();
   1.100 -        for (int i = 0; i < coreLoads.Length; i++)
   1.101 -          coreLoads[i].Value = cpuLoad.GetCoreLoad(i);
   1.102 -        totalLoad.Value = cpuLoad.GetTotalLoad();
   1.103 -      }
   1.104 -    }   
   1.105 +    }  
   1.106 + 
   1.107    }
   1.108  }
     2.1 --- a/Hardware/CPU/AMD10CPU.cs	Sat Sep 18 19:56:39 2010 +0000
     2.2 +++ b/Hardware/CPU/AMD10CPU.cs	Mon Sep 20 19:28:25 2010 +0000
     2.3 @@ -35,52 +35,22 @@
     2.4   
     2.5  */
     2.6  
     2.7 -using System;
     2.8 -using System.Collections.Generic;
     2.9 -using System.Globalization;
    2.10 -using System.Diagnostics;
    2.11 -using System.Text;
    2.12 -
    2.13  namespace OpenHardwareMonitor.Hardware.CPU {
    2.14  
    2.15 -  internal sealed class AMD10CPU : Hardware, IHardware {
    2.16 -    private string name;
    2.17 +  internal sealed class AMD10CPU : GenericCPU {
    2.18  
    2.19 -    private int processorIndex;
    2.20      private uint pciAddress;
    2.21  
    2.22      private Sensor coreTemperature;
    2.23 -    private Sensor totalLoad;
    2.24 -    private Sensor[] coreLoads;
    2.25 -
    2.26 -    private CPULoad cpuLoad;
    2.27  
    2.28      private const ushort PCI_AMD_VENDOR_ID = 0x1022;
    2.29      private const ushort PCI_AMD_10H_MISCELLANEOUS_DEVICE_ID = 0x1203;
    2.30      private const ushort PCI_AMD_11H_MISCELLANEOUS_DEVICE_ID = 0x1303;
    2.31      private const uint REPORTED_TEMPERATURE_CONTROL_REGISTER = 0xA4;
    2.32  
    2.33 -    public AMD10CPU(int processorIndex, CPUID[][] cpuid, ISettings settings) {
    2.34 -
    2.35 -      this.processorIndex = processorIndex;
    2.36 -      this.name = cpuid[0][0].Name;
    2.37 -
    2.38 -      int coreCount = cpuid.Length;
    2.39 -
    2.40 -      totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this, settings);
    2.41 -
    2.42 -      coreLoads = new Sensor[coreCount];
    2.43 -      for (int i = 0; i < coreCount; i++) 
    2.44 -        coreLoads[i] = new Sensor("Core #" + (i + 1), i + 1,
    2.45 -          SensorType.Load, this, settings);
    2.46 -
    2.47 -      cpuLoad = new CPULoad(cpuid);
    2.48 -      if (cpuLoad.IsAvailable) {
    2.49 -        foreach (Sensor sensor in coreLoads)
    2.50 -          ActivateSensor(sensor);
    2.51 -        ActivateSensor(totalLoad);
    2.52 -      }    
    2.53 -      
    2.54 +    public AMD10CPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
    2.55 +      : base(processorIndex, cpuid, settings) 
    2.56 +    {      
    2.57        // AMD family 10h processors support only one temperature sensor
    2.58        coreTemperature = new Sensor(
    2.59          "Core" + (coreCount > 1 ? " #1 - #" + coreCount : ""), 0,
    2.60 @@ -97,22 +67,13 @@
    2.61        Update();                   
    2.62      }
    2.63  
    2.64 -    public override string Name {
    2.65 -      get { return name; }
    2.66 -    }
    2.67 -
    2.68 -    public override Identifier Identifier {
    2.69 -      get { 
    2.70 -        return new Identifier("amdcpu", 
    2.71 -          processorIndex.ToString(CultureInfo.InvariantCulture)); 
    2.72 -      }
    2.73 -    }
    2.74 -
    2.75 -    public override HardwareType HardwareType {
    2.76 -      get { return HardwareType.CPU; }
    2.77 +    protected override uint[] GetMSRs() {
    2.78 +      return new uint[] { };
    2.79      }
    2.80  
    2.81      public override void Update() {
    2.82 +      base.Update();
    2.83 +
    2.84        if (pciAddress != 0xFFFFFFFF) {
    2.85          uint value;
    2.86          if (WinRing0.ReadPciConfigDwordEx(pciAddress,
    2.87 @@ -124,13 +85,6 @@
    2.88            DeactivateSensor(coreTemperature);
    2.89          }
    2.90        }
    2.91 -
    2.92 -      if (cpuLoad.IsAvailable) {
    2.93 -        cpuLoad.Update();
    2.94 -        for (int i = 0; i < coreLoads.Length; i++)
    2.95 -          coreLoads[i].Value = cpuLoad.GetCoreLoad(i);
    2.96 -        totalLoad.Value = cpuLoad.GetTotalLoad();
    2.97 -      }
    2.98      }
    2.99    }
   2.100  }
     3.1 --- a/Hardware/CPU/CPUGroup.cs	Sat Sep 18 19:56:39 2010 +0000
     3.2 +++ b/Hardware/CPU/CPUGroup.cs	Mon Sep 20 19:28:25 2010 +0000
     3.3 @@ -119,7 +119,7 @@
     3.4              
     3.5          CPUID[][] coreThreads = GroupThreadsByCore(threads);
     3.6  
     3.7 -        this.threads[index] = coreThreads;        
     3.8 +        this.threads[index] = coreThreads;
     3.9  
    3.10          switch (threads[0].Vendor) {
    3.11            case Vendor.Intel:
    3.12 @@ -134,9 +134,11 @@
    3.13                  hardware.Add(new AMD10CPU(index, coreThreads, settings));
    3.14                  break;
    3.15                default:
    3.16 +                hardware.Add(new GenericCPU(index, coreThreads, settings));
    3.17                  break;
    3.18              } break;
    3.19            default:
    3.20 +            hardware.Add(new GenericCPU(index, coreThreads, settings));
    3.21              break;
    3.22          }
    3.23  
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/Hardware/CPU/GenericCPU.cs	Mon Sep 20 19:28:25 2010 +0000
     4.3 @@ -0,0 +1,273 @@
     4.4 +/*
     4.5 +  
     4.6 +  Version: MPL 1.1/GPL 2.0/LGPL 2.1
     4.7 +
     4.8 +  The contents of this file are subject to the Mozilla Public License Version
     4.9 +  1.1 (the "License"); you may not use this file except in compliance with
    4.10 +  the License. You may obtain a copy of the License at
    4.11 + 
    4.12 +  http://www.mozilla.org/MPL/
    4.13 +
    4.14 +  Software distributed under the License is distributed on an "AS IS" basis,
    4.15 +  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    4.16 +  for the specific language governing rights and limitations under the License.
    4.17 +
    4.18 +  The Original Code is the Open Hardware Monitor code.
    4.19 +
    4.20 +  The Initial Developer of the Original Code is 
    4.21 +  Michael Möller <m.moeller@gmx.ch>.
    4.22 +  Portions created by the Initial Developer are Copyright (C) 2010
    4.23 +  the Initial Developer. All Rights Reserved.
    4.24 +
    4.25 +  Contributor(s):
    4.26 +
    4.27 +  Alternatively, the contents of this file may be used under the terms of
    4.28 +  either the GNU General Public License Version 2 or later (the "GPL"), or
    4.29 +  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    4.30 +  in which case the provisions of the GPL or the LGPL are applicable instead
    4.31 +  of those above. If you wish to allow use of your version of this file only
    4.32 +  under the terms of either the GPL or the LGPL, and not to allow others to
    4.33 +  use your version of this file under the terms of the MPL, indicate your
    4.34 +  decision by deleting the provisions above and replace them with the notice
    4.35 +  and other provisions required by the GPL or the LGPL. If you do not delete
    4.36 +  the provisions above, a recipient may use your version of this file under
    4.37 +  the terms of any one of the MPL, the GPL or the LGPL.
    4.38 + 
    4.39 +*/
    4.40 +
    4.41 +using System;
    4.42 +using System.Collections.Generic;
    4.43 +using System.Diagnostics;
    4.44 +using System.Globalization;
    4.45 +using System.Text;
    4.46 +using System.Threading;
    4.47 +
    4.48 +namespace OpenHardwareMonitor.Hardware.CPU {
    4.49 +  internal class GenericCPU : Hardware, IHardware {
    4.50 +
    4.51 +    protected readonly CPUID[][] cpuid;
    4.52 +   
    4.53 +    protected readonly uint family;
    4.54 +    protected readonly uint model;
    4.55 +    protected readonly uint stepping;
    4.56 +
    4.57 +    protected readonly int processorIndex;
    4.58 +    protected readonly int coreCount;
    4.59 +    protected readonly string name;
    4.60 +
    4.61 +    protected readonly bool hasTSC;
    4.62 +    protected readonly bool invariantTSC;
    4.63 +
    4.64 +    private ulong lastTimeStampCount;
    4.65 +    private long lastTime;
    4.66 +    private double maxClock;
    4.67 +    private double estimatedMaxClock;
    4.68 +
    4.69 +    private Vendor vendor;
    4.70 +
    4.71 +    private readonly CPULoad cpuLoad;
    4.72 +    private readonly Sensor totalLoad;
    4.73 +    private readonly Sensor[] coreLoads;
    4.74 +
    4.75 +    protected string CoreString(int i) {
    4.76 +      if (coreCount == 1)
    4.77 +        return "CPU Core";
    4.78 +      else
    4.79 +        return "CPU Core #" + (i + 1);
    4.80 +    }
    4.81 +
    4.82 +    public GenericCPU(int processorIndex, CPUID[][] cpuid, ISettings settings) {
    4.83 +      this.cpuid = cpuid;
    4.84 +
    4.85 +      this.vendor = cpuid[0][0].Vendor;
    4.86 +
    4.87 +      this.family = cpuid[0][0].Family;
    4.88 +      this.model = cpuid[0][0].Model;
    4.89 +      this.stepping = cpuid[0][0].Stepping;
    4.90 +
    4.91 +      this.processorIndex = processorIndex;
    4.92 +      this.coreCount = cpuid.Length;
    4.93 +      this.name = cpuid[0][0].Name;      
    4.94 +
    4.95 +      // check if processor has TSC
    4.96 +      if (cpuid[0][0].Data.GetLength(0) > 1
    4.97 +        && (cpuid[0][0].Data[1, 3] & 0x10) != 0)
    4.98 +        hasTSC = true;
    4.99 +      else
   4.100 +        hasTSC = false;
   4.101 +
   4.102 +      // check if processor supports invariant TSC 
   4.103 +      if (cpuid[0][0].ExtData.GetLength(0) > 7
   4.104 +        && (cpuid[0][0].ExtData[7, 3] & 0x100) != 0)
   4.105 +        invariantTSC = true;
   4.106 +      else
   4.107 +        invariantTSC = false;
   4.108 +
   4.109 +      if (coreCount > 1)
   4.110 +        totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this, settings);
   4.111 +      else
   4.112 +        totalLoad = null;
   4.113 +      coreLoads = new Sensor[coreCount];
   4.114 +      for (int i = 0; i < coreLoads.Length; i++)
   4.115 +        coreLoads[i] = new Sensor(CoreString(i), i + 1,
   4.116 +          SensorType.Load, this, settings);
   4.117 +      cpuLoad = new CPULoad(cpuid);
   4.118 +      if (cpuLoad.IsAvailable) {
   4.119 +        foreach (Sensor sensor in coreLoads)
   4.120 +          ActivateSensor(sensor);
   4.121 +        if (totalLoad != null)
   4.122 +          ActivateSensor(totalLoad);
   4.123 +      }
   4.124 +
   4.125 +      if (hasTSC)
   4.126 +        estimatedMaxClock = EstimateMaxClock();
   4.127 +      else
   4.128 +        estimatedMaxClock = 0;
   4.129 +      maxClock = estimatedMaxClock;
   4.130 +
   4.131 +      lastTimeStampCount = 0;
   4.132 +      lastTime = 0;
   4.133 +    }
   4.134 +
   4.135 +    private double EstimateMaxClock() {
   4.136 +      // preload the function
   4.137 +      EstimateMaxClock(0);
   4.138 +      EstimateMaxClock(0);
   4.139 +
   4.140 +      // estimate the max clock in MHz      
   4.141 +      List<double> estimatedMaxClocks = new List<double>(3);
   4.142 +      for (int i = 0; i < 3; i++)
   4.143 +        estimatedMaxClocks.Add(1e-6 * EstimateMaxClock(0.025));
   4.144 +      estimatedMaxClocks.Sort();
   4.145 +      return estimatedMaxClocks[1];
   4.146 +    }
   4.147 +
   4.148 +    private static double EstimateMaxClock(double timeWindow) {
   4.149 +      long ticks = (long)(timeWindow * Stopwatch.Frequency);
   4.150 +      uint lsbBegin, msbBegin, lsbEnd, msbEnd;
   4.151 +
   4.152 +      Thread.BeginThreadAffinity();
   4.153 +      long timeBegin = Stopwatch.GetTimestamp() +
   4.154 +        (long)Math.Ceiling(0.001 * ticks);
   4.155 +      long timeEnd = timeBegin + ticks;
   4.156 +      while (Stopwatch.GetTimestamp() < timeBegin) { }
   4.157 +      WinRing0.Rdtsc(out lsbBegin, out msbBegin);
   4.158 +      while (Stopwatch.GetTimestamp() < timeEnd) { }
   4.159 +      WinRing0.Rdtsc(out lsbEnd, out msbEnd);
   4.160 +      Thread.EndThreadAffinity();
   4.161 +
   4.162 +      ulong countBegin = ((ulong)msbBegin << 32) | lsbBegin;
   4.163 +      ulong countEnd = ((ulong)msbEnd << 32) | lsbEnd;
   4.164 +
   4.165 +      return (((double)(countEnd - countBegin)) * Stopwatch.Frequency) /
   4.166 +        (timeEnd - timeBegin);
   4.167 +    }
   4.168 +
   4.169 +    private static void AppendMSRData(StringBuilder r, uint msr, int thread) {
   4.170 +      uint eax, edx;
   4.171 +      if (WinRing0.RdmsrTx(msr, out eax, out edx, (UIntPtr)(1L << thread))) {
   4.172 +        r.Append(" ");
   4.173 +        r.Append((msr).ToString("X8", CultureInfo.InvariantCulture));
   4.174 +        r.Append("  ");
   4.175 +        r.Append((edx).ToString("X8", CultureInfo.InvariantCulture));
   4.176 +        r.Append("  ");
   4.177 +        r.Append((eax).ToString("X8", CultureInfo.InvariantCulture));
   4.178 +        r.AppendLine();
   4.179 +      }
   4.180 +    }
   4.181 +
   4.182 +    protected virtual uint[] GetMSRs() {
   4.183 +      return null;
   4.184 +    }
   4.185 +
   4.186 +    public override string GetReport() {
   4.187 +      StringBuilder r = new StringBuilder();
   4.188 +
   4.189 +      switch (vendor) {
   4.190 +        case Vendor.AMD: r.AppendLine("Intel CPU"); break;
   4.191 +        case Vendor.Intel: r.AppendLine("Intel CPU"); break;
   4.192 +        default: r.AppendLine("Generic CPU"); break;
   4.193 +      }
   4.194 +
   4.195 +      r.AppendLine();
   4.196 +      r.AppendFormat("Name: {0}{1}", name, Environment.NewLine);
   4.197 +      r.AppendFormat("Number of Cores: {0}{1}", coreCount,
   4.198 +        Environment.NewLine);
   4.199 +      r.AppendFormat("Threads per Core: {0}{1}", cpuid[0].Length,
   4.200 +        Environment.NewLine);
   4.201 +      r.AppendLine("TSC: " +
   4.202 +        (hasTSC ? (invariantTSC ? "Invariant" : "Not Invariant") : "None"));
   4.203 +      r.AppendLine(string.Format(CultureInfo.InvariantCulture,
   4.204 +        "Timer Frequency: {0} MHz", Stopwatch.Frequency * 1e-6));
   4.205 +      r.AppendLine(string.Format(CultureInfo.InvariantCulture,
   4.206 +        "Max Clock: {0} MHz", Math.Round(maxClock * 100) * 0.01));
   4.207 +      r.AppendLine();
   4.208 +
   4.209 +      uint[] msrArray = GetMSRs();
   4.210 +      if (msrArray != null && msrArray.Length > 0) {
   4.211 +        for (int i = 0; i < cpuid.Length; i++) {
   4.212 +          r.AppendLine("MSR Core #" + (i + 1));
   4.213 +          r.AppendLine();
   4.214 +          r.AppendLine(" MSR       EDX       EAX");
   4.215 +          foreach (uint msr in msrArray)
   4.216 +            AppendMSRData(r, msr, cpuid[i][0].Thread);
   4.217 +          r.AppendLine();
   4.218 +        }
   4.219 +      }
   4.220 +
   4.221 +      return r.ToString();
   4.222 +    }
   4.223 +
   4.224 +    public override Identifier Identifier {
   4.225 +      get {
   4.226 +        string s;
   4.227 +        switch (vendor) {
   4.228 +          case Vendor.AMD: s = "amdcpu"; break;
   4.229 +          case Vendor.Intel: s = "intelcpu"; break;
   4.230 +          default: s = "genericcpu"; break;
   4.231 +        }
   4.232 +        return new Identifier(s, 
   4.233 +          processorIndex.ToString(CultureInfo.InvariantCulture));
   4.234 +      }
   4.235 +    }
   4.236 +
   4.237 +    public override string Name {
   4.238 +      get { return name; }
   4.239 +    }
   4.240 +
   4.241 +    public override HardwareType HardwareType {
   4.242 +      get { return HardwareType.CPU; }
   4.243 +    }
   4.244 +
   4.245 +    protected double MaxClock {
   4.246 +      get { return maxClock; }
   4.247 +    }
   4.248 +
   4.249 +    public override void Update() {
   4.250 +      if (hasTSC) {
   4.251 +        uint lsb, msb;
   4.252 +        WinRing0.RdtscTx(out lsb, out msb, (UIntPtr)1);
   4.253 +        long time = Stopwatch.GetTimestamp();
   4.254 +        ulong timeStampCount = ((ulong)msb << 32) | lsb;
   4.255 +        double delta = ((double)(time - lastTime)) / Stopwatch.Frequency;
   4.256 +        if (delta > 0.5) {
   4.257 +          if (invariantTSC)
   4.258 +            maxClock = (timeStampCount - lastTimeStampCount) / (1e6 * delta);
   4.259 +          else
   4.260 +            maxClock = estimatedMaxClock;
   4.261 +
   4.262 +          lastTimeStampCount = timeStampCount;
   4.263 +          lastTime = time;
   4.264 +        }        
   4.265 +      }
   4.266 +
   4.267 +      if (cpuLoad.IsAvailable) {
   4.268 +        cpuLoad.Update();
   4.269 +        for (int i = 0; i < coreLoads.Length; i++)
   4.270 +          coreLoads[i].Value = cpuLoad.GetCoreLoad(i);
   4.271 +        if (totalLoad != null)
   4.272 +          totalLoad.Value = cpuLoad.GetTotalLoad();
   4.273 +      }
   4.274 +    }
   4.275 +  }
   4.276 +}
     5.1 --- a/Hardware/CPU/IntelCPU.cs	Sat Sep 18 19:56:39 2010 +0000
     5.2 +++ b/Hardware/CPU/IntelCPU.cs	Mon Sep 20 19:28:25 2010 +0000
     5.3 @@ -37,52 +37,21 @@
     5.4  
     5.5  using System;
     5.6  using System.Collections.Generic;
     5.7 -using System.Diagnostics;
     5.8 -using System.Globalization;
     5.9 -using System.Text;
    5.10 -using System.Threading;
    5.11  
    5.12  namespace OpenHardwareMonitor.Hardware.CPU {
    5.13 -  internal sealed class IntelCPU : Hardware, IHardware {
    5.14 -
    5.15 -    private int processorIndex;
    5.16 -    private CPUID[][] cpuid;
    5.17 -    private int coreCount;
    5.18 -    
    5.19 -    private string name;
    5.20 -
    5.21 -    private uint family;
    5.22 -    private uint model;
    5.23 -    private uint stepping;
    5.24 +  internal sealed class IntelCPU : GenericCPU {
    5.25  
    5.26      private Sensor[] coreTemperatures;
    5.27 +    private Sensor[] coreClocks;
    5.28 +    private Sensor busClock;
    5.29  
    5.30 -    private Sensor totalLoad;
    5.31 -    private Sensor[] coreLoads;
    5.32 -    private Sensor[] coreClocks;
    5.33 -    private Sensor busClock;    
    5.34 -    private bool hasTSC;
    5.35 -    private bool invariantTSC;    
    5.36 -    private double estimatedMaxClock;
    5.37 +    private uint maxNehalemMultiplier = 0;
    5.38  
    5.39 -    private CPULoad cpuLoad;
    5.40 -
    5.41 -    private ulong lastTimeStampCount;    
    5.42 -    private long lastTime;
    5.43 -    private uint maxNehalemMultiplier = 0;    
    5.44 -    
    5.45      private const uint IA32_THERM_STATUS_MSR = 0x019C;
    5.46      private const uint IA32_TEMPERATURE_TARGET = 0x01A2;
    5.47      private const uint IA32_PERF_STATUS = 0x0198;
    5.48      private const uint MSR_PLATFORM_INFO = 0xCE;
    5.49  
    5.50 -    private string CoreString(int i) {
    5.51 -      if (coreCount == 1)
    5.52 -        return "CPU Core";
    5.53 -      else
    5.54 -        return "CPU Core #" + (i + 1);
    5.55 -    }
    5.56 -
    5.57      private float[] Floats(float f) {
    5.58        float[] result = new float[coreCount];
    5.59        for (int i = 0; i < coreCount; i++)
    5.60 @@ -90,17 +59,9 @@
    5.61        return result;
    5.62      }
    5.63  
    5.64 -    public IntelCPU(int processorIndex, CPUID[][] cpuid, ISettings settings) {
    5.65 -
    5.66 -      this.processorIndex = processorIndex;
    5.67 -      this.cpuid = cpuid;
    5.68 -      this.coreCount = cpuid.Length;
    5.69 -      this.name = cpuid[0][0].Name;
    5.70 -
    5.71 -      this.family = cpuid[0][0].Family;
    5.72 -      this.model = cpuid[0][0].Model;
    5.73 -      this.stepping = cpuid[0][0].Stepping;
    5.74 -
    5.75 +    public IntelCPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
    5.76 +      : base(processorIndex, cpuid, settings) 
    5.77 +    {
    5.78        float[] tjMax;
    5.79        switch (family) {
    5.80          case 0x06: {
    5.81 @@ -134,7 +95,7 @@
    5.82                      tjMax = Floats(100); break;
    5.83                    default:
    5.84                      tjMax = Floats(90); break;
    5.85 -                } break;                
    5.86 +                } break;
    5.87                case 0x1A: // Intel Core i7 LGA1366 (45nm)
    5.88                case 0x1E: // Intel Core i5, i7 LGA1156 (45nm)
    5.89                case 0x25: // Intel Core i3, i5, i7 LGA1156 (32nm)
    5.90 @@ -143,8 +104,7 @@
    5.91                  tjMax = new float[coreCount];
    5.92                  for (int i = 0; i < coreCount; i++) {
    5.93                    if (WinRing0.RdmsrTx(IA32_TEMPERATURE_TARGET, out eax,
    5.94 -                    out edx, (UIntPtr)(1L << cpuid[i][0].Thread)))
    5.95 -                  {
    5.96 +                    out edx, (UIntPtr)(1L << cpuid[i][0].Thread))) {
    5.97                      tjMax[i] = (eax >> 16) & 0xFF;
    5.98                    } else {
    5.99                      tjMax[i] = 100;
   5.100 @@ -162,9 +122,8 @@
   5.101        }
   5.102  
   5.103        // check if processor supports a digital thermal sensor
   5.104 -      if (cpuid[0][0].Data.GetLength(0) > 6 && 
   5.105 -        (cpuid[0][0].Data[6, 0] & 1) != 0) 
   5.106 -      {
   5.107 +      if (cpuid[0][0].Data.GetLength(0) > 6 &&
   5.108 +        (cpuid[0][0].Data[6, 0] & 1) != 0) {
   5.109          coreTemperatures = new Sensor[coreCount];
   5.110          for (int i = 0; i < coreTemperatures.Length; i++) {
   5.111            coreTemperatures[i] = new Sensor(CoreString(i), i,
   5.112 @@ -181,50 +140,7 @@
   5.113          coreTemperatures = new Sensor[0];
   5.114        }
   5.115  
   5.116 -      if (coreCount > 1)
   5.117 -        totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this, settings);
   5.118 -      else
   5.119 -        totalLoad = null;
   5.120 -      coreLoads = new Sensor[coreCount];
   5.121 -      for (int i = 0; i < coreLoads.Length; i++)
   5.122 -        coreLoads[i] = new Sensor(CoreString(i), i + 1,
   5.123 -          SensorType.Load, this, settings);     
   5.124 -      cpuLoad = new CPULoad(cpuid);
   5.125 -      if (cpuLoad.IsAvailable) {
   5.126 -        foreach (Sensor sensor in coreLoads)
   5.127 -          ActivateSensor(sensor);
   5.128 -        if (totalLoad != null)
   5.129 -          ActivateSensor(totalLoad);
   5.130 -      }
   5.131 -
   5.132 -      // check if processor has TSC
   5.133 -      if (cpuid[0][0].Data.GetLength(0) > 1 
   5.134 -        && (cpuid[0][0].Data[1, 3] & 0x10) != 0)
   5.135 -        hasTSC = true;
   5.136 -      else
   5.137 -        hasTSC = false; 
   5.138 -
   5.139 -      // check if processor supports invariant TSC 
   5.140 -      if (cpuid[0][0].ExtData.GetLength(0) > 7 
   5.141 -        && (cpuid[0][0].ExtData[7, 3] & 0x100) != 0)
   5.142 -        invariantTSC = true;
   5.143 -      else
   5.144 -        invariantTSC = false;
   5.145 -
   5.146 -      // preload the function
   5.147 -      EstimateMaxClock(0); 
   5.148 -      EstimateMaxClock(0); 
   5.149 -
   5.150 -      // estimate the max clock in MHz      
   5.151 -      List<double> estimatedMaxClocks = new List<double>(3);
   5.152 -      for (int i = 0; i < 3; i++)
   5.153 -        estimatedMaxClocks.Add(1e-6 * EstimateMaxClock(0.025));
   5.154 -      estimatedMaxClocks.Sort();
   5.155 -      estimatedMaxClock = estimatedMaxClocks[1];
   5.156 -
   5.157 -      lastTimeStampCount = 0;
   5.158 -      lastTime = 0;
   5.159 -      busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);      
   5.160 +      busClock = new Sensor("Bus Speed", 0, SensorType.Clock, this, settings);
   5.161        coreClocks = new Sensor[coreCount];
   5.162        for (int i = 0; i < coreClocks.Length; i++) {
   5.163          coreClocks[i] =
   5.164 @@ -232,96 +148,26 @@
   5.165          if (hasTSC)
   5.166            ActivateSensor(coreClocks[i]);
   5.167        }
   5.168 -      
   5.169 -      Update();                   
   5.170 +
   5.171 +      Update();
   5.172      }
   5.173  
   5.174 -    public override string Name {
   5.175 -      get { return name; }
   5.176 +    protected override uint[] GetMSRs() {
   5.177 +      return new uint[] {
   5.178 +        MSR_PLATFORM_INFO,
   5.179 +        IA32_PERF_STATUS ,
   5.180 +        IA32_THERM_STATUS_MSR,
   5.181 +        IA32_TEMPERATURE_TARGET
   5.182 +      };
   5.183      }
   5.184  
   5.185 -    public override Identifier Identifier {
   5.186 -      get { 
   5.187 -        return new Identifier("intelcpu", 
   5.188 -          processorIndex.ToString(CultureInfo.InvariantCulture)); 
   5.189 -      }
   5.190 -    }
   5.191 +    public override void Update() {
   5.192 +      base.Update();
   5.193  
   5.194 -    public override HardwareType HardwareType {
   5.195 -      get { return HardwareType.CPU; }
   5.196 -    }
   5.197 -
   5.198 -    private static void AppendMSRData(StringBuilder r, uint msr, int thread) {
   5.199 -      uint eax, edx;
   5.200 -      if (WinRing0.RdmsrTx(msr, out eax, out edx, (UIntPtr)(1L << thread))) {
   5.201 -        r.Append(" ");
   5.202 -        r.Append((msr).ToString("X8", CultureInfo.InvariantCulture));
   5.203 -        r.Append("  ");
   5.204 -        r.Append((edx).ToString("X8", CultureInfo.InvariantCulture));
   5.205 -        r.Append("  ");
   5.206 -        r.Append((eax).ToString("X8", CultureInfo.InvariantCulture));
   5.207 -        r.AppendLine();
   5.208 -      }
   5.209 -    }
   5.210 -
   5.211 -    public override string GetReport() {
   5.212 -      StringBuilder r = new StringBuilder();
   5.213 -
   5.214 -      r.AppendLine("Intel CPU");
   5.215 -      r.AppendLine();
   5.216 -      r.AppendFormat("Name: {0}{1}", name, Environment.NewLine);
   5.217 -      r.AppendFormat("Number of Cores: {0}{1}", coreCount, 
   5.218 -        Environment.NewLine);
   5.219 -      r.AppendFormat("Threads per Core: {0}{1}", cpuid[0].Length,
   5.220 -        Environment.NewLine);     
   5.221 -      r.AppendLine("TSC: " + 
   5.222 -        (hasTSC ? (invariantTSC ? "Invariant" : "Not Invariant") : "None"));
   5.223 -      r.AppendLine(string.Format(CultureInfo.InvariantCulture, 
   5.224 -        "Timer Frequency: {0} MHz", Stopwatch.Frequency * 1e-6));
   5.225 -      r.AppendLine(string.Format(CultureInfo.InvariantCulture,
   5.226 -        "Max Clock: {0} MHz", Math.Round(estimatedMaxClock * 100) * 0.01));
   5.227 -      r.AppendLine();
   5.228 -
   5.229 -      for (int i = 0; i < cpuid.Length; i++) {
   5.230 -        r.AppendLine("MSR Core #" + (i + 1));
   5.231 -        r.AppendLine();
   5.232 -        r.AppendLine(" MSR       EDX       EAX");
   5.233 -        AppendMSRData(r, MSR_PLATFORM_INFO, cpuid[i][0].Thread);
   5.234 -        AppendMSRData(r, IA32_PERF_STATUS, cpuid[i][0].Thread);
   5.235 -        AppendMSRData(r, IA32_THERM_STATUS_MSR, cpuid[i][0].Thread);
   5.236 -        AppendMSRData(r, IA32_TEMPERATURE_TARGET, cpuid[i][0].Thread);
   5.237 -        r.AppendLine();
   5.238 -      }
   5.239 -
   5.240 -      return r.ToString();
   5.241 -    }
   5.242 -
   5.243 -    private static double EstimateMaxClock(double timeWindow) {
   5.244 -      long ticks = (long)(timeWindow * Stopwatch.Frequency);
   5.245 -      uint lsbBegin, msbBegin, lsbEnd, msbEnd; 
   5.246 -      
   5.247 -      Thread.BeginThreadAffinity();
   5.248 -      long timeBegin = Stopwatch.GetTimestamp() + 
   5.249 -        (long)Math.Ceiling(0.001 * ticks);
   5.250 -      long timeEnd = timeBegin + ticks;      
   5.251 -      while (Stopwatch.GetTimestamp() < timeBegin) { }
   5.252 -      WinRing0.Rdtsc(out lsbBegin, out msbBegin);
   5.253 -      while (Stopwatch.GetTimestamp() < timeEnd) { }
   5.254 -      WinRing0.Rdtsc(out lsbEnd, out msbEnd);
   5.255 -      Thread.EndThreadAffinity();
   5.256 -
   5.257 -      ulong countBegin = ((ulong)msbBegin << 32) | lsbBegin;
   5.258 -      ulong countEnd = ((ulong)msbEnd << 32) | lsbEnd;
   5.259 -
   5.260 -      return (((double)(countEnd - countBegin)) * Stopwatch.Frequency) / 
   5.261 -        (timeEnd - timeBegin);
   5.262 -    }
   5.263 -
   5.264 -    public override void Update() {      
   5.265        for (int i = 0; i < coreTemperatures.Length; i++) {
   5.266          uint eax, edx;
   5.267          if (WinRing0.RdmsrTx(
   5.268 -          IA32_THERM_STATUS_MSR, out eax, out edx, 
   5.269 +          IA32_THERM_STATUS_MSR, out eax, out edx,
   5.270              (UIntPtr)(1L << cpuid[i][0].Thread))) {
   5.271            // if reading is valid
   5.272            if ((eax & 0x80000000) != 0) {
   5.273 @@ -336,62 +182,39 @@
   5.274          }
   5.275        }
   5.276  
   5.277 -      if (cpuLoad.IsAvailable) {
   5.278 -        cpuLoad.Update();
   5.279 -        for (int i = 0; i < coreLoads.Length; i++)
   5.280 -          coreLoads[i].Value = cpuLoad.GetCoreLoad(i);
   5.281 -        if (totalLoad != null)
   5.282 -          totalLoad.Value = cpuLoad.GetTotalLoad();
   5.283 -      }
   5.284 -
   5.285        if (hasTSC) {
   5.286 -        uint lsb, msb;
   5.287 -        WinRing0.RdtscTx(out lsb, out msb, (UIntPtr)1);
   5.288 -        long time = Stopwatch.GetTimestamp();
   5.289 -        ulong timeStampCount = ((ulong)msb << 32) | lsb;
   5.290 -        double delta = ((double)(time - lastTime)) / Stopwatch.Frequency;
   5.291 -        if (delta > 0.5) {
   5.292 -          double maxClock;
   5.293 -          if (invariantTSC)
   5.294 -            maxClock = (timeStampCount - lastTimeStampCount) / (1e6 * delta);
   5.295 -          else
   5.296 -            maxClock = estimatedMaxClock;
   5.297 -
   5.298 -          double newBusClock = 0;
   5.299 -          uint eax, edx;
   5.300 -          for (int i = 0; i < coreClocks.Length; i++) {
   5.301 -            System.Threading.Thread.Sleep(1);
   5.302 -            if (WinRing0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
   5.303 -              (UIntPtr)(1L << cpuid[i][0].Thread))) {
   5.304 -              if (maxNehalemMultiplier > 0) { // Core i3, i5, i7
   5.305 -                uint nehalemMultiplier = eax & 0xff;
   5.306 -                coreClocks[i].Value =
   5.307 -                  (float)(nehalemMultiplier * maxClock / maxNehalemMultiplier);
   5.308 -                newBusClock = (float)(maxClock / maxNehalemMultiplier);
   5.309 -              } else { // Core 2
   5.310 -                uint multiplier = (eax >> 8) & 0x1f;
   5.311 -                uint maxMultiplier = (edx >> 8) & 0x1f;
   5.312 -                // factor = multiplier * 2 to handle non integer multipliers 
   5.313 -                uint factor = (multiplier << 1) | ((eax >> 14) & 1);
   5.314 -                uint maxFactor = (maxMultiplier << 1) | ((edx >> 14) & 1);
   5.315 -                if (maxFactor > 0) {
   5.316 -                  coreClocks[i].Value = (float)(factor * maxClock / maxFactor);
   5.317 -                  newBusClock = (float)(2 * maxClock / maxFactor);
   5.318 -                }
   5.319 +        double newBusClock = 0;
   5.320 +        uint eax, edx;
   5.321 +        for (int i = 0; i < coreClocks.Length; i++) {
   5.322 +          System.Threading.Thread.Sleep(1);
   5.323 +          if (WinRing0.RdmsrTx(IA32_PERF_STATUS, out eax, out edx,
   5.324 +            (UIntPtr)(1L << cpuid[i][0].Thread))) {
   5.325 +            if (maxNehalemMultiplier > 0) { // Core i3, i5, i7
   5.326 +              uint nehalemMultiplier = eax & 0xff;
   5.327 +              coreClocks[i].Value =
   5.328 +                (float)(nehalemMultiplier * MaxClock / maxNehalemMultiplier);
   5.329 +              newBusClock = (float)(MaxClock / maxNehalemMultiplier);
   5.330 +            } else { // Core 2
   5.331 +              uint multiplier = (eax >> 8) & 0x1f;
   5.332 +              uint maxMultiplier = (edx >> 8) & 0x1f;
   5.333 +              // factor = multiplier * 2 to handle non integer multipliers 
   5.334 +              uint factor = (multiplier << 1) | ((eax >> 14) & 1);
   5.335 +              uint maxFactor = (maxMultiplier << 1) | ((edx >> 14) & 1);
   5.336 +              if (maxFactor > 0) {
   5.337 +                coreClocks[i].Value = (float)(factor * MaxClock / maxFactor);
   5.338 +                newBusClock = (float)(2 * MaxClock / maxFactor);
   5.339                }
   5.340 -            } else { // Intel Pentium 4
   5.341 -              // if IA32_PERF_STATUS is not available, assume maxClock
   5.342 -              coreClocks[i].Value = (float)maxClock;
   5.343              }
   5.344 -          }
   5.345 -          if (newBusClock > 0) {
   5.346 -            this.busClock.Value = (float)newBusClock;
   5.347 -            ActivateSensor(this.busClock);
   5.348 +          } else { // Intel Pentium 4
   5.349 +            // if IA32_PERF_STATUS is not available, assume maxClock
   5.350 +            coreClocks[i].Value = (float)MaxClock;
   5.351            }
   5.352          }
   5.353 -        lastTimeStampCount = timeStampCount;
   5.354 -        lastTime = time;
   5.355 +        if (newBusClock > 0) {
   5.356 +          this.busClock.Value = (float)newBusClock;
   5.357 +          ActivateSensor(this.busClock);
   5.358 +        }
   5.359        }
   5.360      }
   5.361 -  }  
   5.362 +  }
   5.363  }
     6.1 --- a/OpenHardwareMonitorLib.csproj	Sat Sep 18 19:56:39 2010 +0000
     6.2 +++ b/OpenHardwareMonitorLib.csproj	Mon Sep 20 19:28:25 2010 +0000
     6.3 @@ -61,6 +61,7 @@
     6.4      <Compile Include="Hardware\ATI\ATIGPU.cs" />
     6.5      <Compile Include="Hardware\ATI\ATIGroup.cs" />
     6.6      <Compile Include="Hardware\Computer.cs" />
     6.7 +    <Compile Include="Hardware\CPU\GenericCPU.cs" />
     6.8      <Compile Include="Hardware\CPU\AMD0FCPU.cs" />
     6.9      <Compile Include="Hardware\CPU\AMD10CPU.cs" />
    6.10      <Compile Include="Hardware\CPU\CPUGroup.cs" />