diff --git a/include/gpu.hpp b/include/gpu.hpp index 5b04647..0ea8aaf 100644 --- a/include/gpu.hpp +++ b/include/gpu.hpp @@ -1,14 +1,19 @@ #ifndef GPU_HPP #define GPU_HPP +/* see which we actually need now */ #include #include #include #include #include -#define REL_METRICS_PATH = "/../../gpu_metrics" +#include +#define REL_METRICS_PATH "/../../gpu_metrics" +#define MAX_METRICS_LENGTH 512 + +/* should refactor this struct so its a little cleaner and closer to gpu_metrics */ struct gpu_t { uint16_t fan_speed = 0; uint16_t core_clock = 0; @@ -31,15 +36,8 @@ struct gpu_t { uint8_t umc_usage = 0; }; -struct GpuMetricsHeader_t { - uint16_t structure_size = 0; - uint8_t format_revision = 0; - uint8_t content_revision = 0; -}; - std::string detectGpuHwmon(std::string pci); -gpu_t getGpu(GpuMetricsHeader_t header, std::string hw); +bool checkForMetrics(std::string hwmon); gpu_t getGpu(std::string hw, bool hasMetrics); -GpuMetricsHeader_t getGpuMetricsHeader(std::string path); -#endif \ No newline at end of file +#endif diff --git a/include/gpu_structs.hpp b/include/gpu_structs.hpp new file mode 100644 index 0000000..a6e7829 --- /dev/null +++ b/include/gpu_structs.hpp @@ -0,0 +1,795 @@ +#include + +/* STRUCTS COPIED WHOLESALE FROM LINUX SOURCE CODE, formatted and wrapped around a namespace +https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/amd/include/kgd_pp_interface.h */ + +#define NUM_HBM_INSTANCES 4 +#define NUM_XGMI_LINKS 8 +#define MAX_GFX_CLKS 8 +#define MAX_CLKS 4 +#define NUM_VCN 4 +#define NUM_JPEG_ENG 32 +#define NUM_JPEG_ENG_V1 40 +#define MAX_XCC 8 +#define NUM_XCP 8 + +namespace gpu { + +struct metrics_table_header { + uint16_t structure_size; + uint8_t format_revision; + uint8_t content_revision; +}; + +/* + * gpu_metrics_v1_0 is not recommended as it's not naturally aligned. + * Use gpu_metrics_v1_1 or later instead. + */ +struct gpu_metrics_v1_0 { + struct metrics_table_header common_header; + + /* Driver attached timestamp (in ns) */ + uint64_t system_clock_counter; + + /* Temperature */ + uint16_t temperature_edge; + uint16_t temperature_hotspot; + uint16_t temperature_mem; + uint16_t temperature_vrgfx; + uint16_t temperature_vrsoc; + uint16_t temperature_vrmem; + + /* Utilization */ + uint16_t average_gfx_activity; + uint16_t average_umc_activity; // memory controller + uint16_t average_mm_activity; // UVD or VCN + + /* Power/Energy */ + uint16_t average_socket_power; + uint32_t energy_accumulator; + + /* Average clocks */ + uint16_t average_gfxclk_frequency; + uint16_t average_socclk_frequency; + uint16_t average_uclk_frequency; + uint16_t average_vclk0_frequency; + uint16_t average_dclk0_frequency; + uint16_t average_vclk1_frequency; + uint16_t average_dclk1_frequency; + + /* Current clocks */ + uint16_t current_gfxclk; + uint16_t current_socclk; + uint16_t current_uclk; + uint16_t current_vclk0; + uint16_t current_dclk0; + uint16_t current_vclk1; + uint16_t current_dclk1; + + /* Throttle status */ + uint32_t throttle_status; + + /* Fans */ + uint16_t current_fan_speed; + + /* Link width/speed */ + uint8_t pcie_link_width; + uint8_t pcie_link_speed; // in 0.1 GT/s +}; + +struct gpu_metrics_v1_1 { + struct metrics_table_header common_header; + + /* Temperature */ + uint16_t temperature_edge; + uint16_t temperature_hotspot; + uint16_t temperature_mem; + uint16_t temperature_vrgfx; + uint16_t temperature_vrsoc; + uint16_t temperature_vrmem; + + /* Utilization */ + uint16_t average_gfx_activity; + uint16_t average_umc_activity; // memory controller + uint16_t average_mm_activity; // UVD or VCN + + /* Power/Energy */ + uint16_t average_socket_power; + uint64_t energy_accumulator; + + /* Driver attached timestamp (in ns) */ + uint64_t system_clock_counter; + + /* Average clocks */ + uint16_t average_gfxclk_frequency; + uint16_t average_socclk_frequency; + uint16_t average_uclk_frequency; + uint16_t average_vclk0_frequency; + uint16_t average_dclk0_frequency; + uint16_t average_vclk1_frequency; + uint16_t average_dclk1_frequency; + + /* Current clocks */ + uint16_t current_gfxclk; + uint16_t current_socclk; + uint16_t current_uclk; + uint16_t current_vclk0; + uint16_t current_dclk0; + uint16_t current_vclk1; + uint16_t current_dclk1; + + /* Throttle status */ + uint32_t throttle_status; + + /* Fans */ + uint16_t current_fan_speed; + + /* Link width/speed */ + uint16_t pcie_link_width; + uint16_t pcie_link_speed; // in 0.1 GT/s + + uint16_t padding; + + uint32_t gfx_activity_acc; + uint32_t mem_activity_acc; + + uint16_t temperature_hbm[NUM_HBM_INSTANCES]; +}; + +struct gpu_metrics_v1_2 { + struct metrics_table_header common_header; + + /* Temperature */ + uint16_t temperature_edge; + uint16_t temperature_hotspot; + uint16_t temperature_mem; + uint16_t temperature_vrgfx; + uint16_t temperature_vrsoc; + uint16_t temperature_vrmem; + + /* Utilization */ + uint16_t average_gfx_activity; + uint16_t average_umc_activity; // memory controller + uint16_t average_mm_activity; // UVD or VCN + + /* Power/Energy */ + uint16_t average_socket_power; + uint64_t energy_accumulator; + + /* Driver attached timestamp (in ns) */ + uint64_t system_clock_counter; + + /* Average clocks */ + uint16_t average_gfxclk_frequency; + uint16_t average_socclk_frequency; + uint16_t average_uclk_frequency; + uint16_t average_vclk0_frequency; + uint16_t average_dclk0_frequency; + uint16_t average_vclk1_frequency; + uint16_t average_dclk1_frequency; + + /* Current clocks */ + uint16_t current_gfxclk; + uint16_t current_socclk; + uint16_t current_uclk; + uint16_t current_vclk0; + uint16_t current_dclk0; + uint16_t current_vclk1; + uint16_t current_dclk1; + + /* Throttle status (ASIC dependent) */ + uint32_t throttle_status; + + /* Fans */ + uint16_t current_fan_speed; + + /* Link width/speed */ + uint16_t pcie_link_width; + uint16_t pcie_link_speed; // in 0.1 GT/s + + uint16_t padding; + + uint32_t gfx_activity_acc; + uint32_t mem_activity_acc; + + uint16_t temperature_hbm[NUM_HBM_INSTANCES]; + + /* PMFW attached timestamp (10ns resolution) */ + uint64_t firmware_timestamp; +}; + +struct gpu_metrics_v1_3 { + struct metrics_table_header common_header; + + /* Temperature */ + uint16_t temperature_edge; + uint16_t temperature_hotspot; + uint16_t temperature_mem; + uint16_t temperature_vrgfx; + uint16_t temperature_vrsoc; + uint16_t temperature_vrmem; + + /* Utilization */ + uint16_t average_gfx_activity; + uint16_t average_umc_activity; // memory controller + uint16_t average_mm_activity; // UVD or VCN + + /* Power/Energy */ + uint16_t average_socket_power; + uint64_t energy_accumulator; + + /* Driver attached timestamp (in ns) */ + uint64_t system_clock_counter; + + /* Average clocks */ + uint16_t average_gfxclk_frequency; + uint16_t average_socclk_frequency; + uint16_t average_uclk_frequency; + uint16_t average_vclk0_frequency; + uint16_t average_dclk0_frequency; + uint16_t average_vclk1_frequency; + uint16_t average_dclk1_frequency; + + /* Current clocks */ + uint16_t current_gfxclk; + uint16_t current_socclk; + uint16_t current_uclk; + uint16_t current_vclk0; + uint16_t current_dclk0; + uint16_t current_vclk1; + uint16_t current_dclk1; + + /* Throttle status */ + uint32_t throttle_status; + + /* Fans */ + uint16_t current_fan_speed; + + /* Link width/speed */ + uint16_t pcie_link_width; + uint16_t pcie_link_speed; // in 0.1 GT/s + + uint16_t padding; + + uint32_t gfx_activity_acc; + uint32_t mem_activity_acc; + + uint16_t temperature_hbm[NUM_HBM_INSTANCES]; + + /* PMFW attached timestamp (10ns resolution) */ + uint64_t firmware_timestamp; + + /* Voltage (mV) */ + uint16_t voltage_soc; + uint16_t voltage_gfx; + uint16_t voltage_mem; + + uint16_t padding1; + + /* Throttle status (ASIC independent) */ + uint64_t indep_throttle_status; +}; + +struct gpu_metrics_v1_4 { + struct metrics_table_header common_header; + + /* Temperature (Celsius) */ + uint16_t temperature_hotspot; + uint16_t temperature_mem; + uint16_t temperature_vrsoc; + + /* Power (Watts) */ + uint16_t curr_socket_power; + + /* Utilization (%) */ + uint16_t average_gfx_activity; + uint16_t average_umc_activity; // memory controller + uint16_t vcn_activity[NUM_VCN]; + + /* Energy (15.259uJ (2^-16) units) */ + uint64_t energy_accumulator; + + /* Driver attached timestamp (in ns) */ + uint64_t system_clock_counter; + + /* Throttle status */ + uint32_t throttle_status; + + /* Clock Lock Status. Each bit corresponds to clock instance */ + uint32_t gfxclk_lock_status; + + /* Link width (number of lanes) and speed (in 0.1 GT/s) */ + uint16_t pcie_link_width; + uint16_t pcie_link_speed; + + /* XGMI bus width and bitrate (in Gbps) */ + uint16_t xgmi_link_width; + uint16_t xgmi_link_speed; + + /* Utilization Accumulated (%) */ + uint32_t gfx_activity_acc; + uint32_t mem_activity_acc; + + /*PCIE accumulated bandwidth (GB/sec) */ + uint64_t pcie_bandwidth_acc; + + /*PCIE instantaneous bandwidth (GB/sec) */ + uint64_t pcie_bandwidth_inst; + + /* PCIE L0 to recovery state transition accumulated count */ + uint64_t pcie_l0_to_recov_count_acc; + + /* PCIE replay accumulated count */ + uint64_t pcie_replay_count_acc; + + /* PCIE replay rollover accumulated count */ + uint64_t pcie_replay_rover_count_acc; + + /* XGMI accumulated data transfer size(KiloBytes) */ + uint64_t xgmi_read_data_acc[NUM_XGMI_LINKS]; + uint64_t xgmi_write_data_acc[NUM_XGMI_LINKS]; + + /* PMFW attached timestamp (10ns resolution) */ + uint64_t firmware_timestamp; + + /* Current clocks (Mhz) */ + uint16_t current_gfxclk[MAX_GFX_CLKS]; + uint16_t current_socclk[MAX_CLKS]; + uint16_t current_vclk0[MAX_CLKS]; + uint16_t current_dclk0[MAX_CLKS]; + uint16_t current_uclk; + + uint16_t padding; +}; + +struct gpu_metrics_v1_5 { + struct metrics_table_header common_header; + + /* Temperature (Celsius) */ + uint16_t temperature_hotspot; + uint16_t temperature_mem; + uint16_t temperature_vrsoc; + + /* Power (Watts) */ + uint16_t curr_socket_power; + + /* Utilization (%) */ + uint16_t average_gfx_activity; + uint16_t average_umc_activity; // memory controller + uint16_t vcn_activity[NUM_VCN]; + uint16_t jpeg_activity[NUM_JPEG_ENG]; + + /* Energy (15.259uJ (2^-16) units) */ + uint64_t energy_accumulator; + + /* Driver attached timestamp (in ns) */ + uint64_t system_clock_counter; + + /* Throttle status */ + uint32_t throttle_status; + + /* Clock Lock Status. Each bit corresponds to clock instance */ + uint32_t gfxclk_lock_status; + + /* Link width (number of lanes) and speed (in 0.1 GT/s) */ + uint16_t pcie_link_width; + uint16_t pcie_link_speed; + + /* XGMI bus width and bitrate (in Gbps) */ + uint16_t xgmi_link_width; + uint16_t xgmi_link_speed; + + /* Utilization Accumulated (%) */ + uint32_t gfx_activity_acc; + uint32_t mem_activity_acc; + + /*PCIE accumulated bandwidth (GB/sec) */ + uint64_t pcie_bandwidth_acc; + + /*PCIE instantaneous bandwidth (GB/sec) */ + uint64_t pcie_bandwidth_inst; + + /* PCIE L0 to recovery state transition accumulated count */ + uint64_t pcie_l0_to_recov_count_acc; + + /* PCIE replay accumulated count */ + uint64_t pcie_replay_count_acc; + + /* PCIE replay rollover accumulated count */ + uint64_t pcie_replay_rover_count_acc; + + /* PCIE NAK sent accumulated count */ + uint32_t pcie_nak_sent_count_acc; + + /* PCIE NAK received accumulated count */ + uint32_t pcie_nak_rcvd_count_acc; + + /* XGMI accumulated data transfer size(KiloBytes) */ + uint64_t xgmi_read_data_acc[NUM_XGMI_LINKS]; + uint64_t xgmi_write_data_acc[NUM_XGMI_LINKS]; + + /* PMFW attached timestamp (10ns resolution) */ + uint64_t firmware_timestamp; + + /* Current clocks (Mhz) */ + uint16_t current_gfxclk[MAX_GFX_CLKS]; + uint16_t current_socclk[MAX_CLKS]; + uint16_t current_vclk0[MAX_CLKS]; + uint16_t current_dclk0[MAX_CLKS]; + uint16_t current_uclk; + + uint16_t padding; +}; + +/* + * gpu_metrics_v2_0 is not recommended as it's not naturally aligned. + * Use gpu_metrics_v2_1 or later instead. + */ +struct gpu_metrics_v2_0 { + struct metrics_table_header common_header; + + /* Driver attached timestamp (in ns) */ + uint64_t system_clock_counter; + + /* Temperature */ + uint16_t temperature_gfx; // gfx temperature on APUs + uint16_t temperature_soc; // soc temperature on APUs + uint16_t temperature_core[8]; // CPU core temperature on APUs + uint16_t temperature_l3[2]; + + /* Utilization */ + uint16_t average_gfx_activity; + uint16_t average_mm_activity; // UVD or VCN + + /* Power/Energy */ + uint16_t average_socket_power; // dGPU + APU power on A + A platform + uint16_t average_cpu_power; + uint16_t average_soc_power; + uint16_t average_gfx_power; + uint16_t average_core_power[8]; // CPU core power on APUs + + /* Average clocks */ + uint16_t average_gfxclk_frequency; + uint16_t average_socclk_frequency; + uint16_t average_uclk_frequency; + uint16_t average_fclk_frequency; + uint16_t average_vclk_frequency; + uint16_t average_dclk_frequency; + + /* Current clocks */ + uint16_t current_gfxclk; + uint16_t current_socclk; + uint16_t current_uclk; + uint16_t current_fclk; + uint16_t current_vclk; + uint16_t current_dclk; + uint16_t current_coreclk[8]; // CPU core clocks + uint16_t current_l3clk[2]; + + /* Throttle status */ + uint32_t throttle_status; + + /* Fans */ + uint16_t fan_pwm; + + uint16_t padding; +}; + +struct gpu_metrics_v2_1 { + struct metrics_table_header common_header; + + /* Temperature */ + uint16_t temperature_gfx; // gfx temperature on APUs + uint16_t temperature_soc; // soc temperature on APUs + uint16_t temperature_core[8]; // CPU core temperature on APUs + uint16_t temperature_l3[2]; + + /* Utilization */ + uint16_t average_gfx_activity; + uint16_t average_mm_activity; // UVD or VCN + + /* Driver attached timestamp (in ns) */ + uint64_t system_clock_counter; + + /* Power/Energy */ + uint16_t average_socket_power; // dGPU + APU power on A + A platform + uint16_t average_cpu_power; + uint16_t average_soc_power; + uint16_t average_gfx_power; + uint16_t average_core_power[8]; // CPU core power on APUs + + /* Average clocks */ + uint16_t average_gfxclk_frequency; + uint16_t average_socclk_frequency; + uint16_t average_uclk_frequency; + uint16_t average_fclk_frequency; + uint16_t average_vclk_frequency; + uint16_t average_dclk_frequency; + + /* Current clocks */ + uint16_t current_gfxclk; + uint16_t current_socclk; + uint16_t current_uclk; + uint16_t current_fclk; + uint16_t current_vclk; + uint16_t current_dclk; + uint16_t current_coreclk[8]; // CPU core clocks + uint16_t current_l3clk[2]; + + /* Throttle status */ + uint32_t throttle_status; + + /* Fans */ + uint16_t fan_pwm; + + uint16_t padding[3]; +}; + +struct gpu_metrics_v2_2 { + struct metrics_table_header common_header; + + /* Temperature */ + uint16_t temperature_gfx; // gfx temperature on APUs + uint16_t temperature_soc; // soc temperature on APUs + uint16_t temperature_core[8]; // CPU core temperature on APUs + uint16_t temperature_l3[2]; + + /* Utilization */ + uint16_t average_gfx_activity; + uint16_t average_mm_activity; // UVD or VCN + + /* Driver attached timestamp (in ns) */ + uint64_t system_clock_counter; + + /* Power/Energy */ + uint16_t average_socket_power; // dGPU + APU power on A + A platform + uint16_t average_cpu_power; + uint16_t average_soc_power; + uint16_t average_gfx_power; + uint16_t average_core_power[8]; // CPU core power on APUs + + /* Average clocks */ + uint16_t average_gfxclk_frequency; + uint16_t average_socclk_frequency; + uint16_t average_uclk_frequency; + uint16_t average_fclk_frequency; + uint16_t average_vclk_frequency; + uint16_t average_dclk_frequency; + + /* Current clocks */ + uint16_t current_gfxclk; + uint16_t current_socclk; + uint16_t current_uclk; + uint16_t current_fclk; + uint16_t current_vclk; + uint16_t current_dclk; + uint16_t current_coreclk[8]; // CPU core clocks + uint16_t current_l3clk[2]; + + /* Throttle status (ASIC dependent) */ + uint32_t throttle_status; + + /* Fans */ + uint16_t fan_pwm; + + uint16_t padding[3]; + + /* Throttle status (ASIC independent) */ + uint64_t indep_throttle_status; +}; + +struct gpu_metrics_v2_3 { + struct metrics_table_header common_header; + + /* Temperature */ + uint16_t temperature_gfx; // gfx temperature on APUs + uint16_t temperature_soc; // soc temperature on APUs + uint16_t temperature_core[8]; // CPU core temperature on APUs + uint16_t temperature_l3[2]; + + /* Utilization */ + uint16_t average_gfx_activity; + uint16_t average_mm_activity; // UVD or VCN + + /* Driver attached timestamp (in ns) */ + uint64_t system_clock_counter; + + /* Power/Energy */ + uint16_t average_socket_power; // dGPU + APU power on A + A platform + uint16_t average_cpu_power; + uint16_t average_soc_power; + uint16_t average_gfx_power; + uint16_t average_core_power[8]; // CPU core power on APUs + + /* Average clocks */ + uint16_t average_gfxclk_frequency; + uint16_t average_socclk_frequency; + uint16_t average_uclk_frequency; + uint16_t average_fclk_frequency; + uint16_t average_vclk_frequency; + uint16_t average_dclk_frequency; + + /* Current clocks */ + uint16_t current_gfxclk; + uint16_t current_socclk; + uint16_t current_uclk; + uint16_t current_fclk; + uint16_t current_vclk; + uint16_t current_dclk; + uint16_t current_coreclk[8]; // CPU core clocks + uint16_t current_l3clk[2]; + + /* Throttle status (ASIC dependent) */ + uint32_t throttle_status; + + /* Fans */ + uint16_t fan_pwm; + + uint16_t padding[3]; + + /* Throttle status (ASIC independent) */ + uint64_t indep_throttle_status; + + /* Average Temperature */ + uint16_t average_temperature_gfx; // average gfx temperature on APUs + uint16_t average_temperature_soc; // average soc temperature on APUs + uint16_t average_temperature_core[8]; // average CPU core temperature on APUs + uint16_t average_temperature_l3[2]; +}; + +struct gpu_metrics_v2_4 { + struct metrics_table_header common_header; + + /* Temperature (unit: centi-Celsius) */ + uint16_t temperature_gfx; + uint16_t temperature_soc; + uint16_t temperature_core[8]; + uint16_t temperature_l3[2]; + + /* Utilization (unit: centi) */ + uint16_t average_gfx_activity; + uint16_t average_mm_activity; + + /* Driver attached timestamp (in ns) */ + uint64_t system_clock_counter; + + /* Power/Energy (unit: mW) */ + uint16_t average_socket_power; + uint16_t average_cpu_power; + uint16_t average_soc_power; + uint16_t average_gfx_power; + uint16_t average_core_power[8]; + + /* Average clocks (unit: MHz) */ + uint16_t average_gfxclk_frequency; + uint16_t average_socclk_frequency; + uint16_t average_uclk_frequency; + uint16_t average_fclk_frequency; + uint16_t average_vclk_frequency; + uint16_t average_dclk_frequency; + + /* Current clocks (unit: MHz) */ + uint16_t current_gfxclk; + uint16_t current_socclk; + uint16_t current_uclk; + uint16_t current_fclk; + uint16_t current_vclk; + uint16_t current_dclk; + uint16_t current_coreclk[8]; + uint16_t current_l3clk[2]; + + /* Throttle status (ASIC dependent) */ + uint32_t throttle_status; + + /* Fans */ + uint16_t fan_pwm; + + uint16_t padding[3]; + + /* Throttle status (ASIC independent) */ + uint64_t indep_throttle_status; + + /* Average Temperature (unit: centi-Celsius) */ + uint16_t average_temperature_gfx; + uint16_t average_temperature_soc; + uint16_t average_temperature_core[8]; + uint16_t average_temperature_l3[2]; + + /* Power/Voltage (unit: mV) */ + uint16_t average_cpu_voltage; + uint16_t average_soc_voltage; + uint16_t average_gfx_voltage; + + /* Power/Current (unit: mA) */ + uint16_t average_cpu_current; + uint16_t average_soc_current; + uint16_t average_gfx_current; +}; + +struct gpu_metrics_v3_0 { + struct metrics_table_header common_header; + + /* Temperature */ + /* gfx temperature on APUs */ + uint16_t temperature_gfx; + /* soc temperature on APUs */ + uint16_t temperature_soc; + /* CPU core temperature on APUs */ + uint16_t temperature_core[16]; + /* skin temperature on APUs */ + uint16_t temperature_skin; + + /* Utilization */ + /* time filtered GFX busy % [0-100] */ + uint16_t average_gfx_activity; + /* time filtered VCN busy % [0-100] */ + uint16_t average_vcn_activity; + /* time filtered IPU per-column busy % [0-100] */ + uint16_t average_ipu_activity[8]; + /* time filtered per-core C0 residency % [0-100]*/ + uint16_t average_core_c0_activity[16]; + /* time filtered DRAM read bandwidth [MB/sec] */ + uint16_t average_dram_reads; + /* time filtered DRAM write bandwidth [MB/sec] */ + uint16_t average_dram_writes; + /* time filtered IPU read bandwidth [MB/sec] */ + uint16_t average_ipu_reads; + /* time filtered IPU write bandwidth [MB/sec] */ + uint16_t average_ipu_writes; + + /* Driver attached timestamp (in ns) */ + uint64_t system_clock_counter; + + /* Power/Energy */ + /* time filtered power used for PPT/STAPM [APU+dGPU] [mW] */ + uint32_t average_socket_power; + /* time filtered IPU power [mW] */ + uint16_t average_ipu_power; + /* time filtered APU power [mW] */ + uint32_t average_apu_power; + /* time filtered GFX power [mW] */ + uint32_t average_gfx_power; + /* time filtered dGPU power [mW] */ + uint32_t average_dgpu_power; + /* time filtered sum of core power across all cores in the socket [mW] */ + uint32_t average_all_core_power; + /* calculated core power [mW] */ + uint16_t average_core_power[16]; + /* time filtered total system power [mW] */ + uint16_t average_sys_power; + /* maximum IRM defined STAPM power limit [mW] */ + uint16_t stapm_power_limit; + /* time filtered STAPM power limit [mW] */ + uint16_t current_stapm_power_limit; + + /* time filtered clocks [MHz] */ + uint16_t average_gfxclk_frequency; + uint16_t average_socclk_frequency; + uint16_t average_vpeclk_frequency; + uint16_t average_ipuclk_frequency; + uint16_t average_fclk_frequency; + uint16_t average_vclk_frequency; + uint16_t average_uclk_frequency; + uint16_t average_mpipu_frequency; + + /* Current clocks */ + /* target core frequency [MHz] */ + uint16_t current_coreclk[16]; + /* CCLK frequency limit enforced on classic cores [MHz] */ + uint16_t current_core_maxfreq; + /* GFXCLK frequency limit enforced on GFX [MHz] */ + uint16_t current_gfx_maxfreq; + + /* Throttle Residency (ASIC dependent) */ + uint32_t throttle_residency_prochot; + uint32_t throttle_residency_spl; + uint32_t throttle_residency_fppt; + uint32_t throttle_residency_sppt; + uint32_t throttle_residency_thm_core; + uint32_t throttle_residency_thm_gfx; + uint32_t throttle_residency_thm_soc; + + /* Metrics table alpha filter time constant [us] */ + uint32_t time_filter_alphavalue; +}; +} // namespace gpu \ No newline at end of file diff --git a/src/gpu.cpp b/src/gpu.cpp index 9f7e0fc..6729255 100644 --- a/src/gpu.cpp +++ b/src/gpu.cpp @@ -6,100 +6,7 @@ have a gpu_t getGpu(std::string path, bool hasMetrics) function maybe have a read pp_table function MAYBE PASS A POINTER TO SENSORS/SENSORS->GPU TO FUNCS - -general order of operation - 1. [main] get hwmon path from the detectGpuHwmon func - 2. [main] check if we have gpu_metrics present and set hasMetrics accordingly - 3. [main, loop] keep calling getGpu with hasMetrics - 3. [gpu] getGpu called, parses whatever metrics we read from sysfs, then checks if hasMetrics == true - - if true, reads file at (hwmon + REL_METRICS_PATH) into buf - - reads first 4 bytes into GpuMetricsHeader_t with reinterpret_cast - - parses them for format and content version - - skips first 4 bytes of the buf and reinterpret_casts the rest into a correct gpu_metrics type (switch case?) - - populates gpu_t with values from gpu_metrics - - if false, reads the rest of relevant metrics from sysfs - - returns gpu_t - - */ - -struct [[gnu::packed]] GpuMetrics_v1_1_t { - uint16_t temperature_edge; - uint16_t temperature_hotspot; - uint16_t temperature_mem; - uint16_t temperature_vrgfx; - uint16_t temperature_vrsoc; - uint16_t temperature_vrmem; - uint16_t average_gfx_activity; - uint16_t average_umc_activity; - uint16_t average_mm_activity; - uint16_t average_socket_power; - uint64_t energy_accumulator; - uint64_t system_clock_counter; - uint16_t average_gfxclk_frequency; - uint16_t average_socclk_frequency; - uint16_t average_uclk_frequency; - uint16_t average_vclk0_frequency; - uint16_t average_dclk0_frequency; - uint16_t average_vclk1_frequency; - uint16_t average_dclk1_frequency; - uint16_t current_gfxclk; - uint16_t current_socclk; - uint16_t current_uclk; - uint16_t current_vclk0; - uint16_t current_dclk0; - uint16_t current_vclk1; - uint16_t current_dclk1; - uint32_t throttle_status; - uint16_t current_fan_speed; - uint16_t pcie_link_width; - uint16_t pcie_link_speed; - uint16_t padding; - uint32_t gfx_activity_acc; - uint32_t mem_activity_acc; - uint16_t temperature_hbm; -}; - -struct [[gnu::packed]] GpuMetrics_v1_3_t { - uint16_t temperature_edge; - uint16_t temperature_hotspot; - uint16_t temperature_mem; - uint16_t temperature_vrgfx; - uint16_t temperature_vrsoc; - uint16_t temperature_vrmem; - uint16_t average_gfx_activity; - uint16_t average_umc_activity; - uint16_t average_mm_activity; - uint16_t average_socket_power; - uint64_t energy_accumulator; - uint64_t system_clock_counter; - uint16_t average_gfxclk_frequency; - uint16_t average_socclk_frequency; - uint16_t average_uclk_frequency; - uint16_t average_vclk0_frequency; - uint16_t average_dclk0_frequency; - uint16_t average_vclk1_frequency; - uint16_t average_dclk1_frequency; - uint16_t current_gfxclk; - uint16_t current_socclk; - uint16_t current_uclk; - uint16_t current_vclk0; - uint16_t current_dclk0; - uint16_t current_vclk1; - uint16_t current_dclk1; - uint32_t throttle_status; - uint16_t current_fan_speed; - uint16_t pcie_link_width; - uint16_t pcie_link_speed; - uint16_t padding; - uint32_t gfx_activity_acc; - uint32_t mem_activity_acc; - uint16_t temperature_hbm; - uint64_t firmware_timestamp; - uint16_t voltage_soc; - uint16_t voltage_gfx; - uint16_t voltage_mem; - uint8_t padding1; -}; +*/ std::string detectGpuHwmon(std::string pci) { std::string path = getFirstDir("/sys/bus/pci/devices/" + pci + "/hwmon"); @@ -107,87 +14,60 @@ std::string detectGpuHwmon(std::string pci) { return path; } -GpuMetricsHeader_t getGpuMetricsHeader(std::string path) { - GpuMetricsHeader_t header; - std::ifstream f(path, std::ios::binary); - if (f.good()) { - f.read(reinterpret_cast(&header), sizeof(header)); - std::println("[GpuMetrics] header at path {} read, GpuMetrics_v{}_{}, size {}", path, header.format_revision, header.content_revision, header.structure_size); - f.close(); - } else { - std::println("[GpuMetrics] error reading header at path {} (wrong card # ?)", path); // should be err +bool checkForMetrics(std::string hwmon) { + if (FILE* file = fopen((hwmon + REL_METRICS_PATH).c_str(), "r")) { + fclose(file); + std::println("[GpuMetrics] found metrics file"); + return true; } - - return header; + return false; } - -/* will return empty metric if fails */ -auto getGpuMetrics(GpuMetricsHeader_t h, std::string path) { - GpuMetrics_v1_3_t metrics; - // void* raw_data; - uint8_t rev = h.format_revision * 10 + h.content_revision; - // const auto* metrics = reinterpret_cast(raw_data); // raw data is actual metrics read from disk - - switch (rev) { - case 13: { - std::ifstream f(path, std::ios::binary); - if (f.good()) { - f.ignore(sizeof(h)); // skip header - f.read(reinterpret_cast(&metrics), sizeof(metrics)); - f.close(); - } - } break; - } - - return metrics; -} - -// clean abstraction of gpu_metrics + extra metrics from fs, works with rx7800xt -gpu_t getGpu(GpuMetricsHeader_t header, std::string hw) { +gpu_t getGpuFromMetrics(std::string hwmon) { gpu_t gpu; - uint8_t hwmon = 4; + char raw_metrics[MAX_METRICS_LENGTH]; + if(!readFile2(hwmon + REL_METRICS_PATH, raw_metrics, sizeof(raw_metrics))) return gpu; // return empty struct if cant read metrics + auto header = reinterpret_cast(raw_metrics); - // these are always read from fs - gpu.fan_speed = std::stol(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon) + "/fan1_input")); - gpu.vcore = std::stol(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon) + "/in0_input")) / 1000.0; - gpu.power_cap = std::stol(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon) + "/power1_cap", 3)); - gpu.power_max = std::stol(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon) + "/power1_cap_max", 3)); - gpu.fan_pwm = std::stoi(readFile(hwmon + "/pwm1", 4)) * 100 / 256; // not super useful - gpu.vram_used = std::stoul(readFile(hw + "/mem_info_vram_used")); - gpu.vram_total = std::stoul(readFile(hw + "/mem_info_vram_total")); + switch (header->format_revision * 10 + header->content_revision) { - auto metrics = getGpuMetrics(header, hw + "/gpu_metrics"); + /* rx7800xt */ + case 13: { + auto metrics = reinterpret_cast(raw_metrics); + gpu.core_clock = metrics->average_vclk1_frequency; // why not gfxclock? + gpu.mem_clock = metrics->average_gfxclk_frequency; // why gfxclock? min mem clock seems to be 96mhz, this is probably including time sleeping + gpu.core_usage = metrics->average_gfx_activity; + gpu.media_usage = metrics->average_mm_activity; + gpu.umc_usage = metrics->average_umc_activity; + gpu.edge_temp = metrics->temperature_edge; + gpu.hotspot_temp = metrics->temperature_hotspot; + gpu.mem_temp = metrics->temperature_mem; + gpu.gfx_vrm_temp = metrics->temperature_vrgfx; + gpu.soc_vrm_temp = metrics->temperature_vrsoc; + gpu.mem_vrm_temp = metrics->temperature_vrmem; + gpu.power_avg = metrics->average_socket_power; + break; + } - // check if metrics valid, if not use fs - if (header.structure_size != 0) { - gpu.core_clock = metrics.average_vclk1_frequency; // why not gfxclock? - gpu.mem_clock = metrics.average_gfxclk_frequency; // why gfxclock? min mem clock seems to be 96mhz, this is probably including time sleeping - gpu.core_usage = metrics.average_gfx_activity; - gpu.media_usage = metrics.average_mm_activity; - gpu.umc_usage = metrics.average_umc_activity; - gpu.edge_temp = metrics.temperature_edge; - gpu.hotspot_temp = metrics.temperature_hotspot; - gpu.mem_temp = metrics.temperature_mem; - gpu.gfx_vrm_temp = metrics.temperature_vrgfx; - gpu.soc_vrm_temp = metrics.temperature_vrsoc; - gpu.mem_vrm_temp = metrics.temperature_vrmem; - gpu.power_avg = metrics.average_socket_power; - } else { - gpu.core_clock = std::stoll(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon) + "/freq1_input", 16)) / 1000000; - gpu.mem_clock = std::stoll(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon) + "/freq2_input", 16)) / 1000000; - gpu.vcore = std::stod(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon) + "/in0_input", 8)) / 1000.0; - gpu.power_avg = std::stol(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon) + "/power1_input", 3)); - gpu.edge_temp = std::stol(readFile(hw + "/hwmon/hwmon" + std::to_string(hwmon) + "/temp1_input", 2)); - gpu.core_usage = std::stoi(readFile(hw + "/gpu_busy_percent")); + /* ryzen 5 5600g */ + case 22: { + auto metrics = reinterpret_cast(raw_metrics); + gpu.edge_temp = metrics->temperature_gfx / 100; + gpu.power_avg = metrics->average_gfx_power; + gpu.core_usage = metrics->average_gfx_activity; + break; + } + + /* werid hardware i probably dont like */ + default: { + std::println("[GpuMetrics] Unsupported gpu_metrics_v{}_{}", header->format_revision, header->content_revision); + break; + } } - if (gpu.fan_speed > 9999) - gpu.fan_speed = 9999; - return gpu; } -gpu_t getGpu(std::string hwmon, bool hasMetrics) { +gpu_t getGpuFromFs(std::string hwmon) { gpu_t gpu; // these are always read from fs @@ -195,21 +75,23 @@ gpu_t getGpu(std::string hwmon, bool hasMetrics) { gpu.vcore = std::stol(readFile(hwmon + "/in0_input", 4)) / 1000.0; gpu.power_cap = std::stol(readFile(hwmon + "/power1_cap", 16)) / 1000000; // gpu.power_max = std::stol(readFile(hwmon + "/power1_cap_max", 16)) / 1000000; - gpu.fan_pwm = std::stoi(readFile(hwmon + "/pwm1", 4)) * 100 / 256; + gpu.fan_pwm = std::stoi(readFile(hwmon + "/pwm1", 4)) * 100 / 256; gpu.vram_used = std::stoul(readFile(hwmon + "/../../mem_info_vram_used", 16)); // gpu.vram_total = std::stoul(readFile(hwmon + "/../../mem_info_vram_total", 16)); - // these also exist in gpu_metrics? - if (!hasMetrics) { - gpu.core_clock = std::stoll(readFile(hwmon + "/freq1_input", 16)) / 1000000; - gpu.mem_clock = std::stoll(readFile(hwmon + "/freq2_input", 16)) / 1000000; - gpu.power_avg = std::stol(readFile(hwmon + "/power1_input", 16)) / 1000000; - gpu.edge_temp = std::stol(readFile(hwmon + "/temp1_input", 2)); - gpu.core_usage = std::stoi(readFile(hwmon + "/../../gpu_busy_percent")); - } - - if (gpu.fan_speed > 9999) - gpu.fan_speed = 9999; + gpu.core_clock = std::stoll(readFile(hwmon + "/freq1_input", 16)) / 1000000; + gpu.mem_clock = std::stoll(readFile(hwmon + "/freq2_input", 16)) / 1000000; + gpu.power_avg = std::stol(readFile(hwmon + "/power1_input", 16)) / 1000000; + gpu.edge_temp = std::stol(readFile(hwmon + "/temp1_input", 2)); + gpu.core_usage = std::stoi(readFile(hwmon + "/../../gpu_busy_percent")); return gpu; -} \ No newline at end of file +} + +gpu_t getGpu(std::string hwmon, bool hasMetrics) { + if (hasMetrics) { + return getGpuFromMetrics(hwmon); + } else { + return getGpuFromFs(hwmon); + } +}