use std::collections::BTreeMap;
use std::{iter, slice};
use sys::gpu::{clock, power};
use sys;
use void::{Void, ResultVoidExt};
use types::{Kilohertz, Kilohertz2, KilohertzDelta, Kilohertz2Delta, Percentage, Percentage1000, Microvolts, CelsiusShifted, Range, RawConversion};
pub use sys::gpu::clock::PublicClockId as ClockDomain;
pub use sys::gpu::clock::private::ClockLockMode;
pub use sys::gpu::power::private::PerfFlags;
impl RawConversion for clock::NV_GPU_CLOCK_FREQUENCIES {
type Target = BTreeMap<ClockDomain, Kilohertz>;
type Error = Void;
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
Ok(ClockDomain::values().filter(|&c| c != ClockDomain::Undefined)
.map(|id| (id, &self.domain[id.raw() as usize]))
.filter(|&(_, ref clock)| clock.bIsPresent.get())
.map(|(id, clock)| (id, Kilohertz(clock.frequency)))
.collect()
)
}
}
impl RawConversion for clock::private::NV_USAGES_INFO {
type Target = BTreeMap<::pstate::UtilizationDomain, Percentage>;
type Error = sys::ArgumentRangeError;
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
self.usages.iter().enumerate()
.filter(|&(_, ref usage)| usage.bIsPresent.get())
.map(|(i, usage)| ::pstate::UtilizationDomain::from_raw(i as _)
.and_then(|i| Percentage::from_raw(usage.percentage).map(|p| (i, p)))
).collect()
}
}
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub enum VfpMaskType {
Graphics,
Memory,
Unknown,
}
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct VfpMask {
pub mask: [u32; 4],
pub types: Vec<VfpMaskType>,
}
impl VfpMask {
pub fn get_bit(mask: &[u32; 4], mut bit: usize) -> bool {
let mut mask = &mask[..];
while bit >= 32 {
mask = &mask[1..];
bit -= 32;
}
mask[0] & (1u32 << bit) != 0
}
pub fn set_bit(mut mask: &mut [u32], mut bit: usize) {
while bit >= 32 {
mask = &mut { mask }[1..];
bit -= 32;
}
mask[0] |= 1u32 << bit
}
pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter {
self.into_iter()
}
}
impl<'a> IntoIterator for &'a VfpMask {
type Item = (usize, VfpMaskType);
type IntoIter = iter::Zip<VfpMaskIter<'a>, iter::Cloned<slice::Iter<'a, VfpMaskType>>>;
fn into_iter(self) -> Self::IntoIter {
VfpMaskIter::new(&self.mask).zip(self.types.iter().cloned())
}
}
pub struct VfpMaskIter<'a> {
mask: &'a [u32],
offset: usize,
}
impl<'a> VfpMaskIter<'a> {
pub fn new(mask: &'a [u32]) -> Self {
VfpMaskIter {
mask: mask,
offset: 0,
}
}
}
impl<'a> Iterator for VfpMaskIter<'a> {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
while self.mask.len() > 0 {
let offset = self.offset;
let bit = offset % 32;
let set = self.mask[0] & (1u32 << bit) != 0;
self.offset += 1;
if bit == 31 {
self.mask = &self.mask[1..]
}
if set {
return Some(offset)
}
}
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(self.mask.len() * 32 - (self.offset % 32)))
}
}
impl RawConversion for clock::private::NV_CLOCK_MASKS_CLOCK {
type Target = VfpMaskType;
type Error = sys::ArgumentRangeError;
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
match *self {
clock::private::NV_CLOCK_MASKS_CLOCK {
a: 0, b: 0, c: 0, d: 0, memDelta: 1, gpuDelta: 0,
} => Ok(VfpMaskType::Memory),
clock::private::NV_CLOCK_MASKS_CLOCK {
a: 0, b: 0, c: 0, d: 0, memDelta: 0, gpuDelta: 1,
} => Ok(VfpMaskType::Graphics),
clock::private::NV_CLOCK_MASKS_CLOCK {
a: 0, b: 0, c: 0, d: 0, memDelta: 0, gpuDelta: 0,
} => Ok(VfpMaskType::Unknown),
_ => Err(sys::ArgumentRangeError),
}
}
}
impl RawConversion for clock::private::NV_CLOCK_MASKS {
type Target = VfpMask;
type Error = sys::ArgumentRangeError;
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
Ok(VfpMask {
mask: self.mask,
types: VfpMaskIter::new(&self.mask)
.filter_map(|i| self.clocks.inner().get(i))
.map(RawConversion::convert_raw)
.collect::<Result<_, _>>()?,
})
}
}
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct ClockTable {
pub gpu_delta: Vec<(usize, Kilohertz2Delta)>,
pub mem_delta: Vec<(usize, KilohertzDelta)>,
}
impl RawConversion for clock::private::NV_CLOCK_TABLE_GPU_DELTA {
type Target = i32;
type Error = sys::ArgumentRangeError;
#[allow(non_snake_case)]
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
match *self {
clock::private::NV_CLOCK_TABLE_GPU_DELTA {
a: 0, b: 0, c: 0, d: 0, e: 0, freqDeltaKHz, g: 0, h: 0, i: 0,
} => Ok(freqDeltaKHz),
_ => Err(sys::ArgumentRangeError),
}
}
}
impl RawConversion for clock::private::NV_CLOCK_TABLE {
type Target = ClockTable;
type Error = sys::ArgumentRangeError;
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
Ok(ClockTable {
gpu_delta: VfpMaskIter::new(&self.mask)
.filter(|&i| i < self.gpuDeltas.len())
.map(|i| (i, &self.gpuDeltas.inner()[i]))
.map(|(i, delta)| delta.convert_raw().map(|delta| (i, delta.into())))
.collect::<Result<_, _>>()?,
mem_delta: self.memFilled.iter().enumerate().filter_map(|(i, &filled)| match filled {
1 => Some(Ok(i)),
0 => None,
_ => Some(Err(sys::ArgumentRangeError)),
}).map(|i| i.map(|i| (self.gpuDeltas.len() + i, self.memDeltas[i].into())))
.collect::<Result<_, _>>()?,
})
}
}
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct ClockRange {
pub domain: ClockDomain,
pub range: Range<Kilohertz2Delta>,
pub temp_max: CelsiusShifted,
}
impl RawConversion for clock::private::NV_CLOCK_RANGES_ENTRY {
type Target = ClockRange;
type Error = sys::ArgumentRangeError;
#[allow(non_snake_case)]
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
match *self {
clock::private::NV_CLOCK_RANGES_ENTRY {
a: 0, clockType, c: 0, d: 0, e: 0, f: 0, g: 0, h: 0, i: 0,
j: 0, rangeMax, rangeMin, tempMax, n: 0, o: 0, p: 0, q: 0, r: 0,
} => Ok(ClockRange {
domain: ClockDomain::from_raw(clockType)?,
range: Range {
max: Kilohertz2Delta(rangeMax),
min: Kilohertz2Delta(rangeMin),
},
temp_max: CelsiusShifted(tempMax),
}),
_ => Err(sys::ArgumentRangeError),
}
}
}
impl RawConversion for clock::private::NV_CLOCK_RANGES {
type Target = Vec<ClockRange>;
type Error = sys::ArgumentRangeError;
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
self.entries[..(self.numClocks - 1) as usize].iter()
.map(RawConversion::convert_raw)
.collect::<Result<_, _>>()
}
}
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct VfpEntry<K> {
pub unknown: u32,
pub frequency: K,
pub voltage: Microvolts,
}
impl<T> VfpEntry<T> {
pub fn from_entry<K>(e: VfpEntry<K>) -> Self where T: From<K> {
VfpEntry {
unknown: e.unknown,
frequency: e.frequency.into(),
voltage: e.voltage,
}
}
}
impl RawConversion for power::private::NV_VFP_CURVE_GPU_ENTRY {
type Target = VfpEntry<u32>;
type Error = sys::ArgumentRangeError;
#[allow(non_snake_case)]
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
match *self {
power::private::NV_VFP_CURVE_GPU_ENTRY {
a, freq_kHz, voltage_uV, d: 0, e: 0, f: 0, g: 0,
} => Ok(VfpEntry {
unknown: a,
frequency: freq_kHz,
voltage: Microvolts(voltage_uV),
}),
_ => Err(sys::ArgumentRangeError),
}
}
}
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct VfpCurve {
pub graphics: Vec<(usize, VfpEntry<Kilohertz2>)>,
pub memory: Vec<(usize, VfpEntry<Kilohertz>)>,
}
impl RawConversion for power::private::NV_VFP_CURVE {
type Target = VfpCurve;
type Error = sys::ArgumentRangeError;
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
Ok(VfpCurve {
graphics: VfpMaskIter::new(&self.mask)
.filter(|&i| i < self.gpuEntries.len())
.map(|i| self.gpuEntries[i].convert_raw().map(|e| (i, VfpEntry::from_entry(e))))
.collect::<Result<_, _>>()?,
memory: VfpMaskIter::new(&self.mask)
.filter(|&i| i >= self.gpuEntries.len() && i < self.gpuEntries.len() + self.memEntries.len())
.map(|i| self.memEntries[i - self.gpuEntries.len()].convert_raw().map(|e| (i, VfpEntry::from_entry(e))))
.collect::<Result<_, _>>()?,
})
}
}
fn all_zero(s: &[u32]) -> bool {
return s.iter().all(|&v| v == 0)
}
impl RawConversion for power::private::NV_VOLTAGE_STATUS_V1 {
type Target = Microvolts;
type Error = sys::ArgumentRangeError;
#[allow(non_snake_case)]
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
match *self {
power::private::NV_VOLTAGE_STATUS_V1 {
version: _, flags: 0, ref zero,
value_uV, ref unknown,
} if all_zero(zero) && all_zero(unknown) => Ok(Microvolts(value_uV)),
_ => Err(sys::ArgumentRangeError),
}
}
}
impl RawConversion for power::private::NV_VOLTAGE_BOOST_PERCENT_V1 {
type Target = Percentage;
type Error = sys::ArgumentRangeError;
#[allow(non_snake_case)]
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
match *self {
power::private::NV_VOLTAGE_BOOST_PERCENT {
version: _, percent, ref unknown,
} if all_zero(unknown) => Percentage::from_raw(percent),
_ => Err(sys::ArgumentRangeError),
}
}
}
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct PowerInfoEntry {
pub pstate: ::pstate::PState,
pub range: Range<Percentage1000>,
pub default_limit: Percentage1000,
}
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct PowerInfo {
pub valid: bool,
pub entries: Vec<PowerInfoEntry>,
}
impl RawConversion for power::private::NV_GPU_POWER_INFO_ENTRY {
type Target = PowerInfoEntry;
type Error = sys::ArgumentRangeError;
#[allow(non_snake_case)]
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
match *self {
power::private::NV_GPU_POWER_INFO_ENTRY {
pstate, b: 0, c: 0, min_power, e: 0, f: 0,
def_power, h: 0, i: 0, max_power, k: 0,
} => Ok(PowerInfoEntry {
pstate: ::pstate::PState::from_raw(pstate as _)?,
range: Range {
min: Percentage1000(min_power),
max: Percentage1000(max_power),
},
default_limit: Percentage1000(def_power),
}),
_ => Err(sys::ArgumentRangeError),
}
}
}
impl RawConversion for power::private::NV_GPU_POWER_INFO {
type Target = PowerInfo;
type Error = sys::ArgumentRangeError;
#[allow(non_snake_case)]
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
Ok(PowerInfo {
valid: self.valid != 0,
entries: self.entries[..self.count as usize].iter().map(RawConversion::convert_raw).collect::<Result<_, _>>()?,
})
}
}
impl RawConversion for power::private::NV_GPU_POWER_TOPO_ENTRY {
type Target = Percentage1000;
type Error = sys::ArgumentRangeError;
#[allow(non_snake_case)]
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
match *self {
power::private::NV_GPU_POWER_TOPO_ENTRY {
a: unknown, b: 0, power, d: 0
} => Ok(Percentage1000(power)),
_ => Err(sys::ArgumentRangeError),
}
}
}
impl RawConversion for power::private::NV_GPU_POWER_TOPO {
type Target = Vec<Percentage1000>;
type Error = sys::ArgumentRangeError;
#[allow(non_snake_case)]
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
self.entries[..self.count as usize].iter().map(RawConversion::convert_raw).collect()
}
}
impl RawConversion for power::private::NV_GPU_POWER_STATUS_ENTRY {
type Target = Percentage1000;
type Error = sys::ArgumentRangeError;
#[allow(non_snake_case)]
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
match *self {
power::private::NV_GPU_POWER_STATUS_ENTRY {
a: 0, b: 0, power, d: 0,
} => Ok(Percentage1000(power)),
_ => Err(sys::ArgumentRangeError),
}
}
}
impl RawConversion for power::private::NV_GPU_POWER_STATUS {
type Target = Vec<Percentage1000>;
type Error = sys::ArgumentRangeError;
#[allow(non_snake_case)]
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
self.entries[..self.count as usize].iter().map(RawConversion::convert_raw).collect()
}
}
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct ClockLockEntry {
pub mode: ClockLockMode,
pub voltage: Microvolts,
}
impl RawConversion for clock::private::NV_CLOCK_LOCK_ENTRY {
type Target = ClockLockEntry;
type Error = sys::ArgumentRangeError;
#[allow(non_snake_case)]
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
match *self {
clock::private::NV_CLOCK_LOCK_ENTRY {
id: _id, b: 0, mode, d: 0, voltage_uV, f: 0,
} => Ok(ClockLockEntry {
mode: ClockLockMode::from_raw(mode)?,
voltage: Microvolts(voltage_uV),
}),
_ => Err(sys::ArgumentRangeError),
}
}
}
impl RawConversion for clock::private::NV_CLOCK_LOCK {
type Target = BTreeMap<usize, ClockLockEntry>;
type Error = sys::ArgumentRangeError;
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
if self.flags != 0 {
Err(sys::ArgumentRangeError)
} else {
self.entries[..self.count as usize].iter().map(|v| v.convert_raw().map(|e| (v.id as usize, e))).collect()
}
}
}
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct PerfInfo {
pub max_unknown: u32,
pub limits: PerfFlags,
}
impl RawConversion for power::private::NV_GPU_PERF_INFO {
type Target = PerfInfo;
type Error = sys::ArgumentRangeError;
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
Ok(PerfInfo {
max_unknown: self.maxUnknown,
limits: PerfFlags::from_bits(self.limitSupport).ok_or(sys::ArgumentRangeError)?,
})
}
}
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct PerfStatus {
pub unknown: u32,
pub limits: PerfFlags,
}
impl RawConversion for power::private::NV_GPU_PERF_STATUS {
type Target = PerfStatus;
type Error = sys::ArgumentRangeError;
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
match *self {
power::private::NV_GPU_PERF_STATUS {
flags: 0, limits, zero0: 0, unknown, zero1: 0, ..
} => Ok(PerfStatus {
unknown: unknown,
limits: PerfFlags::from_bits(limits).ok_or(sys::ArgumentRangeError)?,
}),
_ => Err(sys::ArgumentRangeError),
}
}
}
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct VoltageEntry {
pub unknown: u32,
pub voltage: Microvolts,
}
impl RawConversion for power::private::NV_VOLT_TABLE_ENTRY {
type Target = VoltageEntry;
type Error = Void;
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
Ok(VoltageEntry {
unknown: self.unknown,
voltage: Microvolts(self.voltage_uV),
})
}
}
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct VoltageTable {
pub flags: u32,
pub entries: Vec<VoltageEntry>,
}
impl RawConversion for power::private::NV_VOLT_TABLE {
type Target = VoltageTable;
type Error = sys::ArgumentRangeError;
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
Ok(VoltageTable {
flags: self.flags,
entries: self.entries.iter().map(RawConversion::convert_raw).collect::<Result<_, _>>().void_unwrap(),
})
}
}
#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct VoltageStatus {
pub flags: u32,
pub unknown0: u32,
pub voltage: Microvolts,
pub count: u32,
pub unknown1: [u32; 30],
}
impl RawConversion for power::private::NV_VOLT_STATUS {
type Target = VoltageStatus;
type Error = sys::ArgumentRangeError;
fn convert_raw(&self) -> Result<Self::Target, Self::Error> {
trace!("convert_raw({:#?})", self);
Ok(VoltageStatus {
flags: self.flags,
count: self.count,
unknown0: self.unknown,
voltage: Microvolts(self.value_uV),
unknown1: self.buf1,
})
}
}