2018-06-25 19:22:36 -05:00
|
|
|
/******************************************************************************
|
2018-08-19 04:11:04 -05:00
|
|
|
Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved.
|
2018-06-25 19:22:36 -05:00
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
2018-08-19 04:11:04 -05:00
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
|
all copies or substantial portions of the Software.
|
2018-06-25 19:22:36 -05:00
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
2018-08-19 04:11:04 -05:00
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
2018-06-25 19:22:36 -05:00
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
2018-08-19 04:11:04 -05:00
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
THE SOFTWARE.
|
2018-06-25 19:22:36 -05:00
|
|
|
*******************************************************************************/
|
|
|
|
|
|
2017-11-09 17:26:19 -06:00
|
|
|
#ifndef SRC_CORE_PROFILE_H_
|
|
|
|
|
#define SRC_CORE_PROFILE_H_
|
|
|
|
|
|
|
|
|
|
#include "inc/rocprofiler.h"
|
|
|
|
|
|
|
|
|
|
#include <hsa.h>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
#include "core/types.h"
|
|
|
|
|
#include "util/exception.h"
|
|
|
|
|
#include "util/hsa_rsrc_factory.h"
|
|
|
|
|
|
|
|
|
|
namespace rocprofiler {
|
|
|
|
|
struct profile_info_t {
|
|
|
|
|
const event_t* event;
|
|
|
|
|
const parameter_t* parameters;
|
|
|
|
|
uint32_t parameter_count;
|
2017-11-27 16:51:03 -06:00
|
|
|
rocprofiler_feature_t* rinfo;
|
2017-11-09 17:26:19 -06:00
|
|
|
};
|
2017-11-27 16:51:03 -06:00
|
|
|
typedef std::vector<rocprofiler_feature_t*> info_vector_t;
|
2017-11-09 17:26:19 -06:00
|
|
|
typedef std::vector<packet_t> pkt_vector_t;
|
|
|
|
|
struct profile_tuple_t {
|
|
|
|
|
const profile_t* profile;
|
|
|
|
|
info_vector_t* info_vector;
|
|
|
|
|
hsa_signal_t completion_signal;
|
|
|
|
|
};
|
|
|
|
|
typedef std::vector<profile_tuple_t> profile_vector_t;
|
|
|
|
|
|
2017-11-29 13:53:12 -06:00
|
|
|
template <class Item> class ConfigBase {};
|
2017-11-09 17:26:19 -06:00
|
|
|
|
2017-11-29 13:53:12 -06:00
|
|
|
template <> class ConfigBase<event_t> {
|
|
|
|
|
public:
|
|
|
|
|
ConfigBase(profile_t* profile) : profile_(profile) {}
|
2017-11-09 17:26:19 -06:00
|
|
|
|
2017-11-29 13:53:12 -06:00
|
|
|
protected:
|
2017-11-09 17:26:19 -06:00
|
|
|
void* Array() { return const_cast<event_t*>(profile_->events); }
|
|
|
|
|
unsigned Count() const { return profile_->event_count; }
|
|
|
|
|
void Set(event_t* events, const unsigned& count) {
|
|
|
|
|
profile_->events = events;
|
|
|
|
|
profile_->event_count = count;
|
|
|
|
|
}
|
|
|
|
|
profile_t* profile_;
|
|
|
|
|
};
|
|
|
|
|
|
2017-11-29 13:53:12 -06:00
|
|
|
template <> class ConfigBase<parameter_t> {
|
|
|
|
|
public:
|
|
|
|
|
ConfigBase(profile_t* profile) : profile_(profile) {}
|
2017-11-09 17:26:19 -06:00
|
|
|
|
2017-11-29 13:53:12 -06:00
|
|
|
protected:
|
2017-11-09 17:26:19 -06:00
|
|
|
void* Array() { return const_cast<parameter_t*>(profile_->parameters); }
|
|
|
|
|
unsigned Count() const { return profile_->parameter_count; }
|
|
|
|
|
void Set(parameter_t* parameters, const unsigned& count) {
|
|
|
|
|
profile_->parameters = parameters;
|
|
|
|
|
profile_->parameter_count = count;
|
|
|
|
|
}
|
|
|
|
|
profile_t* profile_;
|
|
|
|
|
};
|
|
|
|
|
|
2017-11-29 13:53:12 -06:00
|
|
|
template <class Item> class Config : protected ConfigBase<Item> {
|
2017-11-09 17:26:19 -06:00
|
|
|
typedef ConfigBase<Item> Parent;
|
2017-11-29 13:53:12 -06:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
Config(profile_t* profile) : Parent(profile) {}
|
2017-11-09 17:26:19 -06:00
|
|
|
void Insert(const Item& item) {
|
|
|
|
|
auto count = Parent::Count();
|
|
|
|
|
count += 1;
|
2017-11-29 13:53:12 -06:00
|
|
|
Item* array =
|
|
|
|
|
reinterpret_cast<Item*>(realloc(const_cast<void*>(Parent::Array()), count * sizeof(Item)));
|
2017-11-09 17:26:19 -06:00
|
|
|
array[count - 1] = item;
|
|
|
|
|
Parent::Set(array, count);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class Profile {
|
2017-11-29 13:53:12 -06:00
|
|
|
public:
|
|
|
|
|
static const uint32_t LEGACY_SLOT_SIZE_PKT =
|
|
|
|
|
HSA_VEN_AMD_AQLPROFILE_LEGACY_PM4_PACKET_SIZE / sizeof(packet_t);
|
2017-11-09 17:26:19 -06:00
|
|
|
|
|
|
|
|
Profile(const util::AgentInfo* agent_info) : agent_info_(agent_info) {
|
|
|
|
|
profile_ = {};
|
|
|
|
|
profile_.agent = agent_info->dev_id;
|
2018-02-01 14:52:21 -06:00
|
|
|
completion_signal_ = {};
|
2017-11-09 17:26:19 -06:00
|
|
|
is_legacy_ = (strncmp(agent_info->name, "gfx8", 4) == 0);
|
|
|
|
|
}
|
2018-06-21 13:01:15 -05:00
|
|
|
|
2017-11-09 17:26:19 -06:00
|
|
|
virtual ~Profile() {
|
2018-02-01 14:52:21 -06:00
|
|
|
info_vector_.clear();
|
2018-04-27 20:00:20 -05:00
|
|
|
if (profile_.command_buffer.ptr) util::HsaRsrcFactory::FreeMemory(profile_.command_buffer.ptr);
|
|
|
|
|
if (profile_.output_buffer.ptr) util::HsaRsrcFactory::FreeMemory(profile_.output_buffer.ptr);
|
2018-02-01 14:52:21 -06:00
|
|
|
if (profile_.events) free(const_cast<event_t*>(profile_.events));
|
|
|
|
|
if (profile_.parameters) free(const_cast<parameter_t*>(profile_.parameters));
|
|
|
|
|
if (completion_signal_.handle) {
|
2017-12-21 22:24:32 -06:00
|
|
|
hsa_status_t status = hsa_signal_destroy(completion_signal_);
|
2018-03-29 15:28:59 -05:00
|
|
|
if (status != HSA_STATUS_SUCCESS) EXC_ABORT(status, "signal_destroy " << std::hex << status);
|
2017-12-21 22:24:32 -06:00
|
|
|
}
|
2017-11-09 17:26:19 -06:00
|
|
|
}
|
|
|
|
|
|
2017-11-29 13:53:12 -06:00
|
|
|
virtual void Insert(const profile_info_t& info) { info_vector_.push_back(info.rinfo); }
|
2017-11-09 17:26:19 -06:00
|
|
|
|
2018-02-02 15:38:28 -06:00
|
|
|
hsa_status_t Finalize(pkt_vector_t& start_vector, pkt_vector_t& stop_vector, pkt_vector_t& read_vector) {
|
2017-11-09 17:26:19 -06:00
|
|
|
hsa_status_t status = HSA_STATUS_SUCCESS;
|
|
|
|
|
|
|
|
|
|
if (!info_vector_.empty()) {
|
|
|
|
|
util::HsaRsrcFactory* rsrc = &util::HsaRsrcFactory::Instance();
|
|
|
|
|
const pfn_t* api = rsrc->AqlProfileApi();
|
|
|
|
|
packet_t start{};
|
|
|
|
|
packet_t stop{};
|
2018-02-02 15:38:28 -06:00
|
|
|
packet_t read{};
|
2017-11-09 17:26:19 -06:00
|
|
|
|
|
|
|
|
// Check the profile buffer sizes
|
|
|
|
|
status = api->hsa_ven_amd_aqlprofile_start(&profile_, NULL);
|
|
|
|
|
if (status != HSA_STATUS_SUCCESS) AQL_EXC_RAISING(status, "aqlprofile_start(NULL)");
|
2018-04-04 12:14:29 -05:00
|
|
|
status = Allocate(rsrc);
|
|
|
|
|
if (status != HSA_STATUS_SUCCESS) AQL_EXC_RAISING(status, "Allocate()");
|
2018-06-21 13:01:15 -05:00
|
|
|
|
|
|
|
|
// Generate start/stop/read profiling packets
|
2017-11-09 17:26:19 -06:00
|
|
|
status = api->hsa_ven_amd_aqlprofile_start(&profile_, &start);
|
|
|
|
|
if (status != HSA_STATUS_SUCCESS) AQL_EXC_RAISING(status, "aqlprofile_start");
|
|
|
|
|
status = api->hsa_ven_amd_aqlprofile_stop(&profile_, &stop);
|
|
|
|
|
if (status != HSA_STATUS_SUCCESS) AQL_EXC_RAISING(status, "aqlprofile_stop");
|
2018-06-26 16:05:39 -05:00
|
|
|
#ifdef AQLPROF_NEW_API
|
2018-06-21 13:01:15 -05:00
|
|
|
hsa_status_t rd_status = api->hsa_ven_amd_aqlprofile_read(&profile_, &read);
|
|
|
|
|
#if 0 // Read API returns error if disabled
|
|
|
|
|
if (rd_status != HSA_STATUS_SUCCESS) AQL_EXC_RAISING(status, "aqlprofile_read");
|
|
|
|
|
#endif
|
2018-06-26 16:05:39 -05:00
|
|
|
#else
|
|
|
|
|
hsa_status_t rd_status = HSA_STATUS_ERROR;
|
|
|
|
|
#endif
|
2018-02-02 15:38:28 -06:00
|
|
|
|
2018-06-21 13:01:15 -05:00
|
|
|
// Set completion signal
|
2017-11-09 17:26:19 -06:00
|
|
|
hsa_signal_t dummy_signal{};
|
|
|
|
|
dummy_signal.handle = 0;
|
|
|
|
|
start.completion_signal = dummy_signal;
|
|
|
|
|
hsa_signal_t post_signal;
|
|
|
|
|
status = hsa_signal_create(1, 0, NULL, &post_signal);
|
2017-12-21 22:24:32 -06:00
|
|
|
if (status != HSA_STATUS_SUCCESS) EXC_RAISING(status, "signal_create " << std::hex << status);
|
2017-11-09 17:26:19 -06:00
|
|
|
stop.completion_signal = post_signal;
|
2018-02-02 15:38:28 -06:00
|
|
|
read.completion_signal = post_signal;
|
2017-11-09 17:26:19 -06:00
|
|
|
completion_signal_ = post_signal;
|
|
|
|
|
|
2018-06-21 13:01:15 -05:00
|
|
|
// Fill packet vectors
|
2017-11-09 17:26:19 -06:00
|
|
|
if (is_legacy_) {
|
|
|
|
|
const uint32_t start_index = start_vector.size();
|
|
|
|
|
const uint32_t stop_index = stop_vector.size();
|
|
|
|
|
|
|
|
|
|
start_vector.insert(start_vector.end(), LEGACY_SLOT_SIZE_PKT, packet_t{});
|
|
|
|
|
stop_vector.insert(stop_vector.end(), LEGACY_SLOT_SIZE_PKT, packet_t{});
|
2018-02-02 15:38:28 -06:00
|
|
|
|
2017-11-29 13:53:12 -06:00
|
|
|
status = api->hsa_ven_amd_aqlprofile_legacy_get_pm4(
|
|
|
|
|
&start, reinterpret_cast<void*>(&start_vector[start_index]));
|
|
|
|
|
if (status != HSA_STATUS_SUCCESS)
|
|
|
|
|
AQL_EXC_RAISING(status, "hsa_ven_amd_aqlprofile_legacy_get_pm4");
|
2018-06-21 13:01:15 -05:00
|
|
|
|
2017-11-29 13:53:12 -06:00
|
|
|
status = api->hsa_ven_amd_aqlprofile_legacy_get_pm4(
|
|
|
|
|
&stop, reinterpret_cast<void*>(&stop_vector[stop_index]));
|
|
|
|
|
if (status != HSA_STATUS_SUCCESS)
|
|
|
|
|
AQL_EXC_RAISING(status, "hsa_ven_amd_aqlprofile_legacy_get_pm4");
|
2018-02-02 15:38:28 -06:00
|
|
|
|
2018-06-21 13:01:15 -05:00
|
|
|
if (rd_status == HSA_STATUS_SUCCESS) {
|
|
|
|
|
const uint32_t read_index = read_vector.size();
|
|
|
|
|
read_vector.insert(read_vector.end(), LEGACY_SLOT_SIZE_PKT, packet_t{});
|
|
|
|
|
status = api->hsa_ven_amd_aqlprofile_legacy_get_pm4(
|
|
|
|
|
&read, reinterpret_cast<void*>(&read_vector[read_index]));
|
|
|
|
|
if (status != HSA_STATUS_SUCCESS)
|
|
|
|
|
AQL_EXC_RAISING(status, "hsa_ven_amd_aqlprofile_legacy_get_pm4");
|
|
|
|
|
}
|
2017-11-09 17:26:19 -06:00
|
|
|
} else {
|
|
|
|
|
start_vector.push_back(start);
|
|
|
|
|
stop_vector.push_back(stop);
|
2018-06-21 13:01:15 -05:00
|
|
|
if (rd_status == HSA_STATUS_SUCCESS) {
|
|
|
|
|
read_vector.push_back(read);
|
|
|
|
|
}
|
2017-11-09 17:26:19 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return status;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void GetProfiles(profile_vector_t& vec) {
|
|
|
|
|
if (!info_vector_.empty()) {
|
|
|
|
|
vec.push_back(profile_tuple_t{&profile_, &info_vector_, completion_signal_});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-15 20:59:24 -06:00
|
|
|
bool Empty() const { return info_vector_.empty(); }
|
|
|
|
|
|
2017-11-29 13:53:12 -06:00
|
|
|
protected:
|
2017-11-09 17:26:19 -06:00
|
|
|
virtual hsa_status_t Allocate(util::HsaRsrcFactory* rsrc) = 0;
|
|
|
|
|
|
|
|
|
|
const util::AgentInfo* const agent_info_;
|
|
|
|
|
bool is_legacy_;
|
|
|
|
|
profile_t profile_;
|
|
|
|
|
info_vector_t info_vector_;
|
|
|
|
|
hsa_signal_t completion_signal_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class PmcProfile : public Profile {
|
2017-11-29 13:53:12 -06:00
|
|
|
public:
|
2017-11-09 17:26:19 -06:00
|
|
|
PmcProfile(const util::AgentInfo* agent_info) : Profile(agent_info) {
|
|
|
|
|
profile_.type = HSA_VEN_AMD_AQLPROFILE_EVENT_TYPE_PMC;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Insert(const profile_info_t& info) {
|
|
|
|
|
Profile::Insert(info);
|
|
|
|
|
Config<event_t>(&profile_).Insert(*(info.event));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hsa_status_t Allocate(util::HsaRsrcFactory* rsrc) {
|
2017-11-29 13:53:12 -06:00
|
|
|
profile_.command_buffer.ptr =
|
2018-04-29 03:24:46 -05:00
|
|
|
rsrc->AllocateSysMemory(agent_info_, profile_.command_buffer.size);
|
2017-11-09 17:26:19 -06:00
|
|
|
profile_.output_buffer.ptr = rsrc->AllocateSysMemory(agent_info_, profile_.output_buffer.size);
|
2017-11-29 13:53:12 -06:00
|
|
|
return (profile_.command_buffer.ptr && profile_.output_buffer.ptr) ? HSA_STATUS_SUCCESS
|
|
|
|
|
: HSA_STATUS_ERROR;
|
2017-11-09 17:26:19 -06:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2019-05-31 20:20:28 -05:00
|
|
|
class TraceProfile : public Profile {
|
2017-11-29 13:53:12 -06:00
|
|
|
public:
|
2018-03-23 03:19:05 -05:00
|
|
|
static inline void SetSize(const uint32_t& size) { output_buffer_size_ = size; }
|
2018-04-11 13:26:51 -05:00
|
|
|
static inline uint32_t GetSize() { return output_buffer_size_; }
|
2018-04-29 03:24:46 -05:00
|
|
|
static inline void SetLocal(const bool& b) { output_buffer_local_ = b; }
|
|
|
|
|
static inline bool IsLocal() { return output_buffer_local_; }
|
2017-11-09 17:26:19 -06:00
|
|
|
|
2019-05-31 20:20:28 -05:00
|
|
|
TraceProfile(const util::AgentInfo* agent_info) : Profile(agent_info) {
|
|
|
|
|
profile_.type = HSA_VEN_AMD_AQLPROFILE_EVENT_TYPE_TRACE;
|
2017-11-09 17:26:19 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Insert(const profile_info_t& info) {
|
2019-06-04 15:29:37 -05:00
|
|
|
if (info.parameters != NULL) {
|
|
|
|
|
Profile::Insert(info);
|
|
|
|
|
for (unsigned j = 0; j < info.parameter_count; ++j) {
|
|
|
|
|
Config<parameter_t>(&profile_).Insert(info.parameters[j]);
|
|
|
|
|
}
|
|
|
|
|
} else if (info.event != NULL) {
|
2019-05-31 20:20:28 -05:00
|
|
|
Config<event_t>(&profile_).Insert(*(info.event));
|
2019-06-04 15:29:37 -05:00
|
|
|
} else {
|
|
|
|
|
EXC_ABORT(HSA_STATUS_ERROR, "invalid trace info inserted");
|
2017-11-09 17:26:19 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hsa_status_t Allocate(util::HsaRsrcFactory* rsrc) {
|
2017-11-29 13:53:12 -06:00
|
|
|
profile_.command_buffer.ptr =
|
2018-04-29 03:24:46 -05:00
|
|
|
rsrc->AllocateSysMemory(agent_info_, profile_.command_buffer.size);
|
2018-04-04 12:14:29 -05:00
|
|
|
profile_.output_buffer.size = output_buffer_size_;
|
2018-04-29 03:24:46 -05:00
|
|
|
profile_.output_buffer.ptr = (output_buffer_local_) ?
|
|
|
|
|
rsrc->AllocateLocalMemory(agent_info_, profile_.output_buffer.size) :
|
|
|
|
|
rsrc->AllocateSysMemory(agent_info_, profile_.output_buffer.size);
|
2017-11-29 13:53:12 -06:00
|
|
|
return (profile_.command_buffer.ptr && profile_.output_buffer.ptr) ? HSA_STATUS_SUCCESS
|
|
|
|
|
: HSA_STATUS_ERROR;
|
2017-11-09 17:26:19 -06:00
|
|
|
}
|
2018-03-23 03:19:05 -05:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
static uint32_t output_buffer_size_;
|
2018-04-29 03:24:46 -05:00
|
|
|
static bool output_buffer_local_;
|
2017-11-09 17:26:19 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // namespace rocprofiler
|
|
|
|
|
|
|
|
|
|
#endif // SRC_CORE_PROFILE_H_
|