Hardware/CPU/AMD10CPU.cs
changeset 301 d14ce71cef44
parent 298 96263190189a
child 329 756af5ee409e
     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 /