Add Zen 2 CCD temperatures and merged Tdie/Tctl.
Based on the work of @LeagueRaINi Co-Authored-By: RaINi_ <razor13372k@gmail.com>
This commit is contained in:
@@ -93,10 +93,14 @@ namespace LibreHardwareMonitor.Hardware.CPU
|
||||
{
|
||||
private readonly Sensor _coreTemperatureTctl;
|
||||
private readonly Sensor _coreTemperatureTdie;
|
||||
private readonly Sensor _coreTemperatureTctlTdie;
|
||||
private readonly Sensor[] _ccdTemperatures;
|
||||
private readonly Sensor _coreVoltage;
|
||||
private readonly Amd17Cpu _hw;
|
||||
private readonly Sensor _packagePower;
|
||||
private readonly Sensor _socVoltage;
|
||||
private Sensor _ccdsMaxTemperature;
|
||||
private Sensor _ccdsAverageTemperature;
|
||||
private DateTime _lastPwrTime = new DateTime(0);
|
||||
private uint _lastPwrValue;
|
||||
|
||||
@@ -108,20 +112,19 @@ namespace LibreHardwareMonitor.Hardware.CPU
|
||||
_packagePower = new Sensor("Package Power", _hw._sensorPower++, SensorType.Power, _hw, _hw._settings);
|
||||
_coreTemperatureTctl = new Sensor("Core (Tctl)", _hw._sensorTemperatures++, SensorType.Temperature, _hw, _hw._settings);
|
||||
_coreTemperatureTdie = new Sensor("Core (Tdie)", _hw._sensorTemperatures++, SensorType.Temperature, _hw, _hw._settings);
|
||||
_coreTemperatureTctlTdie = new Sensor("Core (Tctl/Tdie)", _hw._sensorTemperatures++, SensorType.Temperature, _hw, _hw._settings);
|
||||
_ccdTemperatures = new Sensor[8]; // Hardcoded until there's a way to get max CCDs.
|
||||
_coreVoltage = new Sensor("Core (SVI2 TFN)", _hw._sensorVoltage++, SensorType.Voltage, _hw, _hw._settings);
|
||||
_socVoltage = new Sensor("SoC (SVI2 TFN)", _hw._sensorVoltage++, SensorType.Voltage, _hw, _hw._settings);
|
||||
|
||||
_hw.ActivateSensor(_packagePower);
|
||||
_hw.ActivateSensor(_coreTemperatureTctl);
|
||||
_hw.ActivateSensor(_coreTemperatureTdie);
|
||||
_hw.ActivateSensor(_coreVoltage);
|
||||
}
|
||||
|
||||
public List<NumaNode> Nodes { get; }
|
||||
|
||||
public void UpdateSensors()
|
||||
{
|
||||
var node = Nodes[0];
|
||||
NumaNode node = Nodes[0];
|
||||
Core core = node?.Cores[0];
|
||||
CpuId cpu = core?.Threads[0];
|
||||
if (cpu == null)
|
||||
@@ -144,23 +147,49 @@ namespace LibreHardwareMonitor.Hardware.CPU
|
||||
|
||||
// THM_TCON_CUR_TMP
|
||||
// CUR_TEMP [31:21]
|
||||
Ring0.WritePciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_THM_TCON_CUR_TMP);
|
||||
Ring0.ReadPciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint temperature);
|
||||
Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_THM_TCON_CUR_TMP);
|
||||
Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint temperature);
|
||||
|
||||
// SVI0_TFN_PLANE0 [0]
|
||||
// SVI0_TFN_PLANE1 [1]
|
||||
Ring0.WritePciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_SVI + 0x8);
|
||||
Ring0.ReadPciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0Tfn);
|
||||
Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_SVI + 0x8);
|
||||
Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0Tfn);
|
||||
|
||||
uint sviPlane0Offset;
|
||||
uint sviPlane1Offset;
|
||||
|
||||
// TODO: find a better way because these will probably keep changing in the future.
|
||||
switch (cpu.Model)
|
||||
{
|
||||
case 0x31: // Threadripper 3000.
|
||||
{
|
||||
sviPlane0Offset = F17H_M01H_SVI + 0x14;
|
||||
sviPlane1Offset = F17H_M01H_SVI + 0x10;
|
||||
break;
|
||||
}
|
||||
case 0x71: // Zen 2.
|
||||
{
|
||||
sviPlane0Offset = F17H_M01H_SVI + 0x10;
|
||||
sviPlane1Offset = F17H_M01H_SVI + 0xC;
|
||||
break;
|
||||
}
|
||||
default: // Zen and Zen+.
|
||||
{
|
||||
sviPlane0Offset = F17H_M01H_SVI + 0xC;
|
||||
sviPlane1Offset = F17H_M01H_SVI + 0x10;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// SVI0_PLANE0_VDDCOR [24:16]
|
||||
// SVI0_PLANE0_IDDCOR [7:0]
|
||||
Ring0.WritePciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_SVI + 0xc);
|
||||
Ring0.ReadPciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0TelPlane0);
|
||||
Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, sviPlane0Offset);
|
||||
Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0TelPlane0);
|
||||
|
||||
// SVI0_PLANE1_VDDCOR [24:16]
|
||||
// SVI0_PLANE1_IDDCOR [7:0]
|
||||
Ring0.WritePciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M01H_SVI + 0x10);
|
||||
Ring0.ReadPciConfig(Ring0.GetPciAddress(0, 0, 0), FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0TelPlane1);
|
||||
Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, sviPlane1Offset);
|
||||
Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint smuSvi0TelPlane1);
|
||||
|
||||
Ring0.ThreadAffinitySet(mask);
|
||||
|
||||
@@ -212,27 +241,92 @@ namespace LibreHardwareMonitor.Hardware.CPU
|
||||
if (tempOffsetFlag)
|
||||
t += -49.0f;
|
||||
|
||||
_coreTemperatureTctl.Value = t;
|
||||
_coreTemperatureTdie.Value = t + offset;
|
||||
if (offset < 0)
|
||||
{
|
||||
_coreTemperatureTctl.Value = t;
|
||||
_coreTemperatureTdie.Value = t + offset;
|
||||
|
||||
_hw.ActivateSensor(_coreTemperatureTctl);
|
||||
_hw.ActivateSensor(_coreTemperatureTdie);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Zen 2 doesn't have an offset so Tdie and Tctl are the same.
|
||||
_coreTemperatureTctlTdie.Value = t;
|
||||
_hw.ActivateSensor(_coreTemperatureTctlTdie);
|
||||
}
|
||||
|
||||
// Tested only on R5 3600 & Threadripper 3960X.
|
||||
for (uint i = 0; i < _ccdTemperatures.Length; i++)
|
||||
{
|
||||
Ring0.WritePciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER, F17H_M70H_CCD1_TEMP + (i * 0x4));
|
||||
Ring0.ReadPciConfig(0x00, FAMILY_17H_PCI_CONTROL_REGISTER + 4, out uint ccdTempData);
|
||||
|
||||
uint ccdTemp = ccdTempData & 0xFFF;
|
||||
if (ccdTemp == 0)
|
||||
continue;
|
||||
|
||||
if (_ccdTemperatures[i] == null)
|
||||
{
|
||||
_hw.ActivateSensor(_ccdTemperatures[i] = new Sensor(
|
||||
$"Core CCD{i + 1} (Tdie)",
|
||||
_hw._sensorTemperatures++,
|
||||
SensorType.Temperature,
|
||||
_hw,
|
||||
_hw._settings));
|
||||
}
|
||||
|
||||
_ccdTemperatures[i].Value = ((ccdTemp * 125) - 305000) * 0.001f;
|
||||
}
|
||||
|
||||
Sensor[] activeCcds = _ccdTemperatures.Where(x => x != null).ToArray();
|
||||
if (activeCcds.Length > 1)
|
||||
{
|
||||
// No need to get the max / average ccds temp if there is only one CCD.
|
||||
|
||||
if (_ccdsMaxTemperature == null)
|
||||
{
|
||||
_hw.ActivateSensor(_ccdsMaxTemperature = new Sensor(
|
||||
"Core CCDs Max (Tdie)",
|
||||
_hw._sensorTemperatures++,
|
||||
SensorType.Temperature,
|
||||
_hw,
|
||||
_hw._settings));
|
||||
}
|
||||
|
||||
if (_ccdsAverageTemperature == null)
|
||||
{
|
||||
_hw.ActivateSensor(_ccdsAverageTemperature = new Sensor(
|
||||
"Core CCDs Average (Tdie)",
|
||||
_hw._sensorTemperatures++,
|
||||
SensorType.Temperature,
|
||||
_hw,
|
||||
_hw._settings));
|
||||
}
|
||||
|
||||
_ccdsMaxTemperature.Value = activeCcds.Max(x => x.Value);
|
||||
_ccdsAverageTemperature.Value = activeCcds.Average(x => x.Value);
|
||||
}
|
||||
|
||||
// voltage
|
||||
double vidStep = 0.00625;
|
||||
const double vidStep = 0.00625;
|
||||
double vcc;
|
||||
uint svi0PlaneXVddCor;
|
||||
|
||||
// Core
|
||||
// Core (0x01).
|
||||
if ((smuSvi0Tfn & 0x01) == 0)
|
||||
{
|
||||
svi0PlaneXVddCor = ((cpu.Model == 0x71 ? smuSvi0TelPlane1 : smuSvi0TelPlane0) >> 16) & 0xff;
|
||||
svi0PlaneXVddCor = (smuSvi0TelPlane0 >> 16) & 0xff;
|
||||
vcc = 1.550 - vidStep * svi0PlaneXVddCor;
|
||||
_coreVoltage.Value = (float)vcc;
|
||||
|
||||
_hw.ActivateSensor(_coreVoltage);
|
||||
}
|
||||
|
||||
// SoC
|
||||
// not every zen cpu has this voltage
|
||||
if (cpu.Model == 0x71 || (smuSvi0Tfn & 0x02) == 0)
|
||||
// SoC (0x02), not every Zen cpu has this voltage.
|
||||
if (cpu.Model == 0x71 || cpu.Model == 0x31 || (smuSvi0Tfn & 0x02) == 0)
|
||||
{
|
||||
svi0PlaneXVddCor = ((cpu.Model == 0x71 ? smuSvi0TelPlane0 : smuSvi0TelPlane1) >> 16) & 0xff;
|
||||
svi0PlaneXVddCor = (smuSvi0TelPlane1 >> 16) & 0xff;
|
||||
vcc = 1.550 - vidStep * svi0PlaneXVddCor;
|
||||
_socVoltage.Value = (float)vcc;
|
||||
|
||||
@@ -243,7 +337,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
|
||||
public void AppendThread(CpuId thread, int numaId, int coreId)
|
||||
{
|
||||
NumaNode node = null;
|
||||
foreach (var n in Nodes)
|
||||
foreach (NumaNode n in Nodes)
|
||||
{
|
||||
if (n.NodeId == numaId)
|
||||
{
|
||||
@@ -281,7 +375,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
|
||||
public void AppendThread(CpuId thread, int coreId)
|
||||
{
|
||||
Core core = null;
|
||||
foreach (var c in Cores)
|
||||
foreach (Core c in Cores)
|
||||
{
|
||||
if (c.CoreId == coreId)
|
||||
core = c;
|
||||
@@ -420,6 +514,7 @@ namespace LibreHardwareMonitor.Hardware.CPU
|
||||
private const uint COFVID_STATUS = 0xC0010071;
|
||||
private const uint F17H_M01H_SVI = 0x0005A000;
|
||||
private const uint F17H_M01H_THM_TCON_CUR_TMP = 0x00059800;
|
||||
private const uint F17H_M70H_CCD1_TEMP = 0x00059954;
|
||||
private const uint F17H_TEMP_OFFSET_FLAG = 0x80000;
|
||||
private const uint FAMILY_17H_PCI_CONTROL_REGISTER = 0x60;
|
||||
private const uint HWCR = 0xC0010015;
|
||||
|
||||
@@ -37,6 +37,7 @@ namespace LibreHardwareMonitor.Hardware
|
||||
IsDefaultHidden = defaultHidden;
|
||||
SensorType = sensorType;
|
||||
_hardware = hardware;
|
||||
|
||||
Parameter[] parameters = new Parameter[parameterDescriptions?.Length ?? 0];
|
||||
for (int i = 0; i < parameters.Length; i++)
|
||||
{
|
||||
@@ -166,29 +167,30 @@ namespace LibreHardwareMonitor.Hardware
|
||||
|
||||
private void SetSensorValuesToSettings()
|
||||
{
|
||||
using (MemoryStream m = new MemoryStream())
|
||||
using (MemoryStream memoryStream = new MemoryStream())
|
||||
{
|
||||
using (GZipStream c = new GZipStream(m, CompressionMode.Compress))
|
||||
using (GZipStream gZipStream = new GZipStream(memoryStream, CompressionMode.Compress))
|
||||
{
|
||||
using (BufferedStream b = new BufferedStream(c, 65536))
|
||||
using (BufferedStream outputStream = new BufferedStream(gZipStream, 65536))
|
||||
{
|
||||
using (BinaryWriter writer = new BinaryWriter(b))
|
||||
using (BinaryWriter binaryWriter = new BinaryWriter(outputStream))
|
||||
{
|
||||
long t = 0;
|
||||
|
||||
foreach (SensorValue sensorValue in _values)
|
||||
{
|
||||
long v = sensorValue.Time.ToBinary();
|
||||
writer.Write(v - t);
|
||||
binaryWriter.Write(v - t);
|
||||
t = v;
|
||||
writer.Write(sensorValue.Value);
|
||||
binaryWriter.Write(sensorValue.Value);
|
||||
}
|
||||
|
||||
writer.Flush();
|
||||
binaryWriter.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_settings.SetValue(new Identifier(Identifier, "values").ToString(), Convert.ToBase64String(m.ToArray()));
|
||||
_settings.SetValue(new Identifier(Identifier, "values").ToString(), Convert.ToBase64String(memoryStream.ToArray()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,20 +205,23 @@ namespace LibreHardwareMonitor.Hardware
|
||||
{
|
||||
byte[] array = Convert.FromBase64String(s);
|
||||
DateTime now = DateTime.UtcNow;
|
||||
using (MemoryStream m = new MemoryStream(array))
|
||||
using (GZipStream c = new GZipStream(m, CompressionMode.Decompress))
|
||||
|
||||
using (MemoryStream memoryStream = new MemoryStream(array))
|
||||
{
|
||||
using (GZipStream gZipStream = new GZipStream(memoryStream, CompressionMode.Decompress))
|
||||
{
|
||||
using (MemoryStream unzip = new MemoryStream())
|
||||
using (MemoryStream destination = new MemoryStream())
|
||||
{
|
||||
c.CopyTo(unzip);
|
||||
unzip.Seek(0, SeekOrigin.Begin);
|
||||
using (BinaryReader reader = new BinaryReader(unzip))
|
||||
gZipStream.CopyTo(destination);
|
||||
destination.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
using (BinaryReader reader = new BinaryReader(destination))
|
||||
{
|
||||
try
|
||||
{
|
||||
long t = 0;
|
||||
long readLen = reader.BaseStream.Length - reader.BaseStream.Position;
|
||||
while (true && readLen > 0)
|
||||
while (readLen > 0)
|
||||
{
|
||||
t += reader.ReadInt64();
|
||||
DateTime time = DateTime.FromBinary(t);
|
||||
@@ -234,9 +239,12 @@ namespace LibreHardwareMonitor.Hardware
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
{
|
||||
// Ignored.
|
||||
}
|
||||
}
|
||||
|
||||
if (_values.Count > 0)
|
||||
|
||||
Reference in New Issue
Block a user