minor fixes, debug output, comments, using env vars, dead code
Change-Id: I08ad73b561709c1818d78a9191c96d6ad141a609
[ROCm/ROCR-Runtime commit: 8618bf7e2c]
Αυτή η υποβολή περιλαμβάνεται σε:
υποβλήθηκε από
Evgeny Shcherbakov
γονέας
1351f204d4
υποβολή
9725267667
@@ -25,4 +25,6 @@ add_subdirectory ( ${TEST_DIR} ${PROJECT_BINARY_DIR}/test )
|
||||
#
|
||||
# Style format
|
||||
#
|
||||
execute_process ( COMMAND sh -xc "/usr/bin/find ${PROJ_DIR} ${TEST_DIR} ${API_DIR} -name '*.cpp' -o -name '*.hpp' -o -name '*.h' -exec /usr/bin/clang-format -i -style=file \{\} \;" )
|
||||
execute_process ( COMMAND sh -xc "/usr/bin/find ${PROJ_DIR} ${TEST_DIR} ${API_DIR} -name '*.cpp' -exec /usr/bin/clang-format -i -style=file \{\} \;" )
|
||||
execute_process ( COMMAND sh -xc "/usr/bin/find ${PROJ_DIR} ${TEST_DIR} ${API_DIR} -name '*.hpp' -exec /usr/bin/clang-format -i -style=file \{\} \;" )
|
||||
execute_process ( COMMAND sh -xc "/usr/bin/find ${PROJ_DIR} ${TEST_DIR} ${API_DIR} -name '*.h' -exec /usr/bin/clang-format -i -style=file \{\} \;" )
|
||||
|
||||
@@ -7,21 +7,19 @@ The library source tree:
|
||||
- doc - Documantation, the API specification and the presentation
|
||||
- inc - Public API
|
||||
- hsa_ext_amd_aql_profile.h - AMD AQL profile library public API
|
||||
- amd_aql_pm4_ib_packet.h - AQL PM4 IB packet type
|
||||
- src - AMD AQL profile library sources
|
||||
- aqlprofile - AMD AQL profile library
|
||||
- commandwriter - PM4 command writer originated from 'hsa-runtime/tools'
|
||||
- perfcounter - PM4 perfcounter manager originated from 'hsa-runtime/tools'
|
||||
- threadtrace - PM4 threadtrace manager originated from 'hsa-runtime/tools'
|
||||
- util - core/utils library build based on 'hsa-runtime/core/util'
|
||||
- test - the library test suite
|
||||
- ctrl - Test controll
|
||||
- common - Test common utils
|
||||
- util - Test utils
|
||||
- SimpleConvolution - Simple convolution test
|
||||
|
||||
To build the library:
|
||||
|
||||
$ cd ..../hsa-ext-aql-profile
|
||||
$ cd .../hsa-ext-aql-profile
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ cmake ..
|
||||
@@ -29,12 +27,13 @@ $ make
|
||||
|
||||
To run the test:
|
||||
|
||||
# cd ..../hsa-ext-aql-profile/build
|
||||
$ cp ../test/SimpleConvolution/gfx9_SimpleConvolution.hsaco .
|
||||
$ test/SimpleConvolution
|
||||
$ cd .../hsa-ext-aql-profile/build
|
||||
$ test/ctrl
|
||||
|
||||
to enable PMC profiling:
|
||||
export ROCR_ENABLE_PMC=1
|
||||
To enable PMC profiling:
|
||||
|
||||
to enable SQTT profiling:
|
||||
export ROCR_ENABLE_SQTT=1
|
||||
$ export ROCR_ENABLE_PMC=1
|
||||
|
||||
To enable SQTT profiling:
|
||||
|
||||
$ export ROCR_ENABLE_SQTT=1
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#ifndef _SI_PM4DEFS_H_
|
||||
#define _SI_PM4DEFS_H_
|
||||
|
||||
#include "si_ci_vi_merged_typedef.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* si_pm4defs.h
|
||||
|
||||
@@ -22,7 +22,9 @@
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#define COPY_DATA_SEL_COUNT_1DW 0 ///< Copy 1 word (32 bits)
|
||||
#define COPY_DATA_SEL_REG 0 ///< Mem-mapped register
|
||||
#define COPY_DATA_SEL_SRC_SYS_PERF_COUNTER 4 ///< Privileged memory performance counter
|
||||
#define COPY_DATA_SEL_COUNT_1DW 0 ///< Copy 1 word (32 bits)
|
||||
#define COPY_DATA_SEL_COUNT_2DW 1 ///< Copy 2 words (64 bits)
|
||||
|
||||
#endif // _GFX9_PM4DEFS_H_
|
||||
|
||||
+2
-2
@@ -202,9 +202,9 @@ hsa_status_t hsa_ext_amd_aql_profile_stop(
|
||||
const hsa_ext_amd_aql_profile_profile_t* profile, // [in] profile contex object
|
||||
hsa_ext_amd_aql_pm4_packet_t* aql_stop_packet); // [out] profile stop AQL packet
|
||||
|
||||
// Legacy PM4 profiling packet size
|
||||
// Legacy devices, PM4 profiling packet size
|
||||
const unsigned HSA_EXT_AQL_PROFILE_LEGACY_PM4_PACKET_SIZE = 192;
|
||||
// GFX8 support, converting the profiling AQL packet to PM4 packet blob
|
||||
// Legacy devices, converting the profiling AQL packet to PM4 packet blob
|
||||
hsa_status_t hsa_ext_amd_aql_profile_legacy_get_pm4(
|
||||
const hsa_ext_amd_aql_pm4_packet_t* aql_packet, // [in] AQL packet
|
||||
void* data); // [out] PM4 packet blob
|
||||
|
||||
@@ -24,6 +24,7 @@ set ( API_DIR ${ROOT_DIR}/inc )
|
||||
set ( HSA_RUNTIME_DIR ${PROJ_DIR}/../../.. )
|
||||
set ( HSA_RUNTIME_OSC_DIR ${HSA_RUNTIME_DIR}/opensrc/hsa-runtime )
|
||||
set ( CORE_UTIL_DIR ${HSA_RUNTIME_OSC_DIR}/core/util )
|
||||
|
||||
include_directories ( ${ROOT_DIR} )
|
||||
|
||||
#
|
||||
@@ -36,13 +37,6 @@ include ( ${ROOT_DIR}/cmake_modules/validateBldEnv.cmake )
|
||||
#
|
||||
include ( ${ROOT_DIR}/cmake_modules/exportToolFlags.cmake )
|
||||
|
||||
#
|
||||
# Set Name for Utils library and build it as a
|
||||
# static library to be linked with others
|
||||
#
|
||||
set ( UTIL_LIB "util${ONLY64STR}" )
|
||||
add_subdirectory ( ${PROJ_DIR}/util "${PROJECT_BINARY_DIR}/util" )
|
||||
|
||||
#
|
||||
# Set Name for Cmdwriter library and build it as a
|
||||
# static library to be linked with others
|
||||
|
||||
+2
-3
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Source files for Rocr Service Manager
|
||||
#
|
||||
set ( LIB_SRC aql_profile.cpp populate_aql.cpp gfx8_factory.cpp gfx9_factory.cpp )
|
||||
set ( LIB_SRC aql_profile.cpp populate_aql.cpp gfx8_factory.cpp gfx9_factory.cpp legacy_pm4.cpp )
|
||||
|
||||
#
|
||||
# Header files include path(s).
|
||||
@@ -10,12 +10,11 @@ include_directories ( $ENV{ROCR_INC_DIR} )
|
||||
include_directories ( ${PROJ_DIR}/perfcounter )
|
||||
include_directories ( ${PROJ_DIR}/threadtrace )
|
||||
include_directories ( ${PROJ_DIR}/commandwriter )
|
||||
include_directories ( ${HSA_RUNTIME_OSC_DIR} )
|
||||
include_directories ( ${API_DIR} )
|
||||
|
||||
#
|
||||
# Build Service Manager as a dynamic Library object
|
||||
#
|
||||
set ( LIB_LIST ${PMC_LIB} ${SQTT_LIB} ${CMDWRITER_LIB} ${UTIL_LIB} )
|
||||
set ( LIB_LIST ${PMC_LIB} ${SQTT_LIB} ${CMDWRITER_LIB} )
|
||||
add_library ( ${TARGET_LIB} SHARED ${LIB_SRC} )
|
||||
target_link_libraries( ${TARGET_LIB} ${LIB_LIST} c stdc++ dl pthread rt )
|
||||
|
||||
+30
-42
@@ -2,11 +2,10 @@
|
||||
|
||||
#include "aql_profile.h"
|
||||
#include "pm4_factory.h"
|
||||
#include "cmdwriter.h" // commandwriter
|
||||
#include "hsa_perf.h" // perfcounter
|
||||
#include "thread_trace.h" // threadtrace
|
||||
#include "gpu_enum.h"
|
||||
#include "gpu_blockinfo.h"
|
||||
#include "cmdwriter.h" // commandwriter
|
||||
#include "perf_counter.h" // perfcounter
|
||||
#include "thread_trace.h" // threadtrace
|
||||
#include "gpu_block_info.h"
|
||||
|
||||
#define PUBLIC_API __attribute__((visibility("default")))
|
||||
|
||||
@@ -129,6 +128,8 @@ hsa_status_t default_sqttdata_callback(hsa_ext_amd_aql_profile_info_type_t info_
|
||||
return status;
|
||||
}
|
||||
|
||||
Pm4Factory::tables_t Pm4Factory::tables;
|
||||
|
||||
} // aql_profile
|
||||
|
||||
extern "C" {
|
||||
@@ -142,8 +143,7 @@ PUBLIC_API hsa_status_t hsa_ext_amd_aql_profile_validate_event(
|
||||
// Method to populate the provided AQL packet with profiling start commands
|
||||
PUBLIC_API hsa_status_t hsa_ext_amd_aql_profile_start(
|
||||
const hsa_ext_amd_aql_profile_profile_t* profile, aql_profile::packet_t* aql_start_packet) {
|
||||
|
||||
aql_profile::Pm4Factory * pm4_factory = aql_profile::Pm4Factory::Create(profile);
|
||||
aql_profile::Pm4Factory* pm4_factory = aql_profile::Pm4Factory::Create(profile);
|
||||
if (pm4_factory == NULL) return HSA_STATUS_ERROR;
|
||||
|
||||
pm4_profile::CommandWriter* cmdWriter = pm4_factory->getCommandWriter();
|
||||
@@ -157,27 +157,22 @@ PUBLIC_API hsa_status_t hsa_ext_amd_aql_profile_start(
|
||||
pm4_profile::Pmu* pmcMgr = pm4_factory->getPmcMgr();
|
||||
if (pmcMgr == NULL) return HSA_STATUS_ERROR;
|
||||
|
||||
pmcMgr->setPmcDataBuff((uint8_t*)profile->output_buffer.ptr, profile->output_buffer.size);
|
||||
|
||||
pm4_profile::CountersMap countersMap;
|
||||
for (const hsa_ext_amd_aql_profile_event_t* p = profile->events;
|
||||
p < profile->events + profile->event_count; ++p) {
|
||||
pm4_profile::CounterBlock* block =
|
||||
pmcMgr->getCounterBlockById(pm4_factory->getBlockId(p));
|
||||
if (block == NULL) return HSA_STATUS_ERROR;
|
||||
|
||||
pm4_profile::Counter* counter = block->createCounter();
|
||||
if (counter == NULL) return HSA_STATUS_ERROR;
|
||||
|
||||
counter->setParameter(HSA_EXT_TOOLS_COUNTER_PARAMETER_EVENT_INDEX, sizeof(uint32_t),
|
||||
&(p->counter_id));
|
||||
counter->setEnable(true);
|
||||
countersMap[pm4_factory->getBlockId(p)].push_back(p->counter_id);
|
||||
}
|
||||
|
||||
// Generate start commands
|
||||
pmcMgr->begin(&commands, cmdWriter);
|
||||
pmcMgr->begin(&commands, cmdWriter, countersMap);
|
||||
cmdBufMgr.setPreSize(commands.Size());
|
||||
|
||||
// Generate stop commands
|
||||
pmcMgr->end(&commands, cmdWriter);
|
||||
const uint32_t data_size =
|
||||
pmcMgr->end(&commands, cmdWriter, countersMap, profile->output_buffer.ptr);
|
||||
if (data_size == 0) return HSA_STATUS_ERROR;
|
||||
assert(data_size <= profile->output_buffer.size);
|
||||
if (data_size > profile->output_buffer.size) return HSA_STATUS_ERROR;
|
||||
} else if (profile->type == HSA_EXT_AQL_PROFILE_EVENT_SQTT) {
|
||||
pm4_profile::ThreadTrace* sqttMgr = pm4_factory->getSqttMgr();
|
||||
if (sqttMgr == NULL) return HSA_STATUS_ERROR;
|
||||
@@ -241,8 +236,7 @@ PUBLIC_API hsa_status_t hsa_ext_amd_aql_profile_start(
|
||||
// Method to populate the provided AQL packet with profiling stop commands
|
||||
PUBLIC_API hsa_status_t hsa_ext_amd_aql_profile_stop(
|
||||
const hsa_ext_amd_aql_profile_profile_t* profile, aql_profile::packet_t* aql_stop_packet) {
|
||||
|
||||
aql_profile::Pm4Factory * pm4_factory = aql_profile::Pm4Factory::Create(profile);
|
||||
aql_profile::Pm4Factory* pm4_factory = aql_profile::Pm4Factory::Create(profile);
|
||||
if (pm4_factory == NULL) return HSA_STATUS_ERROR;
|
||||
|
||||
pm4_profile::CommandWriter* cmdWriter = pm4_factory->getCommandWriter();
|
||||
@@ -258,9 +252,9 @@ PUBLIC_API hsa_status_t hsa_ext_amd_aql_profile_stop(
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// GFX8 support, converting of the profiling AQL packet to PM4 packet blob
|
||||
PUBLIC_API hsa_status_t hsa_ext_amd_aql_profile_legacy_get_pm4(
|
||||
const aql_profile::packet_t* aql_packet, void* data) {
|
||||
// Legacy devices, converting of the profiling AQL packet to PM4 packet blob
|
||||
PUBLIC_API hsa_status_t
|
||||
hsa_ext_amd_aql_profile_legacy_get_pm4(const aql_profile::packet_t* aql_packet, void* data) {
|
||||
// Populate GFX8 pm4 packet blob
|
||||
// Adding HSA barrier acquire packet
|
||||
data = aql_profile::legacyAqlAcquire(aql_packet, data);
|
||||
@@ -272,9 +266,9 @@ PUBLIC_API hsa_status_t hsa_ext_amd_aql_profile_legacy_get_pm4(
|
||||
}
|
||||
|
||||
// Method for getting the profile info
|
||||
PUBLIC_API hsa_status_t hsa_ext_amd_aql_profile_get_info(
|
||||
const hsa_ext_amd_aql_profile_profile_t* profile, hsa_ext_amd_aql_profile_info_type_t attribute,
|
||||
void* value) {
|
||||
PUBLIC_API hsa_status_t
|
||||
hsa_ext_amd_aql_profile_get_info(const hsa_ext_amd_aql_profile_profile_t* profile,
|
||||
hsa_ext_amd_aql_profile_info_type_t attribute, void* value) {
|
||||
hsa_status_t status = HSA_STATUS_SUCCESS;
|
||||
|
||||
switch (attribute) {
|
||||
@@ -301,12 +295,11 @@ PUBLIC_API hsa_status_t hsa_ext_amd_aql_profile_get_info(
|
||||
}
|
||||
|
||||
// Method for iterating the events output data
|
||||
PUBLIC_API hsa_status_t hsa_ext_amd_aql_profile_iterate_data(
|
||||
const hsa_ext_amd_aql_profile_profile_t* profile,
|
||||
hsa_ext_amd_aql_profile_data_callback_t callback, void* data) {
|
||||
|
||||
PUBLIC_API hsa_status_t
|
||||
hsa_ext_amd_aql_profile_iterate_data(const hsa_ext_amd_aql_profile_profile_t* profile,
|
||||
hsa_ext_amd_aql_profile_data_callback_t callback, void* data) {
|
||||
hsa_status_t status = HSA_STATUS_SUCCESS;
|
||||
aql_profile::Pm4Factory * pm4_factory = aql_profile::Pm4Factory::Create(profile);
|
||||
aql_profile::Pm4Factory* pm4_factory = aql_profile::Pm4Factory::Create(profile);
|
||||
if (pm4_factory == NULL) return HSA_STATUS_ERROR;
|
||||
|
||||
if (profile->type == HSA_EXT_AQL_PROFILE_EVENT_PMC) {
|
||||
@@ -321,14 +314,9 @@ PUBLIC_API hsa_status_t hsa_ext_amd_aql_profile_iterate_data(
|
||||
|
||||
for (const hsa_ext_amd_aql_profile_event_t* p = profile->events;
|
||||
p < (profile->events + profile->event_count); ++p) {
|
||||
pm4_profile::CounterBlock* block =
|
||||
pmcMgr->getCounterBlockById(pm4_factory->getBlockId(p));
|
||||
if (block == NULL) return HSA_STATUS_ERROR;
|
||||
if (!block->getInfo(pm4_profile::GPU_BLK_INFO_CONTROL_METHOD, info_size, &info_data)) {
|
||||
return HSA_STATUS_ERROR;
|
||||
}
|
||||
const pm4_profile::CntlMethod method =
|
||||
static_cast<pm4_profile::CntlMethod>(*(static_cast<uint32_t*>(info_data)));
|
||||
const pm4_profile::GpuBlockInfo* block_info = pm4_factory->getBlockInfo(p);
|
||||
if (block_info == NULL) return HSA_STATUS_ERROR;
|
||||
const pm4_profile::CntlMethod method = pm4_factory->getBlockInfo(p)->method;
|
||||
// A perfcounter data sample per ShaderEngine
|
||||
const uint32_t block_samples_count = (method == pm4_profile::CntlMethodBySe ||
|
||||
method == pm4_profile::CntlMethodBySeAndInstance)
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ typedef hsa_ext_amd_aql_profile_data_callback_t data_callback_t;
|
||||
typedef hsa_ext_amd_aql_pm4_packet_t packet_t;
|
||||
typedef hsa_ext_amd_aql_profile_event_t event_t;
|
||||
|
||||
void populateAql(void* cmdBuffer, uint32_t cmdSz, pm4_profile::CommandWriter* cmdWriter,
|
||||
void populateAql(const void* cmd_buffer, uint32_t cmd_size, pm4_profile::CommandWriter* cmd_writer,
|
||||
packet_t* aql_packet);
|
||||
void* legacyAqlAcquire(const packet_t* aql_packet, void* data);
|
||||
void* legacyAqlRelease(const packet_t* aql_packet, void* data);
|
||||
|
||||
+7
-13
@@ -2,9 +2,11 @@
|
||||
// Commandwriter includes
|
||||
#include "gfx8_cmdwriter.h"
|
||||
// PMC includes
|
||||
#include "vi_pmu.h"
|
||||
#include "gfx8_perf_counter.h"
|
||||
// SQTT includes
|
||||
#include "gfx8_thread_trace.h"
|
||||
// Block info
|
||||
#include "gfx8_block_info.h"
|
||||
|
||||
namespace aql_profile {
|
||||
|
||||
@@ -24,20 +26,12 @@ uint32_t Gfx8Factory::block_id_table[HSA_EXT_AQL_PROFILE_BLOCKS_NUMBER] = {
|
||||
pm4_profile::kHsaViCounterBlockIdIa, pm4_profile::kHsaViCounterBlockIdMc,
|
||||
pm4_profile::kHsaViCounterBlockIdTcs, pm4_profile::kHsaViCounterBlockIdWd};
|
||||
|
||||
pm4_profile::CommandWriter * Gfx8Factory::getCommandWriter() {
|
||||
pm4_profile::CommandWriter* Gfx8Factory::getCommandWriter() {
|
||||
return new pm4_profile::gfx8::Gfx8CmdWriter(false, true);
|
||||
}
|
||||
|
||||
pm4_profile::Pmu * Gfx8Factory::getPmcMgr() {
|
||||
return new pm4_profile::ViPmu();
|
||||
}
|
||||
pm4_profile::Pmu* Gfx8Factory::getPmcMgr() { return new pm4_profile::Gfx8PerfCounter(); }
|
||||
|
||||
pm4_profile::ThreadTrace * Gfx8Factory::getSqttMgr() {
|
||||
return new pm4_profile::Gfx8ThreadTrace();
|
||||
}
|
||||
pm4_profile::ThreadTrace* Gfx8Factory::getSqttMgr() { return new pm4_profile::Gfx8ThreadTrace(); }
|
||||
|
||||
uint32_t Gfx8Factory::getBlockId(const event_t* event) {
|
||||
return block_id_table[event->block_name] + event->block_index;
|
||||
}
|
||||
|
||||
} // aql_profile
|
||||
} // aql_profile
|
||||
|
||||
-70
@@ -1,70 +0,0 @@
|
||||
#include "pm4_factory.h"
|
||||
// Commandwriter includes
|
||||
#include "gfx8_cmdwriter.h"
|
||||
#include "gfx9_cmdwriter.h"
|
||||
// PMC includes
|
||||
#include "vi_pmu.h"
|
||||
#include "ai_pmu.h"
|
||||
// SQTT includes
|
||||
#include "gfx8_thread_trace.h"
|
||||
#include "gfx9_thread_trace.h"
|
||||
|
||||
namespace aql_profile {
|
||||
|
||||
// GFX8 block ID mapping table
|
||||
uint32_t gfx8_block_id_table[HSA_EXT_AQL_PROFILE_BLOCKS_NUMBER] = {
|
||||
pm4_profile::kHsaViCounterBlockIdCb0, pm4_profile::kHsaViCounterBlockIdCpf,
|
||||
pm4_profile::kHsaViCounterBlockIdDb0, pm4_profile::kHsaViCounterBlockIdGrbm,
|
||||
pm4_profile::kHsaViCounterBlockIdGrbmSe, pm4_profile::kHsaViCounterBlockIdPaSu,
|
||||
pm4_profile::kHsaViCounterBlockIdPaSc, pm4_profile::kHsaViCounterBlockIdSpi,
|
||||
pm4_profile::kHsaViCounterBlockIdSq, pm4_profile::kHsaViCounterBlockIdSqGs,
|
||||
pm4_profile::kHsaViCounterBlockIdSqVs, pm4_profile::kHsaViCounterBlockIdSqPs,
|
||||
pm4_profile::kHsaViCounterBlockIdSqHs, pm4_profile::kHsaViCounterBlockIdSqCs,
|
||||
pm4_profile::kHsaViCounterBlockIdSx, pm4_profile::kHsaViCounterBlockIdTa0,
|
||||
pm4_profile::kHsaViCounterBlockIdTca0, pm4_profile::kHsaViCounterBlockIdTcc0,
|
||||
pm4_profile::kHsaViCounterBlockIdTd0, pm4_profile::kHsaViCounterBlockIdTcp0,
|
||||
pm4_profile::kHsaViCounterBlockIdGds, pm4_profile::kHsaViCounterBlockIdVgt,
|
||||
pm4_profile::kHsaViCounterBlockIdIa, pm4_profile::kHsaViCounterBlockIdMc,
|
||||
pm4_profile::kHsaViCounterBlockIdTcs, pm4_profile::kHsaViCounterBlockIdWd};
|
||||
|
||||
// GFX9 block ID mapping table
|
||||
uint32_t gfx9_block_id_table[HSA_EXT_AQL_PROFILE_BLOCKS_NUMBER] = {
|
||||
pm4_profile::kHsaAiCounterBlockIdCb0, pm4_profile::kHsaAiCounterBlockIdCpf,
|
||||
pm4_profile::kHsaAiCounterBlockIdDb0, pm4_profile::kHsaAiCounterBlockIdGrbm,
|
||||
pm4_profile::kHsaAiCounterBlockIdGrbmSe, pm4_profile::kHsaAiCounterBlockIdPaSu,
|
||||
pm4_profile::kHsaAiCounterBlockIdPaSc, pm4_profile::kHsaAiCounterBlockIdSpi,
|
||||
pm4_profile::kHsaAiCounterBlockIdSq, pm4_profile::kHsaAiCounterBlockIdSqGs,
|
||||
pm4_profile::kHsaAiCounterBlockIdSqVs, pm4_profile::kHsaAiCounterBlockIdSqPs,
|
||||
pm4_profile::kHsaAiCounterBlockIdSqHs, pm4_profile::kHsaAiCounterBlockIdSqCs,
|
||||
pm4_profile::kHsaAiCounterBlockIdSx, pm4_profile::kHsaAiCounterBlockIdTa0,
|
||||
pm4_profile::kHsaAiCounterBlockIdTca0, pm4_profile::kHsaAiCounterBlockIdTcc0,
|
||||
pm4_profile::kHsaAiCounterBlockIdTd0, pm4_profile::kHsaAiCounterBlockIdTcp0,
|
||||
pm4_profile::kHsaAiCounterBlockIdGds, pm4_profile::kHsaAiCounterBlockIdVgt,
|
||||
pm4_profile::kHsaAiCounterBlockIdIa, pm4_profile::kHsaAiCounterBlockIdMc,
|
||||
pm4_profile::kHsaAiCounterBlockIdTcs, pm4_profile::kHsaAiCounterBlockIdWd};
|
||||
|
||||
pm4_profile::CommandWriter * Pm4Factory::getCommandWriter() {
|
||||
return (is_gfx9 == true) ?
|
||||
new pm4_profile::gfx9::Gfx9CmdWriter(false, true) :
|
||||
new pm4_profile::gfx8::Gfx8CmdWriter(false, true);
|
||||
}
|
||||
|
||||
pm4_profile::Pmu * Pm4Factory::getPmcMgr() {
|
||||
return (is_gfx9 == true) ?
|
||||
new pm4_profile::AiPmu() :
|
||||
new pm4_profile::ViPmu();
|
||||
}
|
||||
|
||||
pm4_profile::ThreadTrace * Pm4Factory::getSqttMgr() {
|
||||
return (is_gfx9 == true) ?
|
||||
new pm4_profile::Gfx9ThreadTrace() :
|
||||
new pm4_profile::Gfx8ThreadTrace();
|
||||
}
|
||||
|
||||
uint32_t Pm4Factory::getBlockId(const event_t* event) {
|
||||
return (is_gfx9 == true) ?
|
||||
gfx9_block_id_table[event->block_name] + event->block_index :
|
||||
gfx8_block_id_table[event->block_name] + event->block_index :
|
||||
}
|
||||
|
||||
} // aql_profile
|
||||
+7
-13
@@ -2,9 +2,11 @@
|
||||
// Commandwriter includes
|
||||
#include "gfx9_cmdwriter.h"
|
||||
// PMC includes
|
||||
#include "ai_pmu.h"
|
||||
#include "gfx9_perf_counter.h"
|
||||
// SQTT includes
|
||||
#include "gfx9_thread_trace.h"
|
||||
// Block info
|
||||
#include "gfx9_block_info.h"
|
||||
|
||||
namespace aql_profile {
|
||||
|
||||
@@ -24,20 +26,12 @@ uint32_t Gfx9Factory::block_id_table[HSA_EXT_AQL_PROFILE_BLOCKS_NUMBER] = {
|
||||
pm4_profile::kHsaAiCounterBlockIdIa, pm4_profile::kHsaAiCounterBlockIdMc,
|
||||
pm4_profile::kHsaAiCounterBlockIdTcs, pm4_profile::kHsaAiCounterBlockIdWd};
|
||||
|
||||
pm4_profile::CommandWriter * Gfx9Factory::getCommandWriter() {
|
||||
pm4_profile::CommandWriter* Gfx9Factory::getCommandWriter() {
|
||||
return new pm4_profile::gfx9::Gfx9CmdWriter(false, true);
|
||||
}
|
||||
|
||||
pm4_profile::Pmu * Gfx9Factory::getPmcMgr() {
|
||||
return new pm4_profile::AiPmu();
|
||||
}
|
||||
pm4_profile::Pmu* Gfx9Factory::getPmcMgr() { return new pm4_profile::Gfx9PerfCounter(); }
|
||||
|
||||
pm4_profile::ThreadTrace * Gfx9Factory::getSqttMgr() {
|
||||
return new pm4_profile::Gfx9ThreadTrace();
|
||||
}
|
||||
pm4_profile::ThreadTrace* Gfx9Factory::getSqttMgr() { return new pm4_profile::Gfx9ThreadTrace(); }
|
||||
|
||||
uint32_t Gfx9Factory::getBlockId(const event_t* event) {
|
||||
return block_id_table[event->block_name] + event->block_index;
|
||||
}
|
||||
|
||||
} // aql_profile
|
||||
} // aql_profile
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "aql_profile.h"
|
||||
#include "amd_aql_pm4_ib_packet.h"
|
||||
#include "gfxip/gfx8/si_pm4defs.h"
|
||||
#include "gfxip/gfx8/si_ci_vi_merged_pm4_it_opcodes.h"
|
||||
#include "gfxip/gfx8/si_ci_vi_merged_pm4cmds.h"
|
||||
|
||||
namespace aql_profile {
|
||||
|
||||
typedef uint16_t aql_packet_header_t;
|
||||
|
||||
void* legacyAqlAcquire(const packet_t* aql_packet, void* data) {
|
||||
hsa_barrier_and_packet_t* aql_barrier = reinterpret_cast<hsa_barrier_and_packet_t*>(data);
|
||||
memset(aql_barrier, 0, sizeof(hsa_barrier_and_packet_t));
|
||||
const aql_packet_header_t aql_header_type = HSA_PACKET_TYPE_BARRIER_AND << HSA_PACKET_HEADER_TYPE;
|
||||
const aql_packet_header_t aql_header_barrier = 1ul << HSA_PACKET_HEADER_BARRIER;
|
||||
const aql_packet_header_t aql_header_acquire = HSA_FENCE_SCOPE_SYSTEM
|
||||
<< HSA_PACKET_HEADER_SCACQUIRE_FENCE_SCOPE;
|
||||
aql_barrier->header |= aql_header_type;
|
||||
aql_barrier->header |= aql_header_barrier;
|
||||
aql_barrier->header |= aql_header_acquire;
|
||||
return data + sizeof(hsa_barrier_and_packet_t);
|
||||
}
|
||||
|
||||
void* legacyAqlRelease(const packet_t* aql_packet, void* data) {
|
||||
hsa_barrier_and_packet_t* aql_barrier = reinterpret_cast<hsa_barrier_and_packet_t*>(data);
|
||||
memset(aql_barrier, 0, sizeof(hsa_barrier_and_packet_t));
|
||||
const aql_packet_header_t aql_header_type = HSA_PACKET_TYPE_BARRIER_AND << HSA_PACKET_HEADER_TYPE;
|
||||
const aql_packet_header_t aql_header_barrier = 1ul << HSA_PACKET_HEADER_BARRIER;
|
||||
const aql_packet_header_t aql_header_release = HSA_FENCE_SCOPE_SYSTEM
|
||||
<< HSA_PACKET_HEADER_SCRELEASE_FENCE_SCOPE;
|
||||
aql_barrier->header |= aql_header_type;
|
||||
aql_barrier->header |= aql_header_barrier;
|
||||
aql_barrier->header |= aql_header_release;
|
||||
aql_barrier->completion_signal = aql_packet->completion_signal;
|
||||
return data + sizeof(hsa_barrier_and_packet_t);
|
||||
}
|
||||
|
||||
void* legacyPm4(const packet_t* aql_packet, void* data) {
|
||||
constexpr uint32_t major_version = 8;
|
||||
constexpr uint32_t slot_size_b = 0x40;
|
||||
constexpr uint32_t slot_size_dw = uint32_t(slot_size_b / sizeof(uint32_t));
|
||||
constexpr uint32_t ib_jump_size_dw = 4;
|
||||
constexpr uint32_t rel_mem_size_dw = 7;
|
||||
constexpr uint32_t nop_pad_size_dw = slot_size_dw - (ib_jump_size_dw + rel_mem_size_dw);
|
||||
|
||||
// Construct a set of PM4 to fit inside the AQL packet slot.
|
||||
const amd_aql_pm4_ib_packet_t* aql_pm4_ib =
|
||||
reinterpret_cast<const amd_aql_pm4_ib_packet_t*>(aql_packet);
|
||||
uint32_t* const slot_data = (uint32_t*)data;
|
||||
uint32_t slot_dw_idx = 0;
|
||||
|
||||
// Construct a no-op command to pad the queue slot.
|
||||
uint32_t* nop_pad = &slot_data[slot_dw_idx];
|
||||
slot_dw_idx += nop_pad_size_dw;
|
||||
nop_pad[0] = PM4_CMD(IT_NOP, nop_pad_size_dw);
|
||||
for (int i = 1; i < nop_pad_size_dw; ++i) {
|
||||
nop_pad[i] = 0;
|
||||
}
|
||||
|
||||
// Copy in command to execute the IB.
|
||||
assert(slot_dw_idx + ib_jump_size_dw <= slot_size_dw);
|
||||
uint32_t* ib_jump = &slot_data[slot_dw_idx];
|
||||
slot_dw_idx += ib_jump_size_dw;
|
||||
assert(ib_jump_size_dw == sizeof(aql_pm4_ib->pm4_ib_command) / sizeof(uint32_t));
|
||||
memcpy(ib_jump, aql_pm4_ib->pm4_ib_command, sizeof(aql_pm4_ib->pm4_ib_command));
|
||||
|
||||
// Construct a command to advance the read index and invalidate the packet
|
||||
// header. This must be the last command since this releases the queue slot
|
||||
// for writing.
|
||||
assert(slot_dw_idx + rel_mem_size_dw <= slot_size_dw);
|
||||
PM4CMDRELEASEMEM* rel_mem = reinterpret_cast<PM4CMDRELEASEMEM*>(&slot_data[slot_dw_idx]);
|
||||
assert(rel_mem_size_dw == sizeof(*rel_mem) / sizeof(uint32_t));
|
||||
memset(rel_mem, 0, sizeof(*rel_mem));
|
||||
rel_mem->ordinal1 = PM4_CMD(IT_RELEASE_MEM__CI__VI, rel_mem_size_dw);
|
||||
rel_mem->eventIndex = EVENT_WRITE_INDEX_CACHE_FLUSH_EVENT;
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
std::ostringstream oss;
|
||||
oss << "AQL 'Legacy PM4' size(" << slot_size_dw << ")";
|
||||
std::clog << std::setw(40) << std::left << oss.str() << ":";
|
||||
for (int idx = 0; idx < 16; idx++) {
|
||||
std::clog << " " << std::hex << std::setw(8) << std::setfill('0') << slot_data[idx];
|
||||
}
|
||||
std::clog << std::setfill(' ') << std::endl;
|
||||
#endif
|
||||
|
||||
return data + slot_size_b;
|
||||
}
|
||||
|
||||
} // aql_profile
|
||||
+62
-3
@@ -3,13 +3,20 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <climits>
|
||||
|
||||
#include "aql_profile.h"
|
||||
#include "gpu_block_info.h"
|
||||
|
||||
namespace pm4_profile {
|
||||
class CommandWriter;
|
||||
class Pmu;
|
||||
class ThreadTrace;
|
||||
extern GpuBlockInfo Gfx9HwBlocks[];
|
||||
extern const uint32_t Gfx9HwBlockCount;
|
||||
extern GpuBlockInfo Gfx8HwBlocks[];
|
||||
extern const uint32_t Gfx8HwBlockCount;
|
||||
}
|
||||
|
||||
namespace aql_profile {
|
||||
@@ -20,15 +27,63 @@ class Pm4Factory {
|
||||
virtual pm4_profile::CommandWriter* getCommandWriter() = 0;
|
||||
virtual pm4_profile::Pmu* getPmcMgr() = 0;
|
||||
virtual pm4_profile::ThreadTrace* getSqttMgr() = 0;
|
||||
virtual uint32_t getBlockId(const event_t* event) = 0;
|
||||
|
||||
uint32_t getBlockId(const event_t* event) {
|
||||
const hsa_ext_amd_aql_profile_block_name_t block_name = event->block_name;
|
||||
return (block_name < tables.get_block_id_count())
|
||||
? tables.get_block_id_ptr()[block_name] + event->block_index
|
||||
: UINT_MAX;
|
||||
}
|
||||
const pm4_profile::GpuBlockInfo* getBlockInfo(const uint32_t& block_id) {
|
||||
const pm4_profile::GpuBlockInfo* info = NULL;
|
||||
if (block_id < tables.get_block_info_count()) {
|
||||
info = tables.get_block_info_ptr() + block_id;
|
||||
if (info->counterGroupId != block_id) info = NULL;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
const pm4_profile::GpuBlockInfo* getBlockInfo(const event_t* event) {
|
||||
const uint32_t block_id = getBlockId(event);
|
||||
return getBlockInfo(block_id);
|
||||
}
|
||||
|
||||
protected:
|
||||
class tables_t {
|
||||
public:
|
||||
tables_t(uint32_t* dp, uint32_t dc, pm4_profile::GpuBlockInfo* ip, uint32_t ic)
|
||||
: block_id_ptr(dp), block_id_count(dc), block_info_ptr(ip), block_info_count(ic) {}
|
||||
tables_t(const tables_t& t)
|
||||
: block_id_ptr(t.block_id_ptr),
|
||||
block_id_count(t.block_id_count),
|
||||
block_info_ptr(t.block_info_ptr),
|
||||
block_info_count(t.block_info_count) {}
|
||||
tables_t() : block_id_ptr(0), block_id_count(0), block_info_ptr(0), block_info_count(0) {}
|
||||
|
||||
uint32_t* get_block_id_ptr() { return block_id_ptr; }
|
||||
uint32_t get_block_id_count() { return block_id_count; }
|
||||
pm4_profile::GpuBlockInfo* get_block_info_ptr() { return block_info_ptr; }
|
||||
uint32_t get_block_info_count() { return block_info_count; }
|
||||
|
||||
private:
|
||||
uint32_t* block_id_ptr;
|
||||
uint32_t block_id_count;
|
||||
pm4_profile::GpuBlockInfo* block_info_ptr;
|
||||
uint32_t block_info_count;
|
||||
};
|
||||
|
||||
Pm4Factory(const tables_t& t) { tables = t; }
|
||||
|
||||
static tables_t tables;
|
||||
};
|
||||
|
||||
class Gfx8Factory : public Pm4Factory {
|
||||
public:
|
||||
Gfx8Factory()
|
||||
: Pm4Factory(tables_t(block_id_table, HSA_EXT_AQL_PROFILE_BLOCKS_NUMBER,
|
||||
pm4_profile::Gfx8HwBlocks, pm4_profile::Gfx8HwBlockCount)) {}
|
||||
pm4_profile::CommandWriter* getCommandWriter();
|
||||
pm4_profile::Pmu* getPmcMgr();
|
||||
pm4_profile::ThreadTrace* getSqttMgr();
|
||||
uint32_t getBlockId(const event_t* event);
|
||||
|
||||
private:
|
||||
static uint32_t block_id_table[HSA_EXT_AQL_PROFILE_BLOCKS_NUMBER];
|
||||
@@ -36,10 +91,12 @@ class Gfx8Factory : public Pm4Factory {
|
||||
|
||||
class Gfx9Factory : public Pm4Factory {
|
||||
public:
|
||||
Gfx9Factory()
|
||||
: Pm4Factory(tables_t(block_id_table, HSA_EXT_AQL_PROFILE_BLOCKS_NUMBER,
|
||||
pm4_profile::Gfx9HwBlocks, pm4_profile::Gfx9HwBlockCount)) {}
|
||||
pm4_profile::CommandWriter* getCommandWriter();
|
||||
pm4_profile::Pmu* getPmcMgr();
|
||||
pm4_profile::ThreadTrace* getSqttMgr();
|
||||
uint32_t getBlockId(const event_t* event);
|
||||
|
||||
private:
|
||||
static uint32_t block_id_table[HSA_EXT_AQL_PROFILE_BLOCKS_NUMBER];
|
||||
@@ -49,11 +106,13 @@ inline Pm4Factory* Pm4Factory::Create(const hsa_ext_amd_aql_profile_profile_t* p
|
||||
Pm4Factory* instance = NULL;
|
||||
char agent_name[64];
|
||||
hsa_agent_get_info(profile->agent, HSA_AGENT_INFO_NAME, agent_name);
|
||||
|
||||
if (strncmp(agent_name, "gfx8", 4) == 0) {
|
||||
instance = new Gfx8Factory();
|
||||
} else if (strncmp(agent_name, "gfx9", 4) == 0) {
|
||||
instance = new Gfx9Factory();
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
+16
-92
@@ -1,96 +1,15 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <assert.h>
|
||||
|
||||
#include "aql_profile.h"
|
||||
#include "cmdwriter.h"
|
||||
#include "amd_aql_pm4_ib_packet.h"
|
||||
#include "core/inc/amd_gpu_pm4.h"
|
||||
|
||||
namespace aql_profile {
|
||||
|
||||
typedef uint16_t aql_packet_header_t;
|
||||
|
||||
void * legacyAqlAcquire(const packet_t* aql_packet, void * data) {
|
||||
hsa_barrier_and_packet_t * aql_barrier =
|
||||
reinterpret_cast<hsa_barrier_and_packet_t*>(data);
|
||||
memset(aql_barrier, 0 , sizeof(hsa_barrier_and_packet_t));
|
||||
const aql_packet_header_t aql_header_type =
|
||||
HSA_PACKET_TYPE_BARRIER_AND << HSA_PACKET_HEADER_TYPE;
|
||||
const aql_packet_header_t aql_header_barrier =
|
||||
1ul << HSA_PACKET_HEADER_BARRIER;
|
||||
aql_barrier->header |= aql_header_type;
|
||||
aql_barrier->header |= aql_header_barrier;
|
||||
return data + sizeof(hsa_barrier_and_packet_t);
|
||||
}
|
||||
|
||||
void * legacyAqlRelease(const packet_t* aql_packet, void * data) {
|
||||
hsa_barrier_and_packet_t * aql_barrier =
|
||||
reinterpret_cast<hsa_barrier_and_packet_t*>(data);
|
||||
memset(aql_barrier, 0 , sizeof(hsa_barrier_and_packet_t));
|
||||
const aql_packet_header_t aql_header_type =
|
||||
HSA_PACKET_TYPE_BARRIER_AND << HSA_PACKET_HEADER_TYPE;
|
||||
const aql_packet_header_t aql_header_barrier =
|
||||
1ul << HSA_PACKET_HEADER_BARRIER;
|
||||
const aql_packet_header_t aql_header_release =
|
||||
HSA_FENCE_SCOPE_SYSTEM << HSA_PACKET_HEADER_SCRELEASE_FENCE_SCOPE;
|
||||
aql_barrier->header |= aql_header_type;
|
||||
aql_barrier->header |= aql_header_barrier;
|
||||
aql_barrier->header |= aql_header_release;
|
||||
aql_barrier->completion_signal = aql_packet->completion_signal;
|
||||
return data + sizeof(hsa_barrier_and_packet_t);
|
||||
}
|
||||
|
||||
void * legacyPm4(const packet_t* aql_packet, void *data) {
|
||||
constexpr uint32_t major_version = 8;
|
||||
constexpr uint32_t slot_size_b = 0x40;
|
||||
constexpr uint32_t ib_jump_size_dw = 4;
|
||||
constexpr uint32_t slot_size_dw = uint32_t(slot_size_b / sizeof(uint32_t));
|
||||
|
||||
const amd_aql_pm4_ib_packet_t* aql_pm4_ib =
|
||||
reinterpret_cast<const amd_aql_pm4_ib_packet_t*>(aql_packet);
|
||||
uint32_t * slot_data = (uint32_t*)data;
|
||||
// Construct a set of PM4 to fit inside the AQL packet slot.
|
||||
uint32_t slot_dw_idx = 0;
|
||||
|
||||
// Construct a no-op command to pad the queue slot.
|
||||
constexpr uint32_t rel_mem_size_dw = 7;
|
||||
constexpr uint32_t nop_pad_size_dw = slot_size_dw - (ib_jump_size_dw + rel_mem_size_dw);
|
||||
|
||||
uint32_t* nop_pad = &slot_data[slot_dw_idx];
|
||||
slot_dw_idx += nop_pad_size_dw;
|
||||
|
||||
nop_pad[0] = PM4_HDR(PM4_HDR_IT_OPCODE_NOP, nop_pad_size_dw, major_version);
|
||||
|
||||
for (int i = 1; i < nop_pad_size_dw; ++i) {
|
||||
nop_pad[i] = 0;
|
||||
}
|
||||
|
||||
// Copy in command to execute the IB.
|
||||
assert(slot_dw_idx + ib_jump_size_dw <= slot_size_dw && "PM4 exceeded queue slot size");
|
||||
uint32_t* ib_jump = &slot_data[slot_dw_idx];
|
||||
slot_dw_idx += ib_jump_size_dw;
|
||||
|
||||
memcpy(ib_jump, aql_pm4_ib->pm4_ib_command, sizeof(aql_pm4_ib->pm4_ib_command));
|
||||
|
||||
// Construct a command to advance the read index and invalidate the packet
|
||||
// header. This must be the last command since this releases the queue slot
|
||||
// for writing.
|
||||
assert(slot_dw_idx + rel_mem_size_dw <= slot_size_dw && "PM4 exceeded queue slot size");
|
||||
uint32_t* rel_mem = &slot_data[slot_dw_idx];
|
||||
|
||||
rel_mem[0] =
|
||||
PM4_HDR(PM4_HDR_IT_OPCODE_RELEASE_MEM, rel_mem_size_dw, major_version);
|
||||
rel_mem[1] = PM4_RELEASE_MEM_DW1_EVENT_INDEX(PM4_RELEASE_MEM_EVENT_INDEX_AQL);
|
||||
rel_mem[2] = 0;
|
||||
rel_mem[3] = 0;
|
||||
rel_mem[4] = 0;
|
||||
rel_mem[5] = 0;
|
||||
rel_mem[6] = 0;
|
||||
|
||||
return data + slot_size_b;
|
||||
}
|
||||
|
||||
void populateAql(uint32_t* ib_packet, packet_t* aql_packet) {
|
||||
void populateAql(const uint32_t* ib_packet, packet_t* aql_packet) {
|
||||
// Populate relevant fields of Aql pkt
|
||||
// Size of IB pkt is four DWords
|
||||
// Header and completion sinal are not set
|
||||
@@ -105,20 +24,25 @@ void populateAql(uint32_t* ib_packet, packet_t* aql_packet) {
|
||||
aql_pm4_ib->reserved[i] = 0;
|
||||
}
|
||||
|
||||
uint32_t* words = (uint32_t*)aql_packet;
|
||||
#if !defined(NDEBUG)
|
||||
const uint32_t* dwords = (uint32_t*)aql_packet;
|
||||
const uint32_t dword_count = sizeof(*aql_packet) / sizeof(uint32_t);
|
||||
std::ostringstream oss;
|
||||
oss << "AQL 'IB' size(" << dword_count << ")";
|
||||
std::clog << std::setw(40) << std::left << "AQL 'IB' size(16)"
|
||||
<< ":";
|
||||
for (int idx = 0; idx < 16; idx++) {
|
||||
std::clog << " " << std::hex << std::setw(8) << std::setfill('0') << words[idx];
|
||||
for (int idx = 0; idx < dword_count; idx++) {
|
||||
std::clog << " " << std::hex << std::setw(8) << std::setfill('0') << dwords[idx];
|
||||
}
|
||||
std::clog << std::setfill(' ') << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
void populateAql(void* cmd_buffer, uint32_t cmd_size,
|
||||
pm4_profile::CommandWriter* cmd_writer, packet_t* aql_packet) {
|
||||
void populateAql(const void* cmd_buffer, uint32_t cmd_size, pm4_profile::CommandWriter* cmd_writer,
|
||||
packet_t* aql_packet) {
|
||||
pm4_profile::DefaultCmdBuf ib_buffer;
|
||||
cmd_writer->BuildIndirectBufferCmd(&ib_buffer, cmd_buffer, (size_t)cmd_size);
|
||||
uint32_t* ib_packet = (uint32_t*)ib_buffer.Base();
|
||||
populateAql(ib_packet, aql_packet);
|
||||
}
|
||||
populateAql((const uint32_t*)ib_buffer.Base(), aql_packet);
|
||||
}
|
||||
|
||||
} // aql_profile
|
||||
|
||||
@@ -4,11 +4,6 @@
|
||||
set ( CmdWriterSrcs gfx8_cmdwriter.cpp )
|
||||
set ( CmdWriterSrcs ${CmdWriterSrcs} gfx9_cmdwriter.cpp )
|
||||
|
||||
#
|
||||
# Header files include path(s).
|
||||
#
|
||||
include_directories ( $ENV{ROCR_INC_DIR} )
|
||||
|
||||
#
|
||||
# Build Cmdwriter as a Static Library object
|
||||
#
|
||||
|
||||
+1
-18
@@ -5,9 +5,8 @@
|
||||
#define _CMDWRITER_H_
|
||||
|
||||
#include <vector>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace pm4_profile {
|
||||
|
||||
@@ -471,28 +470,12 @@ class CommandWriter {
|
||||
uint32_t& IndexBuffer(CmdBuf* cmdbuf, uint32_t index) { return (*cmdbuf)[index]; }
|
||||
};
|
||||
|
||||
/// @brief Returns the Rounded value per input rounding factor
|
||||
inline uint32_t RoundUp(uint32_t u, uint32_t r) { return ((u + (r - 1)) & ~(r - 1)); }
|
||||
|
||||
/// @brief Returns the lower 32-bits of a value
|
||||
inline uint32_t Low32(uint64_t u) { return (u & 0xFFFFFFFFUL); }
|
||||
|
||||
/// @brief Returns the upper 32-bits of a value
|
||||
inline uint32_t High32(uint64_t u) { return (u >> 32); }
|
||||
|
||||
/// @brief Returns the lower 32-bits of an address
|
||||
inline uint32_t Ptr48Low32(const void* p) {
|
||||
uintptr_t ptr = reinterpret_cast<uintptr_t>(p);
|
||||
assert((ptr & 0xFFFFFFFFFF00ULL) == ptr);
|
||||
return (uint32_t)((ptr & 0xFFFFFFFFFFULL) >> 8);
|
||||
}
|
||||
|
||||
/// @brief Returns the upper 8-bits of an address
|
||||
inline uint8_t Ptr48High8(const void* p) {
|
||||
uintptr_t ptr = reinterpret_cast<uintptr_t>(p);
|
||||
return (uint8_t)((ptr & 0xFF0000000000ULL) >> 40);
|
||||
}
|
||||
|
||||
/// @brief Returns the lower 32-bits of an address
|
||||
inline uint32_t PtrLow32(const void* p) {
|
||||
return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(p));
|
||||
|
||||
+20
-23
@@ -1,7 +1,8 @@
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "gfx8_cmdwriter.h"
|
||||
#include "gfxip/gfx8/gfx8_utils.h"
|
||||
@@ -15,10 +16,9 @@
|
||||
#define RELEASE_MEM_CACHE_POLICY_STREAM 1
|
||||
#define RELEASE_MEM_CACHE_POLICY_BYPASS 2
|
||||
|
||||
template <class T>
|
||||
static void PrintPm4Packet(const T& command, const char* name) {
|
||||
#if ! defined(NDEBUG)
|
||||
uint32_t * cmd = (uint32_t*)&command;
|
||||
template <class T> static void PrintPm4Packet(const T& command, const char* name) {
|
||||
#if !defined(NDEBUG)
|
||||
uint32_t* cmd = (uint32_t*)&command;
|
||||
uint32_t size = sizeof(command) / sizeof(uint32_t);
|
||||
std::ostringstream oss;
|
||||
oss << "'" << name << "' size(" << std::dec << size << ")";
|
||||
@@ -30,8 +30,8 @@ static void PrintPm4Packet(const T& command, const char* name) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#define APPEND_COMMAND_WRAPPER(cmdbuf, command) \
|
||||
PrintPm4Packet(command, __FUNCTION__); \
|
||||
#define APPEND_COMMAND_WRAPPER(cmdbuf, command) \
|
||||
PrintPm4Packet(command, __FUNCTION__); \
|
||||
AppendCommand(cmdbuf, command);
|
||||
|
||||
namespace pm4_profile {
|
||||
@@ -164,7 +164,7 @@ Gfx8CmdWriter::Gfx8CmdWriter(bool atc_support, bool pcie_atomic_support) {
|
||||
}
|
||||
|
||||
void Gfx8CmdWriter::BuildWaitRegMemCommand(CmdBuf* cmdbuf, bool mem_space, uint64_t wait_addr,
|
||||
bool func_eq, uint32_t mask_val, uint32_t wait_val) {
|
||||
bool func_eq, uint32_t mask_val, uint32_t wait_val) {
|
||||
gfx8::WaitRegMemTemplate wait_cmd = wait_reg_mem_template_;
|
||||
|
||||
// Apply the space to which addr belongs
|
||||
@@ -212,7 +212,7 @@ void Gfx8CmdWriter::BuildUpdateHostAddress(CmdBuf* cmdbuf, uint64_t* addr, int64
|
||||
}
|
||||
|
||||
void Gfx8CmdWriter::BuildIndirectBufferCmd(CmdBuf* cmdbuf, const void* cmd_addr,
|
||||
std::size_t cmd_size) {
|
||||
std::size_t cmd_size) {
|
||||
gfx8::LaunchTemplate launch = launch_template_;
|
||||
|
||||
launch.indirect_buffer.ibBaseLo = PtrLow32(cmd_addr);
|
||||
@@ -223,7 +223,7 @@ void Gfx8CmdWriter::BuildIndirectBufferCmd(CmdBuf* cmdbuf, const void* cmd_addr,
|
||||
}
|
||||
|
||||
void Gfx8CmdWriter::BuildBOPNotifyCmd(CmdBuf* cmdbuf, const void* write_addr, uint32_t write_val,
|
||||
bool interrupt) {
|
||||
bool interrupt) {
|
||||
// Initialize the command including its header
|
||||
gfx8::EndofKernelNotifyTemplate eopCmd;
|
||||
memset(&eopCmd, 0, sizeof(eopCmd));
|
||||
@@ -273,7 +273,7 @@ void Gfx8CmdWriter::BuildBarrierFenceCommands(CmdBuf* cmdbuf) {
|
||||
#define PM4_PACKET3_CMD_SHIFT 8
|
||||
#define PM4_PACKET3_COUNT_SHIFT 16
|
||||
|
||||
#define PACKET3(cmd, count) \
|
||||
#define PACKET3(cmd, count) \
|
||||
(PM4_PACKET3 | (((count)-1) << PM4_PACKET3_COUNT_SHIFT) | ((cmd) << PM4_PACKET3_CMD_SHIFT))
|
||||
|
||||
// Structure to store the event PM4 packet
|
||||
@@ -282,7 +282,6 @@ typedef struct WriteRegPacket_ { uint32_t item[3]; } WriteRegPacket;
|
||||
typedef struct WriteEventPacket_ { uint32_t item[7]; } WriteEventPacket;
|
||||
|
||||
void Gfx8CmdWriter::BuildWriteEventPacket(CmdBuf* cmdbuf, uint32_t event) {
|
||||
|
||||
PM4CMDEVENTWRITE cp_event_initiator;
|
||||
cp_event_initiator.ordinal1 = PACKET3(IT_EVENT_WRITE, 1);
|
||||
cp_event_initiator.ordinal2 = 0;
|
||||
@@ -346,8 +345,8 @@ void Gfx8CmdWriter::BuildWriteShRegPacket(CmdBuf* cmdbuf, uint32_t addr, uint32_
|
||||
}
|
||||
|
||||
void Gfx8CmdWriter::BuildCopyDataPacket(CmdBuf* cmdbuf, uint32_t src_sel, uint32_t src_addr_lo,
|
||||
uint32_t src_addr_hi, uint32_t* dst_addr, uint32_t size,
|
||||
bool wait) {
|
||||
uint32_t src_addr_hi, uint32_t* dst_addr, uint32_t size,
|
||||
bool wait) {
|
||||
PM4CMDCOPYDATA cmd_data;
|
||||
memset(&cmd_data, 0, sizeof(PM4CMDCOPYDATA));
|
||||
|
||||
@@ -495,9 +494,8 @@ void Gfx8CmdWriter::WriteUserData(uint32_t* dst_addr, uint32_t count, const void
|
||||
}
|
||||
|
||||
|
||||
void Gfx8CmdWriter::BuildAtomicPacket(CmdBuf* cmdbuf, AtomicType atomic_op,
|
||||
volatile uint32_t* addr, uint32_t value,
|
||||
uint32_t compare) {
|
||||
void Gfx8CmdWriter::BuildAtomicPacket(CmdBuf* cmdbuf, AtomicType atomic_op, volatile uint32_t* addr,
|
||||
uint32_t value, uint32_t compare) {
|
||||
gfx8::AtomicTemplate atomic = atomic_template_;
|
||||
|
||||
// make sure the destination adddress is aligned
|
||||
@@ -554,8 +552,7 @@ void Gfx8CmdWriter::BuildAtomicPacket(CmdBuf* cmdbuf, AtomicType atomic_op,
|
||||
}
|
||||
|
||||
void Gfx8CmdWriter::BuildAtomicPacket64(CmdBuf* cmdbuf, AtomicType atomic_op,
|
||||
volatile uint64_t* addr, uint64_t value,
|
||||
uint64_t compare) {
|
||||
volatile uint64_t* addr, uint64_t value, uint64_t compare) {
|
||||
AtomicTemplate atomic = atomic_template_;
|
||||
|
||||
// make sure the destination adddress is aligned
|
||||
@@ -640,7 +637,7 @@ void Gfx8CmdWriter::BuildConditionalExecute(CmdBuf* cmdbuf, uint32_t* signal, ui
|
||||
}
|
||||
|
||||
void Gfx8CmdWriter::BuildWriteDataCommand(CmdBuf* cmdbuf, uint32_t* write_addr,
|
||||
uint32_t write_value) {
|
||||
uint32_t write_value) {
|
||||
// Copy the initialize command packet
|
||||
gfx8::WriteDataTemplate command = write_data_template_;
|
||||
|
||||
@@ -656,7 +653,7 @@ void Gfx8CmdWriter::BuildWriteDataCommand(CmdBuf* cmdbuf, uint32_t* write_addr,
|
||||
}
|
||||
|
||||
void Gfx8CmdWriter::BuildWriteData64Command(CmdBuf* cmdbuf, uint64_t* write_addr,
|
||||
uint64_t write_value) {
|
||||
uint64_t write_value) {
|
||||
// Copy the initialize command packet
|
||||
gfx8::WriteData64Template command = write_data64_template_;
|
||||
|
||||
@@ -672,7 +669,7 @@ void Gfx8CmdWriter::BuildWriteData64Command(CmdBuf* cmdbuf, uint64_t* write_addr
|
||||
}
|
||||
|
||||
void Gfx8CmdWriter::BuildFlushCacheCmd(CmdBuf* cmdbuf, FlushCacheOptions* options,
|
||||
uint32_t* writeAddr, uint32_t writeVal) {
|
||||
uint32_t* writeAddr, uint32_t writeVal) {
|
||||
PM4CMDACQUIREMEM flushCmd;
|
||||
memset(&flushCmd, 0, sizeof(flushCmd));
|
||||
|
||||
@@ -720,7 +717,7 @@ void Gfx8CmdWriter::BuildFlushCacheCmd(CmdBuf* cmdbuf, FlushCacheOptions* option
|
||||
}
|
||||
|
||||
void Gfx8CmdWriter::BuildDmaDataPacket(CmdBuf* cmdbuf, uint32_t* srcAddr, uint32_t* dstAddr,
|
||||
uint32_t copySize, bool waitForConfirm) {
|
||||
uint32_t copySize, bool waitForConfirm) {
|
||||
PM4CMDDMADATA cmdDmaData;
|
||||
memset(&cmdDmaData, 0, sizeof(PM4CMDDMADATA));
|
||||
cmdDmaData.header.u32All =
|
||||
|
||||
+7
-7
@@ -1,14 +1,14 @@
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "gfx9_cmdwriter.h"
|
||||
|
||||
template <class T>
|
||||
static void PrintPm4Packet(const T& command, const char* name) {
|
||||
#if ! defined(NDEBUG)
|
||||
uint32_t * cmd = (uint32_t*)&command;
|
||||
template <class T> static void PrintPm4Packet(const T& command, const char* name) {
|
||||
#if !defined(NDEBUG)
|
||||
uint32_t* cmd = (uint32_t*)&command;
|
||||
uint32_t size = sizeof(command) / sizeof(uint32_t);
|
||||
std::ostringstream oss;
|
||||
oss << "'" << name << "' size(" << std::dec << size << ")";
|
||||
@@ -20,8 +20,8 @@ static void PrintPm4Packet(const T& command, const char* name) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#define APPEND_COMMAND_WRAPPER(cmdbuf, command) \
|
||||
PrintPm4Packet(command, __FUNCTION__); \
|
||||
#define APPEND_COMMAND_WRAPPER(cmdbuf, command) \
|
||||
PrintPm4Packet(command, __FUNCTION__); \
|
||||
AppendCommand(cmdbuf, command);
|
||||
|
||||
namespace pm4_profile {
|
||||
|
||||
+4
-11
@@ -1,22 +1,15 @@
|
||||
#
|
||||
# Source files for Rocr PerfCntr
|
||||
#
|
||||
set ( LIB_SRC var_data.cpp )
|
||||
set ( LIB_SRC ${LIB_SRC} info_set.cpp )
|
||||
set ( LIB_SRC ${LIB_SRC} parameter_set.cpp )
|
||||
set ( LIB_SRC ${LIB_SRC} gpu_counter.cpp )
|
||||
set ( LIB_SRC ${LIB_SRC} gpu_countergroup.cpp )
|
||||
set ( LIB_SRC ${LIB_SRC} vi_blockinfo.cpp )
|
||||
set ( LIB_SRC ${LIB_SRC} vi_pmu.cpp )
|
||||
set ( LIB_SRC ${LIB_SRC} ai_blockinfo.cpp )
|
||||
set ( LIB_SRC ${LIB_SRC} ai_pmu.cpp )
|
||||
set ( LIB_SRC gfx8_perf_counter.cpp )
|
||||
set ( LIB_SRC ${LIB_SRC} gfx9_perf_counter.cpp )
|
||||
set ( LIB_SRC ${LIB_SRC} gfx8_block_info.cpp )
|
||||
set ( LIB_SRC ${LIB_SRC} gfx9_block_info.cpp )
|
||||
|
||||
#
|
||||
# Header files include path(s).
|
||||
#
|
||||
include_directories ( $ENV{ROCR_INC_DIR} )
|
||||
include_directories ( ${PROJ_DIR}/commandwriter )
|
||||
include_directories ( ${CORE_UTIL_DIR} )
|
||||
|
||||
#
|
||||
# Build PerfCntr as a Static Library object
|
||||
|
||||
+4
-2
@@ -1,4 +1,4 @@
|
||||
#include "vi_blockinfo.h"
|
||||
#include "gfx8_block_info.h"
|
||||
#include "gfxip/gfx8/si_ci_vi_merged_offset.h"
|
||||
|
||||
namespace pm4_profile {
|
||||
@@ -6,7 +6,7 @@ namespace pm4_profile {
|
||||
* Table containing CounterGroups which represent VI hardware blocks
|
||||
* as defined by \ref GpuBlockInfo structure
|
||||
*/
|
||||
GpuBlockInfo ViPmuHwBlocks[] = {
|
||||
GpuBlockInfo Gfx8HwBlocks[] = {
|
||||
// Counter block CB
|
||||
{"VI_CB0", kHsaViCounterBlockIdCb0, VI_MAX_NUM_SHADER_ENGINES, 2, VI_NUM_CB,
|
||||
CntlMethodBySeAndInstance, 395, VI_COUNTER_NUM_PER_CB, 0, 0, true, 0, 0, false, 0, 0},
|
||||
@@ -259,6 +259,8 @@ GpuBlockInfo ViPmuHwBlocks[] = {
|
||||
{"", kHsaViCounterBlockIdBlocksLast, 0, 0, 0, CntlMethodNone, 0, 0, 0, 0, false, 0, 0, false, 0,
|
||||
0}};
|
||||
|
||||
extern const uint32_t Gfx8HwBlockCount = sizeof(Gfx8HwBlocks) / sizeof(GpuBlockInfo);
|
||||
|
||||
/*
|
||||
* The following tables contain register addresses of the SQ counter registers
|
||||
*/
|
||||
+2
-5
@@ -1,10 +1,7 @@
|
||||
#ifndef _VI_BLOCKINFO_H_
|
||||
#define _VI_BLOCKINFO_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "rocr_profiler.h"
|
||||
#include "gpu_enum.h"
|
||||
#include "gpu_blockinfo.h"
|
||||
#include "gpu_block_info.h"
|
||||
|
||||
namespace pm4_profile {
|
||||
|
||||
@@ -187,7 +184,7 @@ typedef enum HsaViCounterBlockId {
|
||||
kHsaViCounterBlockIdBlocksLast = kHsaViCounterBlockIdHwInfo
|
||||
} HsaViCounterBlockId;
|
||||
|
||||
extern GpuBlockInfo ViPmuHwBlocks[];
|
||||
extern GpuBlockInfo Gfx8HwBlocks[];
|
||||
extern GpuCounterRegInfo ViSqCounterRegAddr[];
|
||||
extern GpuCounterRegInfo ViCbCounterRegAddr[];
|
||||
extern GpuCounterRegInfo ViDrmdmaCounterRegAddr[];
|
||||
+92
-334
@@ -1,22 +1,21 @@
|
||||
#include <string.h>
|
||||
#include <iomanip>
|
||||
|
||||
#include "os.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include "gfxip/gfx8/si_ci_vi_merged_typedef.h"
|
||||
#include "gfxip/gfx8/si_ci_vi_merged_offset.h"
|
||||
#include "gfxip/gfx8/si_ci_vi_merged_enum.h"
|
||||
#include "gfxip/gfx8/si_pm4defs.h"
|
||||
#include "cmdwriter.h"
|
||||
|
||||
#include "vi_pmu.h"
|
||||
#include "gpu_countergroup.h"
|
||||
#include "vi_blockinfo.h"
|
||||
#include "gpu_enum.h"
|
||||
#include "gfx8_perf_counter.h"
|
||||
#include "gfx8_block_info.h"
|
||||
#include "cmdwriter.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace pm4_profile;
|
||||
|
||||
// A flag to indicate the current packet is for copy register value
|
||||
#define MAX_REG_NUM 100
|
||||
#define COPY_DATA_FLAG 0xFFFFFFFF
|
||||
|
||||
namespace pm4_profile {
|
||||
|
||||
static char errorString[][64] = {{"No error"},
|
||||
@@ -27,20 +26,14 @@ static char errorString[][64] = {{"No error"},
|
||||
{"countegroup error state"},
|
||||
{"countegroup is not completed"}};
|
||||
|
||||
ViPmu::ViPmu() {
|
||||
Gfx8PerfCounter::Gfx8PerfCounter() {
|
||||
// Initialize the number of shader engines
|
||||
num_se_ = 4;
|
||||
Init();
|
||||
}
|
||||
|
||||
void ViPmu::Init() {
|
||||
void Gfx8PerfCounter::Init() {
|
||||
error_code_ = 0;
|
||||
info_set_ = new InfoSet();
|
||||
parameter_set_ = new ParameterSet();
|
||||
|
||||
// Initialize pointer to stored counter block list to NULL
|
||||
blk_list_ = NULL;
|
||||
initCounterBlock();
|
||||
|
||||
// Initialize the value to use in resetting GRBM
|
||||
regGRBM_GFX_INDEX grbm_gfx_index;
|
||||
@@ -49,106 +42,38 @@ void ViPmu::Init() {
|
||||
grbm_gfx_index.bitfields.SE_BROADCAST_WRITES = 1;
|
||||
grbm_gfx_index.bitfields.SH_BROADCAST_WRITES = 1;
|
||||
reset_grbm_ = grbm_gfx_index.u32All;
|
||||
|
||||
// Update state of Perf Mgmt Unit
|
||||
profiler_state_ = ROCR_PMU_STATE_IDLE;
|
||||
}
|
||||
|
||||
ViPmu::~ViPmu() {
|
||||
// Remove all counter blocks
|
||||
RemoveCounterBlocks();
|
||||
blk_map_.clear();
|
||||
delete parameter_set_;
|
||||
delete info_set_;
|
||||
|
||||
if (blk_list_) {
|
||||
free(blk_list_);
|
||||
blk_list_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Initializes the handle of buffer used to collect PMC data
|
||||
// @param cmdBufSz Size in terms of bytes
|
||||
bool ViPmu::setPmcDataBuff(uint8_t* pmcBuffer, uint32_t pmcBuffSz) {
|
||||
// Update counter data buffer addr and size params
|
||||
pmcDataSz_ = pmcBuffSz;
|
||||
pmcData_ = (uint32_t*)pmcBuffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// The logic is quite simple and is as follows
|
||||
//
|
||||
// Issue CsPartialFlush
|
||||
// Issue Cmd to stop Perf Counters
|
||||
// Issue Cmd to Disable & Reset Perf Counters
|
||||
//
|
||||
void ViPmu::ResetCounterBlocks(pm4_profile::DefaultCmdBuf* cmdBuff,
|
||||
pm4_profile::CommandWriter* cmdWriter) {
|
||||
// Waits until all outstanding commands have completed
|
||||
// by issing CS Partial Flush command
|
||||
cmdWriter->BuildWriteWaitIdlePacket(cmdBuff);
|
||||
|
||||
// Program CP Perfmon Cntrl Rgstr to disable and reset counters
|
||||
regCP_PERFMON_CNTL cp_perfmon_cntl;
|
||||
cp_perfmon_cntl.u32All = 0;
|
||||
cp_perfmon_cntl.bits.PERFMON_STATE = 0;
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, mmCP_PERFMON_CNTL__CI__VI, cp_perfmon_cntl.u32All);
|
||||
}
|
||||
|
||||
bool ViPmu::begin(pm4_profile::DefaultCmdBuf* cmdBuff, pm4_profile::CommandWriter* cmdWriter,
|
||||
bool reset_counter) {
|
||||
if (profiler_state_ != ROCR_PMU_STATE_IDLE) {
|
||||
error_code_ = kHsaPmuErrorCodeErrorState;
|
||||
return false;
|
||||
}
|
||||
|
||||
void Gfx8PerfCounter::begin(DefaultCmdBuf* cmdBuff, CommandWriter* cmdWriter,
|
||||
const CountersMap& countersMap) {
|
||||
// Reset Grbm to its default state - broadcast
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, mmGRBM_GFX_INDEX__CI__VI, reset_grbm_);
|
||||
|
||||
// Program CP Perfmon Cntrl Rgstr to disable and reset counters
|
||||
regCP_PERFMON_CNTL cp_perfmon_cntl;
|
||||
cp_perfmon_cntl.u32All = 0;
|
||||
cp_perfmon_cntl.bits.PERFMON_STATE = 0;
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, mmCP_PERFMON_CNTL__CI__VI, cp_perfmon_cntl.u32All);
|
||||
|
||||
// Collect all the program counter blocks
|
||||
uint32_t reg_val[MAX_REG_NUM], reg_addr[MAX_REG_NUM], reg_num;
|
||||
|
||||
// Retrieve the list of blocks whose perf counters have been enabled
|
||||
uint32_t blk_cnt = 0;
|
||||
CounterBlock** blk_list = getAllCounterBlocks(blk_cnt);
|
||||
|
||||
// Iterate through the list of blocks to generate Pm4 commands to
|
||||
// program corresponding perf counters of each block
|
||||
for (uint32_t blkIdx = 0; blkIdx < blk_cnt; blkIdx++) {
|
||||
// Retrieve the list of perf counters and their count
|
||||
uint32_t counter_num;
|
||||
Counter** cntr_list;
|
||||
cntr_list = blk_list[blkIdx]->getEnabledCounters(counter_num);
|
||||
if (counter_num == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Retrieve the block Id of perf counters
|
||||
void* p_data;
|
||||
uint32_t block_id;
|
||||
uint32_t data_size;
|
||||
blk_list[blkIdx]->getInfo(GPU_BLK_INFO_ID, data_size, (void**)&p_data);
|
||||
block_id = *(static_cast<uint32_t*>(p_data));
|
||||
for (CountersMap::const_iterator block_it = countersMap.begin(); block_it != countersMap.end();
|
||||
++block_it) {
|
||||
const uint32_t block_id = block_it->first;
|
||||
const CountersVec& counters = block_it->second;
|
||||
const uint32_t counter_count = counters.size();
|
||||
|
||||
// Iterate through each enabled perf counter and building
|
||||
// corresponding Pm4 commands to program the various control
|
||||
// registers involved
|
||||
for (uint32_t cntrIdx = 0; cntrIdx < counter_num; cntrIdx++) {
|
||||
|
||||
for (uint32_t ind = 0; ind < counter_count; ++ind) {
|
||||
const uint32_t counter_id = counters[ind];
|
||||
|
||||
// Build the list of control registers to program which
|
||||
// varies per perf counter block
|
||||
reg_num = BuildCounterSelRegister(cntrIdx, reg_addr, reg_val, block_id, cntr_list[cntrIdx]);
|
||||
uint32_t reg_addr[MAX_REG_NUM], reg_val[MAX_REG_NUM];
|
||||
const uint32_t reg_num =
|
||||
BuildCounterSelRegister(ind, reg_addr, reg_val, block_id, counter_id);
|
||||
|
||||
// Build the list of Pm4 commands that support control
|
||||
// register programming
|
||||
for (uint32_t regIdx = 0; regIdx < reg_num; regIdx++) {
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, reg_addr[regIdx], reg_val[regIdx]);
|
||||
for (uint32_t n = 0; n < reg_num; ++n) {
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, reg_addr[n], reg_val[n]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -163,96 +88,55 @@ bool ViPmu::begin(pm4_profile::DefaultCmdBuf* cmdBuff, pm4_profile::CommandWrite
|
||||
cmdWriter->BuildWriteShRegPacket(cmdBuff, mmCOMPUTE_PERFCOUNT_ENABLE__CI__VI,
|
||||
cp_perfcount_enable.u32All);
|
||||
|
||||
// Start the counter list
|
||||
// Reset the counter list
|
||||
regCP_PERFMON_CNTL cp_perfmon_cntl;
|
||||
cp_perfmon_cntl.u32All = 0;
|
||||
cp_perfmon_cntl.bits.PERFMON_STATE = 0;
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, mmCP_PERFMON_CNTL__CI__VI, cp_perfmon_cntl.u32All);
|
||||
|
||||
// Start the counter list
|
||||
cp_perfmon_cntl.bits.PERFMON_STATE = 1;
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, mmCP_PERFMON_CNTL__CI__VI, cp_perfmon_cntl.u32All);
|
||||
|
||||
// Issue barrier command to apply the commands to configure perfcounters
|
||||
cmdWriter->BuildWriteWaitIdlePacket(cmdBuff);
|
||||
|
||||
profiler_state_ = ROCR_PMU_STATE_START;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ViPmu::end(pm4_profile::DefaultCmdBuf* cmdBuff, pm4_profile::CommandWriter* cmdWriter) {
|
||||
if (profiler_state_ != ROCR_PMU_STATE_START) {
|
||||
error_code_ = kHsaPmuErrorCodeErrorState;
|
||||
return false;
|
||||
}
|
||||
|
||||
void* p_data;
|
||||
regGRBM_GFX_INDEX grbm_gfx_index;
|
||||
|
||||
// Issue CsPartialFlush command to wait for dispatch to complete
|
||||
uint32_t Gfx8PerfCounter::end(DefaultCmdBuf* cmdBuff, CommandWriter* cmdWriter,
|
||||
const CountersMap& countersMap, void* dataBuff) {
|
||||
// Issue barrier command to wait for dispatch to complete
|
||||
cmdWriter->BuildWriteWaitIdlePacket(cmdBuff);
|
||||
|
||||
// Build PM4 packet for starting counters
|
||||
// Build PM4 packet to stop and freeze counters
|
||||
regCP_PERFMON_CNTL cp_perfmon_cntl;
|
||||
cp_perfmon_cntl.u32All = 0;
|
||||
cp_perfmon_cntl.bits.PERFMON_STATE = 2;
|
||||
cp_perfmon_cntl.bits.PERFMON_SAMPLE_ENABLE = 1;
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, mmCP_PERFMON_CNTL__CI__VI, cp_perfmon_cntl.u32All);
|
||||
|
||||
// Collect all the program counter blocks
|
||||
uint32_t i, j, k, reg_addr[MAX_REG_NUM], reg_val[MAX_REG_NUM], reg_num, data_size;
|
||||
|
||||
uint32_t blk_cnt = 0;
|
||||
CounterBlock** blk_list = getAllCounterBlocks(blk_cnt);
|
||||
|
||||
uint32_t counter_num;
|
||||
Counter** cntr_list;
|
||||
uint32_t total_counter_num = 0;
|
||||
for (i = 0; i < blk_cnt; i++) {
|
||||
// Retrieve all enabled cntr_list in each counter block
|
||||
cntr_list = blk_list[i]->getEnabledCounters(counter_num);
|
||||
if (!blk_list[i]->getInfo(GPU_BLK_INFO_CONTROL_METHOD, data_size, &p_data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CntlMethod method;
|
||||
method = static_cast<CntlMethod>(*(static_cast<uint32_t*>(p_data)));
|
||||
|
||||
// Need to read counter values from each shader engine
|
||||
if (method == CntlMethodBySe || method == CntlMethodBySeAndInstance) {
|
||||
counter_num = counter_num * num_se_;
|
||||
}
|
||||
|
||||
total_counter_num += counter_num;
|
||||
}
|
||||
|
||||
size_t cntrSize = sizeof(int32_t) * 2 * total_counter_num;
|
||||
if (cntrSize > pmcDataSz_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reset Grbm to its default state - broadcast
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, mmGRBM_GFX_INDEX__CI__VI, reset_grbm_);
|
||||
|
||||
// Create PM4 packet to read counter values
|
||||
total_counter_num = 0;
|
||||
for (i = 0; i < blk_cnt; i++) {
|
||||
// Retrieve all enabled cntr_list in each counter block
|
||||
cntr_list = blk_list[i]->getEnabledCounters(counter_num);
|
||||
if (counter_num > 0) {
|
||||
uint32_t block_id;
|
||||
uint32_t data_size;
|
||||
if (!blk_list[i]->getInfo(GPU_BLK_INFO_ID, data_size, (void**)&p_data)) {
|
||||
return false;
|
||||
}
|
||||
block_id = *(static_cast<uint32_t*>(p_data));
|
||||
// Iterate through the list of blocks to create PM4 packets to read counter values
|
||||
uint32_t total_counter_num = 0;
|
||||
for (CountersMap::const_iterator block_it = countersMap.begin(); block_it != countersMap.end();
|
||||
++block_it) {
|
||||
const uint32_t block_id = block_it->first;
|
||||
const uint32_t counter_count = block_it->second.size();
|
||||
|
||||
for (j = 0; j < counter_num; j++) {
|
||||
// retrieve the registers to be set
|
||||
reg_num = BuildCounterReadRegisters(j, block_id, reg_addr, reg_val);
|
||||
for (k = 0; k < reg_num; k++) {
|
||||
if (reg_val[k] == COPY_DATA_FLAG) {
|
||||
cmdWriter->BuildCopyDataPacket(cmdBuff, COPY_DATA_SEL_REG, reg_addr[k], 0,
|
||||
pmcData_ + total_counter_num, COPY_DATA_SEL_COUNT_1DW,
|
||||
false);
|
||||
total_counter_num++;
|
||||
} else {
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, reg_addr[k], reg_val[k]);
|
||||
}
|
||||
for (uint32_t ind = 0; ind < counter_count; ++ind) {
|
||||
// retrieve the registers to be set
|
||||
uint32_t reg_addr[MAX_REG_NUM], reg_val[MAX_REG_NUM];
|
||||
const uint32_t reg_num = BuildCounterReadRegisters(ind, block_id, reg_addr, reg_val);
|
||||
|
||||
for (uint32_t n = 0; n < reg_num; n++) {
|
||||
if (reg_val[n] == COPY_DATA_FLAG) {
|
||||
cmdWriter->BuildCopyDataPacket(cmdBuff, COPY_DATA_SEL_REG, reg_addr[n], 0,
|
||||
((uint32_t*)dataBuff) + total_counter_num,
|
||||
COPY_DATA_SEL_COUNT_1DW, false);
|
||||
total_counter_num++;
|
||||
} else {
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, reg_addr[n], reg_val[n]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -261,138 +145,21 @@ bool ViPmu::end(pm4_profile::DefaultCmdBuf* cmdBuff, pm4_profile::CommandWriter*
|
||||
// Reset Grbm to its default state - broadcast
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, mmGRBM_GFX_INDEX__CI__VI, reset_grbm_);
|
||||
|
||||
profiler_state_ = ROCR_PMU_STATE_STOP;
|
||||
return true;
|
||||
return total_counter_num * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
bool ViPmu::initCounterBlock() {
|
||||
for (int i = 0; !(std::string(ViPmuHwBlocks[i].blockName).empty()); i++) {
|
||||
// Override the value of max number of shader engines
|
||||
ViPmuHwBlocks[i].maxShaderEngineCount = num_se_;
|
||||
int Gfx8PerfCounter::getLastError() { return error_code_; }
|
||||
|
||||
// Instantiate a perf counter block and its properties
|
||||
GpuCounterBlock* cntr_blk = new GpuCounterBlock();
|
||||
if (!cntr_blk) {
|
||||
blk_map_.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_BLOCK_NAME, GPU_BLOCK_NAME_SIZE,
|
||||
(void*)ViPmuHwBlocks[i].blockName);
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_ID, sizeof(uint32_t), (void*)&ViPmuHwBlocks[i].counterGroupId);
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_MAX_SHADER_ENGINE_COUNT, sizeof(uint32_t),
|
||||
(void*)&(ViPmuHwBlocks[i].maxShaderEngineCount));
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_MAX_SHADER_ARRAY_COUNT, sizeof(uint32_t),
|
||||
(void*)&(ViPmuHwBlocks[i].maxShaderArrayCount));
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_MAX_INSTANCE_COUNT, sizeof(uint32_t),
|
||||
(void*)&(ViPmuHwBlocks[i].maxInstanceCount));
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_CONTROL_METHOD, sizeof(uint32_t),
|
||||
(void*)&(ViPmuHwBlocks[i].method));
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_MAX_EVENT_ID, sizeof(uint32_t),
|
||||
(void*)&(ViPmuHwBlocks[i].maxEventId));
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_MAX_SIMULTANEOUS_COUNTERS, sizeof(uint32_t),
|
||||
(void*)&(ViPmuHwBlocks[i].maxSimultaneousCounters));
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_MAX_STREAMING_COUNTERS, sizeof(uint32_t),
|
||||
(void*)&(ViPmuHwBlocks[i].maxStreamingCounters));
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_SHARED_HW_COUNTERS, sizeof(uint32_t),
|
||||
(void*)&(ViPmuHwBlocks[i].sharedHWCounters));
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_HAS_FILTERS, sizeof(bool),
|
||||
(void*)&(ViPmuHwBlocks[i].hasFilters));
|
||||
|
||||
// TODO: Need to fill in the Threadtrace stuff here
|
||||
HsaViCounterBlockId blk_id;
|
||||
blk_id = static_cast<HsaViCounterBlockId>(ViPmuHwBlocks[i].counterGroupId);
|
||||
blk_map_.insert(ViCounterBlockMap::value_type(blk_id, cntr_blk));
|
||||
}
|
||||
|
||||
// Initiate the PMU state and error code
|
||||
error_code_ = 0;
|
||||
profiler_state_ = ROCR_PMU_STATE_IDLE;
|
||||
return true;
|
||||
}
|
||||
|
||||
int ViPmu::getLastError() { return error_code_; }
|
||||
|
||||
std::string ViPmu::getErrorString(int error) {
|
||||
if ((error >= 0) && (error < kHsaPmuErrorCodeMax)) {
|
||||
std::string Gfx8PerfCounter::getErrorString(int error) {
|
||||
if ((error >= 0) && (error < kErrorCodeMax)) {
|
||||
std::string err_string(errorString[error]);
|
||||
return err_string;
|
||||
}
|
||||
return string("Error input code!");
|
||||
}
|
||||
|
||||
bool ViPmu::getParameter(uint32_t param, uint32_t& retSize, void** ppData) {
|
||||
return parameter_set_->getParameter(param, retSize, ppData);
|
||||
}
|
||||
|
||||
bool ViPmu::setParameter(uint32_t param, uint32_t paramSize, const void* p_data) {
|
||||
return parameter_set_->setParameter(param, paramSize, p_data);
|
||||
}
|
||||
|
||||
bool ViPmu::getInfo(uint32_t info, uint32_t& retSize, void** ppData) {
|
||||
return info_set_->getInfo(info, retSize, ppData);
|
||||
}
|
||||
|
||||
pm4_profile::CounterBlock* ViPmu::getCounterBlockById(uint32_t id) {
|
||||
HsaViCounterBlockId block_id = static_cast<HsaViCounterBlockId>(id);
|
||||
|
||||
// Carrizo has only 8 instances of TA, TD, TCP Perf Blocks
|
||||
/*
|
||||
if (asic_ == HsaAmdDeviceAsicTypeCZ) {
|
||||
if ( ((id >= kHsaViCounterBlockIdTa8) && (id <= kHsaViCounterBlockIdTa15)) ||
|
||||
((id >= kHsaViCounterBlockIdTd8) && (id <= kHsaViCounterBlockIdTd15)) ||
|
||||
((id >= kHsaViCounterBlockIdTcp8) && (id <= kHsaViCounterBlockIdTcp15))) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return blk_map_[block_id];
|
||||
}
|
||||
|
||||
pm4_profile::CounterBlock** ViPmu::getAllCounterBlocks(uint32_t& num_blocks) {
|
||||
size_t block_size = blk_map_.size();
|
||||
|
||||
if (block_size <= 0) {
|
||||
error_code_ = kHsaPmuErrorCodeNoCounterBlock;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (blk_list_) {
|
||||
free(blk_list_);
|
||||
blk_list_ = NULL;
|
||||
}
|
||||
|
||||
blk_list_size_ = (uint32_t)(sizeof(GpuCounterBlock*) * block_size);
|
||||
blk_list_size_ = ((blk_list_size_ % 4096) != 0) ? 4096 : blk_list_size_;
|
||||
blk_list_ = (CounterBlock**)malloc(blk_list_size_);
|
||||
if (blk_list_ == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ViCounterBlockMap::iterator it;
|
||||
uint32_t blk_cnt = 0;
|
||||
for (it = blk_map_.begin(); it != blk_map_.end(); it++) {
|
||||
blk_list_[blk_cnt] = it->second;
|
||||
blk_cnt++;
|
||||
}
|
||||
|
||||
num_blocks = blk_cnt;
|
||||
return blk_list_;
|
||||
}
|
||||
|
||||
uint32_t ViPmu::ProgramTcpCntrs(uint32_t tcpRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
uint32_t Gfx8PerfCounter::ProgramTcpCntrs(uint32_t tcpRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
regGRBM_GFX_INDEX grbm_gfx_index;
|
||||
|
||||
grbm_gfx_index.u32All = 0;
|
||||
@@ -416,8 +183,8 @@ uint32_t ViPmu::ProgramTcpCntrs(uint32_t tcpRegIdx, uint32_t* regAddr, uint32_t*
|
||||
return regIdx;
|
||||
}
|
||||
|
||||
uint32_t ViPmu::ProgramTdCntrs(uint32_t tdRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
uint32_t Gfx8PerfCounter::ProgramTdCntrs(uint32_t tdRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
regGRBM_GFX_INDEX grbm_gfx_index;
|
||||
|
||||
grbm_gfx_index.u32All = 0;
|
||||
@@ -440,8 +207,8 @@ uint32_t ViPmu::ProgramTdCntrs(uint32_t tdRegIdx, uint32_t* regAddr, uint32_t* r
|
||||
return regIdx;
|
||||
}
|
||||
|
||||
uint32_t ViPmu::ProgramTccCntrs(uint32_t tccRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
uint32_t Gfx8PerfCounter::ProgramTccCntrs(uint32_t tccRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
regGRBM_GFX_INDEX grbm_gfx_index;
|
||||
|
||||
grbm_gfx_index.u32All = 0;
|
||||
@@ -465,8 +232,8 @@ uint32_t ViPmu::ProgramTccCntrs(uint32_t tccRegIdx, uint32_t* regAddr, uint32_t*
|
||||
return regIdx;
|
||||
}
|
||||
|
||||
uint32_t ViPmu::ProgramTcaCntrs(uint32_t tcaRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
uint32_t Gfx8PerfCounter::ProgramTcaCntrs(uint32_t tcaRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
regGRBM_GFX_INDEX grbm_gfx_index;
|
||||
|
||||
grbm_gfx_index.u32All = 0;
|
||||
@@ -489,8 +256,8 @@ uint32_t ViPmu::ProgramTcaCntrs(uint32_t tcaRegIdx, uint32_t* regAddr, uint32_t*
|
||||
return regIdx;
|
||||
}
|
||||
|
||||
uint32_t ViPmu::ProgramTaCntrs(uint32_t taRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
uint32_t Gfx8PerfCounter::ProgramTaCntrs(uint32_t taRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
regGRBM_GFX_INDEX grbm_gfx_index;
|
||||
|
||||
grbm_gfx_index.u32All = 0;
|
||||
@@ -514,8 +281,8 @@ uint32_t ViPmu::ProgramTaCntrs(uint32_t taRegIdx, uint32_t* regAddr, uint32_t* r
|
||||
return regIdx;
|
||||
}
|
||||
|
||||
uint32_t ViPmu::ProgramSQCntrs(uint32_t sqRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
uint32_t Gfx8PerfCounter::ProgramSQCntrs(uint32_t sqRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
uint32_t regIdx = 0;
|
||||
|
||||
// Program the SQ Counter Select Register
|
||||
@@ -573,22 +340,13 @@ uint32_t ViPmu::ProgramSQCntrs(uint32_t sqRegIdx, uint32_t* regAddr, uint32_t* r
|
||||
return regIdx;
|
||||
}
|
||||
|
||||
uint32_t ViPmu::BuildCounterSelRegister(uint32_t cntrIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, pm4_profile::Counter* blkCntr) {
|
||||
void* p_data;
|
||||
uint32_t data_size;
|
||||
uint32_t blkCntrIdx;
|
||||
uint32_t instance_index;
|
||||
regGRBM_GFX_INDEX grbm_gfx_index;
|
||||
|
||||
// Get the blkCntr selection value
|
||||
if (!blkCntr->getParameter(HSA_EXT_TOOLS_COUNTER_PARAMETER_EVENT_INDEX, data_size,
|
||||
(void**)&p_data)) {
|
||||
return 0;
|
||||
}
|
||||
blkCntrIdx = *(static_cast<uint32_t*>(p_data));
|
||||
|
||||
uint32_t Gfx8PerfCounter::BuildCounterSelRegister(uint32_t cntrIdx, uint32_t* regAddr,
|
||||
uint32_t* regVal, uint32_t blkId,
|
||||
uint32_t blkCntrIdx) {
|
||||
uint32_t instance_index = 0;
|
||||
regGRBM_GFX_INDEX grbm_gfx_index = {0};
|
||||
uint32_t regIdx = 0;
|
||||
|
||||
switch (blkId) {
|
||||
// Program counters belonging to SQ block
|
||||
case kHsaViCounterBlockIdSq:
|
||||
@@ -1011,8 +769,8 @@ uint32_t ViPmu::BuildCounterSelRegister(uint32_t cntrIdx, uint32_t* regAddr, uin
|
||||
return regIdx;
|
||||
}
|
||||
|
||||
uint32_t ViPmu::BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id, uint32_t* reg_addr,
|
||||
uint32_t* reg_val) {
|
||||
uint32_t Gfx8PerfCounter::BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id,
|
||||
uint32_t* reg_addr, uint32_t* reg_val) {
|
||||
uint32_t ii;
|
||||
uint32_t reg_num = 0;
|
||||
uint32_t instance_index;
|
||||
@@ -1031,6 +789,7 @@ uint32_t ViPmu::BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id,
|
||||
grbm_gfx_index.bitfields.INSTANCE_BROADCAST_WRITES = 1;
|
||||
grbm_gfx_index.bitfields.SE_INDEX = ii;
|
||||
grbm_gfx_index.bitfields.SH_BROADCAST_WRITES = 1;
|
||||
|
||||
reg_addr[reg_num] = mmGRBM_GFX_INDEX__CI__VI;
|
||||
reg_val[reg_num] = grbm_gfx_index.u32All;
|
||||
reg_num++;
|
||||
@@ -1056,6 +815,7 @@ uint32_t ViPmu::BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id,
|
||||
grbm_gfx_index.bitfields.INSTANCE_INDEX = instance_index;
|
||||
grbm_gfx_index.bitfields.SE_INDEX = ii;
|
||||
grbm_gfx_index.bitfields.SH_BROADCAST_WRITES = 1;
|
||||
|
||||
reg_addr[reg_num] = mmGRBM_GFX_INDEX__CI__VI;
|
||||
reg_val[reg_num] = grbm_gfx_index.u32All;
|
||||
reg_num++;
|
||||
@@ -1096,6 +856,7 @@ uint32_t ViPmu::BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id,
|
||||
grbm_gfx_index.bitfields.INSTANCE_INDEX = instance_index;
|
||||
grbm_gfx_index.bitfields.SE_INDEX = ii;
|
||||
grbm_gfx_index.bitfields.SH_BROADCAST_WRITES = 1;
|
||||
|
||||
reg_addr[reg_num] = mmGRBM_GFX_INDEX__CI__VI;
|
||||
reg_val[reg_num] = grbm_gfx_index.u32All;
|
||||
reg_num++;
|
||||
@@ -1147,6 +908,7 @@ uint32_t ViPmu::BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id,
|
||||
grbm_gfx_index.bitfields.INSTANCE_BROADCAST_WRITES = 1;
|
||||
grbm_gfx_index.bitfields.SE_INDEX = ii;
|
||||
grbm_gfx_index.bitfields.SH_BROADCAST_WRITES = 1;
|
||||
|
||||
reg_addr[reg_num] = mmGRBM_GFX_INDEX__CI__VI;
|
||||
reg_val[reg_num] = grbm_gfx_index.u32All;
|
||||
reg_num++;
|
||||
@@ -1168,6 +930,7 @@ uint32_t ViPmu::BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id,
|
||||
grbm_gfx_index.bitfields.INSTANCE_BROADCAST_WRITES = 1;
|
||||
grbm_gfx_index.bitfields.SE_INDEX = ii;
|
||||
grbm_gfx_index.bitfields.SH_BROADCAST_WRITES = 1;
|
||||
|
||||
reg_addr[reg_num] = mmGRBM_GFX_INDEX__CI__VI;
|
||||
reg_val[reg_num] = grbm_gfx_index.u32All;
|
||||
reg_num++;
|
||||
@@ -1189,6 +952,7 @@ uint32_t ViPmu::BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id,
|
||||
grbm_gfx_index.bitfields.INSTANCE_BROADCAST_WRITES = 1;
|
||||
grbm_gfx_index.bitfields.SE_INDEX = ii;
|
||||
grbm_gfx_index.bitfields.SH_BROADCAST_WRITES = 1;
|
||||
|
||||
reg_addr[reg_num] = mmGRBM_GFX_INDEX__CI__VI;
|
||||
reg_val[reg_num] = grbm_gfx_index.u32All;
|
||||
reg_num++;
|
||||
@@ -1210,6 +974,7 @@ uint32_t ViPmu::BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id,
|
||||
grbm_gfx_index.bitfields.INSTANCE_BROADCAST_WRITES = 1;
|
||||
grbm_gfx_index.bitfields.SE_INDEX = ii;
|
||||
grbm_gfx_index.bitfields.SH_BROADCAST_WRITES = 1;
|
||||
|
||||
reg_addr[reg_num] = mmGRBM_GFX_INDEX__CI__VI;
|
||||
reg_val[reg_num] = grbm_gfx_index.u32All;
|
||||
reg_num++;
|
||||
@@ -1247,6 +1012,7 @@ uint32_t ViPmu::BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id,
|
||||
grbm_gfx_index.bitfields.INSTANCE_INDEX = instance_index;
|
||||
grbm_gfx_index.bitfields.SE_INDEX = ii;
|
||||
grbm_gfx_index.bitfields.SH_BROADCAST_WRITES = 1;
|
||||
|
||||
reg_addr[reg_num] = mmGRBM_GFX_INDEX__CI__VI;
|
||||
reg_val[reg_num] = grbm_gfx_index.u32All;
|
||||
reg_num++;
|
||||
@@ -1269,6 +1035,7 @@ uint32_t ViPmu::BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id,
|
||||
grbm_gfx_index.bitfields.INSTANCE_INDEX = instance_index;
|
||||
grbm_gfx_index.bitfields.SE_BROADCAST_WRITES = 1;
|
||||
grbm_gfx_index.bitfields.SH_BROADCAST_WRITES = 1;
|
||||
|
||||
reg_addr[reg_num] = mmGRBM_GFX_INDEX__CI__VI;
|
||||
reg_val[reg_num] = grbm_gfx_index.u32All;
|
||||
reg_num++;
|
||||
@@ -1377,6 +1144,7 @@ uint32_t ViPmu::BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id,
|
||||
grbm_gfx_index.bitfields.INSTANCE_INDEX = instance_index;
|
||||
grbm_gfx_index.bitfields.SE_INDEX = ii;
|
||||
grbm_gfx_index.bitfields.SH_BROADCAST_WRITES = 1;
|
||||
|
||||
reg_addr[reg_num] = mmGRBM_GFX_INDEX__CI__VI;
|
||||
reg_val[reg_num] = grbm_gfx_index.u32All;
|
||||
reg_num++;
|
||||
@@ -1413,6 +1181,7 @@ uint32_t ViPmu::BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id,
|
||||
grbm_gfx_index.bitfields.INSTANCE_BROADCAST_WRITES = 1;
|
||||
grbm_gfx_index.bitfields.SE_INDEX = ii;
|
||||
grbm_gfx_index.bitfields.SH_BROADCAST_WRITES = 1;
|
||||
|
||||
reg_addr[reg_num] = mmGRBM_GFX_INDEX__CI__VI;
|
||||
reg_val[reg_num] = grbm_gfx_index.u32All;
|
||||
reg_num++;
|
||||
@@ -1434,6 +1203,7 @@ uint32_t ViPmu::BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id,
|
||||
grbm_gfx_index.bitfields.INSTANCE_BROADCAST_WRITES = 1;
|
||||
grbm_gfx_index.bitfields.SE_INDEX = ii;
|
||||
grbm_gfx_index.bitfields.SH_BROADCAST_WRITES = 1;
|
||||
|
||||
reg_addr[reg_num] = mmGRBM_GFX_INDEX__CI__VI;
|
||||
reg_val[reg_num] = grbm_gfx_index.u32All;
|
||||
reg_num++;
|
||||
@@ -1554,16 +1324,4 @@ uint32_t ViPmu::BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id,
|
||||
return reg_num;
|
||||
}
|
||||
|
||||
hsa_status_t ViPmu::RemoveCounterBlocks() {
|
||||
ViCounterBlockMap::iterator it = blk_map_.begin();
|
||||
ViCounterBlockMap::iterator block_end = blk_map_.end();
|
||||
|
||||
for (; it != block_end; it++) {
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
} /* namespace */
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
#ifndef _VI_PMU_H_
|
||||
#define _VI_PMU_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "perf_counter.h"
|
||||
|
||||
namespace pm4_profile {
|
||||
class CommandWriter;
|
||||
|
||||
// This class implement the VI PMU. It is responsible for setting up
|
||||
// CounterGroups to represent each VI hardware block which exposes performance
|
||||
// counters.
|
||||
class Gfx8PerfCounter : public pm4_profile::Pmu {
|
||||
public:
|
||||
Gfx8PerfCounter();
|
||||
|
||||
// Returns number of shader engines per block
|
||||
// for the blocks featured shader engines instancing
|
||||
uint32_t getNumSe() { return num_se_; }
|
||||
|
||||
int getLastError();
|
||||
|
||||
std::string getErrorString(int error);
|
||||
|
||||
void begin(DefaultCmdBuf* cmdBuff, CommandWriter* cmdWriter, const CountersMap& countersMap);
|
||||
|
||||
uint32_t end(DefaultCmdBuf* cmdBuff, CommandWriter* cmdWriter, const CountersMap& countersMap,
|
||||
void* dataBuff);
|
||||
|
||||
private:
|
||||
void Init();
|
||||
|
||||
// Program SQ block related counters
|
||||
uint32_t ProgramSQCntrs(uint32_t sqRegIdx, uint32_t* regAddr, uint32_t* regVal, uint32_t blkId,
|
||||
uint32_t blkCntrIdx);
|
||||
|
||||
// Program TA block related counters
|
||||
uint32_t ProgramTaCntrs(uint32_t taRegIdx, uint32_t* regAddr, uint32_t* regVal, uint32_t blkId,
|
||||
uint32_t blkCntrIdx);
|
||||
|
||||
// Program TCA block related counters
|
||||
uint32_t ProgramTcaCntrs(uint32_t tcaRegIdx, uint32_t* regAddr, uint32_t* regVal, uint32_t blkId,
|
||||
uint32_t blkCntrIdx);
|
||||
|
||||
// Program TCC block related counters
|
||||
uint32_t ProgramTccCntrs(uint32_t tccRegIdx, uint32_t* regAddr, uint32_t* regVal, uint32_t blkId,
|
||||
uint32_t blkCntrIdx);
|
||||
|
||||
// Program TCP block related counters
|
||||
uint32_t ProgramTcpCntrs(uint32_t tcpRegIdx, uint32_t* regAddr, uint32_t* regVal, uint32_t blkId,
|
||||
uint32_t blkCntrIdx);
|
||||
|
||||
// Program TD block related counters
|
||||
uint32_t ProgramTdCntrs(uint32_t tdRegIdx, uint32_t* regAddr, uint32_t* regVal, uint32_t blkId,
|
||||
uint32_t blkCntrIdx);
|
||||
|
||||
// Build counter selection register, return how many registers are built
|
||||
uint32_t BuildCounterSelRegister(uint32_t cntrIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx);
|
||||
|
||||
// Build counter selection register, return how many registers are built
|
||||
uint32_t BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id, uint32_t* reg_addr,
|
||||
uint32_t* reg_val);
|
||||
|
||||
private:
|
||||
int error_code_;
|
||||
|
||||
// Indicates the number of Shader Engines Present
|
||||
uint32_t num_se_;
|
||||
|
||||
// Used to reset GRBM to its default state
|
||||
uint32_t reset_grbm_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // _VI_PMU_H_
|
||||
+4
-2
@@ -1,4 +1,4 @@
|
||||
#include "ai_blockinfo.h"
|
||||
#include "gfx9_block_info.h"
|
||||
#include "gfxip/gfx9/gfx9_offset.h"
|
||||
#include "gfxip/gfx9/gfx9_typedef.h"
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace pm4_profile {
|
||||
* Table containing CounterGroups which represent AI hardware blocks
|
||||
* as defined by \ref GpuBlockInfo structure
|
||||
*/
|
||||
GpuBlockInfo AiPmuHwBlocks[] = {
|
||||
GpuBlockInfo Gfx9HwBlocks[] = {
|
||||
// Counter block CB
|
||||
{"AI_CB0", kHsaAiCounterBlockIdCb0, AI_MAX_NUM_SHADER_ENGINES, 2, AI_NUM_CB,
|
||||
CntlMethodBySeAndInstance, 395, AI_COUNTER_NUM_PER_CB, 0, 0, true, 0, 0, false, 0, 0},
|
||||
@@ -270,6 +270,8 @@ GpuBlockInfo AiPmuHwBlocks[] = {
|
||||
{"", kHsaAiCounterBlockIdBlocksLast, 0, 0, 0, CntlMethodNone, 0, 0, 0, 0, false, 0, 0, false, 0,
|
||||
0}};
|
||||
|
||||
extern const uint32_t Gfx9HwBlockCount = sizeof(Gfx9HwBlocks) / sizeof(GpuBlockInfo);
|
||||
|
||||
/*
|
||||
* The following tables contain register addresses of the SQ counter registers
|
||||
*/
|
||||
+2
-5
@@ -1,10 +1,7 @@
|
||||
#ifndef _AI_BLOCKINFO_H_
|
||||
#define _AI_BLOCKINFO_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "rocr_profiler.h"
|
||||
#include "gpu_enum.h"
|
||||
#include "gpu_blockinfo.h"
|
||||
#include "gpu_block_info.h"
|
||||
|
||||
namespace pm4_profile {
|
||||
|
||||
@@ -208,7 +205,7 @@ typedef enum HsaAiCounterBlockId {
|
||||
kHsaAiCounterBlockIdBlocksLast = kHsaAiCounterBlockIdHwInfo
|
||||
} HsaAiCounterBlockId;
|
||||
|
||||
extern GpuBlockInfo AiPmuHwBlocks[];
|
||||
extern GpuBlockInfo Gfx9HwBlocks[];
|
||||
extern GpuCounterRegInfo AiSqCounterRegAddr[];
|
||||
extern GpuCounterRegInfo AiCbCounterRegAddr[];
|
||||
extern GpuCounterRegInfo AiDrmdmaCounterRegAddr[];
|
||||
+73
-323
@@ -1,30 +1,21 @@
|
||||
#include "os.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include "gfxip/gfx9/gfx9_registers.h"
|
||||
#include "gfxip/gfx9/gfx9_typedef.h"
|
||||
#include "gfxip/gfx9/gfx9_offset.h"
|
||||
#include "gfxip/gfx9/gfx9_pm4defs.h"
|
||||
|
||||
#include "gfx9_perf_counter.h"
|
||||
#include "gfx9_block_info.h"
|
||||
#include "cmdwriter.h"
|
||||
|
||||
#include "ai_pmu.h"
|
||||
#include "gpu_countergroup.h"
|
||||
#include "ai_blockinfo.h"
|
||||
#include "gpu_enum.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <iomanip>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
using namespace pm4_profile;
|
||||
using namespace pm4_profile::gfx9;
|
||||
|
||||
// A flag to indicate the current packet is for copy register value
|
||||
#define MAX_REG_NUM (100)
|
||||
#define COPY_DATA_FLAG (0xFFFFFFFF)
|
||||
#define COPY_DATA_SEL_REG (0x00) ///< Mem-mapped register
|
||||
#define COPY_DATA_SEL_COUNT_1DW (0x00) ///< Copy 1 word (32 bits)
|
||||
#define COPY_DATA_SEL_COUNT_2DW (0x01) ///< Copy 2 words (64 bits)
|
||||
#define MAX_REG_NUM 100
|
||||
#define COPY_DATA_FLAG 0xFFFFFFFF
|
||||
|
||||
namespace pm4_profile {
|
||||
|
||||
@@ -36,20 +27,14 @@ static char errorString[][64] = {{"No error"},
|
||||
{"countegroup error state"},
|
||||
{"countegroup is not completed"}};
|
||||
|
||||
AiPmu::AiPmu() {
|
||||
Gfx9PerfCounter::Gfx9PerfCounter() {
|
||||
// Initialize the number of shader engines
|
||||
num_se_ = 4;
|
||||
Init();
|
||||
}
|
||||
|
||||
void AiPmu::Init() {
|
||||
void Gfx9PerfCounter::Init() {
|
||||
error_code_ = 0;
|
||||
info_set_ = new InfoSet();
|
||||
parameter_set_ = new ParameterSet();
|
||||
|
||||
// Initialize pointer to stored counter block list to NULL
|
||||
blk_list_ = NULL;
|
||||
initCounterBlock();
|
||||
|
||||
// Initialize the value to use in resetting GRBM
|
||||
regGRBM_GFX_INDEX grbm_gfx_index;
|
||||
@@ -58,60 +43,10 @@ void AiPmu::Init() {
|
||||
grbm_gfx_index.bitfields.SE_BROADCAST_WRITES = 1;
|
||||
grbm_gfx_index.bitfields.SH_BROADCAST_WRITES = 1;
|
||||
reset_grbm_ = grbm_gfx_index.u32All;
|
||||
|
||||
// Update state of Perf Mgmt Unit
|
||||
profiler_state_ = ROCR_PMU_STATE_IDLE;
|
||||
}
|
||||
|
||||
AiPmu::~AiPmu() {
|
||||
// Remove all counter blocks
|
||||
RemoveCounterBlocks();
|
||||
blk_map_.clear();
|
||||
delete parameter_set_;
|
||||
delete info_set_;
|
||||
|
||||
if (blk_list_) {
|
||||
free(blk_list_);
|
||||
blk_list_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Initializes the handle of buffer used to collect PMC data
|
||||
// @param cmdBufSz Size in terms of bytes
|
||||
bool AiPmu::setPmcDataBuff(uint8_t* pmcBuffer, uint32_t pmcBuffSz) {
|
||||
// Update counter data buffer addr and size params
|
||||
pmcDataSz_ = pmcBuffSz;
|
||||
pmcData_ = (uint32_t*)pmcBuffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// The logic is quite simple and is as follows
|
||||
//
|
||||
// Issue CsPartialFlush
|
||||
// Issue Cmd to stop Perf Counters
|
||||
// Issue Cmd to Disable & Reset Perf Counters
|
||||
//
|
||||
void AiPmu::ResetCounterBlocks(pm4_profile::DefaultCmdBuf* cmdBuff,
|
||||
pm4_profile::CommandWriter* cmdWriter) {
|
||||
// Waits until all outstanding commands have completed
|
||||
// by issing CS Partial Flush command
|
||||
cmdWriter->BuildWriteWaitIdlePacket(cmdBuff);
|
||||
|
||||
// Program CP Perfmon Cntrl Rgstr to disable and reset counters
|
||||
regCP_PERFMON_CNTL cp_perfmon_cntl;
|
||||
cp_perfmon_cntl.u32All = 0;
|
||||
cp_perfmon_cntl.bits.PERFMON_STATE = 0;
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, mmCP_PERFMON_CNTL, cp_perfmon_cntl.u32All);
|
||||
}
|
||||
|
||||
bool AiPmu::begin(pm4_profile::DefaultCmdBuf* cmdBuff, pm4_profile::CommandWriter* cmdWriter,
|
||||
bool reset_counter) {
|
||||
if (profiler_state_ != ROCR_PMU_STATE_IDLE) {
|
||||
error_code_ = kHsaPmuErrorCodeErrorState;
|
||||
return false;
|
||||
}
|
||||
|
||||
void Gfx9PerfCounter::begin(DefaultCmdBuf* cmdBuff, CommandWriter* cmdWriter,
|
||||
const CountersMap& countersMap) {
|
||||
// Reset Grbm to its default state - broadcast
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, mmGRBM_GFX_INDEX, reset_grbm_);
|
||||
|
||||
@@ -119,43 +54,31 @@ bool AiPmu::begin(pm4_profile::DefaultCmdBuf* cmdBuff, pm4_profile::CommandWrite
|
||||
// On Vega this is needed to collect Perf Cntrs
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, mmRLC_PERFMON_CLK_CNTL, 1);
|
||||
|
||||
// Collect all the program counter blocks
|
||||
uint32_t reg_val[MAX_REG_NUM], reg_addr[MAX_REG_NUM], reg_num;
|
||||
|
||||
// Retrieve the list of blocks whose perf counters have been enabled
|
||||
uint32_t blk_cnt = 0;
|
||||
CounterBlock** blk_list = getAllCounterBlocks(blk_cnt);
|
||||
|
||||
// Iterate through the list of blocks to generate Pm4 commands to
|
||||
// program corresponding perf counters of each block
|
||||
for (uint32_t blkIdx = 0; blkIdx < blk_cnt; blkIdx++) {
|
||||
// Retrieve the list of perf counters and their count
|
||||
uint32_t counter_num;
|
||||
Counter** cntr_list;
|
||||
cntr_list = blk_list[blkIdx]->getEnabledCounters(counter_num);
|
||||
if (counter_num == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Retrieve the block Id of perf counters
|
||||
void* p_data;
|
||||
uint32_t block_id;
|
||||
uint32_t data_size;
|
||||
blk_list[blkIdx]->getInfo(GPU_BLK_INFO_ID, data_size, (void**)&p_data);
|
||||
block_id = *(static_cast<uint32_t*>(p_data));
|
||||
for (CountersMap::const_iterator block_it = countersMap.begin(); block_it != countersMap.end();
|
||||
++block_it) {
|
||||
const uint32_t block_id = block_it->first;
|
||||
const CountersVec& counters = block_it->second;
|
||||
const uint32_t counter_count = counters.size();
|
||||
|
||||
// Iterate through each enabled perf counter and building
|
||||
// corresponding Pm4 commands to program the various control
|
||||
// registers involved
|
||||
for (uint32_t cntrIdx = 0; cntrIdx < counter_num; cntrIdx++) {
|
||||
|
||||
for (uint32_t ind = 0; ind < counter_count; ++ind) {
|
||||
const uint32_t counter_id = counters[ind];
|
||||
|
||||
// Build the list of control registers to program which
|
||||
// varies per perf counter block
|
||||
reg_num = BuildCounterSelRegister(cntrIdx, reg_addr, reg_val, block_id, cntr_list[cntrIdx]);
|
||||
uint32_t reg_addr[MAX_REG_NUM], reg_val[MAX_REG_NUM];
|
||||
const uint32_t reg_num =
|
||||
BuildCounterSelRegister(ind, reg_addr, reg_val, block_id, counter_id);
|
||||
|
||||
// Build the list of Pm4 commands that support control
|
||||
// register programming
|
||||
for (uint32_t regIdx = 0; regIdx < reg_num; regIdx++) {
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, reg_addr[regIdx], reg_val[regIdx]);
|
||||
for (uint32_t n = 0; n < reg_num; ++n) {
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, reg_addr[n], reg_val[n]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,91 +102,45 @@ bool AiPmu::begin(pm4_profile::DefaultCmdBuf* cmdBuff, pm4_profile::CommandWrite
|
||||
cp_perfmon_cntl.bits.PERFMON_STATE = 1;
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, mmCP_PERFMON_CNTL, cp_perfmon_cntl.u32All);
|
||||
|
||||
// Issue barrier command to apply the commands to configure perfcounters
|
||||
cmdWriter->BuildWriteWaitIdlePacket(cmdBuff);
|
||||
|
||||
profiler_state_ = ROCR_PMU_STATE_START;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AiPmu::end(pm4_profile::DefaultCmdBuf* cmdBuff, pm4_profile::CommandWriter* cmdWriter) {
|
||||
if (profiler_state_ != ROCR_PMU_STATE_START) {
|
||||
error_code_ = kHsaPmuErrorCodeErrorState;
|
||||
return false;
|
||||
}
|
||||
|
||||
void* p_data;
|
||||
regGRBM_GFX_INDEX grbm_gfx_index;
|
||||
|
||||
// Issue CsPartialFlush command to wait for dispatch to complete
|
||||
uint32_t Gfx9PerfCounter::end(DefaultCmdBuf* cmdBuff, CommandWriter* cmdWriter,
|
||||
const CountersMap& countersMap, void* dataBuff) {
|
||||
// Issue barrier command to wait for dispatch to complete
|
||||
cmdWriter->BuildWriteWaitIdlePacket(cmdBuff);
|
||||
|
||||
// Build PM4 packet for starting counters
|
||||
// Build PM4 packet to stop and freeze counters
|
||||
regCP_PERFMON_CNTL cp_perfmon_cntl;
|
||||
cp_perfmon_cntl.u32All = 0;
|
||||
cp_perfmon_cntl.bits.PERFMON_STATE = 2;
|
||||
cp_perfmon_cntl.bits.PERFMON_SAMPLE_ENABLE = 1;
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, mmCP_PERFMON_CNTL, cp_perfmon_cntl.u32All);
|
||||
|
||||
// Collect all the program counter blocks
|
||||
uint32_t i, j, k, reg_addr[MAX_REG_NUM], reg_val[MAX_REG_NUM], reg_num, data_size;
|
||||
|
||||
uint32_t blk_cnt = 0;
|
||||
CounterBlock** blk_list = getAllCounterBlocks(blk_cnt);
|
||||
|
||||
uint32_t counter_num;
|
||||
Counter** cntr_list;
|
||||
uint32_t total_counter_num = 0;
|
||||
for (i = 0; i < blk_cnt; i++) {
|
||||
// Retrieve all enabled cntr_list in each counter block
|
||||
cntr_list = blk_list[i]->getEnabledCounters(counter_num);
|
||||
if (!blk_list[i]->getInfo(GPU_BLK_INFO_CONTROL_METHOD, data_size, &p_data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CntlMethod method;
|
||||
method = static_cast<CntlMethod>(*(static_cast<uint32_t*>(p_data)));
|
||||
|
||||
// Need to read counter values from each shader engine
|
||||
if (method == CntlMethodBySe || method == CntlMethodBySeAndInstance) {
|
||||
counter_num = counter_num * num_se_;
|
||||
}
|
||||
|
||||
total_counter_num += counter_num;
|
||||
}
|
||||
|
||||
size_t cntrSize = sizeof(int32_t) * 2 * total_counter_num;
|
||||
if (cntrSize > pmcDataSz_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reset Grbm to its default state - broadcast
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, mmGRBM_GFX_INDEX, reset_grbm_);
|
||||
|
||||
// Create PM4 packet to read counter values
|
||||
total_counter_num = 0;
|
||||
for (i = 0; i < blk_cnt; i++) {
|
||||
// Retrieve all enabled cntr_list in each counter block
|
||||
cntr_list = blk_list[i]->getEnabledCounters(counter_num);
|
||||
if (counter_num > 0) {
|
||||
uint32_t block_id;
|
||||
uint32_t data_size;
|
||||
if (!blk_list[i]->getInfo(GPU_BLK_INFO_ID, data_size, (void**)&p_data)) {
|
||||
return false;
|
||||
}
|
||||
block_id = *(static_cast<uint32_t*>(p_data));
|
||||
// Iterate through the list of blocks to create PM4 packets to read counter values
|
||||
uint32_t total_counter_num = 0;
|
||||
for (CountersMap::const_iterator block_it = countersMap.begin(); block_it != countersMap.end();
|
||||
++block_it) {
|
||||
const uint32_t block_id = block_it->first;
|
||||
const uint32_t counter_count = block_it->second.size();
|
||||
|
||||
for (j = 0; j < counter_num; j++) {
|
||||
// retrieve the registers to be set
|
||||
reg_num = BuildCounterReadRegisters(j, block_id, reg_addr, reg_val);
|
||||
for (k = 0; k < reg_num; k++) {
|
||||
if (reg_val[k] == COPY_DATA_FLAG) {
|
||||
cmdWriter->BuildCopyDataPacket(cmdBuff, COPY_DATA_SEL_REG, reg_addr[k], 0,
|
||||
pmcData_ + total_counter_num, COPY_DATA_SEL_COUNT_1DW,
|
||||
false);
|
||||
total_counter_num++;
|
||||
} else {
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, reg_addr[k], reg_val[k]);
|
||||
}
|
||||
for (uint32_t ind = 0; ind < counter_count; ++ind) {
|
||||
// retrieve the registers to be set
|
||||
uint32_t reg_addr[MAX_REG_NUM], reg_val[MAX_REG_NUM];
|
||||
const uint32_t reg_num = BuildCounterReadRegisters(ind, block_id, reg_addr, reg_val);
|
||||
|
||||
for (uint32_t n = 0; n < reg_num; n++) {
|
||||
if (reg_val[n] == COPY_DATA_FLAG) {
|
||||
cmdWriter->BuildCopyDataPacket(cmdBuff, COPY_DATA_SEL_REG, reg_addr[n], 0,
|
||||
((uint32_t*)dataBuff) + total_counter_num,
|
||||
COPY_DATA_SEL_COUNT_1DW, false);
|
||||
total_counter_num++;
|
||||
} else {
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, reg_addr[n], reg_val[n]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -276,127 +153,21 @@ bool AiPmu::end(pm4_profile::DefaultCmdBuf* cmdBuff, pm4_profile::CommandWriter*
|
||||
// was disabled during Perf Cntrs collection session
|
||||
cmdWriter->BuildWriteUConfigRegPacket(cmdBuff, mmRLC_PERFMON_CLK_CNTL, 0);
|
||||
|
||||
profiler_state_ = ROCR_PMU_STATE_STOP;
|
||||
return true;
|
||||
return total_counter_num * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
bool AiPmu::initCounterBlock() {
|
||||
for (int i = 0; !(std::string(AiPmuHwBlocks[i].blockName).empty()); i++) {
|
||||
// Override the value of max number of shader engines
|
||||
AiPmuHwBlocks[i].maxShaderEngineCount = num_se_;
|
||||
int Gfx9PerfCounter::getLastError() { return error_code_; }
|
||||
|
||||
// Instantiate a perf counter block and its properties
|
||||
GpuCounterBlock* cntr_blk = new GpuCounterBlock();
|
||||
if (!cntr_blk) {
|
||||
blk_map_.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_BLOCK_NAME, GPU_BLOCK_NAME_SIZE,
|
||||
(void*)AiPmuHwBlocks[i].blockName);
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_ID, sizeof(uint32_t), (void*)&AiPmuHwBlocks[i].counterGroupId);
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_MAX_SHADER_ENGINE_COUNT, sizeof(uint32_t),
|
||||
(void*)&(AiPmuHwBlocks[i].maxShaderEngineCount));
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_MAX_SHADER_ARRAY_COUNT, sizeof(uint32_t),
|
||||
(void*)&(AiPmuHwBlocks[i].maxShaderArrayCount));
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_MAX_INSTANCE_COUNT, sizeof(uint32_t),
|
||||
(void*)&(AiPmuHwBlocks[i].maxInstanceCount));
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_CONTROL_METHOD, sizeof(uint32_t),
|
||||
(void*)&(AiPmuHwBlocks[i].method));
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_MAX_EVENT_ID, sizeof(uint32_t),
|
||||
(void*)&(AiPmuHwBlocks[i].maxEventId));
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_MAX_SIMULTANEOUS_COUNTERS, sizeof(uint32_t),
|
||||
(void*)&(AiPmuHwBlocks[i].maxSimultaneousCounters));
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_MAX_STREAMING_COUNTERS, sizeof(uint32_t),
|
||||
(void*)&(AiPmuHwBlocks[i].maxStreamingCounters));
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_SHARED_HW_COUNTERS, sizeof(uint32_t),
|
||||
(void*)&(AiPmuHwBlocks[i].sharedHWCounters));
|
||||
|
||||
cntr_blk->setInfo(GPU_BLK_INFO_HAS_FILTERS, sizeof(bool),
|
||||
(void*)&(AiPmuHwBlocks[i].hasFilters));
|
||||
|
||||
// TODO: Need to fill in the Threadtrace stuff here
|
||||
HsaAiCounterBlockId blk_id;
|
||||
blk_id = static_cast<HsaAiCounterBlockId>(AiPmuHwBlocks[i].counterGroupId);
|
||||
blk_map_.insert(AiCounterBlockMap::value_type(blk_id, cntr_blk));
|
||||
}
|
||||
|
||||
// Initiate the PMU state and error code
|
||||
error_code_ = 0;
|
||||
profiler_state_ = ROCR_PMU_STATE_IDLE;
|
||||
return true;
|
||||
}
|
||||
|
||||
int AiPmu::getLastError() { return error_code_; }
|
||||
|
||||
std::string AiPmu::getErrorString(int error) {
|
||||
if ((error >= 0) && (error < kHsaPmuErrorCodeMax)) {
|
||||
std::string Gfx9PerfCounter::getErrorString(int error) {
|
||||
if ((error >= 0) && (error < kErrorCodeMax)) {
|
||||
std::string err_string(errorString[error]);
|
||||
return err_string;
|
||||
}
|
||||
return string("Error input code!");
|
||||
}
|
||||
|
||||
bool AiPmu::getParameter(uint32_t param, uint32_t& retSize, void** ppData) {
|
||||
return parameter_set_->getParameter(param, retSize, ppData);
|
||||
}
|
||||
|
||||
bool AiPmu::setParameter(uint32_t param, uint32_t paramSize, const void* p_data) {
|
||||
return parameter_set_->setParameter(param, paramSize, p_data);
|
||||
}
|
||||
|
||||
bool AiPmu::getInfo(uint32_t info, uint32_t& retSize, void** ppData) {
|
||||
return info_set_->getInfo(info, retSize, ppData);
|
||||
}
|
||||
|
||||
pm4_profile::CounterBlock* AiPmu::getCounterBlockById(uint32_t id) {
|
||||
HsaAiCounterBlockId block_id = static_cast<HsaAiCounterBlockId>(id);
|
||||
|
||||
return blk_map_[block_id];
|
||||
}
|
||||
|
||||
pm4_profile::CounterBlock** AiPmu::getAllCounterBlocks(uint32_t& num_blocks) {
|
||||
size_t block_size = blk_map_.size();
|
||||
|
||||
if (block_size <= 0) {
|
||||
error_code_ = kHsaPmuErrorCodeNoCounterBlock;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (blk_list_) {
|
||||
free(blk_list_);
|
||||
blk_list_ = NULL;
|
||||
}
|
||||
|
||||
blk_list_size_ = (uint32_t)(sizeof(GpuCounterBlock*) * block_size);
|
||||
blk_list_size_ = ((blk_list_size_ % 4096) != 0) ? 4096 : blk_list_size_;
|
||||
blk_list_ = (CounterBlock**)malloc(blk_list_size_);
|
||||
if (blk_list_ == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AiCounterBlockMap::iterator it;
|
||||
uint32_t blk_cnt = 0;
|
||||
for (it = blk_map_.begin(); it != blk_map_.end(); it++) {
|
||||
blk_list_[blk_cnt] = it->second;
|
||||
blk_cnt++;
|
||||
}
|
||||
|
||||
num_blocks = blk_cnt;
|
||||
return blk_list_;
|
||||
}
|
||||
|
||||
uint32_t AiPmu::ProgramTcpCntrs(uint32_t tcpRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
uint32_t Gfx9PerfCounter::ProgramTcpCntrs(uint32_t tcpRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
regGRBM_GFX_INDEX grbm_gfx_index;
|
||||
|
||||
grbm_gfx_index.u32All = 0;
|
||||
@@ -420,8 +191,8 @@ uint32_t AiPmu::ProgramTcpCntrs(uint32_t tcpRegIdx, uint32_t* regAddr, uint32_t*
|
||||
return regIdx;
|
||||
}
|
||||
|
||||
uint32_t AiPmu::ProgramTdCntrs(uint32_t tdRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
uint32_t Gfx9PerfCounter::ProgramTdCntrs(uint32_t tdRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
regGRBM_GFX_INDEX grbm_gfx_index;
|
||||
|
||||
grbm_gfx_index.u32All = 0;
|
||||
@@ -444,8 +215,8 @@ uint32_t AiPmu::ProgramTdCntrs(uint32_t tdRegIdx, uint32_t* regAddr, uint32_t* r
|
||||
return regIdx;
|
||||
}
|
||||
|
||||
uint32_t AiPmu::ProgramTccCntrs(uint32_t tccRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
uint32_t Gfx9PerfCounter::ProgramTccCntrs(uint32_t tccRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
regGRBM_GFX_INDEX grbm_gfx_index;
|
||||
|
||||
grbm_gfx_index.u32All = 0;
|
||||
@@ -469,8 +240,8 @@ uint32_t AiPmu::ProgramTccCntrs(uint32_t tccRegIdx, uint32_t* regAddr, uint32_t*
|
||||
return regIdx;
|
||||
}
|
||||
|
||||
uint32_t AiPmu::ProgramTcaCntrs(uint32_t tcaRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
uint32_t Gfx9PerfCounter::ProgramTcaCntrs(uint32_t tcaRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
regGRBM_GFX_INDEX grbm_gfx_index;
|
||||
|
||||
grbm_gfx_index.u32All = 0;
|
||||
@@ -493,8 +264,8 @@ uint32_t AiPmu::ProgramTcaCntrs(uint32_t tcaRegIdx, uint32_t* regAddr, uint32_t*
|
||||
return regIdx;
|
||||
}
|
||||
|
||||
uint32_t AiPmu::ProgramTaCntrs(uint32_t taRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
uint32_t Gfx9PerfCounter::ProgramTaCntrs(uint32_t taRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
regGRBM_GFX_INDEX grbm_gfx_index;
|
||||
|
||||
grbm_gfx_index.u32All = 0;
|
||||
@@ -518,8 +289,8 @@ uint32_t AiPmu::ProgramTaCntrs(uint32_t taRegIdx, uint32_t* regAddr, uint32_t* r
|
||||
return regIdx;
|
||||
}
|
||||
|
||||
uint32_t AiPmu::ProgramSQCntrs(uint32_t sqRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
uint32_t Gfx9PerfCounter::ProgramSQCntrs(uint32_t sqRegIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, uint32_t blkCntrIdx) {
|
||||
uint32_t regIdx = 0;
|
||||
|
||||
// Program the SQ Counter Select Register
|
||||
@@ -571,22 +342,13 @@ uint32_t AiPmu::ProgramSQCntrs(uint32_t sqRegIdx, uint32_t* regAddr, uint32_t* r
|
||||
return regIdx;
|
||||
}
|
||||
|
||||
uint32_t AiPmu::BuildCounterSelRegister(uint32_t cntrIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, pm4_profile::Counter* blkCntr) {
|
||||
void* p_data;
|
||||
uint32_t data_size;
|
||||
uint32_t blkCntrIdx;
|
||||
uint32_t instance_index;
|
||||
regGRBM_GFX_INDEX grbm_gfx_index;
|
||||
|
||||
// Get the blkCntr selection value
|
||||
if (!blkCntr->getParameter(HSA_EXT_TOOLS_COUNTER_PARAMETER_EVENT_INDEX, data_size,
|
||||
(void**)&p_data)) {
|
||||
return 0;
|
||||
}
|
||||
blkCntrIdx = *(static_cast<uint32_t*>(p_data));
|
||||
|
||||
uint32_t Gfx9PerfCounter::BuildCounterSelRegister(uint32_t cntrIdx, uint32_t* regAddr,
|
||||
uint32_t* regVal, uint32_t blkId,
|
||||
uint32_t blkCntrIdx) {
|
||||
uint32_t instance_index = 0;
|
||||
regGRBM_GFX_INDEX grbm_gfx_index = {0};
|
||||
uint32_t regIdx = 0;
|
||||
|
||||
switch (blkId) {
|
||||
// Program counters belonging to SQ block
|
||||
case kHsaAiCounterBlockIdSq:
|
||||
@@ -1019,8 +781,8 @@ uint32_t AiPmu::BuildCounterSelRegister(uint32_t cntrIdx, uint32_t* regAddr, uin
|
||||
return regIdx;
|
||||
}
|
||||
|
||||
uint32_t AiPmu::BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id, uint32_t* reg_addr,
|
||||
uint32_t* reg_val) {
|
||||
uint32_t Gfx9PerfCounter::BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id,
|
||||
uint32_t* reg_addr, uint32_t* reg_val) {
|
||||
uint32_t ii;
|
||||
uint32_t reg_num = 0;
|
||||
uint32_t instance_index;
|
||||
@@ -1586,16 +1348,4 @@ uint32_t AiPmu::BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id,
|
||||
return reg_num;
|
||||
}
|
||||
|
||||
hsa_status_t AiPmu::RemoveCounterBlocks() {
|
||||
AiCounterBlockMap::iterator it = blk_map_.begin();
|
||||
AiCounterBlockMap::iterator block_end = blk_map_.end();
|
||||
|
||||
for (; it != block_end; it++) {
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
} /* namespace */
|
||||
+9
-69
@@ -1,78 +1,36 @@
|
||||
#ifndef _AI_PMU_H_
|
||||
#define _AI_PMU_H_
|
||||
|
||||
#include "hsa.h"
|
||||
#include "cmdwriter.h"
|
||||
#include "hsa_perf.h"
|
||||
#include "info_set.h"
|
||||
#include "parameter_set.h"
|
||||
#include "ai_blockinfo.h"
|
||||
#include "rocr_profiler.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <map>
|
||||
|
||||
#include "perf_counter.h"
|
||||
|
||||
namespace pm4_profile {
|
||||
typedef std::map<HsaAiCounterBlockId, pm4_profile::CounterBlock*> AiCounterBlockMap;
|
||||
class CommandWriter;
|
||||
|
||||
// This class implement the AI PMU. It is responsible for setting up
|
||||
// CounterGroups to represent each AI hardware block which exposes performance
|
||||
// counters.
|
||||
class AiPmu : public pm4_profile::Pmu {
|
||||
class Gfx9PerfCounter : public pm4_profile::Pmu {
|
||||
public:
|
||||
AiPmu();
|
||||
|
||||
~AiPmu();
|
||||
Gfx9PerfCounter();
|
||||
|
||||
// Returns number of shader engines per block
|
||||
// for the blocks featured shader engines instancing
|
||||
uint32_t getNumSe() { return num_se_; }
|
||||
|
||||
// Initializes the handle of buffer used to collect PMC data
|
||||
bool setPmcDataBuff(uint8_t* pmcBuffer, uint32_t pmcBuffSz);
|
||||
|
||||
int getLastError();
|
||||
|
||||
std::string getErrorString(int error);
|
||||
|
||||
virtual bool begin(DefaultCmdBuf* cmdBuff, CommandWriter* cmdWriter, bool reset = true);
|
||||
void begin(DefaultCmdBuf* cmdBuff, CommandWriter* cmdWriter, const CountersMap& countersMap);
|
||||
|
||||
virtual bool end(DefaultCmdBuf* cmdBuff, CommandWriter* cmdWriter);
|
||||
|
||||
// IPMU inherits the IParameterSet and IInfoSetso we implement it
|
||||
// through composition and function forwarding
|
||||
bool getParameter(uint32_t param, uint32_t& ret_size, void** pp_data);
|
||||
|
||||
bool setParameter(uint32_t param, uint32_t param_size, const void* p_data);
|
||||
|
||||
bool getInfo(uint32_t info, uint32_t& ret_size, void** pp_data);
|
||||
|
||||
pm4_profile::CounterBlock* getCounterBlockById(uint32_t id);
|
||||
|
||||
rocr_pmu_state_t getCurrentState() { return profiler_state_; }
|
||||
|
||||
pm4_profile::CounterBlock** getAllCounterBlocks(uint32_t& num_groups);
|
||||
uint32_t end(DefaultCmdBuf* cmdBuff, CommandWriter* cmdWriter, const CountersMap& countersMap,
|
||||
void* dataBuff);
|
||||
|
||||
private:
|
||||
// Addr of Counter Data Buffer
|
||||
uint32_t* pmcData_;
|
||||
|
||||
// Size of Counter Data Buffer
|
||||
uint32_t pmcDataSz_;
|
||||
|
||||
void Init();
|
||||
|
||||
bool initCounterBlock();
|
||||
|
||||
bool isResultReady();
|
||||
|
||||
// Clear CounterBlockMap
|
||||
void clearCounterBlockMap();
|
||||
|
||||
// Reset SQ and CB counters
|
||||
void ResetCounterBlocks(DefaultCmdBuf* cmdBuff, CommandWriter* cmdWriter);
|
||||
|
||||
// Program SQ block related counters
|
||||
uint32_t ProgramSQCntrs(uint32_t sqRegIdx, uint32_t* regAddr, uint32_t* regVal, uint32_t blkId,
|
||||
uint32_t blkCntrIdx);
|
||||
@@ -99,33 +57,15 @@ class AiPmu : public pm4_profile::Pmu {
|
||||
|
||||
// Build counter selection register, return how many registers are built
|
||||
uint32_t BuildCounterSelRegister(uint32_t cntrIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, pm4_profile::Counter* blkCntr);
|
||||
uint32_t blkId, uint32_t blkCntrIdx);
|
||||
|
||||
// Build counter selection register, return how many registers are built
|
||||
uint32_t BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id, uint32_t* reg_addr,
|
||||
uint32_t* reg_val);
|
||||
|
||||
private:
|
||||
// Delete counter blocks in the PMU
|
||||
hsa_status_t RemoveCounterBlocks();
|
||||
|
||||
private:
|
||||
// This contains the available counter groups.
|
||||
AiCounterBlockMap blk_map_;
|
||||
|
||||
// This stores the current profiling state.
|
||||
rocr_pmu_state_t profiler_state_;
|
||||
|
||||
pm4_profile::ParameterSet* parameter_set_;
|
||||
|
||||
pm4_profile::InfoSet* info_set_;
|
||||
|
||||
int error_code_;
|
||||
|
||||
// Pointer used to store counter block list internally
|
||||
uint32_t blk_list_size_;
|
||||
pm4_profile::CounterBlock** blk_list_;
|
||||
|
||||
// Indicates the number of Shader Engines Present
|
||||
uint32_t num_se_;
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
#ifndef _GPU_BLOCKINFO_H_
|
||||
#define _GPU_BLOCKINFO_H_
|
||||
|
||||
#include "rocr_profiler.h"
|
||||
#include "gpu_enum.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace pm4_profile {
|
||||
-73
@@ -1,73 +0,0 @@
|
||||
#include "gpu_counter.h"
|
||||
|
||||
using namespace pm4_profile;
|
||||
|
||||
namespace pm4_profile {
|
||||
static char error_string[][64] = {
|
||||
{"No error"}, {"Counter generic error"}, {"Counter is already set"}, {"Counter not ready"},
|
||||
};
|
||||
|
||||
GpuCounter::GpuCounter() : Counter() {
|
||||
counter_enabled_ = false;
|
||||
parameter_set_ = new ParameterSet();
|
||||
}
|
||||
|
||||
GpuCounter::~GpuCounter() { delete parameter_set_; }
|
||||
|
||||
bool GpuCounter::getResult(uint64_t* p_result) {
|
||||
if (!p_result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*p_result = result_;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GpuCounter::setCounterBlock(pm4_profile::CounterBlock* p_cntr_group) {
|
||||
if (!p_cntr_group) {
|
||||
return false;
|
||||
}
|
||||
|
||||
counter_block_ = p_cntr_group;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
pm4_profile::CounterBlock* GpuCounter::getCounterBlock() { return counter_block_; }
|
||||
|
||||
bool GpuCounter::setEnable(bool b) {
|
||||
// TODO: Validate counter
|
||||
counter_enabled_ = b;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GpuCounter::setResult(uint64_t result) { result_ = result; }
|
||||
|
||||
int GpuCounter::getLastError() { return error_code_; }
|
||||
|
||||
std::string GpuCounter::getErrorString(int error) {
|
||||
if ((error >= 0) && (error < kHsaCounterErrorCodeMax)) {
|
||||
std::string err_string(error_string[error]);
|
||||
return err_string;
|
||||
}
|
||||
return "Incorrect error index";
|
||||
}
|
||||
|
||||
bool GpuCounter::getParameter(uint32_t param, uint32_t& ret_size, void** pp_data) {
|
||||
return parameter_set_->getParameter(param, ret_size, pp_data);
|
||||
}
|
||||
|
||||
bool GpuCounter::setParameter(uint32_t param, uint32_t param_size, const void* p_data) {
|
||||
bool ret_code;
|
||||
|
||||
error_code_ = kHsaCounterErrorCodeNoError;
|
||||
|
||||
ret_code = parameter_set_->setParameter(param, param_size, p_data);
|
||||
if (ret_code == false) {
|
||||
error_code_ = kHsaCounterErrorCodeAlreadySet;
|
||||
}
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
#ifndef _GPU_COUNTER_H_
|
||||
#define _GPU_COUNTER_H_
|
||||
|
||||
#include "hsa_perf.h"
|
||||
#include "parameter_set.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <list>
|
||||
|
||||
namespace pm4_profile {
|
||||
// @brief This class represent each CI performance counter
|
||||
class GpuCounter : public pm4_profile::Counter {
|
||||
public:
|
||||
GpuCounter();
|
||||
|
||||
virtual ~GpuCounter();
|
||||
|
||||
virtual int getLastError();
|
||||
|
||||
virtual std::string getErrorString(int error);
|
||||
|
||||
virtual bool getResult(uint64_t* p_result);
|
||||
|
||||
virtual pm4_profile::CounterBlock* getCounterBlock();
|
||||
|
||||
virtual bool setEnable(bool b);
|
||||
|
||||
virtual bool isEnabled() { return counter_enabled_; }
|
||||
|
||||
virtual bool isResultReady() { return is_result_ready_; }
|
||||
|
||||
virtual bool getParameter(uint32_t param, uint32_t& ret_size, void** pp_data);
|
||||
|
||||
virtual bool setParameter(uint32_t param, uint32_t param_size, const void* p_data);
|
||||
|
||||
bool setCounterBlock(pm4_profile::CounterBlock* p_cntr_group);
|
||||
|
||||
void setResult(uint64_t result);
|
||||
|
||||
private:
|
||||
bool counter_enabled_;
|
||||
bool is_result_ready_;
|
||||
uint64_t result_;
|
||||
pm4_profile::ParameterSet* parameter_set_;
|
||||
pm4_profile::CounterBlock* counter_block_;
|
||||
uint32_t error_code_;
|
||||
};
|
||||
|
||||
typedef std::list<GpuCounter*> GpuCounterList;
|
||||
}
|
||||
#endif // _GPU_COUNTER_H_
|
||||
-215
@@ -1,215 +0,0 @@
|
||||
#include "gpu_countergroup.h"
|
||||
#include "gpu_counter.h"
|
||||
#include "gpu_enum.h"
|
||||
|
||||
using namespace pm4_profile;
|
||||
|
||||
namespace pm4_profile {
|
||||
|
||||
static char error_string[][64] = {
|
||||
{"No error"}, {"Counter block error"}, {"Max counter reached"}, {"Unkown counter"}};
|
||||
|
||||
GpuCounterBlock::GpuCounterBlock() : CounterBlock() {
|
||||
cntr_list_.clear();
|
||||
parameter_set_ = new ParameterSet();
|
||||
info_set_ = new InfoSet();
|
||||
|
||||
// Initialize pointer to NULL
|
||||
pp_cntrs_ = NULL;
|
||||
|
||||
_initCounterBlockType();
|
||||
}
|
||||
|
||||
GpuCounterBlock::~GpuCounterBlock() {
|
||||
GpuCounterList::iterator it = cntr_list_.begin();
|
||||
GpuCounterList::iterator it_end = cntr_list_.end();
|
||||
|
||||
for (; it != it_end; it++) {
|
||||
if (*it) {
|
||||
delete (*it);
|
||||
}
|
||||
}
|
||||
cntr_list_.clear();
|
||||
|
||||
delete parameter_set_;
|
||||
delete info_set_;
|
||||
|
||||
if (pp_cntrs_) {
|
||||
free(pp_cntrs_);
|
||||
pp_cntrs_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void GpuCounterBlock::_initCounterBlockType() {
|
||||
block_type_ = HSA_EXT_TOOLS_COUNTER_BLOCK_TYPE_ASYNC;
|
||||
}
|
||||
|
||||
Counter* GpuCounterBlock::createCounter() {
|
||||
if (!_checkMaxNumOfCounters()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GpuCounter* p_cntr = new GpuCounter();
|
||||
if (!p_cntr) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cntr_list_.push_back(p_cntr);
|
||||
|
||||
return (Counter*)p_cntr;
|
||||
}
|
||||
|
||||
bool GpuCounterBlock::destroyCounter(Counter* p_cntr) {
|
||||
bool ret = false;
|
||||
|
||||
if (!p_cntr) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
GpuCounterList::iterator it = cntr_list_.begin();
|
||||
GpuCounterList::iterator it_end = cntr_list_.end();
|
||||
for (; it != it_end; it++) {
|
||||
if (*it == p_cntr) {
|
||||
delete (*it);
|
||||
cntr_list_.erase(it);
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool GpuCounterBlock::destroyAllCounters() {
|
||||
GpuCounterList::iterator it = cntr_list_.begin();
|
||||
GpuCounterList::iterator it_end = cntr_list_.end();
|
||||
|
||||
for (; it != it_end; it++) {
|
||||
if (*it) {
|
||||
delete (*it);
|
||||
}
|
||||
}
|
||||
|
||||
cntr_list_.clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Counter** GpuCounterBlock::getEnabledCounters(uint32_t& num) {
|
||||
if (pp_cntrs_) {
|
||||
free(pp_cntrs_);
|
||||
pp_cntrs_ = NULL;
|
||||
}
|
||||
|
||||
pp_cntrs_ = (Counter**)malloc(sizeof(GpuCounter*) * cntr_list_.size());
|
||||
|
||||
if (!pp_cntrs_) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int cnt = 0;
|
||||
GpuCounterList::iterator it = cntr_list_.begin();
|
||||
GpuCounterList::iterator it_end = cntr_list_.end();
|
||||
for (; it != it_end; it++) {
|
||||
GpuCounter* p_cntr = (*it);
|
||||
bool is_enabled;
|
||||
is_enabled = p_cntr->isEnabled();
|
||||
if (is_enabled) {
|
||||
*(pp_cntrs_ + cnt) = (Counter*)*it;
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
num = cnt;
|
||||
if (0 == num) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pp_cntrs_;
|
||||
}
|
||||
|
||||
Counter** GpuCounterBlock::getAllCounters(uint32_t& num) {
|
||||
if (pp_cntrs_) {
|
||||
free(pp_cntrs_);
|
||||
pp_cntrs_ = NULL;
|
||||
}
|
||||
|
||||
pp_cntrs_ = (Counter**)malloc(sizeof(GpuCounter*) * cntr_list_.size());
|
||||
|
||||
if (!pp_cntrs_) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int cnt = 0;
|
||||
GpuCounterList::iterator it = cntr_list_.begin();
|
||||
GpuCounterList::iterator it_end = cntr_list_.end();
|
||||
for (; it != it_end; it++, cnt++) {
|
||||
*(pp_cntrs_ + cnt) = (Counter*)*it;
|
||||
}
|
||||
|
||||
num = cnt;
|
||||
if (0 == num) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pp_cntrs_;
|
||||
}
|
||||
|
||||
bool GpuCounterBlock::setInfo(GPU_BLK_INFOS blk_info, uint32_t size, void* data) {
|
||||
return info_set_->setInfo(blk_info, size, data);
|
||||
}
|
||||
|
||||
bool GpuCounterBlock::_checkMaxNumOfCounters() {
|
||||
uint32_t num_enabled = _getNumOfEnabledCounters();
|
||||
|
||||
uint32_t* p_num_max = NULL;
|
||||
uint32_t size = 0;
|
||||
|
||||
if (!getInfo(GPU_BLK_INFO_MAX_SIMULTANEOUS_COUNTERS, size, (void**)&p_num_max)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (num_enabled >= *p_num_max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t GpuCounterBlock::_getNumOfEnabledCounters() {
|
||||
uint32_t cnt = 0;
|
||||
GpuCounterList::iterator it = cntr_list_.begin();
|
||||
GpuCounterList::iterator it_end = cntr_list_.end();
|
||||
|
||||
for (; it != it_end; it++) {
|
||||
GpuCounter* p_cntr = (*it);
|
||||
bool is_enabled;
|
||||
is_enabled = p_cntr->isEnabled();
|
||||
if (is_enabled) {
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
std::string GpuCounterBlock::getErrorString(int error) {
|
||||
if ((error >= 0) && (error < kHsaCounterBlockErrorCodeMaxError)) {
|
||||
std::string err_string(error_string[error]);
|
||||
return err_string;
|
||||
}
|
||||
return "incorrect error code";
|
||||
}
|
||||
|
||||
bool GpuCounterBlock::getParameter(uint32_t param, uint32_t& ret_size, void** pp_data) {
|
||||
return parameter_set_->getParameter(param, ret_size, pp_data);
|
||||
}
|
||||
|
||||
bool GpuCounterBlock::setParameter(uint32_t param, uint32_t param_size, const void* pData) {
|
||||
return parameter_set_->setParameter(param, param_size, pData);
|
||||
}
|
||||
|
||||
bool GpuCounterBlock::getInfo(uint32_t info, uint32_t& ret_size, void** pp_data) {
|
||||
return info_set_->getInfo(info, ret_size, pp_data);
|
||||
}
|
||||
}
|
||||
-70
@@ -1,70 +0,0 @@
|
||||
#ifndef _GPU_COUNTER_GROUP_H_
|
||||
#define _GPU_COUNTER_GROUP_H_
|
||||
|
||||
// This file contains declaration of Sea Island (CI) CounterBlock class.
|
||||
#include "hsa_perf.h"
|
||||
#include "gpu_counter.h"
|
||||
#include "parameter_set.h"
|
||||
#include "info_set.h"
|
||||
#include "gpu_enum.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace pm4_profile {
|
||||
// This class represents one CI hardware block. Each block contains
|
||||
// multiple performance counters.
|
||||
class GpuCounterBlock : public pm4_profile::CounterBlock {
|
||||
public:
|
||||
GpuCounterBlock();
|
||||
~GpuCounterBlock();
|
||||
|
||||
// NOTE [Suravee] : We specify CiPmu as a friend
|
||||
// because the CiPmu needs to be able to setup info of
|
||||
// the counter block.
|
||||
friend class CiPmu;
|
||||
friend class ViPmu;
|
||||
friend class AiPmu;
|
||||
|
||||
std::string getErrorString(int error);
|
||||
|
||||
pm4_profile::Counter* createCounter();
|
||||
|
||||
virtual bool destroyCounter(pm4_profile::Counter* p_cntr);
|
||||
|
||||
virtual bool destroyAllCounters();
|
||||
|
||||
virtual pm4_profile::Counter** getEnabledCounters(uint32_t& num);
|
||||
|
||||
virtual pm4_profile::Counter** getAllCounters(uint32_t& num);
|
||||
|
||||
virtual bool getParameter(uint32_t param, uint32_t& ret_size, void** pp_data);
|
||||
|
||||
virtual bool setParameter(uint32_t param, uint32_t param_size, const void* p_data);
|
||||
|
||||
virtual bool getInfo(uint32_t info, uint32_t& ret_size, void** pp_data);
|
||||
|
||||
protected:
|
||||
void _initCounterBlockType();
|
||||
|
||||
bool setInfo(GPU_BLK_INFOS blk_info, uint32_t size, void* data);
|
||||
|
||||
hsa_ext_tools_counter_block_type_t block_type_;
|
||||
|
||||
private:
|
||||
bool _checkMaxNumOfCounters();
|
||||
|
||||
uint32_t _getNumOfEnabledCounters();
|
||||
|
||||
pm4_profile::ParameterSet* parameter_set_;
|
||||
pm4_profile::InfoSet* info_set_;
|
||||
GpuCounterList cntr_list_;
|
||||
uint32_t error_code_;
|
||||
|
||||
// Pointer of buffer to store counter list
|
||||
pm4_profile::Counter** pp_cntrs_;
|
||||
};
|
||||
|
||||
} // pm4_profile
|
||||
|
||||
#endif // _GPU_COUNTER_GROUP_H_
|
||||
@@ -1,65 +0,0 @@
|
||||
#ifndef _GPU_ENUM_H_
|
||||
#define _GPU_ENUM_H_
|
||||
|
||||
namespace pm4_profile {
|
||||
|
||||
// Enumeration containing GPU hardware block information
|
||||
enum GPU_BLK_INFOS {
|
||||
GPU_BLK_INFO_BLOCK_NAME,
|
||||
GPU_BLK_INFO_ID,
|
||||
GPU_BLK_INFO_MAX_SHADER_ENGINE_COUNT,
|
||||
GPU_BLK_INFO_MAX_SHADER_ARRAY_COUNT,
|
||||
GPU_BLK_INFO_MAX_INSTANCE_COUNT,
|
||||
GPU_BLK_INFO_CONTROL_METHOD,
|
||||
GPU_BLK_INFO_MAX_EVENT_ID,
|
||||
GPU_BLK_INFO_MAX_SIMULTANEOUS_COUNTERS,
|
||||
GPU_BLK_INFO_MAX_STREAMING_COUNTERS,
|
||||
GPU_BLK_INFO_SHARED_HW_COUNTERS,
|
||||
GPU_BLK_INFO_HAS_FILTERS,
|
||||
|
||||
// Trace-specific stuff
|
||||
GPU_TRC_BLK_INFO_BUFFER_SIZE,
|
||||
GPU_TRC_BLK_INFO_BUFFER_WRITE_POINTER_OFFSET,
|
||||
GPU_TRC_BLK_INFO_BUFFER_WRAPPED,
|
||||
GPU_TRC_BLK_INFO_DATA_SIZE_ESTIMATE,
|
||||
GPU_TRC_BLK_INFO_DATA_POINTER,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Trace buffer parameters
|
||||
*/
|
||||
enum GPU_BLK_PARAMS {
|
||||
// Allows user to specify the size of the trace buffers.
|
||||
GPU_BLK_PARAM_TRACE_BUFFER_SIZE,
|
||||
|
||||
// If we decide to implement this functionality, this will allow the user
|
||||
// to specify the number of trace buffers to create.
|
||||
GPU_BLK_PARAM_TRACE_BUFFER_ARRAY,
|
||||
|
||||
// Specifies whether a new trace buffer should be used for each cmd buffer.
|
||||
// This allows for better correlation of data back to the host application
|
||||
// If this is enabled, and the user does not explicitly specify a
|
||||
// TRACE_BUFFER_ARRAY, then the driver should automatically allocate
|
||||
// additional buffers as needed so that as much of the application
|
||||
// can be traced as possible, until the PerfExperiment is ended.
|
||||
// If a TRACE_BUFFER_ARRAY is specified, then only as many buffers
|
||||
// as specified should be created. If more cmd buffers get submitted
|
||||
// than there are trace buffers, then the later cmd buffers should
|
||||
// not be traced.
|
||||
GPU_BLK_PARAM_TRACE_NEW_BUFFER_ON_SUBMIT,
|
||||
};
|
||||
|
||||
|
||||
// Enumeration containing GPU counter parameters
|
||||
enum GPU_CNTR_PARAMS {
|
||||
GPU_CNTR_PARAM_SHADERENGINE_ID,
|
||||
GPU_CNTR_PARAM_SHADERARRAY_ID,
|
||||
GPU_CNTR_PARAM_INSTANCE_ID,
|
||||
GPU_CNTR_PARAM_EVENT_SELECT_ID,
|
||||
GPU_CNTR_PARAM_SIMD_MASK,
|
||||
GPU_CNTR_PARAM_PERF_MODE,
|
||||
GPU_CNTR_PARAM_TRACE_TYPE,
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -1,436 +0,0 @@
|
||||
#ifndef _HSA_PERF_H_
|
||||
#define _HSA_PERF_H_
|
||||
|
||||
#include "rocr_profiler.h"
|
||||
|
||||
#if !defined(AMD_AMP_HSA_INCLUDES)
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
namespace pm4_profile {
|
||||
class Pmu;
|
||||
class Counter;
|
||||
class CounterBlock;
|
||||
class TraceGroup;
|
||||
class CommandWriter;
|
||||
class DefaultCmdBuf;
|
||||
|
||||
|
||||
// @brief This is an abstract class for defining a CounterBlock. Each
|
||||
// CounterBlock contains a set of Counters that often belong to the
|
||||
// same functional unit
|
||||
//
|
||||
// For AMD GPU, this can represent blocks of Counters in each HW block
|
||||
// (e.g. SQ, SQI, CP, etc.).
|
||||
// For AMD CPU, this can represent blocks of core PMCs, NB PMCs, L2I PMCs
|
||||
// on each CPU device
|
||||
//
|
||||
// Generally, CounterBlocks are created and initialized by the \ref Pmu class.
|
||||
// Users can query them by calling \ref Pmu::getAllCounterBlocks() or
|
||||
// \ref Pmu::getCounterBlockById(). A CounterBlock is enabled if it contains
|
||||
// enabled Counters in the block.
|
||||
//
|
||||
// Users can manage Counters in each GounterBlock (e.g. create, destroy,
|
||||
// enable and disable). To specify a Counter, users simply call \ref
|
||||
// createCounter. Then it can be enabled or disabled using \ref
|
||||
// Counter::setEnable. When a Counter is enabled, it is checked against the
|
||||
// CounterBlock checks to make sure that the enabled-counter is valid and is
|
||||
// not conflicting with the current Counters in the block.
|
||||
class CounterBlock {
|
||||
public:
|
||||
typedef enum HsaCounterBlockErrorCode {
|
||||
// Generic CounterBlock error
|
||||
kHsaCounterBlockErrorCodeNoError = 0x0,
|
||||
|
||||
// Generic CounterBlock error
|
||||
kHsaCounterBlockErrorCodeGenericError,
|
||||
|
||||
// The maximum number of Counters in the block is reached.
|
||||
kHsaCounterBlockErrorCodeMaxNumCounterReached,
|
||||
|
||||
// The counter does not belong to this block.
|
||||
kHsaCounterBlockErrorCodeUnknownCounter,
|
||||
|
||||
// The counter does not belong to this block.
|
||||
kHsaCounterBlockErrorCodeMaxError
|
||||
} HsaCounterBlockErrorCode;
|
||||
|
||||
// Destructor of CounterBlock.
|
||||
virtual ~CounterBlock() {}
|
||||
|
||||
// Given and error number reported from getLastError or returned from a
|
||||
// function call, retreive the corresponding stl string.
|
||||
// @param[in] error The error corresponding to a call to getLastError
|
||||
// or a return code from a function call.
|
||||
// Return An stl string representing a text corresponding to the error
|
||||
// number.
|
||||
// If invalid error code is given, the returned string is empty.
|
||||
virtual std::string getErrorString(int error) = 0;
|
||||
|
||||
// Create an Counter object return a pointer to caller.
|
||||
// Return On success, this function returns a pointer to Counter
|
||||
// On failure, this function returns NULL
|
||||
// Possible error codes are:
|
||||
// kHSAPerfErrorCodesUnmodifiableState
|
||||
// kHsaCounterBlockErrorCodeMaxNumCounterReached
|
||||
virtual Counter* createCounter() = 0;
|
||||
|
||||
// Destroy the Counter. The CounterBlock which owns the Counter must be in
|
||||
// disabled state.
|
||||
// Return true or false
|
||||
// Possible error codes are:
|
||||
// kHSAPerfErrorCodesInvalidAargs
|
||||
// kHSAPerfErrorCodesUnmodifiableState
|
||||
// kHsaCounterBlockErrorCodeUnknownCounter
|
||||
virtual bool destroyCounter(Counter* p_counter) = 0;
|
||||
|
||||
// Destroy all counters in the block. The CounterBlock must be in disable
|
||||
// state.
|
||||
// Return true or false.
|
||||
// Possible error codes are:
|
||||
// kHSAPerfErrorCodesUnmodifiableState
|
||||
virtual bool destroyAllCounters() = 0;
|
||||
|
||||
// Get a list of pointers to the enabled Counters in this CounterBlock.
|
||||
// note The Counter must be created by the same CounterBlock object using
|
||||
// createCounter().
|
||||
// @param[in] num The number of Counter pointers returned.
|
||||
// Return
|
||||
// return a list of pointers to the enabled Counters.
|
||||
// return NULL if no counter is enabled.
|
||||
virtual Counter** getEnabledCounters(uint32_t& num) = 0;
|
||||
|
||||
// Get a list of pointers to the all Counters in this CounterBlock.
|
||||
// note The Counter must be created by the same CounterBlock object using
|
||||
// createCounter().
|
||||
// @param[in] num The number of Counter pointers returned.
|
||||
// Return
|
||||
// return a list of pointers in the CounterBlock.
|
||||
// return NULL if no counter is enabled.
|
||||
virtual Counter** getAllCounters(uint32_t& num) = 0;
|
||||
|
||||
// Query value of the parameter specified by param
|
||||
// @param[in] param The enumeration of parameter to be queried
|
||||
// @param[out] return_size The returned size of data
|
||||
// @param[out] pp_data The pointer to the returned data. The API is
|
||||
// responsible for managing the memory to store the information as specified
|
||||
// by return_size.
|
||||
//
|
||||
// Return true or false
|
||||
// Possible error codes are:
|
||||
// kHSAPerfErrorCodesInvalidParam
|
||||
// kHSAPerfErrorCodesInvalidParamSize
|
||||
// kHSAPerfErrorCodesInvalidParamData
|
||||
virtual bool getParameter(uint32_t param, uint32_t& return_size, void** pp_data) = 0;
|
||||
|
||||
// Set value for the parameter specified by param
|
||||
// @param[in] param The enumeration of parameter to be queried
|
||||
// @param[out] param_size The size of data
|
||||
// @param[out] p_data The pointer to the data to be set. Users are responsible
|
||||
// for deallocating the memory of p_data after calling the API.
|
||||
// Return true or false
|
||||
// Possible error codes are:
|
||||
// kHSAPerfErrorCodesUnmodifiableState
|
||||
// kHSAPerfErrorCodesInvalidParam
|
||||
// kHSAPerfErrorCodesInvalidParamSize
|
||||
// kHSAPerfErrorCodesInvalidParamData
|
||||
virtual bool setParameter(uint32_t param, uint32_t param_size, const void* p_data) = 0;
|
||||
|
||||
// Query value of the information specified by info
|
||||
// @param[in] info The enumeration of information to be queried
|
||||
// @param[out] Return_size The returned size of data
|
||||
// @param[out] pp_data The pointer to the returned data
|
||||
// Return true or false
|
||||
// Possible error codes are:
|
||||
// kHSAPerfErrorCodesInvalidInfo
|
||||
// kHSAPerfErrorCodesInvalidInfoSize
|
||||
// kHSAPerfErrorCodesInvalidInfoData
|
||||
virtual bool getInfo(uint32_t info, uint32_t& return_size, void** pp_data) = 0;
|
||||
}; // class CounterBlock
|
||||
|
||||
|
||||
// This is an abstract class for defining a TraceGroup. TraceGroup inherits
|
||||
// CounterBlock and add interfaces for managing trace buffer. It also supports
|
||||
// user-data insertion into trace. This allows users to insert arbitary data
|
||||
// (e.g. markers) into trace which and can be used to correlating a specific
|
||||
// events to the collected trace data.
|
||||
class TraceGroup : public CounterBlock {
|
||||
public:
|
||||
typedef enum HsaTraceGroupErrorCode {
|
||||
// Generic TraceGroup error
|
||||
HsaTraceGroupErrorCodeGenericError = 0x100,
|
||||
} HsaTraceGroupErrorCode;
|
||||
|
||||
// Destructor of TraceGroup.
|
||||
virtual ~TraceGroup() {}
|
||||
|
||||
// Obtains the number of buffers which were collected as part of
|
||||
// the trace.
|
||||
// Return The number of collected buffers.
|
||||
virtual uint32_t getCollectedBufferCount() = 0;
|
||||
|
||||
// Locks a trace buffer for host access.
|
||||
// @param[in] buffer_id The index of the buffer to be locked.
|
||||
// Return true or false
|
||||
virtual bool lock(uint32_t buffer_id) = 0;
|
||||
|
||||
// Unlock a trace buffer that was previously locked.
|
||||
// @param[in] buffer_id The index of the buffer to be unlocked.
|
||||
// Return true or false
|
||||
virtual bool unlock(uint32_t buffer_id) = 0;
|
||||
|
||||
// Inserts data (e.g. trace marker) into the trace.
|
||||
// @param[in] type The type of data to be inserted.
|
||||
// @param[in] p_data The data to be inserted.
|
||||
// @param[in] data_size The size of data to be inserted.
|
||||
// Return true or false
|
||||
virtual bool insertUserData(uint32_t type, void* p_data, uint32_t data_size) = 0;
|
||||
}; // class TraceGroup
|
||||
|
||||
|
||||
// This is an abstract class for defining a performance Counter.
|
||||
// Users can obtain a Counter from \ref CounterBlock::createCounter().
|
||||
// Once obtained, users can set up Counter parameters, and enable it using
|
||||
// \ref Counter::setEnable().
|
||||
//
|
||||
// There are several types of Counter as defined in \ref
|
||||
// HsaCounterBlockTypeMask.
|
||||
// Only the supported Counter type can be added to the CounterBlock.
|
||||
//
|
||||
// Each Counter can store Counter-specific parameters. The Counter is used to
|
||||
// specify types of event to be counted.
|
||||
class Counter {
|
||||
public:
|
||||
typedef enum HsaCounterErrorCode {
|
||||
// Generic Counter error
|
||||
kHsaCounterErrorCodeNoError = 0x0,
|
||||
|
||||
// Generic Counter error
|
||||
kHsaCounterErrorCodeGenericError = 0x1,
|
||||
|
||||
// Counter already error
|
||||
kHsaCounterErrorCodeAlreadySet = 0x2,
|
||||
|
||||
// Counter result is not ready.
|
||||
kHsaCounterErrorCodeResultNotReady = 0x3,
|
||||
|
||||
// Max counter error num
|
||||
kHsaCounterErrorCodeMax,
|
||||
} HsaCounterErrorCode;
|
||||
|
||||
// Destructor of Counter
|
||||
virtual ~Counter() {}
|
||||
|
||||
// Retrieve the last error code generated. This should be checked when
|
||||
// values returned are NULL or void.
|
||||
// Return an integer corresponding to the last error reported.
|
||||
virtual int getLastError() = 0;
|
||||
|
||||
// Given and error number reported from getLastError or returned from a
|
||||
// function call, retreive the corresponding stl string.
|
||||
// @param[in] error The error corresponding to a call to getLastError
|
||||
// or a return code from a function call.
|
||||
// Return An stl string representing a text corresponding to the error
|
||||
// number. If invalid error code is given, the returned string is empty.
|
||||
virtual std::string getErrorString(int error) = 0;
|
||||
|
||||
// Get the \ref CounterBlock which owns this counter.
|
||||
// Return
|
||||
// On success, it returns a pointer to the CounterBlock.
|
||||
// On Failure, it returns NULL.
|
||||
virtual CounterBlock* getCounterBlock() = 0;
|
||||
|
||||
// Enable or disable the Counter.
|
||||
// @param[in] b Set to true to enable the CounterBlock.
|
||||
// Return
|
||||
// return true when successfully set the state.
|
||||
// return false otherwise.
|
||||
// In case of the current state already is set to the specified value,
|
||||
// the API returns true.
|
||||
// Possible error codes are:
|
||||
// kHSAPerfErrorCodesUnmodifiableState
|
||||
virtual bool setEnable(bool b) = 0;
|
||||
|
||||
// Return the current state of the Counter.
|
||||
// Return true or false
|
||||
virtual bool isEnabled() = 0;
|
||||
|
||||
// Return the status of this Counter whether the result is available.
|
||||
// Return true or false
|
||||
virtual bool isResultReady() = 0;
|
||||
|
||||
// Query Counter result
|
||||
// note Must be implemented by derived classes
|
||||
// @param[out] p_result The pointer containing the returned result.
|
||||
// Return true or false
|
||||
// Possible error codes are:
|
||||
// kHSAPerfErrorCodesInvalidAargs
|
||||
// kHsaCounterErrorCodeResultNotReady
|
||||
virtual bool getResult(uint64_t* p_result) = 0;
|
||||
|
||||
// Query value of the parameter specified by param
|
||||
// @param[in] param The enumeration of parameter to be queried
|
||||
// @param[out] Return_size The returned size of data
|
||||
// @param[out] pp_data The pointer to the returned data. The API is
|
||||
// responsible for managing the memory to store the information as
|
||||
// specified by return_size.
|
||||
// Return true or false
|
||||
// Possible error codes are:
|
||||
// kHSAPerfErrorCodesInvalidParam
|
||||
// kHSAPerfErrorCodesInvalidParamSize
|
||||
// kHSAPerfErrorCodesInvalidParamData
|
||||
virtual bool getParameter(uint32_t param, uint32_t& return_size, void** pp_data) = 0;
|
||||
|
||||
// Set value for the parameter specified by param
|
||||
// @param[in] param The enumeration of parameter to be queried
|
||||
// @param[out] param_size The size of data
|
||||
// @param[out] p_data The pointer to the data to be set. Users are responsible
|
||||
// for deallocating the memory of p_data after calling the API.
|
||||
// Return true or false
|
||||
// Possible error codes are:
|
||||
// kHSAPerfErrorCodesUnmodifiableState
|
||||
// kHSAPerfErrorCodesInvalidParam
|
||||
// kHSAPerfErrorCodesInvalidParamSize
|
||||
// kHSAPerfErrorCodesInvalidParamData
|
||||
virtual bool setParameter(uint32_t param, uint32_t param_size, const void* p_data) = 0;
|
||||
}; // class Counter
|
||||
|
||||
class Pmu {
|
||||
public:
|
||||
// Enumeration of Pmu error codes
|
||||
typedef enum HsaPmuErrorCode {
|
||||
// Generic PMU error
|
||||
kHsaPmuErrorCodeNoError = 0x0,
|
||||
|
||||
// Unknown CounterBlock ID
|
||||
kHsaPmuErrorCodeUnknownCounterBlockId,
|
||||
|
||||
// No CounterBlock exists
|
||||
kHsaPmuErrorCodeNoCounterBlock,
|
||||
|
||||
// The previously operation is not valid. This could be due to
|
||||
// invalid transition from the current state.
|
||||
kHsaPmuErrorCodeInvalidOperation,
|
||||
|
||||
// PMU is not currently available (e.g. PMU is currently
|
||||
// in-used by others)
|
||||
kHsaPmuErrorCodeNotAvailable,
|
||||
|
||||
// PMU is not currently available (e.g. PMU is currently
|
||||
// in-used by others)
|
||||
kHsaPmuErrorCodeErrorState,
|
||||
|
||||
// PMU result is timeout
|
||||
kHsaPmuErrorCodeTimeOut,
|
||||
|
||||
// Max error count
|
||||
kHsaPmuErrorCodeMax
|
||||
} HsaPmuErrorCode;
|
||||
|
||||
// Destructor of PMU.
|
||||
// note This stops the performance counters if running and releases
|
||||
// any resources used by the PMU.
|
||||
virtual ~Pmu() {}
|
||||
|
||||
// Retrieve the last error code generated. This should be checked when
|
||||
// values returned are NULL or void.
|
||||
// Return an integer corresponding to the last error reported.
|
||||
virtual int getLastError() = 0;
|
||||
|
||||
// Given and error number reported from getLastError or returned from a
|
||||
// function call, retreive the corresponding stl string.
|
||||
// @param[in] error The error corresponding to a call to getLastError
|
||||
// or a return code from a function call.
|
||||
// Return An stl string representing a text corresponding to the error
|
||||
// number. If invalid error code is given, the returned string is empty.
|
||||
virtual std::string getErrorString(int error) = 0;
|
||||
|
||||
// Get CounterBlock from Id
|
||||
// @param[in] id ID of the target CounterBlock
|
||||
// Return
|
||||
// On success, it returns a pointer to specified CounterBlock.
|
||||
// On Failure, it returns NULL.
|
||||
// Possible error codes are:
|
||||
// kHsaPmuErrorCodeUnknownCounterBlockId.
|
||||
virtual CounterBlock* getCounterBlockById(uint32_t id) = 0;
|
||||
|
||||
// Get all available CounterBlock
|
||||
// @param[out] num_block The returned number of CounterBlocks
|
||||
// Return On success, it returns an array of CounterBlock pointers.
|
||||
// On Failure, it returns NULL.
|
||||
virtual CounterBlock** getAllCounterBlocks(uint32_t& num_block) = 0;
|
||||
|
||||
// Get current PMU profiling state.
|
||||
// Return The PMU profiling state as defined in \ref PMU_PROFILE_STATES
|
||||
virtual rocr_pmu_state_t getCurrentState() = 0;
|
||||
|
||||
// Start profiling on the PMU.
|
||||
// @param[in] reset_counter indicates whether reset counter before
|
||||
// recording. Default is reset counters.
|
||||
// note This function must be implemented by children classes.
|
||||
// Return true or false
|
||||
// Possible error codes are:
|
||||
// kHsaPmuErrorCodeInvalidOperation
|
||||
// kHsaPmuErrorCodeNotAvailable
|
||||
virtual bool begin(DefaultCmdBuf* cmdBuff, CommandWriter* cmdWriter, bool reset = true) = 0;
|
||||
|
||||
// Stop profiling on the PMU.
|
||||
// note This function must be called after \ref begin().
|
||||
// note This function must be implemented by children classes.
|
||||
// Return true or false
|
||||
// Possible error codes are:
|
||||
// kHsaPmuErrorCodeInvalidOperation
|
||||
virtual bool end(DefaultCmdBuf* cmdBuff, CommandWriter* cmdWriter) = 0;
|
||||
|
||||
// Initializes the handle of buffer used to collect PMC data
|
||||
// @param pmcBuffer The buffer pointer
|
||||
// @param cmdBufSz Size in terms of bytes
|
||||
virtual bool setPmcDataBuff(uint8_t* pmcBuffer, uint32_t pmcBuffSz) = 0;
|
||||
|
||||
// Query value of the parameter specified by param
|
||||
// @param[in] param The enumeration of parameter to be queried
|
||||
// @param[out] Return_size The returned size of data
|
||||
// @param[out] pp_data The pointer to the returned data. The API is
|
||||
// responsible for managing the memory to store the information as
|
||||
// specified by return_size.
|
||||
// Return true or false
|
||||
// Possible error codes are:
|
||||
// kHSAPerfErrorCodesInvalidParam
|
||||
// kHSAPerfErrorCodesInvalidParamSize
|
||||
// kHSAPerfErrorCodesInvalidParamData
|
||||
virtual bool getParameter(uint32_t param, uint32_t& return_size, void** pp_data) = 0;
|
||||
|
||||
// Set value for the parameter specified by param
|
||||
// @param[in] param The enumeration of parameter to be queried
|
||||
// @param[out] param_size The size of data
|
||||
// @param[out] p_data The pointer to the data to be set. Users are responsible
|
||||
// for deallocating the memory of p_data after calling the API.
|
||||
// Return true or false
|
||||
// Possible error codes are:
|
||||
// kHSAPerfErrorCodesUnmodifiableState
|
||||
// kHSAPerfErrorCodesInvalidParam
|
||||
// kHSAPerfErrorCodesInvalidParamSize
|
||||
// kHSAPerfErrorCodesInvalidParamData
|
||||
virtual bool setParameter(uint32_t param, uint32_t param_size, const void* p_data) = 0;
|
||||
|
||||
// Query value of the information specified by info
|
||||
// @param[in] info The enumeration of information to be queried
|
||||
// @param[out] Return_size The returned size of data
|
||||
// @param[out] pp_data The pointer to the returned data
|
||||
// Return true or false
|
||||
// Possible error codes are:
|
||||
// kHSAPerfErrorCodesInvalidInfo
|
||||
// kHSAPerfErrorCodesInvalidInfoSize
|
||||
// kHSAPerfErrorCodesInvalidInfoData
|
||||
virtual bool getInfo(uint32_t info, uint32_t& return_size, void** pp_data) = 0;
|
||||
|
||||
// Returns number of shader engines per block
|
||||
// for the blocks featured shader engines instancing
|
||||
virtual uint32_t getNumSe() = 0;
|
||||
|
||||
}; // class Pmu
|
||||
} // pm4_profile
|
||||
#endif // _HSA_PERF_H_
|
||||
@@ -1,74 +0,0 @@
|
||||
#include "info_set.h"
|
||||
#include "var_data.h"
|
||||
using namespace std;
|
||||
|
||||
namespace pm4_profile {
|
||||
InfoSet::InfoSet() {
|
||||
releaseParameters();
|
||||
info_table_.clear();
|
||||
p_data_ = NULL;
|
||||
}
|
||||
|
||||
InfoSet::~InfoSet() {
|
||||
releaseParameters();
|
||||
info_table_.clear();
|
||||
free(p_data_);
|
||||
p_data_ = NULL;
|
||||
}
|
||||
|
||||
bool InfoSet::setInfo(uint32_t info, uint32_t info_size, void* p_data) {
|
||||
if (info_table_.end() != info_table_.find(info)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VarData data;
|
||||
if (!data.set(info_size, p_data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
info_table_.insert(VarDataMap::value_type(info, data));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InfoSet::getInfo(uint32_t info, uint32_t& ret_size, void** pp_data) {
|
||||
if (!pp_data || (0 == info_table_.size())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VarDataMap::iterator it = info_table_.find(info);
|
||||
if (it == info_table_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int size = it->second.getSize();
|
||||
if (size == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
free(p_data_);
|
||||
p_data_ = NULL;
|
||||
|
||||
p_data_ = malloc(size);
|
||||
if (!p_data_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*pp_data = p_data_;
|
||||
|
||||
ret_size = info_table_[info].get(size, *pp_data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void InfoSet::releaseParameters() {
|
||||
VarDataMap::iterator it = info_table_.begin();
|
||||
VarDataMap::iterator table_end = info_table_.end();
|
||||
|
||||
for (; it != table_end; it++) {
|
||||
it->second.clear();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
} // pm4_profile
|
||||
@@ -1,48 +0,0 @@
|
||||
#ifndef _INFO_SET_H_
|
||||
#define _INFO_SET_H_
|
||||
|
||||
// This file contains declaration of IInfoSet class.
|
||||
#include "hsa_perf.h"
|
||||
#include "var_data.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace pm4_profile {
|
||||
// An abstract class defining a container to hold a information data set
|
||||
// (e.g. PMU info, CounterGroup info, etc.). Unlike \ref IParameterSet,
|
||||
// This class allows only the children of the class to set the information.
|
||||
class InfoSet {
|
||||
public:
|
||||
// IInfoSet constructor
|
||||
InfoSet();
|
||||
|
||||
// IInfoSet destructor
|
||||
virtual ~InfoSet();
|
||||
|
||||
// Query value of the information specified by info
|
||||
// @param[in] info The enumeration of information to be queried
|
||||
// @param[out] ret_size The returned size of data
|
||||
// @param[out] pp_data The pointer to the returned data
|
||||
// /return true or false
|
||||
bool getInfo(uint32_t info, uint32_t& ret_size, void** pp_data);
|
||||
|
||||
// Set value for the information specified by info
|
||||
// @param[in] info The enumeration of information to be queried
|
||||
// @param[out] info_size The size of data
|
||||
// @param[out] p_data The pointer to the data to be set
|
||||
// /return true or false
|
||||
bool setInfo(uint32_t info, uint32_t info_size, void* p_data);
|
||||
|
||||
private:
|
||||
// Remove all data in the parameter table
|
||||
void releaseParameters();
|
||||
|
||||
// InfoSet property: The info table
|
||||
VarDataMap info_table_;
|
||||
|
||||
// Pointer to the buffer used in getInfo
|
||||
void* p_data_;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
-74
@@ -1,74 +0,0 @@
|
||||
#include "parameter_set.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace pm4_profile {
|
||||
ParameterSet::ParameterSet() {
|
||||
releaseParameters();
|
||||
param_table_.clear();
|
||||
p_data_ = NULL;
|
||||
}
|
||||
|
||||
ParameterSet::~ParameterSet() {
|
||||
releaseParameters();
|
||||
param_table_.clear();
|
||||
free(p_data_);
|
||||
p_data_ = NULL;
|
||||
}
|
||||
|
||||
bool ParameterSet::setParameter(uint32_t param, uint32_t param_size, const void* p_data) {
|
||||
if (param_table_.end() != param_table_.find(param)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VarData data;
|
||||
if (!data.set(param_size, p_data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
param_table_.insert(VarDataMap::value_type(param, data));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParameterSet::getParameter(uint32_t param, uint32_t& ret_size, void** pp_data) {
|
||||
if (!pp_data || (0 == param_table_.size())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VarDataMap::iterator it = param_table_.find(param);
|
||||
if (it == param_table_.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int size = it->second.getSize();
|
||||
if (size == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// for NULL pointer, free does nothing
|
||||
free(p_data_);
|
||||
p_data_ = malloc(size);
|
||||
if (!p_data_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// store the pointer to be freed
|
||||
*pp_data = p_data_;
|
||||
|
||||
ret_size = param_table_[param].get(size, *pp_data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParameterSet::releaseParameters() {
|
||||
VarDataMap::iterator it = param_table_.begin();
|
||||
VarDataMap::iterator table_end = param_table_.end();
|
||||
|
||||
for (; it != table_end; it++) {
|
||||
it->second.clear();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // pm4_profile
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
#ifndef _PARAMETER_SET_H_
|
||||
#define _PARAMETER_SET_H_
|
||||
|
||||
/*!
|
||||
\note This file contains declaration of IParameterSet class.
|
||||
*/
|
||||
#include "hsa_perf.h"
|
||||
#include "var_data.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace pm4_profile {
|
||||
/*!
|
||||
A class defining a container to hold parameter data set
|
||||
(e.g. PMU parameter, CounterGroup parameter, etc.).
|
||||
*/
|
||||
class ParameterSet {
|
||||
public:
|
||||
/*!
|
||||
Enumeration containing types of parameters
|
||||
*/
|
||||
enum parameter {
|
||||
PARAM_MAX,
|
||||
};
|
||||
|
||||
/*! IParameterSet constructor */
|
||||
ParameterSet();
|
||||
|
||||
/*! IParameterSet destructor */
|
||||
virtual ~ParameterSet();
|
||||
|
||||
/*!
|
||||
Query value of the parameter specified by param
|
||||
@param[in] param The enumeration of parameter to be queried
|
||||
@param[out] ret_size The returned size of data
|
||||
@param[out] pp_data The pointer to the returned data
|
||||
/return true or false
|
||||
*/
|
||||
bool getParameter(
|
||||
/*in*/ uint32_t param,
|
||||
/*out*/ uint32_t& ret_size,
|
||||
/*out*/ void** pp_data);
|
||||
|
||||
/*!
|
||||
Set value for the parameter specified by param
|
||||
@param[in] param The enumeration of parameter to be queried
|
||||
@param[out] param_size The size of data
|
||||
@param[out] p_data The pointer to the data to be set
|
||||
/return true or false
|
||||
*/
|
||||
bool setParameter(
|
||||
/*in*/ uint32_t param,
|
||||
/*in*/ uint32_t param_size,
|
||||
/*in*/ const void* p_data);
|
||||
|
||||
private:
|
||||
/*!
|
||||
Remove all data in the parameter table
|
||||
*/
|
||||
bool releaseParameters();
|
||||
|
||||
/*!
|
||||
IParameterSet property: The parameter table
|
||||
*/
|
||||
VarDataMap param_table_;
|
||||
|
||||
/*!
|
||||
Pointer to the buffer used in getParameter
|
||||
*/
|
||||
void* p_data_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // _PARAMETER_SET_H_
|
||||
+92
@@ -0,0 +1,92 @@
|
||||
#ifndef _HSA_PERF_H_
|
||||
#define _HSA_PERF_H_
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace pm4_profile {
|
||||
class DefaultCmdBuf;
|
||||
class CommandWriter;
|
||||
|
||||
typedef std::vector<uint32_t> CountersVec;
|
||||
typedef std::map<uint32_t, CountersVec> CountersMap;
|
||||
|
||||
class Pmu {
|
||||
public:
|
||||
// Enumeration of Pmu error codes
|
||||
typedef enum ErrorCode {
|
||||
// Generic PMU error
|
||||
kErrorCodeNoError = 0x0,
|
||||
|
||||
// Unknown CounterBlock ID
|
||||
kErrorCodeUnknownCounterBlockId,
|
||||
|
||||
// No CounterBlock exists
|
||||
kErrorCodeNoCounterBlock,
|
||||
|
||||
// The previously operation is not valid. This could be due to
|
||||
// invalid transition from the current state.
|
||||
kErrorCodeInvalidOperation,
|
||||
|
||||
// PMU is not currently available (e.g. PMU is currently
|
||||
// in-used by others)
|
||||
kErrorCodeNotAvailable,
|
||||
|
||||
// PMU is not currently available (e.g. PMU is currently
|
||||
// in-used by others)
|
||||
kErrorCodeErrorState,
|
||||
|
||||
// PMU result is timeout
|
||||
kErrorCodeTimeOut,
|
||||
|
||||
// Max error count
|
||||
kErrorCodeMax
|
||||
} ErrorCode;
|
||||
|
||||
// Destructor of PMU.
|
||||
// note This stops the performance counters if running and releases
|
||||
// any resources used by the PMU.
|
||||
virtual ~Pmu() {}
|
||||
|
||||
// Retrieve the last error code generated. This should be checked when
|
||||
// values returned are NULL or void.
|
||||
// Return an integer corresponding to the last error reported.
|
||||
virtual int getLastError() = 0;
|
||||
|
||||
// Given and error number reported from getLastError or returned from a
|
||||
// function call, retreive the corresponding stl string.
|
||||
// @param[in] error The error corresponding to a call to getLastError
|
||||
// or a return code from a function call.
|
||||
// Return An stl string representing a text corresponding to the error
|
||||
// number. If invalid error code is given, the returned string is empty.
|
||||
virtual std::string getErrorString(int error) = 0;
|
||||
|
||||
// Start profiling on the PMU.
|
||||
// @param[in] reset_counter indicates whether reset counter before
|
||||
// recording. Default is reset counters.
|
||||
// note This function must be implemented by children classes.
|
||||
// Return true or false
|
||||
// Possible error codes are:
|
||||
// kErrorCodeInvalidOperation
|
||||
// kErrorCodeNotAvailable
|
||||
virtual void begin(DefaultCmdBuf* cmdBuff, CommandWriter* cmdWriter,
|
||||
const CountersMap& countersMap) = 0;
|
||||
|
||||
// Stop profiling on the PMU.
|
||||
// note This function must be called after \ref begin().
|
||||
// note This function must be implemented by children classes.
|
||||
// Return true or false
|
||||
// Possible error codes are:
|
||||
// kErrorCodeInvalidOperation
|
||||
virtual uint32_t end(DefaultCmdBuf* cmdBuff, CommandWriter* cmdWriter,
|
||||
const CountersMap& countersMap, void* dataBuff) = 0;
|
||||
|
||||
// Returns number of shader engines per block
|
||||
// for the blocks featured shader engines instancing
|
||||
virtual uint32_t getNumSe() = 0;
|
||||
|
||||
}; // class Pmu
|
||||
} // pm4_profile
|
||||
#endif // _HSA_PERF_H_
|
||||
-254
@@ -1,254 +0,0 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The University of Illinois/NCSA
|
||||
// Open Source License (NCSA)
|
||||
//
|
||||
// Copyright (c) 2014-2015, Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
// Developed by:
|
||||
//
|
||||
// AMD Research and AMD HSA Software Development
|
||||
//
|
||||
// Advanced Micro Devices, Inc.
|
||||
//
|
||||
// www.amd.com
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal with 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:
|
||||
//
|
||||
// - Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimers.
|
||||
// - Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimers in
|
||||
// the documentation and/or other materials provided with the distribution.
|
||||
// - Neither the names of Advanced Micro Devices, Inc,
|
||||
// nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this Software without specific prior written
|
||||
// permission.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS WITH THE SOFTWARE.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _ROCR_PROFILER_H_
|
||||
#define _ROCR_PROFILER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
#ifdef __GNUC__
|
||||
#define HSA_TOOLS_API __attribute__((dllexport))
|
||||
#else
|
||||
#define HSA_TOOLS_API __declspec(dllexport) // Note: actually gcc seems
|
||||
// to also supports this
|
||||
// syntax.
|
||||
#endif
|
||||
#ifndef DLL_LOCAL
|
||||
#define DLL_LOCAL
|
||||
#endif
|
||||
|
||||
#else // defined _WIN32 || defined __CYGWIN__
|
||||
#if __GNUC__ >= 4
|
||||
#define HSA_TOOLS_API __attribute__((visibility("default")))
|
||||
#ifndef DLL_LOCAL
|
||||
#define DLL_LOCAL __attribute__((visibility("hidden")))
|
||||
#endif
|
||||
#else
|
||||
#define HSA_TOOLS_API
|
||||
#ifndef DLL_LOCAL
|
||||
#define DLL_LOCAL
|
||||
#endif
|
||||
#endif
|
||||
#endif // defined _WIN32 || defined __CYGWIN__
|
||||
|
||||
//---------------------------------------------------------------------------//
|
||||
// @brief Enumeration of various information that is set for a counter. //
|
||||
// @detail This enumeration defines the various counter info that could be //
|
||||
// used in a counter. This is used by a counter object to specify //
|
||||
// its type and other conditions that are needed to retrieve a //
|
||||
// counter value. //
|
||||
//---------------------------------------------------------------------------//
|
||||
typedef enum hsa_ext_tools_counter_parameter_s {
|
||||
// Event index of a counter
|
||||
HSA_EXT_TOOLS_COUNTER_PARAMETER_EVENT_INDEX = 0,
|
||||
|
||||
// Simd mask of a counter
|
||||
HSA_EXT_TOOLS_COUNTER_PARAMETER_SIMD_MASK = 1,
|
||||
|
||||
// Shader engine mask of a counter
|
||||
HSA_EXT_TOOLS_COUNTER_PARAMETER_SHADER_MASK = 2,
|
||||
|
||||
// Max counter info index
|
||||
HSA_EXT_TOOLS_COUNTER_PARAMETER_INFO_MAX
|
||||
} hsa_ext_tools_counter_parameter_t;
|
||||
|
||||
//---------------------------------------------------------------------------//
|
||||
// @brief Enumeration of counter block type mask //
|
||||
// @details This enumeration define the bit mask representing types of //
|
||||
// counter broup supported by HSA. This is used by counter block object to //
|
||||
// specify its type. //
|
||||
//---------------------------------------------------------------------------//
|
||||
typedef enum hsa_ext_tools_counter_block_type_s {
|
||||
// Unknown counter block type
|
||||
HSA_EXT_TOOLS_COUNTER_BLOCK_TYPE_UNKNOWN = 0,
|
||||
|
||||
// The CounterBlock of this type can be access at anytime.
|
||||
// note Examples are software Counters and CPU Counters.
|
||||
HSA_EXT_TOOLS_COUNTER_BLOCK_TYPE_SYNC = 1,
|
||||
|
||||
// The CounterBlock type can be access asynchronously.
|
||||
// It is required that the Counter must be stopped
|
||||
// before accessing.
|
||||
HSA_EXT_TOOLS_COUNTER_BLOCK_TYPE_ASYNC = 2,
|
||||
|
||||
// The CounterBlock of this counter block is used for generating
|
||||
// trace.
|
||||
HSA_EXT_TOOLS_COUNTER_BLOCK_TYPE_TRACE = 3,
|
||||
|
||||
// Max CounterBlock type
|
||||
HSA_EXT_TOOLS_COUNTER_BLOCK_TYPE_MAX
|
||||
} hsa_ext_tools_counter_block_type_t;
|
||||
|
||||
//---------------------------------------------------------------------------//
|
||||
// @brief Enumeration of various information that is set for a counter block.//
|
||||
// @detail This enumeration defines the various info that could be used //
|
||||
// in a counter block. This is used by a counter object to specify its type //
|
||||
// and other conditions that are needed for a counter block. //
|
||||
//---------------------------------------------------------------------------//
|
||||
/*
|
||||
typedef enum hsa_ext_tools_counter_block_info_s {
|
||||
// Index of a counter block
|
||||
HSA_EXT_TOOLS_COUNTER_BLOCK_INFO_EVENT_INDEX = 0,
|
||||
|
||||
// Shader bits of a counter block
|
||||
HSA_EXT_TOOLS_COUNTER_BLOCK_INFO_SHADER_BITS = 1,
|
||||
|
||||
// Simd mask of a counter
|
||||
HSA_EXT_TOOLS_COUNTER_BLOCK_INFO_CONTROL_METHOD = 2,
|
||||
|
||||
// Max index of counter block info
|
||||
HSA_EXT_TOOLS_COUNTER_BLOCK_INFO_MAX
|
||||
} hsa_ext_tools_counter_block_info_t;
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------//
|
||||
// Enumeration for the methods used to index into the correct registers. //
|
||||
//---------------------------------------------------------------------------//
|
||||
/*
|
||||
typedef enum hsa_ext_tools_counter_index_method_s {
|
||||
// No index
|
||||
HSA_EXT_TOOLS_COUNTER_INDEX_METHOD_BY_NONE = 0,
|
||||
|
||||
// Index by block instance
|
||||
HSA_EXT_TOOLS_COUNTER_INDEX_METHOD_BY_INSTANCE = 1,
|
||||
|
||||
// Index by shader engine
|
||||
HSA_EXT_TOOLS_COUNTER_INDEX_METHOD_BY_SHADER_ENGINE = 2,
|
||||
|
||||
// Index by shader and instance
|
||||
HSA_EXT_TOOLS_COUNTER_INDEX_METHOD_BY_SHADER_ENGINE_ANDINSTANCE = 3
|
||||
} hsa_ext_tools_counter_index_method_t;
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------//
|
||||
// Enumeration for the HSAPerf generic error codes //
|
||||
//---------------------------------------------------------------------------//
|
||||
/*
|
||||
typedef enum hsa_ext_tools_error_codes_s {
|
||||
// Successful
|
||||
HSA_EXT_TOOLS_ERROR_CODE_OK = 0,
|
||||
|
||||
// Generic error code
|
||||
HSA_EXT_TOOLS_ERROR_CODE_ERROR,
|
||||
|
||||
// Generic invalid HSAPerf API arguments
|
||||
HSA_EXT_TOOLS_ERROR_CODE_INVALID_ARGS,
|
||||
|
||||
// The operation is not permit due to currently in the unmodifiable
|
||||
// HSAPerf state .
|
||||
HSA_EXT_TOOLS_ERROR_CODE_UNMODIFIABLE_STATE,
|
||||
|
||||
// The hsa_ext_tools_set_pmu_parameter() or
|
||||
// hsa_ext_tools_get_pmu_parameter() API contains invalid parameter value.
|
||||
HSA_EXT_TOOLS_ERROR_CODE_INVALID_PARAM,
|
||||
|
||||
// The hsa_ext_tools_set_pmu_parameter() or
|
||||
// hsa_ext_tools_get_pmu_parameter() API contains invalid parameter size
|
||||
// or return size.
|
||||
HSA_EXT_TOOLS_ERROR_CODE_INVALID_PARAM_SIZE,
|
||||
|
||||
// The hsa_ext_tools_set_pmu_parameter() or
|
||||
// hsa_ext_tools_get_pmu_parameter() API contains invalid
|
||||
// pointer (e.g. NULL).
|
||||
HSA_EXT_TOOLS_ERROR_CODE_INVALID_PARAM_DATA,
|
||||
|
||||
// The hsa_ext_tools_get_pmu_info() API contains invalid info value.
|
||||
HSA_EXT_TOOLS_ERROR_CODE_INVALID_INFO,
|
||||
|
||||
// The hsa_ext_tools_get_pmu_info() API contains invalid info
|
||||
// size (e.g. zero).
|
||||
HSA_EXT_TOOLS_ERROR_CODE_INVALID_INFO_SIZE,
|
||||
|
||||
// The hsa_ext_tools_get_pmu_info() API contains invalid
|
||||
// data (e.g. NULL).
|
||||
HSA_EXT_TOOLS_ERROR_CODE_INVALID_INFO_DATA
|
||||
} hsa_ext_tools_error_codes_t;
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------//
|
||||
// Enumeration for Pmu profiling state //
|
||||
//---------------------------------------------------------------------------//
|
||||
typedef enum rocr_pmu_state_s {
|
||||
// Profiling idle. In this state, changes can be made to
|
||||
// the PMU, counter blocks, counters. This state can represent
|
||||
// the moment prior to calling begin or after calling
|
||||
// hsa_ext_tools_pmu_wait_for_completion().
|
||||
ROCR_PMU_STATE_IDLE,
|
||||
|
||||
// Profiling start. In this state, changes cannot be made to
|
||||
// the PMU, counter block, counters. The PMU is collecting
|
||||
// performance counter data. This state represents
|
||||
// the moment after calling hsa_ext_tools_pmu_begin() and before calling
|
||||
// hsa_ext_tools_pmu_end()
|
||||
ROCR_PMU_STATE_START,
|
||||
|
||||
// Profiling stop. In this state, changes cannot be made to
|
||||
// the PMU, counter blocks, Counters. PMU has stopped the
|
||||
// performance counter data collection. However, the result
|
||||
// might not yet be available. This state represents
|
||||
// the moment after calling hsa_ext_tools_pmu_end() and before the call
|
||||
// to hsa_ext_tools_pmu_wait_for_completion() has returned success.
|
||||
ROCR_PMU_STATE_STOP
|
||||
} rocr_pmu_state_t;
|
||||
|
||||
//---------------------------------------------------------------------------//
|
||||
// Opaque pointer to HSA performance monitor unit (PMU) //
|
||||
//---------------------------------------------------------------------------//
|
||||
// typedef void * hsa_ext_tools_pmu_t;
|
||||
|
||||
//---------------------------------------------------------------------------//
|
||||
// Opaque pointer to HSA counter block //
|
||||
//---------------------------------------------------------------------------//
|
||||
// typedef void * hsa_ext_tools_counter_block_t;
|
||||
|
||||
//---------------------------------------------------------------------------//
|
||||
// Opaque pointer to HSA counter //
|
||||
//---------------------------------------------------------------------------//
|
||||
// typedef void * hsa_ext_tools_counter_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#endif // _ROCR_PROFILER_H_
|
||||
@@ -1,48 +0,0 @@
|
||||
#include <string.h>
|
||||
#include "var_data.h"
|
||||
|
||||
namespace pm4_profile {
|
||||
VarData::VarData() {
|
||||
size_ = 0;
|
||||
p_data_ = NULL;
|
||||
}
|
||||
|
||||
VarData::~VarData() {}
|
||||
|
||||
void VarData::clear() {
|
||||
size_ = 0;
|
||||
if (p_data_) {
|
||||
free(p_data_);
|
||||
p_data_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool VarData::set(uint32_t size, const void* p_data) {
|
||||
if (!p_data || (size == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
clear();
|
||||
|
||||
if (NULL == (p_data_ = malloc(size))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(p_data_, p_data, size);
|
||||
size_ = size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t VarData::get(uint32_t size, void* p_data) {
|
||||
if (!p_data || !size || !p_data_ || !size_) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t ret_size = size < size_ ? size : size_;
|
||||
|
||||
memcpy(p_data, p_data_, ret_size);
|
||||
|
||||
return ret_size;
|
||||
}
|
||||
} // pm4_profile
|
||||
@@ -1,65 +0,0 @@
|
||||
#ifndef _VAR_DATA_H_
|
||||
#define _VAR_DATA_H_
|
||||
|
||||
/*!
|
||||
\note This file contains declaration of IVarData class.
|
||||
*/
|
||||
|
||||
#include "hsa_perf.h"
|
||||
|
||||
#include <map>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace pm4_profile {
|
||||
/*!
|
||||
This abstract class implements variable-size storage for information and
|
||||
parameter
|
||||
sets.
|
||||
*/
|
||||
class VarData {
|
||||
public:
|
||||
/*! Constructor for IVarData */
|
||||
VarData();
|
||||
|
||||
/*! Destructor for IVarData */
|
||||
~VarData();
|
||||
|
||||
/*! Deallocate the memory and clean up */
|
||||
void clear();
|
||||
|
||||
/*!
|
||||
Set the data to be stored.
|
||||
@param[in] size Size of data to be stored.
|
||||
@param[in] p_data Pointer to data to be stored.
|
||||
\return true or false
|
||||
*/
|
||||
bool set(uint32_t size, const void* p_data);
|
||||
|
||||
/*!
|
||||
Query the data that was stored.
|
||||
@param[in] size Size (in bytes) of the memory pointed to by p_data.
|
||||
This determines maximum size of the returned data.
|
||||
@param[in,out] p_data Pointer to the result buffer.
|
||||
\return Size (in bytes) of the returned result which is coppied into
|
||||
the buffer pointed to by p_data.
|
||||
*/
|
||||
uint32_t get(uint32_t size, void* p_data);
|
||||
|
||||
/*!
|
||||
Get size of the current data stored
|
||||
\return Size (in bytes) of the data stored.
|
||||
*/
|
||||
uint32_t getSize() { return size_; }
|
||||
|
||||
private:
|
||||
/*! Size of data being stored */
|
||||
uint32_t size_;
|
||||
|
||||
/*! Pointer to the stored data */
|
||||
void* p_data_;
|
||||
};
|
||||
|
||||
typedef std::map<uint32_t, VarData> VarDataMap;
|
||||
}
|
||||
#endif
|
||||
@@ -1,141 +0,0 @@
|
||||
#ifndef _VI_PMU_H_
|
||||
#define _VI_PMU_H_
|
||||
|
||||
#include "hsa.h"
|
||||
#include "cmdwriter.h"
|
||||
#include "hsa_perf.h"
|
||||
#include "info_set.h"
|
||||
#include "parameter_set.h"
|
||||
#include "vi_blockinfo.h"
|
||||
#include "rocr_profiler.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <map>
|
||||
|
||||
namespace pm4_profile {
|
||||
typedef std::map<HsaViCounterBlockId, pm4_profile::CounterBlock*> ViCounterBlockMap;
|
||||
|
||||
// This class implement the VI PMU. It is responsible for setting up
|
||||
// CounterGroups to represent each VI hardware block which exposes performance
|
||||
// counters.
|
||||
class ViPmu : public pm4_profile::Pmu {
|
||||
public:
|
||||
ViPmu();
|
||||
~ViPmu();
|
||||
|
||||
// Returns number of shader engines per block
|
||||
// for the blocks featured shader engines instancing
|
||||
uint32_t getNumSe() { return num_se_; }
|
||||
|
||||
// Initializes the handle of buffer used to collect PMC data
|
||||
bool setPmcDataBuff(uint8_t* pmcBuffer, uint32_t pmcBuffSz);
|
||||
|
||||
int getLastError();
|
||||
|
||||
std::string getErrorString(int error);
|
||||
|
||||
virtual bool begin(pm4_profile::DefaultCmdBuf* cmdBuff, pm4_profile::CommandWriter* cmdWriter,
|
||||
bool reset = true);
|
||||
|
||||
virtual bool end(pm4_profile::DefaultCmdBuf* cmdBuff, pm4_profile::CommandWriter* cmdWriter);
|
||||
|
||||
// IPMU inherits the IParameterSet and IInfoSetso we implement it
|
||||
// through composition and function forwarding
|
||||
bool getParameter(uint32_t param, uint32_t& ret_size, void** pp_data);
|
||||
|
||||
bool setParameter(uint32_t param, uint32_t param_size, const void* p_data);
|
||||
|
||||
bool getInfo(uint32_t info, uint32_t& ret_size, void** pp_data);
|
||||
|
||||
pm4_profile::CounterBlock* getCounterBlockById(uint32_t id);
|
||||
|
||||
rocr_pmu_state_t getCurrentState() { return profiler_state_; }
|
||||
|
||||
pm4_profile::CounterBlock** getAllCounterBlocks(uint32_t& num_groups);
|
||||
|
||||
private:
|
||||
// Addr of Counter Data Buffer
|
||||
uint32_t* pmcData_;
|
||||
|
||||
// Size of Counter Data Buffer
|
||||
uint32_t pmcDataSz_;
|
||||
|
||||
void Init();
|
||||
|
||||
bool initCounterBlock();
|
||||
|
||||
bool isResultReady();
|
||||
|
||||
// Clear CounterBlockMap
|
||||
void clearCounterBlockMap();
|
||||
|
||||
// Reset SQ and CB counters
|
||||
void ResetCounterBlocks(pm4_profile::DefaultCmdBuf* cmdBuff,
|
||||
pm4_profile::CommandWriter* cmdWriter);
|
||||
|
||||
// Program SQ block related counters
|
||||
uint32_t ProgramSQCntrs(uint32_t sqRegIdx, uint32_t* regAddr, uint32_t* regVal, uint32_t blkId,
|
||||
uint32_t blkCntrIdx);
|
||||
|
||||
// Program TA block related counters
|
||||
uint32_t ProgramTaCntrs(uint32_t taRegIdx, uint32_t* regAddr, uint32_t* regVal, uint32_t blkId,
|
||||
uint32_t blkCntrIdx);
|
||||
|
||||
// Program TCA block related counters
|
||||
uint32_t ProgramTcaCntrs(uint32_t tcaRegIdx, uint32_t* regAddr, uint32_t* regVal, uint32_t blkId,
|
||||
uint32_t blkCntrIdx);
|
||||
|
||||
// Program TCC block related counters
|
||||
uint32_t ProgramTccCntrs(uint32_t tccRegIdx, uint32_t* regAddr, uint32_t* regVal, uint32_t blkId,
|
||||
uint32_t blkCntrIdx);
|
||||
|
||||
// Program TCP block related counters
|
||||
uint32_t ProgramTcpCntrs(uint32_t tcpRegIdx, uint32_t* regAddr, uint32_t* regVal, uint32_t blkId,
|
||||
uint32_t blkCntrIdx);
|
||||
|
||||
// Program TD block related counters
|
||||
uint32_t ProgramTdCntrs(uint32_t tdRegIdx, uint32_t* regAddr, uint32_t* regVal, uint32_t blkId,
|
||||
uint32_t blkCntrIdx);
|
||||
|
||||
// Build counter selection register, return how many registers are built
|
||||
uint32_t BuildCounterSelRegister(uint32_t cntrIdx, uint32_t* regAddr, uint32_t* regVal,
|
||||
uint32_t blkId, pm4_profile::Counter* blkCntr);
|
||||
|
||||
// Build counter selection register, return how many registers are built
|
||||
uint32_t BuildCounterReadRegisters(uint32_t reg_index, uint32_t block_id, uint32_t* reg_addr,
|
||||
uint32_t* reg_val);
|
||||
|
||||
private:
|
||||
// Delete counter blocks in the PMU
|
||||
hsa_status_t RemoveCounterBlocks();
|
||||
|
||||
private:
|
||||
// This contains the available counter groups.
|
||||
ViCounterBlockMap blk_map_;
|
||||
|
||||
// This stores the current profiling state.
|
||||
rocr_pmu_state_t profiler_state_;
|
||||
|
||||
pm4_profile::ParameterSet* parameter_set_;
|
||||
|
||||
pm4_profile::InfoSet* info_set_;
|
||||
|
||||
int error_code_;
|
||||
|
||||
// A flag to indicate the current packet is for copy register value
|
||||
#define COPY_DATA_FLAG 0xFFFFFFFF
|
||||
#define MAX_REG_NUM 100
|
||||
|
||||
// Pointer used to store counter block list internally
|
||||
uint32_t blk_list_size_;
|
||||
pm4_profile::CounterBlock** blk_list_;
|
||||
|
||||
// Indicates the number of Shader Engines Present
|
||||
uint32_t num_se_;
|
||||
|
||||
// Used to reset GRBM to its default state
|
||||
uint32_t reset_grbm_;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
@@ -8,9 +8,7 @@ set ( LIB_SRC ${LIB_SRC} gfx9_thread_trace.cpp )
|
||||
#
|
||||
# Header files include path(s).
|
||||
#
|
||||
include_directories ( $ENV{ROCR_INC_DIR} )
|
||||
include_directories ( ${PROJ_DIR}/commandwriter )
|
||||
include_directories ( ${HSA_RUNTIME_OSC_DIR} )
|
||||
|
||||
#
|
||||
# Build ThreadTrace as a Static Library object
|
||||
|
||||
+5
-13
@@ -1,11 +1,3 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <random>
|
||||
#include <memory>
|
||||
|
||||
#include "core/util/os.h"
|
||||
#include "gfx8_thread_trace.h"
|
||||
|
||||
/// @brief Returns the lower 32-bits of a value
|
||||
@@ -68,14 +60,14 @@ void Gfx8ThreadTrace::InitThreadTraceCfgRegs() {
|
||||
ttCfgRegs_.ttRegMask.u32All = 0;
|
||||
ttCfgRegs_.ttRegMask.bits.SH_SEL = 0x0;
|
||||
ttCfgRegs_.ttRegMask.bits.SIMD_EN = 0xF;
|
||||
ttCfgRegs_.ttRegMask.bits.CU_SEL = SetCuId();
|
||||
ttCfgRegs_.ttRegMask.bits.CU_SEL = GetCuId();
|
||||
ttCfgRegs_.ttRegMask.bits.SQ_STALL_EN__CI__VI = 0x1;
|
||||
ttCfgRegs_.ttRegMask.bits.SPI_STALL_EN__CI__VI = 0x1;
|
||||
ttCfgRegs_.ttRegMask.bits.REG_STALL_EN__CI__VI = 0x1;
|
||||
ttCfgRegs_.ttRegMask.bits.VM_ID_MASK = SetVmId();
|
||||
ttCfgRegs_.ttRegMask.bits.VM_ID_MASK = GetVmId();
|
||||
|
||||
// Override Mask value if a user value is available
|
||||
uint32_t ttMask = SetMask();
|
||||
uint32_t ttMask = GetMask();
|
||||
if (ttMask) {
|
||||
ttCfgRegs_.ttRegMask.u32All = ttMask;
|
||||
}
|
||||
@@ -93,7 +85,7 @@ void Gfx8ThreadTrace::InitThreadTraceCfgRegs() {
|
||||
ttCfgRegs_.ttRegTokenMask.bits.REG_DROP_ON_STALL__CI__VI = 0x1;
|
||||
|
||||
// Override TokenMask1 value if a user value is available
|
||||
uint32_t tokenMask1 = SetTokenMask();
|
||||
uint32_t tokenMask1 = GetTokenMask();
|
||||
if (tokenMask1) {
|
||||
ttCfgRegs_.ttRegTokenMask.u32All = tokenMask1;
|
||||
}
|
||||
@@ -105,7 +97,7 @@ void Gfx8ThreadTrace::InitThreadTraceCfgRegs() {
|
||||
ttCfgRegs_.ttRegTokenMask2.bits.INST_MASK = 0xFFFFFF7F;
|
||||
|
||||
// Override TokenMask2 value if a user value is available
|
||||
uint32_t tokenMask2 = SetTokenMask2();
|
||||
uint32_t tokenMask2 = GetTokenMask2();
|
||||
if (tokenMask2) {
|
||||
ttCfgRegs_.ttRegTokenMask2.u32All = tokenMask2;
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
#include "gfxip/gfx8/si_pm4defs.h"
|
||||
#include "thread_trace.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace pm4_profile {
|
||||
|
||||
typedef struct Gfx8ThreadTraceCfgRegs {
|
||||
|
||||
+5
-13
@@ -1,11 +1,3 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <random>
|
||||
#include <memory>
|
||||
|
||||
#include "core/util/os.h"
|
||||
#include "gfx9_thread_trace.h"
|
||||
|
||||
/// @brief Returns the lower 32-bits of a value
|
||||
@@ -68,14 +60,14 @@ void Gfx9ThreadTrace::InitThreadTraceCfgRegs() {
|
||||
ttCfgRegs_.ttRegMask.u32All = 0;
|
||||
ttCfgRegs_.ttRegMask.bits.SH_SEL = 0x0;
|
||||
ttCfgRegs_.ttRegMask.bits.SIMD_EN = 0xF;
|
||||
ttCfgRegs_.ttRegMask.bits.CU_SEL = SetCuId();
|
||||
ttCfgRegs_.ttRegMask.bits.CU_SEL = GetCuId();
|
||||
ttCfgRegs_.ttRegMask.bits.SQ_STALL_EN = 0x1;
|
||||
ttCfgRegs_.ttRegMask.bits.SPI_STALL_EN = 0x1;
|
||||
ttCfgRegs_.ttRegMask.bits.REG_STALL_EN = 0x1;
|
||||
ttCfgRegs_.ttRegMask.bits.VM_ID_MASK = SetVmId();
|
||||
ttCfgRegs_.ttRegMask.bits.VM_ID_MASK = GetVmId();
|
||||
|
||||
// Override Mask value if a user value is available
|
||||
uint32_t ttMask = SetMask();
|
||||
uint32_t ttMask = GetMask();
|
||||
if (ttMask) {
|
||||
ttCfgRegs_.ttRegMask.u32All = ttMask;
|
||||
}
|
||||
@@ -93,7 +85,7 @@ void Gfx9ThreadTrace::InitThreadTraceCfgRegs() {
|
||||
ttCfgRegs_.ttRegTokenMask.bits.REG_DROP_ON_STALL = 0x1;
|
||||
|
||||
// Override TokenMask1 value if a user value is available
|
||||
uint32_t tokenMask1 = SetTokenMask();
|
||||
uint32_t tokenMask1 = GetTokenMask();
|
||||
if (tokenMask1) {
|
||||
ttCfgRegs_.ttRegTokenMask.u32All = tokenMask1;
|
||||
}
|
||||
@@ -105,7 +97,7 @@ void Gfx9ThreadTrace::InitThreadTraceCfgRegs() {
|
||||
ttCfgRegs_.ttRegTokenMask2.bits.INST_MASK = 0xFFFFFF7F;
|
||||
|
||||
// Override TokenMask2 value if a user value is available
|
||||
uint32_t tokenMask2 = SetTokenMask2();
|
||||
uint32_t tokenMask2 = GetTokenMask2();
|
||||
if (tokenMask2) {
|
||||
ttCfgRegs_.ttRegTokenMask2.u32All = tokenMask2;
|
||||
}
|
||||
|
||||
+6
-52
@@ -1,6 +1,5 @@
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
|
||||
#include "core/util/os.h"
|
||||
#include "thread_trace.h"
|
||||
|
||||
namespace pm4_profile {
|
||||
@@ -24,81 +23,36 @@ void ThreadTrace::InitThreadTraceConfig(ThreadTraceConfig* config) const {
|
||||
config->threadTraceTokenMask2 = 0;
|
||||
}
|
||||
|
||||
uint8_t ThreadTrace::SetCuId() {
|
||||
uint8_t ThreadTrace::GetCuId() {
|
||||
uint32_t cuId = ttConfig_.threadTraceTargetCu;
|
||||
|
||||
// Allow users to specify the CU to choose for Target tokens
|
||||
std::string var = os::GetEnvVar("HSA_THREAD_TRACE_SELECT_CU");
|
||||
if (var.length() > 0) {
|
||||
cuId = std::stol(var, nullptr, 16);
|
||||
std::cout << "Using " << cuId << " as CUID for Thread Trace" << std::endl;
|
||||
}
|
||||
|
||||
assert((cuId <= 15) && "Cu Id must be between 0 and 15");
|
||||
|
||||
return cuId;
|
||||
}
|
||||
|
||||
uint8_t ThreadTrace::SetVmId() {
|
||||
uint8_t ThreadTrace::GetVmId() {
|
||||
uint32_t vmId = ttConfig_.threadTraceVmIdMask;
|
||||
|
||||
// Allow users to specify the VMID to choose for Target tokens
|
||||
std::string var = os::GetEnvVar("HSA_THREAD_TRACE_SELECT_VMID");
|
||||
if (var.length() > 0) {
|
||||
vmId = std::stol(var, nullptr, 16);
|
||||
std::cout << "Using " << vmId << " as VMID for Thread Trace" << std::endl;
|
||||
}
|
||||
|
||||
assert((vmId <= 2) && "VmId must be between 0 and 2");
|
||||
|
||||
return vmId;
|
||||
}
|
||||
|
||||
uint32_t ThreadTrace::SetMask() {
|
||||
uint32_t ThreadTrace::GetMask() {
|
||||
uint32_t ttMask = ttConfig_.threadTraceMask;
|
||||
const uint32_t validMask = 0x00C0D0;
|
||||
|
||||
// Allow users to specify the Mask to choose for configuration parameters
|
||||
std::string var = os::GetEnvVar("HSA_THREAD_TRACE_SELECT_MASK");
|
||||
if (var.length() > 0) {
|
||||
ttMask = std::stol(var, nullptr, 16);
|
||||
std::cout << "Using " << ttMask << " as Mask for Thread Trace" << std::endl;
|
||||
}
|
||||
|
||||
assert(((ttMask & validMask) == 0) && "Mask should have bits [4,6,7] set to Zero");
|
||||
|
||||
return ttMask;
|
||||
}
|
||||
|
||||
uint32_t ThreadTrace::SetTokenMask() {
|
||||
uint32_t ThreadTrace::GetTokenMask() {
|
||||
uint32_t tokenMask = ttConfig_.threadTraceTokenMask;
|
||||
const uint32_t validMask = 0xFF000000;
|
||||
|
||||
// Allow users to specify the TokenMask to choose for Target tokens
|
||||
std::string var = os::GetEnvVar("HSA_THREAD_TRACE_SELECT_TOKEN_MASK1");
|
||||
if (var.length() > 0) {
|
||||
tokenMask = std::stol(var, nullptr, 16);
|
||||
std::cout << "Using " << tokenMask << " as TokenMask for Thread Trace" << std::endl;
|
||||
}
|
||||
|
||||
assert(((tokenMask & validMask) == 0) && "TokenMask should have bits [31:25] set to Zero");
|
||||
|
||||
return tokenMask;
|
||||
}
|
||||
|
||||
uint32_t ThreadTrace::SetTokenMask2() {
|
||||
uint32_t ThreadTrace::GetTokenMask2() {
|
||||
uint32_t tokenMask2 = ttConfig_.threadTraceTokenMask2;
|
||||
const uint32_t validMask = 0xFFFF0000;
|
||||
|
||||
// Allow users to specify the TokenMask2 to choose for Target tokens
|
||||
std::string var = os::GetEnvVar("HSA_THREAD_TRACE_SELECT_TOKEN_MASK2");
|
||||
if (var.length() > 0) {
|
||||
tokenMask2 = std::stol(var, nullptr, 16);
|
||||
std::cout << "Using " << tokenMask2 << " as TokenMask2 for Thread Trace" << std::endl;
|
||||
}
|
||||
|
||||
assert(((tokenMask2 & validMask) == 0) && "TokenMask2 should have bits [31:16] set to Zero");
|
||||
|
||||
return tokenMask2;
|
||||
}
|
||||
|
||||
|
||||
+5
-12
@@ -7,18 +7,11 @@
|
||||
|
||||
// Move them as static variables later on
|
||||
#define TT_WRITE_PTR_MASK (0x3FFFFFFF)
|
||||
#define TT_DEFAULT_BUFF_SIZE_SCALE (16)
|
||||
#define TT_DEFAULT_BUFF_SIZE (1024 * 1024 * 8)
|
||||
|
||||
// Size of block in bytesper increment in WPTR
|
||||
#define TT_WRITE_PTR_BLK (32)
|
||||
|
||||
// Factor by which to shift buffer address
|
||||
#define TT_BUFF_ALIGN_SHIFT (12)
|
||||
|
||||
// Align address to 64 Kilobytes
|
||||
#define TT_BUFF_ADDR_ALIGN (0x10000)
|
||||
|
||||
namespace pm4_profile {
|
||||
|
||||
// ThreadTrace config
|
||||
@@ -43,19 +36,19 @@ class ThreadTrace {
|
||||
virtual ~ThreadTrace(){};
|
||||
|
||||
// Obtain the CU id to use for thread tracing
|
||||
uint8_t SetCuId();
|
||||
uint8_t GetCuId();
|
||||
|
||||
// Obtain the VM id to use for thread tracing
|
||||
uint8_t SetVmId();
|
||||
uint8_t GetVmId();
|
||||
|
||||
// Obtain the Mask to use for thread tracing
|
||||
uint32_t SetMask();
|
||||
uint32_t GetMask();
|
||||
|
||||
// Obtain the Token Mask 1 to use for thread tracing
|
||||
uint32_t SetTokenMask();
|
||||
uint32_t GetTokenMask();
|
||||
|
||||
// Obtain the Token Mask 2 to use for thread tracing
|
||||
uint32_t SetTokenMask2();
|
||||
uint32_t GetTokenMask2();
|
||||
|
||||
// Initializes various data structures and handles that
|
||||
// are needed to support a thread trace session
|
||||
|
||||
@@ -3,10 +3,8 @@
|
||||
#
|
||||
include_directories ( $ENV{ROCR_INC_DIR} )
|
||||
include_directories ( ${API_DIR} )
|
||||
include_directories ( ${PROJ_DIR}/aqlprofile )
|
||||
include_directories ( ${TEST_DIR}/common )
|
||||
include_directories ( ${TEST_DIR}/util )
|
||||
include_directories ( ${TEST_DIR}/ctrl )
|
||||
include_directories ( ${CORE_UTIL_DIR} )
|
||||
|
||||
#
|
||||
# Specify the directory containing the libraries of HsaRt
|
||||
@@ -19,8 +17,8 @@ find_library ( ROCR_LIB NAMES hsa-runtime64 PATHS $ENV{ROCR_LIB_DIR} )
|
||||
# Set Name for Common library and build it as a
|
||||
# static library to be linked with others
|
||||
#
|
||||
set ( COMMON_LIB "common${ONLY64STR}" )
|
||||
add_subdirectory ( ${TEST_DIR}/common "${PROJECT_BINARY_DIR}/common" )
|
||||
set ( UTIL_LIB "util${ONLY64STR}" )
|
||||
add_subdirectory ( ${TEST_DIR}/util "${PROJECT_BINARY_DIR}/util" )
|
||||
|
||||
#
|
||||
# Build the test library
|
||||
@@ -39,7 +37,7 @@ set ( TEST_LIBS ${LIB_NAME} )
|
||||
set ( SRC_LIST ${TEST_DIR}/ctrl/test.cpp )
|
||||
set ( SRC_LIST ${SRC_LIST} ${TEST_DIR}/ctrl/test_pmgr.cpp )
|
||||
set ( SRC_LIST ${SRC_LIST} ${TEST_DIR}/ctrl/test_hsa.cpp )
|
||||
set ( LIB_LIST ${TEST_LIBS} ${COMMON_LIB} ${CORE_UTILS_LIB} ${ROCR_LIB} ${TARGET_LIB} )
|
||||
set ( LIB_LIST ${TEST_LIBS} ${UTIL_LIB} ${CORE_UTILS_LIB} ${ROCR_LIB} ${TARGET_LIB} )
|
||||
set ( EXE_NAME "ctrl" )
|
||||
add_executable ( ${EXE_NAME} ${SRC_LIST} )
|
||||
target_link_libraries( ${EXE_NAME} ${LIB_LIST} c stdc++ dl pthread rt atomic )
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#
|
||||
# Source files for Rocr Utils library
|
||||
#
|
||||
file( GLOB MODULE_SRC "*.cpp" )
|
||||
|
||||
#
|
||||
# Header files include path(s).
|
||||
#
|
||||
include_directories ( $ENV{ROCR_INC_DIR} )
|
||||
|
||||
#
|
||||
# Build Utils as a Static Library object
|
||||
#
|
||||
add_library( ${COMMON_LIB} STATIC ${MODULE_SRC} )
|
||||
target_link_libraries( ${COMMON_LIB} c stdc++ dl pthread rt )
|
||||
@@ -1,45 +0,0 @@
|
||||
#include "common.hpp"
|
||||
|
||||
void ErrorCheck(hsa_status_t hsa_error_code) {
|
||||
if (hsa_error_code != HSA_STATUS_SUCCESS) {
|
||||
std::cerr << "HSA reported error!" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
hsa_status_t FindGpuDevice(hsa_agent_t agent, void* data) {
|
||||
if (data == NULL) {
|
||||
return HSA_STATUS_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
hsa_device_type_t hsa_device_type;
|
||||
hsa_status_t hsa_error_code = hsa_agent_get_info(agent, HSA_AGENT_INFO_DEVICE, &hsa_device_type);
|
||||
if (hsa_error_code != HSA_STATUS_SUCCESS) {
|
||||
return hsa_error_code;
|
||||
}
|
||||
|
||||
if (hsa_device_type == HSA_DEVICE_TYPE_GPU) {
|
||||
*((hsa_agent_t*)data) = agent;
|
||||
}
|
||||
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
hsa_status_t FindHostRegion(hsa_region_t region, void* data) {
|
||||
if (data == NULL) {
|
||||
return HSA_STATUS_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
bool is_host_region = false;
|
||||
hsa_status_t hsa_error_code = hsa_region_get_info(
|
||||
region, (hsa_region_info_t)HSA_AMD_REGION_INFO_HOST_ACCESSIBLE, &is_host_region);
|
||||
if (hsa_error_code != HSA_STATUS_SUCCESS) {
|
||||
return hsa_error_code;
|
||||
}
|
||||
|
||||
if (is_host_region) {
|
||||
*((hsa_region_t*)data) = region;
|
||||
}
|
||||
|
||||
return HSA_STATUS_SUCCESS;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#ifndef COMMON_COMMON_HPP
|
||||
#define COMMON_COMMON_HPP
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include "hsa.h"
|
||||
#include "hsa_ext_finalize.h"
|
||||
#include "hsa_ext_amd.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define ALIGNED_(x) __declspec(align(x))
|
||||
#else
|
||||
#if defined(__GNUC__)
|
||||
#define ALIGNED_(x) __attribute__((aligned(x)))
|
||||
#endif // __GNUC__
|
||||
#endif // _MSC_VER
|
||||
|
||||
#define MULTILINE(...) #__VA_ARGS__
|
||||
|
||||
void ErrorCheck(hsa_status_t hsa_error_code);
|
||||
|
||||
hsa_status_t FindGpuDevice(hsa_agent_t agent, void* data);
|
||||
|
||||
hsa_status_t FindHostRegion(hsa_region_t region, void* data);
|
||||
|
||||
#endif // COMMON_COMMON_HPP
|
||||
-155
@@ -1,155 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <cassert>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "hsa.h"
|
||||
#include "hsa_ext_profiler.h"
|
||||
#include "amd_hsa_tools_interfaces.h"
|
||||
|
||||
#include "hsa_perf_cntrs.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void PreDispatchCallback(const hsa_dispatch_callback_t* dispParam, void* usrArg) {
|
||||
assert((dispParam->pre_dispatch) && "Pre Dispatch Callback Param is Malformed");
|
||||
|
||||
hsa_ext_tools_pmu_t* perfMgr = reinterpret_cast<hsa_ext_tools_pmu_t*>(usrArg);
|
||||
hsa_status_t status =
|
||||
hsa_ext_tools_pmu_begin(*perfMgr, dispParam->queue, dispParam->aql_translation_handle, true);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in beginning Perf Cntr Session");
|
||||
}
|
||||
|
||||
void PostDispatchCallback(const hsa_dispatch_callback_t* dispParam, void* usrArg) {
|
||||
assert((!dispParam->pre_dispatch) && "Post Dispatch Callback Param is Malformed");
|
||||
|
||||
hsa_ext_tools_pmu_t* perfMgr = reinterpret_cast<hsa_ext_tools_pmu_t*>(usrArg);
|
||||
hsa_status_t status =
|
||||
hsa_ext_tools_pmu_end(*perfMgr, dispParam->queue, dispParam->aql_translation_handle);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in endning Perf Cntr Session");
|
||||
}
|
||||
|
||||
// Constructor of the class
|
||||
RocrPerfCntrApp::RocrPerfCntrApp() : perfMgr_(NULL) {}
|
||||
|
||||
// Destructor of the class. Ideally it should delete the
|
||||
// PMU and its counters
|
||||
RocrPerfCntrApp::~RocrPerfCntrApp() {}
|
||||
|
||||
// Return the number of perf counters
|
||||
uint32_t RocrPerfCntrApp::GetNumPerfCntrs() { return uint32_t(cntrList_.size()); }
|
||||
|
||||
// Return the handle of perf counter at specified index
|
||||
CntrInfo* RocrPerfCntrApp::GetPerfCntr(uint32_t idx) { return cntrList_[idx]; }
|
||||
|
||||
// Print the various fields of Perf Cntrs being programmed
|
||||
bool RocrPerfCntrApp::PrintCntrs() {
|
||||
CntrInfo* info;
|
||||
int size = uint32_t(cntrList_.size());
|
||||
for (int idx = 0; idx < size; idx++) {
|
||||
info = cntrList_[idx];
|
||||
std::cout << std::endl;
|
||||
std::cout << "Rocr Perf Cntr Id: " << info->cntrId << std::endl;
|
||||
std::cout << "Rocr Perf Cntr Name: " << info->cntrName << std::endl;
|
||||
std::cout << "Rocr Perf Cntr Blk Id: " << info->blkId << std::endl;
|
||||
std::cout << "Rocr Perf Cntr Value: " << info->cntrResult << std::endl;
|
||||
std::cout << "Rocr Perf Cntr Validation: " << info->cnfType << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initialize the list of perf counters
|
||||
// block id of kHsaAiCounterBlockSQ = 14 == 0x0E
|
||||
hsa_status_t RocrPerfCntrApp::Init(hsa_agent_t agent) {
|
||||
// Initialize the list of Perf Cntrs
|
||||
// Add SQ counter for number of waves
|
||||
CntrInfo* info = NULL;
|
||||
cntrList_.reserve(23);
|
||||
|
||||
// Event for number of Waves
|
||||
info = new CntrInfo(0x4, "SQ_SQ_PERF_SEL_WAVES", NULL, 0x0E, NULL, 0x00, 0xFFFFFFFF,
|
||||
CntrValCnf_Exact);
|
||||
cntrList_.push_back(info);
|
||||
|
||||
// Event for number of Threads
|
||||
info = new CntrInfo(0xE, "SQ_SQ_PERF_SEL_ITEMS", NULL, 0x0E, NULL, 0x00, 0xFFFFFFFF,
|
||||
CntrValCnf_Exact);
|
||||
cntrList_.push_back(info);
|
||||
|
||||
|
||||
// Create an instance of Perf Mgr
|
||||
hsa_status_t status;
|
||||
status = hsa_ext_tools_create_pmu(agent, &perfMgr_);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in creating Perf Cntr Mgr");
|
||||
|
||||
// Process each counter from the list as necessary
|
||||
// each counter descriptor with its perf block handle
|
||||
// and create an instance of counter in that block
|
||||
uint32_t size = GetNumPerfCntrs();
|
||||
for (uint32_t idx = 0; idx < size; idx++) {
|
||||
info = GetPerfCntr(idx);
|
||||
|
||||
// Obtain the handle of perf block
|
||||
if (info->blkHndl == NULL) {
|
||||
status = hsa_ext_tools_get_counter_block_by_id(perfMgr_, info->blkId, &info->blkHndl);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in getting Perf Cntr Blk Hndl");
|
||||
}
|
||||
|
||||
// Create an instance of counter in the perf block
|
||||
status = hsa_ext_tools_create_counter(info->blkHndl, &info->cntrHndl);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in creating Perf Cntr in Perf Blk");
|
||||
|
||||
// Update the Event Index property of counter
|
||||
uint32_t cntrProp = HSA_EXT_TOOLS_COUNTER_PARAMETER_EVENT_INDEX;
|
||||
status = hsa_ext_tools_set_counter_parameter(info->cntrHndl, cntrProp, sizeof(uint32_t),
|
||||
(void*)&info->cntrId);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in updating Perf Cntr Property Event Index");
|
||||
|
||||
// Enable the updated perf counter
|
||||
status = hsa_ext_tools_set_counter_enabled(info->cntrHndl, true);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in enabing Perf Cntr");
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Register Pre and Post dispatch callbacks
|
||||
void RocrPerfCntrApp::RegisterCallbacks(hsa_queue_t* queue) {
|
||||
hsa_status_t status;
|
||||
status = hsa_ext_tools_set_callback_functions(queue, PreDispatchCallback, PostDispatchCallback);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in registering Pre & Post Dispatch Callbacks");
|
||||
status = hsa_ext_tools_set_callback_arguments(queue, &perfMgr_, &perfMgr_);
|
||||
assert((status == HSA_STATUS_SUCCESS) &&
|
||||
"Error in registering Pre & Post Dispatch Callback Params");
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait for perf counter collection to complete
|
||||
hsa_status_t RocrPerfCntrApp::Wait() {
|
||||
hsa_status_t status;
|
||||
status = hsa_ext_tools_pmu_wait_for_completion(perfMgr_, 5000);
|
||||
assert((status == HSA_STATUS_SUCCESS) && "Error in Waiting for Perf Cntr Completion");
|
||||
return status;
|
||||
}
|
||||
|
||||
// Validate perf counter values
|
||||
hsa_status_t RocrPerfCntrApp::Validate() {
|
||||
// Retrieve the results of the different Perf Cntrs
|
||||
// and validate them as configured
|
||||
CntrInfo* info = NULL;
|
||||
hsa_status_t status = HSA_STATUS_SUCCESS;
|
||||
uint32_t size = GetNumPerfCntrs();
|
||||
for (uint32_t idx = 0; idx < size; idx++) {
|
||||
info = GetPerfCntr(idx);
|
||||
status = hsa_ext_tools_get_counter_result(info->cntrHndl, &info->cntrResult);
|
||||
std::cout << "Value of Perf Cntr is: " << info->cntrResult << std::endl;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
-110
@@ -1,110 +0,0 @@
|
||||
#ifndef ROCR_PERF_CNTR_APP_H_
|
||||
#define ROCR_PERF_CNTR_APP_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "hsa.h"
|
||||
#include "hsa_ext_profiler.h"
|
||||
|
||||
typedef enum CntrValCnfType {
|
||||
|
||||
///< no counter value validation should be performed
|
||||
CntrValCnf_None,
|
||||
|
||||
///< counter value should be an exact match to expectedResult
|
||||
CntrValCnf_Exact,
|
||||
|
||||
///< counter value should be greater than expectedResult
|
||||
CntrValCnf_GreaterThan,
|
||||
|
||||
///< counter value should be less than expectedResult
|
||||
CntrValCnf_LessThan
|
||||
|
||||
} CntrValCnfType;
|
||||
|
||||
/// Struct used to encapsulate Counter Info
|
||||
typedef struct CntrInfo {
|
||||
///< Id of counter in hardware block
|
||||
uint32_t cntrId;
|
||||
|
||||
///< Name of counter
|
||||
char cntrName[72];
|
||||
|
||||
///< Handle of perf counter
|
||||
hsa_ext_tools_counter_t cntrHndl;
|
||||
|
||||
///< Id of hardware block containing the counter
|
||||
uint32_t blkId;
|
||||
|
||||
///< Handle of counter block
|
||||
hsa_ext_tools_counter_block_t blkHndl;
|
||||
|
||||
///< Expected value of perf counte
|
||||
uint64_t expectedResult;
|
||||
|
||||
///< Value of perf counter expected
|
||||
uint64_t cntrResult;
|
||||
|
||||
///< Type of validation upon completion of dispatch
|
||||
CntrValCnfType cnfType;
|
||||
|
||||
CntrInfo(uint32_t cntrId, char* cntrName, void* cntrHndl, uint32_t blkId, void* blkHndl,
|
||||
uint64_t expResult, uint64_t result, CntrValCnfType cnfType) {
|
||||
this->cntrId = cntrId;
|
||||
this->cntrHndl = cntrHndl;
|
||||
this->blkId = blkId;
|
||||
this->blkHndl = blkHndl;
|
||||
this->expectedResult = expResult;
|
||||
this->cntrResult = result;
|
||||
this->cnfType = cnfType;
|
||||
memcpy(this->cntrName, cntrName, strlen(cntrName));
|
||||
}
|
||||
|
||||
} CntrInfo;
|
||||
|
||||
class RocrPerfCntrApp {
|
||||
public:
|
||||
// Constructor of the class. Will initialize the list of perf counters
|
||||
// that will be used to program the device
|
||||
RocrPerfCntrApp();
|
||||
|
||||
// Destructor of the class
|
||||
~RocrPerfCntrApp();
|
||||
|
||||
// Return the number of perf counters
|
||||
uint32_t GetNumPerfCntrs();
|
||||
|
||||
// Return the handle of perf counter at specified index
|
||||
CntrInfo* GetPerfCntr(uint32_t idx);
|
||||
|
||||
// Print the list of perf counters
|
||||
bool PrintCntrs();
|
||||
|
||||
// Initialize the list of perf counters
|
||||
hsa_status_t Init(hsa_agent_t agent);
|
||||
|
||||
// Register Pre and Post dispatch callbacks
|
||||
void RegisterCallbacks(hsa_queue_t* queue);
|
||||
|
||||
// Wait for perf counter collection to complete
|
||||
hsa_status_t Wait();
|
||||
|
||||
// Validate perf counter values
|
||||
hsa_status_t Validate();
|
||||
|
||||
private:
|
||||
// Number of queues to create
|
||||
std::vector<CntrInfo*> cntrList_;
|
||||
|
||||
// Handle of Perf Cntr Manager
|
||||
hsa_ext_tools_pmu_t perfMgr_;
|
||||
};
|
||||
|
||||
#endif // ROCR_PERF_CNTR_APP_H_
|
||||
@@ -29,7 +29,7 @@ OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define _TESTAQL_H_
|
||||
|
||||
#include "hsa.h"
|
||||
#include "hsa_rsrc_factory.hpp"
|
||||
#include "hsa_rsrc_factory.h"
|
||||
#include "hsa_ext_amd_aql_profile.h"
|
||||
|
||||
#define test_assert(cond) \
|
||||
|
||||
@@ -25,9 +25,12 @@ OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include "os.h"
|
||||
#include "helper_funcs.hpp"
|
||||
#include "hsa_rsrc_factory.hpp"
|
||||
#include <assert.h>
|
||||
#include <atomic>
|
||||
|
||||
//#include "os.h"
|
||||
#include "helper_funcs.h"
|
||||
#include "hsa_rsrc_factory.h"
|
||||
#include "test_hsa.h"
|
||||
|
||||
bool TestHSA::initialize(int arg_cnt, char** arg_list) {
|
||||
@@ -146,7 +149,6 @@ bool TestHSA::run() {
|
||||
memset(&aql, 0, sizeof(aql));
|
||||
// Set the packet's type, barrier bit, acquire and release fences
|
||||
aql.header = HSA_PACKET_TYPE_KERNEL_DISPATCH;
|
||||
aql.header |= 1ul << HSA_PACKET_HEADER_BARRIER;
|
||||
aql.header |= HSA_FENCE_SCOPE_SYSTEM << HSA_PACKET_HEADER_SCACQUIRE_FENCE_SCOPE;
|
||||
aql.header |= HSA_FENCE_SCOPE_SYSTEM << HSA_PACKET_HEADER_SCRELEASE_FENCE_SCOPE;
|
||||
// Populate Aql packet with default values
|
||||
|
||||
@@ -30,7 +30,7 @@ OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "test_aql.h"
|
||||
#include "test_kernel.h"
|
||||
#include "hsa_rsrc_factory.hpp"
|
||||
#include "hsa_rsrc_factory.h"
|
||||
|
||||
// Class implements HSA test
|
||||
class TestHSA : public TestAql {
|
||||
|
||||
@@ -58,9 +58,8 @@ bool TestPMgr::addPacketGfx9(const packet_t* packet) {
|
||||
}
|
||||
|
||||
bool TestPMgr::addPacketGfx8(const packet_t* packet) {
|
||||
// Create Legacy PM4 data
|
||||
const hsa_ext_amd_aql_pm4_packet_t * aql_packet =
|
||||
(const hsa_ext_amd_aql_pm4_packet_t *) packet;
|
||||
// Create legacy devices PM4 data
|
||||
const hsa_ext_amd_aql_pm4_packet_t* aql_packet = (const hsa_ext_amd_aql_pm4_packet_t*)packet;
|
||||
slot_pm4_s data;
|
||||
hsa_ext_amd_aql_profile_legacy_get_pm4(aql_packet, (void*)data.words);
|
||||
|
||||
@@ -70,7 +69,7 @@ bool TestPMgr::addPacketGfx8(const packet_t* packet) {
|
||||
|
||||
// Copy Aql packet into queue buffer
|
||||
packet_t* ptr = ((packet_t*)(getQueue()->base_address)) + (que_idx & mask);
|
||||
slot_pm4_t * slot_pm4 = (slot_pm4_t*)ptr;
|
||||
slot_pm4_t* slot_pm4 = (slot_pm4_t*)ptr;
|
||||
slot_pm4->store(data, std::memory_order_relaxed);
|
||||
|
||||
// Increment the write index and ring the doorbell to dispatch the kernel.
|
||||
@@ -81,10 +80,8 @@ bool TestPMgr::addPacketGfx8(const packet_t* packet) {
|
||||
}
|
||||
|
||||
bool TestPMgr::addPacket(const packet_t* packet) {
|
||||
const char * agent_name = getAgentInfo()->name;
|
||||
return (strncmp(agent_name, "gfx8", 4) == 0) ?
|
||||
addPacketGfx8(packet) :
|
||||
addPacketGfx9(packet);
|
||||
const char* agent_name = getAgentInfo()->name;
|
||||
return (strncmp(agent_name, "gfx8", 4) == 0) ? addPacketGfx8(packet) : addPacketGfx9(packet);
|
||||
}
|
||||
|
||||
bool TestPMgr::run() {
|
||||
|
||||
@@ -31,12 +31,11 @@ OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <atomic>
|
||||
|
||||
#include "test_aql.h"
|
||||
#include "amd_aql_pm4_ib_packet.h"
|
||||
|
||||
// SimpleConvolution: Class implements OpenCL SimpleConvolution sample
|
||||
class TestPMgr : public TestAql {
|
||||
public:
|
||||
typedef amd_aql_pm4_ib_packet_t packet_t;
|
||||
typedef hsa_ext_amd_aql_pm4_packet_t packet_t;
|
||||
TestPMgr(TestAql* t);
|
||||
bool run();
|
||||
|
||||
@@ -53,7 +52,7 @@ class TestPMgr : public TestAql {
|
||||
private:
|
||||
enum {
|
||||
SLOT_PM4_SIZE_DW = HSA_EXT_AQL_PROFILE_LEGACY_PM4_PACKET_SIZE / sizeof(uint32_t),
|
||||
SLOT_PM4_SIZE_AQLP = HSA_EXT_AQL_PROFILE_LEGACY_PM4_PACKET_SIZE / 64
|
||||
SLOT_PM4_SIZE_AQLP = HSA_EXT_AQL_PROFILE_LEGACY_PM4_PACKET_SIZE / sizeof(packet_t)
|
||||
};
|
||||
struct slot_pm4_s {
|
||||
uint32_t words[SLOT_PM4_SIZE_DW];
|
||||
|
||||
+4
-1
@@ -25,7 +25,10 @@ OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include "helper_funcs.hpp"
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
|
||||
#include "helper_funcs.h"
|
||||
#include "simple_convolution.h"
|
||||
|
||||
SimpleConvolution::SimpleConvolution() {
|
||||
|
||||
+1
-3
@@ -1,14 +1,12 @@
|
||||
#
|
||||
# Source files for Rocr Utils library
|
||||
#
|
||||
set ( MODULE_SRC ${CORE_UTIL_DIR}/lnx/os_linux.cpp )
|
||||
file( GLOB MODULE_SRC "*.cpp" )
|
||||
|
||||
#
|
||||
# Header files include path(s).
|
||||
#
|
||||
include_directories ( $ENV{ROCR_INC_DIR} )
|
||||
include_directories ( ${HSA_RUNTIME_OSC_DIR} )
|
||||
include_directories ( ${CORE_UTIL_DIR} )
|
||||
|
||||
#
|
||||
# Build Utils as a Static Library object
|
||||
+48
-80
@@ -22,12 +22,19 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
********************************************************************/
|
||||
|
||||
#include "helper_funcs.hpp"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <time.h>
|
||||
|
||||
#include "helper_funcs.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
void error(std::string errorMsg) { std::cout << "Error: " << errorMsg << std::endl; }
|
||||
|
||||
/*
|
||||
* Prints no more than 256 elements of the given array.
|
||||
@@ -47,11 +54,11 @@ void printArray(const std::string header, const T* data, const int width, const
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int fillRandom(T* arrayPtr, const int width, const int height, const T rangeMin, const T rangeMax,
|
||||
unsigned int seed) {
|
||||
bool fillRandom(T* arrayPtr, const int width, const int height, const T rangeMin, const T rangeMax,
|
||||
unsigned int seed) {
|
||||
if (!arrayPtr) {
|
||||
error("Cannot fill array. NULL pointer.");
|
||||
return HSA_SDK_FAILURE;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!seed) seed = (unsigned int)time(NULL);
|
||||
@@ -66,13 +73,13 @@ int fillRandom(T* arrayPtr, const int width, const int height, const T rangeMin,
|
||||
arrayPtr[index] = rangeMin + T(range * rand() / (RAND_MAX + 1.0));
|
||||
}
|
||||
|
||||
return HSA_SDK_SUCCESS;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T> int fillPos(T* arrayPtr, const int width, const int height) {
|
||||
template <typename T> bool fillPos(T* arrayPtr, const int width, const int height) {
|
||||
if (!arrayPtr) {
|
||||
error("Cannot fill array. NULL pointer.");
|
||||
return HSA_SDK_FAILURE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* initialisation of input with positions*/
|
||||
@@ -82,14 +89,14 @@ template <typename T> int fillPos(T* arrayPtr, const int width, const int height
|
||||
arrayPtr[index] = index;
|
||||
}
|
||||
|
||||
return HSA_SDK_SUCCESS;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int fillConstant(T* arrayPtr, const int width, const int height, const T val) {
|
||||
bool fillConstant(T* arrayPtr, const int width, const int height, const T val) {
|
||||
if (!arrayPtr) {
|
||||
error("Cannot fill array. NULL pointer.");
|
||||
return HSA_SDK_FAILURE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* initialisation of input with constant value*/
|
||||
@@ -99,7 +106,7 @@ int fillConstant(T* arrayPtr, const int width, const int height, const T val) {
|
||||
arrayPtr[index] = val;
|
||||
}
|
||||
|
||||
return HSA_SDK_SUCCESS;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T> T roundToPowerOf2(T val) {
|
||||
@@ -112,32 +119,17 @@ template <typename T> T roundToPowerOf2(T val) {
|
||||
return val;
|
||||
}
|
||||
|
||||
template <typename T> int isPowerOf2(T val) {
|
||||
template <typename T> bool isPowerOf2(T val) {
|
||||
long long _val = val;
|
||||
if ((_val & (-_val)) - _val == 0 && _val != 0)
|
||||
return HSA_SDK_SUCCESS;
|
||||
else
|
||||
return HSA_SDK_FAILURE;
|
||||
return (((_val & (-_val)) - _val == 0) && (_val != 0));
|
||||
}
|
||||
|
||||
|
||||
template <typename T> bool checkVal(T input, T reference, std::string message, bool isAPIerror) {
|
||||
if (input == reference) {
|
||||
return true;
|
||||
} else {
|
||||
error(message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T> std::string toString(T t, std::ios_base& (*r)(std::ios_base&)) {
|
||||
std::ostringstream output;
|
||||
output << r << t;
|
||||
return output.str();
|
||||
}
|
||||
|
||||
|
||||
bool compare(const float* refData, const float* data, const int length, const float epsilon) {
|
||||
float error = 0.0f;
|
||||
float ref = 0.0f;
|
||||
@@ -178,19 +170,6 @@ bool compare(const double* refData, const double* data, const int length, const
|
||||
return error < epsilon;
|
||||
}
|
||||
|
||||
void error(const char* errorMsg) { std::cout << "Error: " << errorMsg << std::endl; }
|
||||
|
||||
void error(std::string errorMsg) { std::cout << "Error: " << errorMsg << std::endl; }
|
||||
|
||||
void expectedError(const char* errorMsg) {
|
||||
std::cout << "Expected Error: " << errorMsg << std::endl;
|
||||
}
|
||||
|
||||
void expectedError(std::string errorMsg) {
|
||||
std::cout << "Expected Error: " << errorMsg << std::endl;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// Template Instantiations
|
||||
/////////////////////////////////////////////////////////////////
|
||||
@@ -202,56 +181,45 @@ template void printArray<long>(const std::string, const long*, int, int);
|
||||
template void printArray<float>(const std::string, const float*, int, int);
|
||||
template void printArray<double>(const std::string, const double*, int, int);
|
||||
|
||||
template int fillRandom<unsigned char>(unsigned char* arrayPtr, const int width, const int height,
|
||||
unsigned char rangeMin, unsigned char rangeMax,
|
||||
template bool fillRandom<unsigned char>(unsigned char* arrayPtr, const int width, const int height,
|
||||
unsigned char rangeMin, unsigned char rangeMax,
|
||||
unsigned int seed);
|
||||
template bool fillRandom<unsigned int>(unsigned int* arrayPtr, const int width, const int height,
|
||||
unsigned int rangeMin, unsigned int rangeMax,
|
||||
unsigned int seed);
|
||||
template int fillRandom<unsigned int>(unsigned int* arrayPtr, const int width, const int height,
|
||||
unsigned int rangeMin, unsigned int rangeMax,
|
||||
unsigned int seed);
|
||||
template int fillRandom<int>(int* arrayPtr, const int width, const int height, int rangeMin,
|
||||
int rangeMax, unsigned int seed);
|
||||
template int fillRandom<long>(long* arrayPtr, const int width, const int height, long rangeMin,
|
||||
long rangeMax, unsigned int seed);
|
||||
template int fillRandom<float>(float* arrayPtr, const int width, const int height, float rangeMin,
|
||||
float rangeMax, unsigned int seed);
|
||||
template int fillRandom<double>(double* arrayPtr, const int width, const int height,
|
||||
double rangeMin, double rangeMax, unsigned int seed);
|
||||
template bool fillRandom<int>(int* arrayPtr, const int width, const int height, int rangeMin,
|
||||
int rangeMax, unsigned int seed);
|
||||
template bool fillRandom<long>(long* arrayPtr, const int width, const int height, long rangeMin,
|
||||
long rangeMax, unsigned int seed);
|
||||
template bool fillRandom<float>(float* arrayPtr, const int width, const int height, float rangeMin,
|
||||
float rangeMax, unsigned int seed);
|
||||
template bool fillRandom<double>(double* arrayPtr, const int width, const int height,
|
||||
double rangeMin, double rangeMax, unsigned int seed);
|
||||
|
||||
template short roundToPowerOf2<short>(short val);
|
||||
template unsigned int roundToPowerOf2<unsigned int>(unsigned int val);
|
||||
template int roundToPowerOf2<int>(int val);
|
||||
template long roundToPowerOf2<long>(long val);
|
||||
|
||||
template int isPowerOf2<short>(short val);
|
||||
template int isPowerOf2<unsigned int>(unsigned int val);
|
||||
template int isPowerOf2<int>(int val);
|
||||
template int isPowerOf2<long>(long val);
|
||||
template bool isPowerOf2<short>(short val);
|
||||
template bool isPowerOf2<unsigned int>(unsigned int val);
|
||||
template bool isPowerOf2<int>(int val);
|
||||
template bool isPowerOf2<long>(long val);
|
||||
|
||||
template <> int fillPos<short>(short* arrayPtr, const int width, const int height);
|
||||
template <> int fillPos<unsigned int>(unsigned int* arrayPtr, const int width, const int height);
|
||||
template <> int fillPos<int>(int* arrayPtr, const int width, const int height);
|
||||
template <> int fillPos<long>(long* arrayPtr, const int width, const int height);
|
||||
template <> bool fillPos<short>(short* arrayPtr, const int width, const int height);
|
||||
template <> bool fillPos<unsigned int>(unsigned int* arrayPtr, const int width, const int height);
|
||||
template <> bool fillPos<int>(int* arrayPtr, const int width, const int height);
|
||||
template <> bool fillPos<long>(long* arrayPtr, const int width, const int height);
|
||||
|
||||
template <>
|
||||
int fillConstant<short>(short* arrayPtr, const int width, const int height, const short val);
|
||||
bool fillConstant<short>(short* arrayPtr, const int width, const int height, const short val);
|
||||
template <>
|
||||
int fillConstant(unsigned int* arrayPtr, const int width, const int height, const unsigned int val);
|
||||
template <> int fillConstant(int* arrayPtr, const int width, const int height, const int val);
|
||||
template <> int fillConstant(long* arrayPtr, const int width, const int height, const long val);
|
||||
template <> int fillConstant(long* arrayPtr, const int width, const int height, const long val);
|
||||
template <> int fillConstant(long* arrayPtr, const int width, const int height, const long val);
|
||||
|
||||
|
||||
template bool checkVal<char>(char input, char reference, std::string message, bool isAPIerror);
|
||||
template bool checkVal<bool>(bool input, bool reference, std::string message, bool isAPIerror);
|
||||
template bool checkVal<std::string>(std::string input, std::string reference, std::string message,
|
||||
bool isAPIerror);
|
||||
template bool checkVal<short>(short input, short reference, std::string message, bool isAPIerror);
|
||||
template bool checkVal<unsigned int>(unsigned int input, unsigned int reference,
|
||||
std::string message, bool isAPIerror);
|
||||
template bool checkVal<int>(int input, int reference, std::string message, bool isAPIerror);
|
||||
template bool checkVal<long>(long input, long reference, std::string message, bool isAPIerror);
|
||||
|
||||
bool fillConstant(unsigned int* arrayPtr, const int width, const int height,
|
||||
const unsigned int val);
|
||||
template <> bool fillConstant(int* arrayPtr, const int width, const int height, const int val);
|
||||
template <> bool fillConstant(long* arrayPtr, const int width, const int height, const long val);
|
||||
template <> bool fillConstant(long* arrayPtr, const int width, const int height, const long val);
|
||||
template <> bool fillConstant(long* arrayPtr, const int width, const int height, const long val);
|
||||
|
||||
template std::string toString<char>(char t, std::ios_base& (*r)(std::ios_base&));
|
||||
template std::string toString<short>(short t, std::ios_base& (*r)(std::ios_base&));
|
||||
+9
-60
@@ -21,53 +21,10 @@ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
********************************************************************/
|
||||
#ifndef HELPER_FUNCS_HPP_
|
||||
#define HELPER_FUNCS_HPP_
|
||||
#ifndef _HELPER_FUNCS_H_
|
||||
#define _HELPER_FUNCS_H_
|
||||
|
||||
#define HSA_SDK_SUCCESS 0
|
||||
#define HSA_SDK_FAILURE 1
|
||||
#define HSA_SDK_EXPECTED_FAILURE 2
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
#include <cmath>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
#include <malloc.h>
|
||||
|
||||
/**
|
||||
* error
|
||||
* constant function, Prints error messages
|
||||
* @param errorMsg char* message
|
||||
*/
|
||||
void error(const char* errorMsg);
|
||||
|
||||
/**
|
||||
* error
|
||||
* constant function, Prints error messages
|
||||
* @param errorMsg std::string message
|
||||
*/
|
||||
void error(std::string errorMsg);
|
||||
|
||||
/**
|
||||
* expectedError
|
||||
* constant function, Prints error messages
|
||||
* @param errorMsg char* message
|
||||
*/
|
||||
void expectedError(const char* errorMsg);
|
||||
|
||||
/**
|
||||
* expectedError
|
||||
* constant function, Prints error messages
|
||||
* @param errorMsg string message
|
||||
*/
|
||||
void expectedError(std::string errorMsg);
|
||||
|
||||
/**
|
||||
* compare template version
|
||||
@@ -95,20 +52,21 @@ void printArray(const std::string header, const T* data, const int width, const
|
||||
* fill array with random values
|
||||
*/
|
||||
template <typename T>
|
||||
int fillRandom(T* arrayPtr, const int width, const int height, const T rangeMin, const T rangeMax,
|
||||
unsigned int seed = 123);
|
||||
bool fillRandom(T* arrayPtr, const int width, const int height, const T rangeMin, const T rangeMax,
|
||||
unsigned int seed = 123);
|
||||
|
||||
/**
|
||||
* fillPos
|
||||
* fill the specified positions
|
||||
*/
|
||||
template <typename T> int fillPos(T* arrayPtr, const int width, const int height);
|
||||
template <typename T> bool fillPos(T* arrayPtr, const int width, const int height);
|
||||
|
||||
/**
|
||||
* fillConstant
|
||||
* fill the array with constant value
|
||||
*/
|
||||
template <typename T> int fillConstant(T* arrayPtr, const int width, const int height, const T val);
|
||||
template <typename T>
|
||||
bool fillConstant(T* arrayPtr, const int width, const int height, const T val);
|
||||
|
||||
|
||||
/**
|
||||
@@ -121,15 +79,7 @@ template <typename T> T roundToPowerOf2(T val);
|
||||
* isPowerOf2
|
||||
* checks if input is a power of 2
|
||||
*/
|
||||
template <typename T> int isPowerOf2(T val);
|
||||
|
||||
/**
|
||||
* checkVal
|
||||
* Set default(isAPIerror) parameter to false
|
||||
* if checkVaul is used to check otherthan OpenCL API error code
|
||||
*/
|
||||
template <typename T>
|
||||
bool checkVal(T input, T reference, std::string message, bool isAPIerror = true);
|
||||
template <typename T> bool isPowerOf2(T val);
|
||||
|
||||
/**
|
||||
* toString
|
||||
@@ -137,5 +87,4 @@ bool checkVal(T input, T reference, std::string message, bool isAPIerror = true)
|
||||
*/
|
||||
template <typename T> std::string toString(T t, std::ios_base& (*r)(std::ios_base&));
|
||||
|
||||
|
||||
#endif
|
||||
#endif // _HELPER_FUNCS_H_
|
||||
+1
-3
@@ -10,12 +10,10 @@
|
||||
#include <string>
|
||||
|
||||
#include "hsa.h"
|
||||
#include "hsa_rsrc_factory.hpp"
|
||||
#include "hsa_rsrc_factory.h"
|
||||
#include "hsa_ext_finalize.h"
|
||||
#include "hsa_ext_profiler.h"
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
// Provide access to command line arguments passed in by user
|
||||
+1
-1
@@ -10,7 +10,7 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "hsatimer.h"
|
||||
#include "perf_timer.h"
|
||||
#include "hsa.h"
|
||||
#include "hsa_ext_finalize.h"
|
||||
|
||||
+7
-18
@@ -1,4 +1,4 @@
|
||||
#include "hsatimer.h"
|
||||
#include "perf_timer.h"
|
||||
|
||||
PerfTimer::PerfTimer() { freq_in_100mhz = MeasureTSCFreqHz(); }
|
||||
|
||||
@@ -30,7 +30,7 @@ int PerfTimer::CreateTimer() {
|
||||
int PerfTimer::StartTimer(int index) {
|
||||
if (index >= (int)_timers.size()) {
|
||||
Error("Cannot reset timer. Invalid handle.");
|
||||
return HSA_FAILURE;
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -41,9 +41,7 @@ int PerfTimer::StartTimer(int index) {
|
||||
_timers[index]->_start = (double)tmpStart;
|
||||
#else
|
||||
// AMD Windows timing method
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
// General Linux timing method
|
||||
#ifndef _AMD
|
||||
@@ -51,17 +49,13 @@ int PerfTimer::StartTimer(int index) {
|
||||
gettimeofday(&s, 0);
|
||||
_timers[index]->_start = s.tv_sec * 1.0E3 + ((double)(s.tv_usec / 1.0E3));
|
||||
#else
|
||||
|
||||
// AMD timing method
|
||||
|
||||
unsigned int unused;
|
||||
_timers[index]->_start = __rdtscp(&unused);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
return HSA_SUCCESS;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +63,7 @@ int PerfTimer::StopTimer(int index) {
|
||||
double n = 0;
|
||||
if (index >= (int)_timers.size()) {
|
||||
Error("Cannot reset timer. Invalid handle.");
|
||||
return HSA_FAILURE;
|
||||
return FAILURE;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
#ifndef _AMD
|
||||
@@ -77,9 +71,7 @@ int PerfTimer::StopTimer(int index) {
|
||||
QueryPerformanceCounter((LARGE_INTEGER*)&(n1));
|
||||
n = (double)n1;
|
||||
#else
|
||||
|
||||
// AMD Window Timing
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
@@ -90,11 +82,9 @@ int PerfTimer::StopTimer(int index) {
|
||||
n = s.tv_sec * 1.0E3 + (double)(s.tv_usec / 1.0E3);
|
||||
#else
|
||||
// AMD Linux timing
|
||||
|
||||
unsigned int unused;
|
||||
n = __rdtscp(&unused);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
n -= _timers[index]->_start;
|
||||
@@ -105,10 +95,9 @@ int PerfTimer::StopTimer(int index) {
|
||||
#else
|
||||
//_timers[index]->_clocks += 10 * n /freq_in_100mhz; // unit is ns
|
||||
_timers[index]->_clocks += 1.0E-6 * 10 * n / freq_in_100mhz; // convert to ms
|
||||
cout << "_AMD is enabled!!!" << endl;
|
||||
#endif
|
||||
|
||||
return HSA_SUCCESS;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
void PerfTimer::Error(string str) { cout << str << endl; }
|
||||
@@ -117,7 +106,7 @@ void PerfTimer::Error(string str) { cout << str << endl; }
|
||||
double PerfTimer::ReadTimer(int index) {
|
||||
if (index >= (int)_timers.size()) {
|
||||
Error("Cannot read timer. Invalid handle.");
|
||||
return HSA_FAILURE;
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
double reading = double(_timers[index]->_clocks);
|
||||
+20
-26
@@ -1,5 +1,5 @@
|
||||
#ifndef __MYTIME__
|
||||
#define __MYTIME__
|
||||
#ifndef _PERF_TIMER_H_
|
||||
#define _PERF_TIMER_H_
|
||||
|
||||
// Will use AMD timer and general Linux timer based on users' need --> compilation flag
|
||||
// need to consider platform is Windows or Linux
|
||||
@@ -11,8 +11,6 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <time.h>
|
||||
#include <windows.h>
|
||||
@@ -24,10 +22,25 @@ using namespace std;
|
||||
#endif // __GNUC__
|
||||
#endif //_MSC_VER
|
||||
|
||||
#define HSA_FAILURE 1
|
||||
#define HSA_SUCCESS 0
|
||||
using namespace std;
|
||||
|
||||
class PerfTimer {
|
||||
public:
|
||||
enum { SUCCESS = 0, FAILURE = 1 };
|
||||
|
||||
PerfTimer();
|
||||
~PerfTimer();
|
||||
|
||||
// General Linux timing method
|
||||
int CreateTimer();
|
||||
int StartTimer(int index);
|
||||
int StopTimer(int index);
|
||||
|
||||
// retrieve time
|
||||
double ReadTimer(int index);
|
||||
// write into a file
|
||||
double WriteTimer(int index);
|
||||
|
||||
private:
|
||||
struct Timer {
|
||||
string name; /* < name name of time object*/
|
||||
@@ -39,30 +52,11 @@ class PerfTimer {
|
||||
std::vector<Timer*> _timers; /*< _timers vector to Timer objects */
|
||||
double freq_in_100mhz;
|
||||
|
||||
public:
|
||||
PerfTimer();
|
||||
~PerfTimer();
|
||||
|
||||
private:
|
||||
// AMD timing method
|
||||
uint64_t CoarseTimestampUs();
|
||||
uint64_t MeasureTSCFreqHz();
|
||||
|
||||
// General Linux timing method
|
||||
|
||||
public:
|
||||
int CreateTimer();
|
||||
int StartTimer(int index);
|
||||
int StopTimer(int index);
|
||||
|
||||
public:
|
||||
// retrieve time
|
||||
double ReadTimer(int index);
|
||||
// write into a file
|
||||
double WriteTimer(int index);
|
||||
|
||||
public:
|
||||
void Error(string str);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // _PERF_TIMER_H_
|
||||
Αναφορά σε νέο ζήτημα
Block a user