diff --git a/projects/roctracer/CMakeLists.txt b/projects/roctracer/CMakeLists.txt
index 72ee504bd4..682fda8947 100644
--- a/projects/roctracer/CMakeLists.txt
+++ b/projects/roctracer/CMakeLists.txt
@@ -94,6 +94,7 @@ install ( FILES ${CMAKE_CURRENT_SOURCE_DIR}/inc/ext/prof_protocol.h DESTINATION
install ( FILES ${CMAKE_CURRENT_SOURCE_DIR}/inc/ext/hsa_rt_utils.hpp DESTINATION include/ext )
install ( FILES ${PROJECT_BINARY_DIR}/inc-link DESTINATION ../include RENAME ${ROCTRACER_NAME} )
install ( FILES ${PROJECT_BINARY_DIR}/so-link DESTINATION ../lib RENAME ${ROCTRACER_LIBRARY}.so )
+install ( FILES ${PROJECT_BINARY_DIR}/test/libtracer_tool.so DESTINATION tool )
## Packaging directives
set ( CPACK_GENERATOR "DEB" "RPM" "TGZ" )
diff --git a/projects/roctracer/inc/roctracer.h b/projects/roctracer/inc/roctracer.h
index 61c7debaaf..b8d4f346e4 100644
--- a/projects/roctracer/inc/roctracer.h
+++ b/projects/roctracer/inc/roctracer.h
@@ -76,12 +76,19 @@ const char* roctracer_error_string();
// Activity domain type
typedef activity_domain_t roctracer_domain_t;
-// Return ID string by given domain and activity/API ID
+// Return Op string by given domain and Op codes
// NULL returned on the error and the library errno is set
const char* roctracer_op_string(
- const uint32_t& domain, // tracing domain
- const uint32_t& op, // activity op ID
- const uint32_t& kind); // activity kind
+ uint32_t domain, // tracing domain
+ uint32_t op, // activity op ID
+ uint32_t kind); // activity kind
+
+// Return Op code and kind by given string
+roctracer_status_t roctracer_op_code(
+ uint32_t domain, // tracing domain
+ const char* str, // [in] op string
+ uint32_t* op, // [out] op code
+ uint32_t* kind = NULL); // [out] op kind code
// Set properties
roctracer_status_t roctracer_set_properties(
diff --git a/projects/roctracer/script/hsaap.py b/projects/roctracer/script/hsaap.py
index ed2e5df1f7..31a8076809 100755
--- a/projects/roctracer/script/hsaap.py
+++ b/projects/roctracer/script/hsaap.py
@@ -307,6 +307,7 @@ class API_DescrParser:
self.add_section('API callback functions', '', self.gen_callbacks)
self.add_section('API intercepting code', '', self.gen_intercept)
self.add_section('API get_name function', ' ', self.gen_get_name)
+ self.add_section('API get_code function', ' ', self.gen_get_code)
self.content += '\n};};\n'
self.content += '#endif // PROF_API_IMPL\n'
@@ -418,6 +419,17 @@ class API_DescrParser:
self.content += ' return "unknown";\n'
self.content += '}\n'
+ # generate API code function
+ def gen_get_code(self, n, name, call, struct):
+ if n == -1:
+ self.content += 'static uint32_t GetApiCode(const char* str) {\n'
+ return
+ if call != '-':
+ self.content += ' if (strcmp("' + call + '", str) == 0) return ' + self.api_id[call] + ';\n'
+ else:
+ self.content += ' return HSA_API_ID_NUMBER;\n'
+ self.content += '}\n'
+
# generate stream operator
def gen_out_stream(self, n, name, call, struct):
if n == -1:
diff --git a/projects/roctracer/src/core/roctracer.cpp b/projects/roctracer/src/core/roctracer.cpp
index 1f3f6c117e..a2747e34b4 100644
--- a/projects/roctracer/src/core/roctracer.cpp
+++ b/projects/roctracer/src/core/roctracer.cpp
@@ -386,13 +386,17 @@ PUBLIC_API const char* roctracer_error_string() {
return strdup(roctracer::util::Logger::LastMessage().c_str());
}
-// Return ID string by given domain and activity/API ID
+// Return Op string by given domain and activity/API codes
// NULL returned on the error and the library errno is set
-PUBLIC_API const char* roctracer_op_string(const uint32_t& domain, const uint32_t& id, const uint32_t& kind) {
+PUBLIC_API const char* roctracer_op_string(
+ uint32_t domain,
+ uint32_t op,
+ uint32_t kind)
+{
API_METHOD_PREFIX
switch (domain) {
case ACTIVITY_DOMAIN_HSA_API: {
- return roctracer::hsa_support::GetApiName(id);
+ return roctracer::hsa_support::GetApiName(op);
break;
}
case ACTIVITY_DOMAIN_HCC_OPS: {
@@ -400,7 +404,7 @@ PUBLIC_API const char* roctracer_op_string(const uint32_t& domain, const uint32_
break;
}
case ACTIVITY_DOMAIN_HIP_API: {
- return hipApiName(id);
+ return hipApiName(op);
break;
}
default:
@@ -409,6 +413,26 @@ PUBLIC_API const char* roctracer_op_string(const uint32_t& domain, const uint32_
API_METHOD_CATCH(NULL)
}
+// Return Op code and kind by given string
+PUBLIC_API roctracer_status_t roctracer_op_code(
+ uint32_t domain,
+ const char* str,
+ uint32_t* op,
+ uint32_t* kind)
+{
+ API_METHOD_PREFIX
+ switch (domain) {
+ case ACTIVITY_DOMAIN_HSA_API: {
+ *op = roctracer::hsa_support::GetApiCode(str);
+ if (kind != NULL) *kind = 0;
+ break;
+ }
+ default:
+ EXC_RAISING(ROCTRACER_STATUS_BAD_DOMAIN, "limited domain ID(" << domain << ")");
+ }
+ API_METHOD_SUFFIX
+}
+
static inline uint32_t get_op_num(const uint32_t& domain) {
switch (domain) {
case ACTIVITY_DOMAIN_HCC_OPS: return hc::HSA_OP_ID_NUMBER;
diff --git a/projects/roctracer/test/CMakeLists.txt b/projects/roctracer/test/CMakeLists.txt
index 6a0dfddbb4..ef74c04466 100644
--- a/projects/roctracer/test/CMakeLists.txt
+++ b/projects/roctracer/test/CMakeLists.txt
@@ -23,6 +23,9 @@
cmake_minimum_required ( VERSION 2.8.12 )
set ( CMAKE_VERBOSE_MAKEFILE TRUE CACHE BOOL "Verbose Output" FORCE )
+## Path to HSA test
+set ( HSA_TEST_DIR "${TEST_DIR}/hsa/test" )
+
## test run script
set ( RUN_SCRIPT "${TEST_DIR}/run.sh" )
@@ -35,20 +38,19 @@ add_custom_target( mytest
)
## Util sources
-file( GLOB UTIL_SRC "${TEST_HSA}/util/*.cpp" )
+file( GLOB UTIL_SRC "${HSA_TEST_DIR}/util/*.cpp" )
## Build test library
set ( TEST_LIB "tracer_tool" )
set ( TEST_LIB_SRC ${TEST_DIR}/tool/tracer_tool.cpp ${UTIL_SRC} )
add_library ( ${TEST_LIB} SHARED ${TEST_LIB_SRC} )
-target_include_directories ( ${TEST_LIB} PRIVATE ${TEST_HSA} ${ROOT_DIR} ${HSA_RUNTIME_INC_PATH} ${HIP_INC_DIR} ${HCC_INC_DIR} )
+target_include_directories ( ${TEST_LIB} PRIVATE ${HSA_TEST_DIR} ${ROOT_DIR} ${HSA_RUNTIME_INC_PATH} ${HIP_INC_DIR} ${HCC_INC_DIR} )
target_link_libraries ( ${TEST_LIB} ${ROCTRACER_TARGET} ${HSA_RUNTIME_LIB} c stdc++ dl pthread rt )
-## HSA test
-set ( TEST_HSA "${TEST_DIR}/hsa/test" )
+## Build HSA test
execute_process ( COMMAND sh -xc "if [ ! -e ${TEST_DIR}/hsa ] ; then git clone https://github.com/ROCmSoftwarePlatform/hsa-class.git ${TEST_DIR}/hsa; fi" )
execute_process ( COMMAND sh -xc "if [ -e ${TEST_DIR}/hsa ] ; then cd ${TEST_DIR}/hsa && git checkout 3e7a87f; fi" )
-set ( TEST_DIR ${TEST_HSA} )
+set ( TEST_DIR ${HSA_TEST_DIR} )
add_subdirectory ( ${TEST_DIR} ${PROJECT_BINARY_DIR}/test/hsa )
## copying run script
diff --git a/projects/roctracer/test/run.sh b/projects/roctracer/test/run.sh
index ef38515ac7..da939d2fd5 100755
--- a/projects/roctracer/test/run.sh
+++ b/projects/roctracer/test/run.sh
@@ -69,6 +69,10 @@ export ROCP_THRS=1
eval_test "tool HSA test" "LD_PRELOAD='$HSA_TOOLS_LIB' ./test/hsa/ctrl"
+echo "" > input.xml
+export ROCP_INPUT=input.xml
+eval_test "tool HSA test input" "LD_PRELOAD='$HSA_TOOLS_LIB' ./test/hsa/ctrl"
+
#valgrind --leak-check=full $tbin
#valgrind --tool=massif $tbin
#ms_print massif.out.
diff --git a/projects/roctracer/test/tool/tracer_tool.cpp b/projects/roctracer/test/tool/tracer_tool.cpp
index 38d896c477..55c76f9b3f 100644
--- a/projects/roctracer/test/tool/tracer_tool.cpp
+++ b/projects/roctracer/test/tool/tracer_tool.cpp
@@ -29,6 +29,7 @@ THE SOFTWARE.
#include
#include
#include
+#include
#define PUBLIC_API __attribute__((visibility("default")))
#define CONSTRUCTOR_API __attribute__((constructor))
@@ -51,6 +52,14 @@ thread_local timestamp_t hip_begin_timestamp = 0;
bool trace_hsa = false;
bool trace_hip = false;
+// Error handler
+void fatal(const std::string msg) {
+ fflush(stdout);
+ fprintf(stderr, "%s\n\n", msg.c_str());
+ fflush(stderr);
+ abort();
+}
+
// HSA API callback function
void hsa_api_callback(
uint32_t domain,
@@ -150,22 +159,119 @@ void activity_callback(const char* begin, const char* end, void* arg) {
}
}
+// Input parser
+std::string normalize_token(const std::string& token, bool not_empty, const std::string& label) {
+ const std::string space_chars_set = " \t";
+ const size_t first_pos = token.find_first_not_of(space_chars_set);
+ size_t norm_len = 0;
+ std::string error_str = "none";
+ if (first_pos != std::string::npos) {
+ const size_t last_pos = token.find_last_not_of(space_chars_set);
+ if (last_pos == std::string::npos) error_str = "token string error: \"" + token + "\"";
+ else {
+ const size_t end_pos = last_pos + 1;
+ if (end_pos <= first_pos) error_str = "token string error: \"" + token + "\"";
+ else norm_len = end_pos - first_pos;
+ }
+ }
+ if (((first_pos != std::string::npos) && (norm_len == 0)) ||
+ ((first_pos == std::string::npos) && not_empty)) {
+ fatal("normalize_token error, " + label + ": '" + token + "'," + error_str);
+ }
+ return (norm_len != 0) ? token.substr(first_pos, norm_len) : std::string("");
+}
+
+int get_xml_array(const xml::Xml::level_t* node, const std::string& field, const std::string& delim, std::vector* vec, const char* label = NULL) {
+ int parse_iter = 0;
+ const auto& opts = node->opts;
+ auto it = opts.find(field);
+ if (it != opts.end()) {
+ const std::string array_string = it->second;
+ if (label != NULL) printf("%s%s = %s\n", label, field.c_str(), array_string.c_str());
+ size_t pos1 = 0;
+ const size_t string_len = array_string.length();
+ while (pos1 < string_len) {
+ const size_t pos2 = array_string.find(delim, pos1);
+ const bool found = (pos2 != std::string::npos);
+ const size_t token_len = (pos2 != std::string::npos) ? pos2 - pos1 : string_len - pos1;
+ const std::string token = array_string.substr(pos1, token_len);
+ const std::string norm_str = normalize_token(token, found, "get_xml_array");
+ if (norm_str.length() != 0) vec->push_back(norm_str);
+ if (!found) break;
+ pos1 = pos2 + 1;
+ ++parse_iter;
+ }
+ }
+ return parse_iter;
+}
+
// HSA-runtime tool on-load method
extern "C" PUBLIC_API bool OnLoad(HsaApiTable* table, uint64_t runtime_version, uint64_t failed_tool_count,
const char* const* failed_tool_names) {
timer = new hsa_rt_utils::Timer(table->core_->hsa_system_get_info_fn);
+ // API traces switches
const char* trace_domain = getenv("ROCTRACER_DOMAIN");
trace_hsa = (trace_domain == NULL) || (strncmp(trace_domain, "hsa", 3) == 0);
trace_hip = (trace_domain == NULL) || (strncmp(trace_domain, "hip", 3) == 0);
+ // API trace vector
+ std::vector hsa_api_vec;
+
+ // XML input
+ const char* xml_name = getenv("ROCP_INPUT");
+ if (xml_name != NULL) {
+ printf("ROCTracer: input from \"%s\"\n", xml_name);
+ xml::Xml* xml = xml::Xml::Create(xml_name);
+ if (xml == NULL) {
+ fprintf(stderr, "ROCTracer: Input file not found '%s'\n", xml_name);
+ abort();
+ }
+
+ for (const auto* entry : xml->GetNodes("top.trace")) {
+ auto it = entry->opts.find("name");
+ if (it == entry->opts.end()) fatal("ROCTracer: trace name is missing");
+ const std::string& name = it->second;
+
+ std::vector api_vec;
+ for (const auto* node : entry->nodes) {
+ if (node->tag != "parameters") fatal("ROCProfiler: trace node is not supported '" + name + ":" + node->tag + "'");
+ get_xml_array(node, "api", ",", &api_vec);
+ break;
+ }
+
+ if (name == "HSA") {
+ trace_hsa |= true;
+ hsa_api_vec = api_vec;
+ }
+ if (name == "HIP") {
+ trace_hip |= true;
+ }
+ }
+ }
+
// Enable HSA API callbacks
if (trace_hsa) {
- ROCTRACER_CALL(roctracer_enable_domain_callback(ACTIVITY_DOMAIN_HSA_API, hsa_api_callback, NULL));
+ printf(" HSA-trace");
+ if (hsa_api_vec.size() != 0) {
+ printf("(");
+ for (unsigned i = 0; i < hsa_api_vec.size(); ++i) {
+ uint32_t cid = HSA_API_ID_NUMBER;
+ const char* api = hsa_api_vec[i].c_str();
+ ROCTRACER_CALL(roctracer_op_code(ACTIVITY_DOMAIN_HSA_API, api, &cid));
+ ROCTRACER_CALL(roctracer_enable_op_callback(ACTIVITY_DOMAIN_HSA_API, cid, hsa_api_callback, NULL));
+ printf(" %s", api);
+ }
+ printf(" )");
+ } else {
+ ROCTRACER_CALL(roctracer_enable_domain_callback(ACTIVITY_DOMAIN_HSA_API, hsa_api_callback, NULL));
+ }
+ printf("\n");
}
// Enable HIP API callbacks/activity
if (trace_hip) {
+ printf(" HIP-trace\n");
// Allocating tracing pool
roctracer_properties_t properties{};
properties.buffer_size = 12;
@@ -181,8 +287,12 @@ extern "C" PUBLIC_API bool OnLoad(HsaApiTable* table, uint64_t runtime_version,
// HSA-runtime tool on-unload method
extern "C" PUBLIC_API void OnUnload() {
- if (trace_hsa) ROCTRACER_CALL(roctracer_disable_domain_callback(ACTIVITY_DOMAIN_HSA_API));
- if (trace_hip) ROCTRACER_CALL(roctracer_disable_domain_callback(ACTIVITY_DOMAIN_HIP_API));
- if (trace_hip) ROCTRACER_CALL(roctracer_disable_domain_callback(ACTIVITY_DOMAIN_HCC_OPS));
- ROCTRACER_CALL(roctracer_close_pool());
+ if (trace_hsa) {
+ ROCTRACER_CALL(roctracer_disable_domain_callback(ACTIVITY_DOMAIN_HSA_API));
+ }
+ if (trace_hip) {
+ ROCTRACER_CALL(roctracer_disable_domain_callback(ACTIVITY_DOMAIN_HIP_API));
+ ROCTRACER_CALL(roctracer_disable_domain_callback(ACTIVITY_DOMAIN_HCC_OPS));
+ ROCTRACER_CALL(roctracer_close_pool());
+ }
}