sane makefile, sane structure, lots of updates

This commit is contained in:
Drath
2025-05-01 18:24:01 +02:00
parent fa0cc42f4a
commit 6b9314761d
11 changed files with 568 additions and 99 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
*.o
*.d
linuxSmartie

View File

@@ -1,13 +1,40 @@
MAKEFLAGS := --jobs=$(shell nproc)
MAKEFLAGS := --jobs=16
# MAKEFLAGS += --output-sync=target
# compiling with C++26
BUILD_OPTS = -std=c++2c -Ofast -fdiagnostics-color=always
CXXFLAGS := -std=c++2c -Ofast -fdiagnostics-color=always -Iinclude
# CXXFLAGS += -MMD -MP
build:
g++ -c $(BUILD_OPTS) -o main.o main.cpp
g++ -c $(BUILD_OPTS) -o LCDDisplay.o -Iinclude include/LCDDisplay.cpp
g++ $(BUILD_OPTS) -o linuxSmartie LCDDisplay.o main.o
SOURCES := main.cpp $(wildcard src/*.cpp)
OBJECTS := $(SOURCES:.cpp=.o)
# DEPS := $(OBJECTS:.o=.d)
TEST_SRC := test.cpp $(wildcard src/*.cpp)
TEST_OBJS := $(TEST_SRC:.cpp=.o)
# glowny target, linkuje linuxSmartie, potrzebuje ${OBJECTS}
linuxSmartie: $(OBJECTS)
g++ $(CXXFLAGS) -o $@ $^
# kompiluje test.cpp zamiast main.cpp
test: $(TEST_OBJS)
g++ $(CXXFLAGS) -o $@ $^
# kompiluje obiekty, potrzebuje zrodel cpp
%.o: %.cpp
g++ $(CXXFLAGS) -c $< -o $@
# -include $(DEPS)
.PHONY: clean
clean:
rm linuxSmartie *.o
rm -f linuxSmartie $(OBJECTS) $(DEPS) $(TEST_OBJS)
# build:
# g++ -c $(BUILD_OPTS) -o LCDDisplay.o -Iinclude include/LCDDisplay.cpp
# g++ -c $(BUILD_OPTS) -o gpu.o -Iinclude include/gpu.cpp
# g++ -c $(BUILD_OPTS) -o utils.o -Iinclude include/utils.cpp
# g++ -c $(BUILD_OPTS) -o main.o main.cpp
# g++ $(BUILD_OPTS) -o linuxSmartie *.o # linking

View File

@@ -13,4 +13,40 @@ Same as plugins. Just write more features scrub, learn some C++, damn
- Screens could be automatic tbh, like if it detects media playing it switches to media screen, if GPU power > 80W it switches to main (hwmon) screen
- Gonna need custom chars for sure at some point
- Measure execution time of main loop, if it's close enough to 1000ms, add network monitoring
- Add more getters in general, CPU temp/clock/power/Vcore would be the big one
- Add more getters in general, CPU temp/clock/power/Vcore would be the big one
- GPU is about as done as it's gonna be
- Needs bar graphs still
- Parse gpu_metrics for GPU metrics
## LCD layout
It looks something like this
```
****************************************
0.4 0 ||09:30:36| 124fps
53/40/35C 4.53GB 544MB 32/40C
26W 424R 65.9W 0R 7/244W 11W
1,200V 1186MHz 3150 2/9MHz 0,112V
****************************************
```
### Ok but what does it all mean
In general left side is CPU/system stuff, right side is GPU stuff
```
{act core cnt} {whea} {time} {bar/1cpu%}{bar/AllCPU%}{TIME}{gpu%} {xbat} {fps}
{dieAvg}/{cache}/{iod}C {ram}GB {vram}GB {edge}/{junction}C
{cpuPpt}W {cpufan}R {wallPow}W {gpufan}R {gpuPpt}/{cap}W {gpuBoard}W
{cpuV}V {avgCpuFreq}MHz {gpuCoreClkCap} {gpuCoreClk}/{gpuMemClk}MHz {gpuV}V
```
Not all of this will be possible ofc but it's a start
Raw LCD Smartie lines below:
```
Text01="$dll(hwinfo,1,Average Active Core Count,1)$Fill(9)$dll(hwinfo,1,Total Errors,0)$Fill(14)$dll(tinybar2,8,$dll(hwinfo,1,Max CPU/Thread Usage,),1)$Fill(5)$dll(tinybar2,7,$dll(hwinfo,1,Total CPU Usage,),1)$Time(hh:mm:ss)$dll(tinybar2,6,$dll(hwinfo,1,GPU Utilization,),1)$dll(xbat,1,i,1)$Fill(33)$Right($dll(hwinfo,1,Framerate (Presented),0),$4%)fps"
Text02="$dll(hwinfo,1,1|CPU Die (average),0|a)/$dll(hwinfo,1,1|L3 Cache (CCD1),0)/$dll(hwinfo,1,1|CPU IOD Hotspot,0)$Chr(176)$Fill(10)$dll(format,2,$dll(hwinfo,1,1|8|4,0),0##B)B$Fill(24)$Right($dll(format,2,$dll(hwinfo,1,GPU D3D Memory Dedicated,0),0##B),$6%)B$Fill(34)$Right($dll(hwinfo,1,GPU|1|1,)/$dll(hwinfo,1,GPU|1|4,)$Chr(176),$7%)"
Text03="$dll(hwinfo,1,5|1,0)W$Fill(5)$dll(hwinfo,1,3|2,)R$Fill(14)$Right($dll(tasmopwr,1,tasmota-plug-pc.lan,)W,$6%)$Fill(21)$Right($dll(hwinfo,1,GPU|3|1,)R,$5%)$Fill(27)$Right($dll(hwinfo,1,GPU|5|9,0)/$dll(hwinfo,1,GPU|5|10,0)W,$8%)$Fill(36)$Right($dll(hwinfo,1,GPU|5|7,0)W,$4%)"
Text04="$dll(hwinfo,1,Vcore,3)V $Right($dll(hwinfo,1,Average Effective Clock,a)MHz,$7%)$Fill(16)$dll(hwinfo,1,GPU Shader Clock Frequency Limit,)$Fill(21)$Right($dll(hwinfo,1,GPU|6|2,)/$dll(hwinfo,1,GPU|6|4,)MHz,$12%)$Fill(34)$dll(hwinfo,1,GPU|2|1,3)V$CustomChar(1,16,6,9,8,8,9,6,0)"
```

View File

@@ -18,4 +18,5 @@ class LCDDisplay {
void setCursor(uint8_t row, uint8_t col);
void writeLines(std::array<std::string, 4> lines);
void writeSStream(std::stringstream& ss);
void setCustomChar(uint8_t index, std::array<uint8_t, 8> cchar);
};

25
include/gpu.hpp Normal file
View File

@@ -0,0 +1,25 @@
#include <string>
struct gpu_t {
uint16_t fan_speed;
uint16_t core_clock;
uint16_t mem_clock;
double vcore;
uint16_t power_avg;
uint16_t power_cap;
uint16_t power_max;
uint8_t fan_pwm;
uint8_t edge_temp;
uint8_t hotspot_temp;
uint8_t mem_temp;
uint8_t gfx_vrm_temp;
uint8_t soc_vrm_temp;
uint8_t mem_vrm_temp;
uint64_t vram_used;
uint64_t vram_total;
uint8_t core_usage;
uint8_t media_usage;
uint8_t umc_usage;
};
gpu_t getGpu(std::string hw);

6
include/utils.hpp Normal file
View File

@@ -0,0 +1,6 @@
#include <cstdint>
#include <string>
std::string readFile(std::string path, uint8_t trim = 0);
int get_val(const std::string &target, const std::string &content);
std::string findHwmonPath(std::string module);

190
main.cpp
View File

@@ -13,32 +13,21 @@
#include <thread>
#include "include/LCDDisplay.hpp"
#include "include/linux-system-usage.hpp"
#include "include/gpu.hpp"
#include "include/utils.hpp"
#define LCD_PORT "/dev/ttyACM0"
#define LCD_INTERVAL_MS 1000
#define LCD_CONTRAST 225
struct gpuHwmon_t {
std::string fan_speed;
std::string core_clock;
std::string mem_clock;
std::string core_mv;
std::string power_avg;
std::string power_cap;
std::string power_max;
std::string fan_pwm;
std::string edge_temp;
std::string junction_temp;
std::string mem_temp;
};
#define LCD_CONTRAST 215
#define FILL_CHAR ' '
struct mem_usage_t {
std::string free;
std::string used;
std::string total;
uint64_t free;
uint64_t used;
uint64_t total;
};
/* DISPLAY FUNCS */
std::string pBytes(double i, bool isKbytes = false) {
std::stringstream ss;
std::array suffix = {'K', 'M', 'G', 'T', 'P', 'E', 'Z'};
@@ -46,24 +35,43 @@ std::string pBytes(double i, bool isKbytes = false) {
if (s == 'K' && isKbytes) continue;
i /= 1024.0;
if (i < 1024) {
ss << std::fixed << std::setprecision(i > 100 ? 1 : 2) << i << s;
uint8_t p = 2;
if (i > 10) p = 1;
if (i > 100) p = 0;
ss << std::fixed << std::setprecision(p) << i << s;
return ss.str();
}
}
return "++++";
}
// converts number to string with given decimal places
std::string pNum(auto num, uint8_t decs = 0) {
std::stringstream ss;
ss << std::fixed << std::setprecision(decs) << num;
return ss.str();
}
// pads given string to size
std::string pad(std::string s, uint8_t w, bool ljust = false) {
if (w > s.size()) s.insert(ljust ? s.end() : s.begin(), w - s.size(), ' ');
if (w > s.size()) s.insert(ljust ? s.end() : s.begin(), w - s.size(), FILL_CHAR);
return s;
}
// fills n spaces
std::string fill(uint8_t n) {
return std::string(n, FILL_CHAR);
}
/* getters */
std::string getAvgs() {
std::stringstream ss;
double avgs[3];
getloadavg(avgs, 3);
ss << std::fixed << std::setprecision(2);
ss << avgs[0] << " " << avgs[1] << " " << avgs[2];
for (uint8_t i = 0; i < 3; i++) {
ss << std::fixed << std::setprecision(avgs[i] > 10 ? 1 : 2);
ss << " " << avgs[i];
}
return ss.str();
}
@@ -83,10 +91,15 @@ std::array<std::string, 2> getTimeDate() {
mem_usage_t getRam() {
mem_usage_t mem;
auto memory_data = get_system_usage_linux::read_memory_data();
mem.free = pBytes(memory_data.available_memory, true);
mem.used = pBytes(memory_data.total_memory - memory_data.available_memory, true);
mem.total = pBytes(memory_data.total_memory, true);
std::ifstream proc_meminfo("/proc/meminfo");
if (proc_meminfo.good()) {
std::string content((std::istreambuf_iterator<char>(proc_meminfo)), std::istreambuf_iterator<char>());
mem.free = get_val("MemAvailable:", content);
mem.total = get_val("MemTotal:", content);
mem.used = mem.total - mem.free;
}
proc_meminfo.close();
return mem;
}
@@ -94,87 +107,82 @@ mem_usage_t getDisk(std::string mount) {
mem_usage_t disk;
struct statvfs diskData;
statvfs(mount.c_str(), &diskData);
disk.free = pBytes(diskData.f_bfree * diskData.f_frsize);
disk.used = pBytes((diskData.f_blocks - diskData.f_bfree) * diskData.f_frsize);
disk.total = pBytes(diskData.f_blocks * diskData.f_frsize);
disk.free = diskData.f_bfree * diskData.f_frsize;
disk.used = (diskData.f_blocks - diskData.f_bfree) * diskData.f_frsize;
disk.total = diskData.f_blocks * diskData.f_frsize;
return disk;
}
std::string readFile(std::string path, uint8_t trim = 0) {
std::string ret;
std::stringstream ss;
std::ifstream fs(path);
if (!fs.good()) {
std::cerr << "Error reading " << path << std::endl;
exit(1);
}
ss << fs.rdbuf();
fs.close();
ret = ss.str();
return ret.substr(0, ret.size() - trim - 1);
}
auto getCpuTemp(std::string hw) {
struct {
double tctl;
double tccd1;
} cpu;
gpuHwmon_t getGpu(std::string hw) {
gpuHwmon_t gpu;
gpu.fan_speed = readFile(hw + "/fan1_input");
gpu.core_clock = readFile(hw + "/freq1_input", 6);
gpu.mem_clock = readFile(hw + "/freq2_input", 6);
gpu.core_mv = readFile(hw + "/in0_input");
gpu.power_avg = readFile(hw + "/power1_average", 6);
gpu.power_cap = readFile(hw + "/power1_cap", 6);
gpu.power_max = readFile(hw + "/power1_cap_max", 6);
gpu.fan_pwm = readFile(hw + "/pwm1");
gpu.edge_temp = readFile(hw + "/temp1_input", 3);
gpu.junction_temp = readFile(hw + "/temp2_input", 3);
gpu.mem_temp = readFile(hw + "/temp3_input", 3);
return gpu;
}
std::string getCpuTemp() {
return readFile("/sys/devices/pci0000:00/0000:00:18.3/hwmon/hwmon3/temp1_input");
cpu.tctl = (double)(std::stoul(readFile(hw + "/temp1_input")) / 1000.0);
cpu.tccd1 = (double)(std::stoul(readFile(hw + "/temp3_input")) / 1000.0);
return cpu;
}
void collectAndDraw(LCDDisplay *lcd) {
auto td = getTimeDate();
auto ram = getRam();
auto anime = getDisk("/mnt/anime");
auto home = getDisk("/var/home/drath");
auto gpu = getGpu("/sys/devices/pci0000:00/0000:00:03.1/0000:08:00.0/0000:09:00.0/0000:0a:00.0/hwmon/hwmon2");
std::array<std::string, 4> lines;
lines[0] = td[1] + " " + td[0] + pad(getAvgs(), 20);
lines[1] = pad(ram.used + "/" + ram.total, 13, true) + " ";
lines[1] += pad(gpu.fan_speed + "R", 5) + " ";
lines[1] += pad(gpu.power_avg + "/" + gpu.power_cap + "W", 8) + " ";
lines[1] += pad(gpu.edge_temp + "/" + gpu.junction_temp + "C", 8);
lines[2] = "/home/drath:" + pad(home.free + " free of " + home.total, 28);
lines[3] = "/mnt/anime: " + pad(anime.free + " free of " + anime.total, 28);
lcd->writeLines(lines);
}
int main(int argc, char *argv[]) {
bool daemon_mode = (argc > 1 && std::string(argv[1]) == "-d");
/* init lcd, set contrast and backlight */
LCDDisplay lcd(LCD_PORT, 0010002);
if (argc > 1 && std::string(argv[1]) == "-d") {
std::cout << "[Chrono] Running in daemon mode, " << LCD_INTERVAL_MS << "ms interval" << std::endl;
if (daemon_mode) {
lcd.setContrast(LCD_CONTRAST);
lcd.setBacklight(true);
std::chrono::milliseconds interval(LCD_INTERVAL_MS);
auto start = std::chrono::steady_clock::now();
while (true) {
collectAndDraw(&lcd);
}
/* initial vars */
std::array<std::string, 4> lines;
auto cpu_hwmon = findHwmonPath("k10temp");
auto gpu_hwmon = "/sys/class/drm/card1/device";
/* loop setup */
std::cout << "[Chrono] Running in daemon mode, " << LCD_INTERVAL_MS << "ms interval" << std::endl;
std::chrono::milliseconds interval(LCD_INTERVAL_MS);
auto start = std::chrono::steady_clock::now();
/* main loop */
while (true) {
auto td = getTimeDate();
auto ram = getRam();
auto anime = getDisk("/mnt/anime");
auto home = getDisk("/var/home/drath");
auto gpu = getGpu(gpu_hwmon);
auto cpu = getCpuTemp(cpu_hwmon);
lines[0] = td[1] + " " + td[0] + pad(getAvgs(), 20);
lines[1] = pad(pNum(cpu.tctl) + "/" + pNum(cpu.tccd1) + "C", 8, true);
lines[1] += pad(pBytes(ram.used, true) + "B", 7, true);
lines[1] += fill(7);
lines[1] += pad(pBytes(gpu.vram_used) + "B", 7);
lines[1] += pad(std::to_string(gpu.edge_temp) + "/" + std::to_string(gpu.hotspot_temp) + "/" + std::to_string(gpu.mem_temp) + "C", 11);
lines[2] = pad("home: " + pBytes(home.free), 11, true);
lines[2] += fill(15);
lines[2] += pad(pNum(gpu.fan_speed) + "R", 5);
lines[2] += pad(std::to_string(gpu.power_avg) + "/" + std::to_string(gpu.power_cap) + "W", 9);
lines[3] = pad("anime: " + pBytes(anime.free), 13, true);
lines[3] += fill(8);
lines[3] += pad(pNum(gpu.core_clock) + "/" + pNum(gpu.mem_clock) + "MHz ", 13);
lines[3] += pad(pNum(gpu.vcore, 3) + "V", 5);
lcd.writeLines(lines);
if (daemon_mode) {
std::this_thread::sleep_until(start + interval);
start += interval;
} else {
break;
}
} else {
collectAndDraw(&lcd);
}
return 0;

View File

@@ -84,3 +84,11 @@ void LCDDisplay::writeSStream(std::stringstream& ss) {
setCursor(2, 0);
writeStr(s.substr(80, 159));
}
void LCDDisplay::setCustomChar(uint8_t index, std::array<uint8_t, 8> cchar) {
uint8_t cmdbuf[11];
cmdbuf[0] = 254; cmdbuf[1] = 78; cmdbuf[2] = index;
for(uint8_t i = 0; i < 8; i++)
cmdbuf[i+3] = cchar[i];
write(_lcd, cmdbuf, 11);
}

151
src/gpu.cpp Normal file
View File

@@ -0,0 +1,151 @@
#include <cstdint>
#include <fstream>
#include <gpu.hpp>
#include <iostream>
#include <string>
#include <utils.hpp>
struct GpuMetricsHeader_t {
uint16_t structure_size;
uint8_t format_revision;
uint8_t content_revision;
};
struct 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 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;
};
GpuMetricsHeader_t getGpuMetricsRev(std::string path) {
GpuMetricsHeader_t header;
std::ifstream f(path, std::ios::binary);
if (f.good()) {
f.read(reinterpret_cast<char *>(&header), sizeof(header));
std::cout << "[GpuMetrics] Read GpuMetrics format v" << std::to_string(header.format_revision) << "_" << std::to_string(header.content_revision);
std::cout << ", size " << std::to_string(header.structure_size) << std::endl;
f.close();
} else {
std::cerr << "[GpuMetrics] Error reading gpu metrics header" << std::endl;
}
return header;
}
auto getGpuMetrics(GpuMetricsHeader_t h, std::string path) {
GpuMetrics_v1_3_t metrics;
if (h.format_revision == 1 && h.content_revision == 3) {
std::ifstream f(path, std::ios::binary);
if (f.good()) {
f.ignore(sizeof(h)); // skip header
f.read(reinterpret_cast<char *>(&metrics), sizeof(metrics));
f.close();
}
} else {
std::cout << "[GpuMetrics] read failed, unsupported format" << std::endl;
}
return metrics;
}
// clean abstraction of gpu_metrics + extra metrics from fs
gpu_t getGpu(std::string hw) {
gpu_t gpu;
auto h = getGpuMetricsRev(hw + "/gpu_metrics");
auto metrics = getGpuMetrics(h, hw + "/gpu_metrics");
// we want as much data as posible from gpu_metrics so we dont read filesystem as much
gpu.fan_speed = std::stol(readFile(hw + "/hwmon/hwmon2/fan1_input"));
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.vcore = std::stod(readFile(hw + "/hwmon/hwmon2/in0_input")) / 1000.0;
gpu.power_avg = metrics.average_socket_power;
gpu.power_cap = std::stol(readFile(hw + "/hwmon/hwmon2/power1_cap", 6));
gpu.power_max = std::stol(readFile(hw + "/hwmon/hwmon2/power1_cap_max", 6));
// gpu.fan_pwm = std::stoi(readFile(hw + "/hwmon/hwmon2/pwm1")); // not super useful
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.vram_used = std::stoul(readFile(hw + "/mem_info_vram_used"));
gpu.vram_total = std::stoul(readFile(hw + "/mem_info_vram_total"));
gpu.core_usage = metrics.average_gfx_activity;
gpu.media_usage = metrics.average_mm_activity;
gpu.umc_usage = metrics.average_umc_activity;
return gpu;
}

44
src/utils.cpp Normal file
View File

@@ -0,0 +1,44 @@
#include <cstdint>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <utils.hpp>
/* SENSOR GETTERS + UTILS*/
std::string readFile(std::string path, uint8_t trim) {
std::string ret;
std::stringstream ss;
std::ifstream fs(path);
if (!fs.good()) {
std::cerr << "Error reading " << path << std::endl;
exit(1);
}
ss << fs.rdbuf();
fs.close();
ret = ss.str();
if (ret.size() < trim) return ret;
return ret.substr(0, ret.size() - trim - 1);
}
int get_val(const std::string &target, const std::string &content) {
int result = -1;
std::size_t start = content.find(target);
if (start != std::string::npos) {
int begin = start + target.length();
std::size_t end = content.find("kB", start);
std::string substr = content.substr(begin, end - begin);
result = std::stoi(substr);
}
return result;
}
std::string findHwmonPath(std::string module) {
uint8_t id = 0;
for (; id < 10; id++)
if (readFile("/sys/class/hwmon/hwmon" + std::to_string(id) + "/name") == module) {
std::cout << ("[Hwmon] Detected " + module + " path is " + "/sys/class/hwmon/hwmon" + std::to_string(id)) << std::endl;
return "/sys/class/hwmon/hwmon" + std::to_string(id);
}
return "";
}

162
tests/gpu_metrics.cpp Normal file
View File

@@ -0,0 +1,162 @@
#include <cstdint>
#include <fstream>
#include <iostream>
#include <string>
struct GpuMetricsHeader_t {
uint16_t structure_size;
uint8_t format_revision;
uint8_t content_revision;
};
struct 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 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;
};
GpuMetricsHeader_t getGpuMetricsRev(std::string path) {
GpuMetricsHeader_t header;
std::ifstream f(path, std::ios::binary);
if (f.good()) {
f.read(reinterpret_cast<char *>(&header), sizeof(header));
std::cout << "[GpuMetrics] Read GpuMetrics format v" << std::to_string(header.format_revision) << "_" << std::to_string(header.content_revision);
std::cout << ", size " << std::to_string(header.structure_size) << std::endl;
} else {
std::cerr << "[GpuMetrics] Error reading gpu metrics header" << std::endl;
}
return header;
}
auto getGpuMetrics(GpuMetricsHeader_t h, std::string path) {
GpuMetrics_v1_3_t gpu;
if (h.format_revision == 1 && h.content_revision == 3) {
std::ifstream f(path, std::ios::binary);
if (f.good()) {
f.ignore(sizeof(h)); // skip header
f.read(reinterpret_cast<char *>(&gpu), sizeof(gpu));
}
} else {
std::cout << "[GpuMetrics] read failed, unsupported format" << std::endl;
}
return gpu;
}
int main(int argc, char *argv[]) {
std::string m = "/sys/devices/pci0000:00/0000:00:03.1/0000:08:00.0/0000:09:00.0/0000:0a:00.0/gpu_metrics";
GpuMetricsHeader_t h = getGpuMetricsRev(m);
auto gpu = getGpuMetrics(h, m);
std::cout << "temperature_edge: " << std::to_string(gpu.temperature_edge) << std::endl;
std::cout << "temperature_hotspot: " << std::to_string(gpu.temperature_hotspot) << std::endl;
std::cout << "temperature_mem: " << std::to_string(gpu.temperature_mem) << std::endl;
std::cout << "temperature_vrgfx: " << std::to_string(gpu.temperature_vrgfx) << std::endl;
std::cout << "temperature_vrsoc: " << std::to_string(gpu.temperature_vrsoc) << std::endl;
std::cout << "temperature_vrmem: " << std::to_string(gpu.temperature_vrmem) << std::endl;
std::cout << "average_gfx_activity: " << std::to_string(gpu.average_gfx_activity) << std::endl;
std::cout << "average_umc_activity: " << std::to_string(gpu.average_umc_activity) << std::endl;
std::cout << "average_mm_activity: " << std::to_string(gpu.average_mm_activity) << std::endl;
std::cout << "average_socket_power: " << std::to_string(gpu.average_socket_power) << std::endl;
std::cout << "energy_accumulator: " << std::to_string(gpu.energy_accumulator) << std::endl;
std::cout << "system_clock_counter: " << std::to_string(gpu.system_clock_counter) << std::endl;
std::cout << "average_gfxclk_frequency: " << std::to_string(gpu.average_gfxclk_frequency) << std::endl;
std::cout << "average_socclk_frequency: " << std::to_string(gpu.average_socclk_frequency) << std::endl;
std::cout << "average_uclk_frequency: " << std::to_string(gpu.average_uclk_frequency) << std::endl;
std::cout << "average_vclk0_frequency: " << std::to_string(gpu.average_vclk0_frequency) << std::endl;
std::cout << "average_dclk0_frequency: " << std::to_string(gpu.average_dclk0_frequency) << std::endl;
std::cout << "average_vclk1_frequency: " << std::to_string(gpu.average_vclk1_frequency) << std::endl;
std::cout << "average_dclk1_frequency: " << std::to_string(gpu.average_dclk1_frequency) << std::endl;
std::cout << "current_gfxclk: " << std::to_string(gpu.current_gfxclk) << std::endl;
std::cout << "current_socclk: " << std::to_string(gpu.current_socclk) << std::endl;
std::cout << "current_uclk: " << std::to_string(gpu.current_uclk) << std::endl;
std::cout << "current_vclk0: " << std::to_string(gpu.current_vclk0) << std::endl;
std::cout << "current_dclk0: " << std::to_string(gpu.current_dclk0) << std::endl;
std::cout << "current_vclk1: " << std::to_string(gpu.current_vclk1) << std::endl;
std::cout << "current_dclk1: " << std::to_string(gpu.current_dclk1) << std::endl;
std::cout << "throttle_status: " << std::to_string(gpu.throttle_status) << std::endl;
std::cout << "current_fan_speed: " << std::to_string(gpu.current_fan_speed) << std::endl;
std::cout << "pcie_link_width: " << std::to_string(gpu.pcie_link_width) << std::endl;
std::cout << "pcie_link_speed: " << std::to_string(gpu.pcie_link_speed) << std::endl;
std::cout << "gfx_activity_acc: " << std::to_string(gpu.gfx_activity_acc) << std::endl;
std::cout << "mem_activity_acc: " << std::to_string(gpu.mem_activity_acc) << std::endl;
std::cout << "temperature_hbm: " << std::to_string(gpu.temperature_hbm) << std::endl;
std::cout << "firmware_timestamp: " << std::to_string(gpu.firmware_timestamp) << std::endl;
std::cout << "voltage_soc: " << std::to_string(gpu.voltage_soc) << std::endl;
std::cout << "voltage_gfx: " << std::to_string(gpu.voltage_gfx) << std::endl;
std::cout << "voltage_mem: " << std::to_string(gpu.voltage_mem) << std::endl;
return 0;
}