test-smi-rs 0.1.2

APIs for managing and monitoring FuriosaAI NPUs
Documentation
use std::ptr;
use std::time::{SystemTime, UNIX_EPOCH};

use crate::generated::binding::*;

pub(crate) fn new_device_performance_counter(
    raw: FuriosaSmiDevicePerformanceCounter,
) -> DevicePerformanceCounter {
    DevicePerformanceCounter { raw }
}

/// A struct for a performance counter of the device
pub struct DevicePerformanceCounter {
    raw: FuriosaSmiDevicePerformanceCounter,
}

impl DevicePerformanceCounter {
    /// Returns a performance counter of PE cores of the device.
    pub fn pe_performance_counters(&self) -> Vec<PePerformanceCounter> {
        let mut result = Vec::with_capacity(self.raw.pe_count as usize);
        for i in 0..self.raw.pe_count {
            result.push(new_pe_performance_counter(
                self.raw.pe_performance_counters[i as usize],
            ));
        }

        result
    }
}

pub(crate) fn new_pe_performance_counter(
    raw: FuriosaSmiPePerformanceCounter,
) -> PePerformanceCounter {
    PePerformanceCounter { raw }
}

/// A struct for PE performance counter
pub struct PePerformanceCounter {
    raw: FuriosaSmiPePerformanceCounter,
}

impl PePerformanceCounter {
    /// Returns a timestamp of the performance counter.
    pub fn timestamp(&self) -> SystemTime {
        UNIX_EPOCH + std::time::Duration::from_secs(self.raw.timestamp as u64)
    }

    /// Returns a cycle count of the performance counter.
    pub fn cycle_count(&self) -> u64 {
        self.raw.cycle_count
    }

    /// Returns a task execution cycle of the performance counter.
    pub fn task_execution_cycle(&self) -> u64 {
        self.raw.task_execution_cycle
    }
}

pub(crate) fn new_core_utilization(raw: FuriosaSmiCoreUtilization) -> CoreUtilization {
    CoreUtilization { raw }
}

/// A struct for a utilization information of the device
pub struct CoreUtilization {
    raw: FuriosaSmiCoreUtilization,
}

impl CoreUtilization {
    /// Returns a utilization of PE cores of the device.
    pub fn pe_utilization(&self) -> Vec<PeUtilization> {
        let mut result = Vec::with_capacity(self.raw.pe_count as usize);
        for i in 0..self.raw.pe_count {
            result.push(new_pe_utilization(self.raw.pe[i as usize]));
        }

        result
    }
}

fn new_pe_utilization(raw: FuriosaSmiPeUtilization) -> PeUtilization {
    PeUtilization { raw }
}

/// A struct for PE utilization
pub struct PeUtilization {
    raw: FuriosaSmiPeUtilization,
}

impl PeUtilization {
    /// Returns PE core index.
    pub fn core(&self) -> u32 {
        self.raw.core
    }

    /// Returns time window for utilization.
    pub fn time_window_mill(&self) -> u32 {
        self.raw.time_window_mil
    }
    /// Returns PE usage percentage.
    pub fn pe_usage_percentage(&self) -> f64 {
        self.raw.pe_usage_percentage
    }
}

pub(crate) fn new_memory_utilization(raw: FuriosaSmiMemoryUtilization) -> MemoryUtilization {
    MemoryUtilization { raw }
}

/// A struct for memory utilization
pub struct MemoryUtilization {
    raw: FuriosaSmiMemoryUtilization,
}

impl MemoryUtilization {
    /// Returns the total bytes of memory.
    pub fn total_bytes(&self) -> u64 {
        self.raw.total_bytes
    }

    /// Returns the memory bytes currently in use.
    pub fn in_use_bytes(&self) -> u64 {
        self.raw.in_use_bytes
    }
}

pub(crate) fn new_device_temperature(raw: FuriosaSmiDeviceTemperature) -> DeviceTemperature {
    DeviceTemperature { raw }
}

/// A struct for a temperature information of the device
pub struct DeviceTemperature {
    raw: FuriosaSmiDeviceTemperature,
}

impl DeviceTemperature {
    /// Returns the highest temperature observed from SoC sensors.
    pub fn soc_peak(&self) -> f64 {
        self.raw.soc_peak
    }

    /// Returns the temperature observed from sensors attached to the board
    pub fn ambient(&self) -> f64 {
        self.raw.ambient
    }
}

pub(crate) fn new_observer_instance(raw: FuriosaSmiObserverInstance) -> DeviceObserverInstance {
    DeviceObserverInstance { raw }
}

pub(crate) struct DeviceObserverInstance {
    raw: FuriosaSmiObserverInstance,
}

impl DeviceObserverInstance {
    pub(crate) fn raw(&self) -> FuriosaSmiObserverInstance {
        self.raw
    }
}

impl Drop for DeviceObserverInstance {
    fn drop(&mut self) {
        unsafe {
            furiosa_smi_destroy_observer(&mut self.raw as *mut FuriosaSmiObserverInstance);
        }
    }
}

fn default_pe_performance_counter() -> FuriosaSmiPePerformanceCounter {
    FuriosaSmiPePerformanceCounter {
        timestamp: 0,
        cycle_count: 0,
        task_execution_cycle: 0,
    }
}

pub(crate) fn default_device_performance_counter() -> FuriosaSmiDevicePerformanceCounter {
    FuriosaSmiDevicePerformanceCounter {
        pe_count: 0,
        pe_performance_counters: [default_pe_performance_counter();
            FURIOSA_SMI_MAX_PE_SIZE as usize],
    }
}

fn default_pe_utilization() -> FuriosaSmiPeUtilization {
    FuriosaSmiPeUtilization {
        core: 0,
        time_window_mil: 0,
        pe_usage_percentage: 0.0,
    }
}

pub(crate) fn default_memory_utilization() -> FuriosaSmiMemoryUtilization {
    FuriosaSmiMemoryUtilization {
        total_bytes: 0,
        in_use_bytes: 0,
    }
}

pub(crate) fn default_core_utilization() -> FuriosaSmiCoreUtilization {
    FuriosaSmiCoreUtilization {
        pe_count: 0,
        pe: [default_pe_utilization(); FURIOSA_SMI_MAX_PE_SIZE as usize],
    }
}

pub(crate) fn default_power_consumption() -> FuriosaSmiDevicePowerConsumption {
    FuriosaSmiDevicePowerConsumption { rms_total: 0.0 }
}

pub(crate) fn default_temperature() -> FuriosaSmiDeviceTemperature {
    FuriosaSmiDeviceTemperature {
        soc_peak: 0.0,
        ambient: 0.0,
    }
}

pub(crate) fn default_observer_instance() -> FuriosaSmiObserverInstance {
    ptr::null_mut()
}