use crate::rocprofiler::error::{Error, Result};
use crate::rocprofiler::bindings;
use std::ffi::{CStr, CString};
use std::ptr;
use std::slice;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FeatureKind {
Metric = bindings::rocprofiler_feature_kind_t_ROCPROFILER_FEATURE_KIND_METRIC as isize,
Trace = bindings::rocprofiler_feature_kind_t_ROCPROFILER_FEATURE_KIND_TRACE as isize,
SpmMod = bindings::rocprofiler_feature_kind_t_ROCPROFILER_FEATURE_KIND_SPM_MOD as isize,
PcsmpMod = bindings::rocprofiler_feature_kind_t_ROCPROFILER_FEATURE_KIND_PCSMP_MOD as isize,
}
impl From<u32> for FeatureKind {
fn from(value: u32) -> Self {
match value {
bindings::rocprofiler_feature_kind_t_ROCPROFILER_FEATURE_KIND_METRIC => FeatureKind::Metric,
bindings::rocprofiler_feature_kind_t_ROCPROFILER_FEATURE_KIND_TRACE => FeatureKind::Trace,
bindings::rocprofiler_feature_kind_t_ROCPROFILER_FEATURE_KIND_SPM_MOD => FeatureKind::SpmMod,
bindings::rocprofiler_feature_kind_t_ROCPROFILER_FEATURE_KIND_PCSMP_MOD => FeatureKind::PcsmpMod,
_ => FeatureKind::Metric, }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DataKind {
Uninit = bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_UNINIT as isize,
Int32 = bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_INT32 as isize,
Int64 = bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_INT64 as isize,
Float = bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_FLOAT as isize,
Double = bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_DOUBLE as isize,
Bytes = bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_BYTES as isize,
}
impl From<u32> for DataKind {
fn from(value: u32) -> Self {
match value {
bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_UNINIT => DataKind::Uninit,
bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_INT32 => DataKind::Int32,
bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_INT64 => DataKind::Int64,
bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_FLOAT => DataKind::Float,
bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_DOUBLE => DataKind::Double,
bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_BYTES => DataKind::Bytes,
_ => DataKind::Uninit, }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProfilerMode {
Standalone = bindings::rocprofiler_mode_t_ROCPROFILER_MODE_STANDALONE as isize,
CreateQueue = bindings::rocprofiler_mode_t_ROCPROFILER_MODE_CREATEQUEUE as isize,
SingleGroup = bindings::rocprofiler_mode_t_ROCPROFILER_MODE_SINGLEGROUP as isize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum InfoKind {
Metric = bindings::rocprofiler_info_kind_t_ROCPROFILER_INFO_KIND_METRIC as isize,
MetricCount = bindings::rocprofiler_info_kind_t_ROCPROFILER_INFO_KIND_METRIC_COUNT as isize,
Trace = bindings::rocprofiler_info_kind_t_ROCPROFILER_INFO_KIND_TRACE as isize,
TraceCount = bindings::rocprofiler_info_kind_t_ROCPROFILER_INFO_KIND_TRACE_COUNT as isize,
TraceParameter = bindings::rocprofiler_info_kind_t_ROCPROFILER_INFO_KIND_TRACE_PARAMETER as isize,
TraceParameterCount = bindings::rocprofiler_info_kind_t_ROCPROFILER_INFO_KIND_TRACE_PARAMETER_COUNT as isize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ParameterName {
SeMask = bindings::hsa_ven_amd_aqlprofile_parameter_name_t_HSA_VEN_AMD_AQLPROFILE_PARAMETER_NAME_SE_MASK as isize,
ComputeUnitTarget = bindings::hsa_ven_amd_aqlprofile_parameter_name_t_HSA_VEN_AMD_AQLPROFILE_PARAMETER_NAME_COMPUTE_UNIT_TARGET as isize,
SimdSelection = bindings::hsa_ven_amd_aqlprofile_parameter_name_t_HSA_VEN_AMD_AQLPROFILE_PARAMETER_NAME_SIMD_SELECTION as isize,
}
#[derive(Debug, Clone)]
pub struct Parameter {
parameter_name: u32,
value: u32,
}
impl Parameter {
pub fn new(name: ParameterName, value: u32) -> Self {
Self {
parameter_name: name as u32,
value,
}
}
pub fn name(&self) -> ParameterName {
match self.parameter_name {
bindings::hsa_ven_amd_aqlprofile_parameter_name_t_HSA_VEN_AMD_AQLPROFILE_PARAMETER_NAME_SE_MASK => ParameterName::SeMask,
bindings::hsa_ven_amd_aqlprofile_parameter_name_t_HSA_VEN_AMD_AQLPROFILE_PARAMETER_NAME_COMPUTE_UNIT_TARGET => ParameterName::ComputeUnitTarget,
bindings::hsa_ven_amd_aqlprofile_parameter_name_t_HSA_VEN_AMD_AQLPROFILE_PARAMETER_NAME_SIMD_SELECTION => ParameterName::SimdSelection,
_ => ParameterName::SeMask, }
}
pub fn value(&self) -> u32 {
self.value
}
pub(crate) fn to_c(&self) -> bindings::rocprofiler_parameter_t {
bindings::rocprofiler_parameter_t {
parameter_name: self.parameter_name,
value: self.value,
}
}
}
#[derive(Debug, Clone)]
pub enum Data {
Uninit,
Int32(u32),
Int64(u64),
Float(f32),
Double(f64),
Bytes(Vec<u8>, u32),
}
impl Data {
pub(crate) fn from_c(data: &bindings::rocprofiler_data_t) -> Self {
match data.kind {
bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_UNINIT => Data::Uninit,
bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_INT32 => {
let value = unsafe { data.__bindgen_anon_1.result_int32 };
Data::Int32(value)
},
bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_INT64 => {
let value = unsafe { data.__bindgen_anon_1.result_int64 };
Data::Int64(value)
},
bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_FLOAT => {
let value = unsafe { data.__bindgen_anon_1.result_float };
Data::Float(value)
},
bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_DOUBLE => {
let value = unsafe { data.__bindgen_anon_1.result_double };
Data::Double(value)
},
bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_BYTES => {
unsafe {
let bytes_info = &data.__bindgen_anon_1.result_bytes;
if bytes_info.ptr.is_null() {
Data::Bytes(Vec::new(), 0)
} else {
let ptr = bytes_info.ptr as *const u8;
let size = bytes_info.size as usize;
let instances = bytes_info.instance_count;
let data_slice = slice::from_raw_parts(ptr, size);
Data::Bytes(data_slice.to_vec(), instances)
}
}
},
_ => Data::Uninit,
}
}
}
#[derive(Debug, Clone)]
pub struct MetricInfo {
pub name: String,
pub instances: u32,
pub expression: Option<String>,
pub description: Option<String>,
pub block_name: Option<String>,
pub block_counters: u32,
}
#[derive(Debug, Clone)]
pub struct TraceInfo {
pub name: String,
pub description: Option<String>,
pub parameter_count: u32,
}
#[derive(Debug, Clone)]
pub struct TraceParameterInfo {
pub code: u32,
pub trace_name: String,
pub parameter_name: String,
pub description: Option<String>,
}
#[derive(Debug, Clone)]
pub enum InfoData {
Metric(MetricInfo),
Trace(TraceInfo),
TraceParameter(TraceParameterInfo),
}
impl InfoData {
pub(crate) fn from_c(data: &bindings::rocprofiler_info_data_t) -> Result<Self> {
let kind = data.kind;
match kind {
bindings::rocprofiler_info_kind_t_ROCPROFILER_INFO_KIND_METRIC => {
unsafe {
let metric_data = &data.__bindgen_anon_1.metric;
let name = if metric_data.name.is_null() {
return Err(Error::new(bindings::hsa_status_t_HSA_STATUS_ERROR_INVALID_ARGUMENT));
} else {
CStr::from_ptr(metric_data.name).to_string_lossy().into_owned()
};
let expression = if metric_data.expr.is_null() {
None
} else {
Some(CStr::from_ptr(metric_data.expr).to_string_lossy().into_owned())
};
let description = if metric_data.description.is_null() {
None
} else {
Some(CStr::from_ptr(metric_data.description).to_string_lossy().into_owned())
};
let block_name = if metric_data.block_name.is_null() {
None
} else {
Some(CStr::from_ptr(metric_data.block_name).to_string_lossy().into_owned())
};
Ok(InfoData::Metric(MetricInfo {
name,
instances: metric_data.instances,
expression,
description,
block_name,
block_counters: metric_data.block_counters,
}))
}
},
bindings::rocprofiler_info_kind_t_ROCPROFILER_INFO_KIND_TRACE => {
unsafe {
let trace_data = &data.__bindgen_anon_1.trace;
let name = if trace_data.name.is_null() {
return Err(Error::new(bindings::hsa_status_t_HSA_STATUS_ERROR_INVALID_ARGUMENT));
} else {
CStr::from_ptr(trace_data.name).to_string_lossy().into_owned()
};
let description = if trace_data.description.is_null() {
None
} else {
Some(CStr::from_ptr(trace_data.description).to_string_lossy().into_owned())
};
Ok(InfoData::Trace(TraceInfo {
name,
description,
parameter_count: trace_data.parameter_count,
}))
}
},
bindings::rocprofiler_info_kind_t_ROCPROFILER_INFO_KIND_TRACE_PARAMETER => {
unsafe {
let param_data = &data.__bindgen_anon_1.trace_parameter;
let trace_name = if param_data.trace_name.is_null() {
return Err(Error::new(bindings::hsa_status_t_HSA_STATUS_ERROR_INVALID_ARGUMENT));
} else {
CStr::from_ptr(param_data.trace_name).to_string_lossy().into_owned()
};
let parameter_name = if param_data.parameter_name.is_null() {
return Err(Error::new(bindings::hsa_status_t_HSA_STATUS_ERROR_INVALID_ARGUMENT));
} else {
CStr::from_ptr(param_data.parameter_name).to_string_lossy().into_owned()
};
let description = if param_data.description.is_null() {
None
} else {
Some(CStr::from_ptr(param_data.description).to_string_lossy().into_owned())
};
Ok(InfoData::TraceParameter(TraceParameterInfo {
code: param_data.code,
trace_name,
parameter_name,
description,
}))
}
},
_ => Err(Error::new(bindings::hsa_status_t_HSA_STATUS_ERROR_INVALID_ARGUMENT)),
}
}
}
#[derive(Debug)]
pub struct Group {
index: u32,
features: Vec<*mut bindings::rocprofiler_feature_t>,
context: *mut bindings::rocprofiler_t,
}
impl Group {
pub(crate) fn from_c(group: &bindings::rocprofiler_group_t) -> Self {
let features_slice = unsafe {
std::slice::from_raw_parts(group.features, group.feature_count as usize)
};
Self {
index: group.index,
features: features_slice.to_vec(),
context: group.context,
}
}
pub fn index(&self) -> u32 {
self.index
}
pub fn feature_count(&self) -> u32 {
self.features.len() as u32
}
pub fn start(&self) -> Result<()> {
let status = unsafe { bindings::rocprofiler_group_start(&mut self.to_c()) };
Error::from_hsa_status(status)
}
pub fn stop(&self) -> Result<()> {
let status = unsafe { bindings::rocprofiler_group_stop(&mut self.to_c()) };
Error::from_hsa_status(status)
}
pub fn read(&self) -> Result<()> {
let status = unsafe { bindings::rocprofiler_group_read(&mut self.to_c()) };
Error::from_hsa_status(status)
}
pub fn get_data(&self) -> Result<()> {
let status = unsafe { bindings::rocprofiler_group_get_data(&mut self.to_c()) };
Error::from_hsa_status(status)
}
pub(crate) fn to_c(&self) -> bindings::rocprofiler_group_t {
bindings::rocprofiler_group_t {
index: self.index,
features: self.features.as_ptr() as *mut *mut bindings::rocprofiler_feature_t,
feature_count: self.features.len() as u32,
context: self.context,
}
}
}
pub struct Feature {
kind: FeatureKind,
name: String,
name_cstr: Option<CString>,
parameters: Vec<Parameter>,
c_parameters: Vec<bindings::rocprofiler_parameter_t>,
data: Option<Data>,
c_feature: Option<Box<bindings::rocprofiler_feature_t>>,
}
impl Feature {
pub fn new_metric<S: Into<String>>(name: S, parameters: Vec<Parameter>) -> Self {
let name_string = name.into();
let name_cstr = CString::new(name_string.clone()).unwrap();
let c_parameters: Vec<bindings::rocprofiler_parameter_t> = parameters
.iter()
.map(|p| p.to_c())
.collect();
Self {
kind: FeatureKind::Metric,
name: name_string,
name_cstr: Some(name_cstr),
parameters,
c_parameters,
data: None,
c_feature: None,
}
}
pub fn name(&self) -> &str {
&self.name
}
pub fn kind(&self) -> FeatureKind {
self.kind
}
pub fn data(&self) -> Option<&Data> {
self.data.as_ref()
}
pub fn parameters(&self) -> &[Parameter] {
&self.parameters
}
pub(crate) fn set_data(&mut self, data: Data) {
self.data = Some(data);
}
pub(crate) fn update_from_c(&mut self, c_feature: *mut bindings::rocprofiler_feature_t) {
if !c_feature.is_null() {
unsafe {
self.data = Some(Data::from_c(&(*c_feature).data));
}
}
}
pub(crate) fn to_c(&mut self) -> *mut bindings::rocprofiler_feature_t {
if let Some(feature) = &self.c_feature {
return feature.as_ref() as *const bindings::rocprofiler_feature_t
as *mut bindings::rocprofiler_feature_t;
}
let name_ptr = self.name_cstr.as_ref()
.map(|cstr| cstr.as_ptr())
.unwrap_or(ptr::null());
let mut feature = Box::new(bindings::rocprofiler_feature_t {
kind: self.kind as u32,
__bindgen_anon_1: bindings::rocprofiler_feature_t__bindgen_ty_1 {
name: name_ptr,
},
parameters: if self.c_parameters.is_empty() {
ptr::null()
} else {
self.c_parameters.as_ptr()
},
parameter_count: self.c_parameters.len() as u32,
data: bindings::rocprofiler_data_t {
kind: bindings::rocprofiler_data_kind_t_ROCPROFILER_DATA_KIND_UNINIT,
__bindgen_anon_1: bindings::rocprofiler_data_t__bindgen_ty_1 {
result_int32: 0,
},
},
});
let ptr = feature.as_mut() as *mut bindings::rocprofiler_feature_t;
self.c_feature = Some(feature);
ptr
}
}