1.1 --- a/Hardware/CPU/AMD10CPU.cs Sun Jun 19 12:59:07 2011 +0000
1.2 +++ b/Hardware/CPU/AMD10CPU.cs Sun Jun 19 14:14:00 2011 +0000
1.3 @@ -61,7 +61,9 @@
1.4 private const byte MISCELLANEOUS_CONTROL_FUNCTION = 3;
1.5 private const ushort FAMILY_10H_MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1203;
1.6 private const ushort FAMILY_11H_MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1303;
1.7 - private const ushort FAMILY_14H_MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1703;
1.8 + private const ushort FAMILY_12H_MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1703;
1.9 + private const ushort FAMILY_14H_MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1703;
1.10 + private const ushort FAMILY_15H_MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1603;
1.11 private const uint REPORTED_TEMPERATURE_CONTROL_REGISTER = 0xA4;
1.12 private const uint CLOCK_POWER_TIMING_CONTROL_0_REGISTER = 0xD4;
1.13
1.14 @@ -76,7 +78,7 @@
1.15 public AMD10CPU(int processorIndex, CPUID[][] cpuid, ISettings settings)
1.16 : base(processorIndex, cpuid, settings)
1.17 {
1.18 - // AMD family 10h/11h processors support only one temperature sensor
1.19 + // AMD family 1Xh processors support only one temperature sensor
1.20 coreTemperature = new Sensor(
1.21 "Core" + (coreCount > 1 ? " #1 - #" + coreCount : ""), 0,
1.22 SensorType.Temperature, this, new [] {
1.23 @@ -88,8 +90,12 @@
1.24 FAMILY_10H_MISCELLANEOUS_CONTROL_DEVICE_ID; break;
1.25 case 0x11: miscellaneousControlDeviceId =
1.26 FAMILY_11H_MISCELLANEOUS_CONTROL_DEVICE_ID; break;
1.27 + case 0x12: miscellaneousControlDeviceId =
1.28 + FAMILY_12H_MISCELLANEOUS_CONTROL_DEVICE_ID; break;
1.29 case 0x14: miscellaneousControlDeviceId =
1.30 FAMILY_14H_MISCELLANEOUS_CONTROL_DEVICE_ID; break;
1.31 + case 0x15: miscellaneousControlDeviceId =
1.32 + FAMILY_15H_MISCELLANEOUS_CONTROL_DEVICE_ID; break;
1.33 default: miscellaneousControlDeviceId = 0; break;
1.34 }
1.35
1.36 @@ -196,23 +202,8 @@
1.37 while (Stopwatch.GetTimestamp() < timeEnd) { }
1.38 Ring0.Rdmsr(PERF_CTR_0, out lsbEnd, out msbEnd);
1.39 Ring0.Rdmsr(COFVID_STATUS, out eax, out edx);
1.40 + double coreMultiplier = GetCoreMultiplier(eax);
1.41
1.42 - double coreMultiplier;
1.43 - if (family == 0x14) {
1.44 - uint divisorIdMSD = (eax >> 4) & 0x1F;
1.45 - uint divisorIdLSD = eax & 0xF;
1.46 - uint value = 0;
1.47 - Ring0.ReadPciConfig(miscellaneousControlAddress,
1.48 - CLOCK_POWER_TIMING_CONTROL_0_REGISTER, out value);
1.49 - uint frequencyId = value & 0x1F;
1.50 -
1.51 - coreMultiplier =
1.52 - MultiplierFromIDs(divisorIdMSD, divisorIdLSD, frequencyId);
1.53 - } else {
1.54 - uint cpuDid = (eax >> 6) & 7;
1.55 - uint cpuFid = eax & 0x1F;
1.56 - coreMultiplier = MultiplierFromIDs(cpuDid, cpuFid);
1.57 - }
1.58 ulong countBegin = ((ulong)msbBegin << 32) | lsbBegin;
1.59 ulong countEnd = ((ulong)msbEnd << 32) | lsbEnd;
1.60
1.61 @@ -252,16 +243,48 @@
1.62 return r.ToString();
1.63 }
1.64
1.65 - // calculate the multiplier for family 10h based on Did and Fid
1.66 - private static double MultiplierFromIDs(uint divisorID, uint frequencyID) {
1.67 - return 0.5 * (frequencyID + 0x10) / (1 << (int)divisorID);
1.68 - }
1.69 -
1.70 - // calculate the multiplier for family 14h based on DidMSD, DidLSD and Fid
1.71 - private static double MultiplierFromIDs(uint divisorIdMSD,
1.72 - uint divisorIdLSD, uint frequencyId)
1.73 - {
1.74 - return (frequencyId + 0x10) / (divisorIdMSD + (divisorIdLSD * 0.25) + 1);
1.75 + private double GetCoreMultiplier(uint cofvidEax) {
1.76 + switch (family) {
1.77 + case 0x10:
1.78 + case 0x11:
1.79 + // 8:6 CpuDid: current core divisor ID
1.80 + // 5:0 CpuFid: current core frequency ID
1.81 + uint cpuDid = (cofvidEax >> 6) & 7;
1.82 + uint cpuFid = cofvidEax & 0x1F;
1.83 + return 0.5 * (cpuFid + 0x10) / (1 << (int)cpuDid);
1.84 + case 0x12:
1.85 + // 8:4 CpuFid: current CPU core frequency ID
1.86 + // 3:0 CpuDid: current CPU core divisor ID
1.87 + uint CpuFid = (cofvidEax >> 4) & 0x1F;
1.88 + uint CpuDid = cofvidEax & 0xF;
1.89 + double divisor;
1.90 + switch (CpuDid) {
1.91 + case 0: divisor = 1; break;
1.92 + case 1: divisor = 1.5; break;
1.93 + case 2: divisor = 2; break;
1.94 + case 3: divisor = 3; break;
1.95 + case 4: divisor = 4; break;
1.96 + case 5: divisor = 6; break;
1.97 + case 6: divisor = 8; break;
1.98 + case 7: divisor = 12; break;
1.99 + case 8: divisor = 16; break;
1.100 + default: divisor = 1; break;
1.101 + }
1.102 + return (CpuFid + 0x10) / divisor;
1.103 + case 0x14:
1.104 + // 8:4: current CPU core divisor ID most significant digit
1.105 + // 3:0: current CPU core divisor ID least significant digit
1.106 + uint divisorIdMSD = (cofvidEax >> 4) & 0x1F;
1.107 + uint divisorIdLSD = cofvidEax & 0xF;
1.108 + uint value = 0;
1.109 + Ring0.ReadPciConfig(miscellaneousControlAddress,
1.110 + CLOCK_POWER_TIMING_CONTROL_0_REGISTER, out value);
1.111 + uint frequencyId = value & 0x1F;
1.112 + return (frequencyId + 0x10) /
1.113 + (divisorIdMSD + (divisorIdLSD * 0.25) + 1);
1.114 + default:
1.115 + return 1;
1.116 + }
1.117 }
1.118
1.119 private string ReadFirstLine(Stream stream) {
1.120 @@ -314,22 +337,7 @@
1.121 1UL << cpuid[i][0].Thread))
1.122 {
1.123 double multiplier;
1.124 - if (family == 0x14) {
1.125 - uint divisorIdMSD = (curEax >> 4) & 0x1F;
1.126 - uint divisorIdLSD = curEax & 0xF;
1.127 - uint value = 0;
1.128 - Ring0.ReadPciConfig(miscellaneousControlAddress,
1.129 - CLOCK_POWER_TIMING_CONTROL_0_REGISTER, out value);
1.130 - uint frequencyId = value & 0x1F;
1.131 - multiplier =
1.132 - MultiplierFromIDs(divisorIdMSD, divisorIdLSD, frequencyId);
1.133 - } else {
1.134 - // 8:6 CpuDid: current core divisor ID
1.135 - // 5:0 CpuFid: current core frequency ID
1.136 - uint cpuDid = (curEax >> 6) & 7;
1.137 - uint cpuFid = curEax & 0x1F;
1.138 - multiplier = MultiplierFromIDs(cpuDid, cpuFid);
1.139 - }
1.140 + multiplier = GetCoreMultiplier(curEax);
1.141
1.142 coreClocks[i].Value =
1.143 (float)(multiplier * TimeStampCounterFrequency /