1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
//! A set of APIs to list and retrieve information of FuriosaAI's NPU devices.
//! To learn more about FuriosaAI's NPU, please visit <https://furiosa.ai>.
//!
//! # Before you start
//!
//! This crate requires FuriosaAI's NPU device and its kernel driver. Currently, FuriosaAI offers
//! NPU devices for only users who register Early Access Program (EAP). Please contact
//! <contact@furiosa.ai> to learn how to start the EAP. You can also refer to
//! [Driver, Firmware, and Runtime Installation](https://furiosa-ai.github.io/docs/latest/en/software/installation.html)
//! to learn the kernel driver installation.
//!
//! # Usage
//!
//! Add this to your 'Cargo.toml':
//! ```toml
//! [dependencies]
//! furiosa-device = "0.1"
//! ```
//!
//! ## Listing devices from the system
//!
//! The current implementation mainly offers two APIs, namely
//! [`list_devices`] and [`find_device_files`].
//!
//! 1. [`list_devices`] enumerates all Furiosa NPU devices in the system.
//! One can simply call as below:
//! ```rust,no_run
//! # #[tokio::main]
//! # async fn main() -> eyre::Result<()> {
//! let devices = furiosa_device::list_devices().await?;
//! # Ok(())
//! # }
//! ```
//!
//! [Struct `Device`][`Device`] offers methods for further information of each
//! device.
//!
//! 2. If you have a desired configuration, call [`find_device_files`] with your device configuration
//! described by a [`DeviceConfig`]. [`find_device_files`] will return a list of
//! [`DeviceFile`]s if there are matched devices.
//! ```rust,no_run
//! use furiosa_device::{find_device_files, DeviceConfig};
//!
//! // Find two Warboy devices, fused.
//! # #[tokio::main]
//! # async fn main() -> eyre::Result<()> {
//! let config = DeviceConfig::warboy().fused().count(2);
//! let dev_files = find_device_files(&config).await?;
//! # Ok(())
//! # }
//! ```
//!
//! 3. In case you have prior knowledge on the system and want to pick out a
//! device with specific name, use [`get_device_file`].
//! ```rust,no_run
//! # #[tokio::main]
//! # async fn main() -> eyre::Result<()> {
//! let device_file = furiosa_device::get_device_file("npu0pe0").await?;
//! # Ok(())
//! # }
//! ```
// Allows displaying feature flags in the documentation.
#![cfg_attr(docsrs, feature(doc_cfg))]
#![feature(associated_type_bounds)]
pub use crate::arch::Arch;
use crate::config::{expand_status, find_device_files_in};
pub use crate::config::{DeviceConfig, DeviceConfigBuilder, EnvBuilder, NotDetermined};
pub use crate::device::{
ClockFrequency, CoreRange, CoreStatus, Device, DeviceFile, DeviceMode, NumaNode,
};
pub use crate::error::{DeviceError, DeviceResult};
use crate::list::{get_device_with, list_devices_with};
mod arch;
#[cfg(feature = "blocking")]
#[cfg_attr(docsrs, doc(cfg(feature = "blocking")))]
pub mod blocking;
mod config;
mod devfs;
mod device;
mod error;
pub mod hwmon;
mod list;
pub mod perf_regs;
pub mod proc;
mod status;
mod sysfs;
/// List all Furiosa NPU devices in the system.
///
/// See the [crate-level documentation](crate).
pub async fn list_devices() -> DeviceResult<Vec<Device>> {
list_devices_with("/dev", "/sys").await
}
/// Return a specific Furiosa NPU device in the system.
///
/// # Arguments
///
/// * `idx` - An index number of the device (e.g., 0, 1)
///
/// See the [crate-level documentation](crate).
pub async fn get_device(idx: u8) -> DeviceResult<Device> {
get_device_with(idx, "/dev", "/sys").await
}
/// Find a set of devices with specific configuration.
///
/// # Arguments
///
/// * `config` - DeviceConfig
///
/// See the [crate-level documentation](crate).
pub async fn find_device_files(config: &DeviceConfig) -> DeviceResult<Vec<DeviceFile>> {
let devices = expand_status(list_devices().await?).await?;
find_device_files_in(config, &devices)
}
/// Return a specific device if it exists.
///
/// # Arguments
///
/// * `device_name` - A device name (e.g., npu0, npu0pe0, npu0pe0-1)
///
/// See the [crate-level documentation](crate).
pub async fn get_device_file<S: AsRef<str>>(device_name: S) -> DeviceResult<DeviceFile> {
get_device_file_with("/dev", device_name.as_ref()).await
}
pub(crate) async fn get_device_file_with(
devfs: &str,
device_name: &str,
) -> DeviceResult<DeviceFile> {
let path = devfs::path(devfs, device_name);
if !path.exists() {
return Err(DeviceError::DeviceNotFound {
name: device_name.to_string(),
});
}
let file = tokio::fs::File::open(&path).await?;
if !devfs::is_character_device(file.metadata().await?.file_type()) {
return Err(DeviceError::invalid_device_file(path.display()));
}
devfs::parse_indices(path.file_name().expect("not a file").to_string_lossy())?;
DeviceFile::try_from(&path)
}