@@ -200,7 +200,7 @@ class Context {
|
||||
const rocprofiler_feature_kind_t kind = info->kind;
|
||||
const char* name = info->name;
|
||||
|
||||
if (kind != ROCPROFILER_FEATURE_KIND_TRACE) { // Processing metrics features
|
||||
if (kind == ROCPROFILER_FEATURE_KIND_METRIC) { // Processing metrics features
|
||||
const Metric* metric = metrics_->Get(name);
|
||||
if (metric == NULL)
|
||||
EXC_RAISING(HSA_STATUS_ERROR, "input metric '" << name << "' is not found");
|
||||
|
||||
@@ -38,7 +38,7 @@ class Metric {
|
||||
virtual const xml::Expr* GetExpr() const = 0;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
const std::string name_;
|
||||
};
|
||||
|
||||
class BaseMetric : public Metric {
|
||||
@@ -107,10 +107,38 @@ class MetricsDict {
|
||||
}
|
||||
}
|
||||
|
||||
const Metric* Get(const std::string& name) const {
|
||||
const Metric* Get(const std::string& name) {
|
||||
const Metric* metric = NULL;
|
||||
|
||||
auto it = cache_.find(name);
|
||||
if (it != cache_.end()) metric = it->second;
|
||||
else {
|
||||
const std::size_t pos = name.find(':');
|
||||
if (pos != std::string::npos) {
|
||||
std::string block_name = name.substr(0, pos);
|
||||
const std::string event_str = name.substr(pos + 1);
|
||||
|
||||
uint32_t block_index = 0;
|
||||
bool indexed = false;
|
||||
const std::size_t pos1 = block_name.find('[');
|
||||
if (pos1 != std::string::npos) {
|
||||
const std::size_t pos2 = block_name.find(']');
|
||||
if (pos2 == std::string::npos) EXC_RAISING(HSA_STATUS_ERROR, "Malformed metric name '" << name << "'");
|
||||
block_name = name.substr(0, pos1);
|
||||
const std::string block_index_str = name.substr(pos1 + 1, pos2 - (pos1 + 1));
|
||||
block_index = atol(block_index_str.c_str());
|
||||
indexed = true;
|
||||
}
|
||||
|
||||
const hsa_ven_amd_aqlprofile_id_query_t query = Translate(agent_info_, block_name);
|
||||
const hsa_ven_amd_aqlprofile_block_name_t block_id = (hsa_ven_amd_aqlprofile_block_name_t)query.id;
|
||||
if ((query.instance_count > 1) && (indexed == false)) EXC_RAISING(HSA_STATUS_ERROR, "Malformed indexed metric name '" << name << "'");
|
||||
const uint32_t event_id = atol(event_str.c_str());
|
||||
const counter_t counter = {name, {block_id, block_index, event_id}};
|
||||
metric = new BaseMetric(name, counter);
|
||||
}
|
||||
}
|
||||
|
||||
return metric;
|
||||
}
|
||||
|
||||
@@ -119,12 +147,15 @@ class MetricsDict {
|
||||
const_iterator_t End() const { return cache_.end(); }
|
||||
|
||||
private:
|
||||
MetricsDict(const util::AgentInfo* agent_info) : xml_(NULL) {
|
||||
MetricsDict(const util::AgentInfo* agent_info) : xml_(NULL), agent_info_(agent_info) {
|
||||
const char* xml_name = getenv("ROCP_METRICS");
|
||||
if (xml_name != NULL) {
|
||||
xml_ = xml::Xml::Create(xml_name);
|
||||
if (xml_ == NULL) EXC_RAISING(HSA_STATUS_ERROR, "metrics .xml open error '" << xml_name << "'");
|
||||
std::cout << "ROCProfiler: importing metrics from '" << xml_name << "':" << std::endl;
|
||||
xml_->AddConst("top.const.metric", "NUM_SIMDS", 64);
|
||||
xml_->AddConst("top.const.metric", "NUM_SHADER_ENGINES", 4);
|
||||
std::cout << "ROCProfiler: importing '" << xml_name << "':" << std::endl;
|
||||
ImportMetrics(agent_info, "const");
|
||||
ImportMetrics(agent_info, agent_info->gfxip);
|
||||
ImportMetrics(agent_info, "global");
|
||||
}
|
||||
@@ -135,47 +166,53 @@ class MetricsDict {
|
||||
for (auto& entry : cache_) delete entry.second;
|
||||
}
|
||||
|
||||
void ImportMetrics(const util::AgentInfo* agent_info, const char* scope) {
|
||||
auto scope_list = xml_->GetNodes("top." + std::string(scope) + ".metric");
|
||||
static hsa_ven_amd_aqlprofile_id_query_t Translate(const util::AgentInfo* agent_info, const std::string& block_name) {
|
||||
hsa_ven_amd_aqlprofile_profile_t profile;
|
||||
profile.agent = agent_info->dev_id;
|
||||
hsa_ven_amd_aqlprofile_id_query_t query = {block_name.c_str(), 0, 0};
|
||||
hsa_status_t status =
|
||||
util::HsaRsrcFactory::Instance().AqlProfileApi()->hsa_ven_amd_aqlprofile_get_info(
|
||||
&profile, HSA_VEN_AMD_AQLPROFILE_INFO_BLOCK_ID, &query);
|
||||
if (status != HSA_STATUS_SUCCESS) AQL_EXC_RAISING(HSA_STATUS_ERROR, "ImportMetrics: bad block name '" << block_name << "'");
|
||||
return query;
|
||||
}
|
||||
|
||||
void ImportMetrics(const util::AgentInfo* agent_info, const std::string& scope) {
|
||||
auto scope_list = xml_->GetNodes("top." + scope + ".metric");
|
||||
if (!scope_list.empty()) {
|
||||
std::cout << " " << scope_list.size() << " " << scope << " metrics found" << std::endl;
|
||||
|
||||
for (auto node : scope_list) {
|
||||
const std::string name = node->opts["name"];
|
||||
if (cache_.find(name) != cache_.end())
|
||||
EXC_RAISING(HSA_STATUS_ERROR, "ImportMetrics: metrics redefined '" << name << "'");
|
||||
|
||||
const std::string expr_str = node->opts["expr"];
|
||||
std::string descr = node->opts["descr"];
|
||||
if (descr.empty()) descr = (expr_str.empty()) ? name : expr_str;
|
||||
|
||||
if (expr_str.empty()) {
|
||||
const std::string block_name = node->opts["block"];
|
||||
const uint32_t event_id = atoi(node->opts["event"].c_str());
|
||||
const std::string event_str = node->opts["event"];
|
||||
const uint32_t event_id = atol(event_str.c_str());
|
||||
|
||||
hsa_ven_amd_aqlprofile_profile_t profile;
|
||||
profile.agent = agent_info->dev_id;
|
||||
hsa_ven_amd_aqlprofile_id_query_t query = {block_name.c_str(), 0, 0};
|
||||
hsa_status_t status =
|
||||
util::HsaRsrcFactory::Instance().AqlProfileApi()->hsa_ven_amd_aqlprofile_get_info(
|
||||
&profile, HSA_VEN_AMD_AQLPROFILE_INFO_BLOCK_ID, &query);
|
||||
if (status == HSA_STATUS_SUCCESS) {
|
||||
const hsa_ven_amd_aqlprofile_block_name_t block_id =
|
||||
(hsa_ven_amd_aqlprofile_block_name_t)query.id;
|
||||
if (query.instance_count > 1) {
|
||||
for (unsigned block_index = 0; block_index < query.instance_count; ++block_index) {
|
||||
std::ostringstream os;
|
||||
os << name << '[' << block_index << ']';
|
||||
const std::string full_name = os.str();
|
||||
const counter_t counter = {full_name, {block_id, block_index, event_id}};
|
||||
cache_[full_name] = new BaseMetric(full_name, counter);
|
||||
}
|
||||
} else {
|
||||
const counter_t counter = {name, {block_id, 0, event_id}};
|
||||
cache_[name] = new BaseMetric(name, counter);
|
||||
const hsa_ven_amd_aqlprofile_id_query_t query = Translate(agent_info, block_name);
|
||||
const hsa_ven_amd_aqlprofile_block_name_t block_id = (hsa_ven_amd_aqlprofile_block_name_t)query.id;
|
||||
if (query.instance_count > 1) {
|
||||
for (unsigned block_index = 0; block_index < query.instance_count; ++block_index) {
|
||||
std::ostringstream full_name;
|
||||
full_name << name << '[' << block_index << ']';
|
||||
std::ostringstream alias;
|
||||
alias << block_name << "[" << block_index << "]:" << event_str;
|
||||
const counter_t counter = {full_name.str(), {block_id, block_index, event_id}};
|
||||
AddMetric(full_name.str(), alias.str(), counter);
|
||||
}
|
||||
} else
|
||||
AQL_EXC_RAISING(HSA_STATUS_ERROR, "ImportMetrics: bad block name '" << block_name
|
||||
<< "'");
|
||||
} else {
|
||||
const std::string alias = block_name + ":" + event_str;
|
||||
const counter_t counter = {name, {block_id, 0, event_id}};
|
||||
AddMetric(name, alias, counter);
|
||||
}
|
||||
} else {
|
||||
xml::Expr* expr_obj = new xml::Expr(expr_str, new ExprCache(&cache_));
|
||||
std::cout << "# " << descr << std::endl;
|
||||
std::cout << name << "=" << expr_obj->String() << "\n" << std::endl;
|
||||
counters_vec_t counters_vec;
|
||||
for (const std::string var : expr_obj->GetVars()) {
|
||||
auto it = cache_.find(var);
|
||||
@@ -184,12 +221,46 @@ class MetricsDict {
|
||||
<< "' is not found");
|
||||
it->second->GetCounters(counters_vec);
|
||||
}
|
||||
cache_[name] = new ExprMetric(name, counters_vec, expr_obj);
|
||||
AddMetric(name, counters_vec, expr_obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Metric* AddMetric(const std::string& name, const std::string& /*alias*/, const counter_t& counter) {
|
||||
const Metric* metric = NULL;
|
||||
const auto ret = cache_.insert({name, NULL});
|
||||
if (ret.second) {
|
||||
metric = new BaseMetric(name, counter);
|
||||
ret.first->second = metric;
|
||||
} else EXC_RAISING(HSA_STATUS_ERROR, "metric redefined '" << name << "'");
|
||||
#if 0
|
||||
if (alias != name) {
|
||||
if (cache_.find(alias) != cache_.end()) EXC_RAISING(HSA_STATUS_ERROR, "metric alias/name interference '" << alias << "'");
|
||||
const auto ret = aliases_.insert({alias, name});
|
||||
if (!ret.second) EXC_RAISING(HSA_STATUS_ERROR, "metric alias redefined '" << alias << "'");
|
||||
}
|
||||
#endif
|
||||
return metric;
|
||||
}
|
||||
|
||||
const Metric* AddMetric(const std::string& name, const counters_vec_t& counters_vec, const xml::Expr* expr_obj) {
|
||||
const Metric* metric = NULL;
|
||||
const auto ret = cache_.insert({name, NULL});
|
||||
if (ret.second) {
|
||||
metric = new ExprMetric(name, counters_vec, expr_obj);
|
||||
ret.first->second = metric;
|
||||
} else EXC_RAISING(HSA_STATUS_ERROR, "expr-metric redefined '" << name << "'");
|
||||
return metric;
|
||||
}
|
||||
|
||||
#if 0
|
||||
std::string UnAlias(const std::string& name) const {
|
||||
auto it = aliases_.find(name);
|
||||
return (it != aliases_.end()) ? it->second : name;
|
||||
}
|
||||
#endif
|
||||
|
||||
void Print() {
|
||||
for (auto& v : cache_) {
|
||||
const Metric* metric = v.second;
|
||||
@@ -203,7 +274,11 @@ class MetricsDict {
|
||||
}
|
||||
|
||||
xml::Xml* xml_;
|
||||
const util::AgentInfo* agent_info_;
|
||||
cache_t cache_;
|
||||
#if 0
|
||||
std::map<std::string, std::string> aliases_;
|
||||
#endif
|
||||
|
||||
static map_t* map_;
|
||||
static mutex_t mutex_;
|
||||
|
||||
@@ -79,15 +79,16 @@ class Profile {
|
||||
Profile(const util::AgentInfo* agent_info) : agent_info_(agent_info) {
|
||||
profile_ = {};
|
||||
profile_.agent = agent_info->dev_id;
|
||||
completion_signal_ = {};
|
||||
is_legacy_ = (strncmp(agent_info->name, "gfx8", 4) == 0);
|
||||
}
|
||||
virtual ~Profile() {
|
||||
if (!info_vector_.empty()) {
|
||||
info_vector_.clear();
|
||||
hsa_memory_free(profile_.command_buffer.ptr);
|
||||
hsa_memory_free(profile_.output_buffer.ptr);
|
||||
free(const_cast<event_t*>(profile_.events));
|
||||
free(const_cast<parameter_t*>(profile_.parameters));
|
||||
info_vector_.clear();
|
||||
if (profile_.command_buffer.ptr) hsa_memory_free(profile_.command_buffer.ptr);
|
||||
if (profile_.output_buffer.ptr) hsa_memory_free(profile_.output_buffer.ptr);
|
||||
if (profile_.events) free(const_cast<event_t*>(profile_.events));
|
||||
if (profile_.parameters) free(const_cast<parameter_t*>(profile_.parameters));
|
||||
if (completion_signal_.handle) {
|
||||
hsa_status_t status = hsa_signal_destroy(completion_signal_);
|
||||
if (status != HSA_STATUS_SUCCESS) EXC_RAISING(status, "signal_destroy " << std::hex << status);
|
||||
}
|
||||
|
||||
@@ -26,12 +26,14 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <hsa.h>
|
||||
#include <hsa_ext_amd.h>
|
||||
#include <hsa_ext_finalize.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cassert>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
@@ -76,6 +78,7 @@ hsa_status_t HsaRsrcFactory::FindMemRegionsCallback(hsa_region_t region, void* d
|
||||
// Constructor of the class
|
||||
HsaRsrcFactory::HsaRsrcFactory() {
|
||||
// Initialize the Hsa Runtime
|
||||
printf("HSA init\n");
|
||||
hsa_status_t status = hsa_init();
|
||||
CHECK_STATUS("Error in hsa_init", status);
|
||||
|
||||
@@ -100,6 +103,10 @@ HsaRsrcFactory::HsaRsrcFactory() {
|
||||
|
||||
// Destructor of the class
|
||||
HsaRsrcFactory::~HsaRsrcFactory() {
|
||||
for (auto p : cpu_list_) free(const_cast<AgentInfo*>(p));
|
||||
for (auto p : gpu_list_) free(const_cast<AgentInfo*>(p));
|
||||
|
||||
printf("HSA shutdown\n");
|
||||
hsa_status_t status = hsa_shut_down();
|
||||
CHECK_STATUS("Error in hsa_shut_down", status);
|
||||
}
|
||||
@@ -162,12 +169,15 @@ const AgentInfo* HsaRsrcFactory::AddAgentInfo(const hsa_agent_t agent) {
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_NAME, agent_info->name);
|
||||
strncpy(agent_info->gfxip, agent_info->name, 4);
|
||||
agent_info->gfxip[4] = '\0';
|
||||
agent_info->max_wave_size = 0;
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_WAVEFRONT_SIZE, &agent_info->max_wave_size);
|
||||
agent_info->max_queue_size = 0;
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_QUEUE_MAX_SIZE, &agent_info->max_queue_size);
|
||||
agent_info->profile = hsa_profile_t(108);
|
||||
hsa_agent_get_info(agent, HSA_AGENT_INFO_PROFILE, &agent_info->profile);
|
||||
agent_info->is_apu = (agent_info->profile == HSA_PROFILE_FULL) ? true : false;
|
||||
hsa_agent_get_info(agent, static_cast<hsa_agent_info_t>(HSA_AMD_AGENT_INFO_COMPUTE_UNIT_COUNT), &agent_info->cu_num);
|
||||
hsa_agent_get_info(agent, static_cast<hsa_agent_info_t>(HSA_AMD_AGENT_INFO_MAX_WAVES_PER_CU), &agent_info->waves_per_cu);
|
||||
hsa_agent_get_info(agent, static_cast<hsa_agent_info_t>(HSA_AMD_AGENT_INFO_NUM_SIMDS_PER_CU), &agent_info->simds_per_cu);
|
||||
hsa_agent_get_info(agent, static_cast<hsa_agent_info_t>(HSA_AMD_AGENT_INFO_NUM_SHADER_ENGINES), &agent_info->se_num);
|
||||
hsa_agent_get_info(agent, static_cast<hsa_agent_info_t>(HSA_AMD_AGENT_INFO_NUM_SHADER_ARRAYS_PER_SE), &agent_info->shader_arrays_per_se);
|
||||
|
||||
// Initialize memory regions to zero
|
||||
agent_info->kernarg_region.handle = 0;
|
||||
@@ -349,8 +359,8 @@ bool HsaRsrcFactory::TransferData(void* dest_buff, void* src_buff, uint32_t leng
|
||||
//
|
||||
// @return bool true if successful, false otherwise
|
||||
//
|
||||
bool HsaRsrcFactory::LoadAndFinalize(const AgentInfo* agent_info, const char* brig_path,
|
||||
char* kernel_name, hsa_executable_symbol_t* code_desc) {
|
||||
void* HsaRsrcFactory::LoadAndFinalize(const AgentInfo* agent_info, const char* brig_path,
|
||||
const char* kernel_name, hsa_executable_t* hsa_exec, hsa_executable_symbol_t* code_desc) {
|
||||
// Finalize the Hsail object into code object
|
||||
hsa_status_t status;
|
||||
hsa_code_object_t code_object;
|
||||
@@ -364,52 +374,52 @@ bool HsaRsrcFactory::LoadAndFinalize(const AgentInfo* agent_info, const char* br
|
||||
if (!codeStream) {
|
||||
std::cerr << "Error: failed to load " << filename << std::endl;
|
||||
assert(false);
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Allocate memory to read in code object from file
|
||||
size_t size = std::string::size_type(codeStream.tellg());
|
||||
char* codeBuff = (char*)AllocateSysMemory(agent_info, size);
|
||||
if (!codeBuff) {
|
||||
char* code_buf = (char*)AllocateSysMemory(agent_info, size);
|
||||
if (!code_buf) {
|
||||
std::cerr << "Error: failed to allocate memory for code object." << std::endl;
|
||||
assert(false);
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read the code object into allocated memory
|
||||
codeStream.seekg(0, std::ios::beg);
|
||||
std::copy(std::istreambuf_iterator<char>(codeStream), std::istreambuf_iterator<char>(), codeBuff);
|
||||
std::copy(std::istreambuf_iterator<char>(codeStream), std::istreambuf_iterator<char>(), code_buf);
|
||||
|
||||
// De-Serialize the code object that has been read into memory
|
||||
status = hsa_code_object_deserialize(codeBuff, size, NULL, &code_object);
|
||||
status = hsa_code_object_deserialize(code_buf, size, NULL, &code_object);
|
||||
if (status != HSA_STATUS_SUCCESS) {
|
||||
std::cerr << "Failed to deserialize code object" << std::endl;
|
||||
return false;
|
||||
if (code_buf) hsa_memory_free(code_buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create executable.
|
||||
hsa_executable_t hsaExecutable;
|
||||
status =
|
||||
hsa_executable_create(HSA_PROFILE_FULL, HSA_EXECUTABLE_STATE_UNFROZEN, "", &hsaExecutable);
|
||||
hsa_executable_create(HSA_PROFILE_FULL, HSA_EXECUTABLE_STATE_UNFROZEN, "", hsa_exec);
|
||||
CHECK_STATUS("Error in creating executable object", status);
|
||||
|
||||
// Load code object.
|
||||
status = hsa_executable_load_code_object(hsaExecutable, agent_info->dev_id, code_object, "");
|
||||
status = hsa_executable_load_code_object(*hsa_exec, agent_info->dev_id, code_object, "");
|
||||
CHECK_STATUS("Error in loading executable object", status);
|
||||
|
||||
// Freeze executable.
|
||||
status = hsa_executable_freeze(hsaExecutable, "");
|
||||
status = hsa_executable_freeze(*hsa_exec, "");
|
||||
CHECK_STATUS("Error in freezing executable object", status);
|
||||
|
||||
// Get symbol handle.
|
||||
hsa_executable_symbol_t kernelSymbol;
|
||||
status = hsa_executable_get_symbol(hsaExecutable, NULL, kernel_name, agent_info->dev_id, 0,
|
||||
status = hsa_executable_get_symbol(*hsa_exec, NULL, kernel_name, agent_info->dev_id, 0,
|
||||
&kernelSymbol);
|
||||
CHECK_STATUS("Error in looking up kernel symbol", status);
|
||||
|
||||
// Update output parameter
|
||||
*code_desc = kernelSymbol;
|
||||
return true;
|
||||
return code_buf;
|
||||
}
|
||||
|
||||
// Print the various fields of Hsa Gpu Agents
|
||||
@@ -423,13 +433,47 @@ bool HsaRsrcFactory::PrintGpuAgents(const std::string& header) {
|
||||
|
||||
std::clog << "> agent[" << idx << "] :" << std::endl;
|
||||
std::clog << ">> Name : " << agent_info->name << std::endl;
|
||||
std::clog << ">> APU : " << agent_info->is_apu << std::endl;
|
||||
std::clog << ">> HSAIL profile : " << agent_info->profile << std::endl;
|
||||
std::clog << ">> Max Wave Size : " << agent_info->max_wave_size << std::endl;
|
||||
std::clog << ">> Max Queue Size : " << agent_info->max_queue_size << std::endl;
|
||||
std::clog << ">> Kernarg Region Id : " << agent_info->coarse_region.handle << std::endl;
|
||||
std::clog << ">> CU number : " << agent_info->cu_num << std::endl;
|
||||
std::clog << ">> Waves per CU : " << agent_info->waves_per_cu << std::endl;
|
||||
std::clog << ">> SIMDs per CU : " << agent_info->simds_per_cu << std::endl;
|
||||
std::clog << ">> SE number : " << agent_info->se_num << std::endl;
|
||||
std::clog << ">> Shader Arrays per SE : " << agent_info->shader_arrays_per_se << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64_t HsaRsrcFactory::Submit(hsa_queue_t* queue, void* packet) {
|
||||
const uint32_t slot_size_b = 0x40;
|
||||
|
||||
// adevance command queue
|
||||
const uint64_t write_idx = hsa_queue_load_write_index_relaxed(queue);
|
||||
hsa_queue_store_write_index_relaxed(queue, write_idx + 1);
|
||||
while ((write_idx - hsa_queue_load_read_index_relaxed(queue)) >= queue->size) {
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
uint32_t slot_idx = (uint32_t)(write_idx % queue->size);
|
||||
uint32_t* queue_slot = (uint32_t*)((uintptr_t)(queue->base_address) + (slot_idx * slot_size_b));
|
||||
uint32_t* slot_data = (uint32_t*)packet;
|
||||
|
||||
// Copy buffered commands into the queue slot.
|
||||
// Overwrite the AQL invalid header (first dword) last.
|
||||
// This prevents the slot from being read until it's fully written.
|
||||
memcpy(&queue_slot[1], &slot_data[1], slot_size_b - sizeof(uint32_t));
|
||||
std::atomic<uint32_t>* header_atomic_ptr = reinterpret_cast<std::atomic<uint32_t>*>(&queue_slot[0]);
|
||||
header_atomic_ptr->store(slot_data[0], std::memory_order_release);
|
||||
|
||||
// ringdoor bell
|
||||
hsa_signal_store_relaxed(queue->doorbell_signal, write_idx);
|
||||
|
||||
return write_idx;
|
||||
}
|
||||
|
||||
HsaRsrcFactory* HsaRsrcFactory::instance_ = NULL;
|
||||
HsaRsrcFactory::mutex_t HsaRsrcFactory::mutex_;
|
||||
|
||||
|
||||
@@ -67,6 +67,9 @@ struct AgentInfo {
|
||||
// Agent type - Cpu = 0, Gpu = 1 or Dsp = 2
|
||||
uint32_t dev_type;
|
||||
|
||||
// APU flag
|
||||
bool is_apu;
|
||||
|
||||
// Agent system index
|
||||
uint32_t dev_index;
|
||||
|
||||
@@ -90,6 +93,21 @@ struct AgentInfo {
|
||||
|
||||
// Memory region supporting kernel arguments
|
||||
hsa_region_t kernarg_region;
|
||||
|
||||
// The number of compute unit available in the agent.
|
||||
uint32_t cu_num;
|
||||
|
||||
// Maximum number of waves possible in a Compute Unit.
|
||||
uint32_t waves_per_cu;
|
||||
|
||||
// Number of SIMD's per compute unit CU
|
||||
uint32_t simds_per_cu;
|
||||
|
||||
// Number of Shader Engines (SE) in Gpu
|
||||
uint32_t se_num;
|
||||
|
||||
// Number of Shader Arrays Per Shader Engines in Gpu
|
||||
uint32_t shader_arrays_per_se;
|
||||
};
|
||||
|
||||
class HsaRsrcFactory {
|
||||
@@ -213,14 +231,17 @@ class HsaRsrcFactory {
|
||||
// @param code_desc Handle of finalized Code Descriptor that could
|
||||
// be used to submit for execution
|
||||
//
|
||||
// @return bool true if successful, false otherwise
|
||||
// @return code buffer, non NULL if successful, NULL otherwise
|
||||
//
|
||||
bool LoadAndFinalize(const AgentInfo* agent_info, const char* brig_path, char* kernel_name,
|
||||
hsa_executable_symbol_t* code_desc);
|
||||
void* LoadAndFinalize(const AgentInfo* agent_info, const char* brig_path, const char* kernel_name,
|
||||
hsa_executable_t* hsa_exec, hsa_executable_symbol_t* code_desc);
|
||||
|
||||
// Print the various fields of Hsa Gpu Agents
|
||||
bool PrintGpuAgents(const std::string& header);
|
||||
|
||||
// Submit AQL packet to given queue
|
||||
static uint64_t Submit(hsa_queue_t* queue, void* packet);
|
||||
|
||||
// Return AqlProfile API table
|
||||
typedef hsa_ven_amd_aqlprofile_1_00_pfn_t aqlprofile_pfn_t;
|
||||
const aqlprofile_pfn_t* AqlProfileApi() const { return &aqlprofile_api_; }
|
||||
|
||||
@@ -24,6 +24,7 @@ class div_zero_exception_t : public exception_t {
|
||||
};
|
||||
|
||||
typedef uint64_t args_t;
|
||||
static const args_t ARGS_MAX = UINT64_MAX;
|
||||
typedef std::map<std::string, args_t> args_map_t;
|
||||
class Expr;
|
||||
|
||||
@@ -177,14 +178,19 @@ class Expr {
|
||||
bool SubCheck() const { return (sub_count_ == 0); }
|
||||
unsigned FindOp() const {
|
||||
unsigned i = pos_;
|
||||
unsigned open_n = 0;
|
||||
while (i < expr_.length()) {
|
||||
switch (Symb(i)) {
|
||||
case '*':
|
||||
case '/':
|
||||
case '+':
|
||||
case '-':
|
||||
goto end;
|
||||
case '(':
|
||||
++open_n;
|
||||
break;
|
||||
case ')':
|
||||
if (open_n != 0) i += 1;
|
||||
goto end;
|
||||
}
|
||||
++i;
|
||||
@@ -263,6 +269,74 @@ class var_expr_t : public bin_expr_t {
|
||||
const std::string name_;
|
||||
};
|
||||
|
||||
class fun_expr_t : public bin_expr_t {
|
||||
public:
|
||||
typedef std::vector<var_expr_t> vvect_t;
|
||||
fun_expr_t(const std::string& fname, const std::string& vname, const uint32_t& vnum) : fname_(fname) {
|
||||
for (uint32_t i = 0; i < vnum; ++i) {
|
||||
std::ostringstream var_full_name;
|
||||
var_full_name << vname << "[" << i << "]";
|
||||
vvect.push_back(var_expr_t(var_full_name.str()));
|
||||
}
|
||||
}
|
||||
const vvect_t& GetVars() const { return vvect; }
|
||||
std::string Symbol() const {
|
||||
const std::string var = vvect[0].Symbol();
|
||||
const std::string vname = var.substr(0, var.length() - 3);
|
||||
std::ostringstream oss;
|
||||
std::string str("(");
|
||||
str.back() = ')';
|
||||
oss << fname_ << "(" << vname << "," << vvect.size() << ")";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string fname_;
|
||||
vvect_t vvect;
|
||||
};
|
||||
class sum_expr_t : public fun_expr_t {
|
||||
public:
|
||||
sum_expr_t(const std::string& vname, const uint32_t& vnum) : fun_expr_t("sum", vname, vnum) {}
|
||||
args_t Eval(const args_cache_t& args) const {
|
||||
args_t result = 0;
|
||||
for (const auto& var : GetVars()) result += var.Eval(args);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
class avr_expr_t : public fun_expr_t {
|
||||
public:
|
||||
avr_expr_t(const std::string& vname, const uint32_t& vnum) : fun_expr_t("avr", vname, vnum) {}
|
||||
args_t Eval(const args_cache_t& args) const {
|
||||
args_t result = 0;
|
||||
for (const auto& var : GetVars()) result += var.Eval(args);
|
||||
return result / GetVars().size();
|
||||
}
|
||||
};
|
||||
class min_expr_t : public fun_expr_t {
|
||||
public:
|
||||
min_expr_t(const std::string& vname, const uint32_t& vnum) : fun_expr_t("min", vname, vnum) {}
|
||||
args_t Eval(const args_cache_t& args) const {
|
||||
args_t result = ARGS_MAX;
|
||||
for (const auto& var : GetVars()) {
|
||||
args_t val = var.Eval(args);
|
||||
result = (val < result) ? val : result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
class max_expr_t : public fun_expr_t {
|
||||
public:
|
||||
max_expr_t(const std::string& vname, const uint32_t& vnum) : fun_expr_t("max", vname, vnum) {}
|
||||
args_t Eval(const args_cache_t& args) const {
|
||||
args_t result = 0;
|
||||
for (const auto& var : GetVars()) {
|
||||
args_t val = var.Eval(args);
|
||||
result = (val > result) ? val : result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
inline const bin_expr_t* bin_expr_t::CreateExpr(const bin_expr_t* arg1, const bin_expr_t* arg2,
|
||||
const char op) {
|
||||
const bin_expr_t* expr = NULL;
|
||||
@@ -285,11 +359,41 @@ inline const bin_expr_t* bin_expr_t::CreateExpr(const bin_expr_t* arg1, const bi
|
||||
|
||||
inline const bin_expr_t* bin_expr_t::CreateArg(Expr* obj, const std::string str) {
|
||||
const bin_expr_t* arg = NULL;
|
||||
|
||||
const unsigned i = strspn(str.c_str(), "1234567890");
|
||||
if (i == str.length()) {
|
||||
const unsigned value = atoi(str.c_str());
|
||||
arg = new const_expr_t(value);
|
||||
} else {
|
||||
}
|
||||
|
||||
if (arg == NULL) {
|
||||
const std::size_t pos = str.find('(');
|
||||
if (pos != std::string::npos) {
|
||||
char* fname = NULL;
|
||||
char* vname = NULL;
|
||||
int vnum = 0;
|
||||
int ret = sscanf(str.c_str(), "%m[a-zA-Z_](%m[0-9a-zA-Z_],%d)", &fname, &vname, &vnum);
|
||||
if (ret == 3) {
|
||||
const std::string fun_name(fname);
|
||||
const fun_expr_t* farg = NULL;
|
||||
if (fun_name == "sum") {
|
||||
farg = new sum_expr_t(vname, vnum);
|
||||
} else if (fun_name == "avr") {
|
||||
farg = new avr_expr_t(vname, vnum);
|
||||
} else if (fun_name == "min") {
|
||||
farg = new min_expr_t(vname, vnum);
|
||||
} else if (fun_name == "max") {
|
||||
farg = new max_expr_t(vname, vnum);
|
||||
}
|
||||
if (farg) for (const auto& var : farg->GetVars()) obj->AddVar(var.Symbol());
|
||||
arg = farg;
|
||||
}
|
||||
free(fname);
|
||||
free(vname);
|
||||
}
|
||||
}
|
||||
|
||||
if (arg == NULL) {
|
||||
const std::string sub_expr = obj->Lookup(str);
|
||||
if (sub_expr.empty()) {
|
||||
arg = new var_expr_t(str);
|
||||
@@ -299,6 +403,7 @@ inline const bin_expr_t* bin_expr_t::CreateArg(Expr* obj, const std::string str)
|
||||
arg = expr->GetTree();
|
||||
}
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,11 +36,29 @@ class Xml {
|
||||
return xml;
|
||||
}
|
||||
|
||||
void AddExpr(const std::string& full_tag, const std::string& name, const std::string& expr) {
|
||||
const std::size_t pos = full_tag.rfind('.');
|
||||
const std::size_t pos1 = (pos == std::string::npos) ? 0 : pos + 1;
|
||||
const std::string level_tag = full_tag.substr(pos1);
|
||||
level_t* level = new level_t;
|
||||
map_[full_tag].push_back(level);
|
||||
level->tag = level_tag;
|
||||
level->opts["name"] = name;
|
||||
level->opts["expr"] = expr;
|
||||
}
|
||||
|
||||
void AddConst(const std::string& full_tag, const std::string& name, const uint64_t& val) {
|
||||
std::ostringstream oss;
|
||||
oss << val;
|
||||
AddExpr(full_tag, name, oss.str());
|
||||
}
|
||||
|
||||
static void Destroy(Xml *xml) { delete xml; }
|
||||
|
||||
std::vector<level_t*> GetNodes(std::string global_tag) { return map_[global_tag]; }
|
||||
|
||||
void Print() const {
|
||||
std::cout << "XML file '" << file_name_ << "':" << std::endl;
|
||||
for (auto& elem : map_) {
|
||||
for (auto node : elem.second) {
|
||||
if (node->opts.size()) {
|
||||
@@ -74,13 +92,14 @@ class Xml {
|
||||
while (1) {
|
||||
token_t token = (remainder.size()) ? remainder : NextToken();
|
||||
remainder.clear();
|
||||
|
||||
// token_t token1 = token;
|
||||
// token1.push_back('\0');
|
||||
// std::cout << "> " << &token1[0] << std::endl;
|
||||
|
||||
// End of file
|
||||
if (token.size() == 0) break;
|
||||
|
||||
// token_t token1 = token;
|
||||
// token1.push_back('\0');
|
||||
// std::cout << "> " << &token1[0] << std::endl;
|
||||
|
||||
switch (state_) {
|
||||
case BODY_STATE:
|
||||
if (token[0] == '<') {
|
||||
@@ -146,6 +165,11 @@ class Xml {
|
||||
|
||||
~Xml() {}
|
||||
|
||||
bool SpaceCheck() const {
|
||||
bool cond = ((buffer_[index_] == ' ') || (buffer_[index_] == ' '));
|
||||
return cond;
|
||||
}
|
||||
|
||||
bool LineEndCheck() {
|
||||
bool found = false;
|
||||
if (buffer_[index_] == '\n') {
|
||||
@@ -162,24 +186,55 @@ class Xml {
|
||||
|
||||
token_t NextToken() {
|
||||
token_t token;
|
||||
bool in_string = false;
|
||||
bool special_symb = false;
|
||||
|
||||
while (1) {
|
||||
if (data_size_ == 0) {
|
||||
data_size_ = read(fd_, buffer_, buf_size_);
|
||||
if (data_size_ <= 0) break;
|
||||
}
|
||||
|
||||
if (token.empty())
|
||||
while ((index_ < data_size_) && ((buffer_[index_] == ' ') || LineEndCheck())) {
|
||||
while ((index_ < data_size_) && (SpaceCheck() || LineEndCheck())) {
|
||||
++index_;
|
||||
}
|
||||
while ((index_ < data_size_) && (buffer_[index_] != ' ') && !LineEndCheck()) {
|
||||
token.push_back(buffer_[index_++]);
|
||||
while ((index_ < data_size_) && (in_string || !(SpaceCheck() || LineEndCheck()))) {
|
||||
const char symb = buffer_[index_];
|
||||
bool skip_symb = false;
|
||||
|
||||
switch (symb) {
|
||||
case '\\':
|
||||
if (special_symb) special_symb = false;
|
||||
else {
|
||||
special_symb = true;
|
||||
skip_symb = true;
|
||||
}
|
||||
break;
|
||||
case '"':
|
||||
if (special_symb) special_symb = false;
|
||||
else {
|
||||
in_string = !in_string;
|
||||
if (!in_string) {
|
||||
buffer_[index_] = ' ';
|
||||
--index_;
|
||||
}
|
||||
skip_symb = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!skip_symb) token.push_back(symb);
|
||||
++index_;
|
||||
}
|
||||
|
||||
if (index_ == data_size_) {
|
||||
index_ = 0;
|
||||
data_size_ = 0;
|
||||
} else
|
||||
} else {
|
||||
if (special_symb || in_string) BadFormat(token);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return token;
|
||||
|
||||
Reference in New Issue
Block a user