Hardware/CPU/AMD10CPU.cs
changeset 273 2054d5dcb680
parent 271 8635fa73eacc
child 279 6bce967ba1b5
     1.1 --- a/Hardware/CPU/AMD10CPU.cs	Sat Apr 16 14:49:47 2011 +0000
     1.2 +++ b/Hardware/CPU/AMD10CPU.cs	Sat Apr 16 19:26:20 2011 +0000
     1.3 @@ -62,6 +62,7 @@
     1.4      private const ushort FAMILY_11H_MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1303;
     1.5      private const ushort FAMILY_14H_MISCELLANEOUS_CONTROL_DEVICE_ID = 0x1703; 
     1.6      private const uint REPORTED_TEMPERATURE_CONTROL_REGISTER = 0xA4;
     1.7 +    private const uint CLOCK_POWER_TIMING_CONTROL_0_REGISTER = 0xD4;
     1.8  
     1.9      private readonly uint miscellaneousControlAddress;
    1.10      private readonly ushort miscellaneousControlDeviceId;
    1.11 @@ -86,7 +87,7 @@
    1.12          case 0x11: miscellaneousControlDeviceId =
    1.13            FAMILY_11H_MISCELLANEOUS_CONTROL_DEVICE_ID; break;
    1.14          case 0x14: miscellaneousControlDeviceId = 
    1.15 -          FAMILY_11H_MISCELLANEOUS_CONTROL_DEVICE_ID; break;
    1.16 +          FAMILY_14H_MISCELLANEOUS_CONTROL_DEVICE_ID; break;
    1.17          default: miscellaneousControlDeviceId = 0; break;
    1.18        }
    1.19  
    1.20 @@ -170,7 +171,7 @@
    1.21        Ring0.Wrmsr(PERF_CTR_0, 0, 0);
    1.22  
    1.23        long ticks = (long)(timeWindow * Stopwatch.Frequency);
    1.24 -      uint lsbBegin, msbBegin, lsbEnd, msbEnd;
    1.25 +      uint lsbBegin, msbBegin, lsbEnd, msbEnd;      
    1.26  
    1.27        long timeBegin = Stopwatch.GetTimestamp() +
    1.28          (long)Math.Ceiling(0.001 * ticks);
    1.29 @@ -181,10 +182,22 @@
    1.30        Ring0.Rdmsr(PERF_CTR_0, out lsbEnd, out msbEnd);
    1.31  
    1.32        Ring0.Rdmsr(COFVID_STATUS, out eax, out edx);
    1.33 -      uint cpuDid = (eax >> 6) & 7;
    1.34 -      uint cpuFid = eax & 0x1F;
    1.35 -      double coreMultiplier = MultiplierFromIDs(cpuDid, cpuFid);
    1.36 +      double coreMultiplier;
    1.37 +      if (family == 0x14) {               
    1.38 +        uint divisorIdMSD = (eax >> 4) & 0x1F;
    1.39 +        uint divisorIdLSD = eax & 0xF;
    1.40 +        uint value = 0;
    1.41 +        Ring0.ReadPciConfig(miscellaneousControlAddress,
    1.42 +          CLOCK_POWER_TIMING_CONTROL_0_REGISTER, out value);
    1.43 +        uint frequencyId = value & 0x1F;
    1.44  
    1.45 +        coreMultiplier = 
    1.46 +          MultiplierFromIDs(divisorIdMSD, divisorIdLSD, frequencyId);
    1.47 +      } else {
    1.48 +        uint cpuDid = (eax >> 6) & 7;
    1.49 +        uint cpuFid = eax & 0x1F;
    1.50 +        coreMultiplier = MultiplierFromIDs(cpuDid, cpuFid);
    1.51 +      }
    1.52        ulong countBegin = ((ulong)msbBegin << 32) | lsbBegin;
    1.53        ulong countEnd = ((ulong)msbEnd << 32) | lsbEnd;
    1.54  
    1.55 @@ -193,7 +206,7 @@
    1.56          (timeEnd - timeBegin);
    1.57  
    1.58        double busFrequency = coreFrequency / coreMultiplier;
    1.59 -      return 0.5 * Math.Round(2 * TimeStampCounterFrequency / busFrequency);
    1.60 +      return 0.25 * Math.Round(4 * TimeStampCounterFrequency / busFrequency);
    1.61      }
    1.62  
    1.63      protected override uint[] GetMSRs() {
    1.64 @@ -210,15 +223,30 @@
    1.65        r.Append("Time Stamp Counter Multiplier: ");
    1.66        r.AppendLine(timeStampCounterMultiplier.ToString(
    1.67          CultureInfo.InvariantCulture));
    1.68 +      if (family == 0x14) {
    1.69 +        uint value = 0;
    1.70 +        Ring0.ReadPciConfig(miscellaneousControlAddress,
    1.71 +          CLOCK_POWER_TIMING_CONTROL_0_REGISTER, out value);
    1.72 +        r.Append("PCI Register D18F3xD4: ");
    1.73 +        r.AppendLine(value.ToString("X8", CultureInfo.InvariantCulture));
    1.74 +      }
    1.75        r.AppendLine();
    1.76  
    1.77        return r.ToString();
    1.78      }
    1.79  
    1.80 +    // calculate the multiplier for family 10h based on Did and Fid
    1.81      private static double MultiplierFromIDs(uint divisorID, uint frequencyID) {
    1.82        return 0.5 * (frequencyID + 0x10) / (1 << (int)divisorID);
    1.83      }
    1.84  
    1.85 +    // calculate the multiplier for family 14h based on DidMSD, DidLSD and Fid
    1.86 +    private static double MultiplierFromIDs(uint divisorIdMSD, 
    1.87 +      uint divisorIdLSD, uint frequencyId) 
    1.88 +    {
    1.89 +      return (frequencyId + 0x10) / (divisorIdMSD + (divisorIdLSD * 0.25) + 1);
    1.90 +    }
    1.91 +
    1.92      private string ReadFirstLine(Stream stream) {
    1.93        StringBuilder sb = new StringBuilder();
    1.94        try {
    1.95 @@ -268,11 +296,23 @@
    1.96            if (Ring0.RdmsrTx(COFVID_STATUS, out curEax, out curEdx,
    1.97              1UL << cpuid[i][0].Thread)) 
    1.98            {
    1.99 -            // 8:6 CpuDid: current core divisor ID
   1.100 -            // 5:0 CpuFid: current core frequency ID
   1.101 -            uint cpuDid = (curEax >> 6) & 7;
   1.102 -            uint cpuFid = curEax & 0x1F;
   1.103 -            double multiplier = MultiplierFromIDs(cpuDid, cpuFid);
   1.104 +            double multiplier;
   1.105 +            if (family == 0x14) {
   1.106 +              uint divisorIdMSD = (curEax >> 4) & 0x1F;
   1.107 +              uint divisorIdLSD = curEax & 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 +              multiplier =
   1.113 +                MultiplierFromIDs(divisorIdMSD, divisorIdLSD, frequencyId);
   1.114 +            } else {
   1.115 +              // 8:6 CpuDid: current core divisor ID
   1.116 +              // 5:0 CpuFid: current core frequency ID
   1.117 +              uint cpuDid = (curEax >> 6) & 7;
   1.118 +              uint cpuFid = curEax & 0x1F;
   1.119 +              multiplier = MultiplierFromIDs(cpuDid, cpuFid);
   1.120 +            }
   1.121  
   1.122              coreClocks[i].Value = 
   1.123                (float)(multiplier * TimeStampCounterFrequency /