From 527aa71f5a4e8425fb65c1b5ef3d2588c16017a4 Mon Sep 17 00:00:00 2001 From: "Jonathan R. Madsen" Date: Tue, 8 Aug 2023 18:39:01 -0500 Subject: [PATCH] Initial skeleton (#1) * googletest submodule * cmake folder * misc root files - clang-format - cmake-format - pyproject.toml - requirements.txt - VERSION * workflows * RPM files * external folder * samples folder * tests root folder * source/bin folder * source/include folder * source/lib/common folder * source/lib/plugins folder * source/lib/tests folder - for library unit tests * source/lib/rocprofiler folder - rocprofiler library implementation * Remaining cmake files * lib/common/containers - ring_buffer - atomic_ring_buffer - stable_vector - static_vector * Update .gitignore * Update hsa.hpp - include cstdint * cmake formatting (cmake-format) (#2) Co-authored-by: jrmadsen * Remove linting.yml - uses self-hosted runners --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .clang-format | 114 + .cmake-format.yaml | 305 ++ .github/workflows/formatting.yml | 146 + .gitignore | 3 + .gitmodules | 3 + CMakeLists.txt | 89 + RPM/post.in | 5 + RPM/postun.in | 4 + VERSION | 1 + cmake/Modules/Findrocm_version.cmake | 302 ++ cmake/Modules/Findrocprofiler.cmake | 97 + cmake/Templates/modulefile.in | 16 + cmake/Templates/rocprofiler-config.cmake.in | 56 + cmake/Templates/setup-env.sh.in | 23 + cmake/rocprofiler_build_settings.cmake | 182 + cmake/rocprofiler_compilers.cmake | 350 ++ cmake/rocprofiler_config_install.cmake | 68 + cmake/rocprofiler_config_interfaces.cmake | 141 + cmake/rocprofiler_config_packaging.cmake | 128 + cmake/rocprofiler_formatting.cmake | 102 + cmake/rocprofiler_interfaces.cmake | 44 + cmake/rocprofiler_linting.cmake | 36 + cmake/rocprofiler_memcheck.cmake | 67 + cmake/rocprofiler_options.cmake | 104 + cmake/rocprofiler_utilities.cmake | 928 ++++ external/CMakeLists.txt | 29 + external/googletest | 1 + pyproject.toml | 25 + requirements.txt | 10 + samples/CMakeLists.txt | 1 + source/CMakeLists.txt | 6 + source/bin/CMakeLists.txt | 1 + source/bin/tests/CMakeLists.txt | 1 + source/include/CMakeLists.txt | 4 + source/include/rocprofiler/CMakeLists.txt | 8 + source/include/rocprofiler/config.h | 189 + source/include/rocprofiler/rocprofiler.h | 2340 +++++++++ .../include/rocprofiler/rocprofiler_plugin.h | 142 + source/lib/CMakeLists.txt | 10 + source/lib/common/CMakeLists.txt | 26 + source/lib/common/config.cpp | 433 ++ source/lib/common/config.hpp | 99 + source/lib/common/container/CMakeLists.txt | 10 + .../common/container/atomic_ring_buffer.cpp | 297 ++ .../common/container/atomic_ring_buffer.hpp | 426 ++ source/lib/common/container/c_array.hpp | 136 + source/lib/common/container/operators.hpp | 239 + source/lib/common/container/ring_buffer.cpp | 289 ++ source/lib/common/container/ring_buffer.hpp | 495 ++ source/lib/common/container/stable_vector.hpp | 389 ++ source/lib/common/container/static_vector.hpp | 221 + source/lib/common/defines.hpp | 65 + source/lib/common/environment.hpp | 185 + source/lib/common/helper.cpp | 373 ++ source/lib/common/helper.hpp | 68 + source/lib/common/join.hpp | 183 + source/lib/common/log.hpp | 140 + source/lib/common/units.hpp | 376 ++ source/lib/plugins/CMakeLists.txt | 1 + source/lib/rocprofiler/CMakeLists.txt | 30 + source/lib/rocprofiler/config_helpers.hpp | 107 + source/lib/rocprofiler/config_internal.cpp | 28 + source/lib/rocprofiler/config_internal.hpp | 74 + source/lib/rocprofiler/hsa/CMakeLists.txt | 10 + source/lib/rocprofiler/hsa/hsa-defines.hpp | 266 + source/lib/rocprofiler/hsa/hsa-ostream.hpp | 1767 +++++++ source/lib/rocprofiler/hsa/hsa-types.h | 1456 ++++++ source/lib/rocprofiler/hsa/hsa-utils.hpp | 99 + source/lib/rocprofiler/hsa/hsa.cpp | 485 ++ source/lib/rocprofiler/hsa/hsa.gen.cpp | 217 + source/lib/rocprofiler/hsa/hsa.hpp | 124 + source/lib/rocprofiler/rocprofiler_config.cpp | 4382 +++++++++++++++++ source/lib/rocprofiler/tracer.hpp | 515 ++ source/lib/tests/CMakeLists.txt | 1 + tests/CMakeLists.txt | 1 + 75 files changed, 20094 insertions(+) create mode 100644 .clang-format create mode 100644 .cmake-format.yaml create mode 100644 .github/workflows/formatting.yml create mode 100644 .gitmodules create mode 100644 CMakeLists.txt create mode 100644 RPM/post.in create mode 100644 RPM/postun.in create mode 100644 VERSION create mode 100644 cmake/Modules/Findrocm_version.cmake create mode 100644 cmake/Modules/Findrocprofiler.cmake create mode 100644 cmake/Templates/modulefile.in create mode 100644 cmake/Templates/rocprofiler-config.cmake.in create mode 100644 cmake/Templates/setup-env.sh.in create mode 100644 cmake/rocprofiler_build_settings.cmake create mode 100644 cmake/rocprofiler_compilers.cmake create mode 100644 cmake/rocprofiler_config_install.cmake create mode 100644 cmake/rocprofiler_config_interfaces.cmake create mode 100644 cmake/rocprofiler_config_packaging.cmake create mode 100644 cmake/rocprofiler_formatting.cmake create mode 100644 cmake/rocprofiler_interfaces.cmake create mode 100644 cmake/rocprofiler_linting.cmake create mode 100644 cmake/rocprofiler_memcheck.cmake create mode 100644 cmake/rocprofiler_options.cmake create mode 100644 cmake/rocprofiler_utilities.cmake create mode 100644 external/CMakeLists.txt create mode 160000 external/googletest create mode 100644 pyproject.toml create mode 100644 requirements.txt create mode 100644 samples/CMakeLists.txt create mode 100644 source/CMakeLists.txt create mode 100644 source/bin/CMakeLists.txt create mode 100644 source/bin/tests/CMakeLists.txt create mode 100644 source/include/CMakeLists.txt create mode 100644 source/include/rocprofiler/CMakeLists.txt create mode 100644 source/include/rocprofiler/config.h create mode 100644 source/include/rocprofiler/rocprofiler.h create mode 100644 source/include/rocprofiler/rocprofiler_plugin.h create mode 100644 source/lib/CMakeLists.txt create mode 100644 source/lib/common/CMakeLists.txt create mode 100644 source/lib/common/config.cpp create mode 100644 source/lib/common/config.hpp create mode 100644 source/lib/common/container/CMakeLists.txt create mode 100644 source/lib/common/container/atomic_ring_buffer.cpp create mode 100644 source/lib/common/container/atomic_ring_buffer.hpp create mode 100644 source/lib/common/container/c_array.hpp create mode 100644 source/lib/common/container/operators.hpp create mode 100644 source/lib/common/container/ring_buffer.cpp create mode 100644 source/lib/common/container/ring_buffer.hpp create mode 100644 source/lib/common/container/stable_vector.hpp create mode 100644 source/lib/common/container/static_vector.hpp create mode 100644 source/lib/common/defines.hpp create mode 100644 source/lib/common/environment.hpp create mode 100644 source/lib/common/helper.cpp create mode 100644 source/lib/common/helper.hpp create mode 100644 source/lib/common/join.hpp create mode 100644 source/lib/common/log.hpp create mode 100644 source/lib/common/units.hpp create mode 100644 source/lib/plugins/CMakeLists.txt create mode 100644 source/lib/rocprofiler/CMakeLists.txt create mode 100644 source/lib/rocprofiler/config_helpers.hpp create mode 100644 source/lib/rocprofiler/config_internal.cpp create mode 100644 source/lib/rocprofiler/config_internal.hpp create mode 100644 source/lib/rocprofiler/hsa/CMakeLists.txt create mode 100644 source/lib/rocprofiler/hsa/hsa-defines.hpp create mode 100644 source/lib/rocprofiler/hsa/hsa-ostream.hpp create mode 100644 source/lib/rocprofiler/hsa/hsa-types.h create mode 100644 source/lib/rocprofiler/hsa/hsa-utils.hpp create mode 100644 source/lib/rocprofiler/hsa/hsa.cpp create mode 100644 source/lib/rocprofiler/hsa/hsa.gen.cpp create mode 100644 source/lib/rocprofiler/hsa/hsa.hpp create mode 100644 source/lib/rocprofiler/rocprofiler_config.cpp create mode 100644 source/lib/rocprofiler/tracer.hpp create mode 100644 source/lib/tests/CMakeLists.txt create mode 100644 tests/CMakeLists.txt diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000..49ed9e082f --- /dev/null +++ b/.clang-format @@ -0,0 +1,114 @@ +# clang-format v11 +--- +Language: Cpp +BasedOnStyle: Google +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: true +AlignConsecutiveAssignments: true +AlignConsecutiveBitFields: true +AlignConsecutiveDeclarations: true +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: TopLevel +AlwaysBreakAfterReturnType: TopLevel +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: Always + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: true + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: true +BreakInheritanceList: BeforeComma +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeComma +BreakStringLiterals: true +ColumnLimit: 100 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: true +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 0 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +IncludeBlocks: Preserve +IndentCaseLabels: true +IndentCaseBlocks: false +IndentFunctionDeclarationAfterType: false +IndentGotoLabels: true +IndentPPDirectives: AfterHash +IndentExternBlock: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: false +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +ReflowComments: true +SortIncludes: false +SortUsingDeclarations: true +SpaceAfterCStyleCast: true +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: Never +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +Standard: Auto +TabWidth: 4 +UseTab: Never +... diff --git a/.cmake-format.yaml b/.cmake-format.yaml new file mode 100644 index 0000000000..cfe16426a5 --- /dev/null +++ b/.cmake-format.yaml @@ -0,0 +1,305 @@ +parse: + additional_commands: + rocprofiler_checkout_git_submodule: + flags: + - RECURSIVE + kwargs: + RELATIVE_PATH: '*' + WORKING_DIRECTORY: '*' + TEST_FILE: '*' + REPO_URL: '*' + REPO_BRANCH: '*' + ADDITIONAL_COMMANDS: '*' + rocprofiler_save_variables: + kwargs: + VARIABLES: '*' + CONDITION: '*' + rocprofiler_restore_variables: + kwargs: + VARIABLES: '*' + CONDITION: '*' + rocprofiler_target_compile_options: + flags: + - BUILD_INTERFACE + - FORCE + kwargs: + PUBLIC: '*' + PRIVATE: '*' + INTERFACE: '*' + LANGUAGES: '*' + LINK_LANGUAGES: '*' + rocprofiler_add_test: + flags: + - SKIP_BASELINE + - SKIP_SAMPLING + - SKIP_REWRITE + - SKIP_RUNTIME + kwargs: + NAME: '*' + TARGET: '*' + MPI: '*' + GPU: '*' + NUM_PROCS: '*' + REWRITE_TIMEOUT: '*' + RUNTIME_TIMEOUT: '*' + SAMPLING_TIMEOUT: '*' + SAMPLING_ARGS: '*' + REWRITE_ARGS: '*' + RUNTIME_ARGS: '*' + RUN_ARGS: '*' + ENVIRONMENT: '*' + LABELS: '*' + PROPERTIES: '*' + SAMPLING_PASS_REGEX: '*' + SAMPLING_FAIL_REGEX: '*' + RUNTIME_PASS_REGEX: '*' + RUNTIME_FAIL_REGEX: '*' + REWRITE_PASS_REGEX: '*' + REWRITE_FAIL_REGEX: '*' + BASELINE_PASS_REGEX: '*' + BASELINE_FAIL_REGEX: '*' + REWRITE_RUN_PASS_REGEX: '*' + REWRITE_RUN_FAIL_REGEX: '*' + rocprofiler_add_causal_test: + flags: + - SKIP_BASELINE + kwargs: + NAME: '*' + TARGET: '*' + CAUSAL_TIMEOUT: '*' + CAUSAL_VALIDATE_TIMEOUT: '*' + CAUSAL_MODE: '*' + CAUSAL_ARGS: '*' + CAUSAL_VALIDATE_ARGS: '*' + RUNTIME_ARGS: '*' + RUN_ARGS: '*' + ENVIRONMENT: '*' + LABELS: '*' + PROPERTIES: '*' + CAUSAL_PASS_REGEX: '*' + CAUSAL_FAIL_REGEX: '*' + BASELINE_PASS_REGEX: '*' + BASELINE_FAIL_REGEX: '*' + CAUSAL_VALIDATE_PASS_REGEX: '*' + CAUSAL_VALIDATE_FAIL_REGEX: '*' + rocprofiler_target_compile_definitions: + kwargs: + PUBLIC: '*' + PRIVATE: '*' + INTERFACE: '*' + rocprofiler_add_bin_test: + flags: + - WILL_FAIL + kwargs: + NAME: '*' + ARGS: '*' + LABELS: '*' + TARGET: '*' + DEPENDS: '*' + COMMAND: '*' + TIMEOUT: '*' + PROPERTIES: '*' + ENVIRONMENT: '*' + WORKING_DIRECTORY: '*' + PASS_REGEX: '*' + FAIL_REGEX: '*' + SKIP_REGEX: '*' + rocprofiler_add_python_test: + flags: + - STANDALONE + kwargs: + NAME: '*' + FILE: '*' + TIMEOUT: '*' + PROFILE_ARGS: '*' + RUN_ARGS: '*' + ENVIRONMENT: '*' + LABELS: '*' + DEPENDS: '*' + COMMAND: '*' + PROPERTIES: '*' + PYTHON_EXECUTABLE: '*' + PYTHON_VERSION: '*' + PASS_REGEX: '*' + FAIL_REGEX: '*' + SKIP_REGEX: '*' + rocprofiler_add_python_validation_test: + kwargs: + NAME: '*' + ARGS: '*' + PERFETTO_FILE: '*' + PERFETTO_METRIC: '*' + TIMEMORY_FILE: '*' + TIMEMORY_METRIC: '*' + rocm_version_message: + flags: + - STATUS + - WARNING + - SEND_ERROR + - FATAL_ERROR + - AUTHOR_WARNING + rocprofiler_find_python: + flags: + - REQUIRED + - QUIET + kwargs: + VERSION: '*' + ROOT_DIR: '*' + COMPONENTS: '*' + rocprofiler_python_console_script: + kwargs: + VERSION: '*' + ROOT_DIR: '*' + rocprofiler_pybind11_add_module: + flags: + - MODULE + - SHARED + - EXCLUDE_FROM_ALL + - NO_EXTRAS + - SYSTEM + - THIN_LTO + - LTO + kwargs: + PYTHON_VERSION: '*' + CXX_STANDARD: '*' + VISIBILITY: '*' + rocprofiler_directory: + flags: + - MKDIR + - FAIL + kwargs: + PREFIX: '*' + OUTPUT_VARIABLE: '*' + WORKING_DIRECTORY: '*' + PATHS: '*' + rocprofiler_check_python_dirs_and_versions: + flags: + - UNSET + - FAIL + kwargs: + RESULT_VARIABLE: '*' + OUTPUT_VARIABLE: '*' + rocprofiler_find_static_library: + flags: + - NO_CACHE + - REQUIRED + - NO_DEFAULT_PATH + - NO_PACKAGE_ROOT_PATH + - NO_CMAKE_PATH + - NO_CMAKE_ENVIRONMENT_PATH + - NO_SYSTEM_ENVIRONMENT_PATH + - CMAKE_FIND_ROOT_PATH_BOTH + - ONLY_CMAKE_FIND_ROOT_PATH + - NO_CMAKE_FIND_ROOT_PATH + kwargs: + NAMES: '*' + NAMES_PER_DIR: '*' + HINTS: '*' + PATHS: '*' + PATH_SUFFIXES: '*' + DOC: '*' + rocprofiler_find_shared_library: + flags: + - NO_CACHE + - REQUIRED + - NO_DEFAULT_PATH + - NO_PACKAGE_ROOT_PATH + - NO_CMAKE_PATH + - NO_CMAKE_ENVIRONMENT_PATH + - NO_SYSTEM_ENVIRONMENT_PATH + - CMAKE_FIND_ROOT_PATH_BOTH + - ONLY_CMAKE_FIND_ROOT_PATH + - NO_CMAKE_FIND_ROOT_PATH + kwargs: + NAMES: '*' + NAMES_PER_DIR: '*' + HINTS: '*' + PATHS: '*' + PATH_SUFFIXES: '*' + DOC: '*' + rocprofiler_causal_example_executable: + kwargs: + TAG: '*' + SOURCES: '*' + DEFINITIONS: '*' + LINK_LIBRARIES: '*' + INCLUDE_DIRECTORIES: '*' + rocprofiler_add_validation_test: + kwargs: + NAME: '*' + ARGS: '*' + LABELS: '*' + TIMEOUT: '*' + DEPENDS: '*' + PROPERTIES: '*' + PASS_REGEX: '*' + FAIL_REGEX: '*' + SKIP_REGEX: '*' + ENVIRONMENT: '*' + PERFETTO_FILE: '*' + PERFETTO_METRIC: '*' + TIMEMORY_FILE: '*' + TIMEMORY_METRIC: '*' + override_spec: {} + vartags: [] + proptags: [] +format: + disable: false + line_width: 90 + tab_size: 4 + use_tabchars: false + fractional_tab_policy: use-space + max_subgroups_hwrap: 2 + max_pargs_hwrap: 8 + max_rows_cmdline: 2 + separate_ctrl_name_with_space: false + separate_fn_name_with_space: false + dangle_parens: false + dangle_align: child + min_prefix_chars: 4 + max_prefix_chars: 10 + max_lines_hwrap: 2 + line_ending: unix + command_case: lower + keyword_case: upper + always_wrap: [] + enable_sort: true + autosort: false + require_valid_layout: false + layout_passes: {} +markup: + bullet_char: '*' + enum_char: . + first_comment_is_literal: true + literal_comment_pattern: ^# + fence_pattern: ^\s*([`~]{3}[`~]*)(.*)$ + ruler_pattern: ^\s*[^\w\s]{3}.*[^\w\s]{3}$ + explicit_trailing_pattern: '#<' + hashruler_min_length: 10 + canonicalize_hashrulers: true + enable_markup: true +lint: + disabled_codes: [] + function_pattern: '[0-9a-z_]+' + macro_pattern: '[0-9A-Z_]+' + global_var_pattern: '[A-Z][0-9A-Z_]+' + internal_var_pattern: _[A-Z][0-9A-Z_]+ + local_var_pattern: '[a-z][a-z0-9_]+' + private_var_pattern: _[0-9a-z_]+ + public_var_pattern: '[A-Z][0-9A-Z_]+' + argument_var_pattern: '[a-z][a-z0-9_]+' + keyword_pattern: '[A-Z][0-9A-Z_]+' + max_conditionals_custom_parser: 2 + min_statement_spacing: 1 + max_statement_spacing: 2 + max_returns: 6 + max_branches: 12 + max_arguments: 5 + max_localvars: 15 + max_statements: 50 +encode: + emit_byteorder_mark: false + input_encoding: utf-8 + output_encoding: utf-8 +misc: + per_command: {} diff --git a/.github/workflows/formatting.yml b/.github/workflows/formatting.yml new file mode 100644 index 0000000000..7cbbb93f75 --- /dev/null +++ b/.github/workflows/formatting.yml @@ -0,0 +1,146 @@ + +name: Formatting + +on: + workflow_dispatch: + pull_request: + branches: [ main ] + paths-ignore: + - '.github/workflows/pull_*.yml' + - '.github/workflows/linting.yml' + - '.github/workflows/markdown_lint.yml' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + cmake: + runs-on: ubuntu-22.04 + + steps: + - uses: actions/checkout@v3 + + - name: Extract branch name + shell: bash + run: | + echo "branch=${GITHUB_HEAD_REF:-${GITHUB_HEAD_REF#refs/heads/}}" >> $GITHUB_OUTPUT + id: extract_branch + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y python3-pip + python3 -m pip install -U cmake-format + + - name: Run cmake-format + run: | + set +e + cmake-format -i $(find . -type f | egrep 'CMakeLists.txt|\.cmake$') + if [ $(git diff | wc -l) -ne 0 ]; then + echo -e "\nError! CMake code not formatted. Run cmake-format...\n" + echo -e "\nFiles:\n" + git diff --name-only + echo -e "\nFull diff:\n" + git diff + exit 1 + fi + + - name: Create pull request + if: failure() + uses: peter-evans/create-pull-request@v5 + with: + commit-message: "cmake formatting (cmake-format)" + branch: ${{ steps.extract_branch.outputs.branch }}-cmake-format + delete-branch: true + title: "Format cmake code (via cmake-format) on ${{ steps.extract_branch.outputs.branch }}" + base: ${{ steps.extract_branch.outputs.branch }} + + source: + runs-on: ubuntu-22.04 + + steps: + - uses: actions/checkout@v3 + + - name: Install dependencies + run: | + DISTRIB_CODENAME=$(cat /etc/lsb-release | grep DISTRIB_CODENAME | awk -F '=' '{print $NF}') + sudo apt-get update + sudo apt-get install -y software-properties-common wget curl clang-format-11 + + - name: Extract branch name + shell: bash + run: | + echo "branch=${GITHUB_HEAD_REF:-${GITHUB_HEAD_REF#refs/heads/}}" >> $GITHUB_OUTPUT + id: extract_branch + + - name: Run clang-format + run: | + set +e + FILES=$(find samples source tests -type f | egrep '\.(h|hpp|hh|c|cc|cpp)(|\.in)$') + FORMAT_OUT=$(clang-format-11 -i ${FILES}) + if [ $(git diff | wc -l) -ne 0 ]; then + echo -e "\nError! Code not formatted. Run clang-format (version 11)...\n" + echo -e "\nFiles:\n" + git diff --name-only + echo -e "\nFull diff:\n" + git diff + exit 1 + fi + + - name: Create pull request + if: failure() + uses: peter-evans/create-pull-request@v5 + with: + commit-message: "source formatting (clang-format v11)" + branch: ${{ steps.extract_branch.outputs.branch }}-clang-format + delete-branch: true + title: "Format source code (via clang-format v11) on ${{ steps.extract_branch.outputs.branch }}" + base: ${{ steps.extract_branch.outputs.branch }} + + python: + runs-on: ubuntu-22.04 + strategy: + matrix: + python-version: ['3.10'] + + steps: + - uses: actions/checkout@v3 + + - name: Extract branch name + shell: bash + run: | + echo "branch=${GITHUB_HEAD_REF:-${GITHUB_HEAD_REF#refs/heads/}}" >> $GITHUB_OUTPUT + id: extract_branch + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install black + + - name: black format + run: | + black . + if [ $(git diff | wc -l) -ne 0 ]; then + echo -e "\nError! Python code not formatted. Run black...\n" + echo -e "\nFiles:\n" + git diff --name-only + echo -e "\nFull diff:\n" + git diff + exit 1 + fi + + - name: Create pull request + if: failure() + uses: peter-evans/create-pull-request@v5 + with: + commit-message: "python formatting (black)" + branch: ${{ steps.extract_branch.outputs.branch }}-python-format + delete-branch: true + title: "Format python code (via black) on ${{ steps.extract_branch.outputs.branch }}" + base: ${{ steps.extract_branch.outputs.branch }} diff --git a/.gitignore b/.gitignore index 259148fa18..a34c72785f 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,6 @@ *.exe *.out *.app + +# Build directories +/build* diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..bab1865156 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "external/googletest"] + path = external/googletest + url = https://github.com/google/googletest.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..aa986460c5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,89 @@ +cmake_minimum_required(VERSION 3.16 FATAL_ERROR) + +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR AND CMAKE_CURRENT_SOURCE_DIR STREQUAL + CMAKE_SOURCE_DIR) + set(MSG "") + message(STATUS "Warning! Building from the source directory is not recommended") + message(STATUS "If unintended, please remove 'CMakeCache.txt' and 'CMakeFiles'") + message(STATUS "and build from a separate directory") + message(AUTHOR_WARNING "In-source build") +endif() + +file(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" FULL_VERSION_STRING LIMIT_COUNT 1) +string(REGEX REPLACE "(\n|\r)" "" FULL_VERSION_STRING "${FULL_VERSION_STRING}") +string(REGEX REPLACE "([0-9]+)\.([0-9]+)\.([0-9]+)(.*)" "\\1.\\2.\\3" ROCPROFILER_VERSION + "${FULL_VERSION_STRING}") + +project( + rocprofiler + LANGUAGES C CXX + VERSION ${ROCPROFILER_VERSION} + DESCRIPTION "ROCm GPU performance analysis" + HOMEPAGE_URL "https://github.com/ROCm-Developer-Tools/rocprofiler-v2-internal") + +find_package(Git) + +if(Git_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git") + execute_process( + COMMAND ${GIT_EXECUTABLE} describe --tags + OUTPUT_VARIABLE ROCPROFILER_GIT_DESCRIBE + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE _GIT_DESCRIBE_RESULT + ERROR_QUIET) + + if(NOT _GIT_DESCRIBE_RESULT EQUAL 0) + execute_process( + COMMAND ${GIT_EXECUTABLE} describe + OUTPUT_VARIABLE ROCPROFILER_GIT_DESCRIBE + OUTPUT_STRIP_TRAILING_WHITESPACE + RESULT_VARIABLE _GIT_DESCRIBE_RESULT + ERROR_QUIET) + endif() + + execute_process( + COMMAND ${GIT_EXECUTABLE} rev-parse HEAD + OUTPUT_VARIABLE ROCPROFILER_GIT_REVISION + OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) +else() + set(ROCPROFILER_GIT_DESCRIBE "v${ROCPROFILER_VERSION}") + set(ROCPROFILER_GIT_REVISION "") +endif() + +message( + STATUS + "[${PROJECT_NAME}] version ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} (${FULL_VERSION_STRING})" + ) +message(STATUS "[${PROJECT_NAME}] git revision: ${ROCPROFILER_GIT_REVISION}") +message(STATUS "[${PROJECT_NAME}] git describe: ${ROCPROFILER_GIT_DESCRIBE}") +set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ${PROJECT_SOURCE_DIR}/cmake/Modules + ${CMAKE_MODULE_PATH}) + +include(GNUInstallDirs) # install directories + +include(rocprofiler_utilities) # various functions/macros +include(rocprofiler_interfaces) # interface libraries +include(rocprofiler_compilers) # compiler identification +include(rocprofiler_options) # project options +include(rocprofiler_build_settings) # build flags +include(rocprofiler_formatting) # formatting +include(rocprofiler_linting) # clang-tidy +include(rocprofiler_config_interfaces) # configure interface libraries + +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}") + +add_subdirectory(external) +add_subdirectory(source) + +if(ROCPROFILER_BUILD_TESTS) + add_subdirectory(tests) +endif() + +if(ROCPROFILER_BUILD_SAMPLES) + add_subdirectory(samples) +endif() + +# +include(rocprofiler_config_install) +include(rocprofiler_config_packaging) diff --git a/RPM/post.in b/RPM/post.in new file mode 100644 index 0000000000..3fb4dd57af --- /dev/null +++ b/RPM/post.in @@ -0,0 +1,5 @@ +# left-hand term originates from ENABLE_LDCONFIG = ON/OFF at package build +if [ "@ENABLE_LDCONFIG@" == "ON" ]; then + echo @CPACK_PACKAGING_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@ > /@CMAKE_INSTALL_SYSCONFDIR@/ld.so.conf.d/librocprofiler64.conf + ldconfig +fi diff --git a/RPM/postun.in b/RPM/postun.in new file mode 100644 index 0000000000..c5750b65e2 --- /dev/null +++ b/RPM/postun.in @@ -0,0 +1,4 @@ +# left-hand term originates from ENABLE_LDCONFIG = ON/OFF at package build +if [ "@ENABLE_LDCONFIG@" == "ON" ]; then + rm -f /@CMAKE_INSTALL_SYSCONFDIR@/ld.so.conf.d/librocprofiler64.conf && ldconfig +fi diff --git a/VERSION b/VERSION new file mode 100644 index 0000000000..227cea2156 --- /dev/null +++ b/VERSION @@ -0,0 +1 @@ +2.0.0 diff --git a/cmake/Modules/Findrocm_version.cmake b/cmake/Modules/Findrocm_version.cmake new file mode 100644 index 0000000000..7c8482f490 --- /dev/null +++ b/cmake/Modules/Findrocm_version.cmake @@ -0,0 +1,302 @@ +#[=======================================================================[.rst: +Findrocm_version +--------------- + +Search the /.info/version* files to determine the version of ROCm + +Use this module by invoking find_package with the form:: + + find_package(rocm_version + [version] [EXACT] + [REQUIRED]) + +This module finds the version info for ROCm. The cached variables are:: + + rocm_version_FOUND - Whether the ROCm versioning was found + rocm_version_FULL_VERSION - The exact string from `/.info/version` or similar + rocm_version_MAJOR_VERSION - Major version, e.g. 4 in 4.5.2.100-40502 + rocm_version_MINOR_VERSION - Minor version, e.g. 5 in 4.5.2.100-40502 + rocm_version_PATCH_VERSION - Patch version, e.g. 2 in 4.5.2.100-40502 + rocm_version_TWEAK_VERSION - Tweak version, e.g. 100 in 4.5.2.100-40502 + rocm_version_REVISION_VERSION - Revision version, e.g. 40502 in 4.5.2.100-40502. + rocm_version_EPOCH_VERSION - See deb-version for a description of epochs. Epochs are used when versioning system change + rocm_version_CANONICAL_VERSION - `[:]..[.][-]` + rocm_version_NUMERIC_VERSION - e.g. `10000* + 100* + `, e.g. 40502 for ROCm 4.5.2 + rocm_version_TRIPLE_VERSION - e.g. `..`, e.g. 4.5.2 for ROCm 4.5.2 + +These variables are relevant for the find procedure:: + + rocm_version_DEBUG - Print info about processing + rocm_version_VERSION_FILE - `` to read from in `/.info/`, e.g. `version`, `version-dev`, `version-hip-libraries`, etc. + It may also be a full path + rocm_version_DIR - Root location for +#]=======================================================================] + +set(rocm_version_VARIABLES + EPOCH + MAJOR + MINOR + PATCH + TWEAK + REVISION + TRIPLE + NUMERIC + CANONICAL + FULL) + +function(ROCM_VERSION_MESSAGE _TYPE) + if(rocm_version_DEBUG) + message(${_TYPE} "[rocm_version] ${ARGN}") + endif() +endfunction() + +# read a .info/version* file and propagate the variables to the calling scope +function(ROCM_VERSION_COMPUTE FULL_VERSION_STRING _VAR_PREFIX) + + # remove any line endings + string(REGEX REPLACE "(\n|\r)" "" FULL_VERSION_STRING "${FULL_VERSION_STRING}") + + # store the full version so it can be set later + set(FULL_VERSION "${FULL_VERSION_STRING}") + + # get number and remove from full version string + string(REGEX REPLACE "([0-9]+)\:(.*)" "\\1" EPOCH_VERSION "${FULL_VERSION_STRING}") + string(REGEX REPLACE "([0-9]+)\:(.*)" "\\2" FULL_VERSION_STRING + "${FULL_VERSION_STRING}") + + if(EPOCH_VERSION STREQUAL FULL_VERSION) + set(EPOCH_VERSION) + endif() + + # get number and remove from full version string + string(REGEX REPLACE "([0-9]+)(.*)" "\\1" MAJOR_VERSION "${FULL_VERSION_STRING}") + string(REGEX REPLACE "([0-9]+)(.*)" "\\2" FULL_VERSION_STRING + "${FULL_VERSION_STRING}") + + # get number and remove from full version string + string(REGEX REPLACE "\.([0-9]+)(.*)" "\\1" MINOR_VERSION "${FULL_VERSION_STRING}") + string(REGEX REPLACE "\.([0-9]+)(.*)" "\\2" FULL_VERSION_STRING + "${FULL_VERSION_STRING}") + + # get number and remove from full version string + string(REGEX REPLACE "\.([0-9]+)(.*)" "\\1" PATCH_VERSION "${FULL_VERSION_STRING}") + string(REGEX REPLACE "\.([0-9]+)(.*)" "\\2" FULL_VERSION_STRING + "${FULL_VERSION_STRING}") + + if(NOT PATCH_VERSION LESS 100) + set(PATCH_VERSION 0) + endif() + + # get number and remove from full version string + string(REGEX REPLACE "\.([0-9]+)(.*)" "\\1" TWEAK_VERSION "${FULL_VERSION_STRING}") + string(REGEX REPLACE "\.([0-9]+)(.*)" "\\2" FULL_VERSION_STRING + "${FULL_VERSION_STRING}") + + # get number + string(REGEX REPLACE "-([0-9A-Za-z+~]+)" "\\1" REVISION_VERSION + "${FULL_VERSION_STRING}") + + set(CANONICAL_VERSION) + set(_MAJOR_SEP ":") + set(_MINOR_SEP ".") + set(_PATCH_SEP ".") + set(_TWEAK_SEP ".") + set(_REVISION_SEP "-") + + foreach(_V EPOCH MAJOR MINOR PATCH TWEAK REVISION) + if(${_V}_VERSION) + set(CANONICAL_VERSION "${CANONICAL_VERSION}${_${_V}_SEP}${${_V}_VERSION}") + else() + set(CANONICAL_VERSION "${CANONICAL_VERSION}${_${_V}_SEP}0") + endif() + endforeach() + + set(_MAJOR_SEP "") + + foreach(_V MAJOR MINOR PATCH) + if(${_V}_VERSION) + set(TRIPLE_VERSION "${TRIPLE_VERSION}${_${_V}_SEP}${${_V}_VERSION}") + else() + set(TRIPLE_VERSION "${TRIPLE_VERSION}${_${_V}_SEP}0") + endif() + endforeach() + + math( + EXPR + NUMERIC_VERSION + "(10000 * (${MAJOR_VERSION}+0)) + (100 * (${MINOR_VERSION}+0)) + (${PATCH_VERSION}+0)" + ) + + # propagate to parent scopes + foreach(_V ${rocm_version_VARIABLES}) + set(${_VAR_PREFIX}_${_V}_VERSION + ${${_V}_VERSION} + PARENT_SCOPE) + endforeach() +endfunction() + +# this macro watches for changes in the variables and unsets the remaining cache varaible +# when they change +function(ROCM_VERSION_WATCH_FOR_CHANGE _var) + set(_rocm_version_watch_var_name rocm_version_WATCH_VALUE_${_var}) + + if(DEFINED ${_rocm_version_watch_var_name}) + if("${${_var}}" STREQUAL "${${_rocm_version_watch_var_name}}") + if(NOT "${${_var}}" STREQUAL "") + rocm_version_message(STATUS "${_var} :: ${${_var}}") + endif() + + list(REMOVE_ITEM _REMAIN_VARIABLES ${_var}) + set(_REMAIN_VARIABLES + "${_REMAIN_VARIABLES}" + PARENT_SCOPE) + return() + else() + rocm_version_message( + STATUS + "${_var} changed :: ${${_rocm_version_watch_var_name}} --> ${${_var}}") + + foreach(_V ${_REMAIN_VARIABLES}) + rocm_version_message( + STATUS "${_var} changed :: Unsetting cache variable ${_V}...") + unset(${_V} CACHE) + endforeach() + endif() + else() + if(NOT "${${_var}}" STREQUAL "") + rocm_version_message(STATUS "${_var} :: ${${_var}}") + endif() + endif() + + # store the value for the next run + set(${_rocm_version_watch_var_name} + "${${_var}}" + CACHE INTERNAL "Last value of ${_var}" FORCE) +endfunction() + +# scope this to a function to avoid leaking local variables +function(ROCM_VERSION_PARSE_VERSION_FILES) + + # the list of variables set by module. when one of these changes, we need to unset the + # cache variables after it + set(_ALL_VARIABLES) + + foreach(_V ${rocm_version_VARIABLES}) + list(APPEND _ALL_VARIABLES rocm_version_${_V}_VERSION) + endforeach() + set(_REMAIN_VARIABLES ${_ALL_VARIABLES}) + + # read a .info/version* file and propagate the variables to the calling scope + function(ROCM_VERSION_READ_FILE _FILE _VAR_PREFIX) + file(READ "${_FILE}" FULL_VERSION_STRING LIMIT_COUNT 1) + rocm_version_compute("${FULL_VERSION_STRING}" "${_VAR_PREFIX}") + + # propagate to parent scopes + foreach(_V ${rocm_version_VARIABLES}) + set(${_VAR_PREFIX}_${_V}_VERSION + ${${_VAR_PREFIX}_${_V}_VERSION} + PARENT_SCOPE) + endforeach() + endfunction() + + # search for HIP to set ROCM_PATH if(NOT hip_FOUND) find_package(hip) endif() + + function(COMPUTE_ROCM_VERSION_DIR) + if(EXISTS "${rocm_version_VERSION_FILE}" AND IS_ABSOLUTE + "${rocm_version_VERSION_FILE}") + get_filename_component(_VERSION_DIR "${rocm_version_VERSION_FILE}" PATH) + get_filename_component(_VERSION_DIR "${_VERSION_DIR}/.." REALPATH) + set(rocm_version_DIR + "${_VERSION_DIR}" + CACHE PATH "Root path to ROCm's .info/${rocm_version_VERSION_FILE}" + ${ARGN}) + rocm_version_watch_for_change(rocm_version_DIR) + endif() + endfunction() + + if(rocm_version_VERSION_FILE) + get_filename_component(_VERSION_FILE "${rocm_version_VERSION_FILE}" NAME) + set(_VERSION_FILES ${_VERSION_FILE}) + compute_rocm_version_dir(FORCE) + else() + set(_VERSION_FILES version version-dev version-hip-libraries version-hiprt + version-hiprt-devel version-hip-sdk version-libs version-utils) + rocm_version_message(STATUS "rocm_version version files: ${_VERSION_FILES}") + endif() + + # convert env to cache if not defined + foreach(_PATH rocm_version_DIR rocm_version_ROOT rocm_version_ROOT_DIR + ROCPROFILER_DEFAULT_ROCM_PATH ROCM_PATH) + if(NOT DEFINED ${_PATH} AND DEFINED ENV{${_PATH}}) + set(_VAL "$ENV{${_PATH}}") + get_filename_component(_VAL "${_VAL}" REALPATH) + set(${_PATH} + "${_VAL}" + CACHE PATH "Search path for ROCm version for rocm_version") + endif() + endforeach() + + if(rocm_version_DIR) + set(_PATHS ${rocm_version_DIR}) + else() + set(_PATHS) + foreach( + _DIR + ${rocm_version_DIR} ${rocm_version_ROOT} ${rocm_version_ROOT_DIR} + $ENV{CMAKE_PREFIX_PATH} ${CMAKE_PREFIX_PATH} ${ROCPROFILER_DEFAULT_ROCM_PATH} + ${ROCM_PATH} /opt/rocm) + if(EXISTS ${_DIR}) + get_filename_component(_ABS_DIR "${_DIR}" REALPATH) + list(APPEND _PATHS ${_ABS_DIR}) + endif() + endforeach() + rocm_version_message(STATUS "rocm_version search paths: ${_PATHS}") + endif() + + string(REPLACE ":" ";" _PATHS "${_PATHS}") + + foreach(_PATH ${_PATHS}) + foreach(_FILE ${_VERSION_FILES}) + set(_F ${_PATH}/.info/${_FILE}) + if(EXISTS ${_F}) + set(rocm_version_VERSION_FILE + "${_F}" + CACHE FILEPATH "File with versioning info") + rocm_version_watch_for_change(rocm_version_VERSION_FILE) + compute_rocm_version_dir() + else() + rocm_version_message(AUTHOR_WARNING "File does not exist: ${_F}") + endif() + endforeach() + endforeach() + + if(EXISTS "${rocm_version_VERSION_FILE}") + set(_F "${rocm_version_VERSION_FILE}") + rocm_version_message(STATUS "Reading ${_F}...") + get_filename_component(_B "${_F}" NAME) + string(REPLACE "." "_" _B "${_B}") + string(REPLACE "-" "_" _B "${_B}") + rocm_version_read_file(${_F} ${_B}) + + foreach(_V ${rocm_version_VARIABLES}) + set(_CACHE_VAR rocm_version_${_V}_VERSION) + set(_LOCAL_VAR ${_B}_${_V}_VERSION) + set(rocm_version_${_V}_VERSION + "${${_LOCAL_VAR}}" + CACHE STRING "ROCm ${_V} version") + rocm_version_watch_for_change(${_CACHE_VAR}) + endforeach() + endif() +endfunction() + +# execute +rocm_version_parse_version_files() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + rocm_version + VERSION_VAR rocm_version_FULL_VERSION + REQUIRED_VARS rocm_version_FULL_VERSION rocm_version_TRIPLE_VERSION rocm_version_DIR + rocm_version_VERSION_FILE) +# don't add major/minor/patch/etc. version variables to required vars because they might +# be zero, which will cause CMake to evaluate it as not set diff --git a/cmake/Modules/Findrocprofiler.cmake b/cmake/Modules/Findrocprofiler.cmake new file mode 100644 index 0000000000..fea224fc1a --- /dev/null +++ b/cmake/Modules/Findrocprofiler.cmake @@ -0,0 +1,97 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying file +# Copyright.txt or https://cmake.org/licensing for details. + +include(FindPackageHandleStandardArgs) + +# ----------------------------------------------------------------------------------------# + +if(NOT ROCM_PATH AND NOT "$ENV{ROCM_PATH}" STREQUAL "") + set(ROCM_PATH "$ENV{ROCM_PATH}") +endif() + +foreach(_DIR ${rocm_version_DIR} ${ROCM_PATH} /opt/rocm /opt/rocm/rocprofiler) + if(EXISTS ${_DIR}) + get_filename_component(_ABS_DIR "${_DIR}" REALPATH) + list(APPEND _ROCM_ROCPROFILER_PATHS ${_ABS_DIR}) + endif() +endforeach() + +# ----------------------------------------------------------------------------------------# + +find_path( + rocprofiler_ROOT_DIR + NAMES include/rocprofiler/rocprofiler.h include/rocprofiler.h + HINTS ${_ROCM_ROCPROFILER_PATHS} + PATHS ${_ROCM_ROCPROFILER_PATHS} + PATH_SUFFIXES rocprofiler) + +mark_as_advanced(rocprofiler_ROOT_DIR) + +# ----------------------------------------------------------------------------------------# + +find_path( + rocprofiler_INCLUDE_DIR + NAMES rocprofiler.h + HINTS ${rocprofiler_ROOT_DIR} ${_ROCM_ROCPROFILER_PATHS} + PATHS ${rocprofiler_ROOT_DIR} ${_ROCM_ROCPROFILER_PATHS} + PATH_SUFFIXES include include/rocprofiler rocprofiler/include) + +mark_as_advanced(rocprofiler_INCLUDE_DIR) + +find_path( + rocprofiler_hsa_INCLUDE_DIR + NAMES hsa.h + HINTS ${rocprofiler_ROOT_DIR} ${_ROCM_ROCPROFILER_PATHS} + PATHS ${rocprofiler_ROOT_DIR} ${_ROCM_ROCPROFILER_PATHS} + PATH_SUFFIXES include include/hsa) + +mark_as_advanced(rocprofiler_hsa_INCLUDE_DIR) + +# ----------------------------------------------------------------------------------------# + +find_library( + rocprofiler_LIBRARY + NAMES rocprofiler64 rocprofiler + HINTS ${rocprofiler_ROOT_DIR}/rocprofiler ${rocprofiler_ROOT_DIR} + ${_ROCM_ROCPROFILER_PATHS} + PATHS ${rocprofiler_ROOT_DIR}/rocprofiler ${rocprofiler_ROOT_DIR} + ${_ROCM_ROCPROFILER_PATHS} + PATH_SUFFIXES lib lib64 + NO_DEFAULT_PATH) + +find_library( + rocprofiler_hsa-runtime_LIBRARY + NAMES hsa-runtime64 hsa-runtime + HINTS ${rocprofiler_ROOT_DIR} ${_ROCM_ROCPROFILER_PATHS} + PATHS ${rocprofiler_ROOT_DIR} ${_ROCM_ROCPROFILER_PATHS} + PATH_SUFFIXES lib lib64) + +if(rocprofiler_LIBRARY) + get_filename_component(rocprofiler_LIBRARY_DIR "${rocprofiler_LIBRARY}" PATH CACHE) +endif() + +mark_as_advanced(rocprofiler_LIBRARY rocprofiler_hsa-runtime_LIBRARY) +unset(_ROCM_ROCPROFILER_PATHS) + +# ----------------------------------------------------------------------------------------# + +find_package_handle_standard_args( + rocprofiler DEFAULT_MSG rocprofiler_ROOT_DIR rocprofiler_INCLUDE_DIR + rocprofiler_hsa_INCLUDE_DIR rocprofiler_LIBRARY rocprofiler_hsa-runtime_LIBRARY) + +# ----------------------------------------------------------------------------------------# + +if(rocprofiler_FOUND) + add_library(rocprofiler::rocprofiler INTERFACE IMPORTED) + add_library(rocprofiler::roctx INTERFACE IMPORTED) + set(rocprofiler_INCLUDE_DIRS ${rocprofiler_INCLUDE_DIR} + ${rocprofiler_hsa_INCLUDE_DIR}) + set(rocprofiler_LIBRARIES ${rocprofiler_LIBRARY} ${rocprofiler_hsa-runtime_LIBRARY}) + set(rocprofiler_LIBRARY_DIRS ${rocprofiler_LIBRARY_DIR}) + + target_include_directories( + rocprofiler::rocprofiler INTERFACE ${rocprofiler_INCLUDE_DIR} + ${rocprofiler_hsa_INCLUDE_DIR}) + + target_link_libraries(rocprofiler::rocprofiler INTERFACE ${rocprofiler_LIBRARIES}) +endif() diff --git a/cmake/Templates/modulefile.in b/cmake/Templates/modulefile.in new file mode 100644 index 0000000000..352fd6b877 --- /dev/null +++ b/cmake/Templates/modulefile.in @@ -0,0 +1,16 @@ +#%Module1.0 + +module-whatis "@PROJECT_NAME@ (version @PROJECT_VERSION@)" + +proc ModulesHelp { } { +puts stderr "Loads @PROJECT_NAME@ v@PROJECT_VERSION@" +} + +set ROOT [file normalize [file dirname [file normalize ${ModulesCurrentModulefile}]]/../../..] + +setenv @PROJECT_NAME@_ROOT "${ROOT}" +prepend-path CMAKE_PREFIX_PATH "${ROOT}" +prepend-path PATH "${ROOT}/bin" +prepend-path LD_LIBRARY_PATH "${ROOT}/@CMAKE_INSTALL_LIBDIR@" +prepend-path PYTHONPATH "${ROOT}/@CMAKE_INSTALL_PYTHONDIR@" +setenv @PROJECT_NAME@_DIR "${ROOT}/@CMAKE_INSTALL_DATAROOTDIR@/cmake/@PROJECT_NAME@" diff --git a/cmake/Templates/rocprofiler-config.cmake.in b/cmake/Templates/rocprofiler-config.cmake.in new file mode 100644 index 0000000000..e2f585a443 --- /dev/null +++ b/cmake/Templates/rocprofiler-config.cmake.in @@ -0,0 +1,56 @@ +# - Config file for @PROJECT_NAME@ and its component libraries +# It defines the following variables: +# +# @PROJECT_NAME@_INCLUDE_DIRS +# @PROJECT_NAME@_LIBRARIES +# @PROJECT_NAME@_INTERNAL_DEFINES - used by the test suite + +# compute paths +get_filename_component(@PROJECT_NAME@_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) + +# version +include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-version.cmake) + +@PACKAGE_INIT@ + +set_and_check(@PROJECT_NAME@_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") +set_and_check(@PROJECT_NAME@_LIB_DIR "@PACKAGE_LIB_INSTALL_DIR@") +get_filename_component(@PROJECT_NAME@_ROOT_DIR ${@PROJECT_NAME@_INCLUDE_DIR} PATH) + +set(@PROJECT_NAME@_LIBRARIES) + +add_library(@PROJECT_NAME@::@PROJECT_NAME@ INTERFACE IMPORTED) + +include("${@PROJECT_NAME@_CMAKE_DIR}/@PROJECT_NAME@-library-targets.cmake") + +# Library dependencies +foreach(TARG @PROJECT_BUILD_TARGETS@) + set(TARG @PROJECT_NAME@-${TARG}) + if(NOT @PROJECT_NAME@_FIND_COMPONENTS) + list(APPEND @PROJECT_NAME@_LIBRARIES @PROJECT_NAME@::${TARG}) + target_link_libraries(@PROJECT_NAME@::@PROJECT_NAME@ + INTERFACE @PROJECT_NAME@::${TARG}) + endif() +endforeach() + +if(@PROJECT_NAME@_FIND_COMPONENTS) + foreach(COMP ${@PROJECT_NAME@_FIND_COMPONENTS}) + set(TARG @PROJECT_NAME@::@PROJECT_NAME@-${COMP}) + if(TARGET ${TARG}) + set(@PROJECT_NAME@_${COMP}_FOUND 1) + list(APPEND @PROJECT_NAME@_LIBRARIES ${TARG}) + target_link_libraries(@PROJECT_NAME@::@PROJECT_NAME@ + INTERFACE ${TARG}) + else() + set(@PROJECT_NAME@_${COMP}_FOUND 0) + endif() + endforeach() +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args( + @PROJECT_NAME@ + FOUND_VAR @PROJECT_NAME@_FOUND + REQUIRED_VARS @PROJECT_NAME@_ROOT_DIR @PROJECT_NAME@_INCLUDE_DIR @PROJECT_NAME@_LIBRARIES + VERSION_VAR @PROJECT_NAME@_VERSION + HANDLE_COMPONENTS) diff --git a/cmake/Templates/setup-env.sh.in b/cmake/Templates/setup-env.sh.in new file mode 100644 index 0000000000..43e8374c9c --- /dev/null +++ b/cmake/Templates/setup-env.sh.in @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +BASEDIR=$(dirname ${BASH_SOURCE[0]}) +command -v realpath &> /dev/null && BASEDIR=$(realpath ${BASEDIR}/../..) || BASEDIR=$(cd ${BASEDIR}/../.. && pwd) + +if [ ! -d "${BASEDIR}" ]; then + echo "${BASEDIR} does not exist" + return 1 +fi + +@PROJECT_NAME@_ROOT=${BASEDIR} +PATH=${BASEDIR}/bin:${PATH} +LD_LIBRARY_PATH=${BASEDIR}/@CMAKE_INSTALL_LIBDIR@:${LD_LIBRARY_PATH} +PYTHONPATH=${BASEDIR}/@CMAKE_INSTALL_PYTHONDIR@:${PYTHONPATH} +CMAKE_PREFIX_PATH=${BASEDIR}:${CMAKE_PREFIX_PATH} +@PROJECT_NAME@_DIR=${BASEDIR}/@CMAKE_INSTALL_DATAROOTDIR@/cmake/@PROJECT_NAME@ + +export @PROJECT_NAME@_ROOT +export PATH +export LD_LIBRARY_PATH +export PYTHONPATH +export CMAKE_PREFIX_PATH +export @PROJECT_NAME@_DIR diff --git a/cmake/rocprofiler_build_settings.cmake b/cmake/rocprofiler_build_settings.cmake new file mode 100644 index 0000000000..5791852202 --- /dev/null +++ b/cmake/rocprofiler_build_settings.cmake @@ -0,0 +1,182 @@ +# ######################################################################################## +# +# Handles the build settings +# +# ######################################################################################## + +include_guard(DIRECTORY) + +include(GNUInstallDirs) +include(FindPackageHandleStandardArgs) +include(rocprofiler_compilers) +include(rocprofiler_utilities) + +target_compile_definitions(rocprofiler-build-flags INTERFACE $<$:DEBUG>) + +if(ROCPROFILER_BUILD_CI) + rocprofiler_target_compile_definitions(rocprofiler-build-flags + INTERFACE ROCPROFILER_CI) +endif() + +# ----------------------------------------------------------------------------------------# +# dynamic linking and runtime libraries +# +if(CMAKE_DL_LIBS AND NOT "${CMAKE_DL_LIBS}" STREQUAL "dl") + # if cmake provides dl library, use that + set(dl_LIBRARY + ${CMAKE_DL_LIBS} + CACHE FILEPATH "dynamic linking system library") +endif() + +foreach(_TYPE dl rt) + if(NOT ${_TYPE}_LIBRARY) + find_library(${_TYPE}_LIBRARY NAMES ${_TYPE}) + find_package_handle_standard_args(${_TYPE}-library REQUIRED_VARS ${_TYPE}_LIBRARY) + if(${_TYPE}-library_FOUND) + string(TOUPPER "${_TYPE}" _TYPE_UC) + rocprofiler_target_compile_definitions(rocprofiler-${_TYPE} + INTERFACE ROCPROFILER_${_TYPE_UC}=1) + target_link_libraries(rocprofiler-${_TYPE} INTERFACE ${${_TYPE}_LIBRARY}) + if("${_TYPE}" STREQUAL "dl") + # This instructs the linker to add all symbols, not only used ones, to the + # dynamic symbol table. This option is needed for some uses of dlopen or + # to allow obtaining backtraces from within a program. + rocprofiler_target_compile_options( + rocprofiler-${_TYPE} + LANGUAGES C CXX + LINK_LANGUAGES C CXX + INTERFACE "-rdynamic") + endif() + else() + rocprofiler_target_compile_definitions(rocprofiler-${_TYPE} + INTERFACE ROCPROFILER_${_TYPE_UC}=0) + endif() + endif() +endforeach() + +target_link_libraries(rocprofiler-build-flags INTERFACE rocprofiler::rocprofiler-dl) + +# ----------------------------------------------------------------------------------------# +# set the compiler flags +# +rocprofiler_target_compile_options(rocprofiler-build-flags + INTERFACE "-W" "-Wall" "-Wno-unknown-pragmas") + +# ----------------------------------------------------------------------------------------# +# extra flags for debug information in debug or optimized binaries +# + +rocprofiler_target_compile_options( + rocprofiler-debug-flags INTERFACE "-g3" "-fno-omit-frame-pointer" + "-fno-optimize-sibling-calls") + +target_compile_options( + rocprofiler-debug-flags + INTERFACE $<$:$<$:-rdynamic>> + $<$:$<$:-rdynamic>>) + +if(NOT APPLE) + target_link_options(rocprofiler-debug-flags INTERFACE + $<$:-rdynamic>) +endif() + +if(dl_LIBRARY) + target_link_libraries(rocprofiler-debug-flags INTERFACE ${dl_LIBRARY}) +endif() + +if(rt_LIBRARY) + target_link_libraries(rocprofiler-debug-flags INTERFACE ${rt_LIBRARY}) +endif() + +if(ROCPROFILER_BUILD_DEBUG) + target_link_libraries(rocprofiler-build-flags + INTERFACE rocprofiler::rocprofiler-debug-flags) +endif() + +# ----------------------------------------------------------------------------------------# +# debug-safe optimizations +# +rocprofiler_target_compile_options( + rocprofiler-build-flags + LANGUAGES CXX + INTERFACE "-faligned-new") + +# ----------------------------------------------------------------------------------------# +# fstack-protector +# +rocprofiler_target_compile_options( + rocprofiler-stack-protector + LANGUAGES C CXX + INTERFACE "-fstack-protector-strong" "-Wstack-protector") + +if(ROCPROFILER_BUILD_STACK_PROTECTOR) + target_link_libraries(rocprofiler-build-flags + INTERFACE rocprofiler::rocprofiler-stack-protector) +endif() + +# ----------------------------------------------------------------------------------------# +# developer build flags +# +rocprofiler_target_compile_options( + rocprofiler-developer-flags + LANGUAGES C CXX + INTERFACE "-Werror" "-Wdouble-promotion" "-Wshadow" "-Wextra" + "-Wstack-usage=524288" # 512 KB + ) + +if(ROCPROFILER_BUILD_DEVELOPER) + target_link_libraries(rocprofiler-build-flags + INTERFACE rocprofiler::rocprofiler-developer-flags) +endif() + +# ----------------------------------------------------------------------------------------# +# release build flags +# +rocprofiler_target_compile_options( + rocprofiler-release-flags + LANGUAGES C CXX + INTERFACE "-g1" "-feliminate-unused-debug-symbols" "-gno-column-info" + "-gno-variable-location-views" "-gline-tables-only") + +if(ROCPROFILER_BUILD_RELEASE) + target_link_libraries(rocprofiler-build-flags + INTERFACE rocprofiler::rocprofiler-release-flags) +endif() + +# ----------------------------------------------------------------------------------------# +# static lib flags +# +target_compile_options( + rocprofiler-static-libgcc + INTERFACE $<$:$<$:-static-libgcc>> + $<$:$<$:-static-libgcc>>) +target_link_options( + rocprofiler-static-libgcc INTERFACE + $<$:$<$:-static-libgcc>> + $<$:$<$:-static-libgcc>>) + +target_compile_options( + rocprofiler-static-libstdcxx + INTERFACE $<$:$<$:-static-libstdc++>>) +target_link_options( + rocprofiler-static-libstdcxx INTERFACE + $<$:$<$:-static-libstdc++>>) + +if(ROCPROFILER_BUILD_STATIC_LIBGCC) + target_link_libraries(rocprofiler-build-flags + INTERFACE rocprofiler::rocprofiler-static-libgcc) +endif() + +if(ROCPROFILER_BUILD_STATIC_LIBSTDCXX) + target_link_libraries(rocprofiler-build-flags + INTERFACE rocprofiler::rocprofiler-static-libstdcxx) +endif() + +# ----------------------------------------------------------------------------------------# +# user customization +# +get_property(LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) + +if(NOT APPLE OR "$ENV{CONDA_PYTHON_EXE}" STREQUAL "") + rocprofiler_target_user_flags(rocprofiler-build-flags "CXX") +endif() diff --git a/cmake/rocprofiler_compilers.cmake b/cmake/rocprofiler_compilers.cmake new file mode 100644 index 0000000000..971d3682d6 --- /dev/null +++ b/cmake/rocprofiler_compilers.cmake @@ -0,0 +1,350 @@ +# include guard +# ######################################################################################## +# +# Compilers +# +# ######################################################################################## +# +# sets (cached): +# +# CMAKE_C_COMPILER_IS_ CMAKE_CXX_COMPILER_IS_ +# +# where TYPE is: - GNU - CLANG - INTEL - INTEL_ICC - INTEL_ICPC - PGI - XLC - HP_ACC - +# MIPS - MSVC +# + +include(CheckCCompilerFlag) +include(CheckCSourceCompiles) +include(CheckCSourceRuns) + +include(CheckCXXCompilerFlag) +include(CheckCXXSourceCompiles) +include(CheckCXXSourceRuns) + +include(CMakeParseArguments) + +include(rocprofiler_utilities) + +# ----------------------------------------------------------------------------------------# +# macro converting string to list +# ----------------------------------------------------------------------------------------# +macro(ROCPROFILER_TO_LIST _VAR _STR) + string(REPLACE " " " " ${_VAR} "${_STR}") + string(REPLACE " " ";" ${_VAR} "${_STR}") +endmacro() + +# ----------------------------------------------------------------------------------------# +# macro converting string to list +# ----------------------------------------------------------------------------------------# +macro(ROCPROFILER_TO_STRING _VAR _STR) + string(REPLACE ";" " " ${_VAR} "${_STR}") +endmacro() + +# ----------------------------------------------------------------------------------------# +# Macro to add to string +# ----------------------------------------------------------------------------------------# +macro(add _VAR _FLAG) + if(NOT "${_FLAG}" STREQUAL "") + if("${${_VAR}}" STREQUAL "") + set(${_VAR} "${_FLAG}") + else() + set(${_VAR} "${${_VAR}} ${_FLAG}") + endif() + endif() +endmacro() + +# ----------------------------------------------------------------------------------------# +# call before running check_{c,cxx}_compiler_flag +# ----------------------------------------------------------------------------------------# +macro(ROCPROFILER_BEGIN_FLAG_CHECK) + if(ROCPROFILER_QUIET_CONFIG) + if(NOT DEFINED CMAKE_REQUIRED_QUIET) + set(CMAKE_REQUIRED_QUIET OFF) + endif() + rocprofiler_save_variables(FLAG_CHECK VARIABLES CMAKE_REQUIRED_QUIET) + set(CMAKE_REQUIRED_QUIET ON) + endif() +endmacro() + +# ----------------------------------------------------------------------------------------# +# call after running check_{c,cxx}_compiler_flag +# ----------------------------------------------------------------------------------------# +macro(ROCPROFILER_END_FLAG_CHECK) + if(ROCPROFILER_QUIET_CONFIG) + rocprofiler_restore_variables(FLAG_CHECK VARIABLES CMAKE_REQUIRED_QUIET) + endif() +endmacro() + +# ----------------------------------------------------------------------------------------# +# check flag +# ----------------------------------------------------------------------------------------# +function(ROCPROFILER_TARGET_COMPILE_OPTIONS _TARG_TARGET) + cmake_parse_arguments(_TARG "BUILD_INTERFACE;FORCE" "" + "PUBLIC;INTERFACE;PRIVATE;LANGUAGES;LINK_LANGUAGES" ${ARGN}) + + if(NOT _TARG_MODE) + set(_TARG_MODE INTERFACE) + endif() + + get_property(_ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) + set(_SUPPORTED_LANGUAGES "C" "CXX") + + if(NOT _TARG_LANGUAGES) + foreach(_LANG ${_ENABLED_LANGUAGES}) + if(_LANG IN_LIST _SUPPORTED_LANGUAGES) + list(APPEND _TARG_LANGUAGES ${_LANG}) + endif() + endforeach() + endif() + + string(TOLOWER "_${_TARG_TARGET}" _TARG_TARGET_LC) + + function(rocprofiler_target_compile_option_impl _TARGET_IMPL _TARGET_MODE_IMPL + _TARGET_LANG_IMPL _TARGET_FLAG_IMPL) + if(_TARG_BUILD_INTERFACE) + target_compile_options( + ${_TARGET_IMPL} + ${_TARGET_MODE_IMPL} + $:${_TARGET_FLAG_IMPL}>> + ) + else() + target_compile_options( + ${_TARGET_IMPL} ${_TARGET_MODE_IMPL} + $<$:${_TARGET_FLAG_IMPL}>) + endif() + + if("${_TARGET_LANG_IMPL}" IN_LIST _TARG_LINK_LANGUAGES) + if(_TARG_BUILD_INTERFACE) + target_link_options( + ${_TARGET_IMPL} + ${_TARGET_MODE_IMPL} + $:${_TARGET_FLAG_IMPL}>> + ) + else() + target_link_options( + ${_TARGET_IMPL} ${_TARGET_MODE_IMPL} + $<$:${_TARGET_FLAG_IMPL}>) + endif() + endif() + endfunction() + + function(rocprofiler_target_compile_option_patch_name _P_LANG _P_IN _P_OUT) + string(TOLOWER "${_P_LANG}" _P_LANG) + string(REGEX REPLACE "^(/|-)" "${_P_LANG}${_TARG_TARGET_LC}_" _NAME "${_P_IN}") + string(REPLACE "-" "_" _NAME "${_NAME}") + string(REPLACE " " "_" _NAME "${_NAME}") + string(REPLACE "=" "_" _NAME "${_NAME}") + set(${_P_OUT} + "${_NAME}" + PARENT_SCOPE) + endfunction() + + if(NOT DEFINED rocprofiler_c_error AND NOT DEFINED rocprofiler_cxx_error) + rocprofiler_begin_flag_check() + check_c_compiler_flag("-Werror" c_rocprofiler_werror) + check_cxx_compiler_flag("-Werror" cxx_rocprofiler_werror) + rocprofiler_end_flag_check() + endif() + + foreach(_TARG_MODE PUBLIC INTERFACE PRIVATE) + foreach(_FLAG ${_TARG_${_TARG_MODE}}) + foreach(_LANG ${_TARG_LANGUAGES}) + unset(FLAG_NAME) + rocprofiler_target_compile_option_patch_name(${_LANG} "${_FLAG}" + FLAG_NAME) + + if(_TARG_FORCE) + set(${FLAG_NAME} + 1 + CACHE INTERNAL "${_LANG} flag: ${_FLAG}") + else() + rocprofiler_begin_flag_check() + + if("${_LANG}" STREQUAL "C") + if(c_rocprofiler_werror) + check_c_compiler_flag("${_FLAG} -Werror" ${FLAG_NAME}) + else() + check_c_compiler_flag("${_FLAG}" ${FLAG_NAME}) + endif() + elseif("${_LANG}" STREQUAL "CXX") + if(cxx_rocprofiler_werror) + check_cxx_compiler_flag("${_FLAG} -Werror" ${FLAG_NAME}) + else() + check_cxx_compiler_flag("${_FLAG}" ${FLAG_NAME}) + endif() + else() + message( + FATAL_ERROR + "rocprofiler_target_compile_option :: unknown language: ${_LANG}" + ) + endif() + + rocprofiler_end_flag_check() + endif() + + if(${FLAG_NAME}) + rocprofiler_target_compile_option_impl(${_TARG_TARGET} ${_TARG_MODE} + ${_LANG} "${_FLAG}") + endif() + endforeach() + endforeach() + endforeach() +endfunction() + +# ----------------------------------------------------------------------------------------# +# add to any language +# ----------------------------------------------------------------------------------------# +function(ROCPROFILER_TARGET_USER_FLAGS _TARGET _LANGUAGE) + + set(_FLAGS ${${_LANGUAGE}FLAGS} $ENV{${_LANGUAGE}FLAGS} ${${_LANGUAGE}_FLAGS} + $ENV{${_LANGUAGE}_FLAGS}) + + string(REPLACE " " ";" _FLAGS "${_FLAGS}") + + set(${PROJECT_NAME}_${_LANGUAGE}_FLAGS + ${${PROJECT_NAME}_${_LANGUAGE}_FLAGS} ${_FLAGS} + PARENT_SCOPE) + + set(${PROJECT_NAME}_${_LANGUAGE}_COMPILE_OPTIONS + ${${PROJECT_NAME}_${_LANGUAGE}_COMPILE_OPTIONS} ${_FLAGS} + PARENT_SCOPE) + + target_compile_options(${_TARGET} + INTERFACE $<$:${_FLAGS}>) +endfunction() + +# ----------------------------------------------------------------------------------------# +# add compiler definition +# ----------------------------------------------------------------------------------------# +function(ROCPROFILER_TARGET_COMPILE_DEFINITIONS _TARG _VIS) + foreach(_DEF ${ARGN}) + if(NOT "${_DEF}" MATCHES "[A-Za-z_]+=.*" AND "${_DEF}" MATCHES "^ROCPROFILER_") + set(_DEF "${_DEF}=1") + endif() + target_compile_definitions(${_TARG} ${_VIS} $<$:${_DEF}>) + endforeach() +endfunction() + +# ----------------------------------------------------------------------------------------# +# determine compiler types for each language +# ----------------------------------------------------------------------------------------# +get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) +foreach(LANG C CXX HIP CUDA) + + if(NOT DEFINED CMAKE_${LANG}_COMPILER) + set(CMAKE_${LANG}_COMPILER "") + endif() + + if(NOT DEFINED CMAKE_${LANG}_COMPILER_ID) + set(CMAKE_${LANG}_COMPILER_ID "") + endif() + + function(SET_COMPILER_VAR VAR _BOOL) + set(CMAKE_${LANG}_COMPILER_IS_${VAR} + ${_BOOL} + CACHE INTERNAL "CMake ${LANG} compiler identification (${VAR})" FORCE) + mark_as_advanced(CMAKE_${LANG}_COMPILER_IS_${VAR}) + endfunction() + + if(("${LANG}" STREQUAL "C" AND CMAKE_COMPILER_IS_GNUCC) + OR ("${LANG}" STREQUAL "CXX" AND CMAKE_COMPILER_IS_GNUCXX)) + + # GNU compiler + set_compiler_var(GNU 1) + + elseif(CMAKE_${LANG}_COMPILER MATCHES "icc.*") + + # Intel icc compiler + set_compiler_var(INTEL 1) + set_compiler_var(INTEL_ICC 1) + + elseif(CMAKE_${LANG}_COMPILER MATCHES "icpc.*") + + # Intel icpc compiler + set_compiler_var(INTEL 1) + set_compiler_var(INTEL_ICPC 1) + + elseif(CMAKE_${LANG}_COMPILER_ID MATCHES "AppleClang") + + # Clang/LLVM compiler + set_compiler_var(CLANG 1) + set_compiler_var(APPLE_CLANG 1) + + elseif(CMAKE_${LANG}_COMPILER_ID MATCHES "Clang") + + # Clang/LLVM compiler + set_compiler_var(CLANG 1) + + # HIP Clang compiler + if(CMAKE_${LANG}_COMPILER MATCHES "hipcc") + set_compiler_var(HIPCC 1) + endif() + + elseif(CMAKE_${LANG}_COMPILER_ID MATCHES "PGI") + + # PGI compiler + set_compiler_var(PGI 1) + + elseif(CMAKE_${LANG}_COMPILER MATCHES "xlC" AND UNIX) + + # IBM xlC compiler + set_compiler_var(XLC 1) + + elseif(CMAKE_${LANG}_COMPILER MATCHES "aCC" AND UNIX) + + # HP aC++ compiler + set_compiler_var(HP_ACC 1) + + elseif( + CMAKE_${LANG}_COMPILER MATCHES "CC" + AND CMAKE_SYSTEM_NAME MATCHES "IRIX" + AND UNIX) + + # IRIX MIPSpro CC Compiler + set_compiler_var(MIPS 1) + + elseif(CMAKE_${LANG}_COMPILER_ID MATCHES "Intel") + + set_compiler_var(INTEL 1) + + set(CTYPE ICC) + if("${LANG}" STREQUAL "CXX") + set(CTYPE ICPC) + endif() + + set_compiler_var(INTEL_${CTYPE} 1) + + elseif(CMAKE_${LANG}_COMPILER MATCHES "MSVC") + + # Windows Visual Studio compiler + set_compiler_var(MSVC 1) + + elseif(CMAKE_${LANG}_COMPILER_ID MATCHES "NVIDIA") + + # NVCC + set_compiler_var(NVIDIA 1) + + endif() + + # set other to no + foreach( + TYPE + GNU + INTEL + INTEL_ICC + INTEL_ICPC + APPLE_CLANG + CLANG + PGI + XLC + HP_ACC + MIPS + MSVC + NVIDIA + HIPCC) + if(NOT DEFINED CMAKE_${LANG}_COMPILER_IS_${TYPE}) + set_compiler_var(${TYPE} 0) + endif() + endforeach() + +endforeach() diff --git a/cmake/rocprofiler_config_install.cmake b/cmake/rocprofiler_config_install.cmake new file mode 100644 index 0000000000..15fbc12f96 --- /dev/null +++ b/cmake/rocprofiler_config_install.cmake @@ -0,0 +1,68 @@ +# include guard +include_guard(GLOBAL) + +include(CMakePackageConfigHelpers) + +set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME config) + +install( + EXPORT rocprofiler-library-targets + FILE rocprofiler-library-targets.cmake + NAMESPACE rocprofiler:: + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/rocprofiler) + +# ------------------------------------------------------------------------------# +# install tree +# +set(PROJECT_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}) +set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}) +set(LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}) +set(PROJECT_BUILD_TARGETS user) + +configure_package_config_file( + ${PROJECT_SOURCE_DIR}/cmake/Templates/${PROJECT_NAME}-config.cmake.in + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/rocprofiler + INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} + PATH_VARS PROJECT_INSTALL_DIR INCLUDE_INSTALL_DIR LIB_INSTALL_DIR) + +write_basic_package_version_file( + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-version.cmake + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMinorVersion) + +install( + FILES + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-config.cmake + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}/${PROJECT_NAME}-version.cmake + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME} + OPTIONAL) + +export(PACKAGE ${PROJECT_NAME}) + +# ------------------------------------------------------------------------------# +# build tree +# +set(_BUILDTREE_EXPORT_DIR + "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/cmake/rocprofiler") + +if(NOT EXISTS "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") + file(MAKE_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}") +endif() + +if(NOT EXISTS "${_BUILDTREE_EXPORT_DIR}") + file(MAKE_DIRECTORY "${_BUILDTREE_EXPORT_DIR}") +endif() + +if(NOT EXISTS "${_BUILDTREE_EXPORT_DIR}/rocprofiler-library-targets.cmake") + file(TOUCH "${_BUILDTREE_EXPORT_DIR}/rocprofiler-library-targets.cmake") +endif() + +export( + EXPORT rocprofiler-library-targets + NAMESPACE rocprofiler:: + FILE "${_BUILDTREE_EXPORT_DIR}/rocprofiler-library-targets.cmake") + +set(rocprofiler_DIR + "${_BUILDTREE_EXPORT_DIR}" + CACHE PATH "rocprofiler" FORCE) diff --git a/cmake/rocprofiler_config_interfaces.cmake b/cmake/rocprofiler_config_interfaces.cmake new file mode 100644 index 0000000000..d61a43b17e --- /dev/null +++ b/cmake/rocprofiler_config_interfaces.cmake @@ -0,0 +1,141 @@ +# include guard +include_guard(DIRECTORY) + +# ######################################################################################## +# +# External Packages are found here +# +# ######################################################################################## + +target_include_directories( + rocprofiler-headers + INTERFACE $ + $ + $) + +# include threading because of rooflines +target_link_libraries(rocprofiler-headers INTERFACE rocprofiler::rocprofiler-threading) + +# ensure the env overrides the appending /opt/rocm later +string(REPLACE ":" ";" CMAKE_PREFIX_PATH "$ENV{CMAKE_PREFIX_PATH};${CMAKE_PREFIX_PATH}") + +set(ROCPROFILER_DEFAULT_ROCM_PATH + /opt/rocm + CACHE PATH "Default search path for ROCM") +if(EXISTS ${ROCPROFILER_DEFAULT_ROCM_PATH}) + get_filename_component(_ROCPROFILER_DEFAULT_ROCM_PATH + "${ROCPROFILER_DEFAULT_ROCM_PATH}" REALPATH) + + if(NOT "${_ROCPROFILER_DEFAULT_ROCM_PATH}" STREQUAL + "${ROCPROFILER_DEFAULT_ROCM_PATH}") + set(ROCPROFILER_DEFAULT_ROCM_PATH + "${_ROCPROFILER_DEFAULT_ROCM_PATH}" + CACHE PATH "Default search path for ROCM" FORCE) + endif() +endif() + +# ----------------------------------------------------------------------------------------# +# +# Threading +# +# ----------------------------------------------------------------------------------------# + +set(CMAKE_THREAD_PREFER_PTHREAD ON) +set(THREADS_PREFER_PTHREAD_FLAG OFF) + +find_library(pthread_LIBRARY NAMES pthread pthreads) +find_package_handle_standard_args(pthread-library REQUIRED_VARS pthread_LIBRARY) + +find_library(pthread_LIBRARY NAMES pthread pthreads) +find_package_handle_standard_args(pthread-library REQUIRED_VARS pthread_LIBRARY) + +if(pthread_LIBRARY) + target_link_libraries(rocprofiler-threading INTERFACE ${pthread_LIBRARY}) +else() + find_package(Threads ${rocprofiler_FIND_QUIETLY} ${rocprofiler_FIND_REQUIREMENT}) + if(Threads_FOUND) + target_link_libraries(rocprofiler-threading INTERFACE Threads::Threads) + endif() +endif() + +# ----------------------------------------------------------------------------------------# +# +# dynamic linking (dl) and runtime (rt) libraries +# +# ----------------------------------------------------------------------------------------# + +foreach(_LIB dl rt) + find_library(${_LIB}_LIBRARY NAMES ${_LIB}) + find_package_handle_standard_args(${_LIB}-library REQUIRED_VARS ${_LIB}_LIBRARY) + if(${_LIB}_LIBRARY) + target_link_libraries(rocprofiler-threading INTERFACE ${${_LIB}_LIBRARY}) + endif() +endforeach() + +# ----------------------------------------------------------------------------------------# +# +# stdc++fs (filesystem) library +# +# ----------------------------------------------------------------------------------------# + +find_library(stdcxxfs_LIBRARY NAMES stdc++fs) +find_package_handle_standard_args(stdcxxfs-library REQUIRED_VARS stdcxxfs_LIBRARY) + +if(stdcxxfs_LIBRARY) + target_link_libraries(rocprofiler-stdcxxfs INTERFACE ${stdcxxfs_LIBRARY}) +else() + target_link_libraries(rocprofiler-stdcxxfs INTERFACE stdc++fs) +endif() + +# ----------------------------------------------------------------------------------------# +# +# HIP +# +# ----------------------------------------------------------------------------------------# + +find_package(rocm_version REQUIRED) +list(APPEND CMAKE_PREFIX_PATH "${rocm_version_DIR}" "${rocm_version_DIR}/llvm") +list(APPEND CMAKE_MODULE_PATH "${rocm_version_DIR}/hip/cmake" + "${rocm_version_DIR}/lib/cmake") +find_package(hip REQUIRED CONFIG) +target_link_libraries(rocprofiler-hip INTERFACE hip::host) + +# ----------------------------------------------------------------------------------------# +# +# HSA runtime +# +# ----------------------------------------------------------------------------------------# + +find_package( + hsa-runtime64 + REQUIRED + CONFIG + HINTS + ${rocm_version_DIR} + ${ROCM_PATH} + PATHS + ${rocm_version_DIR} + ${ROCM_PATH}) + +target_link_libraries(rocprofiler-hsa-runtime INTERFACE hsa-runtime64::hsa-runtime64) + +# ----------------------------------------------------------------------------------------# +# +# amd comgr +# +# ----------------------------------------------------------------------------------------# + +find_package( + amd_comgr + REQUIRED + CONFIG + HINTS + ${rocm_version_DIR} + ${ROCM_PATH} + PATHS + ${rocm_version_DIR} + ${ROCM_PATH} + PATH_SUFFIXES + lib/cmake/amd_comgr) + +target_link_libraries(rocprofiler-amd-comgr INTERFACE amd_comgr) diff --git a/cmake/rocprofiler_config_packaging.cmake b/cmake/rocprofiler_config_packaging.cmake new file mode 100644 index 0000000000..4b10a8972a --- /dev/null +++ b/cmake/rocprofiler_config_packaging.cmake @@ -0,0 +1,128 @@ +# configure packaging + +function(rocprofiler_parse_release) + if(EXISTS /etc/lsb-release AND NOT IS_DIRECTORY /etc/lsb-release) + file(READ /etc/lsb-release _LSB_RELEASE) + if(_LSB_RELEASE) + string(REGEX + REPLACE "DISTRIB_ID=(.*)\nDISTRIB_RELEASE=(.*)\nDISTRIB_CODENAME=.*" + "\\1-\\2" _SYSTEM_NAME "${_LSB_RELEASE}") + endif() + elseif(EXISTS /etc/os-release AND NOT IS_DIRECTORY /etc/os-release) + file(READ /etc/os-release _OS_RELEASE) + if(_OS_RELEASE) + string(REPLACE "\"" "" _OS_RELEASE "${_OS_RELEASE}") + string(REPLACE "-" " " _OS_RELEASE "${_OS_RELEASE}") + string(REGEX REPLACE "NAME=.*\nVERSION=([0-9\.]+).*\nID=([a-z]+).*" "\\2-\\1" + _SYSTEM_NAME "${_OS_RELEASE}") + endif() + endif() + string(TOLOWER "${_SYSTEM_NAME}" _SYSTEM_NAME) + if(NOT _SYSTEM_NAME) + set(_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}") + endif() + set(_SYSTEM_NAME + "${_SYSTEM_NAME}" + PARENT_SCOPE) +endfunction() + +# parse either /etc/lsb-release or /etc/os-release +rocprofiler_parse_release() + +if(NOT _SYSTEM_NAME) + set(_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}") +endif() + +# Add packaging directives +set(CPACK_PACKAGE_NAME ${PROJECT_NAME}) +set(CPACK_PACKAGE_VENDOR "Advanced Micro Devices, Inc.") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_DESCRIPTION}") +set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") +set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}") +set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}") +set(CPACK_PACKAGE_CONTACT "jonathan.madsen@amd.com") +set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") +set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF) +set(ROCPROFILER_CPACK_SYSTEM_NAME + "${_SYSTEM_NAME}" + CACHE STRING "System name, e.g. Linux or Ubuntu-18.04") +set(ROCPROFILER_CPACK_PACKAGE_SUFFIX "") + +set(CPACK_PACKAGE_FILE_NAME + "${CPACK_PACKAGE_NAME}-${ROCPROFILER_VERSION}-${ROCPROFILER_CPACK_SYSTEM_NAME}${ROCPROFILER_CPACK_PACKAGE_SUFFIX}" + ) +if(DEFINED ENV{CPACK_PACKAGE_FILE_NAME}) + set(CPACK_PACKAGE_FILE_NAME $ENV{CPACK_PACKAGE_FILE_NAME}) +endif() + +set(ROCPROFILER_PACKAGE_FILE_NAME + ${CPACK_PACKAGE_NAME}-${ROCPROFILER_VERSION}-${ROCPROFILER_CPACK_SYSTEM_NAME}${ROCPROFILER_CPACK_PACKAGE_SUFFIX} + ) +rocprofiler_add_feature(ROCPROFILER_PACKAGE_FILE_NAME "CPack filename") + +# -------------------------------------------------------------------------------------- # +# +# Debian package specific variables +# +# -------------------------------------------------------------------------------------- # + +set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "${PROJECT_HOMEPAGE_URL}") +set(CPACK_DEBIAN_PACKAGE_RELEASE + "${ROCPROFILER_CPACK_SYSTEM_NAME}${ROCPROFILER_CPACK_PACKAGE_SUFFIX}") +string(REGEX REPLACE "([a-zA-Z])-([0-9])" "\\1\\2" CPACK_DEBIAN_PACKAGE_RELEASE + "${CPACK_DEBIAN_PACKAGE_RELEASE}") +string(REPLACE "-" "~" CPACK_DEBIAN_PACKAGE_RELEASE "${CPACK_DEBIAN_PACKAGE_RELEASE}") +if(DEFINED ENV{CPACK_DEBIAN_PACKAGE_RELEASE}) + set(CPACK_DEBIAN_PACKAGE_RELEASE $ENV{CPACK_DEBIAN_PACKAGE_RELEASE}) +endif() + +set(_DEBIAN_PACKAGE_DEPENDS "") +if(rocm_version_FOUND) + set(_ROCPROFILER_SUFFIX " (>= 1.0.0.${rocm_version_NUMERIC_VERSION})") + set(_ROCTRACER_SUFFIX " (>= 1.0.0.${rocm_version_NUMERIC_VERSION})") + set(_ROCM_SMI_SUFFIX + " (>= ${rocm_version_MAJOR_VERSION}.0.0.${rocm_version_NUMERIC_VERSION})") +endif() +string(REPLACE ";" ", " _DEBIAN_PACKAGE_DEPENDS "${_DEBIAN_PACKAGE_DEPENDS}") +set(CPACK_DEBIAN_PACKAGE_DEPENDS + "${_DEBIAN_PACKAGE_DEPENDS}" + CACHE STRING "Debian package dependencies" FORCE) +rocprofiler_add_feature(CPACK_DEBIAN_PACKAGE_DEPENDS "Debian package dependencies") +set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT") + +# -------------------------------------------------------------------------------------- # +# +# RPM package specific variables +# +# -------------------------------------------------------------------------------------- # + +if(DEFINED CPACK_PACKAGING_INSTALL_PREFIX) + set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "${CPACK_PACKAGING_INSTALL_PREFIX}") +endif() + +set(CPACK_RPM_PACKAGE_RELEASE + "${ROCPROFILER_CPACK_SYSTEM_NAME}${ROCPROFILER_CPACK_PACKAGE_SUFFIX}") +string(REGEX REPLACE "([a-zA-Z])-([0-9])" "\\1\\2" CPACK_RPM_PACKAGE_RELEASE + "${CPACK_RPM_PACKAGE_RELEASE}") +string(REPLACE "-" "~" CPACK_RPM_PACKAGE_RELEASE "${CPACK_RPM_PACKAGE_RELEASE}") +if(DEFINED ENV{CPACK_RPM_PACKAGE_RELEASE}) + set(CPACK_RPM_PACKAGE_RELEASE $ENV{CPACK_RPM_PACKAGE_RELEASE}) +endif() + +# Get rpm distro +if(CPACK_RPM_PACKAGE_RELEASE) + set(CPACK_RPM_PACKAGE_RELEASE_DIST ON) +endif() +set(CPACK_RPM_FILE_NAME "RPM-DEFAULT") + +# -------------------------------------------------------------------------------------- # +# +# Prepare final version for the CPACK use +# +# -------------------------------------------------------------------------------------- # + +set(CPACK_PACKAGE_VERSION + "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}" + ) + +include(CPack) diff --git a/cmake/rocprofiler_formatting.cmake b/cmake/rocprofiler_formatting.cmake new file mode 100644 index 0000000000..fb372905b8 --- /dev/null +++ b/cmake/rocprofiler_formatting.cmake @@ -0,0 +1,102 @@ +# ------------------------------------------------------------------------------# +# +# creates following targets to format code: +# - format +# - format-source +# - format-cmake +# - format-python +# - format-rocprofiler-source +# - format-rocprofiler-cmake +# - format-rocprofiler-python +# +# ------------------------------------------------------------------------------# + +include_guard(DIRECTORY) + +find_program(ROCPROFILER_CLANG_FORMAT_EXE NAMES clang-format-11 clang-format-mp-11) +find_program(ROCPROFILER_CMAKE_FORMAT_EXE NAMES cmake-format) +find_program(ROCPROFILER_BLACK_FORMAT_EXE NAMES black) + +add_custom_target(format-rocprofiler) +if(NOT TARGET format) + add_custom_target(format) +endif() +foreach(_TYPE source python cmake) + if(NOT TARGET format-${_TYPE}) + add_custom_target(format-${_TYPE}) + endif() +endforeach() + +if(ROCPROFILER_CLANG_FORMAT_EXE + OR ROCPROFILER_BLACK_FORMAT_EXE + OR ROCPROFILER_CMAKE_FORMAT_EXE) + + set(rocp_source_files) + set(rocp_header_files) + set(rocp_python_files) + set(rocp_cmake_files ${PROJECT_SOURCE_DIR}/CMakeLists.txt + ${PROJECT_SOURCE_DIR}/external/CMakeLists.txt) + + foreach(_DIR cmake samples source tests) + foreach(_TYPE header_files source_files cmake_files python_files) + set(${_TYPE}) + endforeach() + file(GLOB_RECURSE header_files ${PROJECT_SOURCE_DIR}/${_DIR}/*.h + ${PROJECT_SOURCE_DIR}/${_DIR}/*.hpp) + file(GLOB_RECURSE source_files ${PROJECT_SOURCE_DIR}/${_DIR}/*.c + ${PROJECT_SOURCE_DIR}/${_DIR}/*.cpp) + file(GLOB_RECURSE cmake_files ${PROJECT_SOURCE_DIR}/${_DIR}/*CMakeLists.txt + ${PROJECT_SOURCE_DIR}/${_DIR}/*.cmake) + file(GLOB_RECURSE python_files ${PROJECT_SOURCE_DIR}/${_DIR}/*.py) + foreach(_TYPE header_files source_files cmake_files python_files) + list(APPEND rocp_${_TYPE} ${${_TYPE}}) + endforeach() + endforeach() + + foreach(_TYPE header_files source_files cmake_files python_files) + if(rocp_${_TYPE}) + list(REMOVE_DUPLICATES rocp_${_TYPE}) + list(SORT rocp_${_TYPE}) + endif() + endforeach() + + if(ROCPROFILER_CLANG_FORMAT_EXE) + add_custom_target( + format-rocprofiler-source + ${ROCPROFILER_CLANG_FORMAT_EXE} -i ${rocp_header_files} ${rocp_source_files} + COMMENT + "[rocprofiler] Running source formatter ${ROCPROFILER_CLANG_FORMAT_EXE}..." + ) + endif() + + if(ROCPROFILER_BLACK_FORMAT_EXE) + add_custom_target( + format-rocprofiler-python + ${ROCPROFILER_BLACK_FORMAT_EXE} -q ${rocp_python_files} + COMMENT + "[rocprofiler] Running Python formatter ${ROCPROFILER_BLACK_FORMAT_EXE}..." + ) + endif() + + if(ROCPROFILER_CMAKE_FORMAT_EXE) + add_custom_target( + format-rocprofiler-cmake + ${ROCPROFILER_CMAKE_FORMAT_EXE} -i ${rocp_cmake_files} + COMMENT + "[rocprofiler] Running CMake formatter ${ROCPROFILER_CMAKE_FORMAT_EXE}..." + ) + endif() + + foreach(_TYPE source python cmake) + if(TARGET format-rocprofiler-${_TYPE}) + add_dependencies(format-rocprofiler format-rocprofiler-${_TYPE}) + add_dependencies(format-${_TYPE} format-rocprofiler-${_TYPE}) + endif() + endforeach() + + foreach(_TYPE source python) + if(TARGET format-rocprofiler-${_TYPE}) + add_dependencies(format format-rocprofiler-${_TYPE}) + endif() + endforeach() +endif() diff --git a/cmake/rocprofiler_interfaces.cmake b/cmake/rocprofiler_interfaces.cmake new file mode 100644 index 0000000000..360835d78b --- /dev/null +++ b/cmake/rocprofiler_interfaces.cmake @@ -0,0 +1,44 @@ +# +# +# Forward declaration of all INTERFACE targets +# +# + +include(rocprofiler_utilities) + +# +# interfaces for build flags +# +rocprofiler_add_interface_library( + rocprofiler-headers + "Provides minimal set of include flags to compile with rocprofiler") +rocprofiler_add_interface_library(rocprofiler-build-flags + "Provides generalized build flags for rocprofiler") +rocprofiler_add_interface_library(rocprofiler-threading "Enables multithreading support") +rocprofiler_add_interface_library(rocprofiler-perfetto "Enables Perfetto support") +rocprofiler_add_interface_library(rocprofiler-compile-definitions "Compile definitions") +rocprofiler_add_interface_library(rocprofiler-static-libgcc + "Link to static version of libgcc") +rocprofiler_add_interface_library(rocprofiler-static-libstdcxx + "Link to static version of libstdc++") +rocprofiler_add_interface_library(rocprofiler-developer-flags + "Compiler flags for developers (more warnings, etc.)") +rocprofiler_add_interface_library(rocprofiler-debug-flags + "Compiler flags for more debug info") +rocprofiler_add_interface_library(rocprofiler-release-flags + "Compiler flags for more debug info") +rocprofiler_add_interface_library(rocprofiler-stack-protector + "Adds stack-protector compiler flags") +rocprofiler_add_interface_library(rocprofiler-memcheck INTERFACE) + +# +# interfaces for libraries +# +rocprofiler_add_interface_library(rocprofiler-dl + "Build flags for dynamic linking library") +rocprofiler_add_interface_library(rocprofiler-rt "Build flags for runtime library") +rocprofiler_add_interface_library(rocprofiler-hip "HIP library") +rocprofiler_add_interface_library(rocprofiler-hsa-runtime "HSA runtime library") +rocprofiler_add_interface_library(rocprofiler-amd-comgr "AMD comgr library") +rocprofiler_add_interface_library(rocprofiler-googletest "Google Test library" INTERNAL) +rocprofiler_add_interface_library(rocprofiler-stdcxxfs "C++ filesystem library" INTERNAL) diff --git a/cmake/rocprofiler_linting.cmake b/cmake/rocprofiler_linting.cmake new file mode 100644 index 0000000000..4858e1ef23 --- /dev/null +++ b/cmake/rocprofiler_linting.cmake @@ -0,0 +1,36 @@ +include_guard(GLOBAL) + +# ----------------------------------------------------------------------------------------# +# +# Clang Tidy +# +# ----------------------------------------------------------------------------------------# + +find_program(ROCPROFILER_CLANG_TIDY_COMMAND NAMES clang-tidy) + +macro(ROCPROFILER_ACTIVATE_CLANG_TIDY) + if(ROCPROFILER_ENABLE_CLANG_TIDY) + if(NOT ROCPROFILER_CLANG_TIDY_COMMAND) + message( + FATAL_ERROR + "ROCPROFILER_ENABLE_CLANG_TIDY is ON but clang-tidy is not found!") + endif() + + set(CMAKE_CXX_CLANG_TIDY ${ROCPROFILER_CLANG_TIDY_COMMAND} + -header-filter=${PROJECT_SOURCE_DIR}/.*) + + # Create a preprocessor definition that depends on .clang-tidy content so the + # compile command will change when .clang-tidy changes. This ensures that a + # subsequent build re-runs clang-tidy on all sources even if they do not otherwise + # need to be recompiled. Nothing actually uses this definition. We add it to + # targets on which we run clang-tidy just to get the build dependency on the + # .clang-tidy file. + file(SHA1 ${PROJECT_SOURCE_DIR}/.clang-tidy clang_tidy_sha1) + set(CLANG_TIDY_DEFINITIONS "CLANG_TIDY_SHA1=${clang_tidy_sha1}") + unset(clang_tidy_sha1) + endif() +endmacro() + +macro(ROCPROFILER_DEACTIVATE_CLANG_TIDY) + set(CMAKE_CXX_CLANG_TIDY) +endmacro() diff --git a/cmake/rocprofiler_memcheck.cmake b/cmake/rocprofiler_memcheck.cmake new file mode 100644 index 0000000000..8924667573 --- /dev/null +++ b/cmake/rocprofiler_memcheck.cmake @@ -0,0 +1,67 @@ +# +# +# +set(ROCPROFILER_MEMCHECK_TYPES "ThreadSanitizer" "AddressSanitizer" "LeakSanitizer" + "MemorySanitizer" "UndefinedBehaviorSanitizer") + +if(ROCPROFILER_MEMCHECK AND NOT ROCPROFILER_MEMCHECK IN_LIST ROCPROFILER_MEMCHECK_TYPES) + message( + FATAL_ERROR + "Unsupported memcheck type '${ROCPROFILER_MEMCHECK}'. Options: ${ROCPROFILER_MEMCHECK_TYPES}" + ) +endif() + +set_property(CACHE ROCPROFILER_MEMCHECK PROPERTY STRINGS "${ROCPROFILER_MEMCHECK_TYPES}") + +function(rocprofiler_add_memcheck_flags _TYPE) + target_compile_options( + rocprofiler-memcheck + INTERFACE $) + target_link_options(rocprofiler-memcheck INTERFACE + $) +endfunction() + +function(rocprofiler_set_memcheck_env _TYPE _LIB_BASE) + set(_LIBS ${_LIB_BASE}) + + foreach(_N 6 5 4 3 2 1 0) + list( + APPEND _LIBS + ${CMAKE_SHARED_LIBRARY_PREFIX}${_LIB_BASE}${CMAKE_SHARED_LIBRARY_SUFFIX}.${_N} + ) + endforeach() + + foreach(_LIB ${_LIBS}) + if(NOT ${_TYPE}_LIBRARY) + find_library(${_TYPE}_LIBRARY NAMES ${_LIB} ${ARGN}) + endif() + endforeach() + + target_link_libraries(rocprofiler-memcheck INTERFACE ${_LIB_BASE}) + + if(${_TYPE}_LIBRARY) + set(ROCPROFILER_MEMCHECK_PRELOAD_ENV + " LD_PRELOAD=${${_TYPE}_LIBRARY} " + CACHE INTERNAL " LD_PRELOAD env variable for tests " FORCE) + endif() +endfunction() + +# always unset so that it doesn't preload if memcheck disabled +unset(ROCPROFILER_MEMCHECK_PRELOAD_ENV CACHE) + +if(ROCPROFILER_MEMCHECK STREQUAL " AddressSanitizer ") + rocprofiler_add_memcheck_flags(" address ") + rocprofiler_set_memcheck_env(" ${ROCPROFILER_MEMCHECK}" "asan ") +elseif(ROCPROFILER_MEMCHECK STREQUAL " LeakSanitizer ") + rocprofiler_add_memcheck_flags(" leak ") + rocprofiler_set_memcheck_env(" ${ROCPROFILER_MEMCHECK}" "lsan ") +elseif(ROCPROFILER_MEMCHECK STREQUAL " MemorySanitizer ") + rocprofiler_add_memcheck_flags(" memory ") +elseif(ROCPROFILER_MEMCHECK STREQUAL " ThreadSanitizer ") + rocprofiler_add_memcheck_flags(" thread ") + rocprofiler_set_memcheck_env(" ${ROCPROFILER_MEMCHECK}" "tsan ") +elseif(ROCPROFILER_MEMCHECK STREQUAL " UndefinedBehaviorSanitizer ") + rocprofiler_add_memcheck_flags(" undefined ") + rocprofiler_set_memcheck_env(" ${ROCPROFILER_MEMCHECK}" "ubsan ") +endif() diff --git a/cmake/rocprofiler_options.cmake b/cmake/rocprofiler_options.cmake new file mode 100644 index 0000000000..6632a7d319 --- /dev/null +++ b/cmake/rocprofiler_options.cmake @@ -0,0 +1,104 @@ +# +# rocprofiler_options.cmake +# +# Configure miscellaneous settings +# +# standard cmake options +rocprofiler_add_option(BUILD_SHARED_LIBS "Build shared libraries" ON) +rocprofiler_add_option(BUILD_STATIC_LIBS "Build static libraries" OFF) +rocprofiler_add_option(CMAKE_POSITION_INDEPENDENT_CODE "Build position independent code" + ON) + +# export compile commands in the project +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_EXTENSIONS OFF) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_EXTENSIONS OFF) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +rocprofiler_add_option(ROCPROFILER_BUILD_TESTS "Enable building the tests" OFF) +rocprofiler_add_option(ROCPROFILER_BUILD_SAMPLES "Enable building the code samples" OFF) + +# CLI and FILE plugins are always built +foreach(_PLUGIN "ATT" "CTF" "PERFETTO") + rocprofiler_add_option(ROCPROFILER_BUILD_PLUGIN_${_PLUGIN} + "Enable building the ${_PLUGIN} plugin" ON) +endforeach() + +rocprofiler_add_option(ROCPROFILER_DEBUG_TRACE "Enable debug tracing" OFF ADVANCED) +rocprofiler_add_option(ROCPROFILER_LD_AQLPROFILE + "Enable direct loading of AQL-profile HSA extension" OFF ADVANCED) +rocprofiler_add_option(ROCPROFILER_BUILD_CI "Enable continuous integration additions" OFF + ADVANCED) +rocprofiler_add_option(ROCPROFILER_ENABLE_CLANG_TIDY "Enable clang-tidy checks" OFF + ADVANCED) +rocprofiler_add_option(ROCPROFILER_BUILD_WERROR "Any compiler warnings are errors" OFF + ADVANCED) + +rocprofiler_add_option( + ROCPROFILER_BUILD_DEVELOPER "Extra build flags for development like -Werror" + ${ROCPROFILER_BUILD_CI} ADVANCED) +rocprofiler_add_option(ROCPROFILER_BUILD_RELEASE "Build with minimal debug info" OFF + ADVANCED) +rocprofiler_add_option(ROCPROFILER_BUILD_DEBUG "Build with extra debug info" OFF ADVANCED) +rocprofiler_add_option(ROCPROFILER_BUILD_STATIC_LIBGCC + "Build with -static-libgcc if possible" OFF ADVANCED) +rocprofiler_add_option(ROCPROFILER_BUILD_STATIC_LIBSTDCXX + "Build with -static-libstdc++ if possible" OFF ADVANCED) +rocprofiler_add_option(ROCPROFILER_BUILD_STACK_PROTECTOR "Build with -fstack-protector" + OFF ADVANCED) + +# In the future, we will do this even with clang-tidy enabled +if(ROCPROFILER_BUILD_CI AND NOT ROCPROFILER_ENABLE_CLANG_TIDY) + message(STATUS "Forcing ROCPROFILER_BUILD_WERROR=ON because ROCPROFILER_BUILD_CI=ON") + set(ROCPROFILER_BUILD_WERROR + ON + CACHE BOOL + "Any compiler warnings are errors (forced due ROCPROFILER_BUILD_CI=ON)" + FORCE) +endif() + +set(ROCPROFILER_BUILD_TYPES "Release" "RelWithDebInfo" "Debug" "MinSizeRel" "Coverage") + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE + "Release" + CACHE STRING "Build type" FORCE) +endif() + +if(NOT CMAKE_BUILD_TYPE IN_LIST ROCPROFILER_BUILD_TYPES) + message( + FATAL_ERROR + "Unsupported build type '${CMAKE_BUILD_TYPE}'. Options: ${ROCPROFILER_BUILD_TYPES}" + ) +endif() + +if(ROCPROFILER_BUILD_CI) + foreach(_BUILD_TYPE ${ROCPROFILER_BUILD_TYPES}) + string(TOUPPER "${_BUILD_TYPE}" _BUILD_TYPE) + + # remove NDEBUG preprocessor def so that asserts are triggered + string(REGEX REPLACE ".DNDEBUG" "" CMAKE_C_FLAGS_${_BUILD_TYPE} + "${CMAKE_C_FLAGS_${_BUILD_TYPE}}") + string(REGEX REPLACE ".DNDEBUG" "" CMAKE_CXX_FLAGS_${_BUILD_TYPE} + "${CMAKE_CXX_FLAGS_${_BUILD_TYPE}}") + endforeach() +endif() + +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${ROCPROFILER_BUILD_TYPES}") +endif() + +rocprofiler_add_cache_option(ROCPROFILER_MEMCHECK "" STRING "Memory checker type" + ADVANCED) + +# ASAN is defined by testing team on Jenkins +if(ASAN) + set(ROCPROFILER_MEMCHECK + "AddressSanitizer" + CACHE STRING "Memory checker type (forced by ASAN defined)" FORCE) +endif() + +include(rocprofiler_memcheck) diff --git a/cmake/rocprofiler_utilities.cmake b/cmake/rocprofiler_utilities.cmake new file mode 100644 index 0000000000..44b37af6e3 --- /dev/null +++ b/cmake/rocprofiler_utilities.cmake @@ -0,0 +1,928 @@ +# include guard +include_guard(GLOBAL) + +# MacroUtilities - useful macros and functions for generic tasks +# + +cmake_policy(PUSH) +cmake_policy(SET CMP0054 NEW) +cmake_policy(SET CMP0057 NEW) + +include(CMakeDependentOption) +include(CMakeParseArguments) + +# ----------------------------------------------------------------------- +# message which handles ROCPROFILER_QUIET_CONFIG settings +# ----------------------------------------------------------------------- +# +function(ROCPROFILER_MESSAGE TYPE) + if(NOT ROCPROFILER_QUIET_CONFIG) + message(${TYPE} "[rocprofiler] ${ARGN}") + endif() +endfunction() + +# ----------------------------------------------------------------------- +# Save a set of variables with the given prefix +# ----------------------------------------------------------------------- +macro(ROCPROFILER_SAVE_VARIABLES _PREFIX) + # parse args + cmake_parse_arguments( + SAVE + "" # options + "CONDITION" # single value args + "VARIABLES" # multiple value args + ${ARGN}) + if(DEFINED SAVE_CONDITION AND NOT "${SAVE_CONDITION}" STREQUAL "") + if(${SAVE_CONDITION}) + foreach(_VAR ${SAVE_VARIABLES}) + if(DEFINED ${_VAR}) + set(${_PREFIX}_${_VAR} "${${_VAR}}") + else() + message(AUTHOR_WARNING "${_VAR} is not defined") + endif() + endforeach() + endif() + else() + foreach(_VAR ${SAVE_VARIABLES}) + if(DEFINED ${_VAR}) + set(${_PREFIX}_${_VAR} "${${_VAR}}") + else() + message(AUTHOR_WARNING "${_VAR} is not defined") + endif() + endforeach() + endif() + unset(SAVE_CONDITION) + unset(SAVE_VARIABLES) +endmacro() + +# ----------------------------------------------------------------------- +# Restore a set of variables with the given prefix +# ----------------------------------------------------------------------- +macro(ROCPROFILER_RESTORE_VARIABLES _PREFIX) + # parse args + cmake_parse_arguments( + RESTORE + "" # options + "CONDITION" # single value args + "VARIABLES" # multiple value args + ${ARGN}) + if(DEFINED RESTORE_CONDITION AND NOT "${RESTORE_CONDITION}" STREQUAL "") + if(${RESTORE_CONDITION}) + foreach(_VAR ${RESTORE_VARIABLES}) + if(DEFINED ${_PREFIX}_${_VAR}) + set(${_VAR} ${${_PREFIX}_${_VAR}}) + unset(${_PREFIX}_${_VAR}) + else() + message(AUTHOR_WARNING "${_PREFIX}_${_VAR} is not defined") + endif() + endforeach() + endif() + else() + foreach(_VAR ${RESTORE_VARIABLES}) + if(DEFINED ${_PREFIX}_${_VAR}) + set(${_VAR} ${${_PREFIX}_${_VAR}}) + unset(${_PREFIX}_${_VAR}) + else() + message(AUTHOR_WARNING "${_PREFIX}_${_VAR} is not defined") + endif() + endforeach() + endif() + unset(RESTORE_CONDITION) + unset(RESTORE_VARIABLES) +endmacro() + +# ----------------------------------------------------------------------- +# function - rocprofiler_capitalize - make a string capitalized (first letter is capital) +# usage: capitalize("SHARED" CShared) message(STATUS "-- CShared is \"${CShared}\"") $ -- +# CShared is "Shared" +function(ROCPROFILER_CAPITALIZE str var) + # make string lower + string(TOLOWER "${str}" str) + string(SUBSTRING "${str}" 0 1 _first) + string(TOUPPER "${_first}" _first) + string(SUBSTRING "${str}" 1 -1 _remainder) + string(CONCAT str "${_first}" "${_remainder}") + set(${var} + "${str}" + PARENT_SCOPE) +endfunction() + +# ------------------------------------------------------------------------------# +# function rocprofiler_strip_target( [FORCE] [EXPLICIT]) +# +# Creates a post-build command which strips a binary. FORCE flag will override +# +function(ROCPROFILER_STRIP_TARGET) + cmake_parse_arguments(STRIP "FORCE;EXPLICIT" "" "ARGS" ${ARGN}) + + list(LENGTH STRIP_UNPARSED_ARGUMENTS NUM_UNPARSED) + + if(NUM_UNPARSED EQUAL 1) + set(_TARGET "${STRIP_UNPARSED_ARGUMENTS}") + else() + rocprofiler_message( + FATAL_ERROR "rocprofiler_strip_target cannot deduce target from \"${ARGN}\"") + endif() + + if(NOT TARGET "${_TARGET}") + rocprofiler_message( + FATAL_ERROR + "rocprofiler_strip_target not provided valid target: \"${_TARGET}\"") + endif() + + if(CMAKE_STRIP AND (STRIP_FORCE OR ROCPROFILER_STRIP_LIBRARIES)) + if(STRIP_EXPLICIT) + add_custom_command( + TARGET ${_TARGET} + POST_BUILD + COMMAND ${CMAKE_STRIP} ${STRIP_ARGS} $ + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Stripping ${_TARGET}...") + else() + add_custom_command( + TARGET ${_TARGET} + POST_BUILD + COMMAND + ${CMAKE_STRIP} -w --keep-symbol="rocprofiler_init" + --keep-symbol="rocprofiler_finalize" + --keep-symbol="rocprofiler_push_trace" + --keep-symbol="rocprofiler_pop_trace" + --keep-symbol="rocprofiler_push_region" + --keep-symbol="rocprofiler_pop_region" + --keep-symbol="rocprofiler_set_env" + --keep-symbol="rocprofiler_set_mpi" + --keep-symbol="rocprofiler_reset_preload" + --keep-symbol="rocprofiler_set_instrumented" + --keep-symbol="rocprofiler_user_*" --keep-symbol="ompt_start_tool" + --keep-symbol="kokkosp_*" --keep-symbol="OnLoad" + --keep-symbol="OnUnload" --keep-symbol="OnLoadToolProp" + --keep-symbol="OnUnloadTool" --keep-symbol="__libc_start_main" + ${STRIP_ARGS} $ + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Stripping ${_TARGET}...") + endif() + endif() +endfunction() + +# ------------------------------------------------------------------------------# +# function add_rocprofiler_test_target() +# +# Creates a target which runs ctest but depends on all the tests being built. +# +function(ADD_ROCPROFILER_TEST_TARGET) + if(NOT TARGET rocprofiler-test) + add_custom_target( + rocprofiler-test + COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR} --target test + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + COMMENT "Running tests...") + endif() +endfunction() + +# ----------------------------------------------------------------------------------------# +# macro rocprofiler_checkout_git_submodule() +# +# Run "git submodule update" if a file in a submodule does not exist +# +# ARGS: RECURSIVE (option) -- add "--recursive" flag RELATIVE_PATH (one value) -- +# typically the relative path to submodule from PROJECT_SOURCE_DIR WORKING_DIRECTORY (one +# value) -- (default: PROJECT_SOURCE_DIR) TEST_FILE (one value) -- file to check for +# (default: CMakeLists.txt) ADDITIONAL_CMDS (many value) -- any addition commands to pass +# +function(ROCPROFILER_CHECKOUT_GIT_SUBMODULE) + # parse args + cmake_parse_arguments( + CHECKOUT "RECURSIVE" + "RELATIVE_PATH;WORKING_DIRECTORY;TEST_FILE;REPO_URL;REPO_BRANCH" + "ADDITIONAL_CMDS" ${ARGN}) + + if(NOT CHECKOUT_WORKING_DIRECTORY) + set(CHECKOUT_WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) + endif() + + if(NOT CHECKOUT_TEST_FILE) + set(CHECKOUT_TEST_FILE "CMakeLists.txt") + endif() + + # default assumption + if(NOT CHECKOUT_REPO_BRANCH) + set(CHECKOUT_REPO_BRANCH "master") + endif() + + find_package(Git) + set(_DIR "${CHECKOUT_WORKING_DIRECTORY}/${CHECKOUT_RELATIVE_PATH}") + # ensure the (possibly empty) directory exists + if(NOT EXISTS "${_DIR}") + if(NOT CHECKOUT_REPO_URL) + message(FATAL_ERROR "submodule directory does not exist") + endif() + endif() + + # if this file exists --> project has been checked out if not exists --> not been + # checked out + set(_TEST_FILE "${_DIR}/${CHECKOUT_TEST_FILE}") + # assuming a .gitmodules file exists + set(_SUBMODULE "${PROJECT_SOURCE_DIR}/.gitmodules") + + set(_TEST_FILE_EXISTS OFF) + if(EXISTS "${_TEST_FILE}" AND NOT IS_DIRECTORY "${_TEST_FILE}") + set(_TEST_FILE_EXISTS ON) + endif() + + if(_TEST_FILE_EXISTS) + return() + endif() + + find_package(Git REQUIRED) + + set(_SUBMODULE_EXISTS OFF) + if(EXISTS "${_SUBMODULE}" AND NOT IS_DIRECTORY "${_SUBMODULE}") + set(_SUBMODULE_EXISTS ON) + endif() + + set(_HAS_REPO_URL OFF) + if(NOT "${CHECKOUT_REPO_URL}" STREQUAL "") + set(_HAS_REPO_URL ON) + endif() + + # if the module has not been checked out + if(NOT _TEST_FILE_EXISTS AND _SUBMODULE_EXISTS) + # perform the checkout + execute_process( + COMMAND ${GIT_EXECUTABLE} submodule update --init ${_RECURSE} + ${CHECKOUT_ADDITIONAL_CMDS} ${CHECKOUT_RELATIVE_PATH} + WORKING_DIRECTORY ${CHECKOUT_WORKING_DIRECTORY} + RESULT_VARIABLE RET) + + # check the return code + if(RET GREATER 0) + set(_CMD "${GIT_EXECUTABLE} submodule update --init ${_RECURSE} + ${CHECKOUT_ADDITIONAL_CMDS} ${CHECKOUT_RELATIVE_PATH}") + message(STATUS "function(rocprofiler_checkout_git_submodule) failed.") + message(FATAL_ERROR "Command: \"${_CMD}\"") + else() + set(_TEST_FILE_EXISTS ON) + endif() + endif() + + if(NOT _TEST_FILE_EXISTS AND _HAS_REPO_URL) + message( + STATUS "Checking out '${CHECKOUT_REPO_URL}' @ '${CHECKOUT_REPO_BRANCH}'...") + + # remove the existing directory + if(EXISTS "${_DIR}") + execute_process(COMMAND ${CMAKE_COMMAND} -E remove_directory ${_DIR}) + endif() + + # perform the checkout + execute_process( + COMMAND + ${GIT_EXECUTABLE} clone -b ${CHECKOUT_REPO_BRANCH} + ${CHECKOUT_ADDITIONAL_CMDS} ${CHECKOUT_REPO_URL} ${CHECKOUT_RELATIVE_PATH} + WORKING_DIRECTORY ${CHECKOUT_WORKING_DIRECTORY} + RESULT_VARIABLE RET) + + # perform the submodule update + if(CHECKOUT_RECURSIVE + AND EXISTS "${_DIR}" + AND IS_DIRECTORY "${_DIR}") + execute_process( + COMMAND ${GIT_EXECUTABLE} submodule update --init ${_RECURSE} + WORKING_DIRECTORY ${_DIR} + RESULT_VARIABLE RET) + endif() + + # check the return code + if(RET GREATER 0) + set(_CMD + "${GIT_EXECUTABLE} clone -b ${CHECKOUT_REPO_BRANCH} + ${CHECKOUT_ADDITIONAL_CMDS} ${CHECKOUT_REPO_URL} ${CHECKOUT_RELATIVE_PATH}" + ) + message(STATUS "function(rocprofiler_checkout_git_submodule) failed.") + message(FATAL_ERROR "Command: \"${_CMD}\"") + else() + set(_TEST_FILE_EXISTS ON) + endif() + endif() + + if(NOT EXISTS "${_TEST_FILE}" OR NOT _TEST_FILE_EXISTS) + message( + FATAL_ERROR + "Error checking out submodule: '${CHECKOUT_RELATIVE_PATH}' to '${_DIR}'") + endif() + +endfunction() + +# ----------------------------------------------------------------------------------------# +# try to find a package quietly +# +function(ROCPROFILER_TEST_FIND_PACKAGE PACKAGE_NAME OUTPUT_VAR) + cmake_parse_arguments(PACKAGE "" "" "UNSET" ${ARGN}) + find_package(${PACKAGE_NAME} QUIET ${PACKAGE_UNPARSED_ARGUMENTS}) + if(NOT ${PACKAGE_NAME}_FOUND) + set(${OUTPUT_VAR} + OFF + PARENT_SCOPE) + else() + set(${OUTPUT_VAR} + ON + PARENT_SCOPE) + endif() + foreach(_ARG ${PACKAGE_UNSET} FIND_PACKAGE_MESSAGE_DETAILS_${PACKAGE_NAME}) + unset(${_ARG} CACHE) + endforeach() +endfunction() + +# ----------------------------------------------------------------------------------------# +# macro to add an interface lib +# +function(ROCPROFILER_ADD_INTERFACE_LIBRARY _TARGET _DESCRIPT) + add_library(${_TARGET} INTERFACE) + add_library(${PROJECT_NAME}::${_TARGET} ALIAS ${_TARGET}) + set(_ARGS "${ARGN}") + if(NOT "INTERNAL" IN_LIST _ARGS) + install( + TARGETS ${_TARGET} + DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT core + EXPORT ${PROJECT_NAME}-library-targets + OPTIONAL) + endif() +endfunction() + +# ----------------------------------------------------------------------- +# function add_feature( ) Add a project feature, whose activation is +# specified by the existence of the variable , to the list of enabled/disabled +# features, plus a docstring describing the feature +# +function(ROCPROFILER_ADD_FEATURE _var _description) + set(EXTRA_DESC "") + foreach(currentArg ${ARGN}) + if(NOT "${currentArg}" STREQUAL "${_var}" + AND NOT "${currentArg}" STREQUAL "${_description}" + AND NOT "${currentArg}" STREQUAL "CMAKE_DEFINE" + AND NOT "${currentArg}" STREQUAL "DOC") + set(EXTRA_DESC "${EXTA_DESC}${currentArg}") + endif() + endforeach() + + set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_FEATURES ${_var}) + set_property(GLOBAL PROPERTY ${_var}_DESCRIPTION "${_description}${EXTRA_DESC}") + + if("CMAKE_DEFINE" IN_LIST ARGN) + set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_DEFINES + "${_var} @${_var}@") + if(ROCPROFILER_BUILD_DOCS) + set_property( + GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_OPTIONS_DOC + "${_var}` | ${_description}${EXTRA_DESC} |") + endif() + elseif("DOC" IN_LIST ARGN AND ROCPROFILER_BUILD_DOCS) + set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_OPTIONS_DOC + "${_var}` | ${_description}${EXTRA_DESC} |") + endif() +endfunction() + +# ----------------------------------------------------------------------------------------# +# function add_option( [NO_FEATURE]) Add an +# option and add as a feature if NO_FEATURE is not provided +# +function(ROCPROFILER_ADD_OPTION _NAME _MESSAGE _DEFAULT) + option(${_NAME} "${_MESSAGE}" ${_DEFAULT}) + if("NO_FEATURE" IN_LIST ARGN) + mark_as_advanced(${_NAME}) + else() + rocprofiler_add_feature(${_NAME} "${_MESSAGE}") + if(ROCPROFILER_BUILD_DOCS) + set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_OPTIONS_DOC + "${_NAME}` | ${_MESSAGE} |") + endif() + endif() + if("ADVANCED" IN_LIST ARGN) + mark_as_advanced(${_NAME}) + endif() + if("CMAKE_DEFINE" IN_LIST ARGN) + set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_DEFINES ${_NAME}) + endif() +endfunction() + +# ----------------------------------------------------------------------------------------# +# function rocprofiler_add_cache_option( +# [NO_FEATURE] [ADVANCED] [CMAKE_DEFINE]) +# +function(ROCPROFILER_ADD_CACHE_OPTION _NAME _DEFAULT _TYPE _MESSAGE) + set(_FORCE) + if("FORCE" IN_LIST ARGN) + set(_FORCE FORCE) + endif() + + set(${_NAME} + "${_DEFAULT}" + CACHE ${_TYPE} "${_MESSAGE}" ${_FORCE}) + + if("NO_FEATURE" IN_LIST ARGN) + mark_as_advanced(${_NAME}) + else() + rocprofiler_add_feature(${_NAME} "${_MESSAGE}") + + if(ROCPROFILER_BUILD_DOCS) + set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_OPTIONS_DOC + "${_NAME}` | ${_MESSAGE} |") + endif() + endif() + + if("ADVANCED" IN_LIST ARGN) + mark_as_advanced(${_NAME}) + endif() + + if("CMAKE_DEFINE" IN_LIST ARGN) + set_property(GLOBAL APPEND PROPERTY ${PROJECT_NAME}_CMAKE_DEFINES ${_NAME}) + endif() +endfunction() + +# ----------------------------------------------------------------------------------------# +# function rocprofiler_report_feature_changes() :: print changes in features +# +function(ROCPROFILER_REPORT_FEATURE_CHANGES) + get_property(_features GLOBAL PROPERTY ${PROJECT_NAME}_FEATURES) + if(NOT "${_features}" STREQUAL "") + list(REMOVE_DUPLICATES _features) + list(SORT _features) + endif() + foreach(_feature ${_features}) + if("${ARGN}" STREQUAL "") + rocprofiler_watch_for_change(${_feature}) + elseif("${_feature}" IN_LIST ARGN) + rocprofiler_watch_for_change(${_feature}) + endif() + endforeach() +endfunction() + +# ----------------------------------------------------------------------------------------# +# function print_enabled_features() Print enabled features plus their docstrings. +# +function(ROCPROFILER_PRINT_ENABLED_FEATURES) + set(_basemsg "The following features are defined/enabled (+):") + set(_currentFeatureText "${_basemsg}") + get_property(_features GLOBAL PROPERTY ${PROJECT_NAME}_FEATURES) + if(NOT "${_features}" STREQUAL "") + list(REMOVE_DUPLICATES _features) + list(SORT _features) + endif() + foreach(_feature ${_features}) + if(${_feature}) + # add feature to text + set(_currentFeatureText "${_currentFeatureText}\n ${_feature}") + # get description + get_property(_desc GLOBAL PROPERTY ${_feature}_DESCRIPTION) + # print description, if not standard ON/OFF, print what is set to + if(_desc) + if(NOT "${${_feature}}" STREQUAL "ON" AND NOT "${${_feature}}" STREQUAL + "TRUE") + set(_currentFeatureText + "${_currentFeatureText}: ${_desc} -- [\"${${_feature}}\"]") + else() + string(REGEX REPLACE "^${PROJECT_NAME}_USE_" "" _feature_tmp + "${_feature}") + string(TOLOWER "${_feature_tmp}" _feature_tmp_l) + rocprofiler_capitalize("${_feature_tmp}" _feature_tmp_c) + foreach(_var _feature _feature_tmp _feature_tmp_l _feature_tmp_c) + set(_ver "${${${_var}}_VERSION}") + if(NOT "${_ver}" STREQUAL "") + set(_desc "${_desc} -- [found version ${_ver}]") + break() + endif() + unset(_ver) + endforeach() + set(_currentFeatureText "${_currentFeatureText}: ${_desc}") + endif() + set(_desc NOTFOUND) + endif() + endif() + endforeach() + + if(NOT "${_currentFeatureText}" STREQUAL "${_basemsg}") + message(STATUS "${_currentFeatureText}\n") + endif() +endfunction() + +# ----------------------------------------------------------------------------------------# +# function print_disabled_features() Print disabled features plus their docstrings. +# +function(ROCPROFILER_PRINT_DISABLED_FEATURES) + set(_basemsg "The following features are NOT defined/enabled (-):") + set(_currentFeatureText "${_basemsg}") + get_property(_features GLOBAL PROPERTY ${PROJECT_NAME}_FEATURES) + if(NOT "${_features}" STREQUAL "") + list(REMOVE_DUPLICATES _features) + list(SORT _features) + endif() + foreach(_feature ${_features}) + if(NOT ${_feature}) + set(_currentFeatureText "${_currentFeatureText}\n ${_feature}") + + get_property(_desc GLOBAL PROPERTY ${_feature}_DESCRIPTION) + + if(_desc) + set(_currentFeatureText "${_currentFeatureText}: ${_desc}") + set(_desc NOTFOUND) + endif(_desc) + endif() + endforeach(_feature) + + if(NOT "${_currentFeatureText}" STREQUAL "${_basemsg}") + message(STATUS "${_currentFeatureText}\n") + endif() +endfunction() + +# ----------------------------------------------------------------------------------------# +# function print_features() Print all features plus their docstrings. +# +function(ROCPROFILER_PRINT_FEATURES) + rocprofiler_report_feature_changes() + rocprofiler_print_enabled_features() + rocprofiler_print_disabled_features() +endfunction() + +# ----------------------------------------------------------------------------------------# +# this function is provided to easily select which files use alternative compiler: +# +# GLOBAL --> all files TARGET --> all files in a target SOURCE --> specific +# source files DIRECTORY --> all files in directory PROJECT --> all files/targets in +# a project/subproject +# +function(rocprofiler_custom_compilation) + cmake_parse_arguments(COMP "GLOBAL;PROJECT" "COMPILER" "DIRECTORY;TARGET;SOURCE" + ${ARGN}) + + # find rocprofiler-launch-compiler + find_program( + ROCPROFILER_COMPILE_LAUNCHER + NAMES rocprofiler-launch-compiler + HINTS ${PROJECT_SOURCE_DIR} ${CMAKE_SOURCE_DIR} + PATHS ${PROJECT_SOURCE_DIR} ${CMAKE_SOURCE_DIR} + PATH_SUFFIXES scripts bin) + + if(NOT COMP_COMPILER) + message( + FATAL_ERROR "rocprofiler_custom_compilation not provided COMPILER argument") + endif() + + if(NOT ROCPROFILER_COMPILE_LAUNCHER) + message( + FATAL_ERROR + "rocprofiler could not find 'rocprofiler-launch-compiler'. Please set '-DROCPROFILER_COMPILE_LAUNCHER=/path/to/launcher'" + ) + endif() + + if(COMP_GLOBAL) + # if global, don't bother setting others + set_property( + GLOBAL + PROPERTY + RULE_LAUNCH_COMPILE + "${ROCPROFILER_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}") + set_property( + GLOBAL + PROPERTY + RULE_LAUNCH_LINK + "${ROCPROFILER_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}") + else() + foreach(_TYPE PROJECT DIRECTORY TARGET SOURCE) + # make project/subproject scoping easy, e.g. + # rocprofiler_custom_compilation(PROJECT) after project(...) + if("${_TYPE}" STREQUAL "PROJECT" AND COMP_${_TYPE}) + list(APPEND COMP_DIRECTORY ${PROJECT_SOURCE_DIR}) + unset(COMP_${_TYPE}) + endif() + # set the properties if defined + if(COMP_${_TYPE}) + foreach(_VAL ${COMP_${_TYPE}}) + set_property( + ${_TYPE} ${_VAL} + PROPERTY + RULE_LAUNCH_COMPILE + "${ROCPROFILER_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}" + ) + set_property( + ${_TYPE} ${_VAL} + PROPERTY + RULE_LAUNCH_LINK + "${ROCPROFILER_COMPILE_LAUNCHER} ${COMP_COMPILER} ${CMAKE_CXX_COMPILER}" + ) + endforeach() + endif() + endforeach() + endif() +endfunction() + +function(ROCPROFILER_WATCH_FOR_CHANGE _var) + list(LENGTH ARGN _NUM_EXTRA_ARGS) + if(_NUM_EXTRA_ARGS EQUAL 1) + set(_VAR ${ARGN}) + else() + set(_VAR) + endif() + + macro(update_var _VAL) + if(_VAR) + set(${_VAR} + ${_VAL} + PARENT_SCOPE) + endif() + endmacro() + + update_var(OFF) + + set(_rocprofiler_watch_var_name ROCPROFILER_WATCH_VALUE_${_var}) + if(DEFINED ${_rocprofiler_watch_var_name}) + if("${${_var}}" STREQUAL "${${_rocprofiler_watch_var_name}}") + return() + else() + rocprofiler_message( + STATUS + "${_var} changed :: ${${_rocprofiler_watch_var_name}} --> ${${_var}}") + update_var(ON) + endif() + else() + if(NOT "${${_var}}" STREQUAL "") + rocprofiler_message(STATUS "${_var} :: ${${_var}}") + update_var(ON) + endif() + endif() + + # store the value for the next run + set(${_rocprofiler_watch_var_name} + "${${_var}}" + CACHE INTERNAL "Last value of ${_var}" FORCE) +endfunction() + +function(ROCPROFILER_DIRECTORY) + cmake_parse_arguments(F "MKDIR;FAIL;FORCE" "PREFIX;OUTPUT_VARIABLE;WORKING_DIRECTORY" + "PATHS" ${ARGN}) + + if(F_PREFIX AND NOT IS_ABSOLUTE "${F_PREFIX}") + if(F_WORKING_DIRECTORY) + rocprofiler_message( + STATUS + "PREFIX was specified as a relative path, using working directory + prefix :: '${F_WORKING_DIRECTORY}/${F_PREFIX}'..." + ) + set(F_PREFIX ${F_WORKING_DIRECTORY}/${F_PREFIX}) + else() + rocprofiler_message( + FATAL_ERROR + "PREFIX was specified but it is not an absolute path: ${F_PREFIX}") + endif() + endif() + + if(NOT F_WORKING_DIRECTORY) + set(F_WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) + endif() + + foreach(_PATH ${F_PREFIX} ${F_PATHS}) + if(F_PREFIX AND NOT "${_PATH}" STREQUAL "${F_PREFIX}") + # if path is relative, set to prefix + path + if(NOT IS_ABSOLUTE "${_PATH}") + set(_PATH ${F_PREFIX}/${_PATH}) + endif() + list(APPEND _OUTPUT_VAR ${_PATH}) + elseif(NOT F_PREFIX) + list(APPEND _OUTPUT_VAR ${_PATH}) + endif() + + if(NOT EXISTS "${_PATH}" AND F_FAIL) + rocprofiler_message(FATAL_ERROR "Directory '${_PATH}' does not exist") + elseif(NOT IS_DIRECTORY "${_PATH}" AND F_FAIL) + rocprofiler_message(FATAL_ERROR "'${_PATH}' exists but is not a directory") + elseif(NOT EXISTS "${_PATH}" AND F_MKDIR) + execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${_PATH} + WORKING_DIRECTORY ${F_WORKING_DIRECTORY}) + elseif( + EXISTS "${_PATH}" + AND NOT IS_DIRECTORY "${_PATH}" + AND F_MKDIR) + if(F_FORCE) + execute_process(COMMAND ${CMAKE_COMMAND} -E rm ${_PATH} + WORKING_DIRECTORY ${F_WORKING_DIRECTORY}) + endif() + execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${_PATH} + WORKING_DIRECTORY ${F_WORKING_DIRECTORY}) + endif() + endforeach() + + if(F_OUTPUT_VARIABLE) + set(${F_OUTPUT_VARIABLE} + "${_OUTPUT_VAR}" + PARENT_SCOPE) + endif() +endfunction() + +function(ROCPROFILER_CHECK_PYTHON_DIRS_AND_VERSIONS) + cmake_parse_arguments(F "FAIL;UNSET" "RESULT_VARIABLE;OUTPUT_VARIABLE" "" ${ARGN}) + + list(LENGTH ROCPROFILER_PYTHON_VERSIONS _NUM_PYTHON_VERSIONS) + list(LENGTH ROCPROFILER_PYTHON_ROOT_DIRS _NUM_PYTHON_ROOT_DIRS) + + if(NOT _NUM_PYTHON_VERSIONS EQUAL _NUM_PYTHON_ROOT_DIRS) + set(_RET 1) + else() + set(_RET 0) + if(F_OUTPUT_VARIABLE) + set(${F_OUTPUT_VARIABLE} + ${_NUM_PYTHON_VERSIONS} + PARENT_SCOPE) + endif() + endif() + + if(F_RESULT_VARIABLE) + set(${F_RESULT_VARIABLE} + ${_RET} + PARENT_SCOPE) + endif() + + if(NOT ${_RET} EQUAL 0) + if(F_FAIL) + rocprofiler_message( + WARNING + "Error! Number of python versions : ${_NUM_PYTHON_VERSIONS}. VERSIONS :: ${ROCPROFILER_PYTHON_VERSIONS}" + ) + rocprofiler_message( + WARNING + "Error! Number of python root directories : ${_NUM_PYTHON_ROOT_DIRS}. ROOT DIRS :: ${ROCPROFILER_PYTHON_ROOT_DIRS}" + ) + rocprofiler_message( + FATAL_ERROR + "Error! Number of python versions != number of python root directories") + elseif(F_UNSET) + unset(ROCPROFILER_PYTHON_VERSIONS CACHE) + unset(ROCPROFILER_PYTHON_ROOT_DIRS CACHE) + if(F_OUTPUT_VARIABLE) + set(${F_OUTPUT_VARIABLE} 0) + endif() + endif() + endif() +endfunction() + +# ---------------------------------------------------------------------------- +# Console scripts +# +function(ROCPROFILER_PYTHON_CONSOLE_SCRIPT SCRIPT_NAME SCRIPT_SUBMODULE) + set(options) + set(args VERSION ROOT_DIR) + set(kwargs) + cmake_parse_arguments(ARG "${options}" "${args}" "${kwargs}" ${ARGN}) + + if(ARG_VERSION AND ARG_ROOT_DIR) + set(Python3_ROOT_DIR "${ARG_ROOT_DIR}") + find_package(Python3 ${ARG_VERSION} EXACT QUIET MODULE COMPONENTS Interpreter) + set(PYTHON_EXECUTABLE "${Python3_EXECUTABLE}") + configure_file(${PROJECT_SOURCE_DIR}/cmake/Templates/console-script.in + ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME}-${ARG_VERSION} @ONLY) + + if(CMAKE_INSTALL_PYTHONDIR) + install( + PROGRAMS ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME}-${ARG_VERSION} + DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT python + OPTIONAL) + endif() + + if(ROCPROFILER_BUILD_TESTING OR ROCPROFILER_BUILD_PYTHON) + add_test( + NAME ${SCRIPT_NAME}-console-script-test-${ARG_VERSION} + COMMAND ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME}-${ARG_VERSION} --help + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) + set_tests_properties( + ${SCRIPT_NAME}-console-script-test-${ARG_VERSION} + PROPERTIES LABELS "python;python-${ARG_VERSION};console-script") + add_test( + NAME ${SCRIPT_NAME}-generic-console-script-test-${ARG_VERSION} + COMMAND ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME} --help + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) + set_tests_properties( + ${SCRIPT_NAME}-generic-console-script-test-${ARG_VERSION} + PROPERTIES ENVIRONMENT "PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}" LABELS + "python;python-${ARG_VERSION};console-script") + endif() + else() + set(PYTHON_EXECUTABLE "python3") + + configure_file(${PROJECT_SOURCE_DIR}/cmake/Templates/console-script.in + ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME} @ONLY) + + if(CMAKE_INSTALL_PYTHONDIR) + install( + PROGRAMS ${PROJECT_BINARY_DIR}/bin/${SCRIPT_NAME} + DESTINATION ${CMAKE_INSTALL_BINDIR} + COMPONENT python + OPTIONAL) + endif() + endif() +endfunction() + +function(ROCPROFILER_FIND_STATIC_LIBRARY) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX}) + find_library(${ARGN}) +endfunction() + +function(ROCPROFILER_FIND_SHARED_LIBRARY) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX}) + find_library(${ARGN}) +endfunction() + +function(ROCPROFILER_BUILDTREE_TPL _TPL_TARGET _NEW_NAME _BUILD_TREE_DIR) + get_target_property(_TPL_VERSION ${_TPL_TARGET} VERSION) + get_target_property(_TPL_SOVERSION ${_TPL_TARGET} SOVERSION) + get_target_property(_TPL_NAME ${_TPL_TARGET} OUTPUT_NAME) + set(_TPL_PREFIX ${CMAKE_SHARED_LIBRARY_PREFIX}) + set(_TPL_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}) + + foreach(_TAIL ${_TPL_SUFFIX} ${_TPL_SUFFIX}.${_TPL_SOVERSION} + ${_TPL_SUFFIX}.${_TPL_VERSION}) + set(_INP ${_TPL_PREFIX}${_TPL_NAME}${_TAIL}) + set(_OUT ${_TPL_PREFIX}${_NEW_NAME}${_TAIL}) + endforeach() + + string(REPLACE " " "-" _TAIL "${ARGN}") + + # build tree symbolic links + add_custom_target( + ${_NEW_NAME}-build-tree-library${_TAIL} ALL + ${CMAKE_COMMAND} -E create_symlink $ + ${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION} + COMMAND + ${CMAKE_COMMAND} -E create_symlink + ${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION} + ${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION} + COMMAND + ${CMAKE_COMMAND} -E create_symlink + ${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION} + ${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX} + WORKING_DIRECTORY ${_BUILD_TREE_DIR} + DEPENDS ${_TPL_TARGET} + COMMENT "Creating ${_NEW_NAME} from ${_TPL_TARGET}...") +endfunction() + +function(ROCPROFILER_INSTALL_TPL _TPL_TARGET _NEW_NAME _BUILD_TREE_DIR _COMPONENT) + get_target_property(_TPL_VERSION ${_TPL_TARGET} VERSION) + get_target_property(_TPL_SOVERSION ${_TPL_TARGET} SOVERSION) + get_target_property(_TPL_NAME ${_TPL_TARGET} OUTPUT_NAME) + set(_TPL_PREFIX ${CMAKE_SHARED_LIBRARY_PREFIX}) + set(_TPL_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}) + + foreach(_TAIL ${_TPL_SUFFIX} ${_TPL_SUFFIX}.${_TPL_SOVERSION} + ${_TPL_SUFFIX}.${_TPL_VERSION}) + set(_INP ${_TPL_PREFIX}${_TPL_NAME}${_TAIL}) + set(_OUT ${_TPL_PREFIX}${_NEW_NAME}${_TAIL}) + endforeach() + + # build tree symbolic links + rocprofiler_buildtree_tpl("${_TPL_TARGET}" "${_NEW_NAME}" "${_BUILD_TREE_DIR}" + ${ARGN}) + + install( + FILES $ + DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT ${_COMPONENT} + RENAME ${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_VERSION}) + + install( + FILES + ${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX}.${_TPL_SOVERSION} + ${_BUILD_TREE_DIR}/${_TPL_PREFIX}${_NEW_NAME}${_TPL_SUFFIX} + DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT ${_COMPONENT}) + +endfunction() + +function(COMPUTE_POW2_CEIL _OUTPUT _VALUE) + find_package(Python3 COMPONENTS Interpreter) + + if(Python3_FOUND) + execute_process( + COMMAND + ${Python3_EXECUTABLE} -c + "VALUE = ${_VALUE}; ispow2 = lambda x: x if (x and (not(x & (x - 1)))) else None; v = list(filter(ispow2, [x for x in range(VALUE, VALUE**2)])); print(v[0])" + RESULT_VARIABLE _POW2_RET + OUTPUT_VARIABLE _POW2_OUT + ERROR_VARIABLE _POW2_ERR + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if(_POW2_RET EQUAL 0) + set(${_OUTPUT} + ${_POW2_OUT} + PARENT_SCOPE) + else() + set(${_OUTPUT} + "-1" + PARENT_SCOPE) + endif() + else() + set(${_OUTPUT} + "-1" + PARENT_SCOPE) + endif() + +endfunction() + +cmake_policy(POP) diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt new file mode 100644 index 0000000000..558b521d88 --- /dev/null +++ b/external/CMakeLists.txt @@ -0,0 +1,29 @@ +# +# +# External dependencies +# +# + +if(ROCPROFILER_BUILD_TESTS) + set(INSTALL_GTEST + OFF + CACHE BOOL "") + set(BUILD_GMOCK + OFF + CACHE BOOL "") + + add_subdirectory(googletest EXCLUDE_FROM_ALL) + + if(NOT TARGET GTest::gtest) + message(FATAL_ERROR "missing GTest::gtest") + endif() + + target_link_libraries(rocprofiler-googletest INTERFACE GTest::gtest) + target_include_directories( + rocprofiler-googletest SYSTEM + INTERFACE ${CMAKE_CURRENT_LSIT_DIR}/googletest/googletest/include) + + mark_as_advanced(INSTALL_GTEST) + mark_as_advanced(BUILD_GMOCK) + mark_as_advanced(GTEST_HAS_ABSL) +endif() diff --git a/external/googletest b/external/googletest new file mode 160000 index 0000000000..46db91ef6f --- /dev/null +++ b/external/googletest @@ -0,0 +1 @@ +Subproject commit 46db91ef6ffcc128b2d5f31118ae1108109e3400 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000..585d9d4c24 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,25 @@ + +[tool.black] +line-length = 90 +target-version = ['py36', 'py37', 'py38', 'py39', 'py310'] +include = '\.py$' +exclude = ''' +( + /( + \.eggs + | \.git + | \.github + | \.tox + | \.venv + | \.misc + | \.vscode + | \.cache + | \.pytest_cache + | dist + | external + | build + | build-release + | build-rocprofiler + )/ +) +''' diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000..69a7c594bb --- /dev/null +++ b/requirements.txt @@ -0,0 +1,10 @@ +barectf +bcrypt +CppHeaderParser +lxml +matplotlib +pandas +protobuf +pycparser +pyparsing +websockets \ No newline at end of file diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/samples/CMakeLists.txt @@ -0,0 +1 @@ + diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt new file mode 100644 index 0000000000..f73baf5816 --- /dev/null +++ b/source/CMakeLists.txt @@ -0,0 +1,6 @@ +# +# +# +add_subdirectory(include) +add_subdirectory(lib) +add_subdirectory(bin) diff --git a/source/bin/CMakeLists.txt b/source/bin/CMakeLists.txt new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/source/bin/CMakeLists.txt @@ -0,0 +1 @@ + diff --git a/source/bin/tests/CMakeLists.txt b/source/bin/tests/CMakeLists.txt new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/source/bin/tests/CMakeLists.txt @@ -0,0 +1 @@ + diff --git a/source/include/CMakeLists.txt b/source/include/CMakeLists.txt new file mode 100644 index 0000000000..95af2250ea --- /dev/null +++ b/source/include/CMakeLists.txt @@ -0,0 +1,4 @@ +# +# +# +add_subdirectory(rocprofiler) diff --git a/source/include/rocprofiler/CMakeLists.txt b/source/include/rocprofiler/CMakeLists.txt new file mode 100644 index 0000000000..ce489644af --- /dev/null +++ b/source/include/rocprofiler/CMakeLists.txt @@ -0,0 +1,8 @@ +# +# +# Installation of public headers +# +# +set(ROCPROFILER_INCLUDE_FILES config.h rocprofiler.h rocprofiler_plugin.h) +install(FILES ${ROCPROFILER_INCLUDE_FILES} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rocprofiler) diff --git a/source/include/rocprofiler/config.h b/source/include/rocprofiler/config.h new file mode 100644 index 0000000000..2cd260c85d --- /dev/null +++ b/source/include/rocprofiler/config.h @@ -0,0 +1,189 @@ + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define ROCPROFILER_API_VERSION_ID 1 +#define ROCPROFILER_DOMAIN_OPS_MAX 512 +#define ROCPROFILER_DOMAIN_OPS_RESERVED ((ROCPROFILER_DOMAIN_OPS_MAX * ACTIVITY_DOMAIN_NUMBER / 8)) + +typedef uint64_t (*rocprofiler_external_cid_cb_t)(rocprofiler_tracer_activity_domain_t, + uint32_t, + uint64_t); +typedef int (*rocprofiler_filter_name_t)(const char*); +typedef int (*rocprofiler_filter_op_id_t)(uint32_t); +typedef int (*rocprofiler_filter_range_t)(uint32_t, uint32_t); +typedef int (*rocprofiler_filter_dispatch_id_t)(uint64_t); + +/// permits tools opportunity to modify the correlation id based on the domain, op, and +/// the rocprofiler generated correlation id +struct rocprofiler_correlation_config +{ + rocprofiler_external_cid_cb_t external_id_callback; +}; + +/// how the tools specify the tracing domain and (optionally) which operations in the +/// domain they want to trace +struct rocprofiler_domain_config +{ + rocprofiler_sync_callback_t callback; + char reserved0[sizeof(uint64_t)]; + char reserved1[ROCPROFILER_DOMAIN_OPS_RESERVED]; +}; + +/// for buffered callbacks, the tool provides a callback to create a buffer and the size +struct rocprofiler_buffer_config +{ + rocprofiler_buffer_callback_t callback; + uint64_t buffer_size; + // void* reserved0; + char reserved1[sizeof(uint64_t)]; +}; + +/// filters are available to make quick decisions about whether rocprofiler should +/// assemble the data necessary for a callback. This is more for convenience and +/// performance -- anything decisions here could be made in the callback but rocprofiler +/// has to first assemble all the infomation on the callback before it (eventually) gets +/// discarded because the tool has decided it (after configuration), that it no longer +/// wants info meeting certain requirements +struct rocprofiler_filter_config +{ + // filter callbacks + rocprofiler_filter_name_t name; + rocprofiler_filter_op_id_t hip_function_id; + rocprofiler_filter_op_id_t hsa_function_id; + rocprofiler_filter_range_t range; + rocprofiler_filter_dispatch_id_t dispatch_id; + + // reserved padding + char padding[24 * sizeof(void*)]; +}; + +/// this is the "single source of truth" for the capabilities of rocprofiler. +/// you can one configuration that activates all the capabilities you want +/// and holistically start/stop the sum of those features. Alternatively, +/// you can have multiple configurations in order to activate certain features +/// modularly. +/// +/// The general workflow is: +/// +/// 1. invoke rocprofiler_allocate_config(...) +/// - rocprofiler allocates any space internally needed for the config +/// - rocprofiler sets a few initial values: +/// - "size" to the size of the config structure used internally +/// - "api_version" to the version id of the API in the rocprofiler library that +/// is being used. +/// - these two values can be used by the tool to identify any potential +/// incompatibilities that the tool might want to know about +/// - rocprofiler checks whether it is too late to configure the tool, e.g. +/// something went wrong and rocprofiler was not able to set itself up as +/// the intercepter +/// 2. tool sets up the configuration struct and sets the "size" variable to the size of +/// their configuration struct and sets the "compat_version" field to the +/// ROCPROFILER_API_VERSION_ID defined by the rocprofiler headers when the tool was +/// built +/// - in other words, the user can communicate to rocprofiler, don't read +/// past this distance in my configuration struct and I built against X version +/// so assume the default behavior and capabilties of version X. +/// 3. tool passes this struct to rocprofiler_validate_config(...) +/// - this step checks the config in isolation and will communicate any potential +/// warnings/issues with that configuration, e.g. rocprofiler_X_config is needed, +/// to HW counters XYZ are not available, etc. The tool then has an opportunity +/// to address these issues however they see fit. +/// 4. tool passes this struct to rocprofiler_start_config(...) +/// - internally, we make a call to rocprofiler_validate_config(...) and if any +/// issues still exist with the config in isolation, rocprofiler tells the app +/// to abort -- mechanisms were provided to prevent aborting prior to this call, +/// aborting the app at this point is to guard against rocprofiler "silently" +/// not working because error codes were ignored +/// - rocprofiler then checks whether this config can actually be activated +/// alongside any other active configuration, e.g. this config wants 4 HW counters +/// and another wants 4 HW counters but we can only activate 6 out of 8 of +/// them in this run. Any issues here will not abort execution but, instead, +/// the features of this configuration will not happen (i.e. config won't be +/// activated) and the issues will be communicated with error codes -- giving +/// the tool the opportunity to address the conflicts (i.e. only request tracing +/// and no HW counters) before attempting to activate the modified config. +/// - once rocprofiler determines all features of a config can be activated, it +/// makes an internal copy of the config and returns an identifier for that +/// configuration. The tool is then free to delete the config and any modification +/// to the config will NOT be reflected in the behavior of rocprofiler. +/// +/// +struct rocprofiler_config +{ + // size is used to ensure that we never read past the end of the version + size_t size; // = sizeof(rocprofiler_config) + uint32_t compat_version; // set by user + uint32_t api_version; // set by rocprofiler + uint64_t reserved0; // internal field + void* user_data; // data passed to callbacks + struct rocprofiler_correlation_config* correlation_id; // = &my_cid_config (optional) + struct rocprofiler_buffer_config* buffer; // = &my_buffer_config (required) + struct rocprofiler_domain_config* domain; // = &my_domain_config (required) + struct rocprofiler_filter_config* filter; // = &my_filter_config (optional) +}; + +/// \brief returns a properly initialized config struct and allocates any data structures +/// necessary for the config to be used +/// +/// \param [out] cfg may adjust config or assign values within structs. +rocprofiler_status_t +rocprofiler_allocate_config(struct rocprofiler_config* cfg); + +/// \brief rocprofiler validates config, checks for conflicts, etc. Ensures that +/// the configuration is valid *in isolation*, e.g. it may check that the user +/// set the compat_version field and that required config fields, such as buffer +/// are set. This function will be called before \ref rocprofiler_start_config +/// but is provided to help the user validate one or more configs without starting +/// them +/// +/// \param [in] cfg configuration to validate +rocprofiler_status_t +rocprofiler_validate_config(const struct rocprofiler_config* cfg); + +/// \brief rocprofiler activates configuration and provides a session identifier +/// \param [in] cfg may adjust config or assign values within structs. If error +/// occurs, could nullptr valid sub-configs and leave the pointers to +/// invalid configs +/// \param [out] id the session identifier for this config. +rocprofiler_status_t +rocprofiler_start_config(struct rocprofiler_config*, rocprofiler_session_id_t* id); + +/// \brief disable the configuration. +rocprofiler_status_t rocprofiler_stop_config(rocprofiler_session_id_t); + +/// +/// +/// the following 4 functions may be changed to permit removing domain/ops and/or +/// identifying domains and operations via strings +/// +/// +rocprofiler_status_t +rocprofiler_domain_set_domain(struct rocprofiler_domain_config*, + rocprofiler_tracer_activity_domain_t); + +rocprofiler_status_t +rocprofiler_domain_add_domains(struct rocprofiler_domain_config*, + rocprofiler_tracer_activity_domain_t*, + size_t); + +rocprofiler_status_t +rocprofiler_domain_add_op(struct rocprofiler_domain_config*, + rocprofiler_tracer_activity_domain_t, + uint32_t); + +rocprofiler_status_t +rocprofiler_domain_add_ops(struct rocprofiler_domain_config*, + rocprofiler_tracer_activity_domain_t, + uint32_t*, + size_t); + +#ifdef __cplusplus +} +#endif diff --git a/source/include/rocprofiler/rocprofiler.h b/source/include/rocprofiler/rocprofiler.h new file mode 100644 index 0000000000..6b02e031e6 --- /dev/null +++ b/source/include/rocprofiler/rocprofiler.h @@ -0,0 +1,2340 @@ +/****************************************************************************** +Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +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 +AUTHORS 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 IN +THE SOFTWARE. +*******************************************************************************/ + +//////////////////////////////////////////////////////////////////////////////// +// +// ROC Profiler API +// +// The goal of the implementation is to provide a HW specific low-level +// performance analysis interface for profiling of GPU compute applications. +// The profiling includes HW performance counters (PMC) with complex +// performance metrics and traces. +// +// The library can be used by a tool library loaded by HSA runtime or by +// higher level HW independent performance analysis API like PAPI. +// +// The library is written on C and will be based on AQLprofile AMD specific +// HSA extension. The library implementation requires HSA API intercepting and +// a profiling queue supporting a submit callback interface. +// +// +/** \mainpage ROCProfiler API Specification + * + * \section introduction Introduction + * + * The ROCProfiler library provides GPU Applications Profiling/Tracing APIs. + * The API offers functionality for profiling GPU applications in kernel, + * application and user mode. It also supports no replay mode and provides + * the records pool support through a simple sequence of calls. This enables + * users to profile and trace in easy small steps. Our samples code provides + * good examples on how to use the API calls for both profiling and + * tracing. + * + * \section supported_amd_gpu_architectures Supported AMD GPU Architectures + * + * The following AMD GPU architectures are supported: + * + * - gfx900 (AMD Vega 10) + * - gfx906 (AMD Vega 7nm also referred to as AMD Vega 20) + * - gfx908 (AMD Instinct™ MI100 accelerator) + * - gfx90a (Aldebaran) + * - gfx940 (AMD Instinct™ MI300) + * - gfx1010 (Navi10) + * - gfx1011 (Navi12) + * - gfx1012 (Navi14) + * - gfx1030 (Sienna Cichlid) + * - gfx1031 (Navy Flounder) + * - gfx1032 (Dimgrey Cavefish) + * - gfx1100 (Navi31) + * For more information about the AMD ROCm ecosystem, please refer to: + * + * - https://docs.amd.com/ + * +* + * \section known_limitations Known Limitations and Restrictions + * + * The AMD Profiler API library implementation currently has the following + * restrictions. Future releases aim to address these restrictions. + * + * 1. The following profiling modes are not yet implemented: + * + * - ::ROCPROFILER_APPLICATION_REPLAY_MODE + * - ::ROCPROFILER_USER_REPLAY_MODE + * + * 2. While setting filters, properties can mix up and may produce + * undesirable results. + * + * \section references References + * + * 1. Advanced Micro Devices: [www.amd.com] (https://www.amd.com/) + * 2. AMD ROCm Ecosystem: [docs.amd.com] (https://docs.amd.com/) + * + * \section disclaimer Legal Disclaimer and Copyright Information + * + * AMD ROCm software is made available by Advanced Micro Devices, Inc. under + * the open source license identified in the top-level directory for the + * library in the repository on [Github.com](https://github.com/) (Portions of + * AMD ROCm software are licensed under MITx11 and UIL/NCSA. For more + * information on the license, review the \p license.txt in the top-level + * directory for the library on [Github.com](https://github.com/)). The + * additional terms and conditions below apply to your use of AMD ROCm + * technical documentation. + * + * ©2019-2023 Advanced Micro Devices, Inc. All rights reserved. + * + * The information presented in this document is for informational purposes + * only and may contain technical inaccuracies, omissions, and typographical + * errors. The information contained herein is subject to change and may be + * rendered inaccurate for many reasons, including but not limited to product + * and roadmap changes, component and motherboard version changes, new model + * and/or product releases, product differences between differing + * manufacturers, software changes, BIOS flashes, firmware upgrades, or the + * like. Any computer system has risks of security vulnerabilities that cannot + * be completely prevented or mitigated. AMD assumes no obligation to update + * or otherwise correct or revise this information. However, AMD reserves the + * right to revise this information and to make changes from time to time to + * the content hereof without obligation of AMD to notify any person of such + * revisions or changes. + * + * THIS INFORMATION IS PROVIDED "AS IS." AMD MAKES NO REPRESENTATIONS OR + * WARRANTIES WITH RESPECT TO THE CONTENTS HEREOF AND ASSUMES NO RESPONSIBILITY + * FOR ANY INACCURACIES, ERRORS, OR OMISSIONS THAT MAY APPEAR IN THIS + * INFORMATION. AMD SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF + * NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR ANY PARTICULAR PURPOSE. + * IN NO EVENT WILL AMD BE LIABLE TO ANY PERSON FOR ANY RELIANCE, DIRECT, + * INDIRECT, SPECIAL, OR OTHER CONSEQUENTIAL DAMAGES ARISING FROM THE USE OF + * ANY INFORMATION CONTAINED HEREIN, EVEN IF AMD IS EXPRESSLY ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + * + * AMD, the AMD Arrow logo, AMD Instinct™, Radeon™, AMD ROCm™, and combinations + * thereof are trademarks of Advanced Micro Devices, Inc. Linux® is the + * registered trademark of Linus Torvalds in the U.S. and other countries. + * PCIe® is a registered trademark of PCI-SIG Corporation. Other product names + * used in this publication are for identification purposes only and may be + * trademarks of their respective companies. + * + + * This document is going to discuss the following: + * 1. @ref symbol_versions_group + * 2. @ref versioning_group + * 3. @ref status_codes_group + * 4. @ref rocprofiler_general_group + * 5. @ref timestamp_group + * 6. @ref generic_record_group + * - @ref record_agents_group + * - @ref record_queues_group + * - @ref record_kernels_group + * 7. @ref profiling_api_group + * - @ref profiling_api_counters_group + * 8. @ref tracing_api_group + * - @ref roctx_tracer_api_data_group + * - @ref hsa_tracer_api_data_group + * - @ref hip_tracer_api_data_group + * 9. @ref memory_storage_buffer_group + * 10. @ref sessions_handling_group + * - @ref session_filter_group + * - @ref session_range_group + * - @ref session_user_replay_pass_group + * 11. @ref device_profiling + * 12. @ref rocprofiler_plugins + */ +// +/** + * \file + * ROCPROFILER API interface. + */ +//////////////////////////////////////////////////////////////////////////////// + +#ifndef INC_ROCPROFILER_H_ +#define INC_ROCPROFILER_H_ + +/* Placeholder for calling convention and import/export macros */ +#if !defined(ROCPROFILER_CALL) +# define ROCPROFILER_CALL +#endif /* !defined (ROCPROFILER_CALL) */ + +#if !defined(ROCPROFILER_EXPORT_DECORATOR) +# if defined(__GNUC__) +# define ROCPROFILER_EXPORT_DECORATOR __attribute__((visibility("default"))) +# elif defined(_MSC_VER) +# define ROCPROFILER_EXPORT_DECORATOR __declspec(dllexport) +# endif /* defined (_MSC_VER) */ +#endif /* !defined (ROCPROFILER_EXPORT_DECORATOR) */ + +#if !defined(ROCPROFILER_IMPORT_DECORATOR) +# if defined(__GNUC__) +# define ROCPROFILER_IMPORT_DECORATOR +# elif defined(_MSC_VER) +# define ROCPROFILER_IMPORT_DECORATOR __declspec(dllimport) +# endif /* defined (_MSC_VER) */ +#endif /* !defined (ROCPROFILER_IMPORT_DECORATOR) */ + +#define ROCPROFILER_EXPORT ROCPROFILER_EXPORT_DECORATOR ROCPROFILER_CALL +#define ROCPROFILER_IMPORT ROCPROFILER_IMPORT_DECORATOR ROCPROFILER_CALL + +#if !defined(ROCPROFILER) +# if defined(ROCPROFILER_EXPORTS) +# define ROCPROFILER_API ROCPROFILER_EXPORT +# else /* !defined (ROCPROFILER_EXPORTS) */ +# define ROCPROFILER_API ROCPROFILER_IMPORT +# endif /* !defined (ROCPROFILER_EXPORTS) */ +#endif /* !defined (ROCPROFILER) */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** \defgroup symbol_versions_group Symbol Versions + * + * The names used for the shared library versioned symbols. + * + * Every function is annotated with one of the version macros defined in this + * section. Each macro specifies a corresponding symbol version string. After + * dynamically loading the shared library with \p dlopen, the address of each + * function can be obtained using \p dlsym with the name of the function and + * its corresponding symbol version string. An error will be reported by \p + * dlvsym if the installed library does not support the version for the + * function specified in this version of the interface. + * + * @{ + */ + +/** + * The function was introduced in version 9.0 of the interface and has the + * symbol version string of ``"ROCPROFILER_9.0"``. + */ +#define ROCPROFILER_VERSION_9_0 + +/** @} */ + +/** \defgroup versioning_group Library Versioning + * + * Version information about the interface and the associated installed + * library. + * + * The semantic version of the interface following rules. A client + * that uses this interface is only compatible with the installed library if + * the major version numbers match and the interface minor version number is + * less than or equal to the installed library minor version number. + * + * @{ + */ + +/** + * The major version of the interface as a macro so it can be used by the + * preprocessor. + */ +#define ROCPROFILER_VERSION_MAJOR 9 + +/** + * The minor version of the interface as a macro so it can be used by the + * preprocessor. + */ +#define ROCPROFILER_VERSION_MINOR 0 + +/** + * Query the major version of the installed library. + * + * Return the major version of the installed library. This can be used to + * check if it is compatible with this interface version. This function can be + * used even when the library is not initialized. + */ +ROCPROFILER_API uint32_t +rocprofiler_version_major(); + +/** + * Query the minor version of the installed library. + * + * Return the minor version of the installed library. This can be used to + * check if it is compatible with this interface version. This function can be + * used even when the library is not initialized. + */ +ROCPROFILER_API uint32_t +rocprofiler_version_minor(); + +/** @} */ + +// TODO(aelwazir): Fix them to use the new Error codes +/** \defgroup status_codes_group Status Codes + * + * Most operations return a status code to indicate success or error. + * + * @{ + */ + +/** + * ROCProfiler API status codes. + */ +typedef enum +{ + /** + * The function has executed successfully. + */ + ROCPROFILER_STATUS_SUCCESS = 0, + /** + * A generic error has occurred. + */ + ROCPROFILER_STATUS_ERROR = -1, + /** + * ROCProfiler is already initialized. + */ + ROCPROFILER_STATUS_ERROR_ALREADY_INITIALIZED = -2, + /** + * ROCProfiler is not initialized. + */ + ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED = -3, + /** + * Missing Buffer for a session. + */ + ROCPROFILER_STATUS_ERROR_SESSION_MISSING_BUFFER = -4, + /** + * Timestamps can't be collected + */ + ROCPROFILER_STATUS_ERROR_TIMESTAMP_NOT_APPLICABLE = -5, + /** + * Agent is not found with given identifier. + */ + ROCPROFILER_STATUS_ERROR_AGENT_NOT_FOUND = -6, + /** + * Agent information is missing for the given identifier + */ + ROCPROFILER_STATUS_ERROR_AGENT_INFORMATION_MISSING = -7, + /** + * Queue is not found for the given identifier. + */ + ROCPROFILER_STATUS_ERROR_QUEUE_NOT_FOUND = -8, + /** + * The requested information about the queue is not found. + */ + ROCPROFILER_STATUS_ERROR_QUEUE_INFORMATION_MISSING = -9, + /** + * Kernel is not found with given identifier. + */ + ROCPROFILER_STATUS_ERROR_KERNEL_NOT_FOUND = -10, + /** + * The requested information about the kernel is not found. + */ + ROCPROFILER_STATUS_ERROR_KERNEL_INFORMATION_MISSING = -11, + /** + * Counter is not found with the given identifier. + */ + ROCPROFILER_STATUS_ERROR_COUNTER_NOT_FOUND = -12, + /** + * The requested Counter information for the given kernel is missing. + */ + ROCPROFILER_STATUS_ERROR_COUNTER_INFORMATION_MISSING = -13, + /** + * The requested Tracing API Data for the given data identifier is missing. + */ + ROCPROFILER_STATUS_ERROR_TRACER_API_DATA_NOT_FOUND = -14, + /** + * The requested information for the tracing API Data is missing. + */ + ROCPROFILER_STATUS_ERROR_TRACER_API_DATA_INFORMATION_MISSING = -15, + /** + * The given Domain is incorrect. + */ + ROCPROFILER_STATUS_ERROR_INCORRECT_DOMAIN = -16, + /** + * The requested Session given the session identifier is not found. + */ + ROCPROFILER_STATUS_ERROR_SESSION_NOT_FOUND = -17, + /** + * The requested Session Buffer given the session identifier is corrupted or + * deleted. + */ + ROCPROFILER_STATUS_ERROR_CORRUPTED_SESSION_BUFFER = -18, + /** + * The requested record given the record identifier is corrupted or deleted. + */ + ROCPROFILER_STATUS_ERROR_RECORD_CORRUPTED = -19, + /** + * Incorrect Replay mode. + */ + ROCPROFILER_STATUS_ERROR_INCORRECT_REPLAY_MODE = -20, + /** + * Missing Filter for a session. + */ + ROCPROFILER_STATUS_ERROR_SESSION_MISSING_FILTER = -21, + /** + * The size given for the buffer is not applicable. + */ + ROCPROFILER_STATUS_ERROR_INCORRECT_SIZE = -22, + /** + * Incorrect Flush interval. + */ + ROCPROFILER_STATUS_ERROR_INCORRECT_FLUSH_INTERVAL = -23, + /** + * The session filter can't accept the given data. + */ + ROCPROFILER_STATUS_ERROR_SESSION_FILTER_DATA_MISMATCH = -24, + /** + * The given filter data is corrupted. + */ + ROCPROFILER_STATUS_ERROR_FILTER_DATA_CORRUPTED = -25, + /** + * The given label is corrupted. + */ + ROCPROFILER_STATUS_ERROR_CORRUPTED_LABEL_DATA = -26, + /** + * There is no label in the labels stack to be popped. + */ + ROCPROFILER_STATUS_ERROR_RANGE_STACK_IS_EMPTY = -27, + /** + * There is no pass that started. + */ + ROCPROFILER_STATUS_ERROR_PASS_NOT_STARTED = -28, + /** + * There is already Active session, Can't activate two session at the same + * time + */ + ROCPROFILER_STATUS_ERROR_HAS_ACTIVE_SESSION = -29, + /** + * Can't terminate a non active session + */ + ROCPROFILER_STATUS_ERROR_SESSION_NOT_ACTIVE = -30, + /** + * The required filter is not found for the given session + */ + ROCPROFILER_STATUS_ERROR_FILTER_NOT_FOUND = -31, + /** + * The required buffer is not found for the given session + */ + ROCPROFILER_STATUS_ERROR_BUFFER_NOT_FOUND = -32, + /** + * The required Filter is not supported + */ + ROCPROFILER_STATUS_ERROR_FILTER_NOT_SUPPORTED = -33, + /** + * Invalid Arguments were given to the function + */ + ROCPROFILER_STATUS_ERROR_INVALID_ARGUMENTS = -34, + /** + * The given operation id is not valid. + */ + ROCPROFILER_STATUS_ERROR_INVALID_OPERATION_ID = -35, + /** + * The given domain id is not valid. + */ + ROCPROFILER_STATUS_ERROR_INVALID_DOMAIN_ID = -36, + /** + * The feature requested is not implemented. + */ + ROCPROFILER_STATUS_ERROR_NOT_IMPLEMENTED = -37, + /** + * External Correlation id pop called without matching push. + */ + ROCPROFILER_STATUS_ERROR_MISMATCHED_EXTERNAL_CORRELATION_ID = -38, +} rocprofiler_status_t; + +/** + * Query the textual description of the given error for the current thread. + * + * Returns a NULL terminated string describing the error of the given ROCProfiler + * API call by the calling thread that did not return success. + * + * \retval Return the error string. + */ +ROCPROFILER_API const char* +rocprofiler_error_str(rocprofiler_status_t status) ROCPROFILER_VERSION_9_0; + +/** @} */ + +/** \defgroup rocprofiler_general_group General ROCProfiler Requirements + * @{ + */ + +// TODO(aelwazir): More clear description, (think about nested!!??) + +/** + * Initialize the API Tools + * + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + * \retval ::ROCPROFILER_STATUS_ERROR_API_ALREADY_INITIALIZED If initialize + * wasn't called or finalized called twice + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_initialize() ROCPROFILER_VERSION_9_0; + +/** + * Finalize the API Tools + * + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + * \retval ::ROCPROFILER_STATUS_ERROR_API_NOT_INITIALIZED If initialize wasn't + * called or finalized called twice + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_finalize() ROCPROFILER_VERSION_9_0; + +/** + * \addtogroup sessions_handling_group + * @{ + * ROCProfiler Session Modes. + */ + +/** + * Session Identifier + */ +typedef struct +{ + /** + * Session Identifier to get the session or to be used to call any API that + * needs to deal with a specific session + */ + uint64_t handle; +} rocprofiler_session_id_t; + +/** @} */ + +/** @} */ + +/** \defgroup timestamp_group Timestamp Operations + * + * For this group we are focusing on timestamps collection and timestamp + * definition + * + * @{ + */ + +/** + * ROCProfiling Timestamp Type. + */ +typedef struct +{ + uint64_t value; +} rocprofiler_timestamp_t; + +/** + * Get the system clock timestamp. + * + * \param[out] timestamp The system clock timestamp in nano seconds. + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + * \retval ::ROCPROFILER_STATUS_ERROR_TIMESTAMP_NOT_APPLICABLE
+ * The function failed to get the timestamp using HSA Function. + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_get_timestamp(rocprofiler_timestamp_t* timestamp) ROCPROFILER_VERSION_9_0; + +/** + * Timestamps (start & end), it will be used for kernel dispatch tracing as + * well as API Tracing + */ +typedef struct +{ + rocprofiler_timestamp_t begin; + rocprofiler_timestamp_t end; +} rocprofiler_record_header_timestamp_t; + +/** @} */ + +/** \defgroup generic_record_group General Records Type + * @{ + */ + +/** + * A unique identifier for every record + */ +typedef struct +{ + /** + * Record ID handle + */ + uint64_t handle; +} rocprofiler_record_id_t; + +/** + * Record kind + */ +typedef enum +{ + /** + * Represents records that have profiling data (ex. counter collection + * records) + */ + ROCPROFILER_PROFILER_RECORD = 0, + /** + * Represents records that have tracing data (ex. hip api tracing records) + */ + ROCPROFILER_TRACER_RECORD = 1, + /** + * Represents a ATT tracing record (Not available yet) + */ + ROCPROFILER_ATT_TRACER_RECORD = 2, + /** + * Represents a PC sampling record + */ + ROCPROFILER_PC_SAMPLING_RECORD = 3, + /** + * Represents SPM records + */ + ROCPROFILER_SPM_RECORD = 4, + /** + * Represents Counters sampler records + */ + ROCPROFILER_COUNTERS_SAMPLER_RECORD = 5 +} rocprofiler_record_kind_t; + +/** + * Generic ROCProfiler record header. + */ +typedef struct +{ + /** + * Represents the kind of the record using ::rocprofiler_record_kind_t + */ + rocprofiler_record_kind_t kind; + /** + * Represents the id of the record + */ + rocprofiler_record_id_t id; +} rocprofiler_record_header_t; + +/** \defgroup record_agents_group Agents(AMD CPU/GPU) Handling + * \ingroup generic_record_group + * @{ + */ + +/** + * Agent ID handle, which represents a unique id to the agent reported as it + * can be used to retrieve Agent information using + * ::rocprofiler_query_agent_info, Agents can be CPUs or GPUs + */ +typedef struct +{ + /** + * a unique id to represent every agent on the system, this handle should be + * unique across all nodes in multi-node system + */ + uint64_t handle; // Topology folder serial number +} rocprofiler_agent_id_t; + +/** + * Using ::rocprofiler_query_agent_info, user can determine the type of the agent + * the following struct will be the output in case of retrieving + * ::ROCPROFILER_AGENT_TYPE agent info + */ +typedef enum +{ + /** + * CPU Agent + */ + ROCPROFILER_CPU_AGENT = 0, + /** + * GPU Agent + */ + ROCPROFILER_GPU_AGENT = 1 +} rocprofiler_agent_type_t; + +// TODO(aelwazir): check if we need to report the family name as well!!?? OR +// return the agent itself so that they can use HSA API +/** + * Types of information that can be requested about the Agents + */ +typedef enum +{ + /** + * GPU Agent Name + */ + ROCPROFILER_AGENT_NAME = 0, + /** + * GPU Agent Type + */ + ROCPROFILER_AGENT_TYPE = 1 +} rocprofiler_agent_info_kind_t; + +/** + * Query Agent Information size to allow the user to allocate the right size + * for the information data requested, the information will be collected using + * ::rocprofiler_agent_id_t to identify one type of information available in + * ::rocprofiler_agent_info_t + * + * \param[in] kind Information kind requested by the user + * \param[in] agent_id Agent ID + * \param[out] data_size Size of the information data output + * \retval ::ROCPROFILER_STATUS_SUCCESS if the information was found + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_ERROR_AGENT_NOT_FOUND
, if the agent was not found + * in the saved agents + * \retval ::ROCPROFILER_STATUS_ERROR_AGENT_INFORMATION_MISSING \n if the agent + * was found in the saved agents but the required information is missing + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_query_agent_info_size(rocprofiler_agent_info_kind_t kind, + rocprofiler_agent_id_t agent_id, + size_t* data_size) ROCPROFILER_VERSION_9_0; + +/** + * Query Agent Information Data using an allocated data pointer by the user, + * user can get the size of the data using ::rocprofiler_query_agent_info_size, + * the user can get the data using ::rocprofiler_agent_id_t and the user need to + * identify one type of information available in ::rocprofiler_agent_info_t + * + * \param[in] kind Information kind requested by the user + * \param[in] agent_id Agent ID + * \param[out] data_size Size of the information data output + * \retval ::ROCPROFILER_STATUS_SUCCESS, if the information was found + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED
if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_ERROR_AGENT_NOT_FOUND
if the agent was not found + * in the saved agents + * \retval ::ROCPROFILER_STATUS_ERROR_AGENT_INFORMATION_MISSING \n if the agent + * was found in the saved agents but the required information is missing + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_query_agent_info(rocprofiler_agent_info_kind_t kind, + rocprofiler_agent_id_t descriptor, + const char** name) ROCPROFILER_VERSION_9_0; + +/** @} */ + +/** \defgroup record_queues_group Queues(AMD HSA QUEUES) Handling + * \ingroup generic_record_group + * @{ + */ + +/** + * Unique ID handle to represent an HSA Queue of type \p hsa_queue_t, this id + * can be used by the user to get queue information using + * ::rocprofiler_query_queue_info + */ +typedef struct +{ + /** + * Unique Id for every queue for one agent for one system + */ + uint64_t handle; +} rocprofiler_queue_id_t; + +// TODO(aelwazir): Check if there is anymore Queue Information needed +/** + * Types of information that can be requested about the Queues + */ +typedef enum +{ + /** + * AMD HSA Queue Size. + */ + ROCPROFILER_QUEUE_SIZE = 0 +} rocprofiler_queue_info_kind_t; + +/** + * Query Queue Information size to allow the user to allocate the right size + * for the information data requested, the information will be collected using + * ::rocprofiler_queue_id_t by using ::rocprofiler_query_queue_info and the user + * need to identify one type of information available in + * ::rocprofiler_queue_info_t + * + * \param[in] kind Information kind requested by the user + * \param[in] agent_id Queue ID + * \param[out] data_size Size of the information data output + * \retval ::ROCPROFILER_STATUS_SUCCESS if the information was found + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_ERROR_QUEUE_NOT_FOUND \n if the queue was not found + * in the saved agents + * \retval ::ROCPROFILER_STATUS_ERROR_QUEUE_INFORMATION_MISSING \n + * if the queue was found in the saved queues but the required information is missing + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_query_queue_info_size(rocprofiler_queue_info_kind_t kind, + rocprofiler_queue_id_t agent_id, + size_t* data_size) ROCPROFILER_VERSION_9_0; + +/** + * Query Queue Information Data using an allocated data pointer by the user, + * user can get the size of the data using ::rocprofiler_query_queue_info_size, + * the user can get the data using ::rocprofiler_queue_id_t and the user need to + * identify one type of information available in ::rocprofiler_queue_info_t + * + * \param[in] kind Information kind requested by the user + * \param[in] agent_id Queue ID + * \param[out] data_size Size of the information data output + * \retval ::ROCPROFILER_STATUS_SUCCESS, if the information was found + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED, if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_ERROR_QUEUE_NOT_FOUND \n if the queue was not found + * in the saved agents + * \retval ::ROCPROFILER_STATUS_ERROR_QUEUE_INFORMATION_MISSING \n if the queue + * was found in the saved agents but the required information is missing + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_query_queue_info(rocprofiler_queue_info_kind_t kind, + rocprofiler_queue_id_t descriptor, + const char** name) ROCPROFILER_VERSION_9_0; + +/** @} */ + +/** \defgroup record_kernels_group Kernels Handling + * \ingroup generic_record_group + * @{ + */ + +/** + * Kernel identifier that represent a unique id for every kernel + */ +typedef struct +{ + /** + * Kernel object identifier + */ + uint64_t handle; +} rocprofiler_kernel_id_t; + +/** + * Kernel Information Types, can be used by ::rocprofiler_query_kernel_info + */ +typedef enum +{ + /** + * Kernel Name Information Type + */ + ROCPROFILER_KERNEL_NAME = 0 +} rocprofiler_kernel_info_kind_t; + +/** + * Query Kernel Information Data size to allow the user to allocate the right + * size for the information data requested, the information will be collected + * using + * ::rocprofiler_kernel_id_t by using ::rocprofiler_query_kernel_info and the + * user need to identify one type of information available in + * ::rocprofiler_kernel_info_t + * + * \param[in] kernel_info_type The tyoe of information needed + * \param[in] kernel_id Kernel ID + * \param[out] data_size Kernel Information Data size + * \retval ::ROCPROFILER_STATUS_SUCCESS, if the information was found + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED, if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_ERROR_KERNEL_NOT_FOUND \n if the kernel was not + * found in the saved kernels + * \retval ::ROCPROFILER_STATUS_ERROR_KERNEL_INFORMATION_MISSING \n if the kernel + * was found in the saved counters but the required information is missing + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_query_kernel_info_size(rocprofiler_kernel_info_kind_t kind, + rocprofiler_kernel_id_t kernel_id, + size_t* data_size) ROCPROFILER_VERSION_9_0; + +/** + * Query Kernel Information Data using an allocated data pointer by the user, + * user can get the size of the data using ::rocprofiler_query_kernel_info_size, + * the user can get the data using ::rocprofiler_kernel_id_t and the user need + * to identify one type of information available in ::rocprofiler_kernel_info_t + * + * \param[in] kind Information kind requested by the user + * \param[in] kernel_id Kernel ID + * \param[out] data Information Data + * \retval ::ROCPROFILER_STATUS_SUCCESS, if the information was found + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED, if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_ERROR_KERNEL_NOT_FOUND \n if the kernel was not + * found in the saved kernels + * \retval ::ROCPROFILER_STATUS_ERROR_KERNEL_INFORMATION_MISSING \n if the kernel + * was found in the saved kernels but the required information is missing + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_query_kernel_info(rocprofiler_kernel_info_kind_t kind, + rocprofiler_kernel_id_t kernel_id, + const char** data) ROCPROFILER_VERSION_9_0; + +/** @} */ + +/** + * Holds the thread id + */ +typedef struct +{ + /** + * Thread ID + */ + uint32_t value; +} rocprofiler_thread_id_t; + +/** @} */ + +/** \defgroup profiling_api_group Profiling Part Handling + * + * The profiling records are asynchronously logged to the pool and can be + * associated with the respective GPU kernels. + * Profiling API can be used to enable collecting of the records with or + * without timestamping data for the GPU Application in continuous mode or + * kernel mode. + * + * @{ + */ + +/** \defgroup profiling_api_counters_group Counter Collection Handling + * records + * \ingroup profiling_api_group + * @{ + */ + +typedef struct +{ + const char* name; + const char* description; + const char* expression; + uint32_t instances_count; + const char* block_name; + uint32_t block_counters; +} rocprofiler_counter_info_t; + +typedef int (*rocprofiler_counters_info_callback_t)(rocprofiler_counter_info_t counter, + const char* gpu_name, + uint32_t gpu_index) ROCPROFILER_VERSION_9_0; + +ROCPROFILER_API rocprofiler_status_t +rocprofiler_iterate_counters(rocprofiler_counters_info_callback_t counters_info_callback) + ROCPROFILER_VERSION_9_0; + +/** + * Counter ID to be used to query counter information using + * ::rocprofiler_query_counter_info + */ +typedef struct +{ + /** + * A unique id generated for every counter requested by the user + */ + uint64_t handle; +} rocprofiler_counter_id_t; + +/** + * Counter Information Types, can be used by ::rocprofiler_query_counter_info + */ +typedef enum +{ + /** + * Can be used to get the counter name + */ + ROCPROFILER_COUNTER_NAME = 0, + /** + * Can be used to get the block id of a counter + */ + ROCPROFILER_COUNTER_BLOCK_ID = 2, + /** + * This is the level of hierarchy from the GFX_IP where the counter value + * should be collected + */ + ROCPROFILER_COUNTER_HIERARCHY_LEVEL = 3 +} rocprofiler_counter_info_kind_t; + +/** + * Query Counter Information Data size to allow the user to allocate the right + * size for the information data requested, the information will be collected + * using + * ::rocprofiler_counter_id_t by using ::rocprofiler_query_counter_info and the + * user need to identify one type of information available in + * ::rocprofiler_counter_info_t + * + * \param[in] session_id Session id where this data was collected + * \param[in] counter_info_type The tyoe of information needed + * \param[in] counter_id Counter ID + * \param[out] data_size Counter Information Data size + * \retval ::ROCPROFILER_STATUS_SUCCESS, if the information was found + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED \n if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_ERROR_COUNTER_NOT_FOUND \n if the counter was not + * found in the saved counters + * \retval ::ROCPROFILER_STATUS_ERROR_COUNTER_INFORMATION_MISSING \n if the counter + * was found in the saved counters but the required information is missing + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_query_counter_info_size(rocprofiler_session_id_t session_id, + rocprofiler_counter_info_kind_t counter_info_type, + rocprofiler_counter_id_t counter_id, + size_t* data_size) ROCPROFILER_VERSION_9_0; + +/** + * Query Counter Information Data using an allocated data pointer by the user, + * user can get the size of the data using ::rocprofiler_query_counter_info_size, + * the user can get the data using ::rocprofiler_counter_id_t and the user need + * to identify one type of information available in ::rocprofiler_counter_info_t + * + * \param[in] session_id Session id where this data was collected + * \param[in] kind Information kind requested by the user + * \param[in] counter_id Counter ID + * \param[out] data Information Data + * \retval ::ROCPROFILER_STATUS_SUCCESS, if the information was found + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED \n if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_ERROR_COUNTER_NOT_FOUND \n if the counter was not + * found in the saved counters + * \retval ::ROCPROFILER_STATUS_ERROR_COUNTER_INFORMATION_MISSING \n if the counter + * was found in the saved counters but the required information is missing + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_query_counter_info(rocprofiler_session_id_t session_id, + rocprofiler_counter_info_kind_t kind, + rocprofiler_counter_id_t counter_id, + const char** data) ROCPROFILER_VERSION_9_0; + +typedef struct +{ + /** + * queue index value + */ + uint64_t value; +} rocprofiler_queue_index_t; + +// TODO(aelwazir): add more types to the values should we use unions??!! +/** + * Counter Value Structure + */ +typedef struct +{ + /** + * Counter value + */ + double value; +} rocprofiler_record_counter_value_t; + +/** + * Counter Instance Structure, it will represent every counter reported in the + * array of counters reported by every profiler record if counters were needed + * to be collected + */ +typedef struct +{ + /** + * Counter Instance Identifier + */ + rocprofiler_counter_id_t counter_handler; // Counter Handler + /** + * Counter Instance Value + */ + rocprofiler_record_counter_value_t value; // Counter Value +} rocprofiler_record_counter_instance_t; + +/** + * Counters Instances Count Structure, every profiling record has this + * structure included to report the number of counters collected for this + * kernel dispatch + */ +typedef struct +{ + /** + * Counters Instances Count for every record + */ + uint64_t value; +} rocprofiler_record_counters_instances_count_t; + +/** + * Kernel properties, this will represent the kernel properties + * such as its grid size, workgroup size, wave_size + */ + +typedef struct +{ + /** + * Grid Size + */ + uint64_t grid_size; + /** + * workgroup size + */ + uint64_t workgroup_size; + /** + * lds_size + */ + uint64_t lds_size; + /** + * scratch_size + */ + uint64_t scratch_size; + /** + * arch vgpr count + */ + uint64_t arch_vgpr_count; + /** + * accum vgpr count + */ + uint64_t accum_vgpr_count; + /** + * sgpr_count + */ + uint64_t sgpr_count; + /** + * wave size + */ + uint64_t wave_size; + /** + * Dispatch completion signal handle + */ + uint64_t signal_handle; + +} rocprofiler_kernel_properties_t; + +/** + * Correlation ID + */ +typedef struct +{ + uint64_t value; +} rocprofiler_correlation_id_t; + +/** + * Profiling record, this will represent all the information reported by the + * profiler regarding kernel dispatches and their counters that were collected + * by the profiler and requested by the user, this can be used as the type of + * the flushed records that is reported to the user using + * ::rocprofiler_buffer_callback_t + */ +typedef struct +{ + /** + * ROCProfiler General Record base header to identify the id and kind of every + * record + */ + rocprofiler_record_header_t header; + /** + * Kernel Identifier to be used by the user to get the kernel info using + * ::rocprofiler_query_kernel_info + */ + rocprofiler_kernel_id_t kernel_id; + /** + * Agent Identifier to be used by the user to get the Agent Information using + * ::rocprofiler_query_agent_info + */ + rocprofiler_agent_id_t gpu_id; + /** + * Queue Identifier to be used by the user to get the Queue Information using + * ::rocprofiler_query_agent_info + */ + rocprofiler_queue_id_t queue_id; + /** + * Timestamps, start and end timestamps of the record data (ex. Kernel + * Dispatches) + */ + rocprofiler_record_header_timestamp_t timestamps; + /** + * Counters, including identifiers to get counter information and Counters + * values + */ + const rocprofiler_record_counter_instance_t* counters; + /** + * The count of the counters that were collected by the profiler + */ + rocprofiler_record_counters_instances_count_t counters_count; /* Counters Count */ + /** + * kernel properties, including the grid size, work group size, + * registers count, wave size and completion signal + */ + rocprofiler_kernel_properties_t kernel_properties; + /** + * Thread id + */ + rocprofiler_thread_id_t thread_id; + /** + * Queue Index - packet index in the queue + */ + rocprofiler_queue_index_t queue_idx; + /** + * Correlation id + */ + rocprofiler_correlation_id_t correlation_id; +} rocprofiler_record_profiler_t; + +typedef struct +{ + uint32_t value; + +} rocprofiler_event_id_t; + +typedef struct +{ + uint16_t value; // Counter Value + +} rocprofiler_record_spm_counters_instances_count_t; + +/** + * Counters, including identifiers to get counter information and Counters + * values + */ +typedef struct +{ + rocprofiler_record_spm_counters_instances_count_t counters_data[32]; + +} rocprofiler_record_se_spm_data_t; + +/** + * SPM record, this will represent all the information reported by the + * SPM regarding counters and their timestamps this can be used as the type of + * the flushed records that is reported to the user using + * ::rocprofiler_buffer_callback_t + */ +typedef struct +{ + /** + * ROCProfiler General Record base header to identify the id and kind of every + * record + */ + rocprofiler_record_header_t header; + + /** + * Timestamps at which the counters were sampled. + */ + rocprofiler_record_header_timestamp_t timestamps; + /** + * Counter values per shader engine + */ + rocprofiler_record_se_spm_data_t shader_engine_data[4]; + +} rocprofiler_record_spm_t; + +/** + * struct to store the trace data from a shader engine. + */ +typedef struct +{ + void* buffer_ptr; + uint32_t buffer_size; +} rocprofiler_record_se_att_data_t; + +/** + * ATT tracing record structure. + * This will represent all the information reported by the + * ATT tracer such as the kernel and its thread trace data. + * This record can be flushed to the user using + * ::rocprofiler_buffer_callback_t + */ +typedef struct +{ + /** + * ROCProfiler General Record base header to identify the id and kind of every + * record + */ + rocprofiler_record_header_t header; + /** + * Kernel Identifier to be used by the user to get the kernel info using + * ::rocprofiler_query_kernel_info + */ + rocprofiler_kernel_id_t kernel_id; + /** + * Agent Identifier to be used by the user to get the Agent Information using + * ::rocprofiler_query_agent_info + */ + rocprofiler_agent_id_t gpu_id; + /** + * Queue Identifier to be used by the user to get the Queue Information using + * ::rocprofiler_query_agent_info + */ + rocprofiler_queue_id_t queue_id; + /** + * kernel properties, including the grid size, work group size, + * registers count, wave size and completion signal + */ + rocprofiler_kernel_properties_t kernel_properties; + /** + * Thread id + */ + rocprofiler_thread_id_t thread_id; + /** + * Queue Index - packet index in the queue + */ + rocprofiler_queue_index_t queue_idx; + /** + * ATT data output from each shader engine. + */ + rocprofiler_record_se_att_data_t* shader_engine_data; + /** + * The count of the shader engine ATT data + */ + uint64_t shader_engine_data_count; +} rocprofiler_record_att_tracer_t; + +/** @} */ + +/** \defgroup tracing_api_group Tracer Part Handling + * @{ + */ + +/** + * Traced API domains + */ +typedef enum +{ + ACTIVITY_DOMAIN_NONE = -1, + /** + * HSA API domain + */ + ACTIVITY_DOMAIN_HSA_API = 0, + /** + * HSA async activity domain + */ + ACTIVITY_DOMAIN_HSA_OPS = 1, + /** + * HIP async activity domain + */ + ACTIVITY_DOMAIN_HIP_OPS = 2, + /** + * HIP API domain + */ + ACTIVITY_DOMAIN_HIP_API = 3, + /** + * KFD API domain + */ + ACTIVITY_DOMAIN_KFD_API = 4, + /** + * External ID domain + */ + ACTIVITY_DOMAIN_EXT_API = 5, + /** + * ROCTX domain + */ + ACTIVITY_DOMAIN_ROCTX = 6, + // TODO(aelwazir): Used in kernel Info, memcpy, ..etc, refer to hsa_support + // TODO(aelwazir): Move HSA Events to hsa_support + /** + * HSA events (Device Activity) + */ + ACTIVITY_DOMAIN_HSA_EVT = 7, + ACTIVITY_DOMAIN_NUMBER +} rocprofiler_tracer_activity_domain_t; + +/** + * Tracing Operation ID for HIP/HSA + */ +typedef struct +{ + uint32_t id; +} rocprofiler_tracer_operation_id_t; + +/** + * Correlation identifier + */ +typedef struct +{ + /** + * Correlation ID Value + */ + uint64_t value; +} rocprofiler_tracer_activity_correlation_id_t; + +/** + * Tracer API Calls Data Handler + */ +typedef struct +{ + union + { + const struct hip_api_data_s* hip; + const struct hsa_api_data_s* hsa; + const struct roctx_api_data_s* roctx; + }; +} rocprofiler_tracer_api_data_t; + +/** + * @brief Get Tracer API Function Name + * + * Return NULL if the name is not found for given domain and operation_id. + * + * Note: The returned string is NULL terminated. + * + * @param[in] domain + * @param[in] operation_id + * @param[out] name + * @return ::rocprofiler_status_t + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_query_tracer_operation_name(rocprofiler_tracer_activity_domain_t domain, + rocprofiler_tracer_operation_id_t operation_id, + const char** name); + +/** + * @brief Get Tracer API Operation ID + * + * @param [in] domain + * @param [in] name + * @param [out] operation_id + * @return ::rocprofiler_status_t + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_tracer_operation_id(rocprofiler_tracer_activity_domain_t domain, + const char* name, + rocprofiler_tracer_operation_id_t* operation_id); + +/** + * Tracing external ID + */ +typedef struct +{ + uint64_t id; +} rocprofiler_tracer_external_id_t; + +typedef enum +{ + /** + * No phase, it is an activity record or asynchronous output data + */ + ROCPROFILER_PHASE_NONE = 0, + /** + * Enter phase for API calls + */ + ROCPROFILER_PHASE_ENTER = 1, + /** + * Exit phase for API calls + */ + ROCPROFILER_PHASE_EXIT = 2 +} rocprofiler_api_tracing_phase_t; + +/** + * Tracing record, this will represent all the information reported by the + * tracer regarding APIs and their data that were traced and collected + * by the tracer and requested by the user, this can be used as the type of + * the flushed records that is reported to the user using + * ::rocprofiler_buffer_async_callback_t + */ +typedef struct +{ + /** + * ROCProfiler General Record base header to identify the id and kind of every + * record + */ + rocprofiler_record_header_t header; + /** + * Tracing external ID, and ROCTX ID if domain is ::ACTIVITY_DOMAIN_ROCTX + */ + rocprofiler_tracer_external_id_t external_id; + /** + * Activity domain id, represents the type of the APIs that are being traced + */ + rocprofiler_tracer_activity_domain_t domain; + /** + * Tracing Operation ID for HIP/HSA + */ + rocprofiler_tracer_operation_id_t operation_id; + /** + * API Data + */ + rocprofiler_tracer_api_data_t api_data; + /** + * Activity correlation ID + */ + rocprofiler_tracer_activity_correlation_id_t correlation_id; + /** + * Timestamps + */ + rocprofiler_record_header_timestamp_t timestamps; + /** + * Agent identifier that can be used as a handler in + * ::rocprofiler_query_agent_info + */ + rocprofiler_agent_id_t agent_id; + /** + * Queue identifier that can be used as a handler in + * ::rocprofiler_query_queue_info + */ + rocprofiler_queue_id_t queue_id; + /** + * Thread id + */ + rocprofiler_thread_id_t thread_id; + /** + * API Tracing phase (Enter/Exit/None(Activity Records/Asynchronous Output Records)) + */ + rocprofiler_api_tracing_phase_t phase; + /** + * Kernel Name for HIP API calls that launches kernels or ROCTx message for ROCTx api calls + */ + const char* name; +} rocprofiler_record_tracer_t; + +/** + * Kernel dispatch correlation ID, unique across all dispatches + */ +typedef struct +{ + uint64_t value; +} rocprofiler_kernel_dispatch_id_t; + +/** + * An individual PC sample + */ +typedef struct +{ + /** + * Kernel dispatch ID. This is used by PC sampling to associate samples with + * individual dispatches and is unrelated to any user-supplied correlation ID + */ + rocprofiler_kernel_dispatch_id_t dispatch_id; + union + { + /** + * Host timestamp + */ + rocprofiler_timestamp_t timestamp; + /** + * GPU clock counter (not currently used) + */ + uint64_t cycle; + }; + /** + * Sampled program counter + */ + uint64_t pc; + /** + * Sampled shader element + */ + uint32_t se; + /** + * Sampled GPU agent + */ + rocprofiler_agent_id_t gpu_id; +} rocprofiler_pc_sample_t; + +/** + * PC sample record: contains the program counter/instruction pointer observed + * during periodic sampling of a kernel + */ +typedef struct +{ + /** + * ROCProfiler General Record base header to identify the id and kind of every + * record + */ + rocprofiler_record_header_t header; + /** + * PC sample data + */ + rocprofiler_pc_sample_t pc_sample; +} rocprofiler_record_pc_sample_t; + +/** @} */ + +/** \defgroup memory_storage_buffer_group Memory Storage Buffer + * Sessions + * + * In this group, Memory Pools and their types will be discussed. + * @{ + */ + +/** + * Buffer Property Options + */ +typedef enum +{ + /** + * Flush interval + */ + ROCPROFILER_BUFFER_PROPERTY_KIND_INTERVAL_FLUSH = 0, + // Periodic Flush + // Size + // Think of using the kind as an end of the array!!?? +} rocprofiler_buffer_property_kind_t; + +typedef struct +{ + rocprofiler_buffer_property_kind_t kind; + uint64_t value; +} rocprofiler_buffer_property_t; + +typedef struct +{ + uint64_t value; +} rocprofiler_buffer_id_t; + +typedef struct +{ + uint64_t value; +} rocprofiler_filter_id_t; + +/** + * Memory pool buffer callback. + * The callback that will be invoked when a memory pool buffer becomes full or + * is flushed by the user or using flush thread that was initiated using the + * flush interval set by the user ::rocprofiler_create_session. + * The user needs to read the record header to identify the record kind and + * depending on the kind they can reinterpret_cast to either + * ::rocprofiler_record_profiler_t if the kind was ::ROCPROFILER_PROFILER_RECORD or + * ::rocprofiler_record_tracer_t if the kind is ::ROCPROFILER_TRACER_RECORD + * + * \param[in] begin pointer to first entry in the buffer. + * \param[in] end pointer to one past the end entry in the buffer. + * \param[in] session_id The session id associated with that record + * \param[in] buffer_id The buffer id associated with that record + */ +typedef void (*rocprofiler_buffer_callback_t)(const rocprofiler_record_header_t* begin, + const rocprofiler_record_header_t* end, + rocprofiler_session_id_t session_id, + rocprofiler_buffer_id_t buffer_id); + +/** + * Flush specific Buffer + * + * \param[in] session_id The created session id + * \param[in] buffer_id The buffer ID of the created filter group + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED, if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_ERROR_SESSION_NOT_FOUND \n may return if + * the session is not found + * \retval ::ROCPROFILER_STATUS_ERROR_CORRUPTED_SESSION_BUFFER \n may return if + * the session buffer is corrupted + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_flush_data(rocprofiler_session_id_t session_id, + rocprofiler_buffer_id_t buffer_id) ROCPROFILER_VERSION_9_0; + +/** + * Get a pointer to the next profiling record. + * A memory pool generates buffers that contain multiple profiling records. + * This function steps to the next profiling record. + * + * \param[in] record Pointer to the current profiling record in a memory pool + * buffer. + * \param[out] next Pointer to the following profiling record in the memory + * pool buffer. + * \param[in] session_id Session ID + * \param[in] buffer_id Buffer ID + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED, if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_ERROR_RECORD_CORRUPTED \n if the function couldn't + * get the next record because of corrupted data reported by the previous + * record + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_next_record(const rocprofiler_record_header_t* record, + const rocprofiler_record_header_t** next, + rocprofiler_session_id_t session_id, + rocprofiler_buffer_id_t buffer_id) ROCPROFILER_VERSION_9_0; + +/** @} */ + +/** \defgroup sessions_handling_group ROCProfiler Sessions + * @{ + */ + +/** + * Replay Profiling Modes. + */ +typedef enum +{ + /** + * No Replay to be done, Mostly for tracing tool or if the user wants to make + * sure that no replays will be done + */ + ROCPROFILER_NONE_REPLAY_MODE = -1, +} rocprofiler_replay_mode_t; + +/** + * Create Session + * A ROCProfiler Session is having enough information about what needs to be + * collected or traced and it allows the user to start/stop profiling/tracing + * whenever required. + * Session will hold multiple mode, that can be added using + * ::rocprofiler_add_session_mode, it is required to add at least one session + * mode, if it is tracing or profiling and using ::rocprofiler_session_set_filter + * can set specific data that is required for the profiler or the tracer such + * as the counters for profiling or the APIs for tracing before calling + * ::rocprofiler_start_session, also + * ::rocprofiler_session_set_filter can be used to set optional filters like + * specific GPUs/Kernel Names/API Names and more. Session can be started using + * ::rocprofiler_start_session and can be stopped using + * ::rocprofiler_terminate_session + * + * \param[in] replay_mode The Replay strategy that should be used if replay is + * needed + * \param[out] session_id Pointer to the created session id, the session is + * alive up till ::rocprofiler_destroy_session being called, however, the session + * id can be + * used while the session is active which can be activated using + * ::rocprofiler_start_session and deactivated using + * ::rocprofiler_terminate_session but ::rocprofiler_flush_data can use session_id + * even if it is deactivated for flushing the saved records + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED, if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_create_session(rocprofiler_replay_mode_t replay_mode, + rocprofiler_session_id_t* session_id) ROCPROFILER_VERSION_9_0; + +/** + * Destroy Session + * Destroy session created by ::rocprofiler_create_session, please refer to + * the samples for how to use. + * This marks the end of session and its own id life and none of the session + * related functions will be available after this call. + * + * \param[in] session_id The created session id + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED, if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_ERROR_SESSION_NOT_FOUND \n may return if + * the session is not found + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_destroy_session(rocprofiler_session_id_t session_id) ROCPROFILER_VERSION_9_0; + +/** \defgroup session_filter_group Session Filters Handling + * \ingroup sessions_handling_group + * @{ + */ + +typedef enum +{ + /** + * Kernel Dispatch Timestamp collection. + */ + ROCPROFILER_DISPATCH_TIMESTAMPS_COLLECTION = 1, + /** + * GPU Application counter collection. + */ + ROCPROFILER_COUNTERS_COLLECTION = 2, + /** + * PC Sampling collection. (Not Yet Supported) + */ + ROCPROFILER_PC_SAMPLING_COLLECTION = 3, + /** + * ATT Tracing. (Not Yet Supported) + */ + ROCPROFILER_ATT_TRACE_COLLECTION = 4, + /** + * SPM collection. (Not Yet Supported) + */ + ROCPROFILER_SPM_COLLECTION = 5, + /** + * HIP/HSA/ROCTX/SYS Trace. + */ + ROCPROFILER_API_TRACE = 6, + /** + * Sampled Counters + */ + ROCPROFILER_COUNTERS_SAMPLER = 7 +} rocprofiler_filter_kind_t; + +/** + * Data Filter Types to be used by ::rocprofiler_session_set_filter to add + * filters to a specific session + */ +typedef enum +{ + /** + * Add HSA API calls that will be only traced (ex. hsa_amd_memory_async_copy) + */ + ROCPROFILER_FILTER_HSA_TRACER_API_FUNCTIONS = 1, + /** + * Add HIP API calls that will be only traced (ex. hipLaunchKernel) + */ + ROCPROFILER_FILTER_HIP_TRACER_API_FUNCTIONS = 2, + /** + * Add GPU names that will be only profiled or traced + */ + ROCPROFILER_FILTER_GPU_NAME = 3, + // TODO(aelwazir): Add more clear description on how to use? + /** + * Add Range of calls to be traced or kernels to be profiled + */ + ROCPROFILER_FILTER_RANGE = 4, + /** + * Add Kernel names that will be profiled or traced + */ + ROCPROFILER_FILTER_KERNEL_NAMES = 5, + /** + * Add Kernel correlation ids that will be profiled or traced for ATT + */ + ROCPROFILER_FILTER_DISPATCH_IDS = 6 +} rocprofiler_filter_property_kind_t; + +// TODO(aelwazir): Another way to define this as needed +typedef const char* rocprofiler_hip_function_name_t; +typedef const char* rocprofiler_hsa_function_name_t; + +/** + * ATT parameters to be used by for collection + */ +typedef enum +{ + ROCPROFILER_ATT_COMPUTE_UNIT_TARGET = 0, + ROCPROFILER_ATT_VM_ID_MASK = 1, + ROCPROFILER_ATT_MASK = 2, + ROCPROFILER_ATT_TOKEN_MASK = 3, + ROCPROFILER_ATT_TOKEN_MASK2 = 4, + ROCPROFILER_ATT_SE_MASK = 5, + ROCPROFILER_ATT_SAMPLE_RATE = 6, + ROCPROFILER_ATT_BUFFER_SIZE = 7, //! ATT collection max data size. + ROCPROFILER_ATT_PERF_MASK = 240, + ROCPROFILER_ATT_PERF_CTRL = 241, + ROCPROFILER_ATT_PERFCOUNTER = 242, + ROCPROFILER_ATT_PERFCOUNTER_NAME = 243, + ROCPROFILER_ATT_MAXVALUE +} rocprofiler_att_parameter_name_t; + +// att tracing parameters object +typedef struct +{ + rocprofiler_att_parameter_name_t parameter_name; + union + { + uint32_t value; + const char* counter_name; + }; +} rocprofiler_att_parameter_t; + +/** + * Filter Data Type + * filter data will be used to report required and optional filters for the + * sessions using ::rocprofiler_session_add_filters + */ +typedef struct +{ + /** + * Filter Property kind + */ + rocprofiler_filter_property_kind_t kind; + // TODO(aelwazir): get HIP or HSA or counters as enums + /** + * Array of data required for the filter type chosen + */ + union + { + const char** name_regex; + rocprofiler_hip_function_name_t* hip_functions_names; + rocprofiler_hsa_function_name_t* hsa_functions_names; + uint32_t range[2]; + uint64_t* dispatch_ids; + }; + /** + * Data array count + */ + uint64_t data_count; +} rocprofiler_filter_property_t; + +typedef struct +{ + /** + * Counters to profile + */ + const char** counters_names; + /** + * Counters count + */ + int counters_count; + /** + * Sampling rate + */ + uint32_t sampling_rate; + /** + * Preferred agents to collect SPM on + */ + rocprofiler_agent_id_t* gpu_agent_id; + +} rocprofiler_spm_parameter_t; + +typedef enum +{ + ROCPROFILER_COUNTERS_SAMPLER_PCIE_COUNTERS = 0, + ROCPROFILER_COUNTERS_SAMPLER_XGMI_COUNTERS = 1 +} rocprofiler_counters_sampler_counter_type_t; + +typedef struct +{ + char* name; + rocprofiler_counters_sampler_counter_type_t type; +} rocprofiler_counters_sampler_counter_input_t; + +typedef struct +{ + rocprofiler_counters_sampler_counter_type_t type; + rocprofiler_record_counter_value_t value; +} rocprofiler_counters_sampler_counter_output_t; + +typedef struct +{ + /** + * Counters to profile + */ + rocprofiler_counters_sampler_counter_input_t* counters; + /** + * Counters count + */ + int counters_num; + /** + * Sampling rate (ms) + */ + uint32_t sampling_rate; + /** + * Total sampling duration (ms); time between sampling start/stop + */ + uint32_t sampling_duration; + /** + * Initial delay (ms) + */ + uint32_t initial_delay; + /** + * Preferred agents to collect counters from + */ + int gpu_agent_index; +} rocprofiler_counters_sampler_parameters_t; + +typedef struct +{ + /** + * ROCProfiler General Record base header to identify the id and kind of every + * record + */ + rocprofiler_record_header_t header; + /** + * Agent Identifier to be used by the user to get the Agent Information using + * ::rocprofiler_query_agent_info + */ + rocprofiler_agent_id_t gpu_id; + /** + * Counters, including identifiers to get counter information and Counters + * values + */ + rocprofiler_counters_sampler_counter_output_t* counters; + /** + * Number of counter values + */ + uint32_t num_counters; +} rocprofiler_record_counters_sampler_t; + +/** + * Filter Kind Data + */ +typedef union +{ + /** + * APIs to trace + */ + rocprofiler_tracer_activity_domain_t* trace_apis; + /** + * Counters to profile + */ + const char** counters_names; + /** + * att parameters + */ + rocprofiler_att_parameter_t* att_parameters; + /** + * spm counters parameters + */ + rocprofiler_spm_parameter_t* spm_parameters; + /** + * sampled counters parameters + */ + rocprofiler_counters_sampler_parameters_t counters_sampler_parameters; +} rocprofiler_filter_data_t; + +/** + * Create Session Filter + * This function will create filter and associate it with a specific session + * For every kind, one filter only is allowed per session + * + * \param[in] session_id Session id where these filters will applied to + * \param[in] filter_kind Filter kind associated with these filters + * \param[in] data Pointer to the filter data + * \param[in] data_count Count of data in the data array given in ::data + * \param[out] filter_id The id of the filter created + * \param[in] property property needed for more filteration requests by the + * user (Only one property is allowed per filter) (Optional) + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED, if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_SESSION_NOT_FOUND Couldn't find session + * associated with the given session identifier + * \retval ::ROCPROFILER_STATUS_ERROR_SESSION_FILTER_DATA_MISMATCH \n The session + * filter can't accept the given data + * \retval ::ROCPROFILER_STATUS_ERROR_FILTER_DATA_CORRUPTED \n Data can't be read or + * corrupted + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_create_filter(rocprofiler_session_id_t session_id, + rocprofiler_filter_kind_t filter_kind, + rocprofiler_filter_data_t data, + uint64_t data_count, + rocprofiler_filter_id_t* filter_id, + rocprofiler_filter_property_t property) ROCPROFILER_VERSION_9_0; + +/** + * Set Session Filter Buffer + * This function will associate buffer to a specific filter + * + * if the user wants to get the API traces for the api calls synchronously then + * the user is required to call ::rocprofiler_set_api_trace_sync_callback + * + * \param[in] session_id Session id where these filters will applied to + * \param[in] filter_id The id of the filter + * \param[in] buffer_id The id of the buffer + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED, if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_SESSION_NOT_FOUND Couldn't find session + * associated with the given session identifier + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_set_filter_buffer(rocprofiler_session_id_t session_id, + rocprofiler_filter_id_t filter_id, + rocprofiler_buffer_id_t buffer_id) ROCPROFILER_VERSION_9_0; + +/** + * Synchronous Callback + * To be only used by ::rocprofiler_set_api_trace_sync_callback, please refer to + * ::rocprofiler_set_api_trace_sync_callback for more details + * + * \param[in] record pointer to the record. + * \param[in] session_id The session id associated with that record + */ +typedef void (*rocprofiler_sync_callback_t)(rocprofiler_record_tracer_t record, + rocprofiler_session_id_t session_id); + +/** + * Set Session API Tracing Filter Synchronous Callback + * This function will associate buffer to a specific filter + * + * Currently Synchronous callbacks are only available to API Tracing filters + * for the api calls tracing and not available for the api activities or any + * other filter type, the user is responsible to create and set buffer for the + * other types + * + * \param[in] session_id Session id where these filters will applied to + * \param[in] filter_id The id of the filter + * \param[in] callback Synchronous callback + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED, if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_SESSION_NOT_FOUND, Couldn't find session + * associated with the given session identifier + * \retval ::ROCPROFILER_STATUS_ERROR_FILTER_NOT_SUPPORTED \n if the filter is not + * related to API tracing + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_set_api_trace_sync_callback(rocprofiler_session_id_t session_id, + rocprofiler_filter_id_t filter_id, + rocprofiler_sync_callback_t callback) + ROCPROFILER_VERSION_9_0; + +/** + * Destroy Session Filter + * This function will destroy a specific filter + * + * \param[in] session_id Session id where these filters will applied to + * \param[in] filter_id The id of the filter + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED, if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_SESSION_NOT_FOUND Couldn't find session + * associated with the given session identifier + * \retval ::ROCPROFILER_STATUS_FILTER_NOT_FOUND Couldn't find session filter + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_destroy_filter(rocprofiler_session_id_t session_id, + rocprofiler_filter_id_t filter_id) ROCPROFILER_VERSION_9_0; + +/** + * Create Buffer + * This function will create a buffer that can be associated with a filter + * + * \param[in] session_id Session id where these filters will applied to + * \param[in] buffer_callback Providing a callback for the buffer specialized + * for that filters + * \param[in] buffer_size Providing size for the buffer that will be created + * \param[in] buffer_properties Array of Flush Properties provided by the user + * \param[in] buffer_properties_count The count of the flush properties in the + * array + * \param[out] buffer_id Buffer id that was created + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED, if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_SESSION_NOT_FOUND Couldn't find session + * associated with the given session identifier + * \retval ::ROCPROFILER_STATUS_ERROR_SESSION_PROPERTIES_MISMATCH The given + * properties data are mismatching the properties kind + * \retval ::ROCPROFILER_STATUS_ERROR_PROPERTY_DATA_CORRUPTED Data can't be read + * or corrupted + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_create_buffer(rocprofiler_session_id_t session_id, + rocprofiler_buffer_callback_t buffer_callback, + size_t buffer_size, + rocprofiler_buffer_id_t* buffer_id) ROCPROFILER_VERSION_9_0; + +/** + * Setting Buffer Properties + * This function will set buffer properties + * + * \param[in] session_id Session id where the buffer is associated with + * \param[in] buffer_id Buffer id of the buffer that the properties are going + * to be associated with for that filters + * \param[in] buffer_properties Array of Flush Properties provided by the user + * \param[in] buffer_properties_count The count of the flush properties in the + * array + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED, if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_SESSION_NOT_FOUND Couldn't find session + * associated with the given session identifier + * \retval ::ROCPROFILER_STATUS_BUFFER_NOT_FOUND Couldn't find buffer + * associated with the given buffer identifier + * \retval ::ROCPROFILER_STATUS_ERROR_SESSION_PROPERTIES_MISMATCH The given + * properties data are mismatching the properties kind + * \retval ::ROCPROFILER_STATUS_ERROR_PROPERTY_DATA_CORRUPTED Data can't be read + * or corrupted + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_set_buffer_properties(rocprofiler_session_id_t session_id, + rocprofiler_buffer_id_t buffer_id, + rocprofiler_buffer_property_t* buffer_properties, + uint32_t buffer_properties_count) ROCPROFILER_VERSION_9_0; + +/** + * Destroy Buffer + * This function will destroy a buffer given its id and session id + * + * \param[in] session_id Session id where these filters will applied to + * \param[in] buffer_id Buffer id that will b e destroyed + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED, if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_SESSION_NOT_FOUND Couldn't find session + * associated with the given session identifier + * \retval ::ROCPROFILER_STATUS_BUFFER_NOT_FOUND Couldn't find buffer + * associated with the given buffer identifier + * \retval ::ROCPROFILER_STATUS_ERROR_SESSION_PROPERTIES_MISMATCH The given + * properties data are mismatching the properties kind + * \retval ::ROCPROFILER_STATUS_ERROR_PROPERTY_DATA_CORRUPTED Data can't be read + * or corrupted + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_destroy_buffer(rocprofiler_session_id_t session_id, + rocprofiler_buffer_id_t buffer_id) ROCPROFILER_VERSION_9_0; + +/** @} */ + +/** + * Create Ready Session + * A one call to create a ready profiling or tracing session, so that the + * session will be ready to collect counters with a one call to + * ::rocprofiler_start_session. + * ::rocprofiler_session_set_filter can be used to set optional filters like + * specific GPUs/Kernel Names/Counter Names and more. The Creation of the + * session is responsible for the creation of the buffer saving the records + * generated while the session is active. Session can be started using + * ::rocprofiler_start_session and can be stopped using + * ::rocprofiler_terminate_session + * + * \param[in] counters counter filter data, it is required from the user to + * create the filter with ::ROCPROFILER_FILTER_PROFILER_COUNTER_NAMES and to + * provide an array of counter names needed and their count + * \param[in] replay_mode The Replay strategy that should be used if replay is + * needed + * \param[in] filter_kind Filter kind associated with these filters + * \param[in] data Pointer to the filter data + * \param[in] data_count Filter data array count + * \param[in] buffer_size Size of the memory pool that will be used to save the + * data from profiling or/and tracing, if the buffer was allocated before it + * will be reallocated with the new size in addition to the old size + * \param[in] buffer_callback Asynchronous callback using Memory buffers saving + * the data and then it will be flushed if the user called + * ::rocprofiler_flush_data or if the buffer is full or if the application + * finished execution + * \param[out] session_id Pointer to the created session id, the session is + * alive up till ::rocprofiler_destroy_session being called, however, the session + * id can be used while the session is active which can be activated using + * ::rocprofiler_start_session and deactivated using + * ::rocprofiler_terminate_session but ::rocprofiler_flush_data can use session_id + * even if it is deactivated for flushing the saved records + * \param[in] property Filter Property (Optional) + * \param[in] callback Synchronous callback for API traces (Optional) + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED, if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_ERROR_SESSION_MODE_FILTER_MISMATCH \n The session + * doesn't have the required mode for that filter type + * \retval ::ROCPROFILER_STATUS_ERROR_FILTER_DATA_CORRUPTED \n Data can't be read or + * corrupted + * \retval ::ROCPROFILER_STATUS_ERROR_INCORRECT_SIZE If the size is less than one + * potential record size + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_create_ready_session(rocprofiler_replay_mode_t replay_mode, + rocprofiler_filter_kind_t filter_kind, + rocprofiler_filter_data_t data, + uint64_t data_count, + size_t buffer_size, + rocprofiler_buffer_callback_t buffer_callback, + rocprofiler_session_id_t* session_id, + rocprofiler_filter_property_t property, + rocprofiler_sync_callback_t callback) ROCPROFILER_VERSION_9_0; + +// TODO(aelwazir): Multiple sessions activate for different set of filters +/** + * Activate Session + * Activating session created by ::rocprofiler_create_session, please refer to + * the samples for how to use. + * + * \param[in] session_id Session ID representing the created session + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully + * \retval ::ROCPROFILER_STATUS_ERROR_NOT_INITIALIZED, if rocprofiler_initialize + * wasn't called before or if rocprofiler_finalize is called + * \retval ::ROCPROFILER_STATUS_ERROR_SESSION_NOT_FOUND \n may return if + * the session is not found + * \retval ::ROCPROFILER_STATUS_ERROR_SESSION_MODE_NOT_ADDED if there is no + * session_mode added + * \retval ::ROCPROFILER_STATUS_ERROR_MISSING_SESSION_CALLBACK if any + * session_mode is missing callback set + * \retval ::ROCPROFILER_STATUS_ERROR_HAS_ACTIVE_SESSION \n if there is already + * active session + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_start_session(rocprofiler_session_id_t session_id) ROCPROFILER_VERSION_9_0; + +/** + * Deactivate Session + * Deactivate session created by ::rocprofiler_create_session, please refer to + * the samples for how to use. + * + * \param[in] session_id Session ID for the session that will be terminated + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully + * \retval ::ROCPROFILER_STATUS_ERROR_SESSION_NOT_FOUND \n may return if + * the session is not found + * \retval ::ROCPROFILER_STATUS_ERROR_SESSION_NOT_ACTIVE if the session is not + * active + */ + +ROCPROFILER_API rocprofiler_status_t +rocprofiler_terminate_session(rocprofiler_session_id_t session_id) ROCPROFILER_VERSION_9_0; + +/** @} */ + +/** \defgroup device_profiling Device Profiling API + * @{ + */ + +typedef struct +{ + double value; +} rocprofiler_counter_value_t; + +typedef struct +{ + char metric_name[64]; + rocprofiler_counter_value_t value; +} rocprofiler_device_profile_metric_t; + +/** + * Create a device profiling session + * + * A device profiling session allows the user to profile the GPU device + * for counters irrespective of the running applications on the GPU. + * This is different from application profiling. device profiling session + * doesn't care about the host running processes and threads. It directly + * provides low level profiling information. + * + * \param[in] counter_names The names of the counters to be collected. + * \param[in] num_counters The number of counters specifief to be collected + * \param[out] session_id Pointer to the created session id. + * \param[in] cpu_index index of the cpu to be used + * \param[in] gpu_index index of the gpu to be used + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_device_profiling_session_create(const char** counter_names, + uint64_t num_counters, + rocprofiler_session_id_t* session_id, + int cpu_index, + int gpu_index) ROCPROFILER_VERSION_9_0; + +/** + * Start the device profiling session that was created previously. + * This will enable the GPU device to start incrementing counters + * + * \param[in] session_id session id of the session to start + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_device_profiling_session_start(rocprofiler_session_id_t session_id) + ROCPROFILER_VERSION_9_0; + +/** + * Poll the device profiling session to read counters from the GPU device. + * This will read out the values of the counters from the GPU device at the + * specific instant when this API is called. This is a thread-blocking call. + * Any thread that calls this API will have to wait until + * the counter values are being read out. + * + * \param[in] session_id session id of the session to start + * \param[out] data records of counter data read out from device + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_device_profiling_session_poll(rocprofiler_session_id_t session_id, + rocprofiler_device_profile_metric_t* data) + ROCPROFILER_VERSION_9_0; + +/** + * Stop the device profiling session that was created previously. + * This will inform the GPU device to stop counters collection. + * + * \param[in] session_id session id of the session to start + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_device_profiling_session_stop(rocprofiler_session_id_t session_id) + ROCPROFILER_VERSION_9_0; + +/** + * Destroy the device profiling session that was created previously. + * + * \param[in] session_id session id of the session to start + * \retval ::ROCPROFILER_STATUS_SUCCESS The function has been executed + * successfully. + */ +ROCPROFILER_API rocprofiler_status_t +rocprofiler_device_profiling_session_destroy(rocprofiler_session_id_t session_id) + ROCPROFILER_VERSION_9_0; + +/** @} */ + +#ifdef __cplusplus +} // extern "C" block +#endif // __cplusplus + +#endif // INC_ROCPROFILER_H_ diff --git a/source/include/rocprofiler/rocprofiler_plugin.h b/source/include/rocprofiler/rocprofiler_plugin.h new file mode 100644 index 0000000000..b5ae40d5ee --- /dev/null +++ b/source/include/rocprofiler/rocprofiler_plugin.h @@ -0,0 +1,142 @@ +/* Copyright (c) 2022 Advanced Micro Devices, Inc. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + 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 + AUTHORS 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 IN + THE SOFTWARE. */ + +/** \section rocprofiler_plugin_api ROCProfiler Plugin API + * + * The ROCProfiler Plugin API is used by the ROCProfiler Tool to output all + * profiling information. Different implementations of the ROCProfiler Plugin + * API can be developed that output the data in different formats. The + * ROCProfiler Tool can be configured to load a specific library that supports + * the user desired format. + * + * The API is not thread safe. It is the responsibility of the ROCProfiler Tool + * to ensure the operations are synchronized and not called concurrently. There + * is no requirement for the ROCProfiler Tool to report trace data in any + * specific order. If the format supported by plugin requires specific + * ordering, it is the responsibility of the plugin implementation to perform + * any necessary sorting. + */ + +/** + * \file + * ROCProfiler Tool Plugin API interface. + */ + +#ifndef ROCPROFILER_PLUGIN_H_ +#define ROCPROFILER_PLUGIN_H_ + +#include + +#include "rocprofiler.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** \defgroup rocprofiler_plugins ROCProfiler Plugin API Specification + * @{ + */ + +/** \defgroup initialization_group Initialization and Finalization + * \ingroup rocprofiler_plugins + * + * The ROCProfiler Plugin API must be initialized before using any of the + * operations to report trace data, and finalized after the last trace data has + * been reported. + * + * @{ + */ + +/** + * Initialize plugin. + * Must be called before any other operation. + * + * @param[in] rocprofiler_major_version The major version of the ROCProfiler API + * being used by the ROCProfiler Tool. An error is reported if this does not + * match the major version of the ROCProfiler API used to build the plugin + * library. This ensures compatibility of the trace data format. + * @param[in] rocprofiler_minor_version The minor version of the ROCProfiler API + * being used by the ROCProfiler Tool. An error is reported if the + * \p rocprofiler_major_version matches and this is greater than the minor + * version of the ROCProfiler API used to build the plugin library. This ensures + * compatibility of the trace data format. + * @param[in] data Pointer to the data passed to the ROCProfiler Plugin by the tool + * @return Returns 0 on success and -1 on error. + */ +ROCPROFILER_EXPORT int +rocprofiler_plugin_initialize(uint32_t rocprofiler_major_version, + uint32_t rocprofiler_minor_version, + void* data); + +/** + * Finalize plugin. + * This must be called after ::rocprofiler_plugin_initialize and after all + * profiling data has been reported by + * ::rocprofiler_plugin_write_kernel_records + */ +ROCPROFILER_EXPORT void +rocprofiler_plugin_finalize(); + +/** @} */ + +/** \defgroup profiling_record_write_functions Profiling data reporting + * \ingroup rocprofiler_plugins + * Operations to output profiling data. + * @{ + */ + +// TODO(aelwazir): Recheck wording of the description + +/** + * Report Buffer Records. + * + * @param[in] begin Pointer to the first record. + * @param[in] end Pointer to one past the last record. + * @param[in] session_id Session ID + * @param[in] buffer_id Buffer ID + * @return Returns 0 on success and -1 on error. + */ +ROCPROFILER_EXPORT int +rocprofiler_plugin_write_buffer_records(const rocprofiler_record_header_t* begin, + const rocprofiler_record_header_t* end, + rocprofiler_session_id_t session_id, + rocprofiler_buffer_id_t buffer_id); + +/** + * Report Synchronous Record. + * + * @param[in] record Synchronous Tracer record. + * @param[in] data : api_data + * @param[in] tracer_data :Tracer record extra data such as function name and kernel name + * @return Returns 0 on success and -1 on error. + */ + +ROCPROFILER_EXPORT int +rocprofiler_plugin_write_record(rocprofiler_record_tracer_t record); + +/** @} */ + +/** @} */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* ROCPROFILER_PLUGIN_H_ */ diff --git a/source/lib/CMakeLists.txt b/source/lib/CMakeLists.txt new file mode 100644 index 0000000000..55657945f0 --- /dev/null +++ b/source/lib/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# +# +add_subdirectory(common) +add_subdirectory(rocprofiler) +add_subdirectory(plugins) + +if(ROCPROFILER_BUILD_TESTS) + add_subdirectory(tests) +endif() diff --git a/source/lib/common/CMakeLists.txt b/source/lib/common/CMakeLists.txt new file mode 100644 index 0000000000..634f1aab7c --- /dev/null +++ b/source/lib/common/CMakeLists.txt @@ -0,0 +1,26 @@ +set(common_sources ${CMAKE_CURRENT_LIST_DIR}/config.cpp + ${CMAKE_CURRENT_LIST_DIR}/helper.cpp) + +set(common_headers + ${CMAKE_CURRENT_LIST_DIR}/config.hpp ${CMAKE_CURRENT_LIST_DIR}/defines.hpp + ${CMAKE_CURRENT_LIST_DIR}/environment.hpp ${CMAKE_CURRENT_LIST_DIR}/join.hpp + ${CMAKE_CURRENT_LIST_DIR}/log.hpp ${CMAKE_CURRENT_LIST_DIR}/helper.hpp) + +add_library(rocprofiler-common-library STATIC) +add_library(rocprofiler::rocprofiler-common-library ALIAS rocprofiler-common-library) + +add_subdirectory(container) + +target_sources(rocprofiler-common-library PRIVATE ${common_sources} ${common_headers}) +target_include_directories(rocprofiler-common-library + PUBLIC $) + +target_link_libraries( + rocprofiler-common-library + PUBLIC rocprofiler::rocprofiler-amd-comgr + $ + $ + $ + $) +set_target_properties(rocprofiler-common-library PROPERTIES OUTPUT_NAME + rocprofiler-common) diff --git a/source/lib/common/config.cpp b/source/lib/common/config.cpp new file mode 100644 index 0000000000..6ca1fb68d3 --- /dev/null +++ b/source/lib/common/config.cpp @@ -0,0 +1,433 @@ +// Copyright (c) 2023 Advanced Micro Devices, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN +// THE SOFTWARE. +// + +#include "lib/common/config.hpp" +#include "lib/common/environment.hpp" +#include "lib/common/join.hpp" +#include "lib/common/log.hpp" +#include "lib/common/helper.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace rocprofiler +{ +namespace common +{ +namespace +{ +std::time_t* launch_time = new std::time_t{std::time(nullptr)}; + +std::vector +read_command_line(pid_t _pid) +{ + auto _cmdline = std::vector{}; + auto fcmdline = std::stringstream{}; + fcmdline << "/proc/" << _pid << "/cmdline"; + auto ifs = std::ifstream{fcmdline.str().c_str()}; + if(ifs) + { + char cstr; + std::string sarg; + while(!ifs.eof()) + { + ifs >> cstr; + if(!ifs.eof()) + { + if(cstr != '\0') + { + sarg += cstr; + } + else + { + _cmdline.push_back(sarg); + sarg = ""; + } + } + } + ifs.close(); + } + + return _cmdline; +} + +std::string +get_local_datetime(const char* dt_format, std::time_t* dt_curr) +{ + char mbstr[512]; + if(!dt_curr) dt_curr = launch_time; + + if(std::strftime(mbstr, sizeof(mbstr), dt_format, std::localtime(dt_curr)) != 0) + return std::string{mbstr}; + return std::string{}; +} + +inline bool +not_is_space(int ch) +{ + return std::isspace(ch) == 0; +} + +inline std::string +ltrim(std::string s, bool (*f)(int) = not_is_space) +{ + s.erase(s.begin(), std::find_if(s.begin(), s.end(), f)); + return s; +} + +inline std::string +rtrim(std::string s, bool (*f)(int) = not_is_space) +{ + s.erase(std::find_if(s.rbegin(), s.rend(), f).base(), s.end()); + return s; +} + +inline std::string +trim(std::string s, bool (*f)(int) = not_is_space) +{ + ltrim(s, f); + rtrim(s, f); + return s; +} + +inline std::vector +get_siblings(pid_t _id = getppid()) +{ + auto _data = std::vector{}; + + std::ifstream _ifs{"/proc/" + std::to_string(_id) + "/task/" + std::to_string(_id) + + "/children"}; + while(_ifs) + { + pid_t _n = 0; + _ifs >> _n; + if(!_ifs || _n <= 0) break; + _data.emplace_back(_n); + } + return _data; +} + +inline auto +get_num_siblings(pid_t _id = getppid()) +{ + return get_siblings(_id).size(); +} +} // namespace + +int +get_mpi_size() +{ + static int _v = get_env("OMPI_COMM_WORLD_SIZE", + get_env("MV2_COMM_WORLD_SIZE", get_env("MPI_SIZE", 0))); + return _v; +} + +int +get_mpi_rank() +{ + static int _v = get_env("OMPI_COMM_WORLD_RANK", + get_env("MV2_COMM_WORLD_RANK", get_env("MPI_RANK", -1))); + return _v; +} + +std::vector +output_keys(std::string _tag) +{ + using strpair_t = std::pair; + + auto _cmdline = read_command_line(getpid()); + + if(_tag.empty() && !_cmdline.empty()) _tag = ::basename(_cmdline.front().c_str()); + + std::string _argv_string = {}; // entire argv cmd + std::string _args_string = {}; // cmdline args + std::string _argt_string = _tag; // prefix + cmdline args + const std::string& _tag0_string = _tag; // only the basic prefix + auto _options = std::vector{}; + + auto _replace = [](auto& _v, const strpair_t& pitr) { + auto pos = std::string::npos; + while((pos = _v.find(pitr.first)) != std::string::npos) + _v.replace(pos, pitr.first.length(), pitr.second); + }; + + if(_cmdline.size() > 1 && _cmdline.at(1) == "--") _cmdline.erase(_cmdline.begin() + 1); + + for(auto& itr : _cmdline) + { + itr = trim(itr); + _replace(itr, {"/", "_"}); + while(!itr.empty() && itr.at(0) == '.') + itr = itr.substr(1); + while(!itr.empty() && itr.at(0) == '_') + itr = itr.substr(1); + } + + if(!_cmdline.empty()) + { + for(size_t i = 0; i < _cmdline.size(); ++i) + { + const auto _l = std::string{(i == 0) ? "" : "_"}; + auto _v = _cmdline.at(i); + _argv_string += _l + _v; + if(i > 0) + { + _argt_string += (i > 1) ? (_l + _v) : _v; + _args_string += (i > 1) ? (_l + _v) : _v; + } + } + } + + auto* _launch_time = launch_time; + auto _time_format = get_env("ROCP_TIME_FORMAT", "%F_%H.%M"); + + auto _mpi_size = get_env("OMPI_COMM_WORLD_SIZE", get_env("MV2_COMM_WORLD_SIZE", 0)); + auto _mpi_rank = get_env("OMPI_COMM_WORLD_RANK", get_env("MV2_COMM_WORLD_RANK", -1)); + + auto _dmp_size = join("", (_mpi_size) > 0 ? _mpi_size : 1); + auto _dmp_rank = join("", (_mpi_rank) > 0 ? _mpi_rank : 0); + auto _proc_id = join("", getpid()); + auto _parent_id = join("", getppid()); + auto _pgroup_id = join("", getpgid(getpid())); + auto _session_id = join("", getsid(getpid())); + auto _proc_size = join("", get_num_siblings()); + auto _pwd_string = get_env("PWD", "."); + auto _slurm_job_id = get_env("SLURM_JOB_ID", "0"); + auto _slurm_proc_id = get_env("SLURM_PROCID", _dmp_rank); + auto _launch_string = get_local_datetime(_time_format.c_str(), _launch_time); + + auto _uniq_id = _proc_id; + if(get_env("SLURM_PROCID", -1) >= 0) + { + _uniq_id = _slurm_proc_id; + } + else if(_mpi_size > 0 || _mpi_rank >= 0) + { + _uniq_id = _dmp_rank; + } + + for(auto&& itr : std::initializer_list{ + {"%argv%", _argv_string, "Entire command-line condensed into a single string"}, + {"%argt%", + _argt_string, + "Similar to `%argv%` except basename of first command line argument"}, + {"%args%", _args_string, "All command line arguments condensed into a single string"}, + {"%tag%", _tag0_string, "Basename of first command line argument"}}) + { + _options.emplace_back(itr); + } + + if(!_cmdline.empty()) + { + for(size_t i = 0; i < _cmdline.size(); ++i) + { + auto _v = _cmdline.at(i); + _options.emplace_back(join("", "%arg", i, "%"), _v, join("", "Argument #", i)); + } + } + + for(auto&& itr : std::initializer_list{ + {"%pid%", _proc_id, "Process identifier"}, + {"%ppid%", _parent_id, "Parent process identifier"}, + {"%pgid%", _pgroup_id, "Process group identifier"}, + {"%psid%", _session_id, "Process session identifier"}, + {"%psize%", _proc_size, "Number of sibling process"}, + {"%job%", _slurm_job_id, "SLURM_JOB_ID env variable"}, + {"%rank%", _slurm_proc_id, "MPI/UPC++ rank"}, + {"%size%", _dmp_size, "MPI/UPC++ size"}, + {"%nid%", _uniq_id, "%rank% if possible, otherwise %pid%"}, + {"%launch_time%", _launch_string, "Data and/or time of run according to time format"}, + }) + { + _options.emplace_back(itr); + } + + for(auto&& itr : std::initializer_list{ + {"%p", _proc_id, "Shorthand for %pid%"}, + {"%j", _slurm_job_id, "Shorthand for %job%"}, + {"%r", _slurm_proc_id, "Shorthand for %rank%"}, + {"%s", _dmp_size, "Shorthand for %size"}, + }) + { + _options.emplace_back(itr); + } + + return _options; +} + +std::string +format(std::string _fpath, const std::string& _tag) +{ + if(_fpath.find('%') == std::string::npos && _fpath.find('$') == std::string::npos) + return _fpath; + + auto _replace = [](auto& _v, const output_key& pitr) { + auto pos = std::string::npos; + while((pos = _v.find(pitr.key)) != std::string::npos) + _v.replace(pos, pitr.key.length(), pitr.value); + }; + + for(auto&& itr : output_keys(_tag)) + _replace(_fpath, itr); + + // environment and configuration variables + try + { + for(const auto& _expr : {std::string{"(.*)%(env|ENV)\\{([A-Z0-9_]+)\\}%(.*)"}, + std::string{"(.*)\\$(env|ENV)\\{([A-Z0-9_]+)\\}(.*)"}}) + { + std::regex _re{_expr}; + std::string _cbeg = (_expr.find("(.*)%") == 0) ? "%" : "$"; + std::string _cend = (_expr.find("(.*)%") == 0) ? "}%" : "}"; + bool _is_env = (_expr.find("(env|ENV)") != std::string::npos); + _cbeg += (_is_env) ? "env{" : "cfg{"; + while(std::regex_search(_fpath, _re)) + { + auto _var = std::regex_replace(_fpath, _re, "$3"); + std::string _val = {}; + if(_is_env) + { + _val = get_env(_var, ""); + } + auto _beg = std::regex_replace(_fpath, _re, "$1"); + auto _end = std::regex_replace(_fpath, _re, "$4"); + _fpath = join("", _beg, _val, _end); + } + } + } catch(std::exception& _e) + { + fprintf(stderr, + "%s[rocprofiler][%s:%i] %s threw exception :: %s\n%s", + log::color::dmesg(), + __FILE__, + __LINE__, + __FUNCTION__, + _e.what(), + log::color::end()); + } + + // remove %arg% where N >= argc + try + { + std::regex _re{"(.*)%(arg[0-9]+)%([-/_]*)(.*)"}; + while(std::regex_search(_fpath, _re)) + _fpath = std::regex_replace(_fpath, _re, "$1$4"); + } catch(std::exception& _e) + { + fprintf(stderr, + "%s[rocprofiler][%s:%i] %s threw exception :: %s\n%s", + log::color::dmesg(), + __FILE__, + __LINE__, + __FUNCTION__, + _e.what(), + log::color::end()); + } + + return _fpath; +} + +std::string +compose_filename(const config& _cfg) +{ + auto _output_path = _cfg.output_path; + auto _output_file = _cfg.output_file; + auto _output_ext = _cfg.output_ext; + + if(_output_path.empty()) _output_path = "."; + if(_cfg.mpi_size > 0) + { + if(_cfg.mpi_rank >= 0) + { + _output_file = join('.', _output_file, _cfg.mpi_rank); + } + else + { + _output_file = join('.', _output_file, getpid()); + } + } + if(!_output_ext.empty()) + { + if(_output_ext.find('.') == std::string::npos) _output_ext.insert(0, "."); + if(_output_file.length() < _output_ext.length() || + _output_file.find(_output_ext) != _output_file.length() - _output_ext.length()) + _output_file += _output_ext; + } + + // join / and replace any keys with values + auto _prefix = format(std::filesystem::path{_output_path} / _output_file); + + // return on empty + if(_prefix.empty()) return std::string{}; + + // get the absolute path + auto _fname = std::filesystem::absolute(std::filesystem::path{_prefix}); + + // create the directory if necessary + auto _fname_path = _fname.parent_path(); + if(!std::filesystem::exists(_fname_path)) + std::filesystem::create_directories(_fname.parent_path()); + + return _fname.string(); +} + +std::string +format_name(std::string_view _name, const config& _cfg) +{ + if(_cfg.demangle && _cfg.truncate) + { + return truncate_name(cxx_demangle(_name)); + } + + if(_cfg.demangle) + { + return cxx_demangle(_name); + } + + if(_cfg.truncate) + { + return truncate_name(_name); + } + + return std::string{_name}; +} + +void +initialize() +{ + (void) get_config(); +} + +output_key::output_key(std::string _key, std::string _val, std::string _desc) +: key{std::move(_key)} +, value{std::move(_val)} +, description{std::move(_desc)} +{} +} // namespace common +} // namespace rocprofiler diff --git a/source/lib/common/config.hpp b/source/lib/common/config.hpp new file mode 100644 index 0000000000..55c0ea254c --- /dev/null +++ b/source/lib/common/config.hpp @@ -0,0 +1,99 @@ +// Copyright (c) 2023 Advanced Micro Devices, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN +// THE SOFTWARE. +// + +#pragma once + +#include "lib/common/environment.hpp" + +#include +#include + +namespace rocprofiler +{ +namespace common +{ +enum class config_context +{ + global = 0, + att_plugin, + cli_plugin, + ctf_plugin, + file_plugin, + perfetto_plugin, +}; + +int +get_mpi_size(); +int +get_mpi_rank(); + +struct config +{ + bool demangle = get_env("ROCP_DEMANGLE_KERNELS", true); + bool truncate = get_env("ROCP_TRUNCATE_KERNELS", false); + int mpi_size = get_mpi_size(); + int mpi_rank = get_mpi_rank(); + std::string output_path = get_env("ROCP_OUTPUT_PATH", "."); + std::string output_file = get_env("ROCP_OUTPUT_FILE", "results"); + std::string output_ext = {}; +}; + +template +config& +get_config() +{ + if constexpr(ContextT == config_context::global) + { + static auto _v = config{}; + return _v; + } + else + { + // context specific config copied from global config + static auto _v = get_config(); + return _v; + } +} + +struct output_key +{ + output_key(std::string _key, std::string _val, std::string _desc = {}); + + operator std::pair() const; + + std::string key = {}; + std::string value = {}; + std::string description = {}; +}; + +std::vector +output_keys(std::string _tag = {}); +std::string +compose_filename(const config&); +std::string +format(std::string _fpath, const std::string& _tag = {}); +std::string +format_name(std::string_view _name, const config& = get_config<>()); + +void +initialize(); +} // namespace common +} // namespace rocprofiler diff --git a/source/lib/common/container/CMakeLists.txt b/source/lib/common/container/CMakeLists.txt new file mode 100644 index 0000000000..2e2ade4d04 --- /dev/null +++ b/source/lib/common/container/CMakeLists.txt @@ -0,0 +1,10 @@ +# +set(containers_sources) + +set(containers_headers atomic_ring_buffer.hpp c_array.hpp operators.hpp ring_buffer.hpp + stable_vector.hpp static_vector.hpp) + +set(containers_sources atomic_ring_buffer.cpp ring_buffer.cpp) + +target_sources(rocprofiler-common-library PRIVATE ${containers_sources} + ${containers_headers}) diff --git a/source/lib/common/container/atomic_ring_buffer.cpp b/source/lib/common/container/atomic_ring_buffer.cpp new file mode 100644 index 0000000000..c209077e09 --- /dev/null +++ b/source/lib/common/container/atomic_ring_buffer.cpp @@ -0,0 +1,297 @@ +// MIT License +// +// Copyright (c) 2020, The Regents of the University of California, +// through Lawrence Berkeley National Laboratory (subject to receipt of any +// required approvals from the U.S. Dept. of Energy). All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN THE +// SOFTWARE. + +#include "atomic_ring_buffer.hpp" +#include "lib/common/units.hpp" +#include "lib/common/environment.hpp" + +#include +#include +#include +#include +#include +#include +#include + +namespace rocprofiler +{ +namespace common +{ +namespace container +{ +namespace base +{ +atomic_ring_buffer::atomic_ring_buffer(size_t _size, bool _use_mmap) +{ + set_use_mmap(_use_mmap); + init(_size); +} + +atomic_ring_buffer::~atomic_ring_buffer() { destroy(); } + +atomic_ring_buffer::atomic_ring_buffer(const atomic_ring_buffer& rhs) +: m_use_mmap{rhs.m_use_mmap} +, m_use_mmap_explicit{rhs.m_use_mmap_explicit} +{ + init(rhs.m_size); +} + +atomic_ring_buffer::atomic_ring_buffer(atomic_ring_buffer&& rhs) noexcept +: m_init{rhs.m_init} +, m_use_mmap{rhs.m_use_mmap} +, m_use_mmap_explicit{rhs.m_use_mmap_explicit} +, m_ptr{rhs.m_ptr} +, m_size{rhs.m_size} +, m_read_count{rhs.m_read_count.load()} +, m_write_count{rhs.m_write_count.load()} +{ + rhs.reset(); +} + +atomic_ring_buffer& +atomic_ring_buffer::operator=(const atomic_ring_buffer& rhs) +{ + if(this == &rhs) return *this; + destroy(); + m_use_mmap = rhs.m_use_mmap; + m_use_mmap_explicit = rhs.m_use_mmap_explicit; + init(rhs.m_size); + return *this; +} + +atomic_ring_buffer& +atomic_ring_buffer::operator=(atomic_ring_buffer&& rhs) noexcept +{ + if(this == &rhs) return *this; + destroy(); + m_init = rhs.m_init; + m_use_mmap = rhs.m_use_mmap; + m_use_mmap_explicit = rhs.m_use_mmap_explicit; + m_ptr = rhs.m_ptr; + m_size = rhs.m_size; + m_read_count = rhs.m_read_count.load(); + m_write_count = rhs.m_write_count.load(); + rhs.reset(); + return *this; +} + +void +atomic_ring_buffer::init(size_t _size) +{ + if(m_init) + throw std::runtime_error( + "tim::base::atomic_ring_buffer::init(size_t) :: already initialized"); + + m_init = true; + + // Round up to multiple of page size. + _size += units::get_page_size() - ((_size % units::get_page_size() > 0) + ? (_size % units::get_page_size()) + : units::get_page_size()); + + if((_size % units::get_page_size()) > 0) + { + std::ostringstream _oss{}; + _oss << "Error! size is not a multiple of page size: " << _size << " % " + << units::get_page_size() << " = " << (_size % units::get_page_size()); + throw std::runtime_error(_oss.str()); + } + + m_size = _size; + m_read_count = 0; + m_write_count = 0; + + if(!m_use_mmap_explicit) m_use_mmap = get_env("ROCPROFILER_USE_MMAP", m_use_mmap); + + if(!m_use_mmap) + { + m_ptr = malloc(m_size * sizeof(char)); + return; + } + + // Map twice the buffer size. + if((m_ptr = + mmap(nullptr, m_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)) == + MAP_FAILED) + { + destroy(); + auto _err = errno; + // TIMEMORY_PRINTF_FATAL(stderr, "Error using mmap: %s\n", strerror(_err)); + throw std::runtime_error(strerror(_err)); + } +} + +void +atomic_ring_buffer::destroy() +{ + if(m_ptr && m_init) + { + if(!m_use_mmap) + { + ::free(m_ptr); + } + else + { + // Unmap the mapped virtual memmory. + auto ret = munmap(m_ptr, m_size); + if(ret != 0) perror("munmap"); + } + } + m_init = false; + m_size = 0; + m_read_count = 0; + m_write_count = 0; + m_ptr = nullptr; +} + +void +atomic_ring_buffer::set_use_mmap(bool _v) +{ + if(m_init) + throw std::runtime_error("tim::base::atomic_ring_buffer::set_use_mmap(bool) cannot be " + "called after initialization"); + m_use_mmap = _v; + m_use_mmap_explicit = true; +} + +std::string +atomic_ring_buffer::as_string() const +{ + std::ostringstream ss{}; + ss << std::boolalpha << "is_initialized: " << is_initialized() << ", capacity: " << capacity() + << ", count: " << count() << ", free: " << free() << ", is_empty: " << is_empty() + << ", is_full: " << is_full() << ", pointer: " << m_ptr << ", read count: " << m_read_count + << ", write count: " << m_write_count; + return ss.str(); +} +// + +void* +atomic_ring_buffer::request(size_t _length) +{ + if(m_ptr == nullptr || m_size == 0) return nullptr; + + if(is_full()) return retrieve(_length); + + // if write count is at the tail of buffer, bump to the end of buffer + size_t _write_count = 0; + size_t _offset = 0; + do + { + // Make sure we don't put in more than there's room for, by writing no + // more than there is free. + if(_length > free()) return nullptr; + + _offset = 0; + _write_count = m_write_count.load(); + auto _modulo = m_size - (_write_count % m_size); + if(_modulo < _length) _offset = _modulo; + } while(!m_write_count.compare_exchange_strong( + _write_count, _write_count + _length + _offset, std::memory_order_seq_cst)); + + // pointer in buffer + void* _out = write_ptr(_write_count); + + return _out; +} +// + +void* +atomic_ring_buffer::retrieve(size_t _length) const +{ + if(m_ptr == nullptr || m_size == 0) return nullptr; + + // Make sure we don't put in more than there's room for, by writing no + // more than there is free. + + // if read count is at the tail of buffer, bump to the end of buffer + size_t _read_count = 0; + size_t _offset = 0; + do + { + if(_length > count()) return nullptr; + _offset = 0; + _read_count = m_read_count.load(); + auto _modulo = m_size - (_read_count % m_size); + if(_modulo < _length) _offset = _modulo; + } while(!m_read_count.compare_exchange_strong( + _read_count, _read_count + _length + _offset, std::memory_order_seq_cst)); + + // pointer in buffer + void* _out = read_ptr(_read_count); + + return _out; +} +// + +void +atomic_ring_buffer::reset() +{ + m_init = false; + m_size = 0; + m_ptr = nullptr; + m_read_count.store(0); + m_write_count.store(0); +} +// + +void +atomic_ring_buffer::save(std::fstream& _fs) +{ + auto _read_count = m_read_count.load(); + auto _write_count = m_write_count.load(); + _fs.write(reinterpret_cast(&m_use_mmap), sizeof(m_use_mmap)); + _fs.write(reinterpret_cast(&m_use_mmap_explicit), sizeof(m_use_mmap_explicit)); + _fs.write(reinterpret_cast(&m_size), sizeof(m_size)); + _fs.write(reinterpret_cast(&_read_count), sizeof(_read_count)); + _fs.write(reinterpret_cast(&_write_count), sizeof(_write_count)); + _fs.write(reinterpret_cast(m_ptr), m_size * sizeof(char)); +} +// + +void +atomic_ring_buffer::load(std::fstream& _fs) +{ + destroy(); + size_t _read_count = 0; + size_t _write_count = 0; + + _fs.read(reinterpret_cast(&m_use_mmap), sizeof(m_use_mmap)); + _fs.read(reinterpret_cast(&m_use_mmap_explicit), sizeof(m_use_mmap_explicit)); + _fs.read(reinterpret_cast(&m_size), sizeof(m_size)); + + init(m_size); + if(!m_ptr) m_ptr = malloc(m_size); + + _fs.read(reinterpret_cast(&_read_count), sizeof(_read_count)); + _fs.read(reinterpret_cast(&_write_count), sizeof(_write_count)); + _fs.read(reinterpret_cast(m_ptr), m_size * sizeof(char)); + + m_read_count.store(_read_count); + m_write_count.store(_write_count); +} +} // namespace base +} // namespace container +} // namespace common +} // namespace rocprofiler diff --git a/source/lib/common/container/atomic_ring_buffer.hpp b/source/lib/common/container/atomic_ring_buffer.hpp new file mode 100644 index 0000000000..b2009133e2 --- /dev/null +++ b/source/lib/common/container/atomic_ring_buffer.hpp @@ -0,0 +1,426 @@ +// MIT License +// +// Copyright (c) 2020, The Regents of the University of California, +// through Lawrence Berkeley National Laboratory (subject to receipt of any +// required approvals from the U.S. Dept. of Energy). All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN THE +// SOFTWARE. + +#pragma once + +#include "lib/common/units.hpp" +#include "lib/common/environment.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace rocprofiler +{ +namespace common +{ +namespace container +{ +template +struct atomic_ring_buffer; +// +namespace base +{ +/// \struct tim::base::atomic_ring_buffer +/// \brief Ring buffer implementation, with support for mmap as backend (Linux only). +struct atomic_ring_buffer +{ + template + friend struct container::atomic_ring_buffer; + + atomic_ring_buffer() = default; + explicit atomic_ring_buffer(bool _use_mmap) { set_use_mmap(_use_mmap); } + explicit atomic_ring_buffer(size_t _size) { init(_size); } + atomic_ring_buffer(size_t _size, bool _use_mmap); + + ~atomic_ring_buffer(); + + atomic_ring_buffer(const atomic_ring_buffer&); + atomic_ring_buffer& operator=(const atomic_ring_buffer&); + + atomic_ring_buffer(atomic_ring_buffer&&) noexcept; + atomic_ring_buffer& operator=(atomic_ring_buffer&&) noexcept; + + /// Returns whether the buffer has been allocated + bool is_initialized() const { return m_init; } + + /// Get the total number of bytes supported + size_t capacity() const { return m_size; } + + /// Creates new ring buffer. + void init(size_t size); + + /// Destroy ring buffer. + void destroy(); + + /// Request a pointer for writing at least \param n bytes. + void* request(size_t n); + + /// Retrieve a pointer for reading at least \param n bytes. + void* retrieve(size_t n) const; + + /// Write class-type data to buffer (uses placement new). + template + std::pair write(Tp* in, std::enable_if_t::value, int> = 0); + + /// Write non-class-type data to buffer (uses memcpy). + template + std::pair write(Tp* in, std::enable_if_t::value, int> = 0); + + /// Request a pointer to an allocation. This is similar to a "write" except the + /// memory is uninitialized. Typically used by allocators. If Tp is a class type, + /// be sure to use a placement new instead of a memcpy. + template + Tp* request(); + + /// Read class-type data from buffer (uses placement new). + template + std::pair read(Tp* _dest, + std::enable_if_t::value, int> = 0) const; + + /// Read non-class-type data from buffer (uses memcpy). + template + std::pair read(Tp* _dest, + std::enable_if_t::value, int> = 0) const; + + /// Retrieve a pointer to the head allocation (read). + template + Tp* retrieve() const; + + /// Returns number of bytes currently held by the buffer. + size_t count() const { return (m_write_count - m_read_count); } + + /// Returns how many bytes are availiable in the buffer. + size_t free() const { return (m_size - count()); } + + /// Returns if the buffer is empty. + bool is_empty() const { return (count() == 0); } + + /// Returns if the buffer is full. + bool is_full() const { return (count() == m_size); } + + /// explicitly configure to use mmap if avail + void set_use_mmap(bool); + + /// query whether using mmap + bool get_use_mmap() const { return m_use_mmap; } + + std::string as_string() const; + + void save(std::fstream& _fs); + void load(std::fstream& _fs); + +private: + /// Returns the current write pointer. + void* write_ptr(size_t _write_count) const + { + return static_cast(m_ptr) + (_write_count % m_size); + } + + /// Returns the current read pointer. + void* read_ptr(size_t _read_count) const + { + return static_cast(m_ptr) + (_read_count % m_size); + } + + void reset(); + +private: + bool m_init = false; + bool m_use_mmap = true; + bool m_use_mmap_explicit = false; + void* m_ptr = nullptr; + size_t m_size = 0; + mutable std::atomic m_read_count = 0; + std::atomic m_write_count = 0; +}; +// +template +std::pair +atomic_ring_buffer::write(Tp* in, std::enable_if_t::value, int>) +{ + if(in == nullptr || m_ptr == nullptr) return {0, nullptr}; + + auto _length = sizeof(Tp); + void* _out_p = request(_length); + + if(_out_p == nullptr) return {0, nullptr}; + + // Copy in. + new(_out_p) Tp{std::move(*in)}; + + // pointer in buffer + Tp* _out = reinterpret_cast(_out_p); + + return {_length, _out}; +} +// +template +std::pair +atomic_ring_buffer::write(Tp* in, std::enable_if_t::value, int>) +{ + if(in == nullptr || m_ptr == nullptr) return {0, nullptr}; + + auto _length = sizeof(Tp); + void* _out_p = request(_length); + + if(_out_p == nullptr) return {0, nullptr}; + + // Copy in. + memcpy(_out_p, in, _length); + + // pointer in buffer + Tp* _out = reinterpret_cast(_out_p); + + return {_length, _out}; +} +// +template +Tp* +atomic_ring_buffer::request() +{ + if(m_ptr == nullptr) return nullptr; + + return request(sizeof(Tp)); +} +// +template +std::pair +atomic_ring_buffer::read(Tp* _dest, std::enable_if_t::value, int>) const +{ + if(is_empty() || _dest == nullptr) return {0, nullptr}; + + auto _length = sizeof(Tp); + void* _out_p = retrieve(_length); + + if(_out_p == nullptr) return {0, nullptr}; + + // pointer in buffer + Tp* in = reinterpret_cast(_out_p); + + // Copy out for BYTE, nothing magic here. + *_dest = *in; + + return {_length, in}; +} +// +template +std::pair +atomic_ring_buffer::read(Tp* _dest, std::enable_if_t::value, int>) const +{ + if(is_empty() || _dest == nullptr) return {0, nullptr}; + + auto _length = sizeof(Tp); + void* _out_p = retrieve(_length); + + if(_out_p == nullptr) return {0, nullptr}; + + // pointer in buffer + Tp* in = reinterpret_cast(_out_p); + + using Up = typename std::remove_const::type; + + // Copy out for BYTE, nothing magic here. + Up* _out = const_cast(_dest); + memcpy(_out, in, _length); + + return {_length, in}; +} +// +template +Tp* +atomic_ring_buffer::retrieve() const +{ + if(m_ptr == nullptr) return nullptr; + + return retrieve(sizeof(Tp)); +} +// +} // namespace base +// +/// \struct tim::data_storage::atomic_ring_buffer +/// \brief Ring buffer wrapper around \ref tim::base::atomic_ring_buffer for data of type +/// Tp. If the data object size is larger than the page size (typically 4KB), behavior is +/// undefined. During initialization, one requests a minimum number of objects and the +/// buffer will support that number of object + the remainder of the page, e.g. if a page +/// is 1000 bytes, the object is 1 byte, and the buffer is requested to support 1500 +/// objects, then an allocation supporting 2000 objects (i.e. 2 pages) will be created. +template +struct atomic_ring_buffer : private base::atomic_ring_buffer +{ + using base_type = base::atomic_ring_buffer; + + static size_t get_items_per_page(); + + atomic_ring_buffer() = default; + ~atomic_ring_buffer() = default; + + explicit atomic_ring_buffer(bool _use_mmap) + : base_type{_use_mmap} + {} + + explicit atomic_ring_buffer(size_t _size) + : base_type{_size * sizeof(Tp)} + {} + + atomic_ring_buffer(size_t _size, bool _use_mmap) + : base_type{_size * sizeof(Tp), _use_mmap} + {} + + atomic_ring_buffer(const atomic_ring_buffer&); + atomic_ring_buffer(atomic_ring_buffer&&) noexcept = default; + + atomic_ring_buffer& operator=(const atomic_ring_buffer&); + atomic_ring_buffer& operator=(atomic_ring_buffer&&) noexcept = default; + + /// Returns whether the buffer has been allocated + bool is_initialized() const { return base_type::is_initialized(); } + + /// Get the total number of Tp instances supported + size_t capacity() const { return (base_type::capacity()) / sizeof(Tp); } + + /// Creates new ring buffer. + void init(size_t _size) { base_type::init(_size * sizeof(Tp)); } + + /// Destroy ring buffer. + void destroy() { base_type::destroy(); } + + /// Write data to buffer. + size_t data_size() const { return sizeof(Tp); } + + /// Write data to buffer. Return pointer to location of write + Tp* write(Tp* in) { return base_type::write(in).second; } + + /// Read data from buffer. Return pointer to location of read + Tp* read(Tp* _dest) const { return base_type::read(_dest).second; } + + /// Get an uninitialized address at tail of buffer. + Tp* request() { return base_type::request(); } + + /// Read data from head of buffer. + Tp* retrieve() { return base_type::retrieve(); } + + /// Returns number of Tp instances currently held by the buffer. + size_t count() const { return (base_type::count()) / sizeof(Tp); } + + /// Returns how many Tp instances are availiable in the buffer. + size_t free() const { return (base_type::free()) / sizeof(Tp); } + + /// Returns if the buffer is empty. + bool is_empty() const { return base_type::is_empty(); } + + /// Returns if the buffer is full. + bool is_full() const { return (base_type::free() < sizeof(Tp)); } + + template + auto emplace(Args&&... args) + { + Tp _obj{std::forward(args)...}; + return write(&_obj); + } + + using base_type::get_use_mmap; + using base_type::load; + using base_type::save; + using base_type::set_use_mmap; + + std::string as_string() const + { + std::ostringstream ss{}; + size_t _w = std::log10(base_type::capacity()) + 1; + ss << std::boolalpha << std::right << "data size: " << std::setw(_w) << data_size() + << " B, is_initialized: " << std::setw(5) << is_initialized() + << ", is_empty: " << std::setw(5) << is_empty() << ", is_full: " << std::setw(5) + << is_full() << ", capacity: " << std::setw(_w) << capacity() + << ", count: " << std::setw(_w) << count() << ", free: " << std::setw(_w) << free() + << ", raw capacity: " << std::setw(_w) << base_type::capacity() + << " B, raw count: " << std::setw(_w) << base_type::count() + << " B, raw free: " << std::setw(_w) << base_type::free() + << " B, pointer: " << std::setw(15) << base_type::m_ptr + << ", raw read count: " << std::setw(_w) << base_type::m_read_count + << ", raw write count: " << std::setw(_w) << base_type::m_write_count; + return ss.str(); + } + + friend std::ostream& operator<<(std::ostream& os, const atomic_ring_buffer& obj) + { + return os << obj.as_string(); + } +}; +// +template +size_t +atomic_ring_buffer::get_items_per_page() +{ + return std::max(units::get_page_size() / sizeof(Tp), 1); +} +// +template +atomic_ring_buffer::atomic_ring_buffer(const atomic_ring_buffer& rhs) +: base_type{rhs} +{ + size_t _n = rhs.count(); + char* _end = static_cast(rhs.m_ptr) + rhs.m_size; + for(size_t i = 0; i < _n; ++i) + { + char* _addr = static_cast(rhs.read_ptr(m_read_count)) + (i * sizeof(Tp)); + if((_addr + sizeof(Tp)) > _end) _addr = static_cast(rhs.m_ptr); + Tp* _in = static_cast(static_cast(_addr)); + write(_in); + } +} +// +template +atomic_ring_buffer& +atomic_ring_buffer::operator=(const atomic_ring_buffer& rhs) +{ + if(this == &rhs) return *this; + + base_type::operator=(rhs); + size_t _n = rhs.count(); + char* _end = static_cast(rhs.m_ptr) + rhs.m_size; + for(size_t i = 0; i < _n; ++i) + { + char* _addr = static_cast(rhs.read_ptr(m_read_count)) + (i * sizeof(Tp)); + if((_addr + sizeof(Tp)) > _end) _addr = static_cast(rhs.m_ptr); + Tp* _in = static_cast(static_cast(_addr)); + write(_in); + } + + return *this; +} +// +} // namespace container +} // namespace common +} // namespace rocprofiler diff --git a/source/lib/common/container/c_array.hpp b/source/lib/common/container/c_array.hpp new file mode 100644 index 0000000000..ea856bd1a0 --- /dev/null +++ b/source/lib/common/container/c_array.hpp @@ -0,0 +1,136 @@ +// MIT License +// +// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN THE +// SOFTWARE. + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace rocprofiler +{ +namespace common +{ +namespace container +{ +template +struct c_array +{ + // Construct an array wrapper from a base pointer and array size + c_array(Tp* _base, size_t _size) + : m_base{_base} + , m_size{_size} + {} + + ~c_array() = default; + c_array(const c_array&) = default; + c_array& operator=(const c_array&) = default; + c_array& operator=(c_array&&) noexcept = default; + + // Get the size of the wrapped array + size_t size() const { return m_size; } + + // Access an element by index + Tp& operator[](size_t i) { return m_base[i]; } + + // Access an element by index + const Tp& operator[](size_t i) const { return m_base[i]; } + + // Access an element by index with bounds check + Tp& at(size_t i) + { + if(i < m_size) return m_base[i]; + throw std::out_of_range(std::string{typeid(*this).name()} + std::to_string(i) + + " exceeds size " + std::to_string(m_size)); + } + + // Access an element by index with bounds check + const Tp& at(size_t i) const + { + if(i < m_size) return m_base[i]; + throw std::out_of_range(std::string{typeid(*this).name()} + std::to_string(i) + + " exceeds size " + std::to_string(m_size)); + } + + // Get a slice of this array, from a start index (inclusive) to end index (exclusive) + c_array slice(size_t start, size_t end) { return c_array(&m_base[start], end - start); } + + void pop_front() + { + ++m_base; + --m_size; + } + + void pop_back() { --m_size; } + + operator Tp*() const { return m_base; } + + // Iterator class for convenient range-based for loop support + template + struct iterator + { + // Start the iterator at a given pointer + explicit iterator(Tp* p) + : m_ptr{p} + {} + + // Advance to the next element + void operator++() { ++m_ptr; } + void operator++(int) { m_ptr++; } + + // Get the current element + Up& operator*() const { return *m_ptr; } + + // Compare iterators + bool operator==(const iterator& rhs) const { return m_ptr == rhs.m_ptr; } + bool operator!=(const iterator& rhs) const { return m_ptr != rhs.m_ptr; } + + private: + Tp* m_ptr = nullptr; + }; + + // Get an iterator positioned at the beginning of the wrapped array + iterator begin() { return iterator{m_base}; } + iterator begin() const { return iterator{m_base}; } + + // Get an iterator positioned at the end of the wrapped array + iterator end() { return iterator{&m_base[m_size]}; } + iterator end() const { return iterator{&m_base[m_size]}; } + +private: + Tp* m_base = nullptr; + size_t m_size = 0; +}; + +// Function for automatic template argument deduction +template +c_array +wrap_c_array(Tp* base, size_t size) +{ + return c_array(base, size); +} +} // namespace container +} // namespace common +} // namespace rocprofiler diff --git a/source/lib/common/container/operators.hpp b/source/lib/common/container/operators.hpp new file mode 100644 index 0000000000..bf184b7b71 --- /dev/null +++ b/source/lib/common/container/operators.hpp @@ -0,0 +1,239 @@ +// MIT License +// +// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN THE +// SOFTWARE. + +#pragma once + +#include +#include + +#define ROCPROFILER_IMPORT_TEMPLATE2(template_name) +#define ROCPROFILER_IMPORT_TEMPLATE1(template_name) + +// Import a 2-type-argument operator template into boost (if necessary) and +// provide a specialization of 'is_chained_base<>' for it. +#define ROCPROFILER_OPERATOR_TEMPLATE2(template_name2) \ + ROCPROFILER_IMPORT_TEMPLATE2(template_name2) \ + template \ + struct is_chained_base<::rocprofiler::container::template_name2> \ + { \ + using value = ::rocprofiler::container::true_t; \ + }; + +// Import a 1-type-argument operator template into boost (if necessary) and +// provide a specialization of 'is_chained_base<>' for it. +#define ROCPROFILER_OPERATOR_TEMPLATE1(template_name1) \ + ROCPROFILER_IMPORT_TEMPLATE1(template_name1) \ + template \ + struct is_chained_base<::rocprofiler::container::template_name1> \ + { \ + using value = ::rocprofiler::container::true_t; \ + }; + +#define ROCPROFILER_OPERATOR_TEMPLATE(template_name) \ + template , \ + typename O = typename is_chained_base::value> \ + struct template_name; \ + \ + template \ + struct template_name : template_name##2 < T \ + , U \ + , B > \ + {}; \ + \ + template \ + struct template_name, true_t> : template_name##1 < T \ + , U > \ + {}; \ + \ + template \ + struct template_name : template_name##1 < T \ + , B > \ + {}; \ + \ + template \ + struct is_chained_base> \ + { \ + using value = ::rocprofiler::container::true_t; \ + }; \ + \ + ROCPROFILER_OPERATOR_TEMPLATE2(template_name##2) \ + ROCPROFILER_OPERATOR_TEMPLATE1(template_name##1) + +#define ROCPROFILER_BINARY_OPERATOR_COMMUTATIVE(NAME, OP) \ + template > \ + struct NAME##2 : B{friend T operator OP(T lhs, const U& rhs){return lhs OP## = rhs; \ + } \ + friend T operator OP(const U& lhs, T rhs) { return rhs OP## = lhs; } \ + } \ + ; \ + \ + template > \ + struct NAME##1 : B{friend T operator OP(T lhs, const T& rhs){return lhs OP## = rhs; \ + } \ + } \ + ; + +#define ROCPROFILER_BINARY_OPERATOR_NON_COMMUTATIVE(NAME, OP) \ + template > \ + struct NAME##2 : B{friend T operator OP(T lhs, const U& rhs){return lhs OP## = rhs; \ + } \ + } \ + ; + +namespace rocprofiler +{ +namespace common +{ +namespace container +{ +struct true_t +{}; + +struct false_t +{}; + +template +class empty_base +{}; + +template +struct is_chained_base +{ + using value = true_t; +}; + +ROCPROFILER_BINARY_OPERATOR_COMMUTATIVE(addable, +) +ROCPROFILER_BINARY_OPERATOR_NON_COMMUTATIVE(subtractable, -) + +ROCPROFILER_OPERATOR_TEMPLATE(addable) + +template > +struct incrementable : B +{ + friend T operator++(T& x, int) + { + incrementable_type nrv(x); + ++x; + return nrv; + } + +private: // The use of this typedef works around a Borland bug + typedef T incrementable_type; +}; + +template > +struct decrementable : B +{ + friend T operator--(T& x, int) + { + decrementable_type nrv(x); + --x; + return nrv; + } + +private: // The use of this typedef works around a Borland bug + typedef T decrementable_type; +}; + +template > +struct dereferenceable : B +{ + P operator->() const { return ::std::addressof(*static_cast(*this)); } +}; + +template > +struct indexable : B +{ + R operator[](I n) const { return *(static_cast(*this) + n); } +}; + +template > +struct equality_comparable1 : B +{ + friend bool operator!=(const T& x, const T& y) { return !static_cast(x == y); } +}; + +template > +struct input_iteratable : equality_comparable1>> +{}; + +template > +struct output_iteratable : incrementable +{}; + +template > +struct forward_iteratable : input_iteratable +{}; + +template > +struct bidirectional_iteratable : forward_iteratable> +{}; + +// template > +// struct subtractable2; + +template > +struct additive2 : addable2> +{}; + +template > +struct less_than_comparable1 : B +{ + friend bool operator>(const T& x, const T& y) { return y < x; } + friend bool operator<=(const T& x, const T& y) { return !static_cast(y < x); } + friend bool operator>=(const T& x, const T& y) { return !static_cast(x < y); } +}; + +// To avoid repeated derivation from equality_comparable, +// which is an indirect base typename of bidirectional_iterable, +// random_access_iteratable must not be derived from totally_ordered1 +// but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001) +template > +struct random_access_iteratable +: bidirectional_iteratable>>> +{}; + +template +struct iterator_helper +{ + using iterator_category = CategoryT; + using value_type = Tp; + using difference_type = DistanceT; + using pointer = PointerT; + using reference = ReferenceT; +}; + +template +struct random_access_iterator_helper +: random_access_iteratable> +{ + friend D requires_difference_operator(const T& x, const T& y) { return x - y; } +}; // random_access_iterator_helper +} // namespace container +} // namespace common +} // namespace rocprofiler diff --git a/source/lib/common/container/ring_buffer.cpp b/source/lib/common/container/ring_buffer.cpp new file mode 100644 index 0000000000..ff778a3b4d --- /dev/null +++ b/source/lib/common/container/ring_buffer.cpp @@ -0,0 +1,289 @@ +// MIT License +// +// Copyright (c) 2020, The Regents of the University of California, +// through Lawrence Berkeley National Laboratory (subject to receipt of any +// required approvals from the U.S. Dept. of Energy). All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN THE +// SOFTWARE. + +#include "ring_buffer.hpp" + +#include +#include +#include +#include +#include + +namespace rocprofiler +{ +namespace common +{ +namespace container +{ +namespace base +{ +ring_buffer::ring_buffer(size_t _size, bool _use_mmap) +{ + set_use_mmap(_use_mmap); + init(_size); +} + +ring_buffer::~ring_buffer() { destroy(); } + +ring_buffer::ring_buffer(const ring_buffer& rhs) +: m_use_mmap{rhs.m_use_mmap} +, m_use_mmap_explicit{rhs.m_use_mmap_explicit} +{ + init(rhs.m_size); +} + +ring_buffer::ring_buffer(ring_buffer&& rhs) noexcept +: m_init{rhs.m_init} +, m_use_mmap{rhs.m_use_mmap} +, m_use_mmap_explicit{rhs.m_use_mmap_explicit} +, m_ptr{rhs.m_ptr} +, m_size{rhs.m_size} +, m_read_count{rhs.m_read_count} +, m_write_count{rhs.m_write_count} +{ + rhs.reset(); +} + +ring_buffer& +ring_buffer::operator=(const ring_buffer& rhs) +{ + if(this == &rhs) return *this; + destroy(); + m_use_mmap = rhs.m_use_mmap; + m_use_mmap_explicit = rhs.m_use_mmap_explicit; + init(rhs.m_size); + return *this; +} + +ring_buffer& +ring_buffer::operator=(ring_buffer&& rhs) noexcept +{ + if(this == &rhs) return *this; + destroy(); + m_init = rhs.m_init; + m_use_mmap = rhs.m_use_mmap; + m_use_mmap_explicit = rhs.m_use_mmap_explicit; + m_ptr = rhs.m_ptr; + m_size = rhs.m_size; + m_read_count = rhs.m_read_count; + m_write_count = rhs.m_write_count; + rhs.reset(); + return *this; +} + +void +ring_buffer::init(size_t _size) +{ + if(m_init) + throw std::runtime_error("tim::base::ring_buffer::init(size_t) :: already initialized"); + + m_init = true; + + // Round up to multiple of page size. + _size += units::get_page_size() - ((_size % units::get_page_size() > 0) + ? (_size % units::get_page_size()) + : units::get_page_size()); + + if((_size % units::get_page_size()) > 0) + { + std::ostringstream _oss{}; + _oss << "Error! size is not a multiple of page size: " << _size << " % " + << units::get_page_size() << " = " << (_size % units::get_page_size()); + throw std::runtime_error(_oss.str()); + } + + m_size = _size; + m_read_count = 0; + m_write_count = 0; + + if(!m_use_mmap_explicit) m_use_mmap = get_env("ROCPROFILER_USE_MMAP", m_use_mmap); + + if(!m_use_mmap) + { + m_ptr = malloc(m_size * sizeof(char)); + return; + } + + // Map twice the buffer size. + if((m_ptr = + mmap(nullptr, m_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)) == + MAP_FAILED) + { + destroy(); + auto _err = errno; + // TIMEMORY_PRINTF_FATAL(stderr, "Error using mmap: %s\n", strerror(_err)); + throw std::runtime_error(strerror(_err)); + } +} + +void +ring_buffer::destroy() +{ + if(m_ptr && m_init) + { + if(!m_use_mmap) + { + ::free(m_ptr); + } + else + { + // Unmap the mapped virtual memmory. + auto ret = munmap(m_ptr, m_size); + if(ret != 0) perror("munmap"); + } + } + m_init = false; + m_size = 0; + m_read_count = 0; + m_write_count = 0; + m_ptr = nullptr; +} + +void +ring_buffer::set_use_mmap(bool _v) +{ + if(!m_init) + { + m_use_mmap = _v; + m_use_mmap_explicit = true; + } + else + { + throw std::runtime_error("tim::base::ring_buffer::set_use_mmap(bool) cannot be " + "called after initialization"); + } +} + +std::string +ring_buffer::as_string() const +{ + std::ostringstream ss{}; + ss << std::boolalpha << "is_initialized: " << is_initialized() << ", capacity: " << capacity() + << ", count: " << count() << ", free: " << free() << ", is_empty: " << is_empty() + << ", is_full: " << is_full() << ", pointer: " << m_ptr << ", read count: " << m_read_count + << ", write count: " << m_write_count; + return ss.str(); +} +// + +void* +ring_buffer::request(size_t _length) +{ + if(m_ptr == nullptr) return nullptr; + + // Make sure we don't put in more than there's room for, by writing no + // more than there is free. + if(_length > free()) + throw std::runtime_error("heap-buffer-overflow :: ring buffer is full. read data " + "to avoid data corruption"); + + // if write count is at the tail of buffer, bump to the end of buffer + auto _modulo = m_size - (m_write_count % m_size); + if(_modulo < _length) m_write_count += _modulo; + + // pointer in buffer + void* _out = write_ptr(); + + // Update write count + m_write_count += _length; + + return _out; +} +// + +void* +ring_buffer::retrieve(size_t _length) +{ + if(m_ptr == nullptr) return nullptr; + + // Make sure we don't put in more than there's room for, by writing no + // more than there is free. + if(_length > count()) throw std::runtime_error("ring buffer is empty"); + + // if read count is at the tail of buffer, bump to the end of buffer + auto _modulo = m_size - (m_read_count % m_size); + if(_modulo < _length) m_read_count += _modulo; + + // pointer in buffer + void* _out = read_ptr(); + + // Update write count + m_read_count += _length; + + return _out; +} +// + +size_t +ring_buffer::rewind(size_t n) const +{ + if(n > m_read_count) n = m_read_count; + m_read_count -= n; + return n; +} +// + +void +ring_buffer::reset() +{ + m_init = false; + m_ptr = nullptr; + m_size = 0; + m_read_count = 0; + m_write_count = 0; +} +// + +void +ring_buffer::save(std::fstream& _fs) +{ + _fs.write(reinterpret_cast(&m_use_mmap), sizeof(m_use_mmap)); + _fs.write(reinterpret_cast(&m_use_mmap_explicit), sizeof(m_use_mmap_explicit)); + _fs.write(reinterpret_cast(&m_size), sizeof(m_size)); + _fs.write(reinterpret_cast(&m_read_count), sizeof(m_read_count)); + _fs.write(reinterpret_cast(&m_write_count), sizeof(m_write_count)); + _fs.write(reinterpret_cast(m_ptr), m_size * sizeof(char)); +} +// + +void +ring_buffer::load(std::fstream& _fs) +{ + destroy(); + + _fs.read(reinterpret_cast(&m_use_mmap), sizeof(m_use_mmap)); + _fs.read(reinterpret_cast(&m_use_mmap_explicit), sizeof(m_use_mmap_explicit)); + _fs.read(reinterpret_cast(&m_size), sizeof(m_size)); + + init(m_size); + if(!m_ptr) m_ptr = malloc(m_size); + + _fs.read(reinterpret_cast(&m_read_count), sizeof(m_read_count)); + _fs.read(reinterpret_cast(&m_write_count), sizeof(m_write_count)); + _fs.read(reinterpret_cast(m_ptr), m_size * sizeof(char)); +} +} // namespace base +} // namespace container +} // namespace common +} // namespace rocprofiler diff --git a/source/lib/common/container/ring_buffer.hpp b/source/lib/common/container/ring_buffer.hpp new file mode 100644 index 0000000000..7421cd998c --- /dev/null +++ b/source/lib/common/container/ring_buffer.hpp @@ -0,0 +1,495 @@ +// MIT License +// +// Copyright (c) 2020, The Regents of the University of California, +// through Lawrence Berkeley National Laboratory (subject to receipt of any +// required approvals from the U.S. Dept. of Energy). All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN THE +// SOFTWARE. + +#pragma once + +#include "lib/common/environment.hpp" +#include "lib/common/units.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace rocprofiler +{ +namespace common +{ +namespace container +{ +template +struct ring_buffer; +// +namespace base +{ +/// \struct tim::base::ring_buffer +/// \brief Ring buffer implementation, with support for mmap as backend (Linux only). +struct ring_buffer +{ + template + friend struct container::ring_buffer; + + ring_buffer() = default; + explicit ring_buffer(bool _use_mmap) { set_use_mmap(_use_mmap); } + explicit ring_buffer(size_t _size) { init(_size); } + ring_buffer(size_t _size, bool _use_mmap); + + ~ring_buffer(); + + ring_buffer(const ring_buffer&); + ring_buffer& operator=(const ring_buffer&); + + ring_buffer(ring_buffer&&) noexcept; + ring_buffer& operator=(ring_buffer&&) noexcept; + + /// Returns whether the buffer has been allocated + bool is_initialized() const { return m_init; } + + /// Get the total number of bytes supported + size_t capacity() const { return m_size; } + + /// Creates new ring buffer. + void init(size_t size); + + /// Destroy ring buffer. + void destroy(); + + /// Write class-type data to buffer (uses placement new). + template + std::pair write(Tp* in, std::enable_if_t::value, int> = 0); + + /// Write non-class-type data to buffer (uses memcpy). + template + std::pair write(Tp* in, std::enable_if_t::value, int> = 0); + + /// Request a pointer to an allocation. This is similar to a "write" except the + /// memory is uninitialized. Typically used by allocators. If Tp is a class type, + /// be sure to use a placement new instead of a memcpy. + template + Tp* request(); + + /// Request a pointer to an allocation for at least \param n bytes. + void* request(size_t n); + + /// Read class-type data from buffer (uses placement new). + template + std::pair read(Tp* out, std::enable_if_t::value, int> = 0) const; + + /// Read non-class-type data from buffer (uses memcpy). + template + std::pair read(Tp* out, + std::enable_if_t::value, int> = 0) const; + + /// Retrieve a pointer to the head allocation (read). + template + Tp* retrieve(); + + /// Retrieve a pointer to the head allocation of at least \param n bytes (read). + void* retrieve(size_t n); + + /// Returns number of bytes currently held by the buffer. + size_t count() const { return (m_write_count - m_read_count); } + + /// Returns how many bytes are availiable in the buffer. + size_t free() const { return (m_size - count()); } + + /// Returns if the buffer is empty. + bool is_empty() const { return (count() == 0); } + + /// Returns if the buffer is full. + bool is_full() const { return (count() == m_size); } + + /// Rewind the read position n bytes + size_t rewind(size_t n) const; + + /// explicitly configure to use mmap if avail + void set_use_mmap(bool); + + /// query whether using mmap + bool get_use_mmap() const { return m_use_mmap; } + + std::string as_string() const; + + void save(std::fstream& _fs); + void load(std::fstream& _fs); + + friend std::ostream& operator<<(std::ostream& os, const ring_buffer& obj) + { + return os << obj.as_string(); + } + +private: + /// Returns the current write pointer. + void* write_ptr() const { return static_cast(m_ptr) + (m_write_count % m_size); } + + /// Returns the current read pointer. + void* read_ptr() const { return static_cast(m_ptr) + (m_read_count % m_size); } + + void reset(); + +private: + bool m_init = false; + bool m_use_mmap = true; + bool m_use_mmap_explicit = false; + void* m_ptr = nullptr; + size_t m_size = 0; + mutable size_t m_read_count = 0; + size_t m_write_count = 0; +}; +// +template +std::pair +ring_buffer::write(Tp* in, std::enable_if_t::value, int>) +{ + if(in == nullptr || m_ptr == nullptr) return {0, nullptr}; + + auto _length = sizeof(Tp); + + // Make sure we don't put in more than there's room for, by writing no + // more than there is free. + if(_length > free()) + throw std::runtime_error("heap-buffer-overflow :: ring buffer is full. read data " + "to avoid data corruption"); + + // if write count is at the tail of buffer, bump to the end of buffer + auto _modulo = m_size - (m_write_count % m_size); + if(_modulo < _length) m_write_count += _modulo; + + // pointer in buffer + Tp* out = reinterpret_cast(write_ptr()); + + // Copy in. + new((void*) out) Tp{std::move(*in)}; + + // Update write count + m_write_count += _length; + + return {_length, out}; +} +// +template +std::pair +ring_buffer::write(Tp* in, std::enable_if_t::value, int>) +{ + if(in == nullptr || m_ptr == nullptr) return {0, nullptr}; + + auto _length = sizeof(Tp); + + // Make sure we don't put in more than there's room for, by writing no + // more than there is free. + if(_length > free()) + throw std::runtime_error("heap-buffer-overflow :: ring buffer is full. read data " + "to avoid data corruption"); + + // if write count is at the tail of buffer, bump to the end of buffer + auto _modulo = m_size - (m_write_count % m_size); + if(_modulo < _length) m_write_count += _modulo; + + // pointer in buffer + Tp* out = reinterpret_cast(write_ptr()); + + // Copy in. + memcpy((void*) out, in, _length); + + // Update write count + m_write_count += _length; + + return {_length, out}; +} +// +template +Tp* +ring_buffer::request() +{ + if(m_ptr == nullptr) return nullptr; + + auto _length = sizeof(Tp); + + // Make sure we don't put in more than there's room for, by writing no + // more than there is free. + if(_length > free()) + throw std::runtime_error("heap-buffer-overflow :: ring buffer is full. read data " + "to avoid data corruption"); + + // if write count is at the tail of buffer, bump to the end of buffer + auto _modulo = m_size - (m_write_count % m_size); + if(_modulo < _length) m_write_count += _modulo; + + // pointer in buffer + Tp* _out = reinterpret_cast(write_ptr()); + + // Update write count + m_write_count += _length; + + return _out; +} +// +template +std::pair +ring_buffer::read(Tp* out, std::enable_if_t::value, int>) const +{ + if(is_empty() || out == nullptr) return {0, nullptr}; + + auto _length = sizeof(Tp); + + // Make sure we do not read out more than there is actually in the buffer. + if(_length > count()) throw std::runtime_error("ring buffer is empty"); + + // if read count is at the tail of buffer, bump to the end of buffer + auto _modulo = m_size - (m_read_count % m_size); + if(_modulo < _length) m_read_count += _modulo; + + // pointer in buffer + Tp* in = reinterpret_cast(read_ptr()); + + // Copy out for BYTE, nothing magic here. + *out = *in; + + // Update read count. + m_read_count += _length; + + return {_length, in}; +} +// +template +std::pair +ring_buffer::read(Tp* out, std::enable_if_t::value, int>) const +{ + if(is_empty() || out == nullptr) return {0, nullptr}; + + auto _length = sizeof(Tp); + + using Up = typename std::remove_const::type; + + // Make sure we do not read out more than there is actually in the buffer. + if(_length > count()) throw std::runtime_error("ring buffer is empty"); + + // if read count is at the tail of buffer, bump to the end of buffer + auto _modulo = m_size - (m_read_count % m_size); + if(_modulo < _length) m_read_count += _modulo; + + // pointer in buffer + Tp* in = reinterpret_cast(read_ptr()); + + // Copy out for BYTE, nothing magic here. + Up* _out = const_cast(out); + memcpy(_out, in, _length); + + // Update read count. + m_read_count += _length; + + return {_length, in}; +} +// +template +Tp* +ring_buffer::retrieve() +{ + if(m_ptr == nullptr) return nullptr; + + auto _length = sizeof(Tp); + + // Make sure we don't put in more than there's room for, by writing no + // more than there is free. + if(_length > count()) throw std::runtime_error("ring buffer is empty"); + + // if read count is at the tail of buffer, bump to the end of buffer + auto _modulo = m_size - (m_read_count % m_size); + if(_modulo < _length) m_read_count += _modulo; + + // pointer in buffer + Tp* _out = reinterpret_cast(read_ptr()); + + // Update write count + m_read_count += _length; + + return _out; +} +// +} // namespace base +/// +/// \struct rocprofiler::container::ring_buffer +/// \brief Ring buffer wrapper around \ref tim::base::ring_buffer for data of type Tp. If +/// the data object size is larger than the page size (typically 4KB), behavior is +/// undefined. During initialization, one requests a minimum number of objects and the +/// buffer will support that number of object + the remainder of the page, e.g. if a page +/// is 1000 bytes, the object is 1 byte, and the buffer is requested to support 1500 +/// objects, then an allocation supporting 2000 objects (i.e. 2 pages) will be created. +template +struct ring_buffer : private base::ring_buffer +{ + using base_type = base::ring_buffer; + + static size_t get_items_per_page(); + + ring_buffer() = default; + ~ring_buffer() = default; + + explicit ring_buffer(bool _use_mmap) + : base_type{_use_mmap} + {} + + explicit ring_buffer(size_t _size) + : base_type{_size * sizeof(Tp)} + {} + + ring_buffer(size_t _size, bool _use_mmap) + : base_type{_size * sizeof(Tp), _use_mmap} + {} + + ring_buffer(const ring_buffer&); + ring_buffer(ring_buffer&&) noexcept = default; + + ring_buffer& operator=(const ring_buffer&); + ring_buffer& operator=(ring_buffer&&) noexcept = default; + + /// Returns whether the buffer has been allocated + bool is_initialized() const { return base_type::is_initialized(); } + + /// Get the total number of Tp instances supported + size_t capacity() const { return (base_type::capacity()) / sizeof(Tp); } + + /// Creates new ring buffer. + void init(size_t _size) { base_type::init(_size * sizeof(Tp)); } + + /// Destroy ring buffer. + void destroy() { base_type::destroy(); } + + /// Write data to buffer. + size_t data_size() const { return sizeof(Tp); } + + /// Write data to buffer. Return pointer to location of write + Tp* write(Tp* in) { return base_type::write(in).second; } + + /// Read data from buffer. Return pointer to location of read + Tp* read(Tp* out) const { return base_type::read(out).second; } + + /// Get an uninitialized address at tail of buffer. + Tp* request() { return base_type::request(); } + + /// Read data from head of buffer. + Tp* retrieve() { return base_type::retrieve(); } + + /// Returns number of Tp instances currently held by the buffer. + size_t count() const { return (base_type::count()) / sizeof(Tp); } + + /// Returns how many Tp instances are availiable in the buffer. + size_t free() const { return (base_type::free()) / sizeof(Tp); } + + /// Returns if the buffer is empty. + bool is_empty() const { return base_type::is_empty(); } + + /// Returns if the buffer is full. + bool is_full() const { return (base_type::free() < sizeof(Tp)); } + + /// Rewinds the read pointer + size_t rewind(size_t n) const { return base_type::rewind(n); } + + template + auto emplace(Args&&... args) + { + Tp _obj{std::forward(args)...}; + return write(&_obj); + } + + using base_type::get_use_mmap; + using base_type::load; + using base_type::save; + using base_type::set_use_mmap; + + std::string as_string() const + { + std::ostringstream ss{}; + size_t _w = std::log10(base_type::capacity()) + 1; + ss << std::boolalpha << std::right << "data size: " << std::setw(_w) << data_size() + << " B, is_initialized: " << std::setw(5) << is_initialized() + << ", is_empty: " << std::setw(5) << is_empty() << ", is_full: " << std::setw(5) + << is_full() << ", capacity: " << std::setw(_w) << capacity() + << ", count: " << std::setw(_w) << count() << ", free: " << std::setw(_w) << free() + << ", raw capacity: " << std::setw(_w) << base_type::capacity() + << " B, raw count: " << std::setw(_w) << base_type::count() + << " B, raw free: " << std::setw(_w) << base_type::free() + << " B, pointer: " << std::setw(15) << base_type::m_ptr + << ", raw read count: " << std::setw(_w) << base_type::m_read_count + << ", raw write count: " << std::setw(_w) << base_type::m_write_count; + return ss.str(); + } + + friend std::ostream& operator<<(std::ostream& os, const ring_buffer& obj) + { + return os << obj.as_string(); + } +}; +// +template +size_t +ring_buffer::get_items_per_page() +{ + return std::max(units::get_page_size() / sizeof(Tp), 1); +} +// +template +ring_buffer::ring_buffer(const ring_buffer& rhs) +: base_type{rhs} +{ + size_t _n = rhs.count(); + char* _end = static_cast(rhs.m_ptr) + rhs.m_size; + for(size_t i = 0; i < _n; ++i) + { + char* _addr = static_cast(rhs.read_ptr()) + (i * sizeof(Tp)); + if((_addr + sizeof(Tp)) > _end) _addr = static_cast(rhs.m_ptr); + Tp* _in = static_cast(static_cast(_addr)); + write(_in); + } +} +// +template +ring_buffer& +ring_buffer::operator=(const ring_buffer& rhs) +{ + if(this == &rhs) return *this; + + base_type::operator=(rhs); + size_t _n = rhs.count(); + char* _end = static_cast(rhs.m_ptr) + rhs.m_size; + for(size_t i = 0; i < _n; ++i) + { + char* _addr = static_cast(rhs.read_ptr()) + (i * sizeof(Tp)); + if((_addr + sizeof(Tp)) > _end) _addr = static_cast(rhs.m_ptr); + Tp* _in = static_cast(static_cast(_addr)); + write(_in); + } + + return *this; +} +// +} // namespace container +} // namespace common +} // namespace rocprofiler diff --git a/source/lib/common/container/stable_vector.hpp b/source/lib/common/container/stable_vector.hpp new file mode 100644 index 0000000000..8b95e8b3af --- /dev/null +++ b/source/lib/common/container/stable_vector.hpp @@ -0,0 +1,389 @@ +// MIT License +// +// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN THE +// SOFTWARE. + +#pragma once + +#include "lib/common/container/operators.hpp" +#include "lib/common/container/static_vector.hpp" + +#include +#include +#include +#include +#include +#include +#include + +namespace rocprofiler +{ +namespace common +{ +namespace container +{ +template +class stable_vector +{ +public: + using value_type = Tp; + using reference = value_type&; + using const_reference = const value_type&; + using pointer = value_type*; + using const_pointer = const value_type*; + using size_type = size_t; + using difference_type = std::ptrdiff_t; + + static constexpr const size_t chunk_size = ChunkSizeV; + +private: + template + struct is_pow2 + { + static constexpr bool value = (N & (N - 1)) == 0; + }; + + static_assert(ChunkSizeV > 0, "ChunkSize needs to be greater than zero"); + static_assert(is_pow2::value, "ChunkSize needs to be a power of 2"); + + using this_type = stable_vector; + using const_this_type = const stable_vector; + + template + struct iterator_base + { + iterator_base(ContainerT* c = nullptr, size_type i = 0) + : m_container(c) + , m_index(i) + {} + + iterator_base& operator+=(size_type i) + { + m_index += i; + return *this; + } + iterator_base& operator-=(size_type i) + { + m_index -= i; + return *this; + } + iterator_base& operator++() + { + ++m_index; + return *this; + } + iterator_base& operator--() + { + --m_index; + return *this; + } + + difference_type operator-(const iterator_base& it) + { + assert(m_container == it.m_container); + return m_index - it.m_index; + } + + bool operator<(const iterator_base& it) const + { + assert(m_container == it.m_container); + return m_index < it.m_index; + } + bool operator==(const iterator_base& it) const + { + return m_container == it.m_container && m_index == it.m_index; + } + + protected: + ContainerT* m_container; + size_type m_index; + }; + +public: + struct const_iterator; + + struct iterator + : public iterator_base + //, std::iterator + , public random_access_iterator_helper + { + using iterator_base::iterator_base; + friend struct const_iterator; + + reference operator*() { return (*this->m_container)[this->m_index]; } + }; + + struct const_iterator + : public iterator_base + //, std::iterator + , public random_access_iterator_helper + { + using iterator_base::iterator_base; + + explicit const_iterator(const iterator& it) + : iterator_base(it.m_container, it.m_index) + {} + + const_reference operator*() const { return (*this->m_container)[this->m_index]; } + + bool operator==(const const_iterator& it) const + { + return iterator_base::operator==(it); + } + + friend bool operator==(const iterator& l, const const_iterator& r) { return r == l; } + }; + + stable_vector() = default; + explicit stable_vector(size_type count, const Tp& value); + explicit stable_vector(size_type count); + + template ::iterator_category, + std::input_iterator_tag>::value>> + stable_vector(InputItrT first, InputItrT last); + + explicit stable_vector(std::initializer_list); + + stable_vector(const stable_vector& other); + stable_vector(stable_vector&& other) noexcept; + + stable_vector& operator=(stable_vector v); + + iterator begin() noexcept { return {this, 0}; } + const_iterator begin() const noexcept { return {this, 0}; } + const_iterator cbegin() const noexcept { return begin(); } + + iterator end() noexcept { return {this, size()}; } + const_iterator end() const noexcept { return {this, size()}; } + const_iterator cend() const noexcept { return end(); } + + size_type size() const noexcept + { + return empty() ? 0 : (m_chunks.size() - 1) * ChunkSizeV + m_chunks.back()->size(); + } + size_type max_size() const noexcept { return std::numeric_limits::max(); } + size_type capacity() const noexcept { return m_chunks.size() * ChunkSizeV; } + + bool empty() const noexcept { return m_chunks.size() == 0; } + + void reserve(size_type new_capacity); + void shrink_to_fit() noexcept {} + + bool operator==(const this_type& c) const + { + return size() == c.size() && std::equal(cbegin(), cend(), c.cbegin()); + } + bool operator!=(const this_type& c) const { return !operator==(c); } + + void swap(this_type& v) { std::swap(m_chunks, v.m_chunks); } + + friend void swap(this_type& l, this_type& r) { l.swap(r); } + + reference front() { return m_chunks.front()->front(); } + const_reference front() const { return front(); } + + reference back() { return m_chunks.back()->back(); } + const_reference back() const { return back(); } + + void push_back(const Tp& t); + void push_back(Tp&& t); + + template + void emplace_back(Args&&... args); + + reference operator[](size_type i); + + const_reference operator[](size_type i) const; + + reference at(size_type i); + + const_reference at(size_type i) const; + +private: + using chunk_type = container::static_vector; + using storage_type = std::vector>; + + void add_chunk(); + chunk_type& last_chunk(); + + storage_type m_chunks; +}; + +template +stable_vector::stable_vector(size_type count, const Tp& value) +{ + for(size_type i = 0; i < count; ++i) + { + push_back(value); + } +} + +template +stable_vector::stable_vector(size_type count) +{ + for(size_type i = 0; i < count; ++i) + { + emplace_back(); + } +} + +template +template +stable_vector::stable_vector(InputItrT first, InputItrT last) +{ + for(; first != last; ++first) + { + push_back(*first); + } +} + +template +stable_vector::stable_vector(const stable_vector& other) +{ + for(const auto& chunk : other.m_chunks) + { + m_chunks.emplace_back(std::make_unique(*chunk)); + } +} + +template +stable_vector::stable_vector(stable_vector&& other) noexcept +: m_chunks(std::move(other.m_chunks)) +{} + +template +stable_vector::stable_vector(std::initializer_list ilist) +{ + for(const auto& t : ilist) + { + push_back(t); + } +} + +template +stable_vector& +stable_vector::operator=(stable_vector v) +{ + swap(v); + return *this; +} + +template +void +stable_vector::add_chunk() +{ + m_chunks.emplace_back(std::make_unique()); +} + +template +typename stable_vector::chunk_type& +stable_vector::last_chunk() +{ + if(ROCPROFILER_UNLIKELY(m_chunks.empty() || m_chunks.back()->size() == ChunkSizeV)) + { + add_chunk(); + } + + return *m_chunks.back(); +} + +template +void +stable_vector::reserve(size_type new_capacity) +{ + const size_t initial_capacity = capacity(); + for(difference_type i = new_capacity - initial_capacity; i > 0; i -= ChunkSizeV) + { + add_chunk(); + } +} + +template +void +stable_vector::push_back(const Tp& t) +{ + last_chunk().push_back(t); +} + +template +void +stable_vector::push_back(Tp&& t) +{ + last_chunk().push_back(std::move(t)); +} + +template +template +void +stable_vector::emplace_back(Args&&... args) +{ + last_chunk().emplace_back(std::forward(args)...); +} + +template +typename stable_vector::reference +stable_vector::operator[](size_type i) +{ + return (*m_chunks[i / ChunkSizeV])[i % ChunkSizeV]; +} + +template +typename stable_vector::const_reference +stable_vector::operator[](size_type i) const +{ + return const_cast(*this)[i]; +} + +template +typename stable_vector::reference +stable_vector::at(size_type i) +{ + if(ROCPROFILER_UNLIKELY(i >= size())) + { + throw ::rocprofiler::exception("stable_vector::at(" + std::to_string(i) + + "). size is " + std::to_string(size())); + } + + return operator[](i); +} + +template +typename stable_vector::const_reference +stable_vector::at(size_type i) const +{ + return const_cast(*this).at(i); +} + +template +auto +resize(stable_vector& _v, size_t _n, Args&&... args) +{ + if(_n > _v.capacity()) _v.reserve(_n); + + while(_v.size() < _n) + _v.emplace_back(std::forward(args)...); + + return _v.size(); +} +} // namespace container +} // namespace common +} // namespace rocprofiler diff --git a/source/lib/common/container/static_vector.hpp b/source/lib/common/container/static_vector.hpp new file mode 100644 index 0000000000..24da2d39a9 --- /dev/null +++ b/source/lib/common/container/static_vector.hpp @@ -0,0 +1,221 @@ +// MIT License +// +// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN THE +// SOFTWARE. + +#pragma once + +#include "lib/common/container/c_array.hpp" + +#include +#include +#include +#include +#include + +namespace rocprofiler +{ +namespace common +{ +namespace container +{ +template +struct static_vector +{ + using count_type = std::conditional_t, size_t>; + using this_type = static_vector; + using value_type = Tp; + + static_vector() = default; + static_vector(const static_vector&) = default; + static_vector(static_vector&&) noexcept = default; + static_vector& operator=(const static_vector&) = default; + static_vector& operator=(static_vector&&) noexcept = default; + + explicit static_vector(size_t _n, Tp _v = {}); + explicit static_vector(c_array&&); + + template + explicit static_vector(std::array&&); + + static_vector& operator=(std::initializer_list&& _v); + static_vector& operator=(std::pair, size_t>&&); + + template + value_type& emplace_back(Args&&... _v); + + template + decltype(auto) push_back(Up&& _v) + { + return emplace_back(Tp{std::forward(_v)}); + } + + void pop_back() { --m_size; } + + void clear(); + void reserve(size_t) noexcept {} + void shrink_to_fit() noexcept {} + auto capacity() noexcept { return N; } + + size_t size() const { return m_size; } + bool empty() const { return (size() == 0); } + + auto begin() { return m_data.begin(); } + auto begin() const { return m_data.begin(); } + auto cbegin() const { return m_data.cbegin(); } + + auto end() { return m_data.begin() + size(); } + auto end() const { return m_data.begin() + size(); } + auto cend() const { return m_data.cbegin() + size(); } + + decltype(auto) operator[](size_t _idx) { return m_data[_idx]; } + decltype(auto) operator[](size_t _idx) const { return m_data[_idx]; } + + decltype(auto) at(size_t _idx) { return m_data.at(_idx); } + decltype(auto) at(size_t _idx) const { return m_data.at(_idx); } + + decltype(auto) front() { return m_data.front(); } + decltype(auto) front() const { return m_data.front(); } + decltype(auto) back() { return *(m_data.begin() + size() - 1); } + decltype(auto) back() const { return *(m_data.begin() + size() - 1); } + + auto* data() { return m_data.data(); } + const auto* data() const { return m_data.data(); } + + void swap(this_type& _v); + + friend void swap(this_type& _lhs, this_type& _rhs) { _lhs.swap(_rhs); } + +private: + void update_size(size_t); + +private: + count_type m_size = count_type{0}; + std::array m_data = {}; +}; + +template +static_vector::static_vector(size_t _n, Tp _v) +{ + m_data.fill(_v); + update_size(_n); +} + +template +static_vector::static_vector(c_array&& _v) +{ + auto _n = std::min(N, _v.size()); + for(size_t i = 0; i < _n; ++i, ++m_size) + m_data[i] = _v[i]; +} + +template +template +static_vector::static_vector(std::array&& _v) +{ + auto _n = std::min(N, M); + for(size_t i = 0; i < _n; ++i, ++m_size) + m_data[i] = _v[i]; +} + +template +static_vector& +static_vector::operator=(std::initializer_list&& _v) +{ + if(ROCPROFILER_UNLIKELY(_v.size() > N)) + { + throw exception( + std::string{"static_vector::operator=(initializer_list) size > "} + std::to_string(N)); + } + + clear(); + for(auto&& itr : _v) + m_data[m_size++] = itr; + return *this; +} + +template +static_vector& +static_vector::operator=(std::pair, size_t>&& _v) +{ + update_size(0); + m_data = std::move(_v.first); + update_size(_v.second); + + return *this; +} + +template +void +static_vector::clear() +{ + update_size(0); +} + +template +void +static_vector::swap(this_type& _v) +{ + if constexpr(AtomicSizeV) + { + auto _t_size = m_size; + auto _v_size = _v.m_size; + std::swap(m_data, _v.m_data); + update_size(_v_size); + _v.update_size(_t_size); + } + else + { + std::swap(m_size, _v.m_size); + std::swap(m_data, _v.m_data); + } +} + +template +template +Tp& +static_vector::emplace_back(Args&&... _v) +{ + auto _idx = m_size++; + if(_idx >= N) + { + throw exception( + std::string{"static_vector::emplace_back - reached capacity "} + std::to_string(N)); + } + + if constexpr(std::is_assignable(_v))...>::value) + m_data[_idx] = {std::forward(_v)...}; + else + m_data[_idx] = Tp{std::forward(_v)...}; + return m_data[_idx]; +} + +template +void +static_vector::update_size(size_t _n) +{ + if constexpr(AtomicSizeV) + m_size.store(_n); + else + m_size = _n; +} +} // namespace container +} // namespace common +} // namespace rocprofiler diff --git a/source/lib/common/defines.hpp b/source/lib/common/defines.hpp new file mode 100644 index 0000000000..19683ac05b --- /dev/null +++ b/source/lib/common/defines.hpp @@ -0,0 +1,65 @@ +// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN +// THE SOFTWARE. + +#pragma once + +#define ROCPROFILER_ATTRIBUTE(...) __attribute__((__VA_ARGS__)) +#define ROCPROFILER_VISIBILITY(MODE) ROCPROFILER_ATTRIBUTE(visibility(MODE)) +#define ROCPROFILER_PUBLIC_API ROCPROFILER_VISIBILITY("default") +#define ROCPROFILER_HIDDEN_API ROCPROFILER_VISIBILITY("hidden") +#define ROCPROFILER_INTERNAL_API ROCPROFILER_VISIBILITY("internal") +#define ROCPROFILER_INLINE ROCPROFILER_ATTRIBUTE(always_inline) inline +#define ROCPROFILER_NOINLINE ROCPROFILER_ATTRIBUTE(noinline) +#define ROCPROFILER_HOT ROCPROFILER_ATTRIBUTE(hot) +#define ROCPROFILER_COLD ROCPROFILER_ATTRIBUTE(cold) +#define ROCPROFILER_CONST ROCPROFILER_ATTRIBUTE(const) +#define ROCPROFILER_PURE ROCPROFILER_ATTRIBUTE(pure) +#define ROCPROFILER_WEAK ROCPROFILER_ATTRIBUTE(weak) +#define ROCPROFILER_PACKED ROCPROFILER_ATTRIBUTE(__packed__) +#define ROCPROFILER_PACKED_ALIGN(VAL) ROCPROFILER_PACKED ROCPROFILER_ATTRIBUTE(__aligned__(VAL)) +#define ROCPROFILER_LIKELY(...) __builtin_expect((__VA_ARGS__), 1) +#define ROCPROFILER_UNLIKELY(...) __builtin_expect((__VA_ARGS__), 0) + +#if defined(ROCPROFILER_CI) && ROCPROFILER_CI > 0 +# if defined(NDEBUG) +# undef NDEBUG +# endif +# if !defined(DEBUG) +# define DEBUG 1 +# endif +# if defined(__cplusplus) +# include +# else +# include +# endif +#endif + +#define ROCPROFILER_STRINGIZE(X) ROCPROFILER_STRINGIZE2(X) +#define ROCPROFILER_STRINGIZE2(X) #X +#define ROCPROFILER_VAR_NAME_COMBINE(X, Y) X##Y +#define ROCPROFILER_VARIABLE(X, Y) ROCPROFILER_VAR_NAME_COMBINE(X, Y) +#define ROCPROFILER_LINESTR ROCPROFILER_STRINGIZE(__LINE__) +#define ROCPROFILER_ESC(...) __VA_ARGS__ + +#if defined(__cplusplus) +# if !defined(ROCPROFILER_FOLD_EXPRESSION) +# define ROCPROFILER_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...) +# endif +#endif diff --git a/source/lib/common/environment.hpp b/source/lib/common/environment.hpp new file mode 100644 index 0000000000..5b75c888d6 --- /dev/null +++ b/source/lib/common/environment.hpp @@ -0,0 +1,185 @@ +// Copyright (c) 2023 Advanced Micro Devices, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN +// THE SOFTWARE. + +#pragma once + +#include "lib/common/log.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(ROCPROFILER_ENVIRON_LOG_NAME) +# if defined(ROCPROFILER_COMMON_LIBRARY_NAME) +# define ROCPROFILER_ENVIRON_LOG_NAME "[" ROCPROFILER_COMMON_LIBRARY_NAME "]" +# else +# define ROCPROFILER_ENVIRON_LOG_NAME "[environ]" +# endif +#endif + +#if !defined(ROCPROFILER_ENVIRON_LOG_START) +# if defined(ROCPROFILER_COMMON_LIBRARY_LOG_START) +# define ROCPROFILER_ENVIRON_LOG_START ROCPROFILER_COMMON_LIBRARY_LOG_START +# elif defined(ROCPROFILER_LOG_COLORS_AVAILABLE) +# define ROCPROFILER_ENVIRON_LOG_START \ + fprintf(stderr, "%s", ::rocprofiler::common::log::color::dmesg()); +# else +# define ROCPROFILER_ENVIRON_LOG_START +# endif +#endif + +#if !defined(ROCPROFILER_ENVIRON_LOG_END) +# if defined(ROCPROFILER_COMMON_LIBRARY_LOG_END) +# define ROCPROFILER_ENVIRON_LOG_END ROCPROFILER_COMMON_LIBRARY_LOG_END +# elif defined(ROCPROFILER_LOG_COLORS_AVAILABLE) +# define ROCPROFILER_ENVIRON_LOG_END \ + fprintf(stderr, "%s", ::rocprofiler::common::log::color::dmesg()); +# else +# define ROCPROFILER_ENVIRON_LOG_END +# endif +#endif + +#define ROCPROFILER_ENVIRON_LOG(CONDITION, ...) \ + if(CONDITION) \ + { \ + fflush(stderr); \ + ROCPROFILER_ENVIRON_LOG_START \ + fprintf(stderr, "[rocprofiler]" ROCPROFILER_ENVIRON_LOG_NAME "[%i] ", getpid()); \ + fprintf(stderr, __VA_ARGS__); \ + ROCPROFILER_ENVIRON_LOG_END \ + fflush(stderr); \ + } + +namespace rocprofiler +{ +namespace common +{ +namespace +{ +inline std::string +get_env_impl(std::string_view env_id, std::string_view _default) +{ + if(env_id.empty()) return std::string{_default}; + char* env_var = ::std::getenv(env_id.data()); + if(env_var) return std::string{env_var}; + return std::string{_default}; +} + +inline std::string +get_env_impl(std::string_view env_id, const char* _default) +{ + return get_env_impl(env_id, std::string_view{_default}); +} + +inline int +get_env_impl(std::string_view env_id, int _default) +{ + if(env_id.empty()) return _default; + char* env_var = ::std::getenv(env_id.data()); + if(env_var) + { + try + { + return std::stoi(env_var); + } catch(std::exception& _e) + { + fprintf(stderr, + "[rocprofiler][get_env] Exception thrown converting getenv(\"%s\") = " + "%s to integer :: %s. Using default value of %i\n", + env_id.data(), + env_var, + _e.what(), + _default); + } + return _default; + } + return _default; +} + +inline bool +get_env_impl(std::string_view env_id, bool _default) +{ + if(env_id.empty()) return _default; + char* env_var = ::std::getenv(env_id.data()); + if(env_var) + { + if(std::string_view{env_var}.empty()) + { + throw std::runtime_error(std::string{"No boolean value provided for "} + + std::string{env_id}); + } + + if(std::string_view{env_var}.find_first_not_of("0123456789") == std::string_view::npos) + { + return static_cast(std::stoi(env_var)); + } + + for(size_t i = 0; i < strlen(env_var); ++i) + env_var[i] = tolower(env_var[i]); + for(const auto& itr : {"off", "false", "no", "n", "f", "0"}) + if(strcmp(env_var, itr) == 0) return false; + + return true; + } + return _default; +} +} // namespace + +template +inline auto +get_env(std::string_view env_id, Tp&& _default) +{ + if constexpr(std::is_enum::value) + { + using Up = std::underlying_type_t; + // cast to underlying type -> get_env -> cast to enum type + return static_cast(get_env_impl(env_id, static_cast(_default))); + } + else + { + return get_env_impl(env_id, std::forward(_default)); + } +} + +struct env_config +{ + std::string env_name = {}; + std::string env_value = {}; + int override = 0; + + auto operator()(bool _verbose = false) const + { + if(env_name.empty()) return -1; + ROCPROFILER_ENVIRON_LOG(_verbose, + "setenv(\"%s\", \"%s\", %i)\n", + env_name.c_str(), + env_value.c_str(), + override); + return setenv(env_name.c_str(), env_value.c_str(), override); + } +}; +} // namespace common +} // namespace rocprofiler diff --git a/source/lib/common/helper.cpp b/source/lib/common/helper.cpp new file mode 100644 index 0000000000..31e924606b --- /dev/null +++ b/source/lib/common/helper.cpp @@ -0,0 +1,373 @@ +/* Copyright (c) 2022 Advanced Micro Devices, Inc. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + 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 + AUTHORS 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 IN + THE SOFTWARE. */ + +#include "lib/common/helper.hpp" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ENABLE_BACKTRACE +#if defined(ENABLE_BACKTRACE) +# include +#endif + +#define amd_comgr_(call) \ + do \ + { \ + if(amd_comgr_status_t status = amd_comgr_##call; status != AMD_COMGR_STATUS_SUCCESS) \ + { \ + const char* reason = ""; \ + amd_comgr_status_string(status, &reason); \ + fprintf(stderr, #call " failed: %s\n", reason); \ + abort(); \ + } \ + } while(false) + +namespace rocprofiler +{ +namespace common +{ +std::string +cxa_demangle(std::string_view _mangled_name, int* _status) +{ + constexpr size_t buffer_len = 4096; + // return the mangled since there is no buffer + if(_mangled_name.empty()) + { + *_status = -2; + return std::string{}; + } + + auto _demangled_name = std::string{_mangled_name}; + + // PARAMETERS to __cxa_demangle + // mangled_name: + // A NULL-terminated character string containing the name to be demangled. + // buffer: + // A region of memory, allocated with malloc, of *length bytes, into which the + // demangled name is stored. If output_buffer is not long enough, it is expanded + // using realloc. output_buffer may instead be NULL; in that case, the demangled + // name is placed in a region of memory allocated with malloc. + // _buflen: + // If length is non-NULL, the length of the buffer containing the demangled name + // is placed in *length. + // status: + // *status is set to one of the following values + size_t _demang_len = 0; + char* _demang = abi::__cxa_demangle(_demangled_name.c_str(), nullptr, &_demang_len, _status); + switch(*_status) + { + // 0 : The demangling operation succeeded. + // -1 : A memory allocation failure occurred. + // -2 : mangled_name is not a valid name under the C++ ABI mangling rules. + // -3 : One of the arguments is invalid. + case 0: + { + if(_demang) _demangled_name = std::string{_demang}; + break; + } + case -1: + { + char _msg[buffer_len]; + ::memset(_msg, '\0', buffer_len * sizeof(char)); + ::snprintf(_msg, + buffer_len, + "memory allocation failure occurred demangling %s", + _demangled_name.c_str()); + ::perror(_msg); + break; + } + case -2: break; + case -3: + { + char _msg[buffer_len]; + ::memset(_msg, '\0', buffer_len * sizeof(char)); + ::snprintf(_msg, + buffer_len, + "Invalid argument in: (\"%s\", nullptr, nullptr, %p)", + _demangled_name.c_str(), + (void*) _status); + ::perror(_msg); + break; + } + default: break; + }; + + // if it "demangled" but the length is zero, set the status to -2 + if(_demang_len == 0 && *_status == 0) *_status = -2; + + // free allocated buffer + ::free(_demang); + return _demangled_name; +} + +namespace +{ +#if defined(ENABLE_BACKTRACE) + +// struct BackTraceInfo +// { +// struct ::backtrace_state* state = nullptr; +// std::stringstream sstream{}; +// int depth = 0; +// int error = 0; +// }; + +// void +// errorCallback(void* data, const char* message, int errnum) +// { +// BackTraceInfo* info = static_cast(data); +// info->sstream << "ROCProfiler: error: " << message << '(' << errnum << ')'; +// info->error = 1; +// } + +// void +// syminfoCallback(void* data, +// uintptr_t /* pc */, +// const char* symname, +// uintptr_t /* symval */, +// uintptr_t /* symsize */) +// { +// BackTraceInfo* info = static_cast(data); + +// if(symname == nullptr) return; + +// int status = 0; +// auto&& _demangled = cxa_demangle(symname, &status); +// info->sstream << ' ' +// << (status == 0 ? std::string_view{_demangled} : std::string_view{symname}); +// } + +// int +// fullCallback(void* data, uintptr_t pc, const char* filename, int lineno, const char* function) +// { +// BackTraceInfo* info = static_cast(data); + +// info->sstream << std::endl +// << " #" << std::dec << info->depth++ << ' ' << "0x" << std::noshowbase +// << std::hex << std::setfill('0') << std::setw(sizeof(pc) * 2) << pc; +// if(function == nullptr) +// { +// backtrace_syminfo(info->state, pc, syminfoCallback, errorCallback, data); +// } +// else +// { +// int status = 0; +// auto&& _demangled = cxa_demangle(function, &status); +// info->sstream << ' ' +// << (status == 0 ? std::string_view{_demangled} : +// std::string_view{function}); + +// if(filename != nullptr) +// { +// info->sstream << " in " << filename; +// if(lineno != 0) info->sstream << ':' << std::dec << lineno; +// } +// } + +// return info->error; +// } +#endif // defined (ENABLE_BACKTRACE) +} // namespace + +/* The function extracts the kernel name from +input string. By using the iterators it finds the +window in the string which contains only the kernel name. +For example 'Foo::foo(a[], int (int))' -> 'foo'*/ +std::string +truncate_name(std::string_view name) +{ + auto rit = name.rbegin(); + auto rend = name.rend(); + uint32_t counter = 0; + char open_token = 0; + char close_token = 0; + while(rit != rend) + { + if(counter == 0) + { + switch(*rit) + { + case ')': + counter = 1; + open_token = ')'; + close_token = '('; + break; + case '>': + counter = 1; + open_token = '>'; + close_token = '<'; + break; + case ']': + counter = 1; + open_token = ']'; + close_token = '['; + break; + case ' ': ++rit; continue; + } + if(counter == 0) break; + } + else + { + if(*rit == open_token) counter++; + if(*rit == close_token) counter--; + } + ++rit; + } + auto rbeg = rit; + while((rit != rend) && (*rit != ' ') && (*rit != ':')) + rit++; + return std::string{name.substr(rend - rit, rit - rbeg)}; +} + +// C++ symbol demangle +std::string +cxx_demangle(std::string_view symbol) +{ + int _status = 0; + auto demangled_str = cxa_demangle(symbol, &_status); + if(_status == 0) + { + return demangled_str; + } + + amd_comgr_data_t mangled_data; + amd_comgr_(create_data(AMD_COMGR_DATA_KIND_BYTES, &mangled_data)); + amd_comgr_(set_data(mangled_data, symbol.size(), symbol.data())); + + amd_comgr_data_t demangled_data; + amd_comgr_(demangle_symbol_name(mangled_data, &demangled_data)); + + size_t demangled_size = 0; + amd_comgr_(get_data(demangled_data, &demangled_size, nullptr)); + + demangled_str.resize(demangled_size); + amd_comgr_(get_data(demangled_data, &demangled_size, demangled_str.data())); + + amd_comgr_(release_data(mangled_data)); + amd_comgr_(release_data(demangled_data)); + return demangled_str; +} + +// check if string has special char +bool +has_special_char(std::string_view str) +{ + return std::find_if(str.begin(), str.end(), [](unsigned char ch) { + return !((isalnum(ch) != 0) || ch == '_' || ch == ':' || ch == ' '); + }) != str.end(); +} + +// check if string has correct counter format +bool +has_counter_format(std::string_view str) +{ + return std::find_if(str.begin(), str.end(), [](unsigned char ch) { + return ((isalnum(ch) != 0) || ch == '_'); + }) != str.end(); +} + +// trims the begining of the line for spaces +std::string +left_trim(std::string_view s) +{ + constexpr std::string_view WHITESPACE = " \n\r\t\f\v"; + size_t start = s.find_first_not_of(WHITESPACE); + if(start == std::string_view::npos) return std::string{}; + return std::string{s.substr(start)}; +} + +// trims begining and end of input line in place +void +trim(std::string& str) +{ + // Remove leading spaces. + str.erase(str.begin(), std::find_if(str.begin(), str.end(), [](unsigned char ch) { + return std::isspace(ch) == 0; + })); + // Remove trailing spaces. + str.erase(std::find_if( + str.rbegin(), str.rend(), [](unsigned char ch) { return std::isspace(ch) == 0; }) + .base(), + str.end()); +} + +// replace unsuported specail chars with space +static void +handle_special_chars(std::string& str) +{ + std::set specialChars = {'!', '@', '#', '$', '%', '&', '(', ')', ',', + '*', '+', '-', '.', '/', ';', '<', '=', '>', + '?', '@', '{', '}', '^', '`', '~', '|', ':'}; + + // Iterate over the string and replace any special characters with a space. + for(char& i : str) + { + if(specialChars.find(i) != specialChars.end()) + { + i = ' '; + } + } +} + +// validate input coutners and correct format if needed +void +validate_counters_format(std::vector& counters, std::string line) +{ + // trim line for any white spaces + trim(line); + + if(!(line[0] == '#' || line.find("pmc") == std::string::npos)) + { + handle_special_chars(line); + + std::stringstream input_line(line); + std::string counter; + while(getline(input_line, counter, ' ')) + { + if(counter.substr(0, 3) != "pmc" && has_counter_format(counter)) + { + counters.push_back(counter); + } + } + } + + // raise exception with correct usage if user still managed to corrupt input + for(const auto& itr : counters) + { + if(!has_counter_format(itr)) + { + fprintf(stderr, + "[rocprofiler] Bad input metric. usage --> pmc: \n"); + } + } +} + +} // namespace common +} // namespace rocprofiler diff --git a/source/lib/common/helper.hpp b/source/lib/common/helper.hpp new file mode 100644 index 0000000000..d454d70725 --- /dev/null +++ b/source/lib/common/helper.hpp @@ -0,0 +1,68 @@ +/* Copyright (c) 2022 Advanced Micro Devices, Inc. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + 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 + AUTHORS 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 IN + THE SOFTWARE. */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace rocprofiler +{ +namespace common +{ +[[nodiscard]] std::string +cxa_demangle(std::string_view _mangled_name, int* _status) __attribute__((nonnull(2))); + +/* The function extracts the kernel name from +input string. By using the iterators it finds the +window in the string which contains only the kernel name. +For example 'Foo::foo(a[], int (int))' -> 'foo'*/ +std::string +truncate_name(std::string_view name); + +// C++ symbol demangle +std::string +cxx_demangle(std::string_view symbol); + +// check if string has special char +bool +has_special_char(std::string_view str); + +// check if string has correct counter format +bool +has_counter_format(std::string_view str); + +// trims the begining of the line for spaces +std::string +left_trim(std::string_view s); + +// validates pmc user input format +void +validate_counters_format(std::vector& counters, std::string line); + +} // namespace common +} // namespace rocprofiler diff --git a/source/lib/common/join.hpp b/source/lib/common/join.hpp new file mode 100644 index 0000000000..0814125c4e --- /dev/null +++ b/source/lib/common/join.hpp @@ -0,0 +1,183 @@ +// Copyright (c) 2023 Advanced Micro Devices, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN +// THE SOFTWARE. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(ROCPROFILER_FOLD_EXPRESSION) +# define ROCPROFILER_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...) +#endif + +namespace rocprofiler +{ +namespace common +{ +namespace +{ +template +struct is_string_impl : std::false_type +{}; + +template <> +struct is_string_impl : std::true_type +{}; + +template <> +struct is_string_impl : std::true_type +{}; + +template <> +struct is_string_impl : std::true_type +{}; + +template <> +struct is_string_impl : std::true_type +{}; + +template +struct is_string : is_string_impl>> +{}; + +template +auto +as_string(ArgT&& _v, std::enable_if_t::value, int> = 0) +{ + if constexpr(std::is_pointer>::value) + { + return (_v == nullptr) ? std::string{"\"\""} : (std::string{"\""} + _v + std::string{"\""}); + } + else + { + return std::string{"\""} + _v + std::string{"\""}; + } +} + +template +auto +as_string(ArgT&& _v, std::enable_if_t::value, long> = 0) +{ + return _v; +} + +template +auto +join(DelimT&& _delim, Args&&... _args) +{ + using delim_type = std::remove_cv_t>; + + std::stringstream _ss{}; + _ss << std::boolalpha; + + if constexpr(std::is_same::value) + { + const char _delim_c[2] = {_delim, '\0'}; + ROCPROFILER_FOLD_EXPRESSION(_ss << _delim_c << _args); + auto _ret = _ss.str(); + return (_ret.length() > 1) ? _ret.substr(1) : std::string{}; + } + else + { + ROCPROFILER_FOLD_EXPRESSION(_ss << _delim << _args); + auto _ret = _ss.str(); + auto&& _len = std::string{_delim}.length(); + return (_ret.length() > _len) ? _ret.substr(_len) : std::string{}; + } +} + +struct QuoteStrings +{}; + +template +auto +join(QuoteStrings&&, DelimT&& _delim, Args&&... _args) +{ + using delim_type = std::remove_cv_t>; + + std::stringstream _ss{}; + _ss << std::boolalpha; + + if constexpr(std::is_same::value) + { + const char _delim_c[2] = {_delim, '\0'}; + ROCPROFILER_FOLD_EXPRESSION(_ss << _delim_c << as_string(_args)); + auto _ret = _ss.str(); + return (_ret.length() > 1) ? _ret.substr(1) : std::string{}; + } + else + { + ROCPROFILER_FOLD_EXPRESSION(_ss << _delim << as_string(_args)); + auto _ret = _ss.str(); + auto&& _len = std::string{_delim}.length(); + return (_ret.length() > _len) ? _ret.substr(_len) : std::string{}; + } +} + +template +auto +join(std::array&& _delim, Args&&... _args) +{ + return join("", + std::get<0>(_delim), + join(std::get<1>(_delim), std::forward(_args)...), + std::get<2>(_delim)); +} + +template +auto +join(QuoteStrings&&, std::array&& _delim, Args&&... _args) +{ + return join(QuoteStrings{}, + "", + std::get<0>(_delim), + join(std::get<1>(_delim), std::forward(_args)...), + std::get<2>(_delim)); +} + +template +auto +join(std::tuple&& _delim, Args&&... _args) +{ + return join("", + std::get<0>(_delim), + join(std::get<1>(_delim), std::forward(_args)...), + std::get<2>(_delim)); +} + +template +auto +join(QuoteStrings&&, std::tuple&& _delim, Args&&... _args) +{ + return join(QuoteStrings{}, + "", + std::get<0>(_delim), + join(std::get<1>(_delim), std::forward(_args)...), + std::get<2>(_delim)); +} +} // namespace +} // namespace common +} // namespace rocprofiler diff --git a/source/lib/common/log.hpp b/source/lib/common/log.hpp new file mode 100644 index 0000000000..13b6ada338 --- /dev/null +++ b/source/lib/common/log.hpp @@ -0,0 +1,140 @@ +// MIT License +// +// Copyright (c) 2020, The Regents of the University of California, +// through Lawrence Berkeley National Laboratory (subject to receipt of any +// required approvals from the U.S. Dept. of Energy). All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// 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 +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR rhs +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR rhsWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR rhs DEALINGS IN THE +// SOFTWARE. + +#pragma once + +#ifndef ROCPROFILER_LOG_COLORS_AVAILABLE +# define ROCPROFILER_LOG_COLORS_AVAILABLE 1 +#endif + +#include +#include +#include + +namespace rocprofiler +{ +namespace common +{ +namespace log +{ +bool& +monochrome(); + +inline bool& +monochrome() +{ + static bool _v = []() { + auto _val = false; + const char* _env_cstr = nullptr; +#if defined(ROCPROFILER_LOG_COLORS_ENV) + _env_cstr = std::getenv(ROCPROFILER_LOG_COLORS_ENV); +#elif defined(ROCPROFILER_PROJECT_NAME) + auto _env_name = std::string{ROCPROFILER_PROJECT_NAME} + "_MONOCHROME"; + for(auto& itr : _env_name) + itr = toupper(itr); + _env_cstr = std::getenv(_env_name.c_str()); +#else + _env_cstr = std::getenv("ROCPROFILER_MONOCHROME"); +#endif + + if(!_env_cstr) _env_cstr = std::getenv("MONOCHROME"); + + if(_env_cstr) + { + auto _env = std::string{_env_cstr}; + + // check if numeric + if(_env.find_first_not_of("0123456789") == std::string::npos) + { + return _env.length() > 1 || _env[0] != '0'; + } + + for(auto& itr : _env) + itr = tolower(itr); + + // check for matches to acceptable forms of false + for(const auto& itr : {"off", "false", "no", "n", "f"}) + { + if(_env == itr) return false; + } + + // check for matches to acceptable forms of true + for(const auto& itr : {"on", "true", "yes", "y", "t"}) + { + if(_env == itr) return true; + } + } + return _val; + }(); + return _v; +} + +namespace color +{ +static constexpr auto info_value = "\033[01;34m"; +static constexpr auto warning_value = "\033[01;33m"; +static constexpr auto fatal_value = "\033[01;31m"; +static constexpr auto source_value = "\033[01;32m"; +static constexpr auto dmesg_value = "\033[01;37m"; +static constexpr auto end_value = "\033[0m"; + +inline const char* +info() +{ + return (log::monochrome()) ? "" : info_value; +} + +inline const char* +warning() +{ + return (log::monochrome()) ? "" : warning_value; +} + +inline const char* +fatal() +{ + return (log::monochrome()) ? "" : fatal_value; +} + +inline const char* +source() +{ + return (log::monochrome()) ? "" : source_value; +} + +inline const char* +dmesg() +{ + return (log::monochrome()) ? "" : dmesg_value; +} + +inline const char* +end() +{ + return (log::monochrome()) ? "" : end_value; +} +} // namespace color +} // namespace log +} // namespace common +} // namespace rocprofiler diff --git a/source/lib/common/units.hpp b/source/lib/common/units.hpp new file mode 100644 index 0000000000..c6ceb36f8b --- /dev/null +++ b/source/lib/common/units.hpp @@ -0,0 +1,376 @@ +// MIT License +// +// Copyright (c) 2020, The Regents of the University of California, +// through Lawrence Berkeley National Laboratory (subject to receipt of any +// required approvals from the U.S. Dept. of Energy). All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 +// IN THE SOFTWARE. + +#pragma once + +#include "lib/common/environment.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace rocprofiler +{ +namespace common +{ +namespace units +{ +static constexpr int64_t nsec = 1; +static constexpr int64_t usec = 1000 * nsec; +static constexpr int64_t msec = 1000 * usec; +static constexpr int64_t csec = 10 * msec; +static constexpr int64_t dsec = 10 * csec; +static constexpr int64_t sec = 10 * dsec; +static constexpr int64_t minute = 60 * sec; +static constexpr int64_t hour = 60 * minute; + +static constexpr int64_t byte = 1; +static constexpr int64_t kilobyte = 1000 * byte; +static constexpr int64_t megabyte = 1000 * kilobyte; +static constexpr int64_t gigabyte = 1000 * megabyte; +static constexpr int64_t terabyte = 1000 * gigabyte; +static constexpr int64_t petabyte = 1000 * terabyte; + +static constexpr int64_t kibibyte = 1024 * byte; +static constexpr int64_t mebibyte = 1024 * kibibyte; +static constexpr int64_t gibibyte = 1024 * mebibyte; +static constexpr int64_t tebibyte = 1024 * gibibyte; +static constexpr int64_t pebibyte = 1024 * tebibyte; + +static constexpr int64_t B = 1; +static constexpr int64_t KB = 1000 * B; +static constexpr int64_t MB = 1000 * KB; +static constexpr int64_t GB = 1000 * MB; +static constexpr int64_t TB = 1000 * GB; +static constexpr int64_t PB = 1000 * TB; + +static constexpr int64_t Bi = 1; +static constexpr int64_t KiB = 1024 * Bi; +static constexpr int64_t MiB = 1024 * KiB; +static constexpr int64_t GiB = 1024 * MiB; +static constexpr int64_t TiB = 1024 * GiB; +static constexpr int64_t PiB = 1024 * TiB; + +static constexpr int64_t nanowatt = 1; +static constexpr int64_t microwatt = 1000 * nanowatt; +static constexpr int64_t milliwatt = 1000 * microwatt; +static constexpr int64_t watt = 1000 * milliwatt; +static constexpr int64_t kilowatt = 1000 * watt; +static constexpr int64_t megawatt = 1000 * kilowatt; +static constexpr int64_t gigawatt = 1000 * megawatt; + +static constexpr int64_t hertz = 1; +static constexpr int64_t kilohertz = 1000 * hertz; +static constexpr int64_t megahertz = 1000 * kilohertz; +static constexpr int64_t gigahertz = 1000 * megahertz; + +static constexpr int64_t Hz = 1; +static constexpr int64_t KHz = 1000 * Hz; +static constexpr int64_t MHz = 1000 * KHz; +static constexpr int64_t GHz = 1000 * MHz; + +inline int64_t +get_page_size() +{ + static auto _pagesz = sysconf(_SC_PAGESIZE); + return _pagesz; +} + +const int64_t clocks_per_sec = sysconf(_SC_CLK_TCK); + +//--------------------------------------------------------------------------------------// + +inline std::string +time_repr(int64_t _unit) +{ + switch(_unit) + { + case nsec: return "nsec"; break; + case usec: return "usec"; break; + case msec: return "msec"; break; + case csec: return "csec"; break; + case dsec: return "dsec"; break; + case sec: return "sec"; break; + default: return "UNK"; break; + } + return std::string{}; +} + +//--------------------------------------------------------------------------------------// + +inline std::string +mem_repr(int64_t _unit) +{ + switch(_unit) + { + case byte: return "B"; break; + case kilobyte: return "KB"; break; + case megabyte: return "MB"; break; + case gigabyte: return "GB"; break; + case terabyte: return "TB"; break; + case petabyte: return "PB"; break; + case kibibyte: return "KiB"; break; + case mebibyte: return "MiB"; break; + case gibibyte: return "GiB"; break; + case tebibyte: return "TiB"; break; + case pebibyte: return "PiB"; break; + default: return "UNK"; break; + } + return std::string{}; +} + +//--------------------------------------------------------------------------------------// + +inline std::string +freq_repr(int64_t _unit) +{ + switch(_unit) + { + case hertz: return "Hz"; break; + case kilohertz: return "KHz"; break; + case megahertz: return "MHz"; break; + case gigahertz: return "GHz"; break; + default: return "UNK"; break; + } + return std::string{}; +} + +//--------------------------------------------------------------------------------------// + +inline std::string +power_repr(int64_t _unit) +{ + switch(_unit) + { + case nanowatt: return "nanowatts"; break; + case microwatt: return "microwatts"; break; + case milliwatt: return "milliwatts"; break; + case watt: return "watts"; break; + case kilowatt: return "kilowatts"; break; + case megawatt: return "megawatts"; break; + case gigawatt: return "gigawatts"; break; + default: return "UNK"; break; + } + return std::string{}; +} + +//--------------------------------------------------------------------------------------// + +inline std::tuple +get_memory_unit(std::string _unit) +{ + using string_t = std::string; + using return_type = std::tuple; + using inner_t = std::tuple; + + if(_unit.length() == 0) return return_type{"MB", units::megabyte}; + + for(auto& itr : _unit) + itr = tolower(itr); + + for(const auto& itr : {inner_t{"byte", "b", units::byte}, + inner_t{"kilobyte", "kb", units::kilobyte}, + inner_t{"megabyte", "mb", units::megabyte}, + inner_t{"gigabyte", "gb", units::gigabyte}, + inner_t{"terabyte", "tb", units::terabyte}, + inner_t{"petabyte", "pb", units::petabyte}, + inner_t{"kibibyte", "kib", units::KiB}, + inner_t{"mebibyte", "mib", units::MiB}, + inner_t{"gibibyte", "gib", units::GiB}, + inner_t{"tebibyte", "tib", units::TiB}, + inner_t{"pebibyte", "pib", units::PiB}}) + { + if(_unit == std::get<0>(itr) || _unit == std::get<1>(itr)) + { + if(std::get<2>(itr) == units::byte) + return return_type{std::get<0>(itr), std::get<2>(itr)}; + return return_type{mem_repr(std::get<2>(itr)), std::get<2>(itr)}; + } + } + + std::cerr << "Warning!! No memory unit matching \"" << _unit << "\". Using default..." + << std::endl; + + return return_type{"MB", units::megabyte}; +} + +//--------------------------------------------------------------------------------------// + +inline std::tuple +get_timing_unit(std::string _unit) +{ + using string_t = std::string; + using strset_t = std::unordered_set; + using return_type = std::tuple; + using inner_t = std::tuple; + + if(_unit.length() == 0) return return_type{"sec", units::sec}; + + for(auto& itr : _unit) + itr = tolower(itr); + + for(const auto& itr : + {inner_t{"nsec", strset_t{"ns", "nanosecond", "nanoseconds"}, units::nsec}, + inner_t{"usec", strset_t{"us", "microsecond", "microseconds"}, units::usec}, + inner_t{"msec", strset_t{"ms", "millisecond", "milliseconds"}, units::msec}, + inner_t{"csec", strset_t{"cs", "centisecond", "centiseconds"}, units::csec}, + inner_t{"dsec", strset_t{"ds", "decisecond", "deciseconds"}, units::dsec}, + inner_t{"sec", strset_t{"s", "second", "seconds"}, units::sec}, + inner_t{"min", strset_t{"minute", "minutes"}, units::minute}, + inner_t{"hr", strset_t{"hr", "hour", "hours"}, units::hour}}) + { + if(_unit == std::get<0>(itr) || std::get<1>(itr).find(_unit) != std::get<1>(itr).end()) + { + return return_type{time_repr(std::get<2>(itr)), std::get<2>(itr)}; + } + } + + std::cerr << "Warning!! No timing unit matching \"" << _unit << "\". Using default..." + << std::endl; + + return return_type{"sec", units::sec}; +} + +//--------------------------------------------------------------------------------------// + +inline std::tuple +get_frequncy_unit(std::string _unit) +{ + using string_t = std::string; + using return_type = std::tuple; + using inner_t = std::tuple; + + if(_unit.length() == 0) return return_type{"MHz", units::megahertz}; + + for(auto& itr : _unit) + itr = tolower(itr); + + for(const auto& itr : {inner_t{"hertz", "hz", units::hertz}, + inner_t{"kilohertz", "khz", units::kilohertz}, + inner_t{"megahertz", "mhz", units::megahertz}, + inner_t{"gigahertz", "ghz", units::gigahertz}}) + { + if(_unit == std::get<0>(itr) || _unit == std::get<1>(itr)) + { + return return_type{freq_repr(std::get<2>(itr)), std::get<2>(itr)}; + } + } + + std::cerr << "Warning!! No frequency unit matching \"" << _unit << "\". Using default..." + << std::endl; + + return return_type{"MHz", units::megahertz}; +} + +//--------------------------------------------------------------------------------------// + +inline std::tuple +get_power_unit(const std::string& _unit) +{ + using string_t = std::string; + using return_type = std::tuple; + using inner_t = std::tuple; + + if(_unit.length() == 0) return return_type{"watts", units::watt}; + + auto _lunit = _unit; + for(auto& itr : _lunit) + itr = tolower(itr); + + for(const auto& itr : {inner_t{"nanowatt", "nW", units::nanowatt}, + inner_t{"microwatt", "uW", units::microwatt}, + inner_t{"milliwatt", "mW", units::milliwatt}, + inner_t{"watt", "W", units::watt}, + inner_t{"kilowatt", "KW", units::kilowatt}, + inner_t{"megawatt", "MW", units::megawatt}, + inner_t{"gigawatt", "GW", units::gigawatt}}) + { + if(_lunit == std::get<0>(itr) || _lunit + "s" == std::get<0>(itr) || + _unit == std::get<1>(itr)) + { + return return_type{power_repr(std::get<2>(itr)), std::get<2>(itr)}; + } + } + + std::cerr << "Warning!! No power unit matching \"" << _unit << "\". Using default..." + << std::endl; + + return return_type{"watts", units::watt}; +} + +//--------------------------------------------------------------------------------------// + +namespace temperature +{ +enum unit_system : int8_t +{ + Celsius = 0, + Fahrenheit, + Kelvin +}; + +template +Tp +convert(Tp _v, unit_system _from, unit_system _to) +{ + switch(_from) + { + case Celsius: + { + switch(_to) + { + case Celsius: return _v; + case Fahrenheit: return static_cast((_v * 1.8) + 32); + case Kelvin: return (_v - 273); + } + } + case Fahrenheit: + { + switch(_to) + { + case Celsius: return static_cast((_v - 32) / 1.8); + case Fahrenheit: return _v; + case Kelvin: return (_v - 273); + } + } + case Kelvin: + { + switch(_to) + { + case Celsius: return (_v + 273); + case Fahrenheit: return static_cast(((_v + 273) * 1.8) + 32); + case Kelvin: return _v; + } + } + } +} +} // namespace temperature +} // namespace units +} // namespace common +} // namespace rocprofiler diff --git a/source/lib/plugins/CMakeLists.txt b/source/lib/plugins/CMakeLists.txt new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/source/lib/plugins/CMakeLists.txt @@ -0,0 +1 @@ + diff --git a/source/lib/rocprofiler/CMakeLists.txt b/source/lib/rocprofiler/CMakeLists.txt new file mode 100644 index 0000000000..f4b02039cb --- /dev/null +++ b/source/lib/rocprofiler/CMakeLists.txt @@ -0,0 +1,30 @@ +set(ROCPROFILER_LIB_HEADERS config_helpers.hpp config_internal.hpp tracer.hpp) +set(ROCPROFILER_LIB_SOURCES config_internal.cpp rocprofiler_config.cpp) + +add_library(rocprofiler-library SHARED) +add_library(rocprofiler::rocprofiler-library ALIAS rocprofiler-library) + +target_sources(rocprofiler-library PRIVATE ${ROCPROFILER_LIB_SOURCES} + ${ROCPROFILER_LIB_HEADERS}) + +add_subdirectory(hsa) + +target_link_libraries( + rocprofiler-library + PUBLIC rocprofiler::rocprofiler-headers + PRIVATE rocprofiler::rocprofiler-build-flags + rocprofiler::rocprofiler-memcheck + rocprofiler::rocprofiler-common-library + rocprofiler::rocprofiler-stdcxxfs + rocprofiler::rocprofiler-dl + rocprofiler::rocprofiler-hip + rocprofiler::rocprofiler-amd-comgr + rocprofiler::rocprofiler-hsa-runtime) +target_compile_definitions( + rocprofiler-library PRIVATE AMD_INTERNAL_BUILD=1 PROF_API_IMPL=1 + HIP_PROF_HIP_API_STRING=1 __HIP_PLATFORM_AMD__=1) +set_target_properties( + rocprofiler-library + PROPERTIES OUTPUT_NAME rocprofiler64 + SOVERSION ${PROJECT_VERSION_MAJOR} + VERSION ${PROJECT_VERSION}) diff --git a/source/lib/rocprofiler/config_helpers.hpp b/source/lib/rocprofiler/config_helpers.hpp new file mode 100644 index 0000000000..f81a4d4453 --- /dev/null +++ b/source/lib/rocprofiler/config_helpers.hpp @@ -0,0 +1,107 @@ + +#pragma once + +#include + +#include +#include +#include +#include + +namespace +{ +inline size_t // NOLINTNEXTLINE +get_domain_max_op(rocprofiler_tracer_activity_domain_t _domain) +{ + switch(_domain) + { + case ACTIVITY_DOMAIN_NONE: return -1; + case ACTIVITY_DOMAIN_HSA_API: return 0; + case ACTIVITY_DOMAIN_HSA_OPS: return 0; + case ACTIVITY_DOMAIN_HIP_OPS: return 0; + case ACTIVITY_DOMAIN_HIP_API: return 0; + case ACTIVITY_DOMAIN_KFD_API: return -1; + case ACTIVITY_DOMAIN_EXT_API: return -1; + case ACTIVITY_DOMAIN_ROCTX: return 0; + case ACTIVITY_DOMAIN_HSA_EVT: return 0; + case ACTIVITY_DOMAIN_NUMBER: return -1; + } + return -1; +} + +template +struct allocator +{ + void construct(Tp* const _p, const Tp& _v) const { ::new((void*) _p) Tp{_v}; } + void construct(Tp* const _p, Tp&& _v) const { ::new((void*) _p) Tp{std::move(_v)}; } + + void destroy(Tp* const _p) const { _p->~Tp(); } + + static constexpr auto size = sizeof(Tp); + using buffer_value_t = char[size]; + + struct buffer_entry + { + std::atomic_flag flag = ATOMIC_FLAG_INIT; + buffer_value_t value = {}; + + void* get() + { + if(flag.test_and_set()) + { + return &value[0]; + } + return nullptr; + } + + bool reset(void* p) + { + if(static_cast(&value[0]) == p) + { + flag.clear(); + return true; + } + return false; + } + }; + + static auto& get_buffer() + { + static auto _v = std::array{}; + return _v; + } + + Tp* allocate(const size_t n) const + { + if(n == 0) return nullptr; + + if(n == 1) + { + // try an find in buffer for data locality + for(auto& itr : get_buffer()) + { + auto* _p = itr.get(); + if(_p) return static_cast(_p); + } + } + + auto* _p = new char[n * size]; + return reinterpret_cast(_p); + } + + void deallocate(Tp* const ptr, const size_t /*unused*/) const + { + for(auto& itr : get_buffer()) + { + if(itr.reset(ptr)) return; + } + + delete ptr; + } + + Tp* allocate(const size_t n, const void* const /* hint */) const { return allocate(n); } + + void reserve(const size_t) {} +}; + +} // namespace diff --git a/source/lib/rocprofiler/config_internal.cpp b/source/lib/rocprofiler/config_internal.cpp new file mode 100644 index 0000000000..95178e2530 --- /dev/null +++ b/source/lib/rocprofiler/config_internal.cpp @@ -0,0 +1,28 @@ + +#include "config_internal.hpp" + +namespace rocprofiler +{ +namespace internal +{ +uint64_t +correlation_config::get_unique_record_id() +{ + static auto _v = std::atomic{}; + return _v++; +} + +bool +domain_config::operator()(rocprofiler_tracer_activity_domain_t _domain) const +{ + return ((1 << _domain) & domains) == (1 << _domain); +} + +bool +domain_config::operator()(rocprofiler_tracer_activity_domain_t _domain, uint32_t _op) const +{ + auto _offset = (_domain * rocprofiler::internal::domain_ops_offset); + return (*this)(_domain) && (opcodes.none() || opcodes.test(_offset + _op)); +} +} // namespace internal +} // namespace rocprofiler diff --git a/source/lib/rocprofiler/config_internal.hpp b/source/lib/rocprofiler/config_internal.hpp new file mode 100644 index 0000000000..7e85791926 --- /dev/null +++ b/source/lib/rocprofiler/config_internal.hpp @@ -0,0 +1,74 @@ + +#pragma once + +#include +#include + +#include +#include +#include +#include +#include + +namespace rocprofiler +{ +namespace internal +{ +// number of bits to reserve all op codes +constexpr size_t domain_ops_offset = ROCPROFILER_DOMAIN_OPS_MAX; +constexpr size_t reserved_domain_size = ROCPROFILER_DOMAIN_OPS_RESERVED * 8; +constexpr size_t max_configs_count = 8; + +struct correlation_config +{ + uint64_t id = 0; + uint64_t external_id = 0; + ::rocprofiler_external_cid_cb_t external_id_callback = nullptr; + + static uint64_t get_unique_record_id(); +}; + +struct domain_config +{ + ::rocprofiler_sync_callback_t user_sync_callback = nullptr; + int64_t domains = 0; + std::bitset opcodes = {}; + + /// check if domain is enabled + bool operator()(::rocprofiler_tracer_activity_domain_t) const; + + /// check if op in a domain is enabled + bool operator()(::rocprofiler_tracer_activity_domain_t, uint32_t) const; +}; + +struct buffer_config +{ + ::rocprofiler_buffer_callback_t callback = nullptr; + uint64_t buffer_size; + // Memory::GenericBuffer* buffer = nullptr; + uint64_t buffer_idx = 0; +}; + +using filter_config = ::rocprofiler_filter_config; + +struct config +{ + // size is used to ensure that we never read past the end of the version + size_t size = 0; // = sizeof(rocprofiler_config) + uint32_t compat_version = 0; // set by user + uint32_t api_version = 0; // set by rocprofiler + uint64_t session_idx = 0; // session id index + void* user_data = nullptr; // user data passed to callbacks + correlation_config* correlation_id = nullptr; // &my_cid_config (optional) + buffer_config* buffer = nullptr; // = &my_buffer_config (required) + domain_config* domain = nullptr; // = &my_domain_config (required) + filter_config* filter = nullptr; // = &my_filter_config (optional) +}; + +std::array& +get_registered_configs(); + +std::array, max_configs_count>& +get_active_configs(); +} // namespace internal +} // namespace rocprofiler diff --git a/source/lib/rocprofiler/hsa/CMakeLists.txt b/source/lib/rocprofiler/hsa/CMakeLists.txt new file mode 100644 index 0000000000..3bd8816d18 --- /dev/null +++ b/source/lib/rocprofiler/hsa/CMakeLists.txt @@ -0,0 +1,10 @@ +set(ROCPROFILER_LIB_HSA_SOURCES hsa.cpp) +set(ROCPROFILER_LIB_HSA_HEADERS hsa.hpp hsa-defines.hpp hsa-types.h hsa-utils.hpp) +target_sources(rocprofiler-library PRIVATE ${ROCPROFILER_LIB_HSA_SOURCES} + ${ROCPROFILER_LIB_HSA_HEADERS}) + +# add_executable(rocr-example hsa.cpp rocr.hpp) target_link_libraries(rocr-example PRIVATE +# rocprofiler-v2) target_include_directories( rocr-example PRIVATE ${PROJECT_SOURCE_DIR} +# ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/src ${PROJECT_BINARY_DIR}/src) +# target_compile_definitions( rocr-example PRIVATE AMD_INTERNAL_BUILD PROF_API_IMPL +# HIP_PROF_HIP_API_STRING=1 __HIP_PLATFORM_AMD__=1) diff --git a/source/lib/rocprofiler/hsa/hsa-defines.hpp b/source/lib/rocprofiler/hsa/hsa-defines.hpp new file mode 100644 index 0000000000..114f34ddee --- /dev/null +++ b/source/lib/rocprofiler/hsa/hsa-defines.hpp @@ -0,0 +1,266 @@ +// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN +// THE SOFTWARE. + +#pragma once + +#define IMPL_DETAIL_EXPAND(X) X +#define IMPL_DETAIL_FOR_EACH_NARG(...) \ + IMPL_DETAIL_FOR_EACH_NARG_(__VA_ARGS__, IMPL_DETAIL_FOR_EACH_RSEQ_N()) +#define IMPL_DETAIL_FOR_EACH_NARG_(...) IMPL_DETAIL_EXPAND(IMPL_DETAIL_FOR_EACH_ARG_N(__VA_ARGS__)) +#define IMPL_DETAIL_FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, N, ...) N +#define IMPL_DETAIL_FOR_EACH_RSEQ_N() 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 +#define IMPL_DETAIL_CONCATENATE(X, Y) X##Y +#define IMPL_DETAIL_FOR_EACH_(N, MACRO, PREFIX, ...) \ + IMPL_DETAIL_EXPAND(IMPL_DETAIL_CONCATENATE(MACRO, N)(PREFIX, __VA_ARGS__)) +#define IMPL_DETAIL_FOR_EACH(MACRO, PREFIX, ...) \ + IMPL_DETAIL_FOR_EACH_(IMPL_DETAIL_FOR_EACH_NARG(__VA_ARGS__), MACRO, PREFIX, __VA_ARGS__) + +#define MEMBER_0(...) +#define MEMBER_1(PREFIX, FIELD) PREFIX.FIELD +#define MEMBER_2(PREFIX, A, B) MEMBER_1(PREFIX, A), MEMBER_1(PREFIX, B) +#define MEMBER_3(PREFIX, A, B, C) MEMBER_2(PREFIX, A, B), MEMBER_1(PREFIX, C) +#define MEMBER_4(PREFIX, A, B, C, D) MEMBER_3(PREFIX, A, B, C), MEMBER_1(PREFIX, D) +#define MEMBER_5(PREFIX, A, B, C, D, E) MEMBER_4(PREFIX, A, B, C, D), MEMBER_1(PREFIX, E) +#define MEMBER_6(PREFIX, A, B, C, D, E, F) MEMBER_5(PREFIX, A, B, C, D, E), MEMBER_1(PREFIX, F) +#define MEMBER_7(PREFIX, A, B, C, D, E, F, G) \ + MEMBER_6(PREFIX, A, B, C, D, E, F), MEMBER_1(PREFIX, G) + +#define MEMBER_8(PREFIX, A, B, C, D, E, F, G, H) \ + MEMBER_7(PREFIX, A, B, C, D, E, F, G), MEMBER_1(PREFIX, H) + +#define MEMBER_9(PREFIX, A, B, C, D, E, F, G, H, I) \ + MEMBER_8(PREFIX, A, B, C, D, E, F, G, H), MEMBER_1(PREFIX, I) + +#define MEMBER_10(PREFIX, A, B, C, D, E, F, G, H, I, J) \ + MEMBER_9(PREFIX, A, B, C, D, E, F, G, H, I), MEMBER_1(PREFIX, J) + +#define MEMBER_11(PREFIX, A, B, C, D, E, F, G, H, I, J, K) \ + MEMBER_10(PREFIX, A, B, C, D, E, F, G, H, I, J), MEMBER_1(PREFIX, K) + +#define MEMBER_12(PREFIX, A, B, C, D, E, F, G, H, I, J, K, L) \ + MEMBER_11(PREFIX, A, B, C, D, E, F, G, H, I, J, K), MEMBER_1(PREFIX, L) + +#define NAMED_MEMBER_0(...) +#define NAMED_MEMBER_1(PREFIX, FIELD) std::make_pair(#FIELD, PREFIX.FIELD) +#define NAMED_MEMBER_2(PREFIX, A, B) NAMED_MEMBER_1(PREFIX, A), NAMED_MEMBER_1(PREFIX, B) +#define NAMED_MEMBER_3(PREFIX, A, B, C) NAMED_MEMBER_2(PREFIX, A, B), NAMED_MEMBER_1(PREFIX, C) +#define NAMED_MEMBER_4(PREFIX, A, B, C, D) \ + NAMED_MEMBER_3(PREFIX, A, B, C), NAMED_MEMBER_1(PREFIX, D) +#define NAMED_MEMBER_5(PREFIX, A, B, C, D, E) \ + NAMED_MEMBER_4(PREFIX, A, B, C, D), NAMED_MEMBER_1(PREFIX, E) +#define NAMED_MEMBER_6(PREFIX, A, B, C, D, E, F) \ + NAMED_MEMBER_5(PREFIX, A, B, C, D, E), NAMED_MEMBER_1(PREFIX, F) +#define NAMED_MEMBER_7(PREFIX, A, B, C, D, E, F, G) \ + NAMED_MEMBER_6(PREFIX, A, B, C, D, E, F), NAMED_MEMBER_1(PREFIX, G) +#define NAMED_MEMBER_8(PREFIX, A, B, C, D, E, F, G, H) \ + NAMED_MEMBER_7(PREFIX, A, B, C, D, E, F, G), NAMED_MEMBER_1(PREFIX, H) +#define NAMED_MEMBER_9(PREFIX, A, B, C, D, E, F, G, H, I) \ + NAMED_MEMBER_8(PREFIX, A, B, C, D, E, F, G, H), NAMED_MEMBER_1(PREFIX, I) +#define NAMED_MEMBER_10(PREFIX, A, B, C, D, E, F, G, H, I, J) \ + NAMED_MEMBER_9(PREFIX, A, B, C, D, E, F, G, H, I), NAMED_MEMBER_1(PREFIX, J) +#define NAMED_MEMBER_11(PREFIX, A, B, C, D, E, F, G, H, I, J, K) \ + NAMED_MEMBER_10(PREFIX, A, B, C, D, E, F, G, H, I, J), NAMED_MEMBER_1(PREFIX, K) +#define NAMED_MEMBER_12(PREFIX, A, B, C, D, E, F, G, H, I, J, K, L) \ + NAMED_MEMBER_11(PREFIX, A, B, C, D, E, F, G, H, I, J, K), NAMED_MEMBER_1(PREFIX, L) + +/// @def GET_MEMBER_FIELDS +/// @param VAR some struct instance +/// @param ... The member fields of the struct +/// +/// @brief this macro is used to expand one variable (VAR) + one or more member fields (FIELDS) +/// into a sequence of something like: `(VAR.FIELD, ...)` +/// For example, `GET_MEMBER_FIELDS(foo, a, b, c)` would transform into `foo.a, foo.b, foo.c`: +/// +/// @code{.cpp} +/// +/// struct Foo +/// { +/// int a; +/// float b; +/// double c; +/// }; +/// +/// // some function taking int, float, and double +/// void some_function(int, float, double); +/// +/// // overload to some_function accepting Foo instance and using +/// // the args to invoke "real" function +/// void some_function(Foo _foo_v) +/// { +/// some_function(GET_MEMBER_FIELDS(_foo_v, a, b, c)); +/// } +/// +/// int main() +/// { +/// Foo _foo_v = {-1, 0.5f, 2.0}; +/// invoke_some_function(_foo_v); +/// } +/// +/// @code +#define GET_MEMBER_FIELDS(VAR, ...) IMPL_DETAIL_FOR_EACH(MEMBER_, VAR, __VA_ARGS__) +#define GET_NAMED_MEMBER_FIELDS(VAR, ...) IMPL_DETAIL_FOR_EACH(NAMED_MEMBER_, VAR, __VA_ARGS__) + +#define HSA_API_INFO_DEFINITION_0(HSA_DOMAIN, HSA_TABLE, HSA_API_ID, HSA_FUNC, HSA_FUNC_PTR) \ + namespace rocprofiler \ + { \ + namespace hsa \ + { \ + template <> \ + struct hsa_api_info \ + { \ + static constexpr auto domain_idx = HSA_DOMAIN; \ + static constexpr auto table_idx = HSA_TABLE; \ + static constexpr auto operation_idx = HSA_API_ID; \ + static constexpr auto name = #HSA_FUNC; \ + \ + using this_type = hsa_api_info; \ + using base_type = hsa_api_impl; \ + \ + static auto& get_table() { return hsa_table_lookup{}(); } \ + \ + template \ + static auto& get_table(TableT& _v) \ + { \ + return hsa_table_lookup{}(_v); \ + } \ + \ + template \ + static auto& get_table_func(TableT& _table) \ + { \ + if constexpr(std::is_pointer::value) \ + { \ + assert(_table != nullptr && "nullptr to HSA table for " #HSA_FUNC " function"); \ + return _table->HSA_FUNC_PTR; \ + } \ + else \ + { \ + return _table.HSA_FUNC_PTR; \ + } \ + } \ + \ + static auto& get_table_func() { return get_table_func(get_table()); } \ + \ + template \ + static auto& get_api_data_args(DataT& _data) \ + { \ + return _data.api_data.args.HSA_FUNC; \ + } \ + \ + template \ + static auto get_functor(RetT (*)(Args...)) \ + { \ + if constexpr(std::is_void::value) \ + return [](Args... args) -> RetT { base_type::functor(args...); }; \ + else \ + return [](Args... args) -> RetT { return base_type::functor(args...); }; \ + } \ + \ + static auto get_functor() { return get_functor(get_table_func()); } \ + \ + static std::string as_string(hsa_trace_data_t) { return std::string{name} + "()"; } \ + \ + static std::string as_named_string(hsa_trace_data_t) { return std::string{name} + "()"; } \ + \ + static std::vector> as_arg_list(hsa_trace_data_t) \ + { \ + return {}; \ + } \ + }; \ + } \ + } + +#define HSA_API_INFO_DEFINITION_V(HSA_DOMAIN, HSA_TABLE, HSA_API_ID, HSA_FUNC, HSA_FUNC_PTR, ...) \ + namespace rocprofiler \ + { \ + namespace hsa \ + { \ + template <> \ + struct hsa_api_info \ + { \ + static constexpr auto domain_idx = HSA_DOMAIN; \ + static constexpr auto table_idx = HSA_TABLE; \ + static constexpr auto operation_idx = HSA_API_ID; \ + static constexpr auto name = #HSA_FUNC; \ + \ + using this_type = hsa_api_info; \ + using base_type = hsa_api_impl; \ + \ + static auto& get_table() { return hsa_table_lookup{}(); } \ + \ + template \ + static auto& get_table(TableT& _v) \ + { \ + return hsa_table_lookup{}(_v); \ + } \ + \ + template \ + static auto& get_table_func(TableT& _table) \ + { \ + if constexpr(std::is_pointer::value) \ + { \ + assert(_table != nullptr && "nullptr to HSA table for " #HSA_FUNC " function"); \ + return _table->HSA_FUNC_PTR; \ + } \ + else \ + { \ + return _table.HSA_FUNC_PTR; \ + } \ + } \ + \ + static auto& get_table_func() { return get_table_func(get_table()); } \ + \ + template \ + static auto& get_api_data_args(DataT& _data) \ + { \ + return _data.api_data.args.HSA_FUNC; \ + } \ + \ + template \ + static auto get_functor(RetT (*)(Args...)) \ + { \ + if constexpr(std::is_void::value) \ + return [](Args... args) -> RetT { base_type::functor(args...); }; \ + else \ + return [](Args... args) -> RetT { return base_type::functor(args...); }; \ + } \ + \ + static auto get_functor() { return get_functor(get_table_func()); } \ + \ + static std::string as_string(hsa_trace_data_t trace_data) \ + { \ + return utils::join(utils::join_args{std::string{name} + "(", ")", ", "}, \ + GET_MEMBER_FIELDS(get_api_data_args(trace_data), __VA_ARGS__)); \ + } \ + \ + static std::string as_named_string(hsa_trace_data_t trace_data) \ + { \ + return utils::join( \ + utils::join_args{std::string{name} + "(", ")", ", "}, \ + GET_NAMED_MEMBER_FIELDS(get_api_data_args(trace_data), __VA_ARGS__)); \ + } \ + \ + static auto as_arg_list(hsa_trace_data_t trace_data) \ + { \ + return utils::stringize( \ + GET_NAMED_MEMBER_FIELDS(get_api_data_args(trace_data), __VA_ARGS__)); \ + } \ + }; \ + } \ + } diff --git a/source/lib/rocprofiler/hsa/hsa-ostream.hpp b/source/lib/rocprofiler/hsa/hsa-ostream.hpp new file mode 100644 index 0000000000..2b5336f8cc --- /dev/null +++ b/source/lib/rocprofiler/hsa/hsa-ostream.hpp @@ -0,0 +1,1767 @@ +// automatically generated +/* +Copyright (c) 2018 Advanced Micro Devices, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +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 +AUTHORS 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 IN +THE SOFTWARE. +*/ + +#pragma once + +#include "lib/rocprofiler/tracer.hpp" + +#include +#include + +namespace rocprofiler +{ +namespace hsa +{ +static int HSA_depth_max = 1; +static int HSA_depth_max_cnt = 0; +static std::string HSA_structs_regex = ""; +// begin ostream ops for HSA +// basic ostream ops +namespace detail +{ +template + +inline static std::ostream& +operator<<(std::ostream& out, const T& v) +{ + using std:: operator<<; + static bool recursion = false; + if(recursion == false) + { + recursion = true; + out << v; + recursion = false; + } + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const unsigned char& v) +{ + out << (unsigned int) v; + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const char& v) +{ + out << (unsigned char) v; + return out; +} +// End of basic ostream ops + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_dim3_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_dim3_t::z").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "z="); + rocprofiler::hsa::detail::operator<<(out, v.z); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_dim3_t::y").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "y="); + rocprofiler::hsa::detail::operator<<(out, v.y); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_dim3_t::x").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "x="); + rocprofiler::hsa::detail::operator<<(out, v.x); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_agent_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_agent_t::handle").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "handle="); + rocprofiler::hsa::detail::operator<<(out, v.handle); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_cache_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_cache_t::handle").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "handle="); + rocprofiler::hsa::detail::operator<<(out, v.handle); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_signal_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_signal_t::handle").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "handle="); + rocprofiler::hsa::detail::operator<<(out, v.handle); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_signal_group_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_signal_group_t::handle").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "handle="); + rocprofiler::hsa::detail::operator<<(out, v.handle); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_region_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_region_t::handle").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "handle="); + rocprofiler::hsa::detail::operator<<(out, v.handle); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_queue_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_queue_t::id").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "id="); + rocprofiler::hsa::detail::operator<<(out, v.id); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_queue_t::reserved1").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "reserved1="); + rocprofiler::hsa::detail::operator<<(out, v.reserved1); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_queue_t::size").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "size="); + rocprofiler::hsa::detail::operator<<(out, v.size); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_queue_t::doorbell_signal").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "doorbell_signal="); + rocprofiler::hsa::detail::operator<<(out, v.doorbell_signal); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_queue_t::features").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "features="); + rocprofiler::hsa::detail::operator<<(out, v.features); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_queue_t::type").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "type="); + rocprofiler::hsa::detail::operator<<(out, v.type); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_kernel_dispatch_packet_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_kernel_dispatch_packet_t::completion_signal").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "completion_signal="); + rocprofiler::hsa::detail::operator<<(out, v.completion_signal); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_kernel_dispatch_packet_t::reserved2").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "reserved2="); + rocprofiler::hsa::detail::operator<<(out, v.reserved2); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_kernel_dispatch_packet_t::kernel_object").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "kernel_object="); + rocprofiler::hsa::detail::operator<<(out, v.kernel_object); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_kernel_dispatch_packet_t::group_segment_size") + .find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "group_segment_size="); + rocprofiler::hsa::detail::operator<<(out, v.group_segment_size); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_kernel_dispatch_packet_t::private_segment_size") + .find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "private_segment_size="); + rocprofiler::hsa::detail::operator<<(out, v.private_segment_size); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_kernel_dispatch_packet_t::grid_size_z").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "grid_size_z="); + rocprofiler::hsa::detail::operator<<(out, v.grid_size_z); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_kernel_dispatch_packet_t::grid_size_y").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "grid_size_y="); + rocprofiler::hsa::detail::operator<<(out, v.grid_size_y); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_kernel_dispatch_packet_t::grid_size_x").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "grid_size_x="); + rocprofiler::hsa::detail::operator<<(out, v.grid_size_x); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_kernel_dispatch_packet_t::reserved0").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "reserved0="); + rocprofiler::hsa::detail::operator<<(out, v.reserved0); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_kernel_dispatch_packet_t::workgroup_size_z").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "workgroup_size_z="); + rocprofiler::hsa::detail::operator<<(out, v.workgroup_size_z); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_kernel_dispatch_packet_t::workgroup_size_y").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "workgroup_size_y="); + rocprofiler::hsa::detail::operator<<(out, v.workgroup_size_y); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_kernel_dispatch_packet_t::workgroup_size_x").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "workgroup_size_x="); + rocprofiler::hsa::detail::operator<<(out, v.workgroup_size_x); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_kernel_dispatch_packet_t::setup").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "setup="); + rocprofiler::hsa::detail::operator<<(out, v.setup); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_kernel_dispatch_packet_t::header").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "header="); + rocprofiler::hsa::detail::operator<<(out, v.header); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_agent_dispatch_packet_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_agent_dispatch_packet_t::completion_signal").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "completion_signal="); + rocprofiler::hsa::detail::operator<<(out, v.completion_signal); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_agent_dispatch_packet_t::reserved2").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "reserved2="); + rocprofiler::hsa::detail::operator<<(out, v.reserved2); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_agent_dispatch_packet_t::arg").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "arg="); + rocprofiler::hsa::detail::operator<<(out, v.arg); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_agent_dispatch_packet_t::reserved0").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "reserved0="); + rocprofiler::hsa::detail::operator<<(out, v.reserved0); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_agent_dispatch_packet_t::type").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "type="); + rocprofiler::hsa::detail::operator<<(out, v.type); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_agent_dispatch_packet_t::header").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "header="); + rocprofiler::hsa::detail::operator<<(out, v.header); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_barrier_and_packet_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_barrier_and_packet_t::completion_signal").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "completion_signal="); + rocprofiler::hsa::detail::operator<<(out, v.completion_signal); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_barrier_and_packet_t::reserved2").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "reserved2="); + rocprofiler::hsa::detail::operator<<(out, v.reserved2); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_barrier_and_packet_t::dep_signal").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "dep_signal="); + rocprofiler::hsa::detail::operator<<(out, v.dep_signal); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_barrier_and_packet_t::reserved1").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "reserved1="); + rocprofiler::hsa::detail::operator<<(out, v.reserved1); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_barrier_and_packet_t::reserved0").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "reserved0="); + rocprofiler::hsa::detail::operator<<(out, v.reserved0); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_barrier_and_packet_t::header").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "header="); + rocprofiler::hsa::detail::operator<<(out, v.header); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_barrier_or_packet_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_barrier_or_packet_t::completion_signal").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "completion_signal="); + rocprofiler::hsa::detail::operator<<(out, v.completion_signal); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_barrier_or_packet_t::reserved2").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "reserved2="); + rocprofiler::hsa::detail::operator<<(out, v.reserved2); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_barrier_or_packet_t::dep_signal").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "dep_signal="); + rocprofiler::hsa::detail::operator<<(out, v.dep_signal); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_barrier_or_packet_t::reserved1").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "reserved1="); + rocprofiler::hsa::detail::operator<<(out, v.reserved1); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_barrier_or_packet_t::reserved0").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "reserved0="); + rocprofiler::hsa::detail::operator<<(out, v.reserved0); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_barrier_or_packet_t::header").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "header="); + rocprofiler::hsa::detail::operator<<(out, v.header); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_isa_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_isa_t::handle").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "handle="); + rocprofiler::hsa::detail::operator<<(out, v.handle); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_wavefront_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_wavefront_t::handle").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "handle="); + rocprofiler::hsa::detail::operator<<(out, v.handle); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_code_object_reader_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_code_object_reader_t::handle").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "handle="); + rocprofiler::hsa::detail::operator<<(out, v.handle); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_executable_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_executable_t::handle").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "handle="); + rocprofiler::hsa::detail::operator<<(out, v.handle); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_loaded_code_object_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_loaded_code_object_t::handle").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "handle="); + rocprofiler::hsa::detail::operator<<(out, v.handle); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_executable_symbol_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_executable_symbol_t::handle").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "handle="); + rocprofiler::hsa::detail::operator<<(out, v.handle); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_code_object_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_code_object_t::handle").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "handle="); + rocprofiler::hsa::detail::operator<<(out, v.handle); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_callback_data_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_callback_data_t::handle").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "handle="); + rocprofiler::hsa::detail::operator<<(out, v.handle); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_code_symbol_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_code_symbol_t::handle").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "handle="); + rocprofiler::hsa::detail::operator<<(out, v.handle); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_ext_image_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_ext_image_t::handle").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "handle="); + rocprofiler::hsa::detail::operator<<(out, v.handle); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_ext_image_format_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_ext_image_format_t::channel_order").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "channel_order="); + rocprofiler::hsa::detail::operator<<(out, v.channel_order); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_image_format_t::channel_type").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "channel_type="); + rocprofiler::hsa::detail::operator<<(out, v.channel_type); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_ext_image_descriptor_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_ext_image_descriptor_t::format").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "format="); + rocprofiler::hsa::detail::operator<<(out, v.format); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_image_descriptor_t::array_size").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "array_size="); + rocprofiler::hsa::detail::operator<<(out, v.array_size); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_image_descriptor_t::depth").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "depth="); + rocprofiler::hsa::detail::operator<<(out, v.depth); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_image_descriptor_t::height").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "height="); + rocprofiler::hsa::detail::operator<<(out, v.height); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_image_descriptor_t::width").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "width="); + rocprofiler::hsa::detail::operator<<(out, v.width); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_image_descriptor_t::geometry").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "geometry="); + rocprofiler::hsa::detail::operator<<(out, v.geometry); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_ext_image_data_info_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_ext_image_data_info_t::alignment").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "alignment="); + rocprofiler::hsa::detail::operator<<(out, v.alignment); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_image_data_info_t::size").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "size="); + rocprofiler::hsa::detail::operator<<(out, v.size); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_ext_image_region_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_ext_image_region_t::range").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "range="); + rocprofiler::hsa::detail::operator<<(out, v.range); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_image_region_t::offset").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "offset="); + rocprofiler::hsa::detail::operator<<(out, v.offset); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_ext_sampler_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_ext_sampler_t::handle").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "handle="); + rocprofiler::hsa::detail::operator<<(out, v.handle); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_ext_sampler_descriptor_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_ext_sampler_descriptor_t::address_mode").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "address_mode="); + rocprofiler::hsa::detail::operator<<(out, v.address_mode); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_sampler_descriptor_t::filter_mode").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "filter_mode="); + rocprofiler::hsa::detail::operator<<(out, v.filter_mode); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_sampler_descriptor_t::coordinate_mode").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "coordinate_mode="); + rocprofiler::hsa::detail::operator<<(out, v.coordinate_mode); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_ext_images_1_00_pfn_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_ext_images_1_00_pfn_t::hsa_ext_sampler_destroy") + .find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "hsa_ext_sampler_destroy="); + rocprofiler::hsa::detail::operator<<(out, v.hsa_ext_sampler_destroy); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_images_1_00_pfn_t::hsa_ext_sampler_create") + .find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "hsa_ext_sampler_create="); + rocprofiler::hsa::detail::operator<<(out, v.hsa_ext_sampler_create); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_images_1_00_pfn_t::hsa_ext_image_copy").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "hsa_ext_image_copy="); + rocprofiler::hsa::detail::operator<<(out, v.hsa_ext_image_copy); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_images_1_00_pfn_t::hsa_ext_image_destroy") + .find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "hsa_ext_image_destroy="); + rocprofiler::hsa::detail::operator<<(out, v.hsa_ext_image_destroy); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_images_1_00_pfn_t::hsa_ext_image_data_get_info") + .find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "hsa_ext_image_data_get_info="); + rocprofiler::hsa::detail::operator<<(out, v.hsa_ext_image_data_get_info); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_images_1_00_pfn_t::hsa_ext_image_get_capability") + .find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "hsa_ext_image_get_capability="); + rocprofiler::hsa::detail::operator<<(out, v.hsa_ext_image_get_capability); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_ext_images_1_pfn_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_ext_images_1_pfn_t::hsa_ext_image_data_get_info_with_layout") + .find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "hsa_ext_image_data_get_info_with_layout="); + rocprofiler::hsa::detail::operator<<(out, v.hsa_ext_image_data_get_info_with_layout); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_images_1_pfn_t::hsa_ext_image_get_capability_with_layout") + .find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "hsa_ext_image_get_capability_with_layout="); + rocprofiler::hsa::detail::operator<<(out, v.hsa_ext_image_get_capability_with_layout); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_images_1_pfn_t::hsa_ext_sampler_destroy").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "hsa_ext_sampler_destroy="); + rocprofiler::hsa::detail::operator<<(out, v.hsa_ext_sampler_destroy); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_images_1_pfn_t::hsa_ext_sampler_create").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "hsa_ext_sampler_create="); + rocprofiler::hsa::detail::operator<<(out, v.hsa_ext_sampler_create); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_images_1_pfn_t::hsa_ext_image_copy").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "hsa_ext_image_copy="); + rocprofiler::hsa::detail::operator<<(out, v.hsa_ext_image_copy); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_images_1_pfn_t::hsa_ext_image_destroy").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "hsa_ext_image_destroy="); + rocprofiler::hsa::detail::operator<<(out, v.hsa_ext_image_destroy); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_images_1_pfn_t::hsa_ext_image_data_get_info") + .find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "hsa_ext_image_data_get_info="); + rocprofiler::hsa::detail::operator<<(out, v.hsa_ext_image_data_get_info); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_ext_images_1_pfn_t::hsa_ext_image_get_capability") + .find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "hsa_ext_image_get_capability="); + rocprofiler::hsa::detail::operator<<(out, v.hsa_ext_image_get_capability); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_vendor_packet_header_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_amd_vendor_packet_header_t::reserved").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "reserved="); + rocprofiler::hsa::detail::operator<<(out, v.reserved); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_vendor_packet_header_t::AmdFormat").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "AmdFormat="); + rocprofiler::hsa::detail::operator<<(out, v.AmdFormat); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_vendor_packet_header_t::header").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "header="); + rocprofiler::hsa::detail::operator<<(out, v.header); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_barrier_value_packet_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_amd_barrier_value_packet_t::completion_signal") + .find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "completion_signal="); + rocprofiler::hsa::detail::operator<<(out, v.completion_signal); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_barrier_value_packet_t::reserved3").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "reserved3="); + rocprofiler::hsa::detail::operator<<(out, v.reserved3); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_barrier_value_packet_t::reserved2").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "reserved2="); + rocprofiler::hsa::detail::operator<<(out, v.reserved2); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_barrier_value_packet_t::reserved1").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "reserved1="); + rocprofiler::hsa::detail::operator<<(out, v.reserved1); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_barrier_value_packet_t::cond").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "cond="); + rocprofiler::hsa::detail::operator<<(out, v.cond); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_barrier_value_packet_t::mask").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "mask="); + rocprofiler::hsa::detail::operator<<(out, v.mask); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_barrier_value_packet_t::value").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "value="); + rocprofiler::hsa::detail::operator<<(out, v.value); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_barrier_value_packet_t::signal").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "signal="); + rocprofiler::hsa::detail::operator<<(out, v.signal); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_barrier_value_packet_t::reserved0").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "reserved0="); + rocprofiler::hsa::detail::operator<<(out, v.reserved0); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_barrier_value_packet_t::header").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "header="); + rocprofiler::hsa::detail::operator<<(out, v.header); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_hdp_flush_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_amd_hdp_flush_t::HDP_REG_FLUSH_CNTL").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "HDP_REG_FLUSH_CNTL="); + rocprofiler::hsa::detail::operator<<(out, v.HDP_REG_FLUSH_CNTL); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_hdp_flush_t::HDP_MEM_FLUSH_CNTL").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "HDP_MEM_FLUSH_CNTL="); + rocprofiler::hsa::detail::operator<<(out, v.HDP_MEM_FLUSH_CNTL); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_profiling_dispatch_time_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_amd_profiling_dispatch_time_t::end").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "end="); + rocprofiler::hsa::detail::operator<<(out, v.end); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_profiling_dispatch_time_t::start").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "start="); + rocprofiler::hsa::detail::operator<<(out, v.start); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_profiling_async_copy_time_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_amd_profiling_async_copy_time_t::end").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "end="); + rocprofiler::hsa::detail::operator<<(out, v.end); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_profiling_async_copy_time_t::start").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "start="); + rocprofiler::hsa::detail::operator<<(out, v.start); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_memory_pool_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_amd_memory_pool_t::handle").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "handle="); + rocprofiler::hsa::detail::operator<<(out, v.handle); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_pitched_ptr_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_pitched_ptr_t::slice").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "slice="); + rocprofiler::hsa::detail::operator<<(out, v.slice); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_pitched_ptr_t::pitch").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "pitch="); + rocprofiler::hsa::detail::operator<<(out, v.pitch); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_memory_pool_link_info_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_amd_memory_pool_link_info_t::numa_distance").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "numa_distance="); + rocprofiler::hsa::detail::operator<<(out, v.numa_distance); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_memory_pool_link_info_t::link_type").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "link_type="); + rocprofiler::hsa::detail::operator<<(out, v.link_type); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_memory_pool_link_info_t::max_bandwidth").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "max_bandwidth="); + rocprofiler::hsa::detail::operator<<(out, v.max_bandwidth); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_memory_pool_link_info_t::min_bandwidth").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "min_bandwidth="); + rocprofiler::hsa::detail::operator<<(out, v.min_bandwidth); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_memory_pool_link_info_t::max_latency").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "max_latency="); + rocprofiler::hsa::detail::operator<<(out, v.max_latency); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_memory_pool_link_info_t::min_latency").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "min_latency="); + rocprofiler::hsa::detail::operator<<(out, v.min_latency); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_image_descriptor_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_amd_image_descriptor_t::data").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "data="); + rocprofiler::hsa::detail::operator<<(out, v.data); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_image_descriptor_t::deviceID").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "deviceID="); + rocprofiler::hsa::detail::operator<<(out, v.deviceID); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_image_descriptor_t::version").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "version="); + rocprofiler::hsa::detail::operator<<(out, v.version); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_pointer_info_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_amd_pointer_info_t::global_flags").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "global_flags="); + rocprofiler::hsa::detail::operator<<(out, v.global_flags); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_pointer_info_t::agentOwner").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "agentOwner="); + rocprofiler::hsa::detail::operator<<(out, v.agentOwner); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_pointer_info_t::sizeInBytes").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "sizeInBytes="); + rocprofiler::hsa::detail::operator<<(out, v.sizeInBytes); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_pointer_info_t::type").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "type="); + rocprofiler::hsa::detail::operator<<(out, v.type); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_pointer_info_t::size").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "size="); + rocprofiler::hsa::detail::operator<<(out, v.size); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_ipc_memory_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_amd_ipc_memory_t::handle").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "handle="); + rocprofiler::hsa::detail::operator<<(out, v.handle); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_gpu_memory_fault_info_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_amd_gpu_memory_fault_info_t::fault_reason_mask") + .find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "fault_reason_mask="); + rocprofiler::hsa::detail::operator<<(out, v.fault_reason_mask); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_gpu_memory_fault_info_t::virtual_address") + .find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "virtual_address="); + rocprofiler::hsa::detail::operator<<(out, v.virtual_address); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_gpu_memory_fault_info_t::agent").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "agent="); + rocprofiler::hsa::detail::operator<<(out, v.agent); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_event_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_amd_event_t::event_type").find(HSA_structs_regex) != std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "event_type="); + rocprofiler::hsa::detail::operator<<(out, v.event_type); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_svm_attribute_pair_t& v) +{ + std::operator<<(out, '{'); + HSA_depth_max_cnt++; + if(HSA_depth_max == -1 || HSA_depth_max_cnt <= HSA_depth_max) + { + if(std::string("hsa_amd_svm_attribute_pair_t::value").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "value="); + rocprofiler::hsa::detail::operator<<(out, v.value); + rocprofiler::hsa::detail::operator<<(out, ", "); + } + if(std::string("hsa_amd_svm_attribute_pair_t::attribute").find(HSA_structs_regex) != + std::string::npos) + { + rocprofiler::hsa::detail::operator<<(out, "attribute="); + rocprofiler::hsa::detail::operator<<(out, v.attribute); + } + }; + HSA_depth_max_cnt--; + std::operator<<(out, '}'); + return out; +} +// end ostream ops for HSA +} // namespace detail +} // namespace hsa +} // namespace rocprofiler + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_dim3_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_agent_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_cache_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_signal_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_signal_group_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_region_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_queue_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_kernel_dispatch_packet_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_agent_dispatch_packet_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_barrier_and_packet_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_barrier_or_packet_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_isa_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_wavefront_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_code_object_reader_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_executable_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_loaded_code_object_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_executable_symbol_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_code_object_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_callback_data_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_code_symbol_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_ext_image_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_ext_image_format_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_ext_image_descriptor_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_ext_image_data_info_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_ext_image_region_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_ext_sampler_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_ext_sampler_descriptor_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_ext_images_1_00_pfn_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_ext_images_1_pfn_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_vendor_packet_header_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_barrier_value_packet_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_hdp_flush_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_profiling_dispatch_time_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_profiling_async_copy_time_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_memory_pool_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_pitched_ptr_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_memory_pool_link_info_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_image_descriptor_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_pointer_info_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_ipc_memory_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_gpu_memory_fault_info_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_event_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} + +inline static std::ostream& +operator<<(std::ostream& out, const hsa_amd_svm_attribute_pair_t& v) +{ + rocprofiler::hsa::detail::operator<<(out, v); + return out; +} diff --git a/source/lib/rocprofiler/hsa/hsa-types.h b/source/lib/rocprofiler/hsa/hsa-types.h new file mode 100644 index 0000000000..0aa0e6d27c --- /dev/null +++ b/source/lib/rocprofiler/hsa/hsa-types.h @@ -0,0 +1,1456 @@ +// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN +// THE SOFTWARE. + +#pragma once + +#include +#include +#include +#include + +enum hsa_table_api_id_t +{ + HSA_API_TABLE_ID_NONE = -1, + HSA_API_TABLE_ID_CoreApi = 0, + HSA_API_TABLE_ID_AmdExt, + HSA_API_TABLE_ID_ImageExt, + HSA_API_TABLE_ID_NUMBER, +}; + +enum hsa_api_id_t +{ + HSA_API_ID_NONE = -1, + // block: CoreApi API + HSA_API_ID_hsa_init = 0, + HSA_API_ID_hsa_shut_down, + HSA_API_ID_hsa_system_get_info, + HSA_API_ID_hsa_system_extension_supported, + HSA_API_ID_hsa_system_get_extension_table, + HSA_API_ID_hsa_iterate_agents, + HSA_API_ID_hsa_agent_get_info, + HSA_API_ID_hsa_queue_create, + HSA_API_ID_hsa_soft_queue_create, + HSA_API_ID_hsa_queue_destroy, + HSA_API_ID_hsa_queue_inactivate, + HSA_API_ID_hsa_queue_load_read_index_scacquire, + HSA_API_ID_hsa_queue_load_read_index_relaxed, + HSA_API_ID_hsa_queue_load_write_index_scacquire, + HSA_API_ID_hsa_queue_load_write_index_relaxed, + HSA_API_ID_hsa_queue_store_write_index_relaxed, + HSA_API_ID_hsa_queue_store_write_index_screlease, + HSA_API_ID_hsa_queue_cas_write_index_scacq_screl, + HSA_API_ID_hsa_queue_cas_write_index_scacquire, + HSA_API_ID_hsa_queue_cas_write_index_relaxed, + HSA_API_ID_hsa_queue_cas_write_index_screlease, + HSA_API_ID_hsa_queue_add_write_index_scacq_screl, + HSA_API_ID_hsa_queue_add_write_index_scacquire, + HSA_API_ID_hsa_queue_add_write_index_relaxed, + HSA_API_ID_hsa_queue_add_write_index_screlease, + HSA_API_ID_hsa_queue_store_read_index_relaxed, + HSA_API_ID_hsa_queue_store_read_index_screlease, + HSA_API_ID_hsa_agent_iterate_regions, + HSA_API_ID_hsa_region_get_info, + HSA_API_ID_hsa_agent_get_exception_policies, + HSA_API_ID_hsa_agent_extension_supported, + HSA_API_ID_hsa_memory_register, + HSA_API_ID_hsa_memory_deregister, + HSA_API_ID_hsa_memory_allocate, + HSA_API_ID_hsa_memory_free, + HSA_API_ID_hsa_memory_copy, + HSA_API_ID_hsa_memory_assign_agent, + HSA_API_ID_hsa_signal_create, + HSA_API_ID_hsa_signal_destroy, + HSA_API_ID_hsa_signal_load_relaxed, + HSA_API_ID_hsa_signal_load_scacquire, + HSA_API_ID_hsa_signal_store_relaxed, + HSA_API_ID_hsa_signal_store_screlease, + HSA_API_ID_hsa_signal_wait_relaxed, + HSA_API_ID_hsa_signal_wait_scacquire, + HSA_API_ID_hsa_signal_and_relaxed, + HSA_API_ID_hsa_signal_and_scacquire, + HSA_API_ID_hsa_signal_and_screlease, + HSA_API_ID_hsa_signal_and_scacq_screl, + HSA_API_ID_hsa_signal_or_relaxed, + HSA_API_ID_hsa_signal_or_scacquire, + HSA_API_ID_hsa_signal_or_screlease, + HSA_API_ID_hsa_signal_or_scacq_screl, + HSA_API_ID_hsa_signal_xor_relaxed, + HSA_API_ID_hsa_signal_xor_scacquire, + HSA_API_ID_hsa_signal_xor_screlease, + HSA_API_ID_hsa_signal_xor_scacq_screl, + HSA_API_ID_hsa_signal_exchange_relaxed, + HSA_API_ID_hsa_signal_exchange_scacquire, + HSA_API_ID_hsa_signal_exchange_screlease, + HSA_API_ID_hsa_signal_exchange_scacq_screl, + HSA_API_ID_hsa_signal_add_relaxed, + HSA_API_ID_hsa_signal_add_scacquire, + HSA_API_ID_hsa_signal_add_screlease, + HSA_API_ID_hsa_signal_add_scacq_screl, + HSA_API_ID_hsa_signal_subtract_relaxed, + HSA_API_ID_hsa_signal_subtract_scacquire, + HSA_API_ID_hsa_signal_subtract_screlease, + HSA_API_ID_hsa_signal_subtract_scacq_screl, + HSA_API_ID_hsa_signal_cas_relaxed, + HSA_API_ID_hsa_signal_cas_scacquire, + HSA_API_ID_hsa_signal_cas_screlease, + HSA_API_ID_hsa_signal_cas_scacq_screl, + HSA_API_ID_hsa_isa_from_name, + HSA_API_ID_hsa_isa_get_info, + HSA_API_ID_hsa_isa_compatible, + HSA_API_ID_hsa_code_object_serialize, + HSA_API_ID_hsa_code_object_deserialize, + HSA_API_ID_hsa_code_object_destroy, + HSA_API_ID_hsa_code_object_get_info, + HSA_API_ID_hsa_code_object_get_symbol, + HSA_API_ID_hsa_code_symbol_get_info, + HSA_API_ID_hsa_code_object_iterate_symbols, + HSA_API_ID_hsa_executable_create, + HSA_API_ID_hsa_executable_destroy, + HSA_API_ID_hsa_executable_load_code_object, + HSA_API_ID_hsa_executable_freeze, + HSA_API_ID_hsa_executable_get_info, + HSA_API_ID_hsa_executable_global_variable_define, + HSA_API_ID_hsa_executable_agent_global_variable_define, + HSA_API_ID_hsa_executable_readonly_variable_define, + HSA_API_ID_hsa_executable_validate, + HSA_API_ID_hsa_executable_get_symbol, + HSA_API_ID_hsa_executable_symbol_get_info, + HSA_API_ID_hsa_executable_iterate_symbols, + HSA_API_ID_hsa_status_string, + HSA_API_ID_hsa_extension_get_name, + HSA_API_ID_hsa_system_major_extension_supported, + HSA_API_ID_hsa_system_get_major_extension_table, + HSA_API_ID_hsa_agent_major_extension_supported, + HSA_API_ID_hsa_cache_get_info, + HSA_API_ID_hsa_agent_iterate_caches, + HSA_API_ID_hsa_signal_silent_store_relaxed, + HSA_API_ID_hsa_signal_silent_store_screlease, + HSA_API_ID_hsa_signal_group_create, + HSA_API_ID_hsa_signal_group_destroy, + HSA_API_ID_hsa_signal_group_wait_any_scacquire, + HSA_API_ID_hsa_signal_group_wait_any_relaxed, + HSA_API_ID_hsa_agent_iterate_isas, + HSA_API_ID_hsa_isa_get_info_alt, + HSA_API_ID_hsa_isa_get_exception_policies, + HSA_API_ID_hsa_isa_get_round_method, + HSA_API_ID_hsa_wavefront_get_info, + HSA_API_ID_hsa_isa_iterate_wavefronts, + HSA_API_ID_hsa_code_object_get_symbol_from_name, + HSA_API_ID_hsa_code_object_reader_create_from_file, + HSA_API_ID_hsa_code_object_reader_create_from_memory, + HSA_API_ID_hsa_code_object_reader_destroy, + HSA_API_ID_hsa_executable_create_alt, + HSA_API_ID_hsa_executable_load_program_code_object, + HSA_API_ID_hsa_executable_load_agent_code_object, + HSA_API_ID_hsa_executable_validate_alt, + HSA_API_ID_hsa_executable_get_symbol_by_name, + HSA_API_ID_hsa_executable_iterate_agent_symbols, + HSA_API_ID_hsa_executable_iterate_program_symbols, + + // block: AmdExt API + HSA_API_ID_hsa_amd_coherency_get_type, + HSA_API_ID_hsa_amd_coherency_set_type, + HSA_API_ID_hsa_amd_profiling_set_profiler_enabled, + HSA_API_ID_hsa_amd_profiling_async_copy_enable, + HSA_API_ID_hsa_amd_profiling_get_dispatch_time, + HSA_API_ID_hsa_amd_profiling_get_async_copy_time, + HSA_API_ID_hsa_amd_profiling_convert_tick_to_system_domain, + HSA_API_ID_hsa_amd_signal_async_handler, + HSA_API_ID_hsa_amd_async_function, + HSA_API_ID_hsa_amd_signal_wait_any, + HSA_API_ID_hsa_amd_queue_cu_set_mask, + HSA_API_ID_hsa_amd_memory_pool_get_info, + HSA_API_ID_hsa_amd_agent_iterate_memory_pools, + HSA_API_ID_hsa_amd_memory_pool_allocate, + HSA_API_ID_hsa_amd_memory_pool_free, + HSA_API_ID_hsa_amd_memory_async_copy, + HSA_API_ID_hsa_amd_memory_async_copy_on_engine, + HSA_API_ID_hsa_amd_memory_copy_engine_status, + HSA_API_ID_hsa_amd_agent_memory_pool_get_info, + HSA_API_ID_hsa_amd_agents_allow_access, + HSA_API_ID_hsa_amd_memory_pool_can_migrate, + HSA_API_ID_hsa_amd_memory_migrate, + HSA_API_ID_hsa_amd_memory_lock, + HSA_API_ID_hsa_amd_memory_unlock, + HSA_API_ID_hsa_amd_memory_fill, + HSA_API_ID_hsa_amd_interop_map_buffer, + HSA_API_ID_hsa_amd_interop_unmap_buffer, + HSA_API_ID_hsa_amd_image_create, + HSA_API_ID_hsa_amd_pointer_info, + HSA_API_ID_hsa_amd_pointer_info_set_userdata, + HSA_API_ID_hsa_amd_ipc_memory_create, + HSA_API_ID_hsa_amd_ipc_memory_attach, + HSA_API_ID_hsa_amd_ipc_memory_detach, + HSA_API_ID_hsa_amd_signal_create, + HSA_API_ID_hsa_amd_ipc_signal_create, + HSA_API_ID_hsa_amd_ipc_signal_attach, + HSA_API_ID_hsa_amd_register_system_event_handler, + HSA_API_ID_hsa_amd_queue_intercept_create, + HSA_API_ID_hsa_amd_queue_intercept_register, + HSA_API_ID_hsa_amd_queue_set_priority, + HSA_API_ID_hsa_amd_memory_async_copy_rect, + HSA_API_ID_hsa_amd_runtime_queue_create_register, + HSA_API_ID_hsa_amd_memory_lock_to_pool, + HSA_API_ID_hsa_amd_register_deallocation_callback, + HSA_API_ID_hsa_amd_deregister_deallocation_callback, + HSA_API_ID_hsa_amd_signal_value_pointer, + HSA_API_ID_hsa_amd_svm_attributes_set, + HSA_API_ID_hsa_amd_svm_attributes_get, + HSA_API_ID_hsa_amd_svm_prefetch_async, + HSA_API_ID_hsa_amd_spm_acquire, + HSA_API_ID_hsa_amd_spm_release, + HSA_API_ID_hsa_amd_spm_set_dest_buffer, + HSA_API_ID_hsa_amd_queue_cu_get_mask, + HSA_API_ID_hsa_amd_portable_export_dmabuf, + HSA_API_ID_hsa_amd_portable_close_dmabuf, + + // block: ImageExt API + HSA_API_ID_hsa_ext_image_get_capability, + HSA_API_ID_hsa_ext_image_data_get_info, + HSA_API_ID_hsa_ext_image_create, + HSA_API_ID_hsa_ext_image_import, + HSA_API_ID_hsa_ext_image_export, + HSA_API_ID_hsa_ext_image_copy, + HSA_API_ID_hsa_ext_image_clear, + HSA_API_ID_hsa_ext_image_destroy, + HSA_API_ID_hsa_ext_sampler_create, + HSA_API_ID_hsa_ext_sampler_destroy, + HSA_API_ID_hsa_ext_image_get_capability_with_layout, + HSA_API_ID_hsa_ext_image_data_get_info_with_layout, + HSA_API_ID_hsa_ext_image_create_with_layout, + + HSA_API_ID_DISPATCH, + HSA_API_ID_NUMBER, +}; + +typedef struct hsa_api_data_s +{ + uint64_t correlation_id; + uint32_t phase; + union + { + uint64_t uint64_t_retval; + uint32_t uint32_t_retval; + hsa_signal_value_t hsa_signal_value_t_retval; + hsa_status_t hsa_status_t_retval; + }; + union + { + // block: CoreApi API + struct + { + } hsa_init; + struct + { + } hsa_shut_down; + struct + { + hsa_system_info_t attribute; + void* value; + } hsa_system_get_info; + struct + { + uint16_t extension; + uint16_t version_major; + uint16_t version_minor; + bool* result; + } hsa_system_extension_supported; + struct + { + uint16_t extension; + uint16_t version_major; + uint16_t version_minor; + void* table; + } hsa_system_get_extension_table; + struct + { + hsa_status_t (*callback)(hsa_agent_t agent, void* data); + void* data; + } hsa_iterate_agents; + struct + { + hsa_agent_t agent; + hsa_agent_info_t attribute; + void* value; + } hsa_agent_get_info; + struct + { + hsa_agent_t agent; + uint32_t size; + hsa_queue_type32_t type; + void (*callback)(hsa_status_t status, hsa_queue_t* source, void* data); + void* data; + uint32_t private_segment_size; + uint32_t group_segment_size; + hsa_queue_t** queue; + } hsa_queue_create; + struct + { + hsa_region_t region; + uint32_t size; + hsa_queue_type32_t type; + uint32_t features; + hsa_signal_t doorbell_signal; + hsa_queue_t** queue; + } hsa_soft_queue_create; + struct + { + hsa_queue_t* queue; + } hsa_queue_destroy; + struct + { + hsa_queue_t* queue; + } hsa_queue_inactivate; + struct + { + const hsa_queue_t* queue; + } hsa_queue_load_read_index_scacquire; + struct + { + const hsa_queue_t* queue; + } hsa_queue_load_read_index_relaxed; + struct + { + const hsa_queue_t* queue; + } hsa_queue_load_write_index_scacquire; + struct + { + const hsa_queue_t* queue; + } hsa_queue_load_write_index_relaxed; + struct + { + const hsa_queue_t* queue; + uint64_t value; + } hsa_queue_store_write_index_relaxed; + struct + { + const hsa_queue_t* queue; + uint64_t value; + } hsa_queue_store_write_index_screlease; + struct + { + const hsa_queue_t* queue; + uint64_t expected; + uint64_t value; + } hsa_queue_cas_write_index_scacq_screl; + struct + { + const hsa_queue_t* queue; + uint64_t expected; + uint64_t value; + } hsa_queue_cas_write_index_scacquire; + struct + { + const hsa_queue_t* queue; + uint64_t expected; + uint64_t value; + } hsa_queue_cas_write_index_relaxed; + struct + { + const hsa_queue_t* queue; + uint64_t expected; + uint64_t value; + } hsa_queue_cas_write_index_screlease; + struct + { + const hsa_queue_t* queue; + uint64_t value; + } hsa_queue_add_write_index_scacq_screl; + struct + { + const hsa_queue_t* queue; + uint64_t value; + } hsa_queue_add_write_index_scacquire; + struct + { + const hsa_queue_t* queue; + uint64_t value; + } hsa_queue_add_write_index_relaxed; + struct + { + const hsa_queue_t* queue; + uint64_t value; + } hsa_queue_add_write_index_screlease; + struct + { + const hsa_queue_t* queue; + uint64_t value; + } hsa_queue_store_read_index_relaxed; + struct + { + const hsa_queue_t* queue; + uint64_t value; + } hsa_queue_store_read_index_screlease; + struct + { + hsa_agent_t agent; + hsa_status_t (*callback)(hsa_region_t region, void* data); + void* data; + } hsa_agent_iterate_regions; + struct + { + hsa_region_t region; + hsa_region_info_t attribute; + void* value; + } hsa_region_get_info; + struct + { + hsa_agent_t agent; + hsa_profile_t profile; + uint16_t* mask; + } hsa_agent_get_exception_policies; + struct + { + uint16_t extension; + hsa_agent_t agent; + uint16_t version_major; + uint16_t version_minor; + bool* result; + } hsa_agent_extension_supported; + struct + { + void* ptr; + size_t size; + } hsa_memory_register; + struct + { + void* ptr; + size_t size; + } hsa_memory_deregister; + struct + { + hsa_region_t region; + size_t size; + void** ptr; + } hsa_memory_allocate; + struct + { + void* ptr; + } hsa_memory_free; + struct + { + void* dst; + const void* src; + size_t size; + } hsa_memory_copy; + struct + { + void* ptr; + hsa_agent_t agent; + hsa_access_permission_t access; + } hsa_memory_assign_agent; + struct + { + hsa_signal_value_t initial_value; + uint32_t num_consumers; + const hsa_agent_t* consumers; + hsa_signal_t* signal; + } hsa_signal_create; + struct + { + hsa_signal_t signal; + } hsa_signal_destroy; + struct + { + hsa_signal_t signal; + } hsa_signal_load_relaxed; + struct + { + hsa_signal_t signal; + } hsa_signal_load_scacquire; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_store_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_store_screlease; + struct + { + hsa_signal_t signal; + hsa_signal_condition_t condition; + hsa_signal_value_t compare_value; + uint64_t timeout_hint; + hsa_wait_state_t wait_state_hint; + } hsa_signal_wait_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_condition_t condition; + hsa_signal_value_t compare_value; + uint64_t timeout_hint; + hsa_wait_state_t wait_state_hint; + } hsa_signal_wait_scacquire; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_and_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_and_scacquire; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_and_screlease; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_and_scacq_screl; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_or_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_or_scacquire; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_or_screlease; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_or_scacq_screl; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_xor_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_xor_scacquire; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_xor_screlease; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_xor_scacq_screl; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_exchange_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_exchange_scacquire; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_exchange_screlease; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_exchange_scacq_screl; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_add_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_add_scacquire; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_add_screlease; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_add_scacq_screl; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_subtract_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_subtract_scacquire; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_subtract_screlease; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_subtract_scacq_screl; + struct + { + hsa_signal_t signal; + hsa_signal_value_t expected; + hsa_signal_value_t value; + } hsa_signal_cas_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_value_t expected; + hsa_signal_value_t value; + } hsa_signal_cas_scacquire; + struct + { + hsa_signal_t signal; + hsa_signal_value_t expected; + hsa_signal_value_t value; + } hsa_signal_cas_screlease; + struct + { + hsa_signal_t signal; + hsa_signal_value_t expected; + hsa_signal_value_t value; + } hsa_signal_cas_scacq_screl; + struct + { + const char* name; + hsa_isa_t* isa; + } hsa_isa_from_name; + struct + { + hsa_isa_t isa; + hsa_isa_info_t attribute; + uint32_t index; + void* value; + } hsa_isa_get_info; + struct + { + hsa_isa_t code_object_isa; + hsa_isa_t agent_isa; + bool* result; + } hsa_isa_compatible; + struct + { + hsa_code_object_t code_object; + hsa_status_t (*alloc_callback)(size_t size, hsa_callback_data_t data, void** address); + hsa_callback_data_t callback_data; + const char* options; + void** serialized_code_object; + size_t* serialized_code_object_size; + } hsa_code_object_serialize; + struct + { + void* serialized_code_object; + size_t serialized_code_object_size; + const char* options; + hsa_code_object_t* code_object; + } hsa_code_object_deserialize; + struct + { + hsa_code_object_t code_object; + } hsa_code_object_destroy; + struct + { + hsa_code_object_t code_object; + hsa_code_object_info_t attribute; + void* value; + } hsa_code_object_get_info; + struct + { + hsa_code_object_t code_object; + const char* symbol_name; + hsa_code_symbol_t* symbol; + } hsa_code_object_get_symbol; + struct + { + hsa_code_symbol_t code_symbol; + hsa_code_symbol_info_t attribute; + void* value; + } hsa_code_symbol_get_info; + struct + { + hsa_code_object_t code_object; + hsa_status_t (*callback)(hsa_code_object_t code_object, + hsa_code_symbol_t symbol, + void* data); + void* data; + } hsa_code_object_iterate_symbols; + struct + { + hsa_profile_t profile; + hsa_executable_state_t executable_state; + const char* options; + hsa_executable_t* executable; + } hsa_executable_create; + struct + { + hsa_executable_t executable; + } hsa_executable_destroy; + struct + { + hsa_executable_t executable; + hsa_agent_t agent; + hsa_code_object_t code_object; + const char* options; + } hsa_executable_load_code_object; + struct + { + hsa_executable_t executable; + const char* options; + } hsa_executable_freeze; + struct + { + hsa_executable_t executable; + hsa_executable_info_t attribute; + void* value; + } hsa_executable_get_info; + struct + { + hsa_executable_t executable; + const char* variable_name; + void* address; + } hsa_executable_global_variable_define; + struct + { + hsa_executable_t executable; + hsa_agent_t agent; + const char* variable_name; + void* address; + } hsa_executable_agent_global_variable_define; + struct + { + hsa_executable_t executable; + hsa_agent_t agent; + const char* variable_name; + void* address; + } hsa_executable_readonly_variable_define; + struct + { + hsa_executable_t executable; + uint32_t* result; + } hsa_executable_validate; + struct + { + hsa_executable_t executable; + const char* module_name; + const char* symbol_name; + hsa_agent_t agent; + int32_t call_convention; + hsa_executable_symbol_t* symbol; + } hsa_executable_get_symbol; + struct + { + hsa_executable_symbol_t executable_symbol; + hsa_executable_symbol_info_t attribute; + void* value; + } hsa_executable_symbol_get_info; + struct + { + hsa_executable_t executable; + hsa_status_t (*callback)(hsa_executable_t exec, + hsa_executable_symbol_t symbol, + void* data); + void* data; + } hsa_executable_iterate_symbols; + struct + { + hsa_status_t status; + const char** status_string; + } hsa_status_string; + struct + { + uint16_t extension; + const char** name; + } hsa_extension_get_name; + struct + { + uint16_t extension; + uint16_t version_major; + uint16_t* version_minor; + bool* result; + } hsa_system_major_extension_supported; + struct + { + uint16_t extension; + uint16_t version_major; + size_t table_length; + void* table; + } hsa_system_get_major_extension_table; + struct + { + uint16_t extension; + hsa_agent_t agent; + uint16_t version_major; + uint16_t* version_minor; + bool* result; + } hsa_agent_major_extension_supported; + struct + { + hsa_cache_t cache; + hsa_cache_info_t attribute; + void* value; + } hsa_cache_get_info; + struct + { + hsa_agent_t agent; + hsa_status_t (*callback)(hsa_cache_t cache, void* data); + void* data; + } hsa_agent_iterate_caches; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_silent_store_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_silent_store_screlease; + struct + { + uint32_t num_signals; + const hsa_signal_t* signals; + uint32_t num_consumers; + const hsa_agent_t* consumers; + hsa_signal_group_t* signal_group; + } hsa_signal_group_create; + struct + { + hsa_signal_group_t signal_group; + } hsa_signal_group_destroy; + struct + { + hsa_signal_group_t signal_group; + const hsa_signal_condition_t* conditions; + const hsa_signal_value_t* compare_values; + hsa_wait_state_t wait_state_hint; + hsa_signal_t* signal; + hsa_signal_value_t* value; + } hsa_signal_group_wait_any_scacquire; + struct + { + hsa_signal_group_t signal_group; + const hsa_signal_condition_t* conditions; + const hsa_signal_value_t* compare_values; + hsa_wait_state_t wait_state_hint; + hsa_signal_t* signal; + hsa_signal_value_t* value; + } hsa_signal_group_wait_any_relaxed; + struct + { + hsa_agent_t agent; + hsa_status_t (*callback)(hsa_isa_t isa, void* data); + void* data; + } hsa_agent_iterate_isas; + struct + { + hsa_isa_t isa; + hsa_isa_info_t attribute; + void* value; + } hsa_isa_get_info_alt; + struct + { + hsa_isa_t isa; + hsa_profile_t profile; + uint16_t* mask; + } hsa_isa_get_exception_policies; + struct + { + hsa_isa_t isa; + hsa_fp_type_t fp_type; + hsa_flush_mode_t flush_mode; + hsa_round_method_t* round_method; + } hsa_isa_get_round_method; + struct + { + hsa_wavefront_t wavefront; + hsa_wavefront_info_t attribute; + void* value; + } hsa_wavefront_get_info; + struct + { + hsa_isa_t isa; + hsa_status_t (*callback)(hsa_wavefront_t wavefront, void* data); + void* data; + } hsa_isa_iterate_wavefronts; + struct + { + hsa_code_object_t code_object; + const char* module_name; + const char* symbol_name; + hsa_code_symbol_t* symbol; + } hsa_code_object_get_symbol_from_name; + struct + { + hsa_file_t file; + hsa_code_object_reader_t* code_object_reader; + } hsa_code_object_reader_create_from_file; + struct + { + const void* code_object; + size_t size; + hsa_code_object_reader_t* code_object_reader; + } hsa_code_object_reader_create_from_memory; + struct + { + hsa_code_object_reader_t code_object_reader; + } hsa_code_object_reader_destroy; + struct + { + hsa_profile_t profile; + hsa_default_float_rounding_mode_t default_float_rounding_mode; + const char* options; + hsa_executable_t* executable; + } hsa_executable_create_alt; + struct + { + hsa_executable_t executable; + hsa_code_object_reader_t code_object_reader; + const char* options; + hsa_loaded_code_object_t* loaded_code_object; + } hsa_executable_load_program_code_object; + struct + { + hsa_executable_t executable; + hsa_agent_t agent; + hsa_code_object_reader_t code_object_reader; + const char* options; + hsa_loaded_code_object_t* loaded_code_object; + } hsa_executable_load_agent_code_object; + struct + { + hsa_executable_t executable; + const char* options; + uint32_t* result; + } hsa_executable_validate_alt; + struct + { + hsa_executable_t executable; + const char* symbol_name; + const hsa_agent_t* agent; + hsa_executable_symbol_t* symbol; + } hsa_executable_get_symbol_by_name; + struct + { + hsa_executable_t executable; + hsa_agent_t agent; + hsa_status_t (*callback)(hsa_executable_t exec, + hsa_agent_t agent, + hsa_executable_symbol_t symbol, + void* data); + void* data; + } hsa_executable_iterate_agent_symbols; + struct + { + hsa_executable_t executable; + hsa_status_t (*callback)(hsa_executable_t exec, + hsa_executable_symbol_t symbol, + void* data); + void* data; + } hsa_executable_iterate_program_symbols; + + // block: AmdExt API + struct + { + hsa_agent_t agent; + hsa_amd_coherency_type_t* type; + } hsa_amd_coherency_get_type; + struct + { + hsa_agent_t agent; + hsa_amd_coherency_type_t type; + } hsa_amd_coherency_set_type; + struct + { + hsa_queue_t* queue; + int enable; + } hsa_amd_profiling_set_profiler_enabled; + struct + { + bool enable; + } hsa_amd_profiling_async_copy_enable; + struct + { + hsa_agent_t agent; + hsa_signal_t signal; + hsa_amd_profiling_dispatch_time_t* time; + } hsa_amd_profiling_get_dispatch_time; + struct + { + hsa_signal_t signal; + hsa_amd_profiling_async_copy_time_t* time; + } hsa_amd_profiling_get_async_copy_time; + struct + { + hsa_agent_t agent; + uint64_t agent_tick; + uint64_t* system_tick; + } hsa_amd_profiling_convert_tick_to_system_domain; + struct + { + hsa_signal_t signal; + hsa_signal_condition_t cond; + hsa_signal_value_t value; + hsa_amd_signal_handler handler; + void* arg; + } hsa_amd_signal_async_handler; + struct + { + void (*callback)(void* arg); + void* arg; + } hsa_amd_async_function; + struct + { + uint32_t signal_count; + hsa_signal_t* signals; + hsa_signal_condition_t* conds; + hsa_signal_value_t* values; + uint64_t timeout_hint; + hsa_wait_state_t wait_hint; + hsa_signal_value_t* satisfying_value; + } hsa_amd_signal_wait_any; + struct + { + const hsa_queue_t* queue; + uint32_t num_cu_mask_count; + const uint32_t* cu_mask; + } hsa_amd_queue_cu_set_mask; + struct + { + hsa_amd_memory_pool_t memory_pool; + hsa_amd_memory_pool_info_t attribute; + void* value; + } hsa_amd_memory_pool_get_info; + struct + { + hsa_agent_t agent; + hsa_status_t (*callback)(hsa_amd_memory_pool_t memory_pool, void* data); + void* data; + } hsa_amd_agent_iterate_memory_pools; + struct + { + hsa_amd_memory_pool_t memory_pool; + size_t size; + uint32_t flags; + void** ptr; + } hsa_amd_memory_pool_allocate; + struct + { + void* ptr; + } hsa_amd_memory_pool_free; + struct + { + void* dst; + hsa_agent_t dst_agent; + const void* src; + hsa_agent_t src_agent; + size_t size; + uint32_t num_dep_signals; + const hsa_signal_t* dep_signals; + hsa_signal_t completion_signal; + } hsa_amd_memory_async_copy; + struct + { + void* dst; + hsa_agent_t dst_agent; + const void* src; + hsa_agent_t src_agent; + size_t size; + uint32_t num_dep_signals; + const hsa_signal_t* dep_signals; + hsa_signal_t completion_signal; + hsa_amd_sdma_engine_id_t engine_id; + bool force_copy_on_sdma; + } hsa_amd_memory_async_copy_on_engine; + struct + { + hsa_agent_t dst_agent; + hsa_agent_t src_agent; + uint32_t* engine_ids_mask; + } hsa_amd_memory_copy_engine_status; + struct + { + hsa_agent_t agent; + hsa_amd_memory_pool_t memory_pool; + hsa_amd_agent_memory_pool_info_t attribute; + void* value; + } hsa_amd_agent_memory_pool_get_info; + struct + { + uint32_t num_agents; + const hsa_agent_t* agents; + const uint32_t* flags; + const void* ptr; + } hsa_amd_agents_allow_access; + struct + { + hsa_amd_memory_pool_t src_memory_pool; + hsa_amd_memory_pool_t dst_memory_pool; + bool* result; + } hsa_amd_memory_pool_can_migrate; + struct + { + const void* ptr; + hsa_amd_memory_pool_t memory_pool; + uint32_t flags; + } hsa_amd_memory_migrate; + struct + { + void* host_ptr; + size_t size; + hsa_agent_t* agents; + int num_agent; + void** agent_ptr; + } hsa_amd_memory_lock; + struct + { + void* host_ptr; + } hsa_amd_memory_unlock; + struct + { + void* ptr; + uint32_t value; + size_t count; + } hsa_amd_memory_fill; + struct + { + uint32_t num_agents; + hsa_agent_t* agents; + int interop_handle; + uint32_t flags; + size_t* size; + void** ptr; + size_t* metadata_size; + const void** metadata; + } hsa_amd_interop_map_buffer; + struct + { + void* ptr; + } hsa_amd_interop_unmap_buffer; + struct + { + hsa_agent_t agent; + const hsa_ext_image_descriptor_t* image_descriptor; + const hsa_amd_image_descriptor_t* image_layout; + const void* image_data; + hsa_access_permission_t access_permission; + hsa_ext_image_t* image; + } hsa_amd_image_create; + struct + { + const void* ptr; + hsa_amd_pointer_info_t* info; + void* (*alloc)(size_t); + uint32_t* num_agents_accessible; + hsa_agent_t** accessible; + } hsa_amd_pointer_info; + struct + { + const void* ptr; + void* userdata; + } hsa_amd_pointer_info_set_userdata; + struct + { + void* ptr; + size_t len; + hsa_amd_ipc_memory_t* handle; + } hsa_amd_ipc_memory_create; + struct + { + const hsa_amd_ipc_memory_t* handle; + size_t len; + uint32_t num_agents; + const hsa_agent_t* mapping_agents; + void** mapped_ptr; + } hsa_amd_ipc_memory_attach; + struct + { + void* mapped_ptr; + } hsa_amd_ipc_memory_detach; + struct + { + hsa_signal_value_t initial_value; + uint32_t num_consumers; + const hsa_agent_t* consumers; + uint64_t attributes; + hsa_signal_t* signal; + } hsa_amd_signal_create; + struct + { + hsa_signal_t signal; + hsa_amd_ipc_signal_t* handle; + } hsa_amd_ipc_signal_create; + struct + { + const hsa_amd_ipc_signal_t* handle; + hsa_signal_t* signal; + } hsa_amd_ipc_signal_attach; + struct + { + hsa_amd_system_event_callback_t callback; + void* data; + } hsa_amd_register_system_event_handler; + struct + { + hsa_agent_t agent_handle; + uint32_t size; + hsa_queue_type32_t type; + void (*callback)(hsa_status_t status, hsa_queue_t* source, void* data); + void* data; + uint32_t private_segment_size; + uint32_t group_segment_size; + hsa_queue_t** queue; + } hsa_amd_queue_intercept_create; + struct + { + hsa_queue_t* queue; + hsa_amd_queue_intercept_handler callback; + void* user_data; + } hsa_amd_queue_intercept_register; + struct + { + hsa_queue_t* queue; + hsa_amd_queue_priority_t priority; + } hsa_amd_queue_set_priority; + struct + { + const hsa_pitched_ptr_t* dst; + const hsa_dim3_t* dst_offset; + const hsa_pitched_ptr_t* src; + const hsa_dim3_t* src_offset; + const hsa_dim3_t* range; + hsa_dim3_t range__val; + hsa_agent_t copy_agent; + hsa_amd_copy_direction_t dir; + uint32_t num_dep_signals; + const hsa_signal_t* dep_signals; + hsa_signal_t completion_signal; + } hsa_amd_memory_async_copy_rect; + struct + { + hsa_amd_runtime_queue_notifier callback; + void* user_data; + } hsa_amd_runtime_queue_create_register; + struct + { + void* host_ptr; + size_t size; + hsa_agent_t* agents; + int num_agent; + hsa_amd_memory_pool_t pool; + uint32_t flags; + void** agent_ptr; + } hsa_amd_memory_lock_to_pool; + struct + { + void* ptr; + hsa_amd_deallocation_callback_t callback; + void* user_data; + } hsa_amd_register_deallocation_callback; + struct + { + void* ptr; + hsa_amd_deallocation_callback_t callback; + } hsa_amd_deregister_deallocation_callback; + struct + { + hsa_signal_t signal; + volatile hsa_signal_value_t** value_ptr; + } hsa_amd_signal_value_pointer; + struct + { + void* ptr; + size_t size; + hsa_amd_svm_attribute_pair_t* attribute_list; + size_t attribute_count; + } hsa_amd_svm_attributes_set; + struct + { + void* ptr; + size_t size; + hsa_amd_svm_attribute_pair_t* attribute_list; + size_t attribute_count; + } hsa_amd_svm_attributes_get; + struct + { + void* ptr; + size_t size; + hsa_agent_t agent; + uint32_t num_dep_signals; + const hsa_signal_t* dep_signals; + hsa_signal_t completion_signal; + } hsa_amd_svm_prefetch_async; + struct + { + hsa_agent_t preferred_agent; + } hsa_amd_spm_acquire; + struct + { + hsa_agent_t preferred_agent; + } hsa_amd_spm_release; + struct + { + hsa_agent_t preferred_agent; + size_t size_in_bytes; + uint32_t* timeout; + uint32_t* size_copied; + void* dest; + bool* is_data_loss; + } hsa_amd_spm_set_dest_buffer; + struct + { + const hsa_queue_t* queue; + uint32_t num_cu_mask_count; + uint32_t* cu_mask; + } hsa_amd_queue_cu_get_mask; + struct + { + const void* ptr; + size_t size; + int* dmabuf; + uint64_t* offset; + } hsa_amd_portable_export_dmabuf; + struct + { + int dmabuf; + } hsa_amd_portable_close_dmabuf; + + // block: ImageExt API + struct + { + hsa_agent_t agent; + hsa_ext_image_geometry_t geometry; + const hsa_ext_image_format_t* image_format; + uint32_t* capability_mask; + } hsa_ext_image_get_capability; + struct + { + hsa_agent_t agent; + const hsa_ext_image_descriptor_t* image_descriptor; + hsa_access_permission_t access_permission; + hsa_ext_image_data_info_t* image_data_info; + } hsa_ext_image_data_get_info; + struct + { + hsa_agent_t agent; + const hsa_ext_image_descriptor_t* image_descriptor; + const void* image_data; + hsa_access_permission_t access_permission; + hsa_ext_image_t* image; + } hsa_ext_image_create; + struct + { + hsa_agent_t agent; + const void* src_memory; + size_t src_row_pitch; + size_t src_slice_pitch; + hsa_ext_image_t dst_image; + const hsa_ext_image_region_t* image_region; + } hsa_ext_image_import; + struct + { + hsa_agent_t agent; + hsa_ext_image_t src_image; + void* dst_memory; + size_t dst_row_pitch; + size_t dst_slice_pitch; + const hsa_ext_image_region_t* image_region; + } hsa_ext_image_export; + struct + { + hsa_agent_t agent; + hsa_ext_image_t src_image; + const hsa_dim3_t* src_offset; + hsa_ext_image_t dst_image; + const hsa_dim3_t* dst_offset; + const hsa_dim3_t* range; + } hsa_ext_image_copy; + struct + { + hsa_agent_t agent; + hsa_ext_image_t image; + const void* data; + const hsa_ext_image_region_t* image_region; + } hsa_ext_image_clear; + struct + { + hsa_agent_t agent; + hsa_ext_image_t image; + } hsa_ext_image_destroy; + struct + { + hsa_agent_t agent; + const hsa_ext_sampler_descriptor_t* sampler_descriptor; + hsa_ext_sampler_t* sampler; + } hsa_ext_sampler_create; + struct + { + hsa_agent_t agent; + hsa_ext_sampler_t sampler; + } hsa_ext_sampler_destroy; + struct + { + hsa_agent_t agent; + hsa_ext_image_geometry_t geometry; + const hsa_ext_image_format_t* image_format; + hsa_ext_image_data_layout_t image_data_layout; + uint32_t* capability_mask; + } hsa_ext_image_get_capability_with_layout; + struct + { + hsa_agent_t agent; + const hsa_ext_image_descriptor_t* image_descriptor; + hsa_access_permission_t access_permission; + hsa_ext_image_data_layout_t image_data_layout; + size_t image_data_row_pitch; + size_t image_data_slice_pitch; + hsa_ext_image_data_info_t* image_data_info; + } hsa_ext_image_data_get_info_with_layout; + struct + { + hsa_agent_t agent; + const hsa_ext_image_descriptor_t* image_descriptor; + const void* image_data; + hsa_access_permission_t access_permission; + hsa_ext_image_data_layout_t image_data_layout; + size_t image_data_row_pitch; + size_t image_data_slice_pitch; + hsa_ext_image_t* image; + } hsa_ext_image_create_with_layout; + } args; + uint64_t* phase_data; +} hsa_api_data_t; diff --git a/source/lib/rocprofiler/hsa/hsa-utils.hpp b/source/lib/rocprofiler/hsa/hsa-utils.hpp new file mode 100644 index 0000000000..3515f2dbdf --- /dev/null +++ b/source/lib/rocprofiler/hsa/hsa-utils.hpp @@ -0,0 +1,99 @@ +// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN +// THE SOFTWARE. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace rocprofiler +{ +namespace hsa +{ +namespace utils +{ +struct join_args +{ + std::string_view prefix = {}; + std::string_view suffix = {}; + std::string_view separator = {}; +}; + +template +auto +join_impl(const Tp& _v) +{ + return _v; +} + +template +auto +join_impl(const std::pair& _v) +{ + auto _ss = std::stringstream{}; + _ss << _v.first << "=" << _v.second; + return _ss.str(); +} + +template +auto +join(join_args ja, Args... args) +{ + auto _content = std::string{}; + { + auto _ss = std::stringstream{}; + ((_ss << ja.separator << join_impl(args)), ...); + auto _v = _ss.str(); + if(_v.length() > ja.separator.length()) _content = _v.substr(2); + } + + return (std::stringstream{} << ja.prefix << _content << ja.suffix).str(); +} + +template +auto +stringize_impl(const Tp& _v) +{ + auto _ss = std::stringstream{}; + _ss << _v; + return _ss.str(); +} + +template +auto +stringize_impl(const std::pair& _v) +{ + return std::make_pair(stringize_impl(_v.first), stringize_impl(_v.second)); +} + +template +auto +stringize(Args... args) +{ + return std::vector>{stringize_impl(args)...}; +} +} // namespace utils +} // namespace hsa +} // namespace rocprofiler diff --git a/source/lib/rocprofiler/hsa/hsa.cpp b/source/lib/rocprofiler/hsa/hsa.cpp new file mode 100644 index 0000000000..20a23a8e0f --- /dev/null +++ b/source/lib/rocprofiler/hsa/hsa.cpp @@ -0,0 +1,485 @@ +// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN +// THE SOFTWARE. + +#include "hsa.hpp" +#include "hsa-types.h" + +#include + +#include +#include +#include +#include +#include +#include + +namespace rocprofiler +{ +namespace hsa +{ +namespace +{ +std::atomic report_activity = {}; + +auto& +get_saved_table() +{ + static auto _core = CoreApiTable{}; + static auto _amd_ext = AmdExtTable{}; + static auto _img_ext = ImageExtTable{}; + static auto _fini_ext = FinalizerExtTable{}; + static auto _v = []() { + _core.version = { + HSA_CORE_API_TABLE_MAJOR_VERSION, sizeof(_core), HSA_CORE_API_TABLE_STEP_VERSION, 0}; + _amd_ext.version = {HSA_AMD_EXT_API_TABLE_MAJOR_VERSION, + sizeof(_amd_ext), + HSA_AMD_EXT_API_TABLE_STEP_VERSION, + 0}; + _img_ext.version = {HSA_IMAGE_API_TABLE_MAJOR_VERSION, + sizeof(_img_ext), + HSA_IMAGE_API_TABLE_STEP_VERSION, + 0}; + _fini_ext.version = {HSA_FINALIZER_API_TABLE_MAJOR_VERSION, + sizeof(_fini_ext), + HSA_FINALIZER_API_TABLE_STEP_VERSION, + 0}; + auto _version = ApiTableVersion{ + HSA_API_TABLE_MAJOR_VERSION, sizeof(HsaApiTable), HSA_API_TABLE_STEP_VERSION, 0}; + auto _val = hsa_api_table_t{_version, &_core, &_amd_ext, &_fini_ext, &_img_ext}; + return _val; + }(); + return _v; +} +} // namespace + +template <> +struct hsa_table_lookup +{ + auto& operator()(hsa_api_table_t& _v) const { return _v.core_; } + auto& operator()(hsa_api_table_t* _v) const { return _v->core_; } + auto& operator()() const { return (*this)(get_saved_table()); } +}; + +template <> +struct hsa_table_lookup +{ + auto& operator()(hsa_api_table_t& _v) const { return _v.amd_ext_; } + auto& operator()(hsa_api_table_t* _v) const { return _v->amd_ext_; } + auto& operator()() const { return (*this)(get_saved_table()); } +}; + +template <> +struct hsa_table_lookup +{ + auto& operator()(hsa_api_table_t& _v) const { return _v.image_ext_; } + auto& operator()(hsa_api_table_t* _v) const { return _v->image_ext_; } + auto& operator()() const { return (*this)(get_saved_table()); } +}; + +template +void +set_data_retval(DataT& _data, Tp _val) +{ + if constexpr(std::is_same::value) + { + _data.hsa_signal_value_t_retval = _val; + } + else if constexpr(std::is_same::value) + { + _data.uint64_t_retval = _val; + } + else if constexpr(std::is_same::value) + { + _data.uint32_t_retval = _val; + } + else if constexpr(std::is_same::value) + { + _data.hsa_status_t_retval = _val; + } + else + { + static_assert(std::is_void::value, "Error! unsupported return type"); + } +} + +template +template +auto +hsa_api_impl::phase_enter(DataT& _data, DataArgsT& _data_args, Args... args) +{ + using info_type = hsa_api_info; + + activity_functor_t _func = report_activity.load(std::memory_order_relaxed); + if(_func) + { + if constexpr(Idx == HSA_API_ID_hsa_amd_memory_async_copy_rect) + { + auto _tuple = std::make_tuple(args...); + _data.api_data.args.hsa_amd_memory_async_copy_rect.dst = std::get<0>(_tuple); + _data.api_data.args.hsa_amd_memory_async_copy_rect.dst_offset = std::get<1>(_tuple); + _data.api_data.args.hsa_amd_memory_async_copy_rect.src = std::get<2>(_tuple); + _data.api_data.args.hsa_amd_memory_async_copy_rect.src_offset = std::get<3>(_tuple); + _data.api_data.args.hsa_amd_memory_async_copy_rect.range = std::get<4>(_tuple); + _data.api_data.args.hsa_amd_memory_async_copy_rect.range__val = *(std::get<4>(_tuple)); + _data.api_data.args.hsa_amd_memory_async_copy_rect.copy_agent = std::get<5>(_tuple); + _data.api_data.args.hsa_amd_memory_async_copy_rect.dir = std::get<6>(_tuple); + _data.api_data.args.hsa_amd_memory_async_copy_rect.num_dep_signals = + std::get<7>(_tuple); + _data.api_data.args.hsa_amd_memory_async_copy_rect.dep_signals = std::get<8>(_tuple); + _data.api_data.args.hsa_amd_memory_async_copy_rect.completion_signal = + std::get<9>(_tuple); + } + else + { + _data_args = DataArgsT{args...}; + } + if(_func(info_type::domain_idx, info_type::operation_idx, &_data) == 0) + { + if(_data.phase_enter != nullptr) _data.phase_enter(info_type::operation_idx, &_data); + return true; + } + return false; + } + return false; +} + +template +template +auto +hsa_api_impl::phase_exit(DataT& _data) +{ + using info_type = hsa_api_info; + + if(_data.phase_exit != nullptr) + { + _data.phase_exit(info_type::operation_idx, &_data); + return true; + } + return false; +} + +struct null_type +{}; + +template +template +auto +hsa_api_impl::exec(DataT& _data, FuncT&& _func, Args&&... args) +{ + using return_type = std::decay_t>; + + if(_func) + { + static_assert(std::is_void::value || std::is_enum::value || + std::is_integral::value, + "Error! unsupported return type"); + + if constexpr(std::is_void::value) + { + _func(std::forward(args)...); + return null_type{}; + } + else + { + auto _ret = _func(std::forward(args)...); + set_data_retval(_data.api_data, _ret); + return _ret; + } + } + + if constexpr(std::is_void::value) + return null_type{}; + else + return return_type{HSA_STATUS_ERROR}; +} + +template +template +auto +hsa_api_impl::functor(Args&&... args) +{ + using info_type = hsa_api_info; + + auto trace_data = hsa_trace_data_t{}; + + auto _enabled = phase_enter( + trace_data, info_type::get_api_data_args(trace_data), std::forward(args)...); + + auto _ret = exec(trace_data, info_type::get_table_func(), std::forward(args)...); + + if(_enabled) phase_exit(trace_data); + + if constexpr(!std::is_same::value) + return _ret; + else + return HSA_STATUS_SUCCESS; +} +} // namespace hsa +} // namespace rocprofiler + +#include "hsa.gen.cpp" + +namespace rocprofiler +{ +namespace hsa +{ +namespace +{ +template +const char* +hsa_api_name(const uint32_t id, std::index_sequence) +{ + if(Idx == id) return hsa_api_info::name; + if constexpr(sizeof...(IdxTail) > 0) + return hsa_api_name(id, std::index_sequence{}); + else + return nullptr; +} + +template +uint32_t +hsa_api_id_by_name(const char* name, std::index_sequence) +{ + if(std::string_view{hsa_api_info::name} == std::string_view{name}) + return hsa_api_info::operation_idx; + if constexpr(sizeof...(IdxTail) > 0) + return hsa_api_id_by_name(name, std::index_sequence{}); + else + return HSA_API_ID_NONE; +} + +template +std::string +hsa_api_data_string(const uint32_t id, + const hsa_trace_data_t& _data, + std::index_sequence) +{ + if(Idx == id) return hsa_api_info::as_string(_data); + if constexpr(sizeof...(IdxTail) > 0) + return hsa_api_data_string(id, _data, std::index_sequence{}); + else + return std::string{}; +} + +template +std::string +hsa_api_named_data_string(const uint32_t id, + const hsa_trace_data_t& _data, + std::index_sequence) +{ + if(Idx == id) return hsa_api_info::as_named_string(_data); + if constexpr(sizeof...(IdxTail) > 0) + return hsa_api_named_data_string(id, _data, std::index_sequence{}); + else + return std::string{}; +} + +template +void +hsa_api_iterate_args(const uint32_t id, + const hsa_trace_data_t& _data, + int (*_func)(const char*, const char*), + std::index_sequence) +{ + if(Idx == id) + { + for(auto&& itr : hsa_api_info::as_arg_list(_data)) + { + _func(itr.first.c_str(), itr.second.c_str()); + } + } + if constexpr(sizeof...(IdxTail) > 0) + hsa_api_iterate_args(id, _data, _func, std::index_sequence{}); +} + +template +void +hsa_api_get_ids(std::vector& _id_list, std::index_sequence) +{ + auto _emplace = [](auto& _vec, uint32_t _v) { + if(_v < HSA_API_ID_DISPATCH) _vec.emplace_back(_v); + }; + + (_emplace(_id_list, hsa_api_info::operation_idx), ...); +} + +template +void +hsa_api_get_names(std::vector& _name_list, std::index_sequence) +{ + auto _emplace = [](auto& _vec, const char* _v) { + if(_v != nullptr && strnlen(_v, 1) > 0) _vec.emplace_back(_v); + }; + + (_emplace(_name_list, hsa_api_info::name), ...); +} + +template +void +hsa_api_update_table(hsa_api_table_t* _orig, std::index_sequence) +{ + auto _update = [](hsa_api_table_t* _orig_v, auto _info) { + // 1. get the sub-table containing the function pointer + // 2. get reference to function pointer in sub-table + // 3. update function pointer with functor + auto& _table = _info.get_table(_orig_v); + auto& _func = _info.get_table_func(_table); + _func = _info.get_functor(_func); + }; + + (_update(_orig, hsa_api_info{}), ...); +} +} // namespace + +// check out the assembly here... this compiles to a switch statement +const char* +hsa_api_name(uint32_t id) +{ + return hsa_api_name(id, std::make_index_sequence{}); +} + +uint32_t +hsa_api_id_by_name(const char* name) +{ + return hsa_api_id_by_name(name, std::make_index_sequence{}); +} + +std::string +hsa_api_data_string(uint32_t id, const hsa_trace_data_t& _data) +{ + return hsa_api_data_string(id, _data, std::make_index_sequence{}); +} + +std::string +hsa_api_named_data_string(uint32_t id, const hsa_trace_data_t& _data) +{ + return hsa_api_named_data_string(id, _data, std::make_index_sequence{}); +} + +void +hsa_api_iterate_args(uint32_t id, + const hsa_trace_data_t& _data, + int (*_func)(const char*, const char*)) +{ + if(_func) + hsa_api_iterate_args(id, _data, _func, std::make_index_sequence{}); +} + +std::vector +hsa_api_get_ids() +{ + auto _data = std::vector{}; + _data.reserve(HSA_API_ID_DISPATCH); + hsa_api_get_ids(_data, std::make_index_sequence{}); + return _data; +} + +std::vector +hsa_api_get_names() +{ + auto _data = std::vector{}; + _data.reserve(HSA_API_ID_DISPATCH); + hsa_api_get_names(_data, std::make_index_sequence{}); + return _data; +} + +void +hsa_api_set_callback(activity_functor_t _func) +{ + auto&& _v = report_activity.load(); + report_activity.compare_exchange_strong(_v, _func); +} + +void +hsa_api_update_table(hsa_api_table_t* _orig) +{ + if(_orig) hsa_api_update_table(_orig, std::make_index_sequence{}); +} +} // namespace hsa +} // namespace rocprofiler + +extern "C" { +bool +OnLoad(HsaApiTable* table, + uint64_t runtime_version, + uint64_t failed_tool_count, + const char* const* failed_tool_names) +{ + (void) runtime_version; + (void) failed_tool_count; + (void) failed_tool_names; + + auto& _saved = rocprofiler::hsa::get_saved_table(); + copyTables(table, &_saved); + + rocprofiler::hsa::hsa_api_update_table(table); + + return true; +} +} + +/* +#include + +int +main() +{ + rocprofiler::hsa::activity_functor_t _cb = + [](rocprofiler_tracer_activity_domain_t domain, uint32_t operation_id, void* data) { + const auto* _name = rocprofiler::hsa::hsa_api_name(operation_id); + auto _name_id = rocprofiler::hsa::hsa_api_id_by_name(_name); + auto& _data = *static_cast(data); + std::cout << "[cb] domain=" << domain << ", op_id=" << operation_id << ", data=" << data + << ", name=" << _name << ", name_id=" << _name_id << ", named_string='" + << rocprofiler::hsa::hsa_api_named_data_string(operation_id, _data) << "'" + << "\n"; + auto _func = [](const char* name, const char* value) { + std::cout << " " << std::setw(20) << name << " = " << value << "\n"; + return 0; + }; + rocprofiler::hsa::hsa_api_iterate_args(operation_id, _data, _func); + return 0; + }; + + rocprofiler::hsa::report_activity.store(_cb); + + { + double val = 40; + hsa_code_object_t code_object = {}; + hsa_code_object_info_t attribute = HSA_CODE_OBJECT_INFO_TYPE; + void* value = &val; + + auto _func = + rocprofiler::hsa::hsa_api_info::get_functor(); + _func(code_object, attribute, value); + } + + { + bool result = false; + uint16_t ext = 1; + uint16_t major = 4; + uint16_t minor = 2; + + auto _func = rocprofiler::hsa::hsa_api_info< + HSA_API_ID_hsa_system_extension_supported>::get_functor(); + _func(ext, major, minor, &result); + } +} +*/ diff --git a/source/lib/rocprofiler/hsa/hsa.gen.cpp b/source/lib/rocprofiler/hsa/hsa.gen.cpp new file mode 100644 index 0000000000..2643bc81da --- /dev/null +++ b/source/lib/rocprofiler/hsa/hsa.gen.cpp @@ -0,0 +1,217 @@ +// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN +// THE SOFTWARE. + +#include "hsa.hpp" + +// clang-format off +HSA_API_INFO_DEFINITION_0(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_init, hsa_init, hsa_init_fn) +HSA_API_INFO_DEFINITION_0(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_shut_down, hsa_shut_down, hsa_shut_down_fn) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_system_get_info, hsa_system_get_info, hsa_system_get_info_fn, attribute, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_system_extension_supported, hsa_system_extension_supported, hsa_system_extension_supported_fn, extension, version_major, version_minor, result) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_system_get_extension_table, hsa_system_get_extension_table, hsa_system_get_extension_table_fn, extension, version_major, version_minor, table) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_iterate_agents, hsa_iterate_agents, hsa_iterate_agents_fn, callback, data) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_agent_get_info, hsa_agent_get_info, hsa_agent_get_info_fn, agent, attribute, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_create, hsa_queue_create, hsa_queue_create_fn, agent, size, type, callback, data, private_segment_size, group_segment_size, queue) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_soft_queue_create, hsa_soft_queue_create, hsa_soft_queue_create_fn, region, size, type, features, doorbell_signal, queue) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_destroy, hsa_queue_destroy, hsa_queue_destroy_fn, queue) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_inactivate, hsa_queue_inactivate, hsa_queue_inactivate_fn, queue) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_load_read_index_scacquire, hsa_queue_load_read_index_scacquire, hsa_queue_load_read_index_scacquire_fn, queue) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_load_read_index_relaxed, hsa_queue_load_read_index_relaxed, hsa_queue_load_read_index_relaxed_fn, queue) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_load_write_index_scacquire, hsa_queue_load_write_index_scacquire, hsa_queue_load_write_index_scacquire_fn, queue) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_load_write_index_relaxed, hsa_queue_load_write_index_relaxed, hsa_queue_load_write_index_relaxed_fn, queue) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_store_write_index_relaxed, hsa_queue_store_write_index_relaxed, hsa_queue_store_write_index_relaxed_fn, queue, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_store_write_index_screlease, hsa_queue_store_write_index_screlease, hsa_queue_store_write_index_screlease_fn, queue, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_cas_write_index_scacq_screl, hsa_queue_cas_write_index_scacq_screl, hsa_queue_cas_write_index_scacq_screl_fn, queue, expected, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_cas_write_index_scacquire, hsa_queue_cas_write_index_scacquire, hsa_queue_cas_write_index_scacquire_fn, queue, expected, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_cas_write_index_relaxed, hsa_queue_cas_write_index_relaxed, hsa_queue_cas_write_index_relaxed_fn, queue, expected, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_cas_write_index_screlease, hsa_queue_cas_write_index_screlease, hsa_queue_cas_write_index_screlease_fn, queue, expected, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_add_write_index_scacq_screl, hsa_queue_add_write_index_scacq_screl, hsa_queue_add_write_index_scacq_screl_fn, queue, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_add_write_index_scacquire, hsa_queue_add_write_index_scacquire, hsa_queue_add_write_index_scacquire_fn, queue, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_add_write_index_relaxed, hsa_queue_add_write_index_relaxed, hsa_queue_add_write_index_relaxed_fn, queue, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_add_write_index_screlease, hsa_queue_add_write_index_screlease, hsa_queue_add_write_index_screlease_fn, queue, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_store_read_index_relaxed, hsa_queue_store_read_index_relaxed, hsa_queue_store_read_index_relaxed_fn, queue, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_queue_store_read_index_screlease, hsa_queue_store_read_index_screlease, hsa_queue_store_read_index_screlease_fn, queue, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_agent_iterate_regions, hsa_agent_iterate_regions, hsa_agent_iterate_regions_fn, agent, callback, data) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_region_get_info, hsa_region_get_info, hsa_region_get_info_fn, region, attribute, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_agent_get_exception_policies, hsa_agent_get_exception_policies, hsa_agent_get_exception_policies_fn, agent, profile, mask) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_agent_extension_supported, hsa_agent_extension_supported, hsa_agent_extension_supported_fn, extension, agent, version_major, version_minor, result) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_memory_register, hsa_memory_register, hsa_memory_register_fn, ptr, size) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_memory_deregister, hsa_memory_deregister, hsa_memory_deregister_fn, ptr, size) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_memory_allocate, hsa_memory_allocate, hsa_memory_allocate_fn, region, size, ptr) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_memory_free, hsa_memory_free, hsa_memory_free_fn, ptr) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_memory_copy, hsa_memory_copy, hsa_memory_copy_fn, dst, src, size) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_memory_assign_agent, hsa_memory_assign_agent, hsa_memory_assign_agent_fn, ptr, agent, access) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_create, hsa_signal_create, hsa_signal_create_fn, initial_value, num_consumers, consumers, signal) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_destroy, hsa_signal_destroy, hsa_signal_destroy_fn, signal) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_load_relaxed, hsa_signal_load_relaxed, hsa_signal_load_relaxed_fn, signal) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_load_scacquire, hsa_signal_load_scacquire, hsa_signal_load_scacquire_fn, signal) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_store_relaxed, hsa_signal_store_relaxed, hsa_signal_store_relaxed_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_store_screlease, hsa_signal_store_screlease, hsa_signal_store_screlease_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_wait_relaxed, hsa_signal_wait_relaxed, hsa_signal_wait_relaxed_fn, signal, condition, compare_value, timeout_hint, wait_state_hint) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_wait_scacquire, hsa_signal_wait_scacquire, hsa_signal_wait_scacquire_fn, signal, condition, compare_value, timeout_hint, wait_state_hint) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_and_relaxed, hsa_signal_and_relaxed, hsa_signal_and_relaxed_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_and_scacquire, hsa_signal_and_scacquire, hsa_signal_and_scacquire_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_and_screlease, hsa_signal_and_screlease, hsa_signal_and_screlease_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_and_scacq_screl, hsa_signal_and_scacq_screl, hsa_signal_and_scacq_screl_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_or_relaxed, hsa_signal_or_relaxed, hsa_signal_or_relaxed_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_or_scacquire, hsa_signal_or_scacquire, hsa_signal_or_scacquire_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_or_screlease, hsa_signal_or_screlease, hsa_signal_or_screlease_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_or_scacq_screl, hsa_signal_or_scacq_screl, hsa_signal_or_scacq_screl_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_xor_relaxed, hsa_signal_xor_relaxed, hsa_signal_xor_relaxed_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_xor_scacquire, hsa_signal_xor_scacquire, hsa_signal_xor_scacquire_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_xor_screlease, hsa_signal_xor_screlease, hsa_signal_xor_screlease_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_xor_scacq_screl, hsa_signal_xor_scacq_screl, hsa_signal_xor_scacq_screl_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_exchange_relaxed, hsa_signal_exchange_relaxed, hsa_signal_exchange_relaxed_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_exchange_scacquire, hsa_signal_exchange_scacquire, hsa_signal_exchange_scacquire_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_exchange_screlease, hsa_signal_exchange_screlease, hsa_signal_exchange_screlease_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_exchange_scacq_screl, hsa_signal_exchange_scacq_screl, hsa_signal_exchange_scacq_screl_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_add_relaxed, hsa_signal_add_relaxed, hsa_signal_add_relaxed_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_add_scacquire, hsa_signal_add_scacquire, hsa_signal_add_scacquire_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_add_screlease, hsa_signal_add_screlease, hsa_signal_add_screlease_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_add_scacq_screl, hsa_signal_add_scacq_screl, hsa_signal_add_scacq_screl_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_subtract_relaxed, hsa_signal_subtract_relaxed, hsa_signal_subtract_relaxed_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_subtract_scacquire, hsa_signal_subtract_scacquire, hsa_signal_subtract_scacquire_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_subtract_screlease, hsa_signal_subtract_screlease, hsa_signal_subtract_screlease_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_subtract_scacq_screl, hsa_signal_subtract_scacq_screl, hsa_signal_subtract_scacq_screl_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_cas_relaxed, hsa_signal_cas_relaxed, hsa_signal_cas_relaxed_fn, signal, expected, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_cas_scacquire, hsa_signal_cas_scacquire, hsa_signal_cas_scacquire_fn, signal, expected, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_cas_screlease, hsa_signal_cas_screlease, hsa_signal_cas_screlease_fn, signal, expected, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_cas_scacq_screl, hsa_signal_cas_scacq_screl, hsa_signal_cas_scacq_screl_fn, signal, expected, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_isa_from_name, hsa_isa_from_name, hsa_isa_from_name_fn, name, isa) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_isa_get_info, hsa_isa_get_info, hsa_isa_get_info_fn, isa, attribute, index, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_isa_compatible, hsa_isa_compatible, hsa_isa_compatible_fn, code_object_isa, agent_isa, result) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_serialize, hsa_code_object_serialize, hsa_code_object_serialize_fn, code_object, alloc_callback, callback_data, options, serialized_code_object, serialized_code_object_size) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_deserialize, hsa_code_object_deserialize, hsa_code_object_deserialize_fn, serialized_code_object, serialized_code_object_size, options, code_object) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_destroy, hsa_code_object_destroy, hsa_code_object_destroy_fn, code_object) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_get_info, hsa_code_object_get_info, hsa_code_object_get_info_fn, code_object, attribute, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_get_symbol, hsa_code_object_get_symbol, hsa_code_object_get_symbol_fn, code_object, symbol_name, symbol) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_symbol_get_info, hsa_code_symbol_get_info, hsa_code_symbol_get_info_fn, code_symbol, attribute, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_iterate_symbols, hsa_code_object_iterate_symbols, hsa_code_object_iterate_symbols_fn, code_object, callback, data) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_create, hsa_executable_create, hsa_executable_create_fn, profile, executable_state, options, executable) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_destroy, hsa_executable_destroy, hsa_executable_destroy_fn, executable) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_load_code_object, hsa_executable_load_code_object, hsa_executable_load_code_object_fn, executable, agent, code_object, options) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_freeze, hsa_executable_freeze, hsa_executable_freeze_fn, executable, options) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_get_info, hsa_executable_get_info, hsa_executable_get_info_fn, executable, attribute, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_global_variable_define, hsa_executable_global_variable_define, hsa_executable_global_variable_define_fn, executable, variable_name, address) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_agent_global_variable_define, hsa_executable_agent_global_variable_define, hsa_executable_agent_global_variable_define_fn, executable, agent, variable_name, address) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_readonly_variable_define, hsa_executable_readonly_variable_define, hsa_executable_readonly_variable_define_fn, executable, agent, variable_name, address) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_validate, hsa_executable_validate, hsa_executable_validate_fn, executable, result) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_get_symbol, hsa_executable_get_symbol, hsa_executable_get_symbol_fn, executable, module_name, symbol_name, agent, call_convention, symbol) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_symbol_get_info, hsa_executable_symbol_get_info, hsa_executable_symbol_get_info_fn, executable_symbol, attribute, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_iterate_symbols, hsa_executable_iterate_symbols, hsa_executable_iterate_symbols_fn, executable, callback, data) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_status_string, hsa_status_string, hsa_status_string_fn, status, status_string) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_extension_get_name, hsa_extension_get_name, hsa_extension_get_name_fn, extension, name) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_system_major_extension_supported, hsa_system_major_extension_supported, hsa_system_major_extension_supported_fn, extension, version_major, version_minor, result) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_system_get_major_extension_table, hsa_system_get_major_extension_table, hsa_system_get_major_extension_table_fn, extension, version_major, table_length, table) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_agent_major_extension_supported, hsa_agent_major_extension_supported, hsa_agent_major_extension_supported_fn, extension, agent, version_major, version_minor, result) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_cache_get_info, hsa_cache_get_info, hsa_cache_get_info_fn, cache, attribute, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_agent_iterate_caches, hsa_agent_iterate_caches, hsa_agent_iterate_caches_fn, agent, callback, data) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_silent_store_relaxed, hsa_signal_silent_store_relaxed, hsa_signal_silent_store_relaxed_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_silent_store_screlease, hsa_signal_silent_store_screlease, hsa_signal_silent_store_screlease_fn, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_group_create, hsa_signal_group_create, hsa_signal_group_create_fn, num_signals, signals, num_consumers, consumers, signal_group) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_group_destroy, hsa_signal_group_destroy, hsa_signal_group_destroy_fn, signal_group) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_group_wait_any_scacquire, hsa_signal_group_wait_any_scacquire, hsa_signal_group_wait_any_scacquire_fn, signal_group, conditions, compare_values, wait_state_hint, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_signal_group_wait_any_relaxed, hsa_signal_group_wait_any_relaxed, hsa_signal_group_wait_any_relaxed_fn, signal_group, conditions, compare_values, wait_state_hint, signal, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_agent_iterate_isas, hsa_agent_iterate_isas, hsa_agent_iterate_isas_fn, agent, callback, data) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_isa_get_info_alt, hsa_isa_get_info_alt, hsa_isa_get_info_alt_fn, isa, attribute, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_isa_get_exception_policies, hsa_isa_get_exception_policies, hsa_isa_get_exception_policies_fn, isa, profile, mask) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_isa_get_round_method, hsa_isa_get_round_method, hsa_isa_get_round_method_fn, isa, fp_type, flush_mode, round_method) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_wavefront_get_info, hsa_wavefront_get_info, hsa_wavefront_get_info_fn, wavefront, attribute, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_isa_iterate_wavefronts, hsa_isa_iterate_wavefronts, hsa_isa_iterate_wavefronts_fn, isa, callback, data) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_get_symbol_from_name, hsa_code_object_get_symbol_from_name, hsa_code_object_get_symbol_from_name_fn, code_object, module_name, symbol_name, symbol) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_reader_create_from_file, hsa_code_object_reader_create_from_file, hsa_code_object_reader_create_from_file_fn, file, code_object_reader) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_reader_create_from_memory, hsa_code_object_reader_create_from_memory, hsa_code_object_reader_create_from_memory_fn, code_object, size, code_object_reader) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_code_object_reader_destroy, hsa_code_object_reader_destroy, hsa_code_object_reader_destroy_fn, code_object_reader) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_create_alt, hsa_executable_create_alt, hsa_executable_create_alt_fn, profile, default_float_rounding_mode, options, executable) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_load_program_code_object, hsa_executable_load_program_code_object, hsa_executable_load_program_code_object_fn, executable, code_object_reader, options, loaded_code_object) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_load_agent_code_object, hsa_executable_load_agent_code_object, hsa_executable_load_agent_code_object_fn, executable, agent, code_object_reader, options, loaded_code_object) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_validate_alt, hsa_executable_validate_alt, hsa_executable_validate_alt_fn, executable, options, result) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_get_symbol_by_name, hsa_executable_get_symbol_by_name, hsa_executable_get_symbol_by_name_fn, executable, symbol_name, agent, symbol) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_iterate_agent_symbols, hsa_executable_iterate_agent_symbols, hsa_executable_iterate_agent_symbols_fn, executable, agent, callback, data) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_CoreApi, HSA_API_ID_hsa_executable_iterate_program_symbols, hsa_executable_iterate_program_symbols, hsa_executable_iterate_program_symbols_fn, executable, callback, data) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_coherency_get_type, hsa_amd_coherency_get_type, hsa_amd_coherency_get_type_fn, agent, type) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_coherency_set_type, hsa_amd_coherency_set_type, hsa_amd_coherency_set_type_fn, agent, type) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_profiling_set_profiler_enabled, hsa_amd_profiling_set_profiler_enabled, hsa_amd_profiling_set_profiler_enabled_fn, queue, enable) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_profiling_async_copy_enable, hsa_amd_profiling_async_copy_enable, hsa_amd_profiling_async_copy_enable_fn, enable) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_profiling_get_dispatch_time, hsa_amd_profiling_get_dispatch_time, hsa_amd_profiling_get_dispatch_time_fn, agent, signal, time) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_profiling_get_async_copy_time, hsa_amd_profiling_get_async_copy_time, hsa_amd_profiling_get_async_copy_time_fn, signal, time) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_profiling_convert_tick_to_system_domain, hsa_amd_profiling_convert_tick_to_system_domain, hsa_amd_profiling_convert_tick_to_system_domain_fn, agent, agent_tick, system_tick) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_signal_async_handler, hsa_amd_signal_async_handler, hsa_amd_signal_async_handler_fn, signal, cond, value, handler, arg) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_async_function, hsa_amd_async_function, hsa_amd_async_function_fn, callback, arg) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_signal_wait_any, hsa_amd_signal_wait_any, hsa_amd_signal_wait_any_fn, signal_count, signals, conds, values, timeout_hint, wait_hint, satisfying_value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_queue_cu_set_mask, hsa_amd_queue_cu_set_mask, hsa_amd_queue_cu_set_mask_fn, queue, num_cu_mask_count, cu_mask) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_pool_get_info, hsa_amd_memory_pool_get_info, hsa_amd_memory_pool_get_info_fn, memory_pool, attribute, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_agent_iterate_memory_pools, hsa_amd_agent_iterate_memory_pools, hsa_amd_agent_iterate_memory_pools_fn, agent, callback, data) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_pool_allocate, hsa_amd_memory_pool_allocate, hsa_amd_memory_pool_allocate_fn, memory_pool, size, flags, ptr) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_pool_free, hsa_amd_memory_pool_free, hsa_amd_memory_pool_free_fn, ptr) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_async_copy, hsa_amd_memory_async_copy, hsa_amd_memory_async_copy_fn, dst, dst_agent, src, src_agent, size, num_dep_signals, dep_signals, completion_signal) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_async_copy_on_engine, hsa_amd_memory_async_copy_on_engine, hsa_amd_memory_async_copy_on_engine_fn, dst, dst_agent, src, src_agent, size, num_dep_signals, dep_signals, completion_signal, engine_id, force_copy_on_sdma) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_copy_engine_status, hsa_amd_memory_copy_engine_status, hsa_amd_memory_copy_engine_status_fn, dst_agent, src_agent, engine_ids_mask) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_agent_memory_pool_get_info, hsa_amd_agent_memory_pool_get_info, hsa_amd_agent_memory_pool_get_info_fn, agent, memory_pool, attribute, value) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_agents_allow_access, hsa_amd_agents_allow_access, hsa_amd_agents_allow_access_fn, num_agents, agents, flags, ptr) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_pool_can_migrate, hsa_amd_memory_pool_can_migrate, hsa_amd_memory_pool_can_migrate_fn, src_memory_pool, dst_memory_pool, result) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_migrate, hsa_amd_memory_migrate, hsa_amd_memory_migrate_fn, ptr, memory_pool, flags) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_lock, hsa_amd_memory_lock, hsa_amd_memory_lock_fn, host_ptr, size, agents, num_agent, agent_ptr) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_unlock, hsa_amd_memory_unlock, hsa_amd_memory_unlock_fn, host_ptr) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_fill, hsa_amd_memory_fill, hsa_amd_memory_fill_fn, ptr, value, count) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_interop_map_buffer, hsa_amd_interop_map_buffer, hsa_amd_interop_map_buffer_fn, num_agents, agents, interop_handle, flags, size, ptr, metadata_size, metadata) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_interop_unmap_buffer, hsa_amd_interop_unmap_buffer, hsa_amd_interop_unmap_buffer_fn, ptr) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_image_create, hsa_amd_image_create, hsa_amd_image_create_fn, agent, image_descriptor, image_layout, image_data, access_permission, image) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_pointer_info, hsa_amd_pointer_info, hsa_amd_pointer_info_fn, ptr, info, alloc, num_agents_accessible, accessible) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_pointer_info_set_userdata, hsa_amd_pointer_info_set_userdata, hsa_amd_pointer_info_set_userdata_fn, ptr, userdata) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_ipc_memory_create, hsa_amd_ipc_memory_create, hsa_amd_ipc_memory_create_fn, ptr, len, handle) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_ipc_memory_attach, hsa_amd_ipc_memory_attach, hsa_amd_ipc_memory_attach_fn, handle, len, num_agents, mapping_agents, mapped_ptr) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_ipc_memory_detach, hsa_amd_ipc_memory_detach, hsa_amd_ipc_memory_detach_fn, mapped_ptr) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_signal_create, hsa_amd_signal_create, hsa_amd_signal_create_fn, initial_value, num_consumers, consumers, attributes, signal) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_ipc_signal_create, hsa_amd_ipc_signal_create, hsa_amd_ipc_signal_create_fn, signal, handle) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_ipc_signal_attach, hsa_amd_ipc_signal_attach, hsa_amd_ipc_signal_attach_fn, handle, signal) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_register_system_event_handler, hsa_amd_register_system_event_handler, hsa_amd_register_system_event_handler_fn, callback, data) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_queue_set_priority, hsa_amd_queue_set_priority, hsa_amd_queue_set_priority_fn, queue, priority) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_async_copy_rect, hsa_amd_memory_async_copy_rect, hsa_amd_memory_async_copy_rect_fn, dst, dst_offset, src, src_offset, range, copy_agent, dir, num_dep_signals, dep_signals, completion_signal) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_memory_lock_to_pool, hsa_amd_memory_lock_to_pool, hsa_amd_memory_lock_to_pool_fn, host_ptr, size, agents, num_agent, pool, flags, agent_ptr) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_register_deallocation_callback, hsa_amd_register_deallocation_callback, hsa_amd_register_deallocation_callback_fn, ptr, callback, user_data) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_deregister_deallocation_callback, hsa_amd_deregister_deallocation_callback, hsa_amd_deregister_deallocation_callback_fn, ptr, callback) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_signal_value_pointer, hsa_amd_signal_value_pointer, hsa_amd_signal_value_pointer_fn, signal, value_ptr) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_svm_attributes_set, hsa_amd_svm_attributes_set, hsa_amd_svm_attributes_set_fn, ptr, size, attribute_list, attribute_count) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_svm_attributes_get, hsa_amd_svm_attributes_get, hsa_amd_svm_attributes_get_fn, ptr, size, attribute_list, attribute_count) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_svm_prefetch_async, hsa_amd_svm_prefetch_async, hsa_amd_svm_prefetch_async_fn, ptr, size, agent, num_dep_signals, dep_signals, completion_signal) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_spm_acquire, hsa_amd_spm_acquire, hsa_amd_spm_acquire_fn, preferred_agent) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_spm_release, hsa_amd_spm_release, hsa_amd_spm_release_fn, preferred_agent) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_spm_set_dest_buffer, hsa_amd_spm_set_dest_buffer, hsa_amd_spm_set_dest_buffer_fn, preferred_agent, size_in_bytes, timeout, size_copied, dest, is_data_loss) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_queue_cu_get_mask, hsa_amd_queue_cu_get_mask, hsa_amd_queue_cu_get_mask_fn, queue, num_cu_mask_count, cu_mask) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_portable_export_dmabuf, hsa_amd_portable_export_dmabuf, hsa_amd_portable_export_dmabuf_fn, ptr, size, dmabuf, offset) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_portable_close_dmabuf, hsa_amd_portable_close_dmabuf, hsa_amd_portable_close_dmabuf_fn, dmabuf) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_get_capability, hsa_ext_image_get_capability, hsa_ext_image_get_capability_fn, agent, geometry, image_format, capability_mask) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_data_get_info, hsa_ext_image_data_get_info, hsa_ext_image_data_get_info_fn, agent, image_descriptor, access_permission, image_data_info) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_create, hsa_ext_image_create, hsa_ext_image_create_fn, agent, image_descriptor, image_data, access_permission, image) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_import, hsa_ext_image_import, hsa_ext_image_import_fn, agent, src_memory, src_row_pitch, src_slice_pitch, dst_image, image_region) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_export, hsa_ext_image_export, hsa_ext_image_export_fn, agent, src_image, dst_memory, dst_row_pitch, dst_slice_pitch, image_region) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_copy, hsa_ext_image_copy, hsa_ext_image_copy_fn, agent, src_image, src_offset, dst_image, dst_offset, range) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_clear, hsa_ext_image_clear, hsa_ext_image_clear_fn, agent, image, data, image_region) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_destroy, hsa_ext_image_destroy, hsa_ext_image_destroy_fn, agent, image) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_sampler_create, hsa_ext_sampler_create, hsa_ext_sampler_create_fn, agent, sampler_descriptor, sampler) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_sampler_destroy, hsa_ext_sampler_destroy, hsa_ext_sampler_destroy_fn, agent, sampler) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_get_capability_with_layout, hsa_ext_image_get_capability_with_layout, hsa_ext_image_get_capability_with_layout_fn, agent, geometry, image_format, image_data_layout, capability_mask) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_data_get_info_with_layout, hsa_ext_image_data_get_info_with_layout, hsa_ext_image_data_get_info_with_layout_fn, agent, image_descriptor, access_permission, image_data_layout, image_data_row_pitch, image_data_slice_pitch, image_data_info) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_ImageExt, HSA_API_ID_hsa_ext_image_create_with_layout, hsa_ext_image_create_with_layout, hsa_ext_image_create_with_layout_fn, agent, image_descriptor, image_data, access_permission, image_data_layout, image_data_row_pitch, image_data_slice_pitch, image) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_queue_intercept_create, hsa_amd_queue_intercept_create, hsa_amd_queue_intercept_create_fn, agent_handle, size, type, callback, data, private_segment_size, group_segment_size, queue) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_queue_intercept_register, hsa_amd_queue_intercept_register, hsa_amd_queue_intercept_register_fn, queue, callback, user_data) +HSA_API_INFO_DEFINITION_V(ACTIVITY_DOMAIN_HSA_API, HSA_API_TABLE_ID_AmdExt, HSA_API_ID_hsa_amd_runtime_queue_create_register, hsa_amd_runtime_queue_create_register, hsa_amd_runtime_queue_create_register_fn, callback, user_data) +// clang-format on diff --git a/source/lib/rocprofiler/hsa/hsa.hpp b/source/lib/rocprofiler/hsa/hsa.hpp new file mode 100644 index 0000000000..9b77118a93 --- /dev/null +++ b/source/lib/rocprofiler/hsa/hsa.hpp @@ -0,0 +1,124 @@ +// Copyright (c) 2018-2023 Advanced Micro Devices, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// 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 +// AUTHORS 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 IN +// THE SOFTWARE. + +#pragma once + +#include "lib/common/defines.hpp" +#include "lib/rocprofiler/hsa/hsa-defines.hpp" +#include "lib/rocprofiler/hsa/hsa-ostream.hpp" +#include "lib/rocprofiler/hsa/hsa-types.h" +#include "lib/rocprofiler/hsa/hsa-utils.hpp" + +#include +#include + +#include + +namespace rocprofiler +{ +namespace hsa +{ +using activity_functor_t = int (*)(rocprofiler_tracer_activity_domain_t domain, + uint32_t operation_id, + void* data); + +using hsa_api_table_t = HsaApiTable; + +struct hsa_trace_data_t +{ + hsa_api_data_t api_data; + uint64_t phase_enter_timestamp; + uint64_t phase_data; + + void (*phase_enter)(hsa_api_id_t operation_id, hsa_trace_data_t* data); + void (*phase_exit)(hsa_api_id_t operation_id, hsa_trace_data_t* data); +}; + +enum hsa_table_api_id_t +{ + HSA_API_TABLE_ID_CoreApi, + HSA_API_TABLE_ID_AmdExt, + HSA_API_TABLE_ID_ImageExt, + HSA_API_TABLE_ID_NUMBER, +}; + +template +void +set_data_retval(DataT&, Tp); + +template +struct hsa_table_lookup; + +template +struct hsa_api_impl +{ + template + static auto phase_enter(DataT& _data, DataArgsT&, Args... args); + + template + static auto phase_exit(DataT& _data); + + template + static auto exec(DataT& _data, FuncT&&, Args&&... args); + + template + static auto functor(Args&&... args); +}; + +template +struct hsa_api_info; + +const char* +hsa_api_name(uint32_t id); + +uint32_t +hsa_api_id_by_name(const char* name); + +std::string +hsa_api_data_string(uint32_t id, const hsa_trace_data_t& _data); + +std::string +hsa_api_named_data_string(uint32_t id, const hsa_trace_data_t& _data); + +void +hsa_api_iterate_args(uint32_t id, + const hsa_trace_data_t& _data, + int (*_func)(const char*, const char*)); + +std::vector +hsa_api_get_names(); + +std::vector +hsa_api_get_ids(); + +void +hsa_api_set_callback(activity_functor_t _func); +} // namespace hsa +} // namespace rocprofiler + +extern "C" { +using on_load_t = bool (*)(HsaApiTable*, uint64_t, uint64_t, const char* const*); + +bool +OnLoad(HsaApiTable* table, + uint64_t runtime_version, + uint64_t failed_tool_count, + const char* const* failed_tool_names) ROCPROFILER_PUBLIC_API; +} diff --git a/source/lib/rocprofiler/rocprofiler_config.cpp b/source/lib/rocprofiler/rocprofiler_config.cpp new file mode 100644 index 0000000000..b0d26aa0cb --- /dev/null +++ b/source/lib/rocprofiler/rocprofiler_config.cpp @@ -0,0 +1,4382 @@ + +#include +#include + +#include "config_helpers.hpp" +#include "config_internal.hpp" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +typedef enum +{ + ACTIVITY_API_PHASE_ENTER = 0, + ACTIVITY_API_PHASE_EXIT = 1 +} activity_api_phase_t; + +typedef struct roctx_api_data_s +{ + union + { + struct + { + const char* message; + roctx_range_id_t id; + }; + struct + { + const char* message; + } roctxMarkA; + struct + { + const char* message; + } roctxRangePushA; + struct + { + const char* message; + } roctxRangePop; + struct + { + const char* message; + roctx_range_id_t id; + } roctxRangeStartA; + struct + { + const char* message; + roctx_range_id_t id; + } roctxRangeStop; + } args; +} roctx_api_data_t; + +typedef struct hsa_api_data_s +{ + uint64_t correlation_id; + uint32_t phase; + union + { + uint32_t uint32_t_retval; + hsa_signal_value_t hsa_signal_value_t_retval; + uint64_t uint64_t_retval; + hsa_status_t hsa_status_t_retval; + }; + union + { + /* block: CoreApi API */ + struct + { + } hsa_init; + struct + { + } hsa_shut_down; + struct + { + hsa_system_info_t attribute; + void* value; + } hsa_system_get_info; + struct + { + uint16_t extension; + uint16_t version_major; + uint16_t version_minor; + bool* result; + } hsa_system_extension_supported; + struct + { + uint16_t extension; + uint16_t version_major; + uint16_t version_minor; + void* table; + } hsa_system_get_extension_table; + struct + { + hsa_status_t (*callback)(hsa_agent_t agent, void* data); + void* data; + } hsa_iterate_agents; + struct + { + hsa_agent_t agent; + hsa_agent_info_t attribute; + void* value; + } hsa_agent_get_info; + struct + { + hsa_agent_t agent; + uint32_t size; + hsa_queue_type32_t type; + void (*callback)(hsa_status_t status, hsa_queue_t* source, void* data); + void* data; + uint32_t private_segment_size; + uint32_t group_segment_size; + hsa_queue_t** queue; + } hsa_queue_create; + struct + { + hsa_region_t region; + uint32_t size; + hsa_queue_type32_t type; + uint32_t features; + hsa_signal_t doorbell_signal; + hsa_queue_t** queue; + } hsa_soft_queue_create; + struct + { + hsa_queue_t* queue; + } hsa_queue_destroy; + struct + { + hsa_queue_t* queue; + } hsa_queue_inactivate; + struct + { + const hsa_queue_t* queue; + } hsa_queue_load_read_index_scacquire; + struct + { + const hsa_queue_t* queue; + } hsa_queue_load_read_index_relaxed; + struct + { + const hsa_queue_t* queue; + } hsa_queue_load_write_index_scacquire; + struct + { + const hsa_queue_t* queue; + } hsa_queue_load_write_index_relaxed; + struct + { + const hsa_queue_t* queue; + uint64_t value; + } hsa_queue_store_write_index_relaxed; + struct + { + const hsa_queue_t* queue; + uint64_t value; + } hsa_queue_store_write_index_screlease; + struct + { + const hsa_queue_t* queue; + uint64_t expected; + uint64_t value; + } hsa_queue_cas_write_index_scacq_screl; + struct + { + const hsa_queue_t* queue; + uint64_t expected; + uint64_t value; + } hsa_queue_cas_write_index_scacquire; + struct + { + const hsa_queue_t* queue; + uint64_t expected; + uint64_t value; + } hsa_queue_cas_write_index_relaxed; + struct + { + const hsa_queue_t* queue; + uint64_t expected; + uint64_t value; + } hsa_queue_cas_write_index_screlease; + struct + { + const hsa_queue_t* queue; + uint64_t value; + } hsa_queue_add_write_index_scacq_screl; + struct + { + const hsa_queue_t* queue; + uint64_t value; + } hsa_queue_add_write_index_scacquire; + struct + { + const hsa_queue_t* queue; + uint64_t value; + } hsa_queue_add_write_index_relaxed; + struct + { + const hsa_queue_t* queue; + uint64_t value; + } hsa_queue_add_write_index_screlease; + struct + { + const hsa_queue_t* queue; + uint64_t value; + } hsa_queue_store_read_index_relaxed; + struct + { + const hsa_queue_t* queue; + uint64_t value; + } hsa_queue_store_read_index_screlease; + struct + { + hsa_agent_t agent; + hsa_status_t (*callback)(hsa_region_t region, void* data); + void* data; + } hsa_agent_iterate_regions; + struct + { + hsa_region_t region; + hsa_region_info_t attribute; + void* value; + } hsa_region_get_info; + struct + { + hsa_agent_t agent; + hsa_profile_t profile; + uint16_t* mask; + } hsa_agent_get_exception_policies; + struct + { + uint16_t extension; + hsa_agent_t agent; + uint16_t version_major; + uint16_t version_minor; + bool* result; + } hsa_agent_extension_supported; + struct + { + void* ptr; + size_t size; + } hsa_memory_register; + struct + { + void* ptr; + size_t size; + } hsa_memory_deregister; + struct + { + hsa_region_t region; + size_t size; + void** ptr; + } hsa_memory_allocate; + struct + { + void* ptr; + } hsa_memory_free; + struct + { + void* dst; + const void* src; + size_t size; + } hsa_memory_copy; + struct + { + void* ptr; + hsa_agent_t agent; + hsa_access_permission_t access; + } hsa_memory_assign_agent; + struct + { + hsa_signal_value_t initial_value; + uint32_t num_consumers; + const hsa_agent_t* consumers; + hsa_signal_t* signal; + } hsa_signal_create; + struct + { + hsa_signal_t signal; + } hsa_signal_destroy; + struct + { + hsa_signal_t signal; + } hsa_signal_load_relaxed; + struct + { + hsa_signal_t signal; + } hsa_signal_load_scacquire; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_store_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_store_screlease; + struct + { + hsa_signal_t signal; + hsa_signal_condition_t condition; + hsa_signal_value_t compare_value; + uint64_t timeout_hint; + hsa_wait_state_t wait_state_hint; + } hsa_signal_wait_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_condition_t condition; + hsa_signal_value_t compare_value; + uint64_t timeout_hint; + hsa_wait_state_t wait_state_hint; + } hsa_signal_wait_scacquire; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_and_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_and_scacquire; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_and_screlease; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_and_scacq_screl; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_or_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_or_scacquire; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_or_screlease; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_or_scacq_screl; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_xor_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_xor_scacquire; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_xor_screlease; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_xor_scacq_screl; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_exchange_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_exchange_scacquire; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_exchange_screlease; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_exchange_scacq_screl; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_add_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_add_scacquire; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_add_screlease; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_add_scacq_screl; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_subtract_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_subtract_scacquire; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_subtract_screlease; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_subtract_scacq_screl; + struct + { + hsa_signal_t signal; + hsa_signal_value_t expected; + hsa_signal_value_t value; + } hsa_signal_cas_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_value_t expected; + hsa_signal_value_t value; + } hsa_signal_cas_scacquire; + struct + { + hsa_signal_t signal; + hsa_signal_value_t expected; + hsa_signal_value_t value; + } hsa_signal_cas_screlease; + struct + { + hsa_signal_t signal; + hsa_signal_value_t expected; + hsa_signal_value_t value; + } hsa_signal_cas_scacq_screl; + struct + { + const char* name; + hsa_isa_t* isa; + } hsa_isa_from_name; + struct + { + hsa_isa_t isa; + hsa_isa_info_t attribute; + uint32_t index; + void* value; + } hsa_isa_get_info; + struct + { + hsa_isa_t code_object_isa; + hsa_isa_t agent_isa; + bool* result; + } hsa_isa_compatible; + struct + { + hsa_code_object_t code_object; + hsa_status_t (*alloc_callback)(size_t size, hsa_callback_data_t data, void** address); + hsa_callback_data_t callback_data; + const char* options; + void** serialized_code_object; + size_t* serialized_code_object_size; + } hsa_code_object_serialize; + struct + { + void* serialized_code_object; + size_t serialized_code_object_size; + const char* options; + hsa_code_object_t* code_object; + } hsa_code_object_deserialize; + struct + { + hsa_code_object_t code_object; + } hsa_code_object_destroy; + struct + { + hsa_code_object_t code_object; + hsa_code_object_info_t attribute; + void* value; + } hsa_code_object_get_info; + struct + { + hsa_code_object_t code_object; + const char* symbol_name; + hsa_code_symbol_t* symbol; + } hsa_code_object_get_symbol; + struct + { + hsa_code_symbol_t code_symbol; + hsa_code_symbol_info_t attribute; + void* value; + } hsa_code_symbol_get_info; + struct + { + hsa_code_object_t code_object; + hsa_status_t (*callback)(hsa_code_object_t code_object, + hsa_code_symbol_t symbol, + void* data); + void* data; + } hsa_code_object_iterate_symbols; + struct + { + hsa_profile_t profile; + hsa_executable_state_t executable_state; + const char* options; + hsa_executable_t* executable; + } hsa_executable_create; + struct + { + hsa_executable_t executable; + } hsa_executable_destroy; + struct + { + hsa_executable_t executable; + hsa_agent_t agent; + hsa_code_object_t code_object; + const char* options; + } hsa_executable_load_code_object; + struct + { + hsa_executable_t executable; + const char* options; + } hsa_executable_freeze; + struct + { + hsa_executable_t executable; + hsa_executable_info_t attribute; + void* value; + } hsa_executable_get_info; + struct + { + hsa_executable_t executable; + const char* variable_name; + void* address; + } hsa_executable_global_variable_define; + struct + { + hsa_executable_t executable; + hsa_agent_t agent; + const char* variable_name; + void* address; + } hsa_executable_agent_global_variable_define; + struct + { + hsa_executable_t executable; + hsa_agent_t agent; + const char* variable_name; + void* address; + } hsa_executable_readonly_variable_define; + struct + { + hsa_executable_t executable; + uint32_t* result; + } hsa_executable_validate; + struct + { + hsa_executable_t executable; + const char* module_name; + const char* symbol_name; + hsa_agent_t agent; + int32_t call_convention; + hsa_executable_symbol_t* symbol; + } hsa_executable_get_symbol; + struct + { + hsa_executable_symbol_t executable_symbol; + hsa_executable_symbol_info_t attribute; + void* value; + } hsa_executable_symbol_get_info; + struct + { + hsa_executable_t executable; + hsa_status_t (*callback)(hsa_executable_t exec, + hsa_executable_symbol_t symbol, + void* data); + void* data; + } hsa_executable_iterate_symbols; + struct + { + hsa_status_t status; + const char** status_string; + } hsa_status_string; + struct + { + uint16_t extension; + const char** name; + } hsa_extension_get_name; + struct + { + uint16_t extension; + uint16_t version_major; + uint16_t* version_minor; + bool* result; + } hsa_system_major_extension_supported; + struct + { + uint16_t extension; + uint16_t version_major; + size_t table_length; + void* table; + } hsa_system_get_major_extension_table; + struct + { + uint16_t extension; + hsa_agent_t agent; + uint16_t version_major; + uint16_t* version_minor; + bool* result; + } hsa_agent_major_extension_supported; + struct + { + hsa_cache_t cache; + hsa_cache_info_t attribute; + void* value; + } hsa_cache_get_info; + struct + { + hsa_agent_t agent; + hsa_status_t (*callback)(hsa_cache_t cache, void* data); + void* data; + } hsa_agent_iterate_caches; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_silent_store_relaxed; + struct + { + hsa_signal_t signal; + hsa_signal_value_t value; + } hsa_signal_silent_store_screlease; + struct + { + uint32_t num_signals; + const hsa_signal_t* signals; + uint32_t num_consumers; + const hsa_agent_t* consumers; + hsa_signal_group_t* signal_group; + } hsa_signal_group_create; + struct + { + hsa_signal_group_t signal_group; + } hsa_signal_group_destroy; + struct + { + hsa_signal_group_t signal_group; + const hsa_signal_condition_t* conditions; + const hsa_signal_value_t* compare_values; + hsa_wait_state_t wait_state_hint; + hsa_signal_t* signal; + hsa_signal_value_t* value; + } hsa_signal_group_wait_any_scacquire; + struct + { + hsa_signal_group_t signal_group; + const hsa_signal_condition_t* conditions; + const hsa_signal_value_t* compare_values; + hsa_wait_state_t wait_state_hint; + hsa_signal_t* signal; + hsa_signal_value_t* value; + } hsa_signal_group_wait_any_relaxed; + struct + { + hsa_agent_t agent; + hsa_status_t (*callback)(hsa_isa_t isa, void* data); + void* data; + } hsa_agent_iterate_isas; + struct + { + hsa_isa_t isa; + hsa_isa_info_t attribute; + void* value; + } hsa_isa_get_info_alt; + struct + { + hsa_isa_t isa; + hsa_profile_t profile; + uint16_t* mask; + } hsa_isa_get_exception_policies; + struct + { + hsa_isa_t isa; + hsa_fp_type_t fp_type; + hsa_flush_mode_t flush_mode; + hsa_round_method_t* round_method; + } hsa_isa_get_round_method; + struct + { + hsa_wavefront_t wavefront; + hsa_wavefront_info_t attribute; + void* value; + } hsa_wavefront_get_info; + struct + { + hsa_isa_t isa; + hsa_status_t (*callback)(hsa_wavefront_t wavefront, void* data); + void* data; + } hsa_isa_iterate_wavefronts; + struct + { + hsa_code_object_t code_object; + const char* module_name; + const char* symbol_name; + hsa_code_symbol_t* symbol; + } hsa_code_object_get_symbol_from_name; + struct + { + hsa_file_t file; + hsa_code_object_reader_t* code_object_reader; + } hsa_code_object_reader_create_from_file; + struct + { + const void* code_object; + size_t size; + hsa_code_object_reader_t* code_object_reader; + } hsa_code_object_reader_create_from_memory; + struct + { + hsa_code_object_reader_t code_object_reader; + } hsa_code_object_reader_destroy; + struct + { + hsa_profile_t profile; + hsa_default_float_rounding_mode_t default_float_rounding_mode; + const char* options; + hsa_executable_t* executable; + } hsa_executable_create_alt; + struct + { + hsa_executable_t executable; + hsa_code_object_reader_t code_object_reader; + const char* options; + hsa_loaded_code_object_t* loaded_code_object; + } hsa_executable_load_program_code_object; + struct + { + hsa_executable_t executable; + hsa_agent_t agent; + hsa_code_object_reader_t code_object_reader; + const char* options; + hsa_loaded_code_object_t* loaded_code_object; + } hsa_executable_load_agent_code_object; + struct + { + hsa_executable_t executable; + const char* options; + uint32_t* result; + } hsa_executable_validate_alt; + struct + { + hsa_executable_t executable; + const char* symbol_name; + const hsa_agent_t* agent; + hsa_executable_symbol_t* symbol; + } hsa_executable_get_symbol_by_name; + struct + { + hsa_executable_t executable; + hsa_agent_t agent; + hsa_status_t (*callback)(hsa_executable_t exec, + hsa_agent_t agent, + hsa_executable_symbol_t symbol, + void* data); + void* data; + } hsa_executable_iterate_agent_symbols; + struct + { + hsa_executable_t executable; + hsa_status_t (*callback)(hsa_executable_t exec, + hsa_executable_symbol_t symbol, + void* data); + void* data; + } hsa_executable_iterate_program_symbols; + + /* block: AmdExt API */ + struct + { + hsa_agent_t agent; + hsa_amd_coherency_type_t* type; + } hsa_amd_coherency_get_type; + struct + { + hsa_agent_t agent; + hsa_amd_coherency_type_t type; + } hsa_amd_coherency_set_type; + struct + { + hsa_queue_t* queue; + int enable; + } hsa_amd_profiling_set_profiler_enabled; + struct + { + bool enable; + } hsa_amd_profiling_async_copy_enable; + struct + { + hsa_agent_t agent; + hsa_signal_t signal; + hsa_amd_profiling_dispatch_time_t* time; + } hsa_amd_profiling_get_dispatch_time; + struct + { + hsa_signal_t signal; + hsa_amd_profiling_async_copy_time_t* time; + } hsa_amd_profiling_get_async_copy_time; + struct + { + hsa_agent_t agent; + uint64_t agent_tick; + uint64_t* system_tick; + } hsa_amd_profiling_convert_tick_to_system_domain; + struct + { + hsa_signal_t signal; + hsa_signal_condition_t cond; + hsa_signal_value_t value; + hsa_amd_signal_handler handler; + void* arg; + } hsa_amd_signal_async_handler; + struct + { + void (*callback)(void* arg); + void* arg; + } hsa_amd_async_function; + struct + { + uint32_t signal_count; + hsa_signal_t* signals; + hsa_signal_condition_t* conds; + hsa_signal_value_t* values; + uint64_t timeout_hint; + hsa_wait_state_t wait_hint; + hsa_signal_value_t* satisfying_value; + } hsa_amd_signal_wait_any; + struct + { + const hsa_queue_t* queue; + uint32_t num_cu_mask_count; + const uint32_t* cu_mask; + } hsa_amd_queue_cu_set_mask; + struct + { + hsa_amd_memory_pool_t memory_pool; + hsa_amd_memory_pool_info_t attribute; + void* value; + } hsa_amd_memory_pool_get_info; + struct + { + hsa_agent_t agent; + hsa_status_t (*callback)(hsa_amd_memory_pool_t memory_pool, void* data); + void* data; + } hsa_amd_agent_iterate_memory_pools; + struct + { + hsa_amd_memory_pool_t memory_pool; + size_t size; + uint32_t flags; + void** ptr; + } hsa_amd_memory_pool_allocate; + struct + { + void* ptr; + } hsa_amd_memory_pool_free; + struct + { + void* dst; + hsa_agent_t dst_agent; + const void* src; + hsa_agent_t src_agent; + size_t size; + uint32_t num_dep_signals; + const hsa_signal_t* dep_signals; + hsa_signal_t completion_signal; + } hsa_amd_memory_async_copy; + struct + { + void* dst; + hsa_agent_t dst_agent; + const void* src; + hsa_agent_t src_agent; + size_t size; + uint32_t num_dep_signals; + const hsa_signal_t* dep_signals; + hsa_signal_t completion_signal; + hsa_amd_sdma_engine_id_t engine_id; + bool force_copy_on_sdma; + } hsa_amd_memory_async_copy_on_engine; + struct + { + hsa_agent_t dst_agent; + hsa_agent_t src_agent; + uint32_t* engine_ids_mask; + } hsa_amd_memory_copy_engine_status; + struct + { + hsa_agent_t agent; + hsa_amd_memory_pool_t memory_pool; + hsa_amd_agent_memory_pool_info_t attribute; + void* value; + } hsa_amd_agent_memory_pool_get_info; + struct + { + uint32_t num_agents; + const hsa_agent_t* agents; + const uint32_t* flags; + const void* ptr; + } hsa_amd_agents_allow_access; + struct + { + hsa_amd_memory_pool_t src_memory_pool; + hsa_amd_memory_pool_t dst_memory_pool; + bool* result; + } hsa_amd_memory_pool_can_migrate; + struct + { + const void* ptr; + hsa_amd_memory_pool_t memory_pool; + uint32_t flags; + } hsa_amd_memory_migrate; + struct + { + void* host_ptr; + size_t size; + hsa_agent_t* agents; + int num_agent; + void** agent_ptr; + } hsa_amd_memory_lock; + struct + { + void* host_ptr; + } hsa_amd_memory_unlock; + struct + { + void* ptr; + uint32_t value; + size_t count; + } hsa_amd_memory_fill; + struct + { + uint32_t num_agents; + hsa_agent_t* agents; + int interop_handle; + uint32_t flags; + size_t* size; + void** ptr; + size_t* metadata_size; + const void** metadata; + } hsa_amd_interop_map_buffer; + struct + { + void* ptr; + } hsa_amd_interop_unmap_buffer; + struct + { + hsa_agent_t agent; + const hsa_ext_image_descriptor_t* image_descriptor; + const hsa_amd_image_descriptor_t* image_layout; + const void* image_data; + hsa_access_permission_t access_permission; + hsa_ext_image_t* image; + } hsa_amd_image_create; + struct + { + const void* ptr; + hsa_amd_pointer_info_t* info; + void* (*alloc)(size_t); + uint32_t* num_agents_accessible; + hsa_agent_t** accessible; + } hsa_amd_pointer_info; + struct + { + const void* ptr; + void* userdata; + } hsa_amd_pointer_info_set_userdata; + struct + { + void* ptr; + size_t len; + hsa_amd_ipc_memory_t* handle; + } hsa_amd_ipc_memory_create; + struct + { + const hsa_amd_ipc_memory_t* handle; + size_t len; + uint32_t num_agents; + const hsa_agent_t* mapping_agents; + void** mapped_ptr; + } hsa_amd_ipc_memory_attach; + struct + { + void* mapped_ptr; + } hsa_amd_ipc_memory_detach; + struct + { + hsa_signal_value_t initial_value; + uint32_t num_consumers; + const hsa_agent_t* consumers; + uint64_t attributes; + hsa_signal_t* signal; + } hsa_amd_signal_create; + struct + { + hsa_signal_t signal; + hsa_amd_ipc_signal_t* handle; + } hsa_amd_ipc_signal_create; + struct + { + const hsa_amd_ipc_signal_t* handle; + hsa_signal_t* signal; + } hsa_amd_ipc_signal_attach; + struct + { + hsa_amd_system_event_callback_t callback; + void* data; + } hsa_amd_register_system_event_handler; + struct + { + hsa_agent_t agent_handle; + uint32_t size; + hsa_queue_type32_t type; + void (*callback)(hsa_status_t status, hsa_queue_t* source, void* data); + void* data; + uint32_t private_segment_size; + uint32_t group_segment_size; + hsa_queue_t** queue; + } hsa_amd_queue_intercept_create; + struct + { + hsa_queue_t* queue; + hsa_amd_queue_intercept_handler callback; + void* user_data; + } hsa_amd_queue_intercept_register; + struct + { + hsa_queue_t* queue; + hsa_amd_queue_priority_t priority; + } hsa_amd_queue_set_priority; + struct + { + const hsa_pitched_ptr_t* dst; + const hsa_dim3_t* dst_offset; + const hsa_pitched_ptr_t* src; + const hsa_dim3_t* src_offset; + const hsa_dim3_t* range; + hsa_dim3_t range__val; + hsa_agent_t copy_agent; + hsa_amd_copy_direction_t dir; + uint32_t num_dep_signals; + const hsa_signal_t* dep_signals; + hsa_signal_t completion_signal; + } hsa_amd_memory_async_copy_rect; + struct + { + hsa_amd_runtime_queue_notifier callback; + void* user_data; + } hsa_amd_runtime_queue_create_register; + struct + { + void* host_ptr; + size_t size; + hsa_agent_t* agents; + int num_agent; + hsa_amd_memory_pool_t pool; + uint32_t flags; + void** agent_ptr; + } hsa_amd_memory_lock_to_pool; + struct + { + void* ptr; + hsa_amd_deallocation_callback_t callback; + void* user_data; + } hsa_amd_register_deallocation_callback; + struct + { + void* ptr; + hsa_amd_deallocation_callback_t callback; + } hsa_amd_deregister_deallocation_callback; + struct + { + hsa_signal_t signal; + volatile hsa_signal_value_t** value_ptr; + } hsa_amd_signal_value_pointer; + struct + { + void* ptr; + size_t size; + hsa_amd_svm_attribute_pair_t* attribute_list; + size_t attribute_count; + } hsa_amd_svm_attributes_set; + struct + { + void* ptr; + size_t size; + hsa_amd_svm_attribute_pair_t* attribute_list; + size_t attribute_count; + } hsa_amd_svm_attributes_get; + struct + { + void* ptr; + size_t size; + hsa_agent_t agent; + uint32_t num_dep_signals; + const hsa_signal_t* dep_signals; + hsa_signal_t completion_signal; + } hsa_amd_svm_prefetch_async; + struct + { + hsa_agent_t preferred_agent; + } hsa_amd_spm_acquire; + struct + { + hsa_agent_t preferred_agent; + } hsa_amd_spm_release; + struct + { + hsa_agent_t preferred_agent; + size_t size_in_bytes; + uint32_t* timeout; + uint32_t* size_copied; + void* dest; + bool* is_data_loss; + } hsa_amd_spm_set_dest_buffer; + struct + { + const hsa_queue_t* queue; + uint32_t num_cu_mask_count; + uint32_t* cu_mask; + } hsa_amd_queue_cu_get_mask; + struct + { + const void* ptr; + size_t size; + int* dmabuf; + uint64_t* offset; + } hsa_amd_portable_export_dmabuf; + struct + { + int dmabuf; + } hsa_amd_portable_close_dmabuf; + + /* block: ImageExt API */ + struct + { + hsa_agent_t agent; + hsa_ext_image_geometry_t geometry; + const hsa_ext_image_format_t* image_format; + uint32_t* capability_mask; + } hsa_ext_image_get_capability; + struct + { + hsa_agent_t agent; + const hsa_ext_image_descriptor_t* image_descriptor; + hsa_access_permission_t access_permission; + hsa_ext_image_data_info_t* image_data_info; + } hsa_ext_image_data_get_info; + struct + { + hsa_agent_t agent; + const hsa_ext_image_descriptor_t* image_descriptor; + const void* image_data; + hsa_access_permission_t access_permission; + hsa_ext_image_t* image; + } hsa_ext_image_create; + struct + { + hsa_agent_t agent; + const void* src_memory; + size_t src_row_pitch; + size_t src_slice_pitch; + hsa_ext_image_t dst_image; + const hsa_ext_image_region_t* image_region; + } hsa_ext_image_import; + struct + { + hsa_agent_t agent; + hsa_ext_image_t src_image; + void* dst_memory; + size_t dst_row_pitch; + size_t dst_slice_pitch; + const hsa_ext_image_region_t* image_region; + } hsa_ext_image_export; + struct + { + hsa_agent_t agent; + hsa_ext_image_t src_image; + const hsa_dim3_t* src_offset; + hsa_ext_image_t dst_image; + const hsa_dim3_t* dst_offset; + const hsa_dim3_t* range; + } hsa_ext_image_copy; + struct + { + hsa_agent_t agent; + hsa_ext_image_t image; + const void* data; + const hsa_ext_image_region_t* image_region; + } hsa_ext_image_clear; + struct + { + hsa_agent_t agent; + hsa_ext_image_t image; + } hsa_ext_image_destroy; + struct + { + hsa_agent_t agent; + const hsa_ext_sampler_descriptor_t* sampler_descriptor; + hsa_ext_sampler_t* sampler; + } hsa_ext_sampler_create; + struct + { + hsa_agent_t agent; + hsa_ext_sampler_t sampler; + } hsa_ext_sampler_destroy; + struct + { + hsa_agent_t agent; + hsa_ext_image_geometry_t geometry; + const hsa_ext_image_format_t* image_format; + hsa_ext_image_data_layout_t image_data_layout; + uint32_t* capability_mask; + } hsa_ext_image_get_capability_with_layout; + struct + { + hsa_agent_t agent; + const hsa_ext_image_descriptor_t* image_descriptor; + hsa_access_permission_t access_permission; + hsa_ext_image_data_layout_t image_data_layout; + size_t image_data_row_pitch; + size_t image_data_slice_pitch; + hsa_ext_image_data_info_t* image_data_info; + } hsa_ext_image_data_get_info_with_layout; + struct + { + hsa_agent_t agent; + const hsa_ext_image_descriptor_t* image_descriptor; + const void* image_data; + hsa_access_permission_t access_permission; + hsa_ext_image_data_layout_t image_data_layout; + size_t image_data_row_pitch; + size_t image_data_slice_pitch; + hsa_ext_image_t* image; + } hsa_ext_image_create_with_layout; + } args; + uint64_t* phase_data; +} hsa_api_data_t; + +// HIP API callbacks data structures +typedef struct hip_api_data_s +{ + uint64_t correlation_id; + uint32_t phase; + union + { + struct + { + dim3* gridDim; + dim3 gridDim__val; + dim3* blockDim; + dim3 blockDim__val; + size_t* sharedMem; + size_t sharedMem__val; + hipStream_t* stream; + hipStream_t stream__val; + } __hipPopCallConfiguration; + struct + { + dim3 gridDim; + dim3 blockDim; + size_t sharedMem; + hipStream_t stream; + } __hipPushCallConfiguration; + struct + { + hipArray** array; + hipArray* array__val; + const HIP_ARRAY3D_DESCRIPTOR* pAllocateArray; + HIP_ARRAY3D_DESCRIPTOR pAllocateArray__val; + } hipArray3DCreate; + struct + { + HIP_ARRAY3D_DESCRIPTOR* pArrayDescriptor; + HIP_ARRAY3D_DESCRIPTOR pArrayDescriptor__val; + hipArray* array; + hipArray array__val; + } hipArray3DGetDescriptor; + struct + { + hipArray** pHandle; + hipArray* pHandle__val; + const HIP_ARRAY_DESCRIPTOR* pAllocateArray; + HIP_ARRAY_DESCRIPTOR pAllocateArray__val; + } hipArrayCreate; + struct + { + hipArray* array; + hipArray array__val; + } hipArrayDestroy; + struct + { + HIP_ARRAY_DESCRIPTOR* pArrayDescriptor; + HIP_ARRAY_DESCRIPTOR pArrayDescriptor__val; + hipArray* array; + hipArray array__val; + } hipArrayGetDescriptor; + struct + { + hipChannelFormatDesc* desc; + hipChannelFormatDesc desc__val; + hipExtent* extent; + hipExtent extent__val; + unsigned int* flags; + unsigned int flags__val; + hipArray* array; + hipArray array__val; + } hipArrayGetInfo; + struct + { + int* device; + int device__val; + const hipDeviceProp_t* prop; + hipDeviceProp_t prop__val; + } hipChooseDevice; + struct + { + dim3 gridDim; + dim3 blockDim; + size_t sharedMem; + hipStream_t stream; + } hipConfigureCall; + struct + { + hipSurfaceObject_t* pSurfObject; + hipSurfaceObject_t pSurfObject__val; + const hipResourceDesc* pResDesc; + hipResourceDesc pResDesc__val; + } hipCreateSurfaceObject; + struct + { + hipCtx_t* ctx; + hipCtx_t ctx__val; + unsigned int flags; + hipDevice_t device; + } hipCtxCreate; + struct + { + hipCtx_t ctx; + } hipCtxDestroy; + struct + { + hipCtx_t peerCtx; + } hipCtxDisablePeerAccess; + struct + { + hipCtx_t peerCtx; + unsigned int flags; + } hipCtxEnablePeerAccess; + struct + { + hipCtx_t ctx; + int* apiVersion; + int apiVersion__val; + } hipCtxGetApiVersion; + struct + { + hipFuncCache_t* cacheConfig; + hipFuncCache_t cacheConfig__val; + } hipCtxGetCacheConfig; + struct + { + hipCtx_t* ctx; + hipCtx_t ctx__val; + } hipCtxGetCurrent; + struct + { + hipDevice_t* device; + hipDevice_t device__val; + } hipCtxGetDevice; + struct + { + unsigned int* flags; + unsigned int flags__val; + } hipCtxGetFlags; + struct + { + hipSharedMemConfig* pConfig; + hipSharedMemConfig pConfig__val; + } hipCtxGetSharedMemConfig; + struct + { + hipCtx_t* ctx; + hipCtx_t ctx__val; + } hipCtxPopCurrent; + struct + { + hipCtx_t ctx; + } hipCtxPushCurrent; + struct + { + hipFuncCache_t cacheConfig; + } hipCtxSetCacheConfig; + struct + { + hipCtx_t ctx; + } hipCtxSetCurrent; + struct + { + hipSharedMemConfig config; + } hipCtxSetSharedMemConfig; + struct + { + hipExternalMemory_t extMem; + } hipDestroyExternalMemory; + struct + { + hipExternalSemaphore_t extSem; + } hipDestroyExternalSemaphore; + struct + { + hipSurfaceObject_t surfaceObject; + } hipDestroySurfaceObject; + struct + { + int* canAccessPeer; + int canAccessPeer__val; + int deviceId; + int peerDeviceId; + } hipDeviceCanAccessPeer; + struct + { + int* major; + int major__val; + int* minor; + int minor__val; + hipDevice_t device; + } hipDeviceComputeCapability; + struct + { + int peerDeviceId; + } hipDeviceDisablePeerAccess; + struct + { + int peerDeviceId; + unsigned int flags; + } hipDeviceEnablePeerAccess; + struct + { + hipDevice_t* device; + hipDevice_t device__val; + int ordinal; + } hipDeviceGet; + struct + { + int* pi; + int pi__val; + hipDeviceAttribute_t attr; + int deviceId; + } hipDeviceGetAttribute; + struct + { + int* device; + int device__val; + const char* pciBusId; + char pciBusId__val; + } hipDeviceGetByPCIBusId; + struct + { + hipFuncCache_t* cacheConfig; + hipFuncCache_t cacheConfig__val; + } hipDeviceGetCacheConfig; + struct + { + hipMemPool_t* mem_pool; + hipMemPool_t mem_pool__val; + int device; + } hipDeviceGetDefaultMemPool; + struct + { + int device; + hipGraphMemAttributeType attr; + void* value; + } hipDeviceGetGraphMemAttribute; + struct + { + size_t* pValue; + size_t pValue__val; + enum hipLimit_t limit; + } hipDeviceGetLimit; + struct + { + hipMemPool_t* mem_pool; + hipMemPool_t mem_pool__val; + int device; + } hipDeviceGetMemPool; + struct + { + char* name; + char name__val; + int len; + hipDevice_t device; + } hipDeviceGetName; + struct + { + int* value; + int value__val; + hipDeviceP2PAttr attr; + int srcDevice; + int dstDevice; + } hipDeviceGetP2PAttribute; + struct + { + char* pciBusId; + char pciBusId__val; + int len; + int device; + } hipDeviceGetPCIBusId; + struct + { + hipSharedMemConfig* pConfig; + hipSharedMemConfig pConfig__val; + } hipDeviceGetSharedMemConfig; + struct + { + int* leastPriority; + int leastPriority__val; + int* greatestPriority; + int greatestPriority__val; + } hipDeviceGetStreamPriorityRange; + struct + { + hipUUID* uuid; + hipUUID uuid__val; + hipDevice_t device; + } hipDeviceGetUuid; + struct + { + int device; + } hipDeviceGraphMemTrim; + struct + { + hipDevice_t dev; + unsigned int* flags; + unsigned int flags__val; + int* active; + int active__val; + } hipDevicePrimaryCtxGetState; + struct + { + hipDevice_t dev; + } hipDevicePrimaryCtxRelease; + struct + { + hipDevice_t dev; + } hipDevicePrimaryCtxReset; + struct + { + hipCtx_t* pctx; + hipCtx_t pctx__val; + hipDevice_t dev; + } hipDevicePrimaryCtxRetain; + struct + { + hipDevice_t dev; + unsigned int flags; + } hipDevicePrimaryCtxSetFlags; + struct + { + hipFuncCache_t cacheConfig; + } hipDeviceSetCacheConfig; + struct + { + int device; + hipGraphMemAttributeType attr; + void* value; + } hipDeviceSetGraphMemAttribute; + struct + { + enum hipLimit_t limit; + size_t value; + } hipDeviceSetLimit; + struct + { + int device; + hipMemPool_t mem_pool; + } hipDeviceSetMemPool; + struct + { + hipSharedMemConfig config; + } hipDeviceSetSharedMemConfig; + struct + { + size_t* bytes; + size_t bytes__val; + hipDevice_t device; + } hipDeviceTotalMem; + struct + { + int* driverVersion; + int driverVersion__val; + } hipDriverGetVersion; + struct + { + const hip_Memcpy2D* pCopy; + hip_Memcpy2D pCopy__val; + } hipDrvMemcpy2DUnaligned; + struct + { + const HIP_MEMCPY3D* pCopy; + HIP_MEMCPY3D pCopy__val; + } hipDrvMemcpy3D; + struct + { + const HIP_MEMCPY3D* pCopy; + HIP_MEMCPY3D pCopy__val; + hipStream_t stream; + } hipDrvMemcpy3DAsync; + struct + { + unsigned int numAttributes; + hipPointer_attribute* attributes; + hipPointer_attribute attributes__val; + void** data; + void* data__val; + hipDeviceptr_t ptr; + } hipDrvPointerGetAttributes; + struct + { + hipEvent_t* event; + hipEvent_t event__val; + } hipEventCreate; + struct + { + hipEvent_t* event; + hipEvent_t event__val; + unsigned int flags; + } hipEventCreateWithFlags; + struct + { + hipEvent_t event; + } hipEventDestroy; + struct + { + float* ms; + float ms__val; + hipEvent_t start; + hipEvent_t stop; + } hipEventElapsedTime; + struct + { + hipEvent_t event; + } hipEventQuery; + struct + { + hipEvent_t event; + hipStream_t stream; + } hipEventRecord; + struct + { + hipEvent_t event; + } hipEventSynchronize; + struct + { + int device1; + int device2; + unsigned int* linktype; + unsigned int linktype__val; + unsigned int* hopcount; + unsigned int hopcount__val; + } hipExtGetLinkTypeAndHopCount; + struct + { + const void* function_address; + dim3 numBlocks; + dim3 dimBlocks; + void** args; + void* args__val; + size_t sharedMemBytes; + hipStream_t stream; + hipEvent_t startEvent; + hipEvent_t stopEvent; + int flags; + } hipExtLaunchKernel; + struct + { + hipLaunchParams* launchParamsList; + hipLaunchParams launchParamsList__val; + int numDevices; + unsigned int flags; + } hipExtLaunchMultiKernelMultiDevice; + struct + { + void** ptr; + void* ptr__val; + size_t sizeBytes; + unsigned int flags; + } hipExtMallocWithFlags; + struct + { + hipFunction_t f; + unsigned int globalWorkSizeX; + unsigned int globalWorkSizeY; + unsigned int globalWorkSizeZ; + unsigned int localWorkSizeX; + unsigned int localWorkSizeY; + unsigned int localWorkSizeZ; + size_t sharedMemBytes; + hipStream_t hStream; + void** kernelParams; + void* kernelParams__val; + void** extra; + void* extra__val; + hipEvent_t startEvent; + hipEvent_t stopEvent; + unsigned int flags; + } hipExtModuleLaunchKernel; + struct + { + hipStream_t* stream; + hipStream_t stream__val; + unsigned int cuMaskSize; + const unsigned int* cuMask; + unsigned int cuMask__val; + } hipExtStreamCreateWithCUMask; + struct + { + hipStream_t stream; + unsigned int cuMaskSize; + unsigned int* cuMask; + unsigned int cuMask__val; + } hipExtStreamGetCUMask; + struct + { + void** devPtr; + void* devPtr__val; + hipExternalMemory_t extMem; + const hipExternalMemoryBufferDesc* bufferDesc; + hipExternalMemoryBufferDesc bufferDesc__val; + } hipExternalMemoryGetMappedBuffer; + struct + { + void* ptr; + } hipFree; + struct + { + hipArray* array; + hipArray array__val; + } hipFreeArray; + struct + { + void* dev_ptr; + hipStream_t stream; + } hipFreeAsync; + struct + { + void* ptr; + } hipFreeHost; + struct + { + hipMipmappedArray_t mipmappedArray; + } hipFreeMipmappedArray; + struct + { + int* value; + int value__val; + hipFunction_attribute attrib; + hipFunction_t hfunc; + } hipFuncGetAttribute; + struct + { + hipFuncAttributes* attr; + hipFuncAttributes attr__val; + const void* func; + } hipFuncGetAttributes; + struct + { + const void* func; + hipFuncAttribute attr; + int value; + } hipFuncSetAttribute; + struct + { + const void* func; + hipFuncCache_t config; + } hipFuncSetCacheConfig; + struct + { + const void* func; + hipSharedMemConfig config; + } hipFuncSetSharedMemConfig; + struct + { + unsigned int* pHipDeviceCount; + unsigned int pHipDeviceCount__val; + int* pHipDevices; + int pHipDevices__val; + unsigned int hipDeviceCount; + hipGLDeviceList deviceList; + } hipGLGetDevices; + struct + { + hipChannelFormatDesc* desc; + hipChannelFormatDesc desc__val; + hipArray_const_t array; + } hipGetChannelDesc; + struct + { + int* deviceId; + int deviceId__val; + } hipGetDevice; + struct + { + int* count; + int count__val; + } hipGetDeviceCount; + struct + { + unsigned int* flags; + unsigned int flags__val; + } hipGetDeviceFlags; + struct + { + hipDeviceProp_t* props; + hipDeviceProp_t props__val; + hipDevice_t device; + } hipGetDeviceProperties; + struct + { + hipArray_t* levelArray; + hipArray_t levelArray__val; + hipMipmappedArray_const_t mipmappedArray; + unsigned int level; + } hipGetMipmappedArrayLevel; + struct + { + void** devPtr; + void* devPtr__val; + const void* symbol; + } hipGetSymbolAddress; + struct + { + size_t* size; + size_t size__val; + const void* symbol; + } hipGetSymbolSize; + struct + { + hipGraphNode_t* pGraphNode; + hipGraphNode_t pGraphNode__val; + hipGraph_t graph; + const hipGraphNode_t* pDependencies; + hipGraphNode_t pDependencies__val; + size_t numDependencies; + hipGraph_t childGraph; + } hipGraphAddChildGraphNode; + struct + { + hipGraph_t graph; + const hipGraphNode_t* from; + hipGraphNode_t from__val; + const hipGraphNode_t* to; + hipGraphNode_t to__val; + size_t numDependencies; + } hipGraphAddDependencies; + struct + { + hipGraphNode_t* pGraphNode; + hipGraphNode_t pGraphNode__val; + hipGraph_t graph; + const hipGraphNode_t* pDependencies; + hipGraphNode_t pDependencies__val; + size_t numDependencies; + } hipGraphAddEmptyNode; + struct + { + hipGraphNode_t* pGraphNode; + hipGraphNode_t pGraphNode__val; + hipGraph_t graph; + const hipGraphNode_t* pDependencies; + hipGraphNode_t pDependencies__val; + size_t numDependencies; + hipEvent_t event; + } hipGraphAddEventRecordNode; + struct + { + hipGraphNode_t* pGraphNode; + hipGraphNode_t pGraphNode__val; + hipGraph_t graph; + const hipGraphNode_t* pDependencies; + hipGraphNode_t pDependencies__val; + size_t numDependencies; + hipEvent_t event; + } hipGraphAddEventWaitNode; + struct + { + hipGraphNode_t* pGraphNode; + hipGraphNode_t pGraphNode__val; + hipGraph_t graph; + const hipGraphNode_t* pDependencies; + hipGraphNode_t pDependencies__val; + size_t numDependencies; + const hipHostNodeParams* pNodeParams; + hipHostNodeParams pNodeParams__val; + } hipGraphAddHostNode; + struct + { + hipGraphNode_t* pGraphNode; + hipGraphNode_t pGraphNode__val; + hipGraph_t graph; + const hipGraphNode_t* pDependencies; + hipGraphNode_t pDependencies__val; + size_t numDependencies; + const hipKernelNodeParams* pNodeParams; + hipKernelNodeParams pNodeParams__val; + } hipGraphAddKernelNode; + struct + { + hipGraphNode_t* pGraphNode; + hipGraphNode_t pGraphNode__val; + hipGraph_t graph; + const hipGraphNode_t* pDependencies; + hipGraphNode_t pDependencies__val; + size_t numDependencies; + hipMemAllocNodeParams* pNodeParams; + hipMemAllocNodeParams pNodeParams__val; + } hipGraphAddMemAllocNode; + struct + { + hipGraphNode_t* pGraphNode; + hipGraphNode_t pGraphNode__val; + hipGraph_t graph; + const hipGraphNode_t* pDependencies; + hipGraphNode_t pDependencies__val; + size_t numDependencies; + void* dev_ptr; + } hipGraphAddMemFreeNode; + struct + { + hipGraphNode_t* pGraphNode; + hipGraphNode_t pGraphNode__val; + hipGraph_t graph; + const hipGraphNode_t* pDependencies; + hipGraphNode_t pDependencies__val; + size_t numDependencies; + const hipMemcpy3DParms* pCopyParams; + hipMemcpy3DParms pCopyParams__val; + } hipGraphAddMemcpyNode; + struct + { + hipGraphNode_t* pGraphNode; + hipGraphNode_t pGraphNode__val; + hipGraph_t graph; + const hipGraphNode_t* pDependencies; + hipGraphNode_t pDependencies__val; + size_t numDependencies; + void* dst; + const void* src; + size_t count; + hipMemcpyKind kind; + } hipGraphAddMemcpyNode1D; + struct + { + hipGraphNode_t* pGraphNode; + hipGraphNode_t pGraphNode__val; + hipGraph_t graph; + const hipGraphNode_t* pDependencies; + hipGraphNode_t pDependencies__val; + size_t numDependencies; + void* dst; + const void* symbol; + size_t count; + size_t offset; + hipMemcpyKind kind; + } hipGraphAddMemcpyNodeFromSymbol; + struct + { + hipGraphNode_t* pGraphNode; + hipGraphNode_t pGraphNode__val; + hipGraph_t graph; + const hipGraphNode_t* pDependencies; + hipGraphNode_t pDependencies__val; + size_t numDependencies; + const void* symbol; + const void* src; + size_t count; + size_t offset; + hipMemcpyKind kind; + } hipGraphAddMemcpyNodeToSymbol; + struct + { + hipGraphNode_t* pGraphNode; + hipGraphNode_t pGraphNode__val; + hipGraph_t graph; + const hipGraphNode_t* pDependencies; + hipGraphNode_t pDependencies__val; + size_t numDependencies; + const hipMemsetParams* pMemsetParams; + hipMemsetParams pMemsetParams__val; + } hipGraphAddMemsetNode; + struct + { + hipGraphNode_t node; + hipGraph_t* pGraph; + hipGraph_t pGraph__val; + } hipGraphChildGraphNodeGetGraph; + struct + { + hipGraph_t* pGraphClone; + hipGraph_t pGraphClone__val; + hipGraph_t originalGraph; + } hipGraphClone; + struct + { + hipGraph_t* pGraph; + hipGraph_t pGraph__val; + unsigned int flags; + } hipGraphCreate; + struct + { + hipGraph_t graph; + const char* path; + char path__val; + unsigned int flags; + } hipGraphDebugDotPrint; + struct + { + hipGraph_t graph; + } hipGraphDestroy; + struct + { + hipGraphNode_t node; + } hipGraphDestroyNode; + struct + { + hipGraphNode_t node; + hipEvent_t* event_out; + hipEvent_t event_out__val; + } hipGraphEventRecordNodeGetEvent; + struct + { + hipGraphNode_t node; + hipEvent_t event; + } hipGraphEventRecordNodeSetEvent; + struct + { + hipGraphNode_t node; + hipEvent_t* event_out; + hipEvent_t event_out__val; + } hipGraphEventWaitNodeGetEvent; + struct + { + hipGraphNode_t node; + hipEvent_t event; + } hipGraphEventWaitNodeSetEvent; + struct + { + hipGraphExec_t hGraphExec; + hipGraphNode_t node; + hipGraph_t childGraph; + } hipGraphExecChildGraphNodeSetParams; + struct + { + hipGraphExec_t graphExec; + } hipGraphExecDestroy; + struct + { + hipGraphExec_t hGraphExec; + hipGraphNode_t hNode; + hipEvent_t event; + } hipGraphExecEventRecordNodeSetEvent; + struct + { + hipGraphExec_t hGraphExec; + hipGraphNode_t hNode; + hipEvent_t event; + } hipGraphExecEventWaitNodeSetEvent; + struct + { + hipGraphExec_t hGraphExec; + hipGraphNode_t node; + const hipHostNodeParams* pNodeParams; + hipHostNodeParams pNodeParams__val; + } hipGraphExecHostNodeSetParams; + struct + { + hipGraphExec_t hGraphExec; + hipGraphNode_t node; + const hipKernelNodeParams* pNodeParams; + hipKernelNodeParams pNodeParams__val; + } hipGraphExecKernelNodeSetParams; + struct + { + hipGraphExec_t hGraphExec; + hipGraphNode_t node; + hipMemcpy3DParms* pNodeParams; + hipMemcpy3DParms pNodeParams__val; + } hipGraphExecMemcpyNodeSetParams; + struct + { + hipGraphExec_t hGraphExec; + hipGraphNode_t node; + void* dst; + const void* src; + size_t count; + hipMemcpyKind kind; + } hipGraphExecMemcpyNodeSetParams1D; + struct + { + hipGraphExec_t hGraphExec; + hipGraphNode_t node; + void* dst; + const void* symbol; + size_t count; + size_t offset; + hipMemcpyKind kind; + } hipGraphExecMemcpyNodeSetParamsFromSymbol; + struct + { + hipGraphExec_t hGraphExec; + hipGraphNode_t node; + const void* symbol; + const void* src; + size_t count; + size_t offset; + hipMemcpyKind kind; + } hipGraphExecMemcpyNodeSetParamsToSymbol; + struct + { + hipGraphExec_t hGraphExec; + hipGraphNode_t node; + const hipMemsetParams* pNodeParams; + hipMemsetParams pNodeParams__val; + } hipGraphExecMemsetNodeSetParams; + struct + { + hipGraphExec_t hGraphExec; + hipGraph_t hGraph; + hipGraphNode_t* hErrorNode_out; + hipGraphNode_t hErrorNode_out__val; + hipGraphExecUpdateResult* updateResult_out; + hipGraphExecUpdateResult updateResult_out__val; + } hipGraphExecUpdate; + struct + { + hipGraph_t graph; + hipGraphNode_t* from; + hipGraphNode_t from__val; + hipGraphNode_t* to; + hipGraphNode_t to__val; + size_t* numEdges; + size_t numEdges__val; + } hipGraphGetEdges; + struct + { + hipGraph_t graph; + hipGraphNode_t* nodes; + hipGraphNode_t nodes__val; + size_t* numNodes; + size_t numNodes__val; + } hipGraphGetNodes; + struct + { + hipGraph_t graph; + hipGraphNode_t* pRootNodes; + hipGraphNode_t pRootNodes__val; + size_t* pNumRootNodes; + size_t pNumRootNodes__val; + } hipGraphGetRootNodes; + struct + { + hipGraphNode_t node; + hipHostNodeParams* pNodeParams; + hipHostNodeParams pNodeParams__val; + } hipGraphHostNodeGetParams; + struct + { + hipGraphNode_t node; + const hipHostNodeParams* pNodeParams; + hipHostNodeParams pNodeParams__val; + } hipGraphHostNodeSetParams; + struct + { + hipGraphExec_t* pGraphExec; + hipGraphExec_t pGraphExec__val; + hipGraph_t graph; + hipGraphNode_t* pErrorNode; + hipGraphNode_t pErrorNode__val; + char* pLogBuffer; + char pLogBuffer__val; + size_t bufferSize; + } hipGraphInstantiate; + struct + { + hipGraphExec_t* pGraphExec; + hipGraphExec_t pGraphExec__val; + hipGraph_t graph; + unsigned long long flags; + } hipGraphInstantiateWithFlags; + struct + { + hipGraphNode_t hSrc; + hipGraphNode_t hDst; + } hipGraphKernelNodeCopyAttributes; + struct + { + hipGraphNode_t hNode; + hipKernelNodeAttrID attr; + hipKernelNodeAttrValue* value; + hipKernelNodeAttrValue value__val; + } hipGraphKernelNodeGetAttribute; + struct + { + hipGraphNode_t node; + hipKernelNodeParams* pNodeParams; + hipKernelNodeParams pNodeParams__val; + } hipGraphKernelNodeGetParams; + struct + { + hipGraphNode_t hNode; + hipKernelNodeAttrID attr; + const hipKernelNodeAttrValue* value; + hipKernelNodeAttrValue value__val; + } hipGraphKernelNodeSetAttribute; + struct + { + hipGraphNode_t node; + const hipKernelNodeParams* pNodeParams; + hipKernelNodeParams pNodeParams__val; + } hipGraphKernelNodeSetParams; + struct + { + hipGraphExec_t graphExec; + hipStream_t stream; + } hipGraphLaunch; + struct + { + hipGraphNode_t node; + hipMemAllocNodeParams* pNodeParams; + hipMemAllocNodeParams pNodeParams__val; + } hipGraphMemAllocNodeGetParams; + struct + { + hipGraphNode_t node; + void* dev_ptr; + } hipGraphMemFreeNodeGetParams; + struct + { + hipGraphNode_t node; + hipMemcpy3DParms* pNodeParams; + hipMemcpy3DParms pNodeParams__val; + } hipGraphMemcpyNodeGetParams; + struct + { + hipGraphNode_t node; + const hipMemcpy3DParms* pNodeParams; + hipMemcpy3DParms pNodeParams__val; + } hipGraphMemcpyNodeSetParams; + struct + { + hipGraphNode_t node; + void* dst; + const void* src; + size_t count; + hipMemcpyKind kind; + } hipGraphMemcpyNodeSetParams1D; + struct + { + hipGraphNode_t node; + void* dst; + const void* symbol; + size_t count; + size_t offset; + hipMemcpyKind kind; + } hipGraphMemcpyNodeSetParamsFromSymbol; + struct + { + hipGraphNode_t node; + const void* symbol; + const void* src; + size_t count; + size_t offset; + hipMemcpyKind kind; + } hipGraphMemcpyNodeSetParamsToSymbol; + struct + { + hipGraphNode_t node; + hipMemsetParams* pNodeParams; + hipMemsetParams pNodeParams__val; + } hipGraphMemsetNodeGetParams; + struct + { + hipGraphNode_t node; + const hipMemsetParams* pNodeParams; + hipMemsetParams pNodeParams__val; + } hipGraphMemsetNodeSetParams; + struct + { + hipGraphNode_t* pNode; + hipGraphNode_t pNode__val; + hipGraphNode_t originalNode; + hipGraph_t clonedGraph; + } hipGraphNodeFindInClone; + struct + { + hipGraphNode_t node; + hipGraphNode_t* pDependencies; + hipGraphNode_t pDependencies__val; + size_t* pNumDependencies; + size_t pNumDependencies__val; + } hipGraphNodeGetDependencies; + struct + { + hipGraphNode_t node; + hipGraphNode_t* pDependentNodes; + hipGraphNode_t pDependentNodes__val; + size_t* pNumDependentNodes; + size_t pNumDependentNodes__val; + } hipGraphNodeGetDependentNodes; + struct + { + hipGraphExec_t hGraphExec; + hipGraphNode_t hNode; + unsigned int* isEnabled; + unsigned int isEnabled__val; + } hipGraphNodeGetEnabled; + struct + { + hipGraphNode_t node; + hipGraphNodeType* pType; + hipGraphNodeType pType__val; + } hipGraphNodeGetType; + struct + { + hipGraphExec_t hGraphExec; + hipGraphNode_t hNode; + unsigned int isEnabled; + } hipGraphNodeSetEnabled; + struct + { + hipGraph_t graph; + hipUserObject_t object; + unsigned int count; + } hipGraphReleaseUserObject; + struct + { + hipGraph_t graph; + const hipGraphNode_t* from; + hipGraphNode_t from__val; + const hipGraphNode_t* to; + hipGraphNode_t to__val; + size_t numDependencies; + } hipGraphRemoveDependencies; + struct + { + hipGraph_t graph; + hipUserObject_t object; + unsigned int count; + unsigned int flags; + } hipGraphRetainUserObject; + struct + { + hipGraphExec_t graphExec; + hipStream_t stream; + } hipGraphUpload; + struct + { + hipGraphicsResource** resource; + hipGraphicsResource* resource__val; + GLuint buffer; + unsigned int flags; + } hipGraphicsGLRegisterBuffer; + struct + { + hipGraphicsResource** resource; + hipGraphicsResource* resource__val; + GLuint image; + GLenum target; + unsigned int flags; + } hipGraphicsGLRegisterImage; + struct + { + int count; + hipGraphicsResource_t* resources; + hipGraphicsResource_t resources__val; + hipStream_t stream; + } hipGraphicsMapResources; + struct + { + void** devPtr; + void* devPtr__val; + size_t* size; + size_t size__val; + hipGraphicsResource_t resource; + } hipGraphicsResourceGetMappedPointer; + struct + { + hipArray_t* array; + hipArray_t array__val; + hipGraphicsResource_t resource; + unsigned int arrayIndex; + unsigned int mipLevel; + } hipGraphicsSubResourceGetMappedArray; + struct + { + int count; + hipGraphicsResource_t* resources; + hipGraphicsResource_t resources__val; + hipStream_t stream; + } hipGraphicsUnmapResources; + struct + { + hipGraphicsResource_t resource; + } hipGraphicsUnregisterResource; + struct + { + hipFunction_t f; + unsigned int globalWorkSizeX; + unsigned int globalWorkSizeY; + unsigned int globalWorkSizeZ; + unsigned int blockDimX; + unsigned int blockDimY; + unsigned int blockDimZ; + size_t sharedMemBytes; + hipStream_t hStream; + void** kernelParams; + void* kernelParams__val; + void** extra; + void* extra__val; + hipEvent_t startEvent; + hipEvent_t stopEvent; + } hipHccModuleLaunchKernel; + struct + { + void** ptr; + void* ptr__val; + size_t size; + unsigned int flags; + } hipHostAlloc; + struct + { + void* ptr; + } hipHostFree; + struct + { + void** devPtr; + void* devPtr__val; + void* hstPtr; + unsigned int flags; + } hipHostGetDevicePointer; + struct + { + unsigned int* flagsPtr; + unsigned int flagsPtr__val; + void* hostPtr; + } hipHostGetFlags; + struct + { + void** ptr; + void* ptr__val; + size_t size; + unsigned int flags; + } hipHostMalloc; + struct + { + void* hostPtr; + size_t sizeBytes; + unsigned int flags; + } hipHostRegister; + struct + { + void* hostPtr; + } hipHostUnregister; + struct + { + hipExternalMemory_t* extMem_out; + hipExternalMemory_t extMem_out__val; + const hipExternalMemoryHandleDesc* memHandleDesc; + hipExternalMemoryHandleDesc memHandleDesc__val; + } hipImportExternalMemory; + struct + { + hipExternalSemaphore_t* extSem_out; + hipExternalSemaphore_t extSem_out__val; + const hipExternalSemaphoreHandleDesc* semHandleDesc; + hipExternalSemaphoreHandleDesc semHandleDesc__val; + } hipImportExternalSemaphore; + struct + { + unsigned int flags; + } hipInit; + struct + { + void* devPtr; + } hipIpcCloseMemHandle; + struct + { + hipIpcEventHandle_t* handle; + hipIpcEventHandle_t handle__val; + hipEvent_t event; + } hipIpcGetEventHandle; + struct + { + hipIpcMemHandle_t* handle; + hipIpcMemHandle_t handle__val; + void* devPtr; + } hipIpcGetMemHandle; + struct + { + hipEvent_t* event; + hipEvent_t event__val; + hipIpcEventHandle_t handle; + } hipIpcOpenEventHandle; + struct + { + void** devPtr; + void* devPtr__val; + hipIpcMemHandle_t handle; + unsigned int flags; + } hipIpcOpenMemHandle; + struct + { + const void* hostFunction; + } hipLaunchByPtr; + struct + { + const void* f; + dim3 gridDim; + dim3 blockDimX; + void** kernelParams; + void* kernelParams__val; + unsigned int sharedMemBytes; + hipStream_t stream; + } hipLaunchCooperativeKernel; + struct + { + hipLaunchParams* launchParamsList; + hipLaunchParams launchParamsList__val; + int numDevices; + unsigned int flags; + } hipLaunchCooperativeKernelMultiDevice; + struct + { + hipStream_t stream; + hipHostFn_t fn; + void* userData; + } hipLaunchHostFunc; + struct + { + const void* function_address; + dim3 numBlocks; + dim3 dimBlocks; + void** args; + void* args__val; + size_t sharedMemBytes; + hipStream_t stream; + } hipLaunchKernel; + struct + { + void** ptr; + void* ptr__val; + size_t size; + } hipMalloc; + struct + { + hipPitchedPtr* pitchedDevPtr; + hipPitchedPtr pitchedDevPtr__val; + hipExtent extent; + } hipMalloc3D; + struct + { + hipArray_t* array; + hipArray_t array__val; + const hipChannelFormatDesc* desc; + hipChannelFormatDesc desc__val; + hipExtent extent; + unsigned int flags; + } hipMalloc3DArray; + struct + { + hipArray** array; + hipArray* array__val; + const hipChannelFormatDesc* desc; + hipChannelFormatDesc desc__val; + size_t width; + size_t height; + unsigned int flags; + } hipMallocArray; + struct + { + void** dev_ptr; + void* dev_ptr__val; + size_t size; + hipStream_t stream; + } hipMallocAsync; + struct + { + void** dev_ptr; + void* dev_ptr__val; + size_t size; + hipMemPool_t mem_pool; + hipStream_t stream; + } hipMallocFromPoolAsync; + struct + { + void** ptr; + void* ptr__val; + size_t size; + } hipMallocHost; + struct + { + void** dev_ptr; + void* dev_ptr__val; + size_t size; + unsigned int flags; + } hipMallocManaged; + struct + { + hipMipmappedArray_t* mipmappedArray; + hipMipmappedArray_t mipmappedArray__val; + const hipChannelFormatDesc* desc; + hipChannelFormatDesc desc__val; + hipExtent extent; + unsigned int numLevels; + unsigned int flags; + } hipMallocMipmappedArray; + struct + { + void** ptr; + void* ptr__val; + size_t* pitch; + size_t pitch__val; + size_t width; + size_t height; + } hipMallocPitch; + struct + { + void* devPtr; + size_t size; + } hipMemAddressFree; + struct + { + void** ptr; + void* ptr__val; + size_t size; + size_t alignment; + void* addr; + unsigned long long flags; + } hipMemAddressReserve; + struct + { + const void* dev_ptr; + size_t count; + hipMemoryAdvise advice; + int device; + } hipMemAdvise; + struct + { + void** ptr; + void* ptr__val; + size_t size; + } hipMemAllocHost; + struct + { + hipDeviceptr_t* dptr; + hipDeviceptr_t dptr__val; + size_t* pitch; + size_t pitch__val; + size_t widthInBytes; + size_t height; + unsigned int elementSizeBytes; + } hipMemAllocPitch; + struct + { + hipMemGenericAllocationHandle_t* handle; + hipMemGenericAllocationHandle_t handle__val; + size_t size; + const hipMemAllocationProp* prop; + hipMemAllocationProp prop__val; + unsigned long long flags; + } hipMemCreate; + struct + { + void* shareableHandle; + hipMemGenericAllocationHandle_t handle; + hipMemAllocationHandleType handleType; + unsigned long long flags; + } hipMemExportToShareableHandle; + struct + { + unsigned long long* flags; + unsigned long long flags__val; + const hipMemLocation* location; + hipMemLocation location__val; + void* ptr; + } hipMemGetAccess; + struct + { + hipDeviceptr_t* pbase; + hipDeviceptr_t pbase__val; + size_t* psize; + size_t psize__val; + hipDeviceptr_t dptr; + } hipMemGetAddressRange; + struct + { + size_t* granularity; + size_t granularity__val; + const hipMemAllocationProp* prop; + hipMemAllocationProp prop__val; + hipMemAllocationGranularity_flags option; + } hipMemGetAllocationGranularity; + struct + { + hipMemAllocationProp* prop; + hipMemAllocationProp prop__val; + hipMemGenericAllocationHandle_t handle; + } hipMemGetAllocationPropertiesFromHandle; + struct + { + size_t* free; + size_t free__val; + size_t* total; + size_t total__val; + } hipMemGetInfo; + struct + { + hipMemGenericAllocationHandle_t* handle; + hipMemGenericAllocationHandle_t handle__val; + void* osHandle; + hipMemAllocationHandleType shHandleType; + } hipMemImportFromShareableHandle; + struct + { + void* ptr; + size_t size; + size_t offset; + hipMemGenericAllocationHandle_t handle; + unsigned long long flags; + } hipMemMap; + struct + { + hipArrayMapInfo* mapInfoList; + hipArrayMapInfo mapInfoList__val; + unsigned int count; + hipStream_t stream; + } hipMemMapArrayAsync; + struct + { + hipMemPool_t* mem_pool; + hipMemPool_t mem_pool__val; + const hipMemPoolProps* pool_props; + hipMemPoolProps pool_props__val; + } hipMemPoolCreate; + struct + { + hipMemPool_t mem_pool; + } hipMemPoolDestroy; + struct + { + hipMemPoolPtrExportData* export_data; + hipMemPoolPtrExportData export_data__val; + void* dev_ptr; + } hipMemPoolExportPointer; + struct + { + void* shared_handle; + hipMemPool_t mem_pool; + hipMemAllocationHandleType handle_type; + unsigned int flags; + } hipMemPoolExportToShareableHandle; + struct + { + hipMemAccessFlags* flags; + hipMemAccessFlags flags__val; + hipMemPool_t mem_pool; + hipMemLocation* location; + hipMemLocation location__val; + } hipMemPoolGetAccess; + struct + { + hipMemPool_t mem_pool; + hipMemPoolAttr attr; + void* value; + } hipMemPoolGetAttribute; + struct + { + hipMemPool_t* mem_pool; + hipMemPool_t mem_pool__val; + void* shared_handle; + hipMemAllocationHandleType handle_type; + unsigned int flags; + } hipMemPoolImportFromShareableHandle; + struct + { + void** dev_ptr; + void* dev_ptr__val; + hipMemPool_t mem_pool; + hipMemPoolPtrExportData* export_data; + hipMemPoolPtrExportData export_data__val; + } hipMemPoolImportPointer; + struct + { + hipMemPool_t mem_pool; + const hipMemAccessDesc* desc_list; + hipMemAccessDesc desc_list__val; + size_t count; + } hipMemPoolSetAccess; + struct + { + hipMemPool_t mem_pool; + hipMemPoolAttr attr; + void* value; + } hipMemPoolSetAttribute; + struct + { + hipMemPool_t mem_pool; + size_t min_bytes_to_hold; + } hipMemPoolTrimTo; + struct + { + const void* dev_ptr; + size_t count; + int device; + hipStream_t stream; + } hipMemPrefetchAsync; + struct + { + void* ptr; + size_t* size; + size_t size__val; + } hipMemPtrGetInfo; + struct + { + void* data; + size_t data_size; + hipMemRangeAttribute attribute; + const void* dev_ptr; + size_t count; + } hipMemRangeGetAttribute; + struct + { + void** data; + void* data__val; + size_t* data_sizes; + size_t data_sizes__val; + hipMemRangeAttribute* attributes; + hipMemRangeAttribute attributes__val; + size_t num_attributes; + const void* dev_ptr; + size_t count; + } hipMemRangeGetAttributes; + struct + { + hipMemGenericAllocationHandle_t handle; + } hipMemRelease; + struct + { + hipMemGenericAllocationHandle_t* handle; + hipMemGenericAllocationHandle_t handle__val; + void* addr; + } hipMemRetainAllocationHandle; + struct + { + void* ptr; + size_t size; + const hipMemAccessDesc* desc; + hipMemAccessDesc desc__val; + size_t count; + } hipMemSetAccess; + struct + { + void* ptr; + size_t size; + } hipMemUnmap; + struct + { + void* dst; + const void* src; + size_t sizeBytes; + hipMemcpyKind kind; + } hipMemcpy; + struct + { + void* dst; + size_t dpitch; + const void* src; + size_t spitch; + size_t width; + size_t height; + hipMemcpyKind kind; + } hipMemcpy2D; + struct + { + void* dst; + size_t dpitch; + const void* src; + size_t spitch; + size_t width; + size_t height; + hipMemcpyKind kind; + hipStream_t stream; + } hipMemcpy2DAsync; + struct + { + void* dst; + size_t dpitch; + hipArray_const_t src; + size_t wOffset; + size_t hOffset; + size_t width; + size_t height; + hipMemcpyKind kind; + } hipMemcpy2DFromArray; + struct + { + void* dst; + size_t dpitch; + hipArray_const_t src; + size_t wOffset; + size_t hOffset; + size_t width; + size_t height; + hipMemcpyKind kind; + hipStream_t stream; + } hipMemcpy2DFromArrayAsync; + struct + { + hipArray* dst; + hipArray dst__val; + size_t wOffset; + size_t hOffset; + const void* src; + size_t spitch; + size_t width; + size_t height; + hipMemcpyKind kind; + } hipMemcpy2DToArray; + struct + { + hipArray* dst; + hipArray dst__val; + size_t wOffset; + size_t hOffset; + const void* src; + size_t spitch; + size_t width; + size_t height; + hipMemcpyKind kind; + hipStream_t stream; + } hipMemcpy2DToArrayAsync; + struct + { + const hipMemcpy3DParms* p; + hipMemcpy3DParms p__val; + } hipMemcpy3D; + struct + { + const hipMemcpy3DParms* p; + hipMemcpy3DParms p__val; + hipStream_t stream; + } hipMemcpy3DAsync; + struct + { + void* dst; + const void* src; + size_t sizeBytes; + hipMemcpyKind kind; + hipStream_t stream; + } hipMemcpyAsync; + struct + { + void* dst; + hipArray* srcArray; + hipArray srcArray__val; + size_t srcOffset; + size_t count; + } hipMemcpyAtoH; + struct + { + hipDeviceptr_t dst; + hipDeviceptr_t src; + size_t sizeBytes; + } hipMemcpyDtoD; + struct + { + hipDeviceptr_t dst; + hipDeviceptr_t src; + size_t sizeBytes; + hipStream_t stream; + } hipMemcpyDtoDAsync; + struct + { + void* dst; + hipDeviceptr_t src; + size_t sizeBytes; + } hipMemcpyDtoH; + struct + { + void* dst; + hipDeviceptr_t src; + size_t sizeBytes; + hipStream_t stream; + } hipMemcpyDtoHAsync; + struct + { + void* dst; + hipArray_const_t srcArray; + size_t wOffset; + size_t hOffset; + size_t count; + hipMemcpyKind kind; + } hipMemcpyFromArray; + struct + { + void* dst; + const void* symbol; + size_t sizeBytes; + size_t offset; + hipMemcpyKind kind; + } hipMemcpyFromSymbol; + struct + { + void* dst; + const void* symbol; + size_t sizeBytes; + size_t offset; + hipMemcpyKind kind; + hipStream_t stream; + } hipMemcpyFromSymbolAsync; + struct + { + hipArray* dstArray; + hipArray dstArray__val; + size_t dstOffset; + const void* srcHost; + size_t count; + } hipMemcpyHtoA; + struct + { + hipDeviceptr_t dst; + void* src; + size_t sizeBytes; + } hipMemcpyHtoD; + struct + { + hipDeviceptr_t dst; + void* src; + size_t sizeBytes; + hipStream_t stream; + } hipMemcpyHtoDAsync; + struct + { + const hip_Memcpy2D* pCopy; + hip_Memcpy2D pCopy__val; + } hipMemcpyParam2D; + struct + { + const hip_Memcpy2D* pCopy; + hip_Memcpy2D pCopy__val; + hipStream_t stream; + } hipMemcpyParam2DAsync; + struct + { + void* dst; + int dstDeviceId; + const void* src; + int srcDeviceId; + size_t sizeBytes; + } hipMemcpyPeer; + struct + { + void* dst; + int dstDeviceId; + const void* src; + int srcDevice; + size_t sizeBytes; + hipStream_t stream; + } hipMemcpyPeerAsync; + struct + { + hipArray* dst; + hipArray dst__val; + size_t wOffset; + size_t hOffset; + const void* src; + size_t count; + hipMemcpyKind kind; + } hipMemcpyToArray; + struct + { + const void* symbol; + const void* src; + size_t sizeBytes; + size_t offset; + hipMemcpyKind kind; + } hipMemcpyToSymbol; + struct + { + const void* symbol; + const void* src; + size_t sizeBytes; + size_t offset; + hipMemcpyKind kind; + hipStream_t stream; + } hipMemcpyToSymbolAsync; + struct + { + void* dst; + const void* src; + size_t sizeBytes; + hipMemcpyKind kind; + hipStream_t stream; + } hipMemcpyWithStream; + struct + { + void* dst; + int value; + size_t sizeBytes; + } hipMemset; + struct + { + void* dst; + size_t pitch; + int value; + size_t width; + size_t height; + } hipMemset2D; + struct + { + void* dst; + size_t pitch; + int value; + size_t width; + size_t height; + hipStream_t stream; + } hipMemset2DAsync; + struct + { + hipPitchedPtr pitchedDevPtr; + int value; + hipExtent extent; + } hipMemset3D; + struct + { + hipPitchedPtr pitchedDevPtr; + int value; + hipExtent extent; + hipStream_t stream; + } hipMemset3DAsync; + struct + { + void* dst; + int value; + size_t sizeBytes; + hipStream_t stream; + } hipMemsetAsync; + struct + { + hipDeviceptr_t dest; + unsigned short value; + size_t count; + } hipMemsetD16; + struct + { + hipDeviceptr_t dest; + unsigned short value; + size_t count; + hipStream_t stream; + } hipMemsetD16Async; + struct + { + hipDeviceptr_t dest; + int value; + size_t count; + } hipMemsetD32; + struct + { + hipDeviceptr_t dst; + int value; + size_t count; + hipStream_t stream; + } hipMemsetD32Async; + struct + { + hipDeviceptr_t dest; + unsigned char value; + size_t count; + } hipMemsetD8; + struct + { + hipDeviceptr_t dest; + unsigned char value; + size_t count; + hipStream_t stream; + } hipMemsetD8Async; + struct + { + hipMipmappedArray_t* pHandle; + hipMipmappedArray_t pHandle__val; + HIP_ARRAY3D_DESCRIPTOR* pMipmappedArrayDesc; + HIP_ARRAY3D_DESCRIPTOR pMipmappedArrayDesc__val; + unsigned int numMipmapLevels; + } hipMipmappedArrayCreate; + struct + { + hipMipmappedArray_t hMipmappedArray; + } hipMipmappedArrayDestroy; + struct + { + hipArray_t* pLevelArray; + hipArray_t pLevelArray__val; + hipMipmappedArray_t hMipMappedArray; + unsigned int level; + } hipMipmappedArrayGetLevel; + struct + { + hipFunction_t* function; + hipFunction_t function__val; + hipModule_t module; + const char* kname; + char kname__val; + } hipModuleGetFunction; + struct + { + hipDeviceptr_t* dptr; + hipDeviceptr_t dptr__val; + size_t* bytes; + size_t bytes__val; + hipModule_t hmod; + const char* name; + char name__val; + } hipModuleGetGlobal; + struct + { + textureReference** texRef; + textureReference* texRef__val; + hipModule_t hmod; + const char* name; + char name__val; + } hipModuleGetTexRef; + struct + { + hipFunction_t f; + unsigned int gridDimX; + unsigned int gridDimY; + unsigned int gridDimZ; + unsigned int blockDimX; + unsigned int blockDimY; + unsigned int blockDimZ; + unsigned int sharedMemBytes; + hipStream_t stream; + void** kernelParams; + void* kernelParams__val; + } hipModuleLaunchCooperativeKernel; + struct + { + hipFunctionLaunchParams* launchParamsList; + hipFunctionLaunchParams launchParamsList__val; + unsigned int numDevices; + unsigned int flags; + } hipModuleLaunchCooperativeKernelMultiDevice; + struct + { + hipFunction_t f; + unsigned int gridDimX; + unsigned int gridDimY; + unsigned int gridDimZ; + unsigned int blockDimX; + unsigned int blockDimY; + unsigned int blockDimZ; + unsigned int sharedMemBytes; + hipStream_t stream; + void** kernelParams; + void* kernelParams__val; + void** extra; + void* extra__val; + } hipModuleLaunchKernel; + struct + { + hipModule_t* module; + hipModule_t module__val; + const char* fname; + char fname__val; + } hipModuleLoad; + struct + { + hipModule_t* module; + hipModule_t module__val; + const void* image; + } hipModuleLoadData; + struct + { + hipModule_t* module; + hipModule_t module__val; + const void* image; + unsigned int numOptions; + hipJitOption* options; + hipJitOption options__val; + void** optionsValues; + void* optionsValues__val; + } hipModuleLoadDataEx; + struct + { + int* numBlocks; + int numBlocks__val; + hipFunction_t f; + int blockSize; + size_t dynSharedMemPerBlk; + } hipModuleOccupancyMaxActiveBlocksPerMultiprocessor; + struct + { + int* numBlocks; + int numBlocks__val; + hipFunction_t f; + int blockSize; + size_t dynSharedMemPerBlk; + unsigned int flags; + } hipModuleOccupancyMaxActiveBlocksPerMultiprocessorWithFlags; + struct + { + int* gridSize; + int gridSize__val; + int* blockSize; + int blockSize__val; + hipFunction_t f; + size_t dynSharedMemPerBlk; + int blockSizeLimit; + } hipModuleOccupancyMaxPotentialBlockSize; + struct + { + int* gridSize; + int gridSize__val; + int* blockSize; + int blockSize__val; + hipFunction_t f; + size_t dynSharedMemPerBlk; + int blockSizeLimit; + unsigned int flags; + } hipModuleOccupancyMaxPotentialBlockSizeWithFlags; + struct + { + hipModule_t module; + } hipModuleUnload; + struct + { + int* numBlocks; + int numBlocks__val; + const void* f; + int blockSize; + size_t dynamicSMemSize; + } hipOccupancyMaxActiveBlocksPerMultiprocessor; + struct + { + int* numBlocks; + int numBlocks__val; + const void* f; + int blockSize; + size_t dynamicSMemSize; + unsigned int flags; + } hipOccupancyMaxActiveBlocksPerMultiprocessorWithFlags; + struct + { + int* gridSize; + int gridSize__val; + int* blockSize; + int blockSize__val; + const void* f; + size_t dynSharedMemPerBlk; + int blockSizeLimit; + } hipOccupancyMaxPotentialBlockSize; + struct + { + void* data; + hipPointer_attribute attribute; + hipDeviceptr_t ptr; + } hipPointerGetAttribute; + struct + { + hipPointerAttribute_t* attributes; + hipPointerAttribute_t attributes__val; + const void* ptr; + } hipPointerGetAttributes; + struct + { + const void* value; + hipPointer_attribute attribute; + hipDeviceptr_t ptr; + } hipPointerSetAttribute; + struct + { + int* runtimeVersion; + int runtimeVersion__val; + } hipRuntimeGetVersion; + struct + { + int deviceId; + } hipSetDevice; + struct + { + unsigned int flags; + } hipSetDeviceFlags; + struct + { + const void* arg; + size_t size; + size_t offset; + } hipSetupArgument; + struct + { + const hipExternalSemaphore_t* extSemArray; + hipExternalSemaphore_t extSemArray__val; + const hipExternalSemaphoreSignalParams* paramsArray; + hipExternalSemaphoreSignalParams paramsArray__val; + unsigned int numExtSems; + hipStream_t stream; + } hipSignalExternalSemaphoresAsync; + struct + { + hipStream_t stream; + hipStreamCallback_t callback; + void* userData; + unsigned int flags; + } hipStreamAddCallback; + struct + { + hipStream_t stream; + void* dev_ptr; + size_t length; + unsigned int flags; + } hipStreamAttachMemAsync; + struct + { + hipStream_t stream; + hipStreamCaptureMode mode; + } hipStreamBeginCapture; + struct + { + hipStream_t* stream; + hipStream_t stream__val; + } hipStreamCreate; + struct + { + hipStream_t* stream; + hipStream_t stream__val; + unsigned int flags; + } hipStreamCreateWithFlags; + struct + { + hipStream_t* stream; + hipStream_t stream__val; + unsigned int flags; + int priority; + } hipStreamCreateWithPriority; + struct + { + hipStream_t stream; + } hipStreamDestroy; + struct + { + hipStream_t stream; + hipGraph_t* pGraph; + hipGraph_t pGraph__val; + } hipStreamEndCapture; + struct + { + hipStream_t stream; + hipStreamCaptureStatus* pCaptureStatus; + hipStreamCaptureStatus pCaptureStatus__val; + unsigned long long* pId; + unsigned long long pId__val; + } hipStreamGetCaptureInfo; + struct + { + hipStream_t stream; + hipStreamCaptureStatus* captureStatus_out; + hipStreamCaptureStatus captureStatus_out__val; + unsigned long long* id_out; + unsigned long long id_out__val; + hipGraph_t* graph_out; + hipGraph_t graph_out__val; + const hipGraphNode_t** dependencies_out; + const hipGraphNode_t* dependencies_out__val; + size_t* numDependencies_out; + size_t numDependencies_out__val; + } hipStreamGetCaptureInfo_v2; + struct + { + hipStream_t stream; + hipDevice_t* device; + hipDevice_t device__val; + } hipStreamGetDevice; + struct + { + hipStream_t stream; + unsigned int* flags; + unsigned int flags__val; + } hipStreamGetFlags; + struct + { + hipStream_t stream; + int* priority; + int priority__val; + } hipStreamGetPriority; + struct + { + hipStream_t stream; + hipStreamCaptureStatus* pCaptureStatus; + hipStreamCaptureStatus pCaptureStatus__val; + } hipStreamIsCapturing; + struct + { + hipStream_t stream; + } hipStreamQuery; + struct + { + hipStream_t stream; + } hipStreamSynchronize; + struct + { + hipStream_t stream; + hipGraphNode_t* dependencies; + hipGraphNode_t dependencies__val; + size_t numDependencies; + unsigned int flags; + } hipStreamUpdateCaptureDependencies; + struct + { + hipStream_t stream; + hipEvent_t event; + unsigned int flags; + } hipStreamWaitEvent; + struct + { + hipStream_t stream; + void* ptr; + unsigned int value; + unsigned int flags; + unsigned int mask; + } hipStreamWaitValue32; + struct + { + hipStream_t stream; + void* ptr; + uint64_t value; + unsigned int flags; + uint64_t mask; + } hipStreamWaitValue64; + struct + { + hipStream_t stream; + void* ptr; + unsigned int value; + unsigned int flags; + } hipStreamWriteValue32; + struct + { + hipStream_t stream; + void* ptr; + uint64_t value; + unsigned int flags; + } hipStreamWriteValue64; + struct + { + hipDeviceptr_t* dev_ptr; + hipDeviceptr_t dev_ptr__val; + const textureReference* texRef; + textureReference texRef__val; + } hipTexRefGetAddress; + struct + { + unsigned int* pFlags; + unsigned int pFlags__val; + const textureReference* texRef; + textureReference texRef__val; + } hipTexRefGetFlags; + struct + { + hipArray_Format* pFormat; + hipArray_Format pFormat__val; + int* pNumChannels; + int pNumChannels__val; + const textureReference* texRef; + textureReference texRef__val; + } hipTexRefGetFormat; + struct + { + int* pmaxAnsio; + int pmaxAnsio__val; + const textureReference* texRef; + textureReference texRef__val; + } hipTexRefGetMaxAnisotropy; + struct + { + hipMipmappedArray_t* pArray; + hipMipmappedArray_t pArray__val; + const textureReference* texRef; + textureReference texRef__val; + } hipTexRefGetMipMappedArray; + struct + { + float* pbias; + float pbias__val; + const textureReference* texRef; + textureReference texRef__val; + } hipTexRefGetMipmapLevelBias; + struct + { + float* pminMipmapLevelClamp; + float pminMipmapLevelClamp__val; + float* pmaxMipmapLevelClamp; + float pmaxMipmapLevelClamp__val; + const textureReference* texRef; + textureReference texRef__val; + } hipTexRefGetMipmapLevelClamp; + struct + { + size_t* ByteOffset; + size_t ByteOffset__val; + textureReference* texRef; + textureReference texRef__val; + hipDeviceptr_t dptr; + size_t bytes; + } hipTexRefSetAddress; + struct + { + textureReference* texRef; + textureReference texRef__val; + const HIP_ARRAY_DESCRIPTOR* desc; + HIP_ARRAY_DESCRIPTOR desc__val; + hipDeviceptr_t dptr; + size_t Pitch; + } hipTexRefSetAddress2D; + struct + { + textureReference* tex; + textureReference tex__val; + hipArray_const_t array; + unsigned int flags; + } hipTexRefSetArray; + struct + { + textureReference* texRef; + textureReference texRef__val; + float* pBorderColor; + float pBorderColor__val; + } hipTexRefSetBorderColor; + struct + { + textureReference* texRef; + textureReference texRef__val; + unsigned int Flags; + } hipTexRefSetFlags; + struct + { + textureReference* texRef; + textureReference texRef__val; + hipArray_Format fmt; + int NumPackedComponents; + } hipTexRefSetFormat; + struct + { + textureReference* texRef; + textureReference texRef__val; + unsigned int maxAniso; + } hipTexRefSetMaxAnisotropy; + struct + { + textureReference* texRef; + textureReference texRef__val; + float bias; + } hipTexRefSetMipmapLevelBias; + struct + { + textureReference* texRef; + textureReference texRef__val; + float minMipMapLevelClamp; + float maxMipMapLevelClamp; + } hipTexRefSetMipmapLevelClamp; + struct + { + textureReference* texRef; + textureReference texRef__val; + hipMipmappedArray* mipmappedArray; + hipMipmappedArray mipmappedArray__val; + unsigned int Flags; + } hipTexRefSetMipmappedArray; + struct + { + hipStreamCaptureMode* mode; + hipStreamCaptureMode mode__val; + } hipThreadExchangeStreamCaptureMode; + struct + { + hipUserObject_t* object_out; + hipUserObject_t object_out__val; + void* ptr; + hipHostFn_t destroy; + unsigned int initialRefcount; + unsigned int flags; + } hipUserObjectCreate; + struct + { + hipUserObject_t object; + unsigned int count; + } hipUserObjectRelease; + struct + { + hipUserObject_t object; + unsigned int count; + } hipUserObjectRetain; + struct + { + const hipExternalSemaphore_t* extSemArray; + hipExternalSemaphore_t extSemArray__val; + const hipExternalSemaphoreWaitParams* paramsArray; + hipExternalSemaphoreWaitParams paramsArray__val; + unsigned int numExtSems; + hipStream_t stream; + } hipWaitExternalSemaphoresAsync; + } args; + uint64_t* phase_data; +} hip_api_data_t; + +// helper macros ensuring C and C++ structs adhere to specific naming convention +#define ROCP_PUBLIC_CONFIG(TYPE) ::rocprofiler_##TYPE +#define ROCP_PRIVATE_CONFIG(TYPE) ::rocprofiler::internal::TYPE + +// Below asserts at compile time that the external C object has the same size as internal +// C++ object, e.g., +// sizeof(rocprofiler_domain_config) == sizeof(rocprofiler::internal::domain_config) +#define ROCP_ASSERT_CONFIG_ABI(TYPE) \ + static_assert(sizeof(ROCP_PUBLIC_CONFIG(TYPE)) == sizeof(ROCP_PRIVATE_CONFIG(TYPE)), \ + "Error! rocprofiler_" #TYPE " ABI error"); + +// Below asserts at compile time that the external C struct members has the same offset as +// internal C++ struct members +#define ROCP_ASSERT_CONFIG_OFFSET_ABI(TYPE, PUB_FIELD, PRIV_FIELD) \ + static_assert(offsetof(ROCP_PUBLIC_CONFIG(TYPE), PUB_FIELD) == \ + offsetof(ROCP_PRIVATE_CONFIG(TYPE), PRIV_FIELD), \ + "Error! rocprofiler_" #TYPE "." #PUB_FIELD " ABI offset error"); \ + static_assert(sizeof(ROCP_PUBLIC_CONFIG(TYPE)::PUB_FIELD) == \ + sizeof(ROCP_PRIVATE_CONFIG(TYPE)::PRIV_FIELD), \ + "Error! rocprofiler_" #TYPE "." #PUB_FIELD " ABI size error"); + +// this defines a template specialization for ensuring that the reinterpret_cast is only +// applied between public C structs and private C++ structs which are compatible. +#define ROCP_DEFINE_API_CAST_IMPL(INPUT_TYPE, OUTPUT_TYPE) \ + namespace traits \ + { \ + template <> \ + struct api_cast \ + { \ + using input_type = INPUT_TYPE; \ + using output_type = OUTPUT_TYPE; \ + \ + output_type* operator()(input_type* _v) const \ + { \ + return reinterpret_cast(_v); \ + } \ + \ + const output_type* operator()(const input_type* _v) const \ + { \ + return reinterpret_cast(_v); \ + } \ + }; \ + } + +// define C -> C++ and C++ -> C casting rules +#define ROCP_DEFINE_API_CAST_D(TYPE) \ + ROCP_DEFINE_API_CAST_IMPL(ROCP_PUBLIC_CONFIG(TYPE), ROCP_PRIVATE_CONFIG(TYPE)) \ + ROCP_DEFINE_API_CAST_IMPL(ROCP_PRIVATE_CONFIG(TYPE), ROCP_PUBLIC_CONFIG(TYPE)) + +// use only when C++ struct is just an alias for C struct +#define ROCP_DEFINE_API_CAST_S(TYPE) \ + ROCP_DEFINE_API_CAST_IMPL(ROCP_PUBLIC_CONFIG(TYPE), ROCP_PRIVATE_CONFIG(TYPE)) + +namespace +{ +namespace traits +{ +// left undefined to ensure template specialization +template +struct api_cast; + +// ensure api_cast where decltype(a) is const Tp equates to api_cast +template +struct api_cast : api_cast +{}; + +// ensure api_cast where decltype(a) is Tp& equates to api_cast +template +struct api_cast : api_cast +{}; + +// ensure api_cast where decltype(a) is Tp* equates to api_cast +template +struct api_cast : api_cast +{}; +} // namespace traits + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// +// +// SEE BELOW! VERY IMPORTANT! +// +// +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// +// +// EVERY NEW CONFIG AND ALL OF ITS MEMBER FIELDS NEED TO HAVE THESE COMPILE TIME CHECKS! +// +// these checks verify the two structs have the same size and that each +// member field has the same size and offset into the struct +// +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +ROCP_ASSERT_CONFIG_ABI(config) +ROCP_ASSERT_CONFIG_OFFSET_ABI(config, size, size) +ROCP_ASSERT_CONFIG_OFFSET_ABI(config, compat_version, compat_version) +ROCP_ASSERT_CONFIG_OFFSET_ABI(config, api_version, api_version) +ROCP_ASSERT_CONFIG_OFFSET_ABI(config, reserved0, session_idx) +ROCP_ASSERT_CONFIG_OFFSET_ABI(config, user_data, user_data) +ROCP_ASSERT_CONFIG_OFFSET_ABI(config, buffer, buffer) +ROCP_ASSERT_CONFIG_OFFSET_ABI(config, domain, domain) +ROCP_ASSERT_CONFIG_OFFSET_ABI(config, filter, filter) + +ROCP_ASSERT_CONFIG_ABI(domain_config) +ROCP_ASSERT_CONFIG_OFFSET_ABI(domain_config, callback, user_sync_callback) +ROCP_ASSERT_CONFIG_OFFSET_ABI(domain_config, reserved0, domains) +ROCP_ASSERT_CONFIG_OFFSET_ABI(domain_config, reserved1, opcodes) + +ROCP_ASSERT_CONFIG_ABI(buffer_config) +ROCP_ASSERT_CONFIG_OFFSET_ABI(buffer_config, callback, callback) +ROCP_ASSERT_CONFIG_OFFSET_ABI(buffer_config, buffer_size, buffer_size) +// ROCP_ASSERT_CONFIG_OFFSET_ABI(buffer_config, reserved0, buffer) +ROCP_ASSERT_CONFIG_OFFSET_ABI(buffer_config, reserved1, buffer_idx) + +ROCP_DEFINE_API_CAST_D(config) +ROCP_DEFINE_API_CAST_D(domain_config) +ROCP_DEFINE_API_CAST_D(buffer_config) +ROCP_DEFINE_API_CAST_S(filter_config) + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// +// +// SEE ABOVE! VERY IMPORTANT! +// +// +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +/// use this to ensure that reinterpret_cast from public C struct to internal C++ struct +/// is valid, e.g. guard against accidentally casting to wrong type +template +auto +rocp_cast(Tp* _val) +{ + return traits::api_cast{}(_val); +} + +/// helper function for making copies of the fields in rocprofiler_config. If the config +/// field needs to be copied in some special way, use a template specialization of the +/// "construct" function in the allocator to handle this, e.g.: +/// +/// using special_config = ::rocprofiler::internal::special_config; +/// +/// template <> +/// void +/// allocator::construct(special_config* const _p, +/// const special_config& _v) const +/// { +/// auto _tmp = special_config{}; +/// // ... special copy of fields from _v into _tmp +/// +/// // placement new of _tmp into _p +/// _p = new(_p) special_config{ _tmp }; +/// } +/// +/// template <> +/// void +/// allocator::construct(special_config* const _p, +/// special_config&& _v) const +/// { +/// auto _tmp = std::move(_v); +/// // ... perform special needs +/// +/// // placement new of _tmp into _p +/// _p = new(_p) special_config{ std::move(_tmp) }; +/// } +/// +template +Tp*& +copy_config_field(Tp*& _dst, Up* _src_v) +{ + static auto _allocator = allocator{}; + + if constexpr(!std::is_same::value) + { + using PrivateT = typename traits::api_cast::output_type; + static_assert(std::is_same::value, "Error incorrect field copy"); + + auto _src = rocp_cast(_src_v); + if(_src) + { + _dst = _allocator.allocate(1); + _allocator.construct(_dst, *_src); + } + return _dst; + } + else + { + if(_src_v) + { + _dst = _allocator.allocate(1); + _allocator.construct(_dst, *_src_v); + } + return _dst; + } +} + +auto& +get_configs_buffer() +{ + static char + _v[::rocprofiler::internal::max_configs_count * sizeof(rocprofiler::internal::config)]; + return _v; +} + +auto& +get_configs_mutex() +{ + static auto _v = std::mutex{}; + return _v; +} + +inline uint32_t +get_tid() +{ + return syscall(__NR_gettid); +} + +constexpr auto rocp_max_configs = ::rocprofiler::internal::max_configs_count; +} // namespace + +namespace rocprofiler +{ +namespace internal +{ +std::array& +get_registered_configs() +{ + static auto _v = std::array{}; + return _v; +} + +std::array, max_configs_count>& +get_active_configs() +{ + static auto _v = std::array, max_configs_count>{}; + return _v; +} +} // namespace internal +} // namespace rocprofiler + +extern "C" { + +rocprofiler_status_t +rocprofiler_allocate_config(rocprofiler_config* _inp_cfg) +{ + // perform checks that rocprofiler can be activated + + ::memset(_inp_cfg, 0, sizeof(rocprofiler_config)); + + auto* _cfg = rocp_cast(_inp_cfg); + + _cfg->size = sizeof(::rocprofiler_config); + _cfg->compat_version = 0; + _cfg->api_version = ROCPROFILER_API_VERSION_ID; + _cfg->session_idx = std::numeric_limitssession_idx)>::max(); + + // initial value checks + assert(_cfg->size == sizeof(rocprofiler::internal::config)); + assert(_cfg->compat_version == 0); + assert(_cfg->api_version == ROCPROFILER_API_VERSION_ID); + assert(_cfg->buffer == nullptr); + assert(_cfg->domain == nullptr); + assert(_cfg->filter == nullptr); + assert(_cfg->session_idx == + std::numeric_limits::max()); + + // ... allocate any internal space needed to handle another config ... + { + auto _lk = std::unique_lock{get_configs_mutex()}; + // ... + } + + return ROCPROFILER_STATUS_SUCCESS; +} + +rocprofiler_status_t +rocprofiler_validate_config(const rocprofiler_config* cfg_v) +{ + const auto* cfg = rocp_cast(cfg_v); + + if(cfg->buffer == nullptr) return ROCPROFILER_STATUS_ERROR_BUFFER_NOT_FOUND; + + if(cfg->filter == nullptr) return ROCPROFILER_STATUS_ERROR_FILTER_NOT_FOUND; + + if(cfg->domain == nullptr || cfg->domain->domains == 0) + return ROCPROFILER_STATUS_ERROR_INCORRECT_DOMAIN; + + return ROCPROFILER_STATUS_SUCCESS; +} + +rocprofiler_status_t +rocprofiler_start_config(rocprofiler_config* cfg_v, rocprofiler_session_id_t* session_id) +{ + if(rocprofiler_validate_config(cfg_v) != ROCPROFILER_STATUS_SUCCESS) + { + std::cerr << "rocprofiler_start_config() provided an invalid configuration. tool " + "should use rocprofiler_validate_config() to check whether the " + "config is valid and adapt accordingly to issues before trying to " + "start the configuration." + << std::endl; + abort(); + } + + auto* cfg = rocp_cast(cfg_v); + + uint64_t idx = rocp_max_configs; + { + auto _lk = std::unique_lock{get_configs_mutex()}; + for(size_t i = 0; i < rocp_max_configs; ++i) + { + if(rocprofiler::internal::get_registered_configs().at(i) == nullptr) + { + idx = i; + break; + } + } + } + + // too many configs already registered + if(idx == rocp_max_configs) return ROCPROFILER_STATUS_ERROR_SESSION_NOT_ACTIVE; + + cfg->session_idx = idx; + session_id->handle = idx; + + // using the session id, compute the location in the buffer of configs + auto* _offset = get_configs_buffer() + (idx * sizeof(rocprofiler::internal::config)); + + // placement new into the buffer + auto* _copy_cfg = new(_offset) rocprofiler::internal::config{*cfg}; + + // make copies of non-null config fields + copy_config_field(_copy_cfg->buffer, cfg->buffer); + copy_config_field(_copy_cfg->domain, cfg->domain); + copy_config_field(_copy_cfg->filter, cfg->filter); + + // store until "deallocation" + rocprofiler::internal::get_registered_configs().at(idx) = _copy_cfg; + + using config_t = rocprofiler::internal::config; + // atomic swap the pointer into the "active" array used internally + config_t* _expected = nullptr; + bool success = rocprofiler::internal::get_active_configs().at(idx).compare_exchange_strong( + _expected, rocprofiler::internal::get_registered_configs().at(idx)); + + if(!success) return ROCPROFILER_STATUS_ERROR_HAS_ACTIVE_SESSION; // need relevant enum + + return ROCPROFILER_STATUS_SUCCESS; +} + +rocprofiler_status_t +rocprofiler_stop_config(rocprofiler_session_id_t idx) +{ + // atomically assign the config pointer to NULL so that it is skipped in future + // callbacks + auto* _expected = + rocprofiler::internal::get_active_configs().at(idx.handle).load(std::memory_order_relaxed); + bool success = rocprofiler::internal::get_active_configs() + .at(idx.handle) + .compare_exchange_strong(_expected, nullptr); + + if(!success) + return ROCPROFILER_STATUS_ERROR_SESSION_NOT_FOUND; // compare exchange strong + // failed + + return ROCPROFILER_STATUS_SUCCESS; +} + +rocprofiler_status_t +rocprofiler_domain_add_domain(struct rocprofiler_domain_config* _inp_cfg, + rocprofiler_tracer_activity_domain_t _domain) +{ + auto* _cfg = rocp_cast(_inp_cfg); + if(_domain <= ACTIVITY_DOMAIN_NONE || _domain >= ACTIVITY_DOMAIN_NUMBER) + return ROCPROFILER_STATUS_ERROR_INVALID_DOMAIN_ID; + + _cfg->domains |= (1 << _domain); + return ROCPROFILER_STATUS_SUCCESS; +} + +rocprofiler_status_t +rocprofiler_domain_add_domains(struct rocprofiler_domain_config* _inp_cfg, + rocprofiler_tracer_activity_domain_t* _domains, + size_t _ndomains) +{ + for(size_t i = 0; i < _ndomains; ++i) + { + auto _status = rocprofiler_domain_add_domain(_inp_cfg, _domains[i]); + if(_status != ROCPROFILER_STATUS_SUCCESS) return _status; + } + return ROCPROFILER_STATUS_SUCCESS; +} + +rocprofiler_status_t +rocprofiler_domain_add_op(struct rocprofiler_domain_config* _inp_cfg, + rocprofiler_tracer_activity_domain_t _domain, + uint32_t _op) +{ + auto* _cfg = rocp_cast(_inp_cfg); + if(_domain <= ACTIVITY_DOMAIN_NONE || _domain >= ACTIVITY_DOMAIN_NUMBER) + return ROCPROFILER_STATUS_ERROR_INVALID_DOMAIN_ID; + + if(_op >= get_domain_max_op(_domain)) return ROCPROFILER_STATUS_ERROR_INVALID_OPERATION_ID; + + auto _offset = (_domain * rocprofiler::internal::domain_ops_offset); + _cfg->opcodes.set(_offset + _op, true); + return ROCPROFILER_STATUS_SUCCESS; +} + +rocprofiler_status_t +rocprofiler_domain_add_ops(struct rocprofiler_domain_config* _inp_cfg, + rocprofiler_tracer_activity_domain_t _domain, + uint32_t* _ops, + size_t _nops) +{ + for(size_t i = 0; i < _nops; ++i) + { + auto _status = rocprofiler_domain_add_op(_inp_cfg, _domain, _ops[i]); + if(_status != ROCPROFILER_STATUS_SUCCESS) return _status; + } + return ROCPROFILER_STATUS_SUCCESS; +} + +// ------------------------------------------------------------------------------------ // +// +// demo of internal implementation +// +// ------------------------------------------------------------------------------------ // + +void +api_callback(rocprofiler_tracer_activity_domain_t domain, + uint32_t cid, + const void* callback_data, + void*) +{ + for(const auto& aitr : rocprofiler::internal::get_active_configs()) + { + auto* itr = aitr.load(); + if(!itr) continue; + + // below should be valid so this might need to raise error + if(!itr->domain) continue; + + // if the given domain + op is not enabled, skip this config + if(!(*itr->domain)(domain, cid)) continue; + + if(itr->filter) + { + if(domain == ACTIVITY_DOMAIN_ROCTX) + {} + else if(domain == ACTIVITY_DOMAIN_HSA_API) + { + if(itr->filter->hsa_function_id && itr->filter->hsa_function_id(cid) == 0) continue; + } + else if(domain == ACTIVITY_DOMAIN_HIP_API) + { + if(itr->filter->hip_function_id && itr->filter->hip_function_id(cid) == 0) continue; + } + } + + auto& _domain = (*itr->domain); + auto& _correlation = (*itr->correlation_id); + + auto _correlation_id = rocprofiler::internal::correlation_config::get_unique_record_id(); + if(_correlation.external_id_callback) + _correlation.external_id = + _correlation.external_id_callback(domain, cid, _correlation_id); + + auto timestamp_ns = []() -> uint64_t { + return std::chrono::steady_clock::now().time_since_epoch().count(); + }; + + auto _header = rocprofiler_record_header_t{ROCPROFILER_TRACER_RECORD, + rocprofiler_record_id_t{_correlation_id}}; + auto _op_id = rocprofiler_tracer_operation_id_t{cid}; + auto _agent_id = rocprofiler_agent_id_t{0}; + auto _queue_id = rocprofiler_queue_id_t{0}; + auto _thread_id = rocprofiler_thread_id_t{get_tid()}; + auto _session = rocprofiler_session_id_t{itr->session_idx}; + auto _timestamp_raw = rocprofiler_timestamp_t{timestamp_ns()}; + auto _timestamp = rocprofiler_record_header_timestamp_t{_timestamp_raw, _timestamp_raw}; + + if(domain == ACTIVITY_DOMAIN_ROCTX) + { + auto _api_data = rocprofiler_tracer_api_data_t{}; + const roctx_api_data_t* _data = + reinterpret_cast(callback_data); + + if(itr->filter && itr->filter->name && itr->filter->name(_data->args.message) == 0) + continue; + + _api_data.roctx = _data; + + auto _phase = rocprofiler_api_tracing_phase_t{ROCPROFILER_PHASE_ENTER}; + _timestamp = {_timestamp_raw, _timestamp_raw}; + + auto _external_cid = rocprofiler_tracer_external_id_t{_data ? _data->args.id : 0}; + auto _activity_cid = rocprofiler_tracer_activity_correlation_id_t{0}; + const char* _name = _data->args.message; + + _domain.user_sync_callback(rocprofiler_record_tracer_t{_header, + _external_cid, + ACTIVITY_DOMAIN_ROCTX, + _op_id, + _api_data, + _activity_cid, + _timestamp, + _agent_id, + _queue_id, + _thread_id, + _phase, + _name}, + _session); + } + else if(domain == ACTIVITY_DOMAIN_HSA_API) + { + auto _api_data = rocprofiler_tracer_api_data_t{}; + const hsa_api_data_t* _data = reinterpret_cast(callback_data); + _api_data.hsa = _data; + + auto _phase = rocprofiler_api_tracing_phase_t{(_data->phase == ACTIVITY_API_PHASE_ENTER) + ? ROCPROFILER_PHASE_ENTER + : ROCPROFILER_PHASE_EXIT}; + + if(_phase == ROCPROFILER_PHASE_ENTER) + _timestamp.begin = _timestamp_raw; + else + _timestamp.end = _timestamp_raw; + + auto _external_cid = rocprofiler_tracer_external_id_t{0}; + auto _activity_cid = + rocprofiler_tracer_activity_correlation_id_t{_data->correlation_id}; + const char* _name = nullptr; + + _domain.user_sync_callback(rocprofiler_record_tracer_t{_header, + _external_cid, + ACTIVITY_DOMAIN_HSA_API, + _op_id, + _api_data, + _activity_cid, + _timestamp, + _agent_id, + _queue_id, + _thread_id, + _phase, + _name}, + _session); + } + else if(domain == ACTIVITY_DOMAIN_HIP_API) + { + auto _api_data = rocprofiler_tracer_api_data_t{}; + const hip_api_data_t* _data = reinterpret_cast(callback_data); + _api_data.hip = _data; + + auto _phase = rocprofiler_api_tracing_phase_t{(_data->phase == ACTIVITY_API_PHASE_ENTER) + ? ROCPROFILER_PHASE_ENTER + : ROCPROFILER_PHASE_EXIT}; + + if(_phase == ROCPROFILER_PHASE_ENTER) + _timestamp.begin = _timestamp_raw; + else + _timestamp.end = _timestamp_raw; + + auto _external_cid = rocprofiler_tracer_external_id_t{0}; + auto _activity_cid = + rocprofiler_tracer_activity_correlation_id_t{_data->correlation_id}; + const char* _name = nullptr; + + _domain.user_sync_callback(rocprofiler_record_tracer_t{_header, + _external_cid, + ACTIVITY_DOMAIN_HIP_API, + _op_id, + _api_data, + _activity_cid, + _timestamp, + _agent_id, + _queue_id, + _thread_id, + _phase, + _name}, + _session); + } + } +} + +void +InitRoctracer() +{ + for(const auto& itr : rocprofiler::internal::get_registered_configs()) + { + if(!itr) continue; + + // below should be valid so this might need to raise error + if(!itr->domain) continue; + + for(auto ditr : {ACTIVITY_DOMAIN_ROCTX, ACTIVITY_DOMAIN_HSA_API, ACTIVITY_DOMAIN_HIP_API}) + { + if((*itr->domain)(ditr)) + { + if(itr->domain->user_sync_callback) + { + // ... + } + else + { + // ... + } + } + } + + for(auto ditr : {ACTIVITY_DOMAIN_HSA_OPS, ACTIVITY_DOMAIN_HIP_OPS}) + { + if((*itr->domain)(ditr)) + { + if(itr->domain->opcodes.none()) + { + // ... + } + else + { + for(size_t i = 0; i < itr->domain->opcodes.size(); ++i) + { + if((*itr->domain)(ditr, i)) + { + // ... + } + } + } + } + } + } +} +} diff --git a/source/lib/rocprofiler/tracer.hpp b/source/lib/rocprofiler/tracer.hpp new file mode 100644 index 0000000000..b713e9b83e --- /dev/null +++ b/source/lib/rocprofiler/tracer.hpp @@ -0,0 +1,515 @@ +/* Copyright (c) 2018-2022 Advanced Micro Devices, Inc. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + 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 + AUTHORS 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 IN + THE SOFTWARE. */ + +#pragma once + +#include +#include +#include +#include + +#include +#include +#include +#include + +typedef struct +{ + rocprofiler_session_id_t session_id; + rocprofiler_buffer_id_t buffer_id; +} session_buffer_id_t; + +typedef session_buffer_id_t roctracer_pool_t; + +/* Correlation id */ +typedef uint64_t activity_correlation_id_t; + +typedef uint32_t activity_kind_t; +typedef uint32_t activity_op_t; + +typedef uint64_t roctracer_timestamp_t; + +typedef rocprofiler_tracer_activity_domain_t roctracer_domain_t; +typedef rocprofiler_tracer_activity_domain_t activity_domain_t; + +// Prof_Protocol +/* Activity record type */ +typedef struct activity_record_s +{ + uint32_t domain; /* activity domain id */ + activity_kind_t kind; /* activity kind */ + activity_op_t op; /* activity op */ + union + { + struct + { + activity_correlation_id_t correlation_id; /* activity ID */ + roctracer_timestamp_t begin_ns; /* host begin timestamp */ + roctracer_timestamp_t end_ns; /* host end timestamp */ + }; + struct + { + uint32_t se; /* sampled SE */ + uint64_t cycle; /* sample cycle */ + uint64_t pc; /* sample PC */ + } pc_sample; + }; + union + { + struct + { + int device_id; /* device id */ + uint64_t queue_id; /* queue id */ + }; + struct + { + uint32_t process_id; /* device id */ + uint32_t thread_id; /* thread id */ + }; + struct + { + activity_correlation_id_t external_id; /* external correlation id */ + }; + }; + union + { + size_t bytes; /* data size bytes */ + const char* kernel_name; /* kernel name */ + const char* mark_message; + }; +} activity_record_t; + +typedef activity_record_t roctracer_record_t; + +/* Activity sync callback type */ +typedef void (*activity_sync_callback_t)(activity_domain_t cid, + activity_record_t* record, + const void* data, + void* arg); +/* Activity async callback type */ +typedef void (*activity_async_callback_t)(activity_domain_t op, void* record, void* arg); + +/* API callback type */ +typedef void (*activity_rtapi_callback_t)(activity_domain_t domain, + uint32_t cid, + const void* data, + void* arg); +typedef activity_rtapi_callback_t roctracer_rtapi_callback_t; + +typedef roctracer_timestamp_t (*roctracer_get_timestamp_t)(); +typedef rocprofiler_timestamp_t (*rocprofiler_get_timestamp_t)(); + +typedef uint32_t activity_kind_t; +typedef uint32_t activity_op_t; + +/* API callback phase */ +typedef enum +{ + ACTIVITY_API_PHASE_ENTER = 0, + ACTIVITY_API_PHASE_EXIT = 1 +} activity_api_phase_t; + +const char* +roctracer_op_string(uint32_t domain, uint32_t op); + +/* Trace record types */ + +/** + * Memory pool allocator callback. + * + * If \p *ptr is NULL, then allocate memory of \p size bytes and save address + * in \p *ptr. + * + * If \p *ptr is non-NULL and size is non-0, then reallocate the memory at \p + * *ptr with size \p size and save the address in \p *ptr. The memory will have + * been allocated by the same callback. + * + * If \p *ptr is non-NULL and size is 0, then deallocate the memory at \p *ptr. + * The memory will have been allocated by the same callback. + * + * \p size is the size of the memory allocation or reallocation, or 0 if + * deallocating. + * + * \p arg Argument provided + */ +typedef void (*roctracer_allocator_t)(char** ptr, size_t size, void* arg); + +/** + * Memory pool buffer callback. + * + * The callback that will be invoked when a memory pool buffer becomes full or + * is flushed. + * + * \p begin pointer to first entry entry in the buffer. + * + * \p end pointer to one past the end entry in the buffer. + * + * \p arg the argument specified when the callback was defined. + */ +typedef void (*roctracer_buffer_callback_t)(const char* begin, const char* end, void* arg); + +/** + * Memory pool properties. + * + * Defines the properties when a tracer memory pool is created. + */ +typedef struct +{ + /** + * ROC Tracer mode. + */ + uint32_t mode; + + /** + * Size of buffer in bytes. + */ + size_t buffer_size; + + /** + * The allocator function to use to allocate and deallocate the buffer. If + * NULL then \p malloc, \p realloc, and \p free are used. + */ + roctracer_allocator_t alloc_fun; + + /** + * The argument to pass when invoking the \p alloc_fun allocator. + */ + void* alloc_arg; + + /** + * The function to call when a buffer becomes full or is flushed. + */ + roctracer_buffer_callback_t buffer_callback_fun; + + /** + * The argument to pass when invoking the \p buffer_callback_fun callback. + */ + void* buffer_callback_arg; +} roctracer_properties_t; + +/** + * ROC Tracer API status codes. + */ +typedef enum +{ + /** + * The function has executed successfully. + */ + ROCTRACER_STATUS_SUCCESS = 0, + /** + * A generic error has occurred. + */ + ROCTRACER_STATUS_ERROR = -1, + /** + * The domain ID is invalid. + */ + ROCTRACER_STATUS_ERROR_INVALID_DOMAIN_ID = -2, + /** + * An invalid argument was given to the function. + */ + ROCTRACER_STATUS_ERROR_INVALID_ARGUMENT = -3, + /** + * No default pool is defined. + */ + ROCTRACER_STATUS_ERROR_DEFAULT_POOL_UNDEFINED = -4, + /** + * The default pool is already defined. + */ + ROCTRACER_STATUS_ERROR_DEFAULT_POOL_ALREADY_DEFINED = -5, + /** + * Memory allocation error. + */ + ROCTRACER_STATUS_ERROR_MEMORY_ALLOCATION = -6, + /** + * External correlation ID pop mismatch. + */ + ROCTRACER_STATUS_ERROR_MISMATCHED_EXTERNAL_CORRELATION_ID = -7, + /** + * The operation is not currently implemented. This error may be reported by + * any function. Check the \ref known_limitations section to determine the + * status of the library implementation of the interface. + */ + ROCTRACER_STATUS_ERROR_NOT_IMPLEMENTED = -8, + /** + * Deprecated error code. + */ + ROCTRACER_STATUS_UNINIT = 2, + /** + * Deprecated error code. + */ + ROCTRACER_STATUS_BREAK = 3, + /** + * Deprecated error code. + */ + ROCTRACER_STATUS_BAD_DOMAIN = ROCTRACER_STATUS_ERROR_INVALID_DOMAIN_ID, + /** + * Deprecated error code. + */ + ROCTRACER_STATUS_BAD_PARAMETER = ROCTRACER_STATUS_ERROR_INVALID_ARGUMENT, + /** + * Deprecated error code. + */ + ROCTRACER_STATUS_HIP_API_ERR = 6, + /** + * Deprecated error code. + */ + ROCTRACER_STATUS_HIP_OPS_ERR = 7, + /** + * Deprecated error code. + */ + ROCTRACER_STATUS_HCC_OPS_ERR = ROCTRACER_STATUS_HIP_OPS_ERR, + /** + * Deprecated error code. + */ + ROCTRACER_STATUS_HSA_ERR = 7, + /** + * Deprecated error code. + */ + ROCTRACER_STATUS_ROCTX_ERR = 8, +} roctracer_status_t; + +/** + * Query textual name of an operation of a domain. + * @param[in] domain Domain being queried. + * @param[in] op Operation within \p domain. + * @param[in] kind \todo Define kind. + * @return Returns the NUL terminated string for the operation name, or NULL if + * the domain or operation are invalid. The string is owned by the ROC Tracer + * library. + */ +const char* +roctracer_op_string(uint32_t domain, uint32_t op, uint32_t kind); + +/** + * Query the operation code given a domain and the name of an operation. + * @param[in] domain The domain being queried. + * @param[in] str The NUL terminated name of the operation name being queried. + * @param[out] op The operation code. + * @param[out] kind If not NULL then the operation kind code. + */ +void +roctracer_op_code(uint32_t domain, const char* str, uint32_t* op, uint32_t* kind); + +/** + * Set the properties of a domain. + * @param[in] domain The domain. + * @param[in] properties The properties. Each domain defines its own type for + * the properties. Some domains require the properties to be set before they + * can be enabled. + */ +void +roctracer_set_properties(roctracer_domain_t domain, void* properties); + +/** + * Enable runtime API callback for a specific operation of a domain. + * @param domain The domain. + * @param op The operation ID in \p domain. + * @param callback The callback to invoke each time the operation is performed + * on entry and exit. + * @param pool Value to pass as last argument of \p callback. + */ +void +roctracer_enable_op_callback(roctracer_domain_t domain, + uint32_t op, + roctracer_rtapi_callback_t callback); + +/** + * Enable runtime API callback for all operations of a domain. + * @param domain The domain + * @param callback The callback to invoke each time the operation is performed + * on entry and exit. + * @param arg Value to pass as last argument of \p callback. + */ +void +roctracer_enable_domain_callback(roctracer_domain_t domain, + roctracer_rtapi_callback_t callback, + void* user_data = nullptr); + +/** + * Disable runtime API callback for a specific operation of a domain. + * @param domain The domain + * @param op The operation in \p domain. + */ +void +roctracer_disable_op_callback(roctracer_domain_t domain, uint32_t op); + +/** + * Disable runtime API callback for all operations of a domain. + * @param domain The domain + */ +void +roctracer_disable_domain_callback(roctracer_domain_t domain); + +/** + * Enable activity record logging for a specified operation of a domain using + * the default memory pool. + * @param[in] domain The domain. + * @param[in] op The activity operation ID in \p domain. + */ +void +roctracer_enable_op_activity(roctracer_domain_t domain, uint32_t op, roctracer_pool_t pool); + +/** + * Enable activity record logging for all operations of a domain using the + * default memory pool. + * @param[in] domain The domain. + */ +void +roctracer_enable_domain_activity(roctracer_domain_t domain, roctracer_pool_t pool); + +/** + * Disable activity record logging for a specified operation of a domain. + * @param[in] domain The domain. + * @param[in] op The activity operation ID in \p domain. + */ +void +roctracer_disable_op_activity(roctracer_domain_t domain, uint32_t op); + +/** + * Disable activity record logging for all operations of a domain. + * @param[in] domain The domain. + */ +void +roctracer_disable_domain_activity(roctracer_domain_t domain); + +// HIP Support +typedef enum +{ + HIP_OP_ID_DISPATCH = 0, + HIP_OP_ID_COPY = 1, + HIP_OP_ID_BARRIER = 2, + HIP_OP_ID_NUMBER = 3 +} hip_op_id_t; + +// HSA Support +// HSA OP ID enumeration +enum hsa_op_id_t +{ + HSA_OP_ID_DISPATCH = 0, + HSA_OP_ID_COPY = 1, + HSA_OP_ID_BARRIER = 2, + HSA_OP_ID_RESERVED1 = 3, + HSA_OP_ID_NUMBER +}; + +// HSA EVT ID enumeration +enum hsa_evt_id_t +{ + HSA_EVT_ID_ALLOCATE = 0, // Memory allocate callback + HSA_EVT_ID_DEVICE = 1, // Device assign callback + HSA_EVT_ID_MEMCOPY = 2, // Memcopy callback + HSA_EVT_ID_SUBMIT = 3, // Packet submission callback + HSA_EVT_ID_KSYMBOL = 4, // Loading/unloading of kernel symbol + HSA_EVT_ID_CODEOBJ = 5, // Loading/unloading of device code object + HSA_EVT_ID_NUMBER +}; + +struct hsa_ops_properties_t +{ + void* reserved1[4]; +}; + +// ROCTx Support +typedef uint64_t roctx_range_id_t; + +/** + * ROCTX API ID enumeration + */ +enum roctx_api_id_t +{ + ROCTX_API_ID_roctxMarkA = 0, + ROCTX_API_ID_roctxRangePushA = 1, + ROCTX_API_ID_roctxRangePop = 2, + ROCTX_API_ID_roctxRangeStartA = 3, + ROCTX_API_ID_roctxRangeStop = 4, + ROCTX_API_ID_NUMBER, +}; + +/** + * ROCTX callbacks data type + */ +typedef struct roctx_api_data_s +{ + union + { + struct + { + const char* message; + roctx_range_id_t id; + }; + struct + { + const char* message; + } roctxMarkA; + struct + { + const char* message; + } roctxRangePushA; + struct + { + const char* message; + } roctxRangePop; + struct + { + const char* message; + roctx_range_id_t id; + } roctxRangeStartA; + struct + { + const char* message; + roctx_range_id_t id; + } roctxRangeStop; + } args; +} roctx_api_data_t; + +// External Support +/* Extension opcodes */ +typedef enum +{ + ACTIVITY_EXT_OP_MARK = 0, + ACTIVITY_EXT_OP_EXTERN_ID = 1 +} activity_ext_op_t; + +typedef void (*roctracer_start_cb_t)(); +typedef void (*roctracer_stop_cb_t)(); +typedef struct +{ + roctracer_start_cb_t start_cb; + roctracer_stop_cb_t stop_cb; +} roctracer_ext_properties_t; + +// Tracing start +void +roctracer_start(); + +// Tracing stop +void +roctracer_stop(); + +// Notifies that the calling thread is entering an external region. +// Push an external correlation id for the calling thread. +void +roctracer_activity_push_external_correlation_id(activity_correlation_id_t id); + +// Notifies that the calling thread is leaving an external region. +// Pop an external correlation id for the calling thread. +// 'lastId' returns the last external correlation if not NULL +void +roctracer_activity_pop_external_correlation_id(activity_correlation_id_t* last_id); diff --git a/source/lib/tests/CMakeLists.txt b/source/lib/tests/CMakeLists.txt new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/source/lib/tests/CMakeLists.txt @@ -0,0 +1 @@ + diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1 @@ +