Refactored the CPU classes and added a GenericCPU class.
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" />