diff --git a/.clang-format b/.clang-format index f36b968..bcdf484 100644 --- a/.clang-format +++ b/.clang-format @@ -146,4 +146,3 @@ WhitespaceSensitiveMacros: - PP_STRINGIZE - BOOST_PP_STRINGIZE ... - diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..0246d77 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,43 @@ +--- +Checks: '-*,-readability-identifier-length, clang-diagnostic-*,-clang-diagnostic-unused-value,clang-analyzer-*,-*,bugprone-*,performance-*,readability-*,-readability-magic-numbers,-readability-braces-around-statements,-readability-inconsistent-declaration-parameter-name,-readability-named-parameter' + #HeaderFilterRegex: '' +WarningsAsErrors: '*' +AnalyzeTemporaryDtors: false +WarningsAsErrors: '' +FormatStyle: file +User: chrjacob +CheckOptions: + llvm-else-after-return.WarnOnConditionVariables: 'false' + modernize-loop-convert.MinConfidence: reasonable + modernize-replace-auto-ptr.IncludeStyle: llvm + modernize-pass-by-value.IncludeStyle: llvm + google-readability-namespace-comments.ShortNamespaceLines: '10' + google-readability-namespace-comments.SpacesBeforeComments: '2' + cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic: 'true' + google-readability-braces-around-statements.ShortStatementLines: '1' + cert-err33-c.CheckedFunctions: '::aligned_alloc;::asctime_s;::at_quick_exit;::atexit;::bsearch;::bsearch_s;::btowc;::c16rtomb;::c32rtomb;::calloc;::clock;::cnd_broadcast;::cnd_init;::cnd_signal;::cnd_timedwait;::cnd_wait;::ctime_s;::fclose;::fflush;::fgetc;::fgetpos;::fgets;::fgetwc;::fopen;::fopen_s;::fprintf;::fprintf_s;::fputc;::fputs;::fputwc;::fputws;::fread;::freopen;::freopen_s;::fscanf;::fscanf_s;::fseek;::fsetpos;::ftell;::fwprintf;::fwprintf_s;::fwrite;::fwscanf;::fwscanf_s;::getc;::getchar;::getenv;::getenv_s;::gets_s;::getwc;::getwchar;::gmtime;::gmtime_s;::localtime;::localtime_s;::malloc;::mbrtoc16;::mbrtoc32;::mbsrtowcs;::mbsrtowcs_s;::mbstowcs;::mbstowcs_s;::memchr;::mktime;::mtx_init;::mtx_lock;::mtx_timedlock;::mtx_trylock;::mtx_unlock;::printf_s;::putc;::putwc;::raise;::realloc;::remove;::rename;::scanf;::scanf_s;::setlocale;::setvbuf;::signal;::snprintf;::snprintf_s;::sprintf;::sprintf_s;::sscanf;::sscanf_s;::strchr;::strerror_s;::strftime;::strpbrk;::strrchr;::strstr;::strtod;::strtof;::strtoimax;::strtok;::strtok_s;::strtol;::strtold;::strtoll;::strtoul;::strtoull;::strtoumax;::strxfrm;::swprintf;::swprintf_s;::swscanf;::swscanf_s;::thrd_create;::thrd_detach;::thrd_join;::thrd_sleep;::time;::timespec_get;::tmpfile;::tmpfile_s;::tmpnam;::tmpnam_s;::tss_create;::tss_get;::tss_set;::ungetc;::ungetwc;::vfprintf;::vfprintf_s;::vfscanf;::vfscanf_s;::vfwprintf;::vfwprintf_s;::vfwscanf;::vfwscanf_s;::vprintf_s;::vscanf;::vscanf_s;::vsnprintf;::vsnprintf_s;::vsprintf;::vsprintf_s;::vsscanf;::vsscanf_s;::vswprintf;::vswprintf_s;::vswscanf;::vswscanf_s;::vwprintf_s;::vwscanf;::vwscanf_s;::wcrtomb;::wcschr;::wcsftime;::wcspbrk;::wcsrchr;::wcsrtombs;::wcsrtombs_s;::wcsstr;::wcstod;::wcstof;::wcstoimax;::wcstok;::wcstok_s;::wcstol;::wcstold;::wcstoll;::wcstombs;::wcstombs_s;::wcstoul;::wcstoull;::wcstoumax;::wcsxfrm;::wctob;::wctrans;::wctype;::wmemchr;::wprintf_s;::wscanf;::wscanf_s;' + modernize-loop-convert.MaxCopySize: '16' + cert-dcl16-c.NewSuffixes: 'L;LL;LU;LLU' + cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField: 'false' + cert-str34-c.DiagnoseSignedUnsignedCharComparisons: 'false' + modernize-use-nullptr.NullMacros: 'NULL' + llvm-qualified-auto.AddConstToQualified: 'false' + modernize-loop-convert.NamingStyle: CamelCase + llvm-else-after-return.WarnOnUnfixable: 'false' + google-readability-function-size.StatementThreshold: '800' + readability-identifier-naming.NamespaceCase: CamelCase + readability-identifier-naming.VariableCase: camelBack + readability-identifier-naming.FunctionCase: camelBack + readability-identifier-naming.ConstexprVariableCase: UPPER_CASE + readability-identifier-naming.ConstexprFunctionCase: camelBack + readability-identifier-naming.ClassCase: CamelCase + readability-identifier-naming.ConstexprMethodCase: CamelCase + readability-identifier-naming.EnumCase: UPPER_CASE + readability-identifier-naming.StructCase: CamelCase + readability-identifier-naming.GlobalConstantCase: UPPER_CASE + readability-identifier-naming.GlobalConstantPointerCase: UPPER_CASE + readability-identifier-naming.GlobalFunctionCase: camelBack + readability-identifier-naming.MemberCase: lower_case + readability-identifier-naming.MemberPrefix: 'm_' + readability-identifier-naming.MemberSuffix: '' +... diff --git a/.gitignore b/.gitignore index 06688bb..385cc97 100644 --- a/.gitignore +++ b/.gitignore @@ -1,23 +1,27 @@ -.vscode -.ccls -.dir-locals.el -.clang-format -**/CMakeCache.txt -**/CMakeFiles -CTestTestfile.cmake -Makefile -cmake_install.cmake -docs/Makefile -docs/cmake_install.cmake -docs/internal/Makefile -docs/internal/cmake_install.cmake -lib/Makefile -lib/cmake_install.cmake -libcpu.so -examples/Makefile -examples/cmake_install.cmake -tests/CTestTestfile.cmake -tests/Makefile -tests/cmake_install.cmake -build/ -docs/doxygen/html/ +.vscode +.ccls +.dir-locals.el +**/CMakeCache.txt +**/CMakeFiles +CTestTestfile.cmake +Makefile +cmake_install.cmake +docs/Makefile +docs/cmake_install.cmake +docs/internal/Makefile +docs/internal/cmake_install.cmake +lib/Makefile +lib/cmake_install.cmake +libcpu.so +examples/Makefile +examples/cmake_install.cmake +tests/CTestTestfile.cmake +tests/Makefile +tests/cmake_install.cmake +build/ +docs/.doxygen +docs/_doxygen +docs/.sphinx +docs/sphinx +sanity_test/ +``` diff --git a/BUILD.md b/BUILD.md deleted file mode 100644 index 8a19a79..0000000 --- a/BUILD.md +++ /dev/null @@ -1,86 +0,0 @@ -# AOCL-Utils library - ------------- -Linux build: ------------- -With GCC: ---------- -Tools needed: CMAKE v3.15 or above, GCC v12 or above. - -$ mkdir build -$ cd build -$ cmake .. (installs to default path) - - [cmake flag "-DCMAKE_INSTALL_PREFIX" can be used to avoid lib installation into defalut path(/home/usr/) - and to install in a user specified path. - - usage: cmake -DCMAKE_INSTALL_PREFIX= ..(to install library into custom path) ] - -$ cmake -DCMAKE_INSTALL_PREFIX= ..(to install library into custom path) - -$ make (without installing the library) - or - make install (to install library) - -Static library binary: libaoclutils.a -Shared/Dynamic library binary: libaoclutils.so - -NOTES: -If multiple GCC versions are installed in same system, please use below command to perform build with default compilers: -cmake -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ .. -(or) -you can export the compilers path (to be used) in CC, CXX variables before performing cmake command. -Example: export CC=/usr/bin/gcc; export CXX=/usr/bin/g++; - -With AOCC: ----------- -Tools needed: CMAKE v3.15 or above, AOCC v4.0 -Install AOCC 4.0, go to that path and use below commands: -$ cd /home/amd/aocc-compiler-4.0.0 -$ ./install.sh -$ source /home/amd/setenv_AOCC.sh -$ export CC=clang -$ export CXX=clang++ - -And follow the same above steps as per GCC build. - --------------- -Windows build: --------------- -Tools needed: CMAKE v3.15 or above, LLVM(Atleast version 15), MS Visual Studio community 2019/2022, Clang v15 or above. - -With Clang: -1. cmake -A x64 -DCMAKE_BUILD_TYPE=RELEASE -B build -T ClangCl -2. cmake --build ./build --config Release -3. cmake --install ./build --config Release - -Static library binary: libaoclutils_static.lib -Shared/Dynamic library binary: libaoclutils.lib, libaoclutils.dll - ----------------------------- -Doxygen document generation: ----------------------------- -Tools needed: Doxygen 1.9.6 or above -Include "-DALCI_DOXYGEN_DOC=ON" along with above commands during compilation. - -Example: -cmake -A x64 -DCMAKE_BUILD_TYPE=RELEASE -B build -T ClangCl -DALCI_DOXYGEN_DOC=ON - -After successful command execution, document will be generated in HTML format. -Open docs/doxygen/html/index.html in any browser to view documentation. - -CMake will use the existing Doxygen if already installed. Else user need to install Doxygen and try again. - -NOTES: -1. cmake flag "CMAKE_INSTALL_PREFIX" can be used to avoid lib installation into default path and to install in a user specified path. - cmake -A x64 -DCMAKE_BUILD_TYPE=RELEASE -B build -DCMAKE_INSTALL_PREFIX="custom_path" -T ClangCl -2. In order to use Clang v16, Need to install MS Visual Studio 2019 and below plugin: - LLVM 2019 plugin: https://marketplace.visualstudio.com/items?itemName=MarekAniola.mangh-llvm2019 - Change the command as follows: - cmake -A x64 -DCMAKE_BUILD_TYPE=RELEASE -B build -T LLVM -3. Few warnings are expected in Windows build with Clang. -4. If BUILD_SHARED_LIBS is OFF, then only static library binary is generated. - By default, BUILD_SHARED_LIBS is ON and both static, shared library binaries are generated. - Example: cmake -A x64 -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_SHARED_LIBS=OFF -B build -T ClangCl -5. Use -j option along with make/cmake build command to use multiple processes parallely to build the library. - Example:In linux, use "make -j" and in Windows, use "cmake --build ./build --config Release -j" diff --git a/CMake/FindSphinx.cmake b/CMake/FindSphinx.cmake new file mode 100644 index 0000000..3856556 --- /dev/null +++ b/CMake/FindSphinx.cmake @@ -0,0 +1,40 @@ +# +# Copyright (C) 2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +find_program(SPHINX_EXECUTABLE NAMES sphinx-build + HINTS + $ENV{SPHINX_DIR} + PATH_SUFFIXES bin + DOC "Sphinx documentation generator" +) + +include(FindPackageHandleStandardArgs) + +find_package_handle_standard_args(Sphinx DEFAULT_MSG + SPHINX_EXECUTABLE +) + +mark_as_advanced(SPHINX_EXECUTABLE) diff --git a/CMake/aocl-utils.pc.in b/CMake/aocl-utils.pc.in new file mode 100644 index 0000000..18ce5eb --- /dev/null +++ b/CMake/aocl-utils.pc.in @@ -0,0 +1,11 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=${prefix}/@AU_INSTALL_LIB_DIR@ +includedir=${prefix}/@AU_INSTALL_INCLUDE_DIR@ + +Name: @PROJECT_FULL_NAME@ +Description: @AU_DESCRIPTION@ +Version: @AU_VERSION_STRING@ +Libs: -L${libdir} -laoclutils +Libs.private: @CMAKE_CXX_LINK_FLAGS@ +Cflags: -I${includedir} diff --git a/CMake/au_compiler_msvc.cmake b/CMake/au_compiler_msvc.cmake new file mode 100644 index 0000000..5eef429 --- /dev/null +++ b/CMake/au_compiler_msvc.cmake @@ -0,0 +1,40 @@ +# +# Copyright (C) 2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +set(AU_CXX_FLAGS_COMMON "-W4 -Wextra" "-fno-rtti" "-fno-exceptions") +set(AU_CXX_FLAGS_DEBUG + "-Wsuggest-final-types" + "-Wsuggest-final-methods" + "-Wsuggest-override" + "-g") +set(AU_CXX_FLAGS_RELEASE "-O3" "-Wno-unused") + +list(APPEND CXX_FLAGS_DEBUG "${AU_CXX_FLAGS_COMMON} ${AU_CXX_FLAGS_DEBUG}") +list(APPEND CXX_FLAGS_RELEASE "${AU_CXX_FLAGS_COMMON} ${AU_CXX_FLAGS_RELEASE}") + +# Note that CMAKE_REQUIRED_FLAGS must be a string, not a list +#set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=${CXX_STD}") diff --git a/CMake/au_compiler_unix.cmake b/CMake/au_compiler_unix.cmake new file mode 100644 index 0000000..87305ad --- /dev/null +++ b/CMake/au_compiler_unix.cmake @@ -0,0 +1,40 @@ +# +# Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +set(AU_CXX_FLAGS_COMMON "-Wall -Wextra" "-fno-rtti" "-fno-exceptions") +set(AU_CXX_FLAGS_DEBUG + "-Wsuggest-final-types" + "-Wsuggest-final-methods" + "-Wsuggest-override" + "-g") +set(AU_CXX_FLAGS_RELEASE "-O3" "-Wno-unused") + +list(APPEND CXX_FLAGS_DEBUG "${AU_CXX_FLAGS_COMMON} ${AU_CXX_FLAGS_DEBUG}") +list(APPEND CXX_FLAGS_RELEASE "${AU_CXX_FLAGS_COMMON} ${AU_CXX_FLAGS_RELEASE}") + +# Note that CMAKE_REQUIRED_FLAGS must be a string, not a list +#set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=${CXX_STD}") diff --git a/CMake/au_examples.cmake b/CMake/au_examples.cmake new file mode 100644 index 0000000..f453fcf --- /dev/null +++ b/CMake/au_examples.cmake @@ -0,0 +1,70 @@ +# +# Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +# au_add_application( PACKAGE +# SOURCES source... +# HEADERS headers... +# [LIBS component...] +# ) +# +if(NOT DEFINED AU_CXX_STANDARD) + set(AU_CXX_STANDARD 17) +endif() +set(CMAKE_CXX_STANDARD ${AU_CXX_STANDARD}) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +function(au_add_application NAME) + set(fPrefix APP) + set(fOptions ) + set(fOneArg ) + set(fMultiArgs "INCLUDES;SOURCES;HEADERS;LIBS") + + cmake_parse_arguments( + ${fPrefix} + "${fOptions}" + "${fOneArg}" + "${fMultiArgs}" + ${ARGN} + ) + + #cmake_parse_arguments(APP "" "PACKAGE" "SOURCES;COMPONENTS" ${ARGN}) + + add_executable(${NAME} ${APP_SOURCES}) + add_executable(${APP_PACKAGE}::${NAME} ALIAS ${NAME}) + + if(DEFINED APP_LIBS) + target_link_directories(${NAME} PRIVATE ${CMAKE_BINARY_DIR}/Library) + target_link_libraries(${NAME} + PRIVATE + ${APP_LIBS} + ) + endif() + if(DEFINED APP_INCLUDES) + target_include_directories(${NAME} PRIVATE ${APP_INCLUDES}) + endif() + +endfunction(au_add_application) diff --git a/CMake/au_find_gtest.cmake b/CMake/au_find_gtest.cmake new file mode 100644 index 0000000..36a9369 --- /dev/null +++ b/CMake/au_find_gtest.cmake @@ -0,0 +1,29 @@ +include(FetchContent) +set(INSTALL_GTEST OFF) +include(GoogleTest) +FetchContent_Declare(gtest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.12.1 + ) +FetchContent_MakeAvailable(gtest) + +# +# On Windows: Prevent overriding the parent project's compiler/linker settings +# +IF(WIN32) + target_link_libraries(gmock PUBLIC gtest) + target_link_libraries(gmock_main PUBLIC gtest_main) +ENDIF() + +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +option(GTEST_ENABLE_INSTALL "" OFF) +option(GMOCK_ENABLE_INSTALL "" OFF) +#FetchContent_MakeAvailable(gtest) +# You can disable clang-tidy for specific folders in the fetched content project +if(CMAKE_CXX_CLANG_TIDY) + set_target_properties(gtest PROPERTIES CXX_CLANG_TIDY "") + set_target_properties(gtest_main PROPERTIES CXX_CLANG_TIDY "") + set_target_properties(gmock PROPERTIES CXX_CLANG_TIDY "") + set_target_properties(gmock_main PROPERTIES CXX_CLANG_TIDY "") +endif() diff --git a/CMake/au_functions.cmake b/CMake/au_functions.cmake new file mode 100644 index 0000000..1f68400 --- /dev/null +++ b/CMake/au_functions.cmake @@ -0,0 +1,91 @@ +# +# Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +function(au_module_exists arg var) +list(FIND "${arg}" AU_MODULES_LIST var) +if (${var} GREATER -1) + set(var TRUE) +else() + unset(var) +endif() +endfunction() + +# au_add_component( PACKAGE +# SOURCES source... +# [INCLUDES include...] +# [USING dependency...] +# [SHARING dependency...] +# [TESTS test...] +# ) +# +function(au_add_component NAME) + set(fPrefix COMP) + set(fOptions ) + set(fOneArg PACKAGE) + set(fMultiArgs "INCLUDES;SOURCES;TESTS;USING;SHARING") + + cmake_parse_arguments( + ${fPrefix} + "${fOptions}" + "${fOneArg}" + "${fMultiArgs}" + ${ARGN} + ) + + add_library(${NAME} ${COMP_SOURCES}) + add_library(${COMP_PACKAGE}::${NAME} ALIAS ${NAME}) + + if(DEFINED COMP_INCLUDES) + target_include_directories(${NAME} PUBLIC ${COMP_INCLUDES}) + endif() + + if(DEFINED COMP_SHARING) + target_link_libraries(${NAME} PUBLIC ${COMP_SHARING}) + endif() + + if(DEFINED COMP_USING) + target_link_libraries(${NAME} PRIVATE ${COMP_USING}) + endif() + + if(DEFINED COMP_TESTS) + # add_executable(${NAME}-tests ${COMP_TESTS}) + # add_executable(tests::${NAME} ALIAS ${NAME}-tests) + + # add_custom_target(run-${NAME}-tests ALL COMMAND tests::${NAME}) + + # target_link_libraries(${NAME}-tests + # PRIVATE + # ${COMP_PACKAGE}::${NAME} + # ${COMP_USING} + # #${AU_MODULE}::base + # gtest + # ) + #target_include_directories(${NAME}-tests PRIVATE src) + endif() + + #target_link_libraries(${NAME} PRIVATE ) +endfunction(au_add_component) diff --git a/CMake/au_git_hash.cmake b/CMake/au_git_hash.cmake new file mode 100644 index 0000000..d1b6207 --- /dev/null +++ b/CMake/au_git_hash.cmake @@ -0,0 +1,48 @@ +# +# Copyright (C) 2022-2023, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +function(CheckGit) + add_custom_target(AlwaysCheckGit COMMAND ${CMAKE_COMMAND} + -DRUN_CHECK_GIT_VERSION=1 + -Dpre_configure_dir=${pre_configure_dir} + -Dpost_configure_file=${post_configure_dir} + -DGIT_HASH_CACHE=${GIT_HASH_CACHE} + -P ${CURRENT_LIST_DIR}/CheckGit.cmake + BYPRODUCTS ${post_configure_file} + ) + +endfunction() + +if(AU_BUILD_TYPE_DEBUG OR AU_BUILD_TYPE_DEVELOPER) +# Get the latest abbreviated commit hash of the working branch + execute_process( + COMMAND git log -1 --format=%h + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + OUTPUT_VARIABLE AU_GIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE + ) +endif() diff --git a/CMake/au_helpers.cmake b/CMake/au_helpers.cmake new file mode 100644 index 0000000..4e6eb12 --- /dev/null +++ b/CMake/au_helpers.cmake @@ -0,0 +1,73 @@ +# +# Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +macro(au_module NAME) + set(AU_MODULE ${NAME}) + list(FIND AU_MODULES_LIST ${NAME} EXISTS__) + #message("Called from " ${CMAKE_CURRENT_LIST_FILE} " With name: " ${NAME} + # " EXISTS: " ${EXISTS__}) + if (${EXISTS__} GREATER -1) + message(SEND_ERROR "Module ${NAME} already exists") + endif() + list(APPEND AU_MODULES_LIST ${NAME}) + unset(EXISTS__) +endmacro() + +# +# au_install_with_dir( +# DESTINATION +# [FILES files...]) +function (au_install_with_dir NAME) + set(fPrefix INST) + set(fOptions ) + set(fOneArg DESITNATION) + set(fMultiArgs FILES) + + cmake_parse_arguments( + ${fPrefix} + "${fOptions}" + "${fOneArg}" + "${fMultiArgs}" + ${ARGN} + ) + + foreach(FILE ${INST_FILES}) + get_filename_component(DIR ${FILE} DIRECTORY) + install(FILES ${FILE} DESTINATION ${INST_DESTINATION}/${DIR}) + endforeach() + +endfunction(au_install_with_dir) + +if (UNIX) + if(APPLE) + set(AU_TARGET_OS_IS_MACOS TRUE) + elseif(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Linux") + set(AU_TARGET_OS_IS_LINUX TRUE) + endif() +elseif(WIN32) + set(AU_TARGET_OS_IS_WINDOWS TRUE) +endif() diff --git a/CMake/au_install.cmake b/CMake/au_install.cmake new file mode 100644 index 0000000..5e0401b --- /dev/null +++ b/CMake/au_install.cmake @@ -0,0 +1,103 @@ +# +# Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +install( + DIRECTORY ${PROJECT_SOURCE_DIR}/SDK/Include/ + DESTINATION include + FILES_MATCHING REGEX ".*\\.(h|hh)") + +install( + FILES ${PROJECT_BINARY_DIR}/aocl-utils.pc + DESTINATION ${AU_INSTALL_LIB_DIR}/pkgconfig +) + +# for backward compatibility. +install( + DIRECTORY ${PROJECT_SOURCE_DIR}/SDK/Bcl/ + DESTINATION include + FILES_MATCHING REGEX ".*\\.(h|hh)") + +#install(TARGETS ${AU_INSTALL_TARGETS} +# EXPORT ${AU_INSTALL_EXPORT_NAME} +# LIBRARY DESTINATION ${AU_INSTALL_LIB_DIR} +# ARCHIVE DESTINATION ${AU_INSTALL_ARCHIVE_DIR} +# RUNTIME DESTINATION ${AU_INSTALL_BIN_DIR} +# PUBLIC_HEADER DESTINATION ${AU_INSTALL_INCLUDE_DIR} +# COMPONENT runtime +#) + +if (UNIX) + install(CODE "execute_process(COMMAND ldconfig)" + COMPONENT runtime + ) +endif() + +install(EXPORT ${AU_INSTALL_EXPORT_NAME} + DESTINATION ${AU_INSTALL_CMAKE_CONFIG_DIR} + NAMESPACE au:: + FILE ${AU_INSTALL_CMAKE_CONFIG_NAME} +) + +install( + DIRECTORY ${PROJECT_SOURCE_DIR}/CMake/ + DESTINATION ${AU_INSTALL_LIB_DIR}/CMake + FILES_MATCHING PATTERN "*.cmake" +) + +message("Installing... " ${AU_CONFIG_OUTPUT_FILE}) +install( + FILES ${AU_CONFIG_OUTPUT_FILE} + DESTINATION ${AU_INSTALL_INCLUDE_DIR}/Au +) + +message("Installing Version.txt... ") +install( + FILES version.txt + DESTINATION ${CMAKE_INSTALL_PREFIX} +) +message("Installing binaries... ") +if (${CMAKE_BUILD_TYPE} MATCHES "DEBUG") + set(DEBUG_POSTFIX "-dbg") +endif() + + +# +# CPACK configuration +# +set(CPACK_PACKAGE_NAME "${PACKAGE_NAME}") +set(CPACK_PACKAGE_DESCRIPTION "AOCL Foundations") +set(CPACK_PACKAGE_VENDOR "AMD") +set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/Readme.md") +set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/Readme.md") +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt") +set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CMAKE_INSTALL_PREFIX}") +set(CPACK_PACKAGE_VERSION_MAJOR ${AU_VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${AU_VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION_PATCH ${AU_VERSION_PATCH}) +set(CPACK_PACKAGE_VERSION ${AU_VERSION_STRING}) + +include(CPack) diff --git a/CMake/au_lib.cmake b/CMake/au_lib.cmake new file mode 100644 index 0000000..d61da45 --- /dev/null +++ b/CMake/au_lib.cmake @@ -0,0 +1,262 @@ +# +# Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +macro(au_normalize_name name var) + STRING(REPLACE "::" "__" ${var} ${name}) +endmacro() + +macro(setlibname NAME isPublic __target_name) + if(UNIX) + # set the target name if it is public or the name not equal to aoclutils + if(${isPublic}) + if(${NAME} STREQUAL "aoclutils") + set(__target_name "aoclutils") + else() + set(__target_name "au_${NAME}") + endif() + else() + if(${NAME} STREQUAL "aoclutils") + set(__target_name "aoclutils") + else() + set(__target_name "au_internal_${NAME}") + endif() + endif() + else() + if(${isPublic}) + if(${NAME} STREQUAL "aoclutils") + set(__target_name "libaoclutils") + else() + set(__target_name "au_${NAME}") + endif() + else() + if(${NAME} STREQUAL "aoclutils") + set(__target_name "libaoclutils") + else() + set(__target_name "au_internal_${NAME}") + endif() + endif() + endif() +endmacro() + + +# au_add_interface( PACKAGE +# [INCLUDES include...] +# ) +# +function(au_add_interface NAME) + set(fPrefix cciface) + set(fOptions PUBLIC) + set(fOneArg ) + set(fMultiArgs HEADERS) + + cmake_parse_arguments( + ${fPrefix} + "${fOptions}" + "${fOneArg}" + "${fMultiArgs}" + ${ARGN} + ) + if (NOT DEFINED AU_MODULE) + #message(FATAL_ERROR "af module name not defined") + set(AU_MODULE af) + endif() + + au_normalize_name(${NAME} __new_name) + add_library(${__new_name} INTERFACE) + + if(cciface_PUBLIC) + set(__target_name "au_${__new_name}") + else() + set(__target_name "au_internal_${__new_name}") + endif() + + target_include_directories(${__new_name} INTERFACE ${cciface_HEADERS}) + + add_library(${AU_MODULE}::${NAME} ALIAS ${__new_name}) +endfunction(au_add_interface) + + +# Produces a static library that can be linked into other test, binary or +# library targets. +# +# Arguments: +# NAME base name of the target. See below for target naming conventions. +# SOURCES list of source files, including headers. +# DEPENDS list of dependency libraries +# PUBLIC flag, intended for external use. +# +# If SRCS contains only headers, an INTERFACE rule is created. This rule carries +# include path and link library information, but is not directly buildable. +# +# The corresponding build target is named au__ if PUBLIC is +# specified, or au_internal__ otherwise. An alias is also defined +# for use in CMake scripts, in the form af:::: or +# af::internal:::: +# +function(au_cc_library NAME) + set(fPrefix cclib) + set(fOptions PUBLIC;TEST_ONLY) + set(fOneArg ) + set(fMultiArgs SOURCES;HEADERS;DEPENDS;USING) + + if (NOT DEFINED AU_MODULE) + message(FATAL_ERROR "af module name not defined") + endif() + + cmake_parse_arguments( + ${fPrefix} + "${fOptions}" + "${fOneArg}" + "${fMultiArgs}" + ${ARGN} + ) + + # Check if header-only library + set(tmp_src_list ${${fPrefix}_SOURCES}) + list(FILTER tmp_src_list INCLUDE REGEX "\\.cc$") + + if(UNIX) + set(libaoclutils "aoclutils") + else() + set(libaoclutils "libaoclutils") + endif() + + if(${AU_BUILD_STATIC_LIBS}) + if (TARGET ${libaoclutils}) + target_sources(${libaoclutils} PRIVATE ${${fPrefix}_SOURCES} ${${fPrefix}_HEADERS}) + endif() + endif() + if(${AU_BUILD_SHARED_LIBS}) + if (TARGET ${libaoclutils}_shared) + target_sources(${libaoclutils}_shared PRIVATE ${${fPrefix}_SOURCES} ${${fPrefix}_HEADERS}) + endif() + endif() + + if (DEFINED tmp_src_list) + set(isPublic ${cclib_PUBLIC}) + setlibname(${NAME} ${isPublic} __target_name) + + if(UNIX) + set(output_name ${__target_name}) + else() + set(output_name ${__target_name}_static) + endif() + if(${AU_BUILD_STATIC_LIBS}) + add_library(${__target_name} STATIC "") + target_sources(${__target_name} + PRIVATE + ${${fPrefix}_SOURCES} + ${${fPrefix}_HEADERS}) + + target_link_libraries(${__target_name} + PUBLIC ${cclib_DEPENDS} + ) + + set_target_properties(${__target_name} + PROPERTIES + CXX_STANDARD ${AU_CXX_STANDARD} + CXX_STANDARD_REQUIRED true + INCLUDE_DIRECTORIES "${AU_INCLUDE_DIRS}" + OUTPUT_NAME ${output_name} + ) + endif() + if(${AU_BUILD_SHARED_LIBS}) + #target_link_libraries(af::all PUBLIC ${__target_name}) + add_library(${__target_name}_shared SHARED "") + target_sources(${__target_name}_shared + PRIVATE + ${${fPrefix}_SOURCES} + ${${fPrefix}_HEADERS} + ) + target_link_libraries(${__target_name}_shared + PUBLIC ${cclib_DEPENDS} + ) + set_target_properties(${__target_name}_shared + PROPERTIES + CXX_STANDARD ${AU_CXX_STANDARD} + CXX_STANDARD_REQUIRED true + INCLUDE_DIRECTORIES "${AU_INCLUDE_DIRS}" + OUTPUT_NAME ${__target_name} + ) + endif() + else() + add_library(${__target_name} INTERFACE) + target_include_directories(${__target_name} INTERFACE ${AU_INCLUDE_DIRS}) + endif() + + # install targets that are not internal + if (cclib_PUBLIC) + if(UNIX) + if(${AU_BUILD_STATIC_LIBS}) + install(TARGETS ${__target_name} EXPORT ${AU_INSTALL_EXPORT_NAME} + RUNTIME DESTINATION ${AU_INSTALL_BIN_DIR} + LIBRARY DESTINATION ${AU_INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${AU_INSTALL_ARCHIVE_DIR} + ) + endif() + if(${AU_BUILD_SHARED_LIBS}) + install(TARGETS ${__target_name}_shared EXPORT ${AU_INSTALL_EXPORT_NAME} + RUNTIME DESTINATION ${AU_INSTALL_BIN_DIR} + LIBRARY DESTINATION ${AU_INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${AU_INSTALL_ARCHIVE_DIR} + ) + endif() + else() + if(${AU_BUILD_STATIC_LIBS}) + install(TARGETS ${__target_name} EXPORT ${AU_INSTALL_EXPORT_NAME} + RUNTIME DESTINATION ${AU_INSTALL_BIN_DIR} + LIBRARY DESTINATION ${AU_INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${AU_INSTALL_ARCHIVE_DIR} + ) + install(TARGETS ${__target_name} EXPORT + RUNTIME DESTINATION ${AU_INSTALL_LIB_DIR} + LIBRARY DESTINATION ${AU_INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${AU_INSTALL_ARCHIVE_DIR} + ) + endif() + if(${AU_BUILD_SHARED_LIBS}) + install(TARGETS ${__target_name}_shared EXPORT ${AU_INSTALL_EXPORT_NAME} + RUNTIME DESTINATION ${AU_INSTALL_BIN_DIR} + LIBRARY DESTINATION ${AU_INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${AU_INSTALL_BIN_DIR} + ) + install(TARGETS ${__target_name}_shared + RUNTIME DESTINATION ${AU_INSTALL_LIB_DIR} + LIBRARY DESTINATION ${AU_INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${AU_INSTALL_ARCHIVE_DIR} + ) + endif() + endif() + endif() + if (${AU_BUILD_STATIC_LIBS} AND ${AU_BUILD_SHARED_LIBS}) + add_library(au::${AU_MODULE} ALIAS ${__target_name}) + elseif (${AU_BUILD_STATIC_LIBS}) + add_library(au::${AU_MODULE} ALIAS ${__target_name}) + elseif (${AU_BUILD_SHARED_LIBS}) + add_library(au::${AU_MODULE} ALIAS ${__target_name}_shared) + endif() + +endfunction(au_cc_library) diff --git a/CMake/au_options.cmake b/CMake/au_options.cmake new file mode 100644 index 0000000..56b69b0 --- /dev/null +++ b/CMake/au_options.cmake @@ -0,0 +1,91 @@ +# +# Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +include(CMakeDependentOption) + +option(AU_BUILD_TESTS "Enable the tests." OFF) +option(AU_BUILD_DOCS "Generate Docs during build" OFF) +option(AU_BUILD_EXAMPLES "Enable examples" OFF) +option(AU_ENABLE_SLOW_TESTS "Option to Enable SLOW tests" OFF) +option(AU_ENABLE_BROKEN_TESTS "Option to Enable BROKEN tests" OFF) +option(AU_ENABLE_ASSERTIONS "Enable asserts in the code" OFF) +option(AU_ENABLE_OLD_API "Enable OLD alci_* APIs" OFF) +option(AU_BUILD_WITH_ASAN "Enable ASAN Options on build" OFF) +option(AU_ENABLE_CODE_COVERAGE "Enable Code coverage on build" OFF) +option(AU_BUILD_STATIC_LIBS "Build static libraries" ON) +option(AU_BUILD_SHARED_LIBS "Build shared libraries" ON) +option(AU_CMAKE_VERBOSE "Set cmake verbosity" OFF) + +# Define the processor type +string(TOUPPER "${CMAKE_SYSTEM_PROCESSOR}" upper_CMAKE_SYSTEM_PROCESSOR) +cmake_dependent_option(AU_CPU_ARCH_X86 "" OFF "${upper_CMAKE_SYSTEM_PROCESSOR} MATCHES ^x86" ON) + + +# Lets make the build +string(TOUPPER "${CMAKE_BUILD_TYPE}" upper_CMAKE_BUILD_TYPE) +if (CMAKE_BUILD_TYPE AND + NOT upper_CMAKE_BUILD_TYPE MATCHES "^(DEBUG|RELEASE|DEVELOPER)$") + message(FATAL_ERROR "Invalid value for CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") +endif() + +# Handle deprecated APIs +if(${AU_ENABLE_OLD_API}) + set(AU_WARN_DEPRECATION FALSE) +else() + set(AU_WARN_DEPRECATION TRUE) +endif() + +cmake_dependent_option(AU_BUILD_TYPE_RELEASE "" ON "upper_CMAKE_BUILD_TYPE STREQUAL RELEASE" OFF) +cmake_dependent_option(AU_BUILD_TYPE_DEBUG "" ON "upper_CMAKE_BUILD_TYPE STREQUAL DEBUG" OFF) +cmake_dependent_option(AU_BUILD_TYPE_DEVELOPER "" ON "upper_CMAKE_BUILD_TYPE STREQUAL DEVELOPER" OFF) + +mark_as_advanced(AU_BUILD_TYPE_RELEASE + AU_BUILD_TYPE_DEBUG + AU_BUILD_TYPE_DEVELOPER + AU_ENABLE_ASSERTIONS + AU_WARN_DEPRECATION) + +if (AU_CMAKE_VERBOSE AND FALSE) +message( + "build type \n" + "release:" ${AU_BUILD_TYPE_RELEASE} "\n" + "debug:" ${AU_BUILD_TYPE_DEBUG} "\n" + "developer:" ${AU_BUILD_TYPE_DEVELOPER} "\n" + "assertions: " ${AU_ENABLE_ASSERTIONS}) +endif() + + +if (AU_BUILD_TYPE_RELEASE) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/Release) +elseif(AU_BUILD_TYPE_DEVELOPER) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/Developer) +elseif(AU_BUILD_TYPE_DEBUG) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/Debug) +endif() + + +option(AU_BUILD_SHARED_LIBS "Build shared libraries" OFF) diff --git a/CMake/au_unit_tests.cmake b/CMake/au_unit_tests.cmake new file mode 100644 index 0000000..8682acd --- /dev/null +++ b/CMake/au_unit_tests.cmake @@ -0,0 +1,180 @@ +# +# Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# Declare the beginning of a new namespace. +# +# As a rule of thumb, every CMakeLists.txt should be a different module, named +# after the directory that contains it, and this function should appear at the +# top of each CMakeLists script. Multiple directories can be part of the same +# module as long as target names do not collide. +# + +include(CMakeParseArguments) + +# Declare a test using googletest. +# +# Parameters: +# NAME name of the test. +# SOURCES list of test source files, headers included. +# HEADERS list of headers to depend on +# DEPENDS list of dependencies +# CONTENTS list of non-code dependencies, such as test vectors. +# +# Attributes: +# BROKEN Known to fail +# SKIP Dont add to targets +# HANGING Test might hang(such as looking for Entropy) +# WINDOWS_DISABLED Dont run on Windows (Why ? you'll know) +# +# Tests added with this macro are automatically registered. +# Each test produces a build target named au_test__. +# +# +# au_cc_test( +# DIRECTORY test/ +# TEST BufferTest WINDOWS_DISABLED +# SOURCES BufferTest.cc +# HEADERS BufferTest.hh +# CONTENTS data/ +# ) + +function(au_cc_test testName) + + if (NOT AU_BUILD_TESTS) + return() + endif() + + if (NOT DEFINED AU_MODULE) + message(FATAL_ERROR "af module name not defined") + endif() + + au_normalize_name(${AU_MODULE} _ESCAPED_AU_MODULE) + + set(fPrefix test) + set(fOptions BROKEN;SKIP;WINDOWS_DISABLED) + set(fOneArg CONTENTS;DIRECTORY) + set(fMultiArgs SOURCES;HEADERS;DEPENDS;EXTLIBRARY) + + cmake_parse_arguments( + ${fPrefix} + "${fOptions}" + "${fOneArg}" + "${fMultiArgs}" + ${ARGN} + ) + + set(_target_name "${_ESCAPED_AU_MODULE}_${testName}") + + if ( ${${fPrefix}_SKIP} OR ${${fPrefix}_BROKEN} ) + message("Test : " ${testName} "[SKIPPED]") + return() + endif() + + if ( ${${fPrefix}_WINDOWS_DISABLED} AND WIN32) + message("Test : " ${testName} "[WIN32-DISABLED]") + return() + endif() + + if ( ${${fPrefix}_SLOW} ) + if (STREQUAL "${au_ENABLE_SLOW_TESTS}" "OFF" ) + message("Test : " ${testName} "[SKIPPED] SLOW") + return() + endif() + endif() + + # message( + # " taget-" ${_target_name} + # " SOURCES-" ${${fPrefix}_SOURCES} + # " DIRECTORY-" ${${fPrefix}_DIRECTORY} + # " DEPENDS-" ${${fPrefix}_DEPENDS} + # " CONTENTS-" ${${fPrefix}_CONTENTS} + # ) + + if (${fPrefix}_DIRECTORY) + add_executable(${_target_name} + ${${fPrefix}_DIRECTORY}/${${fPrefix}_SOURCES}) + else() + add_executable(${_target_name} ${${fPrefix}_SOURCES}) + endif() + + target_include_directories(${_target_name} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PUBLIC "${AU_INCLUDE_DIRS}" + ) + + # Add gtest with main() as dependency + target_link_libraries(${_target_name} PRIVATE gmock_main) + + # + # Add additional dependencies, + # au_base will be added towards end by default + # + list(APPEND ${fPrefix}_DEPENDS ) + if(${fPrefix}_DEPENDS) + target_link_libraries(${_target_name} PRIVATE ${${fPrefix}_DEPENDS}) + endif() + if(${fPrefix}_EXTLIBRARY) + # check if the library is python + if(${${fPrefix}_EXTLIBRARY} STREQUAL "Python3") + find_package(Python3 COMPONENTS Interpreter Development REQUIRED) + else() + find_package(${${fPrefix}_EXTLIBRARY} COMPONENTS Development REQUIRED) + endif() + target_include_directories(${_target_name} PRIVATE ${${${fPrefix}_EXTLIBRARY}_INCLUDE_DIRS}) + target_link_libraries(${_target_name} PRIVATE ${${${fPrefix}_EXTLIBRARY}_LIBRARIES}) + endif() + #message("cxx standard" ${AU_CXX_STANDARD}) + set_target_properties( + ${_target_name} + PROPERTIES + CXX_STANDARD ${AU_CXX_STANDARD} + CXX_STANDARD_REQUIRED true + #TIMEOUT 120 + ) + + #message("Adding Test: " ${_target_name}) + + if (HAVE_CMAKE_GTEST) + # If we have CMake's built-in gtest support use it to add each test + # function as a separate test. + gtest_add_tests(TARGET ${_target_name} + WORKING_DIRECTORY "${PROJECT_BINARY_DIR}" + AUTO) + set_tests_properties(${test_cases} PROPERTIES TIMEOUT 120) + else() + # Otherwise add each test executable as a single test. + add_test(NAME ${_target_name} + COMMAND ${_target_name} + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + ) + #set_tests_properties( + #ctest_run_test_code + #PROPERTIES DEPENDS ${_target_name}) + endif() + +# TODO: Set the CONTENTS directory and copy its contents to ${PROJECT_BINARY_DIR} +endfunction(au_cc_test) diff --git a/CMake/au_variables.cmake b/CMake/au_variables.cmake new file mode 100644 index 0000000..dda7ef2 --- /dev/null +++ b/CMake/au_variables.cmake @@ -0,0 +1,73 @@ +# +# Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +include(GNUInstallDirs) + +if(AU_CMAKE_VERBOSE) + message(STATUS "Configuring...") +endif() + + + +# Figure out where to put the Config.h +# Input for this is config.h.in in ${PROJECT_SOURCE_DIR}/Library +if (NOT DEFINED AU_CONFIG_DIR) + set(AU_CONFIG_DIR "${PROJECT_BINARY_DIR}/generated") +endif() + +if (NOT DEFINED AU_VERSION_OUTPUT_FILE) + set(AU_VERSION_OUTPUT_FILE ${AU_CONFIG_DIR}/version.cc) +endif() + + +if (NOT DEFINED AU_CONFIG_OUTPUT_FILE) + set(AU_CONFIG_OUTPUT_FILE ${AU_CONFIG_DIR}/Au/Config.h) +endif() + +if (NOT DEFINED AU_CXX_STANDARD) + set(AU_CXX_STANDARD 17) +endif() + +set(CMAKE_DEBUG_POSTFIX "-dbg") + + +set(AU_INSTALL_INCLUDE_DIR "${CMAKE_INSTALL_INCLUDEDIR}") +set(AU_INSTALL_BIN_DIR "${CMAKE_INSTALL_BINDIR}") +set(AU_INSTALL_TEST_DIR "${CMAKE_INSTALL_DIR}/tests") +set(AU_INSTALL_LIB_DIR "${CMAKE_INSTALL_LIBDIR}") +set(AU_INSTALL_ARCHIVE_DIR "${CMAKE_INSTALL_LIBDIR}") +set(AU_INSTALL_FRAMEWORK_DIR "${CMAKE_INSTALL_LIBDIR}") +set(AU_INSTALL_CMAKE_CONFIG_DIR "${CMAKE_INSTALL_LIBDIR}/CMake") +set(AU_INSTALL_CMAKE_CONFIG_NAME "aocl-utils-config.cmake") +set(AU_INSTALL_ADDITIONAL_FILES_DIR "${CMAKE_INSTALL_DATADIR}/aocl-utils") +#set(AU_INSTALL_TARGETS "") +set(AU_INSTALL_EXPORT_NAME aocl_utils) + +if(WIN32) +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin") +endif() diff --git a/CMake/au_version.cmake b/CMake/au_version.cmake new file mode 100644 index 0000000..14b7ad5 --- /dev/null +++ b/CMake/au_version.cmake @@ -0,0 +1,75 @@ +# +# Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# +# Set Package version extracted from a string of format +# ${major}.${minor}.${patch}-${patch_extra} +# +function(au_extract_version_details var_prefix version_string) + +set(AU_VERSION_STRING_REGEX "^([0-9]+)\\.([0-9]+)\\.([0-9]+)([-])(rc|dev|\\.)?([0-9]*)$") +string(REGEX MATCH ${AU_VERSION_STRING_REGEX} version_matches "${version_string}") + +# don't use CMAKE_MATCH_0 for `full` since it may not have the `v` prefix. +if(CMAKE_MATCH_0) + set(major ${CMAKE_MATCH_1}) + set(minor ${CMAKE_MATCH_2}) + set(patch ${CMAKE_MATCH_3}) + set(suffix ${CMAKE_MATCH_5}) + set(suffix_extra ${CMAKE_MATCH_6}) + set(full "${major}.${minor}.${patch}${suffix}${suffix_extra}") + + set(${var_prefix} "${major}.${minor}.${patch}" PARENT_SCOPE) + set(${var_prefix}_FULL ${full} PARENT_SCOPE) + set(${var_prefix}_MAJOR ${major} PARENT_SCOPE) + set(${var_prefix}_MINOR ${minor} PARENT_SCOPE) + set(${var_prefix}_PATCH ${patch} PARENT_SCOPE) + set(${var_prefix}_SUFFIX_EXTRA ${suffix_extra} PARENT_SCOPE) + +if(AU_CMAKE_VERBOSE) + message("version string: " ${full}) + message("version major: " ${major}) + message("version minor: " ${minor}) + message("version patch: " ${patch}) + message("version suffix: " ${suffix}) + message("version suffix-extra: " ${suffix_extra}) +endif() + +endif() +endfunction() + +function(dummy_dont_call) +set(AU_VERSION_STRING_REGEX "^([0-9]+)\\.([0-9]+)\\.([0-9]+)([-]rc|\\.)?([0-9]*)$") +string(REGEX REPLACE "${AU_VERSION_STRING_REGEX}" "\\1" + AU_VERSION_MAJOR "${AU_VERSION_STRING_PRE}") +string(REGEX REPLACE "${AU_VERSION_STRING_REGEX}" "\\2" + AU_VERSION_MINOR "${AU_VERSION_STRING_PRE}") +string(REGEX REPLACE "${AU_VERSION_STRING_REGEX}" "\\3" + AU_VERSION_PATCH "${AU_VERSION_STRING_PRE}") +string(REGEX REPLACE "${AU_VERSION_STRING_REGEX}" "\\5" + AU_VERSION_PRERELEASE "${AU_VERSION_STRING_PRE}") +endfunction() diff --git a/CMakeLists.txt b/CMakeLists.txt index f49a563..3d37a9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,103 +1,259 @@ -##Copyright (C) 2023, Advanced Micro Devices, Inc.## - -CMAKE_MINIMUM_REQUIRED(VERSION 3.15) -PROJECT (aoclutils) -IF(NOT CMAKE_BUILD_TYPE) - SET(CMAKE_BUILD_TYPE "Release" CACHE STRING - "Choose the type of build, options are: Debug Release" - FORCE) -ENDIF() - -# ADDING INCLUDE DIRECTORY -INCLUDE_DIRECTORIES(INCLUDE) - -# SPECIFY THE C STANDARD -SET(CMAKE_C_STANDARD 11) -SET(CMAKE_CXX_STANDARD 17) -SET(CMAKE_C_STANDARD_REQUIRED TRUE) -SET(CMAKE_CXX_STANDARD_REQUIRED TRUE) - -IF(UNIX) -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11 -Wall -Werror -Wpedantic") -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -Wall -Werror -Wpedantic") -ELSEIF(WIN32) -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /std:c11 -Wall -Wpedantic") -# Disable C++98 compatibility warnings. -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++17 -Wall -Wpedantic -Wno-c++98-compat -Wno-c++98-compat-pedantic") -# Prefix all shared libraries with 'lib'. -SET(CMAKE_SHARED_LIBRARY_PREFIX "lib") -# Prefix all static libraries with 'lib'. -SET(CMAKE_STATIC_LIBRARY_PREFIX "lib") -# Export all symbols. -SET(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) -ENDIF() - -SET(AOCL_RELEASE_VERSION "4.2.0") - -STRING(TIMESTAMP AOCL_UTILS_RELEASE_VERSION_STRING "AOCL-Utils ${AOCL_RELEASE_VERSION} Build %Y%m%d") - -SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") - -# CONTROL WHERE THE STATIC AND SHARED LIBRARIES ARE BUILT SO THAT ON WINDOWS -# WE DON'T NEED TO TINKER WITH THE PATH TO RUN THE EXECUTABLE -SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") -SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") -SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}") - -SET(CMAKE_INSTALL_LIBDIR "lib") - -OPTION(ALCI_DOCS "ENABLE DOCUMENTATION" ON) -OPTION(ALCI_DOXYGEN_DOC "ENABLE DOXYGEN DOCUMENTATION" OFF) - -IF (NOT DEFINED BUILD_SHARED_LIBS) -OPTION(BUILD_SHARED_LIBS "Build shared library" ON) -ENDIF() - -SET(CMAKE_DEBUG_POSTFIX _DEBUG) - -ADD_SUBDIRECTORY(lib) - -IF (ALCI_DOCS) - if (ALCI_DOXYGEN_DOC) - find_package(Doxygen 1.9.6) - set(W_DIR "${CMAKE_CURRENT_SOURCE_DIR}/docs/doxygen") - if(NOT (DOXYGEN_FOUND)) - message(STATUS "Doxygen not found please install doxygen and try again.") +# +# Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# We use the GoogleTest module if it is available (only in CMake 3.9+) +cmake_minimum_required(VERSION 3.22 FATAL_ERROR) + +# CMake extensions include directory +set(CMAKE_MODULE_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/CMake" + # Add the default path + ${CMAKE_MODULE_PATH} + ) + +# Export to CMakePresets.json, which is used by various IDE, +# easy integration on any IDE using LSP (Language Server Protocol) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# +# Determine versions and its components +# +include(au_version) + +file (STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/version.txt AU_VERSION_FROM_FILE) +au_extract_version_details("AU_VERSION" "${AU_VERSION_FROM_FILE}") + +set(AU_VERSION_STRING "${AU_VERSION_MAJOR}.${AU_VERSION_MINOR}.${AU_VERSION_PATCH}") +if(AU_VERSION_SUFFIX) + set(AU_VERSION_STRING "${AU_VERSION_STRING}.${AU_VERSION_SUFFIX}${AU_VERSION_SUFFIX_EXTRA}") +endif() + + +set(PACKAGE "libau") +set(PACKAGE_NAME "au") +set(PACKAGE_STRING "${PACKAGE_NAME} ${AU_VERSION_STRING}") +set(PACKAGE_TARNAME "${PACKAGE_NAME}-${AU_VERSION_STRING}") +set(PACKAGE_BUGREPORT "aocl@amd.com") +set(PACKAGE_URL "https://developer.amd.com/aocl/") +set(PACKAGE_VERSION "${AU_VERSION_STRING}") + +set(PROJECT_FULL_NAME "AOCL Utilities Library") +set(PROJECT_NAME "AOCL Library") +message("version " ${AU_VERSION_STRING}) +project(${PACKAGE_NAME} VERSION ${AU_VERSION_STRING} LANGUAGES CXX C ASM) +# +# Set language features +# Require C++-20 +set(CMAKE_CXX_STANDARD ${AU_CXX_STANDARD}) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(AU_COMPILER_IS_GNU 0) +set(AU_COMPILER_IS_CLANG 0) +set(AU_COMPILER_IS_MSVC 0) +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + # require at least gcc 8 + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8) + message(FATAL_ERROR "GCC version must be at least 8!") + else() + set(AU_COMPILER_IS_GNU 1) + endif() +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # require at least clang 12 + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 12.0) + message(FATAL_ERROR "Clang version must be at least 12.0!") else() - execute_process(COMMAND ${DOXYGEN_EXECUTABLE} Doxyfile - WORKING_DIRECTORY ${W_DIR} - COMMAND_ECHO STDOUT) + set(AU_COMPILER_IS_CLANG 1) endif() - if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/docs/doxygen/html/index.html) - message(STATUS "Documentation generated successfully, to view documentation open docs/doxygen/html/index.html") +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + message("MSVC version: " ${CMAKE_CXX_COMPILER_VERSION}) + # require at least MSVC 19.29 + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.29) + message(FATAL_ERROR "MSVC version must be at least 19.29!") else() - message(STATUS "Document generation failed.") + set(AU_COMPILER_IS_MSVC 1) + endif() + +else() + message(WARNING "Unsupported compiler! Compilation has + only been tested with above versions.") +endif() + +if( NOT CMAKE_BUILD_TYPE ) + set(CMAKE_BUILD_TYPE "Release" CACHE STRING + "Default build type: Release" FORCE ) +endif() + +if(NOT CMAKE_CXX_CLANG_TIDY) + find_program(CLANG_TIDY "clang-tidy") + if(NOT ${CLANG_TIDY} MATCHES "CLANG_TIDY-NOTFOUND") + if (MSVC) + set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY};--extra-arg=-EHsc") + else() + set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY}") endif() endif() -ENDIF() - -IF (ALCI_BENCH) - IF (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/BENCHMARK) - MESSAGE(FATAL_ERROR "BENCHMARKS NOT SUPPORTED") - ENDIF() - - ENABLE_TESTING() - ADD_SUBDIRECTORY(TEST/BENCHMARK) -ENDIF() - -# Add library install path -IF (BUILD_SHARED_LIBS) - INSTALL(TARGETS - aoclutils - aoclutils_static) -ELSE() - INSTALL(TARGETS - aoclutils_static) -ENDIF() - -INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/include/alci - TYPE INCLUDE - ) - -# Add library version in file. -FILE(WRITE ${CMAKE_BINARY_DIR}/version.h ${AOCL_UTILS_RELEASE_VERSION_STRING}) +endif() + +include(TestBigEndian) +test_big_endian(AU_TAGET_TEST_BIG_ENDIAN) +if(AU_TARGET_TEST_BIG_ENDIAN) +set(AU_TARGET_IS_BIG_ENDIAN TRUE) +set(AU_TARGET_IS_LITTLE_ENDIAN FALSE) +else() +set(AU_TARGET_IS_BIG_ENDIAN FALSE) +set(AU_TARGET_IS_LITTLE_ENDIAN TRUE) +endif() + +include(au_options) +add_compile_definitions(PROJECT_SOURCE_DIR="${PROJECT_SOURCE_DIR}") +add_compile_definitions(PROJECT_BUILD_DIR="${PROJECT_BINARY_DIR}") + +if(MSVC) + include(au_compiler_msvc) +else() + include(au_compiler_unix) +endif() +if(AU_ENABLE_CODE_COVERAGE) + add_compile_options(-O0 -fprofile-arcs -ftest-coverage) + add_link_options(-lgcov --coverage) +endif() +if (AU_BUILD_WITH_ASAN) + add_compile_options(-fsanitize=address) + add_link_options(-fsanitize=address) +endif() +# Fetch googletest if "testing" is enabled +if (AU_BUILD_TESTS) + enable_testing() + include(au_find_gtest) + include(au_unit_tests) +endif() + +option(INSTALL_GTEST OFF) + +if (AU_BUILD_EXAMPLES) + include(au_examples) +endif() + +include(au_variables) +include(au_git_hash) +include(au_functions) +include(au_helpers) + +if(NOT AU_BUILD_SHARED_LIBS AND NOT AU_BUILD_STATIC_LIBS) + # nothing to build raise warning and exit + message(WARNING "Nothing to build. Please set AU_BUILD_SHARED_LIBS and/or AU_BUILD_STATIC_LIBS to ON") + return() +endif() +# Config.h generation +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Library/config.h.in" "${AU_CONFIG_OUTPUT_FILE}" @ONLY) + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Library/version.cc.in" "${AU_VERSION_OUTPUT_FILE}" @ONLY) + +#include_directories("${AU_CONFIG_DIR}") +set(AU_INCLUDE_DIRS + ${PROJECT_SOURCE_DIR}/SDK/Include + ${PROJECT_SOURCE_DIR}/Library/Private + ${AU_CONFIG_DIR} +) + +include(au_lib) + +au_add_interface(sdk__include + PUBLIC +) +set_target_properties(sdk__include + PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/SDK/Include" +) + + +add_subdirectory(Library) + +if (AU_BUILD_TESTS) + add_subdirectory(Tests) +endif() +if (AU_BUILD_DOCS) + add_subdirectory(docs) +endif() + +if (AU_BUILD_EXAMPLES) + add_subdirectory(SDK/Examples) +endif() + +configure_file( + ${PROJECT_SOURCE_DIR}/CMake/aocl-utils.pc.in + ${PROJECT_BINARY_DIR}/aocl-utils.pc + @ONLY +) +# +# Print a banner if verbosity is enabled +# +if(AU_CMAKE_VERBOSE AND TRUE) + message(STATUS "Project : ${PROJECT_FULL_NAME}") + message(STATUS " Description : ${AU_DESCRIPTION}") + message(STATUS " Version : ${AU_VERSION_STRING} (${AU_VERSION_FULL})") + message(STATUS " Build Type : ${CMAKE_BUILD_TYPE}") + if (AU_BUILD_EXAMPLES) + message(STATUS " Examples : " "Enabled") + else() + message(STATUS " Examples : " "Off") + endif() + + if (AU_BUILD_TESTS) + message(STATUS " Tests : " "Enabled") + else() + message(STATUS " Tests : " "Off") + endif() + + if (AU_BUILD_WITH_ASAN) + message(STATUS " ASAN : " "Enabled") + else() + message(STATUS " ASAN : " "Disabled") + endif() + + if (AU_BUILD_DOCS) + message(STATUS " Docs : " "Enabled") + else() + message(STATUS " Docs : " "Off") + endif() + if (AU_ENABLE_ASSERTIONS) + message(STATUS " Assertions : " "Enabled") + else() + message(STATUS " Assertions : " "Disabled") + endif() + if (AU_ENABLE_OLD_API) + message(STATUS " Deprecated APIs Warning : " "Disabled") + else() + message(STATUS " Deprecated APIs Warning : Enabled") + endif() + + message(STATUS " CMAKE_INSTALL_PREFIX : " ${CMAKE_INSTALL_PREFIX}) + message(STATUS " CMAKE_GENERATOR : " ${CMAKE_GENERATOR}) + message(STATUS " CMAKE_C_COMPILER_ID : " ${CMAKE_C_COMPILER_ID}) + message(STATUS " CMAKE_CXX_COMPILER_ID: " ${CMAKE_CXX_COMPILER_ID}) +endif() + +include(au_install) diff --git a/CPUID_API_STACK.png b/CPUID_API_STACK.png new file mode 100644 index 0000000..c803fbf Binary files /dev/null and b/CPUID_API_STACK.png differ diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 0a66941..0000000 --- a/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2023, Advanced Micro Devices, Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Library/CMakeLists.txt b/Library/CMakeLists.txt new file mode 100644 index 0000000..6c1976c --- /dev/null +++ b/Library/CMakeLists.txt @@ -0,0 +1,129 @@ +# +# Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +#set(AU_MODULE "core") +au_module("core") + +if (MSVC) + add_compile_options(-W4 /Za /DLL) +else() + add_compile_options(-Wall -Weffc++ -pedantic -fPIC) +endif() + +set(LOGGER_SRC_FILES + Logger.cc + LoggerFactory.cc +) + +set(BASE64_SRC_FILES + Base64/Base64.cc + Base64/Base64Encoder.cc + Base64/Base64Decoder.cc +) + +set(MEMORY_SRC_FILES + Memory/BufferView.cc +) + +set(MESSAGE_SRC_FILES +) + +set(EVENT_SRC_FILES +) + +set(CAPI_SRC_FILES + #Capi/base64.cc + Capi/environ.cc + Capi/threadpinning.cc + ) + +set(AVX2_FILES + Base64/transform_avx2.cc +) + +set_source_files_properties( + ${AVX2_FILES} + PROPERTIES + COMPILE_FLAGS "-mavx2" +) + +set(CORE_SRC_FILES + #Core/Buffer.cc + Core/Status.cc + Core/GenericError.cc + Core/SourceLocation.cc + Core/StatusOr.cc + Core/Environ.cc + Core/BitMap.cc + Core/ThreadPinningImpl.cc + Core/ThreadPinning.cc + #Core/DynamicLoader.cc + #${BASE64_SRC_FILES} + # ${LOGGER_SRC_FILES} + #${MEMORY_SRC_FILES} + # ${MESSAGE_SRC_FILES} + # ${EVENT_SRC_FILES} + ${CAPI_SRC_FILES} + #${AVX2_FILES} +) + +au_cc_library(core +PRIVATE +SOURCES + ${CORE_SRC_FILES} + +HEADERS + Core/ThreadPinningImpl.hh +USING + af::sdk::include +) + + +au_module("aoclutils") +au_cc_library(aoclutils + PUBLIC + SOURCES + ${CORE_SRC_FILES} + HEADERS + Core/ThreadPinningImpl.hh + USING + af::sdk::include +) + +if(AU_BUILD_TESTS) + add_subdirectory(Tests) +endif() + +set(AU_SUBMODULE_DIRS + Cpuid + #Base64 + #Provider +) + +foreach(__moddir ${AU_SUBMODULE_DIRS}) + add_subdirectory(${__moddir}) +endforeach() diff --git a/Library/Capi/.clang-tidy b/Library/Capi/.clang-tidy new file mode 100644 index 0000000..ae204c1 --- /dev/null +++ b/Library/Capi/.clang-tidy @@ -0,0 +1,7 @@ +# File: project/external/.clang-tidy + +# Disable all checks in this folder. +# +Checks: '-*,misc-definitions-in-headers' +CheckOptions: + {HeaderFileExtensions: "x" } diff --git a/Library/Capi/cpuid.cc b/Library/Capi/cpuid.cc new file mode 100644 index 0000000..c8f81b3 --- /dev/null +++ b/Library/Capi/cpuid.cc @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/Cpuid/Cpuid.hh" +#include "Au/Assert.hh" +#include "Au/Cpuid/X86Cpu.hh" + +#include "Capi/au/cpuid/cpuid.h" +#include "Capi/au/macros.h" + +AUD_EXTERN_C_BEGIN + +using namespace Au; + +AUD_API_EXPORT +bool +au_cpuid_is_amd(au_cpu_num_t cpu_num) +{ + X86Cpu cpu{ cpu_num }; + + return cpu.isAMD(); +} +AUD_API_EXPORT +bool +alci_is_amd(au_cpu_num_t cpu_num) +{ + return au_cpuid_is_amd(cpu_num); +} + +AUD_API_EXPORT +void +au_cpuid_get_vendor(au_cpu_num_t cpu_num, char* vend_info, size_t size) +{ + X86Cpu cpu{ cpu_num }; + VendorInfo v_info = cpu.getVendorInfo(); + std::ostringstream ss; + ss << static_cast(v_info.m_mfg) << "\n" + << static_cast(v_info.m_family) << "\n" + << v_info.m_model << "\n" + << v_info.m_stepping << "\n" + << static_cast(v_info.m_uarch) << "\n"; + + AUD_ASSERT(size >= ss.str().size(), "Buffer too small"); +#if defined(AU_TARGET_OS_IS_WINDOWS) + strncpy(vend_info, (ss.str()).c_str(), fmin(ss.str().size(), size)); +#else + strncpy(vend_info, (ss.str()).c_str(), std::min(ss.str().size(), size)); +#endif +} + +AUD_API_EXPORT +au_error_t +alci_cpu_get_vendor(au_cpu_num_t cpu_num, char* arr, size_t size) +{ + au_cpuid_get_vendor(cpu_num, arr, size); + return 1; +} + +AUD_API_EXPORT +bool +au_cpuid_arch_is_zen(au_cpu_num_t cpu_num) +{ + X86Cpu cpu{ cpu_num }; + return cpu.isUarch(EUarch::Zen); +} + +AUD_API_EXPORT +bool +alci_arch_is_zen(au_cpu_num_t cpu_num) +{ + return au_cpuid_arch_is_zen(cpu_num); +} + +AUD_API_EXPORT +bool +au_cpuid_arch_is_zenplus(au_cpu_num_t cpu_num) +{ + X86Cpu cpu{ cpu_num }; + return cpu.isUarch(EUarch::ZenPlus); +} + +AUD_API_EXPORT +bool +au_cpuid_arch_is_zen2(au_cpu_num_t cpu_num) +{ + X86Cpu cpu{ cpu_num }; + return cpu.isUarch(EUarch::Zen2); +} + +AUD_API_EXPORT +bool +alci_arch_is_zen2(au_cpu_num_t cpu_num) +{ + return au_cpuid_arch_is_zen2(cpu_num); +} + +AUD_API_EXPORT +bool +au_cpuid_arch_is_zen3(au_cpu_num_t cpu_num) +{ + X86Cpu cpu{ cpu_num }; + return cpu.isUarch(EUarch::Zen3); +} + +AUD_API_EXPORT +bool +alci_arch_is_zen3(au_cpu_num_t cpu_num) +{ + return au_cpuid_arch_is_zen3(cpu_num); +} + +AUD_API_EXPORT +bool +au_cpuid_arch_is_zen4(au_cpu_num_t cpu_num) +{ + X86Cpu cpu{ cpu_num }; + return cpu.isUarch(EUarch::Zen4); +} + +AUD_API_EXPORT +bool +alci_arch_is_zen4(au_cpu_num_t cpu_num) +{ + return au_cpuid_arch_is_zen4(cpu_num); +} + +AUD_API_EXPORT +bool +alci_arch_is_zen5(au_cpu_num_t cpu_num) +{ + return au_cpuid_arch_is_zen5(cpu_num); +} + +AUD_API_EXPORT +bool +au_cpuid_arch_is_zen5(au_cpu_num_t cpu_num) +{ + X86Cpu cpu{ cpu_num }; + return cpu.isUarch(EUarch::Zen5); +} + +AUD_API_EXPORT +bool* +au_cpuid_has_flag(au_cpu_num_t cpu_num, + const char* const flag_array[], + int count) +{ + AUD_ASSERT(count > 0, "No flags to check"); + if (count == 0) + return nullptr; + + std::stringstream ss; + std::vector flag_names(flag_array, flag_array + count); + ss << flag_names; + AUD_ASSERT(flag_names.size() > 1, "The flags list is empty"); + if (flag_names.size() == 1) + return nullptr; + + X86Cpu cpu{ cpu_num }; + String token; + int index = 0; + // Use malloc to allocate memory, as it is used in C API. and will be freed + // using free in a cprogram. + bool* result = (bool*)malloc(count * sizeof(bool)); + AUD_ASSERT(result, "Memory allocation failed"); + if (!result) + return nullptr; + + while (std::getline(ss, token, ':')) { + au_cpu_flag_t flag = stoi(token); + AUD_ASSERT(flag > static_cast(ECpuidFlag::Min) + && flag < static_cast(ECpuidFlag::Max), + "Flag not supported"); + if (flag < static_cast(ECpuidFlag::Min) + || flag > static_cast(ECpuidFlag::Max)) + continue; + auto cpuid_flag = static_cast(flag); + result[index++] = cpu.hasFlag(cpuid_flag); + } + return result; +} + +AUD_API_EXPORT +bool +au_cpuid_has_flags(au_cpu_num_t cpu_num, + const char* const flag_array[], + int count) +{ + AUD_ASSERT(count > 0, "No flags to check"); + if (count == 0) + return false; + + std::stringstream ss; + std::vector flag_names(flag_array, flag_array + count); + ss << flag_names; + AUD_ASSERT(flag_names.size() > 1, "The flags list is empty"); + if (flag_names.size() == 1) + return false; + + X86Cpu cpu{ cpu_num }; + String token; + bool result = 1; + + while (std::getline(ss, token, ':')) { + au_cpu_flag_t flag = stoi(token); + AUD_ASSERT(flag > static_cast(ECpuidFlag::Min) + && flag < static_cast(ECpuidFlag::Max), + "Flag not supported"); + if (flag < static_cast(ECpuidFlag::Min) + || flag > static_cast(ECpuidFlag::Max)) + continue; + auto cpuid_flag = static_cast(flag); + result &= cpu.hasFlag(cpuid_flag); + } + return result; +} + +AUD_API_EXPORT +bool +alci_cpu_has_flag(au_cpu_num_t cpu_num, au_cpu_flag_t flag) +{ + X86Cpu cpu{ cpu_num }; + return cpu.hasFlag(static_cast(flag)); +} + +AUD_API_EXPORT +bool +au_cpuid_is_error(au_error_t err) +{ + AUD_ASSERT(err >= 0, "Invalid error code"); // Never be negative. + if (static_cast(err)) + return true; + return false; +} +AUD_EXTERN_C_END diff --git a/Library/Capi/environ.cc b/Library/Capi/environ.cc new file mode 100644 index 0000000..60c1aab --- /dev/null +++ b/Library/Capi/environ.cc @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/Environ.hh" +#include "Au/Au.hh" + +#include "Capi/au/environ.h" + +#include +#include +#include +#include + +using namespace Au; + +static inline void +str_tolower(String& s) +{ + std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { + return std::tolower(c); + }); +} + +AUD_EXTERN_C_BEGIN + +AUD_API_EXPORT const char* +au_env_get(const char* name) +{ + if (!name) + return nullptr; + + StringView sv{ name }; + + auto val = Env::get(sv); + + return val.data(); +} + +AUD_API_EXPORT void +au_env_unset(const char* name) +{ + if (!name) + return; + Env::unset(name); +} + +AUD_API_EXPORT const char* +au_env_set(const char* name, const char* val) +{ + if (!name || !val) + return nullptr; + + String n{ name }; + String v{ val }; + + Env::set(n, v); + + return name; +} + +AUD_API_EXPORT bool +au_env_is_enabled(const char* cc) +{ + if (!cc) + return false; + + String sv{ + Env::get(cc).data() + }; /* returned string from Env::get() is a const */ + + str_tolower(sv); + + if (sv == String("yes") || sv == String("on") || sv == String("1") + || sv == String("true")) + return true; + + return false; +} + +AUD_API_EXPORT bool +au_env_is_set(const char* cc) +{ + if (!cc) + return false; + + StringView sv{ cc }; + auto val = Env::get(sv); + + if (val.length() == 0) + return false; + + return true; +} + +AUD_EXTERN_C_END diff --git a/Library/Capi/threadpinning.cc b/Library/Capi/threadpinning.cc new file mode 100644 index 0000000..9616107 --- /dev/null +++ b/Library/Capi/threadpinning.cc @@ -0,0 +1,104 @@ +/* + * Copyright(c) 2024 Advanced Micro Devices, Inc.All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this softwareand 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 noticeand 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 "Au/ThreadPinning.hh" +#include "Au/Assert.hh" +#include "Capi/au/macros.h" +#include "Capi/au/threadpinning.h" +#include + +AUD_EXTERN_C_BEGIN + +using namespace Au; + +AUD_API_EXPORT +void +au_pin_threads_core(pthread_t* threadList, size_t threadListSize) +{ + AUD_ASSERT(threadList != nullptr, "Thread list is null"); + AUD_ASSERT(threadListSize > 0, "Thread list size is 0"); + + ThreadPinning tp; + std::vector threadListVec; + for (size_t i = 0; i < threadListSize; i++) { + threadListVec.push_back(threadList[i]); + } + tp.pinThreads(threadListVec, 1); // core +} + +AUD_API_EXPORT +void +au_pin_threads_logical(pthread_t* threadList, size_t threadListSize) +{ + AUD_ASSERT(threadList != nullptr, "Thread list is null"); + AUD_ASSERT(threadListSize > 0, "Thread list size is 0"); + + ThreadPinning tp; + std::vector threadListVec; + for (size_t i = 0; i < threadListSize; i++) { + threadListVec.push_back(threadList[i]); + } + tp.pinThreads(threadListVec, 2); // logical +} + +AUD_API_EXPORT +void +au_pin_threads_spread(pthread_t* threadList, size_t threadListSize) +{ + AUD_ASSERT(threadList != nullptr, "Thread list is null"); + AUD_ASSERT(threadListSize > 0, "Thread list size is 0"); + + ThreadPinning tp; + std::vector threadListVec; + for (size_t i = 0; i < threadListSize; i++) { + threadListVec.push_back(threadList[i]); + } + tp.pinThreads(threadListVec, 0); // spread +} + +AUD_API_EXPORT +void +au_pin_threads_custom(pthread_t* threadList, + size_t threadListSize, + int* affinityVector, + size_t affinityVectorSize) +{ + AUD_ASSERT(threadList != nullptr, "Thread list is null"); + AUD_ASSERT(threadListSize > 0, "Thread list size is 0"); + AUD_ASSERT(affinityVector != nullptr, "Affinity vector is null"); + AUD_ASSERT(affinityVectorSize > 0, "Affinity vector size is 0"); + AUD_ASSERT(affinityVectorSize == threadListSize, + "Affinity vector size is not equal to thread list size"); + + ThreadPinning tp; + std::vector threadListVec; + for (size_t i = 0; i < threadListSize; i++) { + threadListVec.push_back(threadList[i]); + } + + std::vector affinityVectorVec; + for (size_t i = 0; i < affinityVectorSize; i++) { + affinityVectorVec.push_back(affinityVector[i]); + } + tp.pinThreads(threadListVec, affinityVectorVec); +} +AUD_EXTERN_C_END diff --git a/Library/Core/.clang-tidy b/Library/Core/.clang-tidy new file mode 100644 index 0000000..ae204c1 --- /dev/null +++ b/Library/Core/.clang-tidy @@ -0,0 +1,7 @@ +# File: project/external/.clang-tidy + +# Disable all checks in this folder. +# +Checks: '-*,misc-definitions-in-headers' +CheckOptions: + {HeaderFileExtensions: "x" } diff --git a/Library/Core/BitMap.cc b/Library/Core/BitMap.cc new file mode 100644 index 0000000..d39f1f0 --- /dev/null +++ b/Library/Core/BitMap.cc @@ -0,0 +1,379 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/BitMap.hh" +#include "Au/Assert.hh" +#include "Au/Au.hh" +#include "Au/Exception.hh" + +#include +#include + +namespace Au { + +enum class Operation +{ + eOpSet, + eOpClear, + eOpFlip +}; + +template +static inline void +OpOr(T& x, T const& y) +{ + x |= y; +} + +template +static inline void +OpClear(T& x, T const& y) +{ + x &= ~y; +} + +template +static inline bool +OpEq(T const& x, T const& y) +{ + AUD_ASSERT_NOT_IMPLEMENTED(); + // x &= ~y; + return false; +} + +template +static inline void +OpNot(T& x, T const& y) +{ + x = ~x; +} + +template +static inline void +OpXor(T& x, T const& y) +{ + x ^= y; +} + +template +static auto +getOp(Operation op = Operation::eOpSet) -> std::function +{ + if (op == Operation::eOpClear) + return OpClear; + + if (op == Operation::eOpFlip) + return OpXor; + + return OpOr; +} + +Uint32 +BitMap::size() const +{ + return m_size; +} + +/** + * NOTE: + * Assumption last word which is partially used has other bits set to 0 + */ +Uint32 +BitMap::count() const +{ + auto cnt = 0; + + std::lock_guard lock(m_lock); + for (auto& word : m_bit_words) { +#if defined(__GNUG__) || defined(__clang__) + cnt += __builtin_popcountll(word); +#else + cnt += __popcnt64(word); +#endif + } + return cnt; +} + +void +BitMap::doSetOrClear(bool doclear) +{ + auto remaining_bits = m_size; + auto mask = doclear ? ~getAllSetMask() : getAllSetMask(); + auto op = + getOp(doclear ? Operation::eOpClear : Operation::eOpSet); + + for (auto& i : m_bit_words) { + if (remaining_bits < bitsPerWord()) { + mask &= (1ULL << remaining_bits) - 1; + } + + /* Moving critical section to its own block */ + if (true) { + std::lock_guard lock(m_lock); + op(i, mask); + } + + remaining_bits -= bitsPerWord(); + } +} + +void +BitMap::doSetOrClear(BitMap const& other, bool doclear) +{ + auto words = other.m_nwords; + auto sz = other.size(); + + if (size() < sz) { + words = m_nwords; + sz = size(); + } + + auto op = + getOp(doclear ? Operation::eOpClear : Operation::eOpSet); + + std::lock_guard lock(m_lock); + for (auto i = 0U; i < words - 1; i++) { + op(m_bit_words[i], other.m_bit_words[i]); + + sz -= bitsPerWord(); + } + + AUD_ASSERT(sz < bitsPerWord(), "Unfavorable condition"); + + /* Last word must be dealt separately */ + auto [idx, pos] = getWordIdxPair(sz); + auto data = getNBitMask(pos) & other.m_bit_words[idx]; + + op(m_bit_words[idx], data); +} + +void +BitMap::set() +{ + doSetOrClear(false); +} + +void +BitMap::set(Uint32 bitpos) +{ + AUD_ASSERT(isValidPos(bitpos), "Invalid Size"); + + if (isValidPos(bitpos)) { + std::lock_guard lock(m_lock); + + auto [idx, pos] = getWordIdxPair(bitpos); + m_bit_words[idx] |= 1 << pos; + } +} + +void +BitMap::set(BitMap const& other) +{ + doSetOrClear(other, false); +} + +void +BitMap::clear() +{ + std::lock_guard lock(m_lock); + + /* memset() in C++ :) */ + std::fill(m_bit_words.begin(), m_bit_words.end(), 0); +} + +void +BitMap::clear(Uint32 bitpos) +{ + AUD_ASSERT(isValidPos(bitpos), "Invalid Size"); + + if (isValidPos(bitpos)) { + auto [idx, pos] = getWordIdxPair(bitpos); + + std::lock_guard lock(m_lock); + m_bit_words[idx] &= ~(1 << pos); + } +} + +void +BitMap::clear(BitMap const& other) +{ + doSetOrClear(other, true); +} + +void +BitMap::flip() +{ /* FIXME: Add at a later stage */ +} + +void +BitMap::flip(Uint32 bitpos) +{ + /* FIXME: Add at a later stage */ +} + +void +BitMap::flip(BitMap const& other) +{ + /* FIXME: Add at a later stage */ +} + +bool +BitMap::isSet(Uint32 bitpos) const +{ + AUD_ASSERT(isValidPos(bitpos), "Invalid Size"); + + if (bitpos <= m_size) { + auto [idx, pos] = getWordIdxPair(bitpos); + + std::lock_guard lock(m_lock); + return m_bit_words[idx] & (1 << pos); + } + + return false; +} + +bool +BitMap::isClear(Uint32 bitpos) const +{ + return !isSet(bitpos); +} + +bool +BitMap::isZero() const +{ + auto iszero = true; + + std::lock_guard lock(m_lock); + for (auto word : m_bit_words) { + if (word != 0) { + iszero = false; + break; + } + } + + return iszero; +} + +bool +BitMap::isFull() const +{ + return count() == size(); +} + +bool +BitMap::isSubset(BitMap const& other) +{ + AUD_ASSERT_NOT_IMPLEMENTED(); + return false; +} + +/* Operators */ +BitMap& +BitMap::operator|(BitMap const& other) +{ + doSetOrClear(other, true); + + return *this; +} + +BitMap& +BitMap::operator&(BitMap const& other) +{ + /* FIXME: */ + AUD_ASSERT_NOT_IMPLEMENTED(); + return *this; +} + +BitMap& +BitMap::operator^(BitMap const& other) +{ + /* FIXME: */ + AUD_ASSERT_NOT_IMPLEMENTED(); + return *this; +} + +bool +BitMap::operator==(BitMap const& other) const +{ + /* FIXME: */ + AUD_ASSERT_NOT_IMPLEMENTED(); + return false; +} + +BitMap& +BitMap::operator!() +{ + /* FIXME: */ + AUD_ASSERT_NOT_IMPLEMENTED(); + return *this; +} + +/* Iterator trait */ +BitMap& +BitMap::begin() +{ + /* FIXME: */ + AUD_ASSERT_NOT_IMPLEMENTED(); + return *this; +} + +BitMap& +BitMap::end() +{ + /* FIXME: */ + AUD_ASSERT_NOT_IMPLEMENTED(); + return *this; +} + +#if 0 +BitMap& +operator=(BitMap&& src) +{ + if (this != &src) { + std::lock_guard lock(m_lock); + std::move(m_bit_words, src.m_bit_words); + m_size = src.size(); + m_count = src.count(); + } + + return *this; +} +#endif + +BitMap::BitMap(Uint32 size) + : m_size{ size } + , m_nwords{ size / bitsPerWord() + 1 } + , m_bit_words{ std::vector(m_nwords) } + , m_lock{} +{ + AUD_ASSERT(size, "Invalid size for BitMap"); +} + +BitMap::~BitMap() {} + +} // namespace Au diff --git a/Library/Core/Environ.cc b/Library/Core/Environ.cc new file mode 100644 index 0000000..aa5952c --- /dev/null +++ b/Library/Core/Environ.cc @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2022-2022, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * FIXME: + * Research + * https://www.ncbi.nlm.nih.gov/IEB/ToolBox/CPP_DOC/lxr/source/include/corelib/ncbienv.hpp#0156 + * + */ +#include "Au/Environ.hh" +#include "Au/Assert.hh" +#include "Os/Env.hh" + +#include + +namespace Au { + +static Environ& +__getStaticUserEnv() +{ + static Environ gsUserEnv{}; + return gsUserEnv; +} + +static Environ& +__getStaticSystemEnv() +{ + static Environ gsSystem{}; + return gsSystem; +} + +Environ& +Env::getUserEnv() +{ + return __getStaticUserEnv(); +} + +Environ& +Env::getSystemEnv() +{ + return __getStaticSystemEnv(); +} + +StringView const +Env::get(StringView const& key) +{ + AUD_ASSERT(key.length() != 0, "Key is empty"); + + if (Env::getUserEnv().exists(key)) + return Env::getUserEnv().get(key); + + return Env::getSystemEnv().get(key); +} + +void +Env::set(String const& key, String const& val) +{ + AUD_ASSERT(key.length() != 0, "Key is empty"); + + Env::getUserEnv().set(key, val); +} + +void +Env::unset(String const& key) +{ + AUD_ASSERT(key.length() != 0, "Key is empty"); + + Env::getUserEnv().unset(key); +} + +void +Env::init(const char** envp) +{ + AUD_ASSERT(envp, "Key is empty"); + + Env::getUserEnv().init(envp); +} + +Environ::Environ() + : m_environ{} + , m_lock{} +{ + for (auto& i : Os::Env::getAll()) { + m_environ.emplace(i); + } +} + +StringView const +Environ::get(StringView const key) const +{ + AUD_ASSERT(key.length() != 0, "Key is empty"); + + if (exists(key)) { + return m_environ.at(std::move(String{ key })); + } + + return m_empty_string; +} + +void +Environ::set(String const& key, String const& val) +{ + AUD_ASSERT(key.length() != 0, "Key is empty"); + + if (exists(key)) { + /* FIXME: add this to log */ + // AUD_ASSERT(false, "Overrwriting existing key"); + } + + _set(key, val); +} + +void +Environ::unset(String const& key) +{ + AUD_ASSERT(key.length() != 0, "Key is empty"); + + if (exists(key)) { + m_environ.erase(key); + } +} + +bool +Environ::exists(StringView const& key) const +{ + AUD_ASSERT(key.length() != 0, "Key is empty"); + + std::lock_guard lock(m_lock); + + auto got = m_environ.find(key); + if (got == m_environ.end()) + return false; + + return true; +} + +void +Environ::_set(String const& key, String const& val) +{ + AUD_ASSERT(key.length() != 0, "Key is empty"); + //AUD_ASSERT(val.length() != 0, "Value of key/val pair is empty"); + + std::lock_guard lock(m_lock); + m_environ[key] = val; +} + +void +Environ::init(const char** envp) +{ + auto e = envp; + + m_environ.clear(); + + for (; e && *e; ++e) { + String s(*e); + if (*e == NULL) /* We reached end of list */ + break; + + auto keyval = Os::Env::split(s); + auto [key, val] = keyval; + AUD_ASSERT(key.length() != 0, String{ "Invalid Key: " + key }); + AUD_ASSERT(val.length() != 0, String{ "Value is empty for " + key }); + + _set(key, val); + } +} + +Environ::~Environ() = default; + +} // namespace Au diff --git a/Library/Core/GenericError.cc b/Library/Core/GenericError.cc new file mode 100644 index 0000000..f6a5284 --- /dev/null +++ b/Library/Core/GenericError.cc @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/Au.hh" +#include "Au/Error.hh" + +#include +#include +#include + +namespace Au { + +/** + * Some of the Error codes are similar but based on the + * application one makes more sense than other. + * Application developers are encouraged to use them accordingly. + */ +enum ErrorCode : ErrorCodeGeneric +{ + /* ErrorCode:eOk + * + * Though this does not signify an error, but a status + * that is a success. Application should always check + * for this before proceeding. + */ + eOk = 0, + eNone = eOk, + + /* ErrorCode:eUknown + * + * An error has occured but cannot be categorized under + * any of the other + */ + eUnknown = 1, + + /* ErrorCode:eInvalidArgument + * + * Argument passed to a function, or part of the configuration + * Should be used to indicate that the application cannot request + * for services as the configuration sent across is not valid + */ + eInvalidArgument = 2, + + /* ErrorCode:eNotFound + * + * Useful in a collection/file when searching + */ + eNotFound = 4, + + /* ErrorCode:eExists + * + * A plugin that already exists, but register is called again + * A file that to be created but an entry exits, etc + */ + eExists = 8, + + /* ErrorCode::eNotImplemented + * + * A feature, function, subsystem not yet implemented + */ + eNotImplemented = 16, + + /* ErrorCode::eNotAvailable + * + * A feature, function, sybsystem, or a device exists/implemented but + * not available for use + */ + eNotAvailable = 32, + + /* ErrorCode::eInternal + * + * Internal Error could be described by rest of the error code + */ + eInternal = 64, + + /* ErrorCode::eMaxDontUse + * + * Dont use, here to mark the largest error code + */ + eMaxDontUse = 128, +}; + +GenericError::GenericError() + : GenericError{ ErrorCode::eOk } +{ +} + +GenericError::GenericError(ErrorCodeGeneric ecode) + : ErrorBase{} +{ + m_error.field.base_error = ecode; +} + +String +GenericError::message() const +{ + + using ec = ErrorCode; + using ErrorMapT = std::unordered_map; + + static const ErrorMapT str_map = { + { ec::eOk, "All is Well !!" }, + { ec::eExists, "Already Exists" }, + { ec::eInternal, "Internal Error" }, + { ec::eInvalidArgument, "Invalid Argument" }, + { ec::eNotAvailable, "Not Available" }, + { ec::eNotFound, "Not Found" }, + { ec::eNotImplemented, "Not Implemented" }, + }; + + ErrorMapT::const_iterator it = str_map.find(getModuleError()); + + String s{}; + + if (it != str_map.end()) { + s = it->second; + } else { + s = std::string("Unknown Error: "); + } + + return s; +} + +IError const& +Aborted() +{ + static GenericError gr{ ErrorCode::eInternal }; + return gr; +} + +IError const& +NoError() +{ + static GenericError gr{ ErrorCode::eOk }; + return gr; +} + +IError const& +AlreadyExistsError() +{ + static GenericError gr{ ErrorCode::eExists }; + return gr; +} + +IError const& +InternalError() +{ + static GenericError gr{ ErrorCode::eInternal }; + return gr; +} + +IError const& +InvalidArgumentError() +{ + static GenericError gr{ ErrorCode::eInvalidArgument }; + return gr; +} + +IError const& +NotFoundError() +{ + static GenericError gr{ ErrorCode::eNotFound }; + return gr; +} + +IError const& +NotAvailableError() +{ + static GenericError gr{ ErrorCode::eNotAvailable }; + return gr; +} + +IError const& +NotImplementedError() +{ + static GenericError gr{ ErrorCode::eNotImplemented }; + return gr; +} + +IError const& +UnknownError() +{ + static GenericError gr{ ErrorCode::eUnknown }; + return gr; +} + +} // namespace Au diff --git a/Library/Core/SourceLocation.cc b/Library/Core/SourceLocation.cc new file mode 100644 index 0000000..68819c3 --- /dev/null +++ b/Library/Core/SourceLocation.cc @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2022-2022, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "Au/SourceLocation.hh" + +#include "filesystem" +#include "string" + +namespace Au { + +using string = std::string; +namespace fs = std::filesystem; + +String +SourceLocation::relativeFile() const +{ + auto file_str = String{ m_file }; + + // Full path of "SourceLocation.cc" file + String this_path{ __FILE__ }; + + // finding the two pointers through the mismatch() + std::pair p = + std::mismatch(file_str.begin(), file_str.end(), this_path.begin()); + + auto start = p.first - file_str.begin(); + + if (start > 0) + return file_str.substr(start, file_str.size()); + + return file_str; +} + +/** + * Return the, fully qualified name of the function. + */ +String +SourceLocation::qualifiedFunction() const +{ + if (m_pretty_function) + return m_pretty_function; + + return m_function; +} + +} // namespace Au diff --git a/Library/Core/Status.cc b/Library/Core/Status.cc new file mode 100644 index 0000000..eee786d --- /dev/null +++ b/Library/Core/Status.cc @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2022-2022, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "Au/Error.hh" +#include "Au/Status.hh" + +namespace Au { + +Status +StatusAlreadyExists(StringView msg) +{ + static auto& err = AlreadyExistsError(); + return Status{ err, msg }; +} + +Status +StatusInternalError(StringView msg) +{ + static auto& err = InternalError(); + return Status{ err, msg }; +} + +Status +StatusInvalidArgument(StringView msg) +{ + static auto& err = InvalidArgumentError(); + return Status{ err, msg }; +} + +Status +StatusNotFound(StringView msg) +{ + static auto& err = NotFoundError(); + return Status{ err, msg }; +} + +Status +StatusNotAvailable(StringView msg) +{ + static auto& err = NotAvailableError(); + return Status{ err, msg }; +} + +Status +StatusNotImplemented(StringView msg) +{ + static auto& err = NotImplementedError(); + return Status{ err, msg }; +} + +Status +StatusUnknown(StringView msg) +{ + static auto& err = UnknownError(); + return Status{ err, msg }; +} + +} // namespace Au diff --git a/Library/Core/StatusOr.cc b/Library/Core/StatusOr.cc new file mode 100644 index 0000000..cae5bda --- /dev/null +++ b/Library/Core/StatusOr.cc @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/StatusOr.hh" +#include "Au/Au.hh" + +namespace Au { + +} // namespace Au diff --git a/Library/Core/ThreadPinning.cc b/Library/Core/ThreadPinning.cc new file mode 100644 index 0000000..74e2ff8 --- /dev/null +++ b/Library/Core/ThreadPinning.cc @@ -0,0 +1,47 @@ +/* + * Copyright(c) 2024 Advanced Micro Devices, Inc.All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this softwareand 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 noticeand 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 "Au/ThreadPinning.hh" +#include "ThreadPinningImpl.hh" + +namespace Au { +ThreadPinning::ThreadPinning() + : m_pimpl{ new ThreadPinning::Impl{} } +{ +} + +ThreadPinning::~ThreadPinning() {} + +void +ThreadPinning::pinThreads(std::vector const& threadList, + int pinStrategyIndex) +{ + pImpl()->pinThreads(threadList, pinStrategyIndex); +} + +void +ThreadPinning::pinThreads(std::vector const& threadList, + std::vector const& processPinGroup) +{ + pImpl()->pinThreads(threadList, processPinGroup); +} + +} // namespace Au diff --git a/Library/Core/ThreadPinningImpl.cc b/Library/Core/ThreadPinningImpl.cc new file mode 100644 index 0000000..fd7e00f --- /dev/null +++ b/Library/Core/ThreadPinningImpl.cc @@ -0,0 +1,65 @@ +/* + * Copyright(c) 2024 Advanced Micro Devices, Inc.All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this softwareand 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 noticeand 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 "ThreadPinningImpl.hh" +#include "Au/Assert.hh" +namespace Au { + +void +ThreadPinning::Impl::pinThreads(std::vector threadList, + int pinStrategyIndex) +{ + AUD_ASSERT(threadList.size() > 0, "Thread list is empty"); + if (threadList.size() == 0) { + return; + } + AUD_ASSERT(pinStrategyIndex >= 0 && pinStrategyIndex < 3, + "Invalid pin strategy index"); + std::vector processPinGroup(threadList.size()); + if (threadList.size() == 0) { + return; + } + processPinGroup.reserve(threadList.size()); + // Get the processor group to pin the threads + getAffinityVector(processPinGroup, pinStrategyIndex); + // Pin the threads to the processor group in the processPinGroup + if (processPinGroup.size() == 0) { + return; + } + pinThreads(threadList, processPinGroup); +} + +void +ThreadPinning::Impl::pinThreads(std::vector threadList, + std::vector const& processPinGroup) +{ + AUD_ASSERT(threadList.size() > 0, "Thread list is empty"); + AUD_ASSERT(processPinGroup.size() > 0, "Processor group is empty"); + AUD_ASSERT(threadList.size() == processPinGroup.size(), + "Thread list and processor group size mismatch"); + if (threadList.size() == 0 || threadList.size() != processPinGroup.size()) { + return; + } + // Pin the threads to the processor group in the processPinGroup + setAffinity(threadList, processPinGroup); +} + +} // namespace Au diff --git a/Library/Core/ThreadPinningImpl.hh b/Library/Core/ThreadPinningImpl.hh new file mode 100644 index 0000000..95ee285 --- /dev/null +++ b/Library/Core/ThreadPinningImpl.hh @@ -0,0 +1,58 @@ +/* + * Copyright(c) 2024 Advanced Micro Devices, Inc.All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this softwareand 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 noticeand 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 "Au/ThreadPinning.hh" +#include "Au/ThreadPinning/ThreadPinning.hh" +#include + +namespace Au { +class ThreadPinning::Impl : public AffinityVector +{ + public: + /** + * @brief PinThreads + * + * @details Pin Threads to a specific processor group. + * + * @param[in] threadList ThreadIds to pin + * + * @param[in] pinStrategyIndex 0 - spread , 1 - Core, 2 - Logical + * Processor + * + * @return None + */ + void pinThreads(std::vector threadList, int pinStrategyIndex); + /** + * @brief pinThreads + * + * @details Pin Threads to a specific processor group. + * + * @param[in] threadList ThreadIds to pin + * + * @param[in] processPinGroup Processor Group to pin the threads + * + */ + void pinThreads(std::vector threadList, + std::vector const& processPinGroup); +}; +} // namespace Au diff --git a/Library/Cpuid/CMakeLists.txt b/Library/Cpuid/CMakeLists.txt new file mode 100644 index 0000000..02eeec2 --- /dev/null +++ b/Library/Cpuid/CMakeLists.txt @@ -0,0 +1,62 @@ +# +# Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +set(AU_MODULE "cpuid") + +set(CPUID_SRC_FILES + CacheInfo.cc + Cache.cc + Cpuid.cc + CpuidUtils.cc + X86RawData.cc + ../Capi/cpuid.cc + X86Cpu.cc +) +if(${AU_ENABLE_ASSERTIONS}) + au_cc_library(cpuid + PUBLIC + SOURCES + ${CPUID_SRC_FILES} + + HEADERS + X86RawData.hh + + DEPENDS + au::aoclutils + ) +else() + au_cc_library(cpuid + PUBLIC + SOURCES + ${CPUID_SRC_FILES} + + HEADERS + X86RawData.hh + ) +endif() + +#target_link_libraries(au_all PUBLIC af::cpuid) diff --git a/Library/Cpuid/Cache.cc b/Library/Cpuid/Cache.cc new file mode 100644 index 0000000..76783f1 --- /dev/null +++ b/Library/Cpuid/Cache.cc @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/Au.hh" + +#include "Au/Assert.hh" +#include "Au/Cpuid/CacheInfo.hh" + +#include +#include +#include + +namespace Au { + +using CacheLevel = cache_attr::ELevel; +using CacheType = cache_attr::EType; + +std::ostream& +operator<<(std::ostream& os, CacheLevel const& level) // NOLINT +{ + using Cl = CacheLevel; + // clang-format off + switch (level) { + case Cl::L1: os << "L1"; break; + case Cl::L2: os << "L2"; break; + case Cl::L3: os << "L3"; break; + case Cl::L4: os << "L4"; break; + default: os << "Unknown"; break; + } + // clang-format on + return os; +} + +std::ostream& +operator<<(std::ostream& os, CacheType const& type) // NOLINT +{ + using Ct = CacheType; + // clang-format off + switch (type) { + case Ct::ICache: os << "I$"; break; + case Ct::DCache: os << "D$"; break; + case Ct::Unified: os << "Unified Cache"; break; + default: os << "Unkown"; break; + } + // clang-format on + return os; +} + +} // namespace Au diff --git a/Library/Cpuid/CacheInfo.cc b/Library/Cpuid/CacheInfo.cc new file mode 100644 index 0000000..d189adf --- /dev/null +++ b/Library/Cpuid/CacheInfo.cc @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/Cpuid/CacheInfo.hh" +#include "Au/Assert.hh" +#include "Au/Misc.hh" /* for enum->int */ + +namespace Au { +/** + * TODO: Return error codes instead of assert in release builds + */ +CacheInfo::CacheInfo(CacheLevel level, CacheType type) + : m_level{ level } + , m_type{ type } +{ + AUD_ASSERT(*level > 0, "Level should be > 0"); + AUD_ASSERT(*type > 0, "Type should be > 0"); +} + +void +CacheInfo::setSize(Uint64 size) +{ + AUD_ASSERT(size != 0, "Size is 0"); + m_size = size; +} + +void +CacheInfo::setWay(Uint64 way_size) +{ + AUD_ASSERT(way_size != 0, "Way is 0"); + m_way = way_size; +} + +void +CacheInfo::setLane(Uint64 lane_size) +{ + AUD_ASSERT(lane_size != 0, "Lane is 0"); + m_lane = lane_size; +} + +void +CacheInfo::setType(CacheType type) +{ + AUD_ASSERT(*type > 0, "Type is Unknown"); + AUD_ASSERT(type < CacheType::Unknown, "Type is Unknown"); + m_type = type; +} +void +CacheInfo::setLevel(CacheLevel lvl) +{ + AUD_ASSERT(*lvl > 0, "Level is Unknown"); + AUD_ASSERT(lvl < CacheLevel::Unknown, "Level is Unknown"); + m_level = lvl; +} +void +CacheInfo::setSets(Uint64 sets) +{ + AUD_ASSERT(sets != 0, "Set is 0"); + m_set = sets; +} + +} // namespace Au diff --git a/Library/Cpuid/Cpuid.cc b/Library/Cpuid/Cpuid.cc new file mode 100644 index 0000000..de98324 --- /dev/null +++ b/Library/Cpuid/Cpuid.cc @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/Cpuid/Cpuid.hh" +#include "Au/Assert.hh" + +namespace Au { + +CpuInfo::CpuInfo(CpuNumT idx) + : m_logical_core_num{ idx } + , m_physical_core_num{ idx } +{ +#if !defined(AU_CPU_ARCH_X86) + AUD_ASSERT(false, "Not an x86 Cpu"); +#endif +} + +std::ostream& +operator<<(std::ostream& os, EGoverner const& gov) // NOLINT +{ + using G = EGoverner; + + switch (gov) { + // clang-format off + case G::ePerformance:os << "Performance";break; + case G::ePowersave:os << "Power Save";break; + case G::eUserspace:os << "User Defined";break; + case G::eOndemand:os << "On Demand";break; + case G::eUnknown: + default:os << "Unknown";break; + // clang-format on + } + + return os; +} + +} // namespace Au diff --git a/Library/Cpuid/CpuidUtils.cc b/Library/Cpuid/CpuidUtils.cc new file mode 100644 index 0000000..7cf0fb2 --- /dev/null +++ b/Library/Cpuid/CpuidUtils.cc @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/Cpuid/CpuidUtils.hh" +#include "Au/Misc.hh" +#include "Au/Config.h" +#include +#ifdef _WIN32 +#include +#endif +namespace Au { +ResponseT CpuidUtils::__raw_cpuid(RequestT& req) +{ + ResponseT resp; +#ifdef _WIN32 + int cpuInfo[4] = { -1 }; // Array to store the cpuid output + if (req.eax == 0x00000007 || (req.eax == 0x00000001 && req.ecx == 0x00000001)) { + __cpuidex(cpuInfo, req.eax, req.ecx); + } else { + __cpuid(cpuInfo, req.eax); + } + + resp.eax = cpuInfo[0]; + resp.ebx = cpuInfo[1]; + resp.ecx = cpuInfo[2]; + resp.edx = cpuInfo[3]; +#else + if (req.eax == 0x00000007 + || (req.eax == 0x00000001 && req.ecx == 0x00000001)) { + asm volatile( + "cpuid" + : "=a"(resp.eax), "=b"(resp.ebx), "=c"(resp.ecx), "=d"(resp.edx) + : "0"(req.eax), "2"(req.ecx)); + } else { + asm volatile( + "cpuid" + : "=a"(resp.eax), "=b"(resp.ebx), "=c"(resp.ecx), "=d"(resp.edx) + : "0"(req.eax)); + } +#endif + return resp; +} + +EVendor +CpuidUtils::getMfgInfo(ResponseT const& regs) +{ + if (regs.ebx == 0x68747541 && regs.ecx == 0x444d4163 + && regs.edx == 0x69746e65) { + return EVendor::Amd; + } + if (regs.ebx == 0x756e6547 && regs.ecx == 0x6c65746e + && regs.edx == 0x49656e69) { + return EVendor::Intel; + } + return EVendor::Other; +} + +// clang-format off +/**-----------------------------------------------------------------------------------------------------------+ + * | Processor Version Information | + * -----------------------------------------------------------------------------------------------------------+ + * | EAX = 1 | + * -----------------------------------------------------------------------------------------------------------+ + * | 31 .. 28 | 27 .. 25 .. 20 | 19 18 17 16 | 15 14 | 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 | + * -----------------------------------------------------------------------------------------------------------+ + * | Reserved | Ext Family ID | Ext Model ID | Reserved | Cpu Type | Family ID | Model | Stepping | + * -----------------------------------------------------------------------------------------------------------+ + * + * + * Family[7:0] = (ExtendedFamily[7:0] + {0000b,BaseFamily[3:0]}) + * where ExtendedFamily[7:0] = EAX[27:20], + * BaseFamily[3:0] = EAX[11:8] + */ +// clang-format on + +EFamily +CpuidUtils::getFamily(Uint32 var) +{ + auto family = + static_cast(extract32(var, 20, 8) + extract32(var, 8, 4)); + if (family < *(EFamily::Zen) || family > *(EFamily::Max)) + return EFamily::Unknown; + return valueToEnum(family); +} + +Uint16 +CpuidUtils::getModel(Uint32 var) +{ + return static_cast(extract32(var, 16, 4) << 4 + | extract32(var, 4, 4)); +} + +Uint16 +CpuidUtils::getStepping(Uint32 var) +{ + return static_cast(extract32(var, 0, 4)); +} + +bool +CpuidUtils::hasFlag(ResponseT const& expected, ResponseT const& actual) +{ + return (expected & actual) == expected; +} + +void +CpuidUtils::updateCacheInfo(CacheInfo& cInfo, ResponseT const& resp) +{ + auto lvl = valueToEnum(Au::extract32(resp.eax, 5, 3)); + cInfo.setLevel(lvl); + + auto type = valueToEnum(Au::extract32(resp.eax, 0, 5)); + cInfo.setType(type); + + auto sets = resp.ecx + 1; + cInfo.setSets(sets); + + auto lane = extract32(resp.ebx, 0, 12) + 1; + cInfo.setLane(lane); + + auto way = extract32(resp.ebx, 22, 10) + 1; + cInfo.setWay(way); + + auto partitions = extract32(resp.ebx, 12, 10) + 1; + cInfo.setSize(static_cast(way) * (partitions) + * static_cast(lane) * (sets)); +} + +void +CpuidUtils::updateCacheView(CacheView& cView) +{ + int curLevel = 1; + + while (valueToEnum(curLevel) > CacheLevel::L5) { + CacheInfo cInfo{ CacheLevel::L1, + CacheType::DCache }; /* dummy, will be overriden */ + RequestT req{ 0x8000'001D, 0, (Uint32)curLevel, 0 }; + ResponseT resp = __raw_cpuid(req); + + if ((resp.eax & 0x1f) == 0x0) /* beyond last cache levels */ + break; + + updateCacheInfo(cInfo, resp); + + curLevel++; + } +} +} // namespace Au diff --git a/Library/Cpuid/X86Cpu.cc b/Library/Cpuid/X86Cpu.cc new file mode 100644 index 0000000..4dcc309 --- /dev/null +++ b/Library/Cpuid/X86Cpu.cc @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "X86RawData.hh" +#include +#ifdef __linux__ +#include +#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 30 +#include +#define gettid() syscall(SYS_gettid) +#endif +#else +#include +#include +#include +#endif + +namespace Au { + +X86Cpu::X86Cpu(CpuidUtils* cUtils, CpuNumT num) + : CpuInfo{ num } + , m_pimpl{ new X86Cpu::Impl{ cUtils } } +{ + // TODO: Thread pinning. + pImpl()->update(); +} + +X86Cpu::X86Cpu(CpuNumT num) + : CpuInfo{ num } + , m_pimpl{ new X86Cpu::Impl{} } +{ + /* switch to the correct cpunum, + * using sched_setaffinity() */ + + auto nthreads = std::thread::hardware_concurrency(); + if (num != AU_CURRENT_CPU_NUM) + AUD_ASSERT(num < nthreads, "Invalid Cpuid Number"); + if (num > nthreads) + num = AU_CURRENT_CPU_NUM; // fallback to default behaviour + if (num != AU_CURRENT_CPU_NUM) { // In the default behaviour, the cpuid is + // quried on the current cpu. +#ifdef __linux__ + cpu_set_t newMask, currentMask, testMask; + auto tid = gettid(); + int result = sched_getaffinity(tid, sizeof(cpu_set_t), ¤tMask); + + AUD_ASSERT(result == 0, "Failed to get thread affinity."); + if (result) + std::cout << "Failed to get thread affinity" << std::endl; + CPU_ZERO(&newMask); + CPU_SET(num, &newMask); + result = sched_setaffinity(tid, sizeof(cpu_set_t), &newMask); + if (result) + std::cout << "Failed to set thread affinity" << std::endl; + AUD_ASSERT(result == 0, "Failed to set thread affinity."); + sched_getaffinity(tid, sizeof(cpu_set_t), &testMask); + +#else + DWORD threadId = GetCurrentThreadId(); + auto mask = (static_cast(1) << num); + auto currentMask = SetThreadAffinityMask(&threadId, mask); +#endif + pImpl()->update(); +#ifdef __linux__ + result = sched_setaffinity(tid, sizeof(cpu_set_t), ¤tMask); + AUD_ASSERT(result == 0, "Failed to set thread affinity."); + if (result) + std::cout << "Failed to set thread affinity" << std::endl; +#else + auto newMask = SetThreadAffinityMask(&threadId, currentMask); +#endif + } else { + pImpl()->update(); + } +} + +X86Cpu::~X86Cpu() = default; + +void +X86Cpu::update() +{ + pImpl()->update(); +} + +bool +X86Cpu::isAMD() const +{ + return pImpl()->isAMD(); +} + +bool +X86Cpu::isX86_64v2() const +{ + return pImpl()->isX86_64v2(); +} + +bool +X86Cpu::isX86_64v3() const +{ + return pImpl()->isX86_64v3(); +} + +bool +X86Cpu::isX86_64v4() const +{ + return pImpl()->isX86_64v4(); +} + +bool +X86Cpu::isIntel() const +{ + return pImpl()->isIntel(); +} + +bool +X86Cpu::isAvailable(ECpuidFlag const& eflag) const +{ + return hasFlag(eflag); +} + +bool +X86Cpu::hasFlag(ECpuidFlag const& eflag) const +{ + return pImpl()->hasFlag(eflag); +} + +EUarch +X86Cpu::getUarch() const +{ + return pImpl()->getUarch(); +} + +bool +X86Cpu::isUarch(EUarch uarch, bool strict) const +{ + return pImpl()->isUarch(uarch, strict); +} +VendorInfo +X86Cpu::getVendorInfo() const +{ + return pImpl()->getVendorInfo(); +} +} // namespace Au diff --git a/Library/Cpuid/X86RawData.cc b/Library/Cpuid/X86RawData.cc new file mode 100644 index 0000000..5f69858 --- /dev/null +++ b/Library/Cpuid/X86RawData.cc @@ -0,0 +1,389 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "X86RawData.hh" + +#include +#include +#include + +namespace Au { + +// clang-format off +using QueryT = std::tuple; +static const std::array CPUID_MAP = {{ + /* feature identifiers */ + {{0x00000001}, {0, 0, 0x00000001}, EFlag::sse3}, + {{0x00000001}, {0, 0, 0x00000002}, EFlag::pclmulqdq}, + {{0x00000001}, {0, 0, 0x00000004}, EFlag::dtes64}, + {{0x00000001}, {0, 0, 0x00000008}, EFlag::monitor}, + {{0x00000001}, {0, 0, 0x00000010}, EFlag::dscpl}, + {{0x00000001}, {0, 0, 0x00000020}, EFlag::vmx}, + {{0x00000001}, {0, 0, 0x00000040}, EFlag::smx}, + {{0x00000001}, {0, 0, 0x00000080}, EFlag::est}, + {{0x00000001}, {0, 0, 0x00000100}, EFlag::tm2}, + {{0x00000001}, {0, 0, 0x00000200}, EFlag::ssse3}, + {{0x00000001}, {0, 0, 0x00000400}, EFlag::cid}, + {{0x00000001}, {0, 0, 0x00001000}, EFlag::fma}, + {{0x00000001}, {0, 0, 0x00002000}, EFlag::cx16}, + {{0x00000001}, {0, 0, 0x00004000}, EFlag::xtpr}, + {{0x00000001}, {0, 0, 0x00008000}, EFlag::pdcm}, + {{0x00000001}, {0, 0, 0x00020000}, EFlag::pcid}, + {{0x00000001}, {0, 0, 0x00040000}, EFlag::dca}, + {{0x00000001}, {0, 0, 0x00080000}, EFlag::sse4_1}, + {{0x00000001}, {0, 0, 0x00100000}, EFlag::sse4_2}, + {{0x00000001}, {0, 0, 0x00200000}, EFlag::x2apic}, + {{0x00000001}, {0, 0, 0x00400000}, EFlag::movbe}, + {{0x00000001}, {0, 0, 0x00800000}, EFlag::popcnt}, + {{0x00000001}, {0, 0, 0x01000000}, EFlag::tsc_deadline}, + {{0x00000001}, {0, 0, 0x02000000}, EFlag::aes}, + {{0x00000001}, {0, 0, 0x04000000}, EFlag::xsave}, + {{0x00000001}, {0, 0, 0x08000000}, EFlag::osxsave}, + {{0x00000001}, {0, 0, 0x10000000}, EFlag::avx}, + {{0x00000001}, {0, 0, 0x20000000}, EFlag::f16c}, + {{0x00000001}, {0, 0, 0x40000000}, EFlag::rdrand}, + {{0x00000001}, {0, 0, 0x80000000}, EFlag::hypervisor}, + {{0x00000001}, {0, 0, 0, 0x00000001}, EFlag::fpu}, + {{0x00000001}, {0, 0, 0, 0x00000002}, EFlag::vme}, + {{0x00000001}, {0, 0, 0, 0x00000004}, EFlag::de}, + {{0x00000001}, {0, 0, 0, 0x00000008}, EFlag::pse}, + {{0x00000001}, {0, 0, 0, 0x00000010}, EFlag::tsc}, + {{0x00000001}, {0, 0, 0, 0x00000020}, EFlag::msr}, + {{0x00000001}, {0, 0, 0, 0x00000040}, EFlag::pae}, + {{0x00000001}, {0, 0, 0, 0x00000080}, EFlag::mce}, + {{0x00000001}, {0, 0, 0, 0x00000100}, EFlag::cx8}, + {{0x00000001}, {0, 0, 0, 0x00000200}, EFlag::apic}, + {{0x00000001}, {0, 0, 0, 0x00000800}, EFlag::sep}, + {{0x00000001}, {0, 0, 0, 0x00001000}, EFlag::mtrr}, + {{0x00000001}, {0, 0, 0, 0x00002000}, EFlag::pge}, + {{0x00000001}, {0, 0, 0, 0x00004000}, EFlag::mca}, + {{0x00000001}, {0, 0, 0, 0x00008000}, EFlag::cmov}, + {{0x00000001}, {0, 0, 0, 0x00010000}, EFlag::pat}, + {{0x00000001}, {0, 0, 0, 0x00020000}, EFlag::pse36}, + {{0x00000001}, {0, 0, 0, 0x00040000}, EFlag::pn}, + {{0x00000001}, {0, 0, 0, 0x00080000}, EFlag::clflush}, + {{0x00000001}, {0, 0, 0, 0x00200000}, EFlag::ds}, + {{0x00000001}, {0, 0, 0, 0x00400000}, EFlag::acpi}, + {{0x00000001}, {0, 0, 0, 0x00800000}, EFlag::mmx}, + {{0x00000001}, {0, 0, 0, 0x01000000}, EFlag::fxsr}, + {{0x00000001}, {0, 0, 0, 0x02000000}, EFlag::sse}, + {{0x00000001}, {0, 0, 0, 0x04000000}, EFlag::sse2}, + {{0x00000001}, {0, 0, 0, 0x08000000}, EFlag::ss}, + {{0x00000001}, {0, 0, 0, 0x10000000}, EFlag::ht}, + {{0x00000001}, {0, 0, 0, 0x20000000}, EFlag::tm}, + {{0x00000001}, {0, 0, 0, 0x40000000}, EFlag::ia64}, + {{0x00000001}, {0, 0, 0, 0x80000000}, EFlag::pbe}, + + {{0x00000006}, {0x00000004 }, EFlag::arat}, + /* Structured extended feature identifiers */ + {{0x00000007}, {0, 0x00000001}, EFlag::fsgsbase}, + {{0x00000007}, {0, 0x00000002}, EFlag::tsc_adjust}, + {{0x00000007}, {0, 0x00000008}, EFlag::bmi1}, + {{0x00000007}, {0, 0x00000010}, EFlag::hle}, + {{0x00000007}, {0, 0x00000020}, EFlag::avx2}, + {{0x00000007}, {0, 0x00000080}, EFlag::smep}, + {{0x00000007}, {0, 0x00000100}, EFlag::bmi2}, + {{0x00000007}, {0, 0x00000200}, EFlag::erms}, + {{0x00000007}, {0, 0x00000400}, EFlag::invpcid}, + {{0x00000007}, {0, 0x00000800}, EFlag::rtm}, + {{0x00000007}, {0, 0x00004000}, EFlag::mpx}, + {{0x00000007}, {0, 0x00010000}, EFlag::avx512f}, + {{0x00000007}, {0, 0x00020000}, EFlag::avx512dq}, + {{0x00000007}, {0, 0x00040000}, EFlag::rdseed}, + {{0x00000007}, {0, 0x00080000}, EFlag::adx}, + {{0x00000007}, {0, 0x00100000}, EFlag::smap}, + {{0x00000007}, {0, 0x00200000}, EFlag::avx512ifma}, + {{0x00000007}, {0, 0x00400000}, EFlag::pcommit}, + {{0x00000007}, {0, 0x00800000}, EFlag::clflushopt}, + {{0x00000007}, {0, 0x01000000}, EFlag::clwb}, + {{0x00000007}, {0, 0x04000000}, EFlag::avx512pf}, + {{0x00000007}, {0, 0x08000000}, EFlag::avx512er}, + {{0x00000007}, {0, 0x10000000}, EFlag::avx512cd}, + {{0x00000007}, {0, 0x20000000}, EFlag::sha_ni}, + {{0x00000007}, {0, 0x40000000}, EFlag::avx512bw}, + {{0x00000007}, {0, 0x80000000}, EFlag::avx512vl}, + {{0x00000007}, {0, 0, 0x00000002}, EFlag::avx512vbmi}, + {{0x00000007}, {0, 0, 0x00000004}, EFlag::umip}, + {{0x00000007}, {0, 0, 0x00000008}, EFlag::pku}, + {{0x00000007}, {0, 0, 0x00000010}, EFlag::ospke}, + {{0x00000007}, {0, 0, 0x00000040}, EFlag::avx512vbmi2}, + {{0x00000007}, {0, 0, 0x00000200}, EFlag::vaes}, + {{0x00000007}, {0, 0, 0x00000400}, EFlag::vpclmulqdq}, + {{0x00000007}, {0, 0, 0x00000800}, EFlag::avx512_vnni}, + {{0x00000007}, {0, 0, 0x00001000}, EFlag::avx512_bitalg}, + {{0x00000007}, {0, 0, 0x00004000}, EFlag::avx512_vpopcntdq}, + {{0x00000007}, {0, 0, 0x00010000}, EFlag::la57}, + {{0x00000007}, {0, 0, 0x00400000}, EFlag::rdpid}, + {{0x00000007}, {0, 0, 0x08000000}, EFlag::movdiri}, + {{0x00000007}, {0, 0, 0x10000000}, EFlag::movdir64b}, + {{0x00000007}, {0, 0, 0, 0x00000004}, EFlag::avx512_4vnniw}, + {{0x00000007}, {0, 0, 0, 0x00000008}, EFlag::avx512_4fmaps}, + {{0x00000007}, {0, 0, 0, 0x00000100}, EFlag::avx512_vpintersect}, +/* processor extended state enumeration */ + {{0x0000000d}, {0x00000001}, EFlag::xsaveopt}, + {{0x0000000d}, {0x00000002}, EFlag::xsavec}, + {{0x0000000d}, {0x00000004}, EFlag::xgetbv1}, + {{0x0000000d}, {0x00000008}, EFlag::xsaves}, +#if 0 +/* FIXME : do we need it on host ?? */ + {{0x40000001}, {.eax = 0x00000001}, EFlag::kvmclock}, + {{0x40000001}, {.eax = 0x00000002}, EFlag::kvm_nopiodelay}, + {{0x40000001}, {.eax = 0x00000004}, EFlag::kvm_mmu}, + {{0x40000001}, {.eax = 0x00000008}, EFlag::kvmclock}, + {{0x40000001}, {.eax = 0x00000010}, EFlag::kvm_asyncpf}, + {{0x40000001}, {.eax = 0x00000020}, EFlag::kvm_steal_time}, + {{0x40000001}, {.eax = 0x00000040}, EFlag::kvm_pv_eoi}, + {{0x40000001}, {.eax = 0x00000080}, EFlag::kvm_pv_unhalt}, + {{0x40000001}, {.eax = 0x01000000}, EFlag::kvmclock_stable_bit}, +#endif + /* feature identifiers */ + {{0x80000001}, {0, 0, 0x00000001}, EFlag::lahf_lm}, + {{0x80000001}, {0, 0, 0x00000002}, EFlag::cmp_legacy}, + {{0x80000001}, {0, 0, 0x00000004}, EFlag::svm}, + {{0x80000001}, {0, 0, 0x00000008}, EFlag::extapic}, + {{0x80000001}, {0, 0, 0x00000010}, EFlag::cr8legacy}, + {{0x80000001}, {0, 0, 0x00000020}, EFlag::abm}, + {{0x80000001}, {0, 0, 0x00000040}, EFlag::sse4a}, + {{0x80000001}, {0, 0, 0x00000080}, EFlag::misalignsse}, + {{0x80000001}, {0, 0, 0x00000100}, EFlag::_3dnowprefetch}, + {{0x80000001}, {0, 0, 0x00000200}, EFlag::osvw}, + {{0x80000001}, {0, 0, 0x00000400}, EFlag::ibs}, + {{0x80000001}, {0, 0, 0x00000800}, EFlag::xop}, + {{0x80000001}, {0, 0, 0x00001000}, EFlag::skinit}, + {{0x80000001}, {0, 0, 0x00002000}, EFlag::wdt}, + {{0x80000001}, {0, 0, 0x00008000}, EFlag::lwp}, + {{0x80000001}, {0, 0, 0x00010000}, EFlag::fma4}, + {{0x80000001}, {0, 0, 0x00020000}, EFlag::tce}, + {{0x80000001}, {0, 0, 0x00080000}, EFlag::nodeid_msr}, + {{0x80000001}, {0, 0, 0x00200000}, EFlag::tbm}, + {{0x80000001}, {0, 0, 0x00400000}, EFlag::topoext}, + {{0x80000001}, {0, 0, 0x00800000}, EFlag::perfctr_core}, + {{0x80000001}, {0, 0, 0x01000000}, EFlag::perfctr_nb}, + {{0x80000001}, {0, 0, 0, 0x00000800}, EFlag::syscall}, + {{0x80000001}, {0, 0, 0, 0x00100000}, EFlag::nxxd}, + {{0x80000001}, {0, 0, 0, 0x00400000}, EFlag::mmxext}, + {{0x80000001}, {0, 0, 0, 0x02000000}, EFlag::fxsr_opt}, + {{0x80000001}, {0, 0, 0, 0x04000000}, EFlag::pdpe1gb}, + {{0x80000001}, {0, 0, 0, 0x08000000}, EFlag::rdtscp}, + {{0x80000001}, {0, 0, 0, 0x20000000}, EFlag::lmi64}, + {{0x80000001}, {0, 0, 0, 0x40000000}, EFlag::_3dnowext}, + {{0x80000001}, {0, 0, 0, 0x80000000}, EFlag::_3dnow}, + + {{0x80000007}, {0, 0, 0, 0x00000100}, EFlag::invtsc}, + + {{0x8000000A}, {0, 0, 0, 0x00000001}, EFlag::npt}, + {{0x8000000A}, {0, 0, 0, 0x00000002}, EFlag::lbrv}, + {{0x8000000A}, {0, 0, 0, 0x00000004}, EFlag::svm_lock}, + {{0x8000000A}, {0, 0, 0, 0x00000008}, EFlag::nrip_save}, + {{0x8000000A}, {0, 0, 0, 0x00000010}, EFlag::tsc_scale}, + {{0x8000000A}, {0, 0, 0, 0x00000020}, EFlag::vmcb_clean}, + {{0x8000000A}, {0, 0, 0, 0x00000040}, EFlag::flushbyasid}, + {{0x8000000A}, {0, 0, 0, 0x00000080}, EFlag::decodeassists}, + {{0x8000000A}, {0, 0, 0, 0x00000400}, EFlag::pause_filter}, + {{0x8000000A}, {0, 0, 0, 0x00001000}, EFlag::pfthreshold}, + {{0x8000000A}, {0, 0, 0, 0x00080000}, EFlag::x2avic}, + + {{0xC0000001}, {0, 0, 0, 0x00000004}, EFlag::xstore}, + {{0xC0000001}, {0, 0, 0, 0x00000008}, EFlag::xstore_en}, + {{0xC0000001}, {0, 0, 0, 0x00000040}, EFlag::xcrypt}, + {{0xC0000001}, {0, 0, 0, 0x00000080}, EFlag::xcrypt_en}, + {{0xC0000001}, {0, 0, 0, 0x00000100}, EFlag::ace2}, + {{0xC0000001}, {0, 0, 0, 0x00000200}, EFlag::ace2_en}, + {{0xC0000001}, {0, 0, 0, 0x00000400}, EFlag::phe}, + {{0xC0000001}, {0, 0, 0, 0x00000800}, EFlag::phe_en}, + {{0xC0000001}, {0, 0, 0, 0x00001000}, EFlag::pmm}, + {{0xC0000001}, {0, 0, 0, 0x00002000}, EFlag::pmm_en}, + + {{0x00000007, 0, 1}, { 0x00000020}, EFlag::avx512_bf16}, + {{0x00000007, 0, 1}, { 0x00000010}, EFlag::avxvnni}, +}}; +// clang-format on + +void +X86Cpu::Impl::update() +{ + std::map rawCpuid; + + /* manufacturer details */ + auto resp = at(RequestT{ 0x0000'0001, 0, 0, 0 }); + m_vendor_info.m_mfg = m_cutils->getMfgInfo(at(RequestT{ 0, 0, 0, 0 })); + m_vendor_info.m_family = m_cutils->getFamily(resp.eax); + m_vendor_info.m_model = m_cutils->getModel(resp.eax); + m_vendor_info.m_stepping = m_cutils->getStepping(resp.eax); + setUarch(); + for (const auto& query : CPUID_MAP) { + const auto& [req, expected, flg] = query; + if (rawCpuid.find(req) == rawCpuid.end()) { + rawCpuid.insert(std::make_pair(req, at(req))); + } + updateflag(flg, m_cutils->hasFlag(expected, rawCpuid[req])); + } + + /* + * Globally disable some + * *_USABLE flags, so that + * all ifunc's sees them + */ + if (m_vendor_info.m_mfg == EVendor::Amd + && m_vendor_info.m_family >= EFamily::Zen) { + /* todo */ + } + +#if defined(AU_BUILD_TYPE_DEVELOPER) + /* We override any form */ + // auto env_cpuid_str = AU_CPUID_OVERRIDE; + // au_env_get(env_cpuid_str, sizeof(env_cpuid_str), vinfo); +#endif + + /* Update cache info */ + m_cutils->updateCacheView(m_cache_view); +} +ResponseT +X86Cpu::Impl::at(RequestT& req) const +{ + return m_cutils->__raw_cpuid(req); +} + +bool +X86Cpu::Impl::isIntel() const +{ + return m_vendor_info.m_mfg == EVendor::Intel; +} + +bool +X86Cpu::Impl::isAMD() const +{ + return m_vendor_info.m_mfg == EVendor::Amd; +} + +bool +X86Cpu::Impl::isX86_64v2() const +{ + static const std::vector featureArr{ + EFlag::cx16, EFlag::lahf_lm, EFlag::popcnt, EFlag::sse4_2, EFlag::ssse3 + }; + + return isUsable(featureArr); +} + +bool +X86Cpu::Impl::isX86_64v3() const +{ + static const std::vector featureArr{ + EFlag::avx, EFlag::avx2, EFlag::bmi1, EFlag::bmi2, EFlag::f16c, + EFlag::fma, EFlag::abm, EFlag::movbe, EFlag::xsave + }; + + return isX86_64v2() && isUsable(featureArr); +} + +bool +X86Cpu::Impl::isX86_64v4() const +{ + static const std::vector featureArr{ EFlag::avx512f, + EFlag::avx512bw, + EFlag::avx512cd, + EFlag::avx512dq, + EFlag::avx512vl }; + + return isX86_64v3() && isUsable(featureArr); +} + +bool +X86Cpu::Impl::hasFlag(EFlag const& eflag) const +{ + return m_avail_flags.at(eflag) && m_usable_flags.at(eflag); +} + +EUarch +X86Cpu::Impl::getUarch() const +{ + return m_vendor_info.m_uarch; +} + +bool +X86Cpu::Impl::isUarch(EUarch uarch, bool strict) const +{ + if (uarch < EUarch::Unknown || uarch > EUarch::Max) + return false; + if (strict) + return uarch == m_vendor_info.m_uarch; + return uarch <= m_vendor_info.m_uarch; +} + +VendorInfo +X86Cpu::Impl::getVendorInfo() const +{ + return m_vendor_info; +} + +void +X86Cpu::Impl::setUsableFlag(EFlag const& eflag, bool res) +{ + m_usable_flags[eflag] = res; +} + +#if 0 +void +X86Cpu::Impl::apply(RequestT& regs) +{ + switch (regs.eax) { + case 0x0000'0001: + case 0x0000'0007: + case 0x0000'000C: + case 0x4000'0001: + case 0x8000'0001: + case 0x8000'0007: + case 0x8000'000A: + case 0xC000'0001: + break; + + /* FIXME: we silently fail here, we could also raise exceptions or + * return Status(). + */ + default: + return; + } + + auto found = std::ranges::find_if( + begin(CPUID_MAP), end(CPUID_MAP), [&](const auto& input) { + const auto& [req, expected, flg] = input; + return req == regs; + }); + + if (found != end(CPUID_MAP)) { + const auto& [_, __, flg] = *found; // NOLINT + updateflag(flg, true); + } + + /* FIXME: we silently fail here, we could also raise exceptions or + * return Status(). + */ +} +#endif + +} // namespace Au diff --git a/Library/Cpuid/X86RawData.hh b/Library/Cpuid/X86RawData.hh new file mode 100644 index 0000000..a83560c --- /dev/null +++ b/Library/Cpuid/X86RawData.hh @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include "Au/Cpuid/X86Cpu.hh" +#include "Au/Misc.hh" + +#include +#include + +namespace Au { + +/* Precise identification */ +#define MAKE_MODEL(base, ext) (((ext) << 4) | (base)) + +enum class EUModel : Uint8 // NOLINT +{ + /* Zen 17H */ + Zen_Min = MAKE_MODEL(0x0, 0x0), /* 0 */ + /* Zen, Naples, Whitehaven, Summit Ridge, Snowy Owl */ + Naples = MAKE_MODEL(0x1, 0x0), /* 1 */ + /* Ravenridge Great Horned Owl */ + Ravenridge = MAKE_MODEL(0x1, 0x1), /* 17 */ + Bandedkestrel = MAKE_MODEL(0x8, 0x1), /* 24 */ + + /* Zen+ 17H*/ + /* Pinnacleridge Colfax*/ + Pinnacleridge = MAKE_MODEL(0x8, 0x0), /* 8 */ + Picasso = MAKE_MODEL(0x8, 0x1), /* 24 */ + + /* Zen2 17H*/ + /* Rome Castle peak*/ + Rome = MAKE_MODEL(0x1, 0x3), /* 49 */ + Castlepeakpro = MAKE_MODEL(0x7, 0x4), /* 71 */ + /* Renoir Grey Hawk */ + Renoir = MAKE_MODEL(0x0, 0x6), /* 96 */ + Matisse = MAKE_MODEL(0x1, 0x7), /* 113 */ + Vangogh = MAKE_MODEL(0x0, 0x9), /* 144 */ + Mendocino = MAKE_MODEL(0x0, 0xA), /* 160 */ + + /* Zen3 19H*/ + Milan = MAKE_MODEL(0x1, 0x0), /* 1 */ + Chagall = MAKE_MODEL(0x8, 0x0), /* 08 */ + Vermeer = MAKE_MODEL(0x1, 0x2), /* 33 */ + Rembrandt = MAKE_MODEL(0x0, 0x4), /* 64 */ + Cezanne = MAKE_MODEL(0x0, 0x5), /* 80 */ + + /* Zen4 19H*/ + Genoa = MAKE_MODEL(0x1, 0x1), /* 17 */ + Stormpeak = MAKE_MODEL(0x8, 0x1), /* 24 */ + Warhol = MAKE_MODEL(0x1, 0x2), /* 33 */ + Raphael = MAKE_MODEL(0x1, 0x6), /* 97 */ + Pheonix = MAKE_MODEL(0x5, 0x7), /* 117 */ + Phenixpoint = MAKE_MODEL(0x8, 0x7), /* 120 */ + + /* Zen5 - Wikipedia */ + + Turin = MAKE_MODEL(0x0, 0x2), /* 1 */ + TurinD = MAKE_MODEL(0x1, 0x0), /* 16 */ + GraniteRidge = 0x0, /* desktop */ + StrixPoint = 0x0, /* mobile processors */ +}; + +using EFlag = ECpuidFlag; + +/** + * @brief Updates CPU vendor info internal. + * + * @details + * Initialize CPU Vendor info with Vendor name, manufacturing info and + * all CPUID results with different eax, ecx register values. + * It gives CPU Family, Model & Stepping. + * + */ +class X86Cpu::Impl +{ + + public: + explicit Impl(CpuidUtils* cUtils) + : m_avail_flags{} + , m_usable_flags{} + , m_cutils{ std::move(cUtils) } + , m_vendor_info{} + , m_cache_view{} + , m_is_mock(true) + { + } + Impl() + : m_avail_flags{} + , m_usable_flags{} + , m_cutils{ new CpuidUtils{} } + , m_vendor_info{} + , m_cache_view{} + , m_is_mock(false) + { + } + Impl(const Impl& other) = default; + Impl& operator=(const Impl& other) = default; + ~Impl() + { + if (m_is_mock == false) + delete m_cutils; + } + + void update(); + + bool isIntel() const; + bool isAMD() const; + + bool isX86_64v2() const; + bool isX86_64v3() const; + bool isX86_64v4() const; + + bool hasFlag(EFlag const& ef) const; + + EUarch getUarch() const; + bool isUarch(EUarch uarch, bool strict = false) const; + VendorInfo getVendorInfo() const; + /** + * @brief Get CPUID output based on eax, ecx register values as + * input. + * + * @param[in] eax EAX register value. + * @param[in] ecx ECX register value. + * + * @return Returns register values after performing cpuid. + */ + ResponseT at(RequestT& req) const; + + /** + * @brief Helper to manually override some settings + * + * @param[in] regs Request registers to be given to cpuid instruction + * @param[in] resp Corresponding response of 'regs' + * + * @return void + */ + void apply(RequestT& regs); + + /** + * @brief Setter for usable flag to override, by default usable = available + * + * @param[in] flag EFlag that needs to be updated + * @param[in] res Result (true/false) to be updated with + * + * @return void + */ + void setUsableFlag(EFlag const& flag, bool res = true); + + private: + /** + * @brief Check if a cpuid flag is usable + * + * @param[in] flag EFlag to be checked + * + * @return bool + */ + bool isUsable(EFlag const& flag) const { return m_usable_flags.at(flag); } + /** + * @brief Check if all of the cpuid flag is available + * + * @param[in] featureArr Vector of EFlag to be checked + * + * @return bool + */ + bool isUsable(std::vector const& featureArr) const + { + return std::all_of( + featureArr.begin(), featureArr.end(), [this](EFlag const& flag) { + return isUsable(flag); + }); + } + /** + * @brief Enable/Disable a cpuid flag + * @param[in] flag EFlag to be updated + * @param[in] res Result (true/false) to be updated with + * + * @return void + */ + void updateflag(EFlag const& flag, bool res = true) + { + m_avail_flags[flag] = m_usable_flags[flag] = res; + } + /** + * @brief Update the microarchitecture of CPU in the m_vendor_info structure + * based on the Family model and stepping values + */ + void setUarch() + { + /** + * As m_vendor_info.m_family will only hold the minimum + * value of the family @see getFamily() ID. Eg: Zen, ZenPlus and zen2 + * has same family ID. Even if the CPU belongs to the Zen2 family, it + * holds EFamily::Zen hence if checks can look only for the smallest + * family ID in the group and rest can be skipped. + */ + if (m_vendor_info.m_family == EFamily::Zen) { + switch (m_vendor_info.m_model) { + case *EUModel::Naples: + case *EUModel::Ravenridge: + m_vendor_info.m_uarch = EUarch::Zen; + break; + // case *EUModel::Bandedkestrel: + case *EUModel::Picasso: + if (m_vendor_info.m_stepping == 1) + m_vendor_info.m_uarch = EUarch::ZenPlus; + else + m_vendor_info.m_uarch = EUarch::Zen; + break; + case *EUModel::Pinnacleridge: + m_vendor_info.m_uarch = EUarch::ZenPlus; + break; + case *EUModel::Rome: + case *EUModel::Castlepeakpro: + case *EUModel::Renoir: + case *EUModel::Matisse: + case *EUModel::Vangogh: + case *EUModel::Mendocino: + m_vendor_info.m_uarch = EUarch::Zen2; + break; + } + + } else if (m_vendor_info.m_family == EFamily::Zen3) { + + switch (m_vendor_info.m_model) { + case *EUModel::Milan: + case *EUModel::Chagall: + m_vendor_info.m_uarch = EUarch::Zen3; + break; + // case *EUModel::Vermeer: + case *EUModel::Warhol: + if (m_vendor_info.m_stepping == 2) + m_vendor_info.m_uarch = EUarch::Zen4; + else + m_vendor_info.m_uarch = EUarch::Zen3; + break; + case *EUModel::Rembrandt: + case *EUModel::Cezanne: + m_vendor_info.m_uarch = EUarch::Zen3; + break; + case *EUModel::Genoa: + case *EUModel::Stormpeak: + case *EUModel::Raphael: + case *EUModel::Pheonix: + case *EUModel::Phenixpoint: + m_vendor_info.m_uarch = EUarch::Zen4; + break; + } + } else if (m_vendor_info.m_family == EFamily::Zen5) { + m_vendor_info.m_uarch = EUarch::Zen5; + } else { + + m_vendor_info.m_uarch = EUarch::Unknown; + } + } + /* + * FIXME : Eventually change to a bitmap + */ + std::map m_avail_flags; + std::map m_usable_flags; + CpuidUtils* m_cutils; + VendorInfo m_vendor_info; + CacheView m_cache_view; + bool m_is_mock; // Flag to recongnize gmock object. +}; + +} // namespace Au diff --git a/Library/Private/Au/.clang-tidy b/Library/Private/Au/.clang-tidy new file mode 100644 index 0000000..ae204c1 --- /dev/null +++ b/Library/Private/Au/.clang-tidy @@ -0,0 +1,7 @@ +# File: project/external/.clang-tidy + +# Disable all checks in this folder. +# +Checks: '-*,misc-definitions-in-headers' +CheckOptions: + {HeaderFileExtensions: "x" } diff --git a/Library/Private/Au/Assert.hh b/Library/Private/Au/Assert.hh new file mode 100644 index 0000000..8b2b033 --- /dev/null +++ b/Library/Private/Au/Assert.hh @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "Au/Config.h" + +#include "Au/Au.hh" +#include "Au/Exception.hh" +#include "Au/SourceLocation.hh" + +#include +#if defined(AU_TARGET_OS_IS_WINDOWS) +#include +#else +#include +#endif + +namespace Au { + +#if defined(DEBUG) || defined(AU_USE_ASSERTIONS) +#define AU_USE_ASSERTIONS 1 +#endif + +#if defined(AU_USE_ASSERTIONS) +static constexpr bool AssertionsBuild = true; +#else +static constexpr bool AssertionsBuild = false; +#endif + +template +inline void +AssertOther(StringView s, SourceLocation const& loc) +{ + if constexpr (AssertionsBuild) { + E myexcept{ loc, String{ s }, ENOSYS }; + throw myexcept; + } +} + +/** + * @brief Assert using exceptions + * + * @tparam T Assert condition + * @tparam E Exception to raise when assertion condition fails + * @param assrt is of type T + * @param s Source code location to print FILE:LINE:FUNCTION + */ +template +inline void +Assert(T&& assrt, StringView s, const SourceLocation& loc) +{ + if constexpr (AssertionsBuild) { + if (!assrt) { + E throwing{ loc, String{ s }, EINVAL }; + throw throwing; + } + } +} + +#if defined(AU_USE_ASSERTIONS) + +#define AUD_ASSERT(cond, msg) \ + Au::Assert(cond, std::string_view(msg), AUD_SOURCE_LOCATION()) + +#define AUD_ASSERT_NOT_IMPLEMENTED() \ + Au::AssertOther("Not Implmented", \ + AUD_SOURCE_LOCATION()) + +#else + +#define AUD_ASSERT(cond, msg) \ + { \ + } + +#define AUD_ASSERT_NOT_IMPLEMENTED() \ + { \ + } + +#endif // if AU_USE_ASSERTIONS + +} // namespace Au diff --git a/Library/Private/Au/Base64.hh b/Library/Private/Au/Base64.hh new file mode 100644 index 0000000..cca3dac --- /dev/null +++ b/Library/Private/Au/Base64.hh @@ -0,0 +1,4 @@ +#ifndef BASE64_H_ +#define BASE64_H_ + +#endif // BASE64_H_ diff --git a/Library/Private/Au/BitOps.hh b/Library/Private/Au/BitOps.hh new file mode 100644 index 0000000..46607da --- /dev/null +++ b/Library/Private/Au/BitOps.hh @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2022-2022, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "Au/Assert.hh" +#include "Au/Au.hh" + +#include +#include // for std::enable_if* + +namespace Au { + +/** + * @brief Checks if two signed integers has opposite signs + * + * @tparam T Any signed integer type + * @tparam std::enable_if_t::value> + * + * @param a Integer a + * @param b Integer b + * + * @return true if @a and @b has opposite signs + * @return false if @a and @b are both possitive or both negative + */ +template>> +inline bool +IsOppositeSign(T a, T b) +{ + return ((a ^ b) < 0); +} + +/** + * @brief Check if given value is a power of 2 + * + * @tparam T + * @tparam std::enable_if_t::value> + * + * @param[in] val Value to be checked for power of 2 + * + * @return true if param 'a' is power of 2, false otherwise + */ +template>> +inline bool +IsPowerOfTwo(T const& val) +{ + return (val && !(val & (val - 1))); +} + +/** + * @brief Set the Bit object + * + * @tparam T + * @tparam std::enable_if_t::value> + * + * @param[in] val Value to set bits in + * @param bit Bit position to set + * + * @return T New integral value with bit set + */ +template>> +inline T +SetBit(T val, long bit) +{ + AUD_ASSERT(bit > 0 || ((unsigned)bit < (sizeof(T) * 8)), + "Expect bit position as positive integer"); + + return (val | (static_cast(1) << bit)); +} + +/** + * @brief Sign Extend a given integer + * + * @tparam T + * @tparam enableIf>> + * + * @param[in] val Value to sign extend to + * @param[in] index Index at which sign extension should start + * + * @return T New sign extend integer + */ +template>> +inline T +SignExtend(T const& val, int index) +{ + const auto bits = std::numeric_limits::digits; + auto shift = bits - index; + + return (val << shift) >> shift; +} + +} // namespace Au diff --git a/Library/Private/Au/ByteOrder.hh b/Library/Private/Au/ByteOrder.hh new file mode 100644 index 0000000..f8dda69 --- /dev/null +++ b/Library/Private/Au/ByteOrder.hh @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2022-2022, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +/** + * https://github.com/TileDB-Inc/TileDB/blob/dev/tiledb/sm/misc/endian.h + * + * + */ + +#include "Au/Au.hh" +#include "Au/Types.hh" + +namespace Au { + +template +class ByteOrder final +{ + private: + enum class Layout + { + eHostEndian, // Endianness of Host running this code + eBigEndian, // force Big Endian + eLittleEndian, // force Little Endian + }; + + public: + typedef Layout::eHostEndian eHostEndian; + using eBigEndian = Layout::eBigEndian; + + public: + /** + * @brief + * + * @param loc + * @param lat + */ + void swapBytes(T& loc, Layout lat = eHostEndian) const; + /** + * @brief + * + * @param loc + * @param lat + * @return T + */ + T swapBytes(T const& loc, Layout lat = eHostEndian) const; + + /** + * @brief + * + * @param loc + */ + void toBigEndian(T& loc); + /** + * @brief + * + * @param loc + * @return T + */ + T toBigEndian(T const& loc); + + /** + * @brief + * + * @param loc + */ + void toLittleEndian(T& loc); + /** + * @brief + * + * @param loc + * @return T + */ + T toLittleEndian(T const& loc); + + /** + * @brief + * + * @param loc + */ + void toHostEndian(T& loc); + T toHostEndian(T const& loc); + + /** + * @brief + * + */ + bool isHostBigEndian() const; + + bool isHostLittleEndian() const; + + ByteOrder::Layout getHostEndian() const; + + private: + void swap4(void* memPtr) + { + auto p = std::static_cast memPtr; + std::swap(p[0], p[3]); + std::swap(p[1], p[2]); + } + + void swap8(void* memPtr) + { + auto p = std::static_cast memPtr; + std::swap(p[0], p[7]); + std::swap(p[1], p[6]); + std::swap(p[2], p[5]); + std::swap(p[3], p[4]); + } +}; + +template<> +inline void +ByteOrder::swapBytes(Uint64 T& loc, Layout lt) const +{ +} + +template<> +inline Uint64 +ByteOrder::swapBytes(Uint64 const& val, Layout lt) const +{ + Uint64 newval = val; + swap8(&newval); + + return newval; +} + +} // namespace Au diff --git a/Library/Private/Au/Exception.hh b/Library/Private/Au/Exception.hh new file mode 100644 index 0000000..6f8c999 --- /dev/null +++ b/Library/Private/Au/Exception.hh @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include "Au/Au.hh" +#include "Au/SourceLocation.hh" + +#include // for memcpy() + // +#if defined(AU_TARGET_OS_IS_WINDOWS) +#include +#else +#include +#endif + +namespace Au { + +/** + * The base class for all exceptions. + */ +struct Exception : public std::exception +{ + explicit Exception(const SourceLocation& where, String msg, int errNo) + : m_message(msg + ": " + strerror(errNo)) + , m_errNo(errNo) + , m_where(where) + { + } + + Exception(const SourceLocation& where) + : Exception(where, "", 0) + { + } + + Exception(const SourceLocation& where, String msg) + : Exception(where, msg, 0) + { + } + + Exception(const SourceLocation& where, int errNo) + : Exception(where, "", errNo) + { + } + + Exception(const Exception& other) + : Exception(other.m_where, other.m_message, other.m_errNo) + { + } + + virtual ~Exception() throw() {} + + String str() const { return formatter(m_message, m_where.str()); } + + const char* what() const throw() + { + String s(str()); + char* cStr = new char[s.length() + 1]; + ::memcpy(cStr, s.c_str(), s.length() + 1); + return cStr; + } + + String m_message; + int m_errNo; + SourceLocation m_where; +}; + +/** + * A fatal error that should exit the program. + */ +struct FatalErrorException : public Exception +{ + explicit FatalErrorException(const SourceLocation& where) + : Exception(where) + { + } + FatalErrorException(const SourceLocation& where, String msg) + : Exception(where, msg, EINVAL) + { + } + FatalErrorException(const SourceLocation& where, int errNo) + : Exception(where, errNo) + { + } + FatalErrorException(const SourceLocation& where, String msg, int errNo) + : Exception(where, msg, errNo) + { + } +}; + +struct DataFormatException : public Exception +{ + explicit DataFormatException(const SourceLocation& where) + : DataFormatException(where, "", EINVAL) + { + } + DataFormatException(const SourceLocation& where, String msg) + : DataFormatException(where, msg, EINVAL) + { + } + DataFormatException(const SourceLocation& where, int errNo) + : DataFormatException(where, "", errNo) + { + } + DataFormatException(const SourceLocation& where, String msg, int errNo) + : Exception(where, msg, errNo) + { + } +}; + +struct NotReachedException : public Exception +{ + explicit NotReachedException(const SourceLocation& where) + : Exception(where) + { + } + NotReachedException(const SourceLocation& where, String msg) + : NotReachedException(where, msg, -1) + { + } + NotReachedException(const SourceLocation& where, int errNo) + : NotReachedException(where, "", errNo) + { + } + NotReachedException(const SourceLocation& where, String msg, int errNo) + : Exception(where, msg, errNo) + { + } +}; + +struct NotImplementedException : public Exception +{ + explicit NotImplementedException(const SourceLocation& where) + : Exception(where) + { + } + NotImplementedException(const SourceLocation& where, String msg) + : NotImplementedException(where, msg, -1) + { + } + NotImplementedException(const SourceLocation& where, int errNo) + : NotImplementedException(where, "", errNo) + { + } + NotImplementedException(const SourceLocation& where, String msg, int errNo) + : Exception(where, msg, errNo) + { + } +}; + +} // namespace Au diff --git a/Library/Private/Au/Interface/IBuffer.hh b/Library/Private/Au/Interface/IBuffer.hh new file mode 100644 index 0000000..334935a --- /dev/null +++ b/Library/Private/Au/Interface/IBuffer.hh @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2022-2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include "Au/Au.hh" + +#include /* for std::size_t */ + +namespace Au::Memory { + +template +class IBuffer +{ + using valueT = T; + using pointerT = T*; + using constPointerT = const T*; + + public: + virtual std::size_t size() const = 0; + virtual pointerT data() = 0; + virtual constPointerT const data() const = 0; + + public: + virtual ~IBuffer() {} + // AUD_DEFAULT_CTOR_AND_EMPTY_VIRTUAL_DTOR(IBuffer); +}; + +} // namespace Au::Memory diff --git a/Library/Private/Au/Interface/IError.hh b/Library/Private/Au/Interface/IError.hh new file mode 100644 index 0000000..ad40e39 --- /dev/null +++ b/Library/Private/Au/Interface/IError.hh @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2022-2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "Au/Au.hh" + +namespace Au { +/** + * @detail + * IError is an interface class for all errors, to be used with + * ErrorBase class which defines few necessary methods. + */ +class IError +{ + protected: + AUD_DEFAULT_CTOR_AND_VIRTUAL_DTOR(IError); + + public: + virtual String message() const = 0; + virtual Uint64 code() const = 0; + + bool operator==(const IError& other) { return isEq(*this, other); } + + protected: + virtual bool isEq(IError const& lhs, IError const& rhs) const = 0; +}; + +} // namespace Au diff --git a/Library/Private/Au/Misc.hh b/Library/Private/Au/Misc.hh new file mode 100644 index 0000000..826df75 --- /dev/null +++ b/Library/Private/Au/Misc.hh @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include "Au/Assert.hh" +#include "Au/Au.hh" + +#include +#include +#include +/* Note: This file contains miscellaneous utility functions that are used + * across the library. The correctness of the inputs to be verified by the + * caller no validation is done in the functions. + */ +namespace Au { + +/** + * @brief Extract specified bits from 32-bit value. + * + * Extracts length number of bits starting from bit position + * start in 32-bit value. + * + * @param[in] value 32-bit value. + * @param[in] start Starting bit position. + * @param[in] length Number of bits to be extracted. + * + * @return integer Extracted value. + */ +inline Uint32 +extract32(Uint32 value, int start, int length) +{ + AUD_ASSERT(start >= 0 && length > 0 && length <= 32 - start, + "Invalid start/size"); + + return (value >> start) & (~0U >> (32 - length)); +} + +/** + * @brief Helper function to convert Enum->Int + * + * @return Integer type of T + */ +template::value>::type> +inline constexpr auto +operator*(T const e) noexcept + -> std::enable_if_t::value, std::underlying_type_t> +{ + return static_cast>(e); +} + +template +UnderlyingType +enumToValue(EnumType enumValue) +{ + if (static_cast(enumValue) + < (std::numeric_limits::min)() + || static_cast(enumValue) + > (std::numeric_limits::max)()) { + AUD_ASSERT(0, + "Enum value out of range for conversion to underlying type"); + } + + return static_cast(enumValue); +} + +template +EnumType +valueToEnum(UnderlyingType value) +{ + /*if (value < EnumMin || value > EnumMax) + return static_cast();*/ + + return static_cast(value); +} + +} // namespace Au diff --git a/Library/Private/Au/Named.hh b/Library/Private/Au/Named.hh new file mode 100644 index 0000000..7e21240 --- /dev/null +++ b/Library/Private/Au/Named.hh @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/Foundations/Types.hh" + +namespace Au { +class Named +{ + public: + Named(String initial_name = String{ "" }) + : m_name(initial_name) + { + } + virtual ~Named() {} + + StringView getNameSafe(StringView defval) const + { + StringView str = m_name; + return str.length() ? str : defval; + } + + void setName(StringView newname) + { + if (m_name == newname) + return; + + m_name.assign(newname); + onSetName(); + } + // override to notify any name changes + virtual void onSetName() {} + + private: + String m_name; +}; + +} // namespace Au diff --git a/Library/Private/Au/Pattern/.clang-tidy b/Library/Private/Au/Pattern/.clang-tidy new file mode 100644 index 0000000..ae204c1 --- /dev/null +++ b/Library/Private/Au/Pattern/.clang-tidy @@ -0,0 +1,7 @@ +# File: project/external/.clang-tidy + +# Disable all checks in this folder. +# +Checks: '-*,misc-definitions-in-headers' +CheckOptions: + {HeaderFileExtensions: "x" } diff --git a/Library/Private/Au/Pattern/DisableMoveCopy.hh b/Library/Private/Au/Pattern/DisableMoveCopy.hh new file mode 100644 index 0000000..dfd1f7d --- /dev/null +++ b/Library/Private/Au/Pattern/DisableMoveCopy.hh @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2022-2022, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +namespace Au { + +class DisableCopy +{ + public: + virtual ~DisableCopy() {} + + protected: + DisableCopy(void) = default; + DisableCopy(const DisableCopy&) = delete; + DisableCopy& operator=(const DisableCopy&) = delete; +}; + +class DisableMove +{ + public: + virtual ~DisableMove() {} + + protected: + DisableMove(void) = default; + DisableMove(DisableMove&&) = delete; + DisableMove& operator=(DisableMove&&) = delete; +}; + +class DisableCopyMove + : public DisableCopy + , public DisableMove +{ + public: + virtual ~DisableCopyMove() {} + + protected: + DisableCopyMove(void) = default; +}; + +} // namespace Au diff --git a/Library/Private/Au/Pattern/Singleton.hh b/Library/Private/Au/Pattern/Singleton.hh new file mode 100644 index 0000000..eec1faf --- /dev/null +++ b/Library/Private/Au/Pattern/Singleton.hh @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2022-2022, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "Au/Private/DisableMoveCopy.hh" + +namespace Au { + +/** + * @brief: A Singleton Pattern class + * @details: An Object of Class which inherits from 'Singleton' class + * will be a single instance and prevent creation of objects + * + */ +template +class Singleton : public DisableCopyMove +{ + public: + static T& getInstance(void) + { + static T _impl; + return _impl; + } + + protected: + Singleton(void) = default; +}; + +} // namespace Au diff --git a/Library/Private/Au/SourceLocation.hh b/Library/Private/Au/SourceLocation.hh new file mode 100644 index 0000000..d2a4613 --- /dev/null +++ b/Library/Private/Au/SourceLocation.hh @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2022-2022, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#pragma once + +#include "Au/Au.hh" +#include "Au/Types.hh" + +namespace Au { + +/** + * Describes the location of a line of code. + * You can get one of these with #AUD_CURRENT_LINE. + */ +struct SourceLocation +{ + /// Called by #AUD_CURRENT_LINE only. + SourceLocation(const char* file, const Uint32 line, const char* function) + : SourceLocation{ file, line, function, nullptr } + { + } + + SourceLocation(const char* file, + const Uint32 line, + const char* function, + const char* prettyFunction) + : m_file{ file } + , m_line{ line } + , m_function{ function } + , m_pretty_function{ prettyFunction } + { + } + + String str() const + { + return Au::formatter(" ", + m_function, + "@", + this->relativeFile(), + ":", + std::to_string(m_line)); + } + + String relativeFile() const; + String qualifiedFunction() const; + + /// __FILE__ + const char* m_file; + /// __LINE__ + Uint32 m_line; + /// __func__ + const char* m_function; + /// __PRETTY_FUNCTION__ + const char* m_pretty_function; +}; + +#if defined(MSVC) +#define AUD_PRETTY_FUNCTION __FUNCSIG__ +#elif defined(__GNUC__) || defined(CLANG) +#define AUD_PRETTY_FUNCTION __PRETTY_FUNCTION__ +#endif + +/** + * Construct fully qualified source location + */ +#define AUD_SORUCE_LOCATION_PRETTY() \ + Au::SourceLocation(__FILE__, __LINE__, __func__, AUD_PRETTY_FUNCTION) + +#define AUD_SOURCE_LOCATION() Au::SourceLocation(__FILE__, __LINE__, __func__) + +} // namespace Au diff --git a/Library/Private/Au/ThreadPinning/Linux/CpuTopology.hh b/Library/Private/Au/ThreadPinning/Linux/CpuTopology.hh new file mode 100644 index 0000000..3f1497b --- /dev/null +++ b/Library/Private/Au/ThreadPinning/Linux/CpuTopology.hh @@ -0,0 +1,285 @@ +/* + * Copyright(c) 2024 Advanced Micro Devices, Inc.All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this softwareand 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 noticeand 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 +#include +#include +#include + +namespace Au { +typedef unsigned long DWORD; +typedef unsigned long KAFFINITY; +typedef std::pair CoreMask; + +class LogicalProcessorInformation +{ + + public: + std::string filename; + int cpuId; + DIR* dirp; + struct dirent* dp; // Pointer to the directory entry + + explicit LogicalProcessorInformation(const std::string& filename) + : filename(filename) + , cpuId(0) + , dirp(opendir("/sys/devices/system/cpu/")) + , dp(NULL) + { + } + // Copy constructor + LogicalProcessorInformation(LogicalProcessorInformation& other) + : filename(other.filename) + , cpuId(other.cpuId) + , dirp(other.dirp) + , dp(other.dp) + { + other.dp = NULL; + other.dirp = NULL; + } + // = operator + LogicalProcessorInformation& operator=(LogicalProcessorInformation& other) + { + if (this != &other) { + filename = other.filename; + cpuId = other.cpuId; + dirp = other.dirp; + dp = other.dp; + other.dp = NULL; + other.dirp = NULL; + } + return *this; + } + ~LogicalProcessorInformation() { closedir(dirp); } + /** + * @brief Move to the next directory entry. + * + * @details This function moves to the next directory + * corresponding to cpu, updates cpuid memeber variable + * + * @param[in] void + * + * @return void + */ + void MoveNext() + { + // Move to the next directory entry + while ((dp = readdir(dirp)) != NULL) { + std::string dirName(dp->d_name); + if (dirName.find("cpu") == 0 && isdigit(dirName[3])) { + cpuId = std::stoi(dirName.substr(3)); + break; + } + } + } + + /** + * @brief Parse the line and store the information. + * + * @details This function parses the line and stores the information in + * the Map. The line is a comma separated string of hexadecimal values. + * + * @param[out] std::vector& Map + * A vector of pairs that stores the mask and the position of + * the mask. obtained from parsing the line. + * + * @param[in] std::string line + * + * @return void + */ + void parseLine(std::vector& Map, std::string line) + { + std::reverse(line.begin(), line.end()); + std::stringstream ss(line); + int position = 0; + std::string chunk; + int nonZeroMask = 0; + + while (std::getline(ss, chunk, ',')) { + if (std::stoull(chunk, nullptr, 16)) { + std::reverse(chunk.begin(), chunk.end()); + + Map.resize(nonZeroMask + 1); + Map[nonZeroMask].first = std::stoull(chunk, nullptr, 16); + Map[nonZeroMask].second = position; + + nonZeroMask++; + } + position++; + } + } + + /** + * @brief Process the file and store the information. + * + * @details This function processes the file and stores the information + * in the Map. The file is a comma separated string of hexadecimal values. + * + * @param[out] std::vector& Map + * A vector of pairs that stores the mask and the position of + * the mask. obtained from parsing the line. + * + * @param[in] std::ifstream& file + * + * @return void + */ + void processFile(std::vector& Map, std::ifstream& file) + { + std::string line; + if (getline(file, line)) + parseLine(Map, line); + } + + /** + * @brief Get the current directory entry. + * + * @details This function gets the current directory entry. + * + * @param[out] std::vector& Map + * A vector of pairs that stores the mask and the position of + * the mask. obtained from parsing the line. + * + * @return void + */ + void Current(std::vector& Map) + { + if (dp) { + std::string dirName(dp->d_name); + std::ifstream file("/sys/devices/system/cpu/" + dirName + filename); + // check if file is open, for offline cpus the file will not be + // present. + // Hence will fail to open. + if (file.is_open()) { + processFile(Map, file); + } + } + } +}; + +class CpuTopology +{ + private: + /** + * @brief Eliminate duplicates from the Map. + * + * @details This function eliminates duplicates from the Map. + * + * @param[in/out] std::vector>& + * Map A vector of unique pairs from the Map. + * @return void + */ + void eliminateDuplicates(std::vector>& Map) + { + std::sort(Map.begin(), Map.end()); + auto newMap = std::unique(Map.begin(), Map.end()); + Map.erase(newMap, Map.end()); + } + + /** + * @brief Compare two vectors. + * + * @details Used to reorder the vector after eliminating + * duplicates. + * + * @param[in] const std::vector& a + * A vector of pairs. + * @param[in] const std::vector& b + * A vector of pairs. + * + * @return bool + */ + static bool compareVectors(const std::vector& a, + const std::vector& b) + { + if (a[0].second == b[0].second) + return a[0].first < b[0].first; + else + return a[0].second < b[0].second; + } + + public: + uint32_t active_processors; + std::vector> processorMap; + std::vector> cacheMap; + std::vector groupMap; + + static const CpuTopology& get() + { + static const CpuTopology info; + return info; + } + + CpuTopology() + : active_processors(0) + , processorMap{} + , cacheMap{} + , groupMap{} + { + active_processors = get_nprocs(); + LogicalProcessorInformation processorInfo("/topology/thread_siblings"); + LogicalProcessorInformation cacheInfo("/cache/index3/shared_cpu_map"); + + // Collect the physical core -> logical core mapping + processorMap.resize(active_processors); + processorInfo.MoveNext(); + while (processorInfo.dp) { + processorInfo.Current(processorMap[processorInfo.cpuId]); + processorInfo.MoveNext(); + } + eliminateDuplicates(processorMap); + std::sort(processorMap.begin(), processorMap.end(), compareVectors); + + // Collect the L3 Cache --> Logical core mapping + cacheMap.resize(active_processors); + cacheInfo.MoveNext(); + while (cacheInfo.dp) { + cacheInfo.Current(cacheMap[cacheInfo.cpuId]); + cacheInfo.MoveNext(); + } + + eliminateDuplicates(cacheMap); + std::sort(cacheMap.begin(), cacheMap.end(), compareVectors); + + // Collect the Group --> Logical core mapping + groupMap.resize(active_processors); + for (size_t cpuId = 0; cpuId < processorMap.size(); cpuId++) { + for (auto processorMask : processorMap[cpuId]) { + int groupIndex = processorMask.second; + groupMap[groupIndex].first |= processorMask.first; + std::bitset<32> bits(processorMask.first); + groupMap[groupIndex].second += bits.count(); + } + } + while (!groupMap.back().first) { + groupMap.pop_back(); + } + } +}; +} // namespace Au diff --git a/Library/Private/Au/ThreadPinning/ThreadPinning.hh b/Library/Private/Au/ThreadPinning/ThreadPinning.hh new file mode 100644 index 0000000..c116cdc --- /dev/null +++ b/Library/Private/Au/ThreadPinning/ThreadPinning.hh @@ -0,0 +1,532 @@ +/* + * Copyright(c) 2024 Advanced Micro Devices, Inc.All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this softwareand 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 noticeand 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 + +#ifdef __linux__ +#include "Au/ThreadPinning/Linux/CpuTopology.hh" +#else +#include "Au/ThreadPinning/Windows/CpuTopology.hh" +#include +#endif + +#include "Au/Assert.hh" +#include +namespace Au { + +class AffinityVector +{ + protected: + const CpuTopology& cpuInfo; + + private: + /** + * @brief Calculate the offset + * + * @details This function calculates the offset based on the group + * and groupMap + * + * @param[in] group Group number + * + * @param[in] groupMap Map of groups + * + * @return int + */ + int calculateOffset(int group, const std::vector& groupMap) + { + int offset = 0; + if (group > 0) { + for (int i = 0; i < group; i++) { + offset += groupMap[i].second; + } + } + return offset; + } + + /** + * @brief Calculate the core number + * + * @details This function calculates the core number based on the + * bitMap + * + * @param[in] pMap ProcessorMap + * + * @return int + */ + int calculateCoreNum(CoreMask& pMap) + { + return log2(pMap.first & -1 * pMap.first); + } + + /** + * @brief Update the map + * + * @details This function updates the map by clearing the bit at + * coreId + * + * @param[in] pMap ProcessorMap + * + * @param[in] coreId Core number + * + * @return void + */ + void updateMap(CoreMask& pMap, int coreId) + { + pMap.first &= ~(1ULL << coreId); + } + + /** + * @brief Get the cache affinity map + * + * @details This function creates a map that maps the given threads + * to cache groups. + * + * @param[in] procVect Vector to store the spread affinity + * + * @param[out] cacheMap Map to store the cache affinity + * It is a map of cache number to a vector of thread indexes + * Example: + * cacheMap[0] = [0, 1, 2, 3] + * cacheMap[1] = [4, 5, 6, 7] + * Implies, threads at indices 0,1,2,3 are pinned to cache 0 and threads at + * indices 4,5,6,7 are pinned to cache 1 + * + * @return void + */ + void getCacheAffinityMap(int threadCount, + std::map>& cacheMap) + { + + std::vector procVect(threadCount); + createVector( + procVect, 0, threadCount - 1, 0, cpuInfo.cacheMap.size() - 1); + for (size_t thread = 0; thread < procVect.size(); thread++) { + int coreNum = procVect[thread]; + cacheMap[coreNum].push_back(thread); + } + } + + /** + * @brief CoreMapToCoreList + * + * @details Convert the given bitmap to a list of core numbers + * + * @param[in] processorMap Bitmap of processors + * + * @param[out] coreList List of core numbers + * + * @return void + */ + void coreMapToCoreList(const std::vector& processorMap, + std::vector& coreList) + { + for (auto pMap : processorMap) { + while (pMap.first > 0) { + coreList.push_back( + calculateCoreNum(pMap) + + calculateOffset(pMap.second, cpuInfo.groupMap)); + updateMap(pMap, calculateCoreNum(pMap)); + } + } + } + + /** + * @brief Check if the processorMap is reset + * + * @details This function checks if the processorMap is reset + * + * @param[in] processorMap ProcessorMap to check + * + * @return bool + */ + bool isReset(std::vector>& processorMap) + { + return std::all_of( + processorMap.begin(), processorMap.end(), [](auto& pMap) { + return ( + std::all_of(pMap.begin(), pMap.end(), [](const auto& p) { + return p.first == 0; + })); + }); + } + + /** + * @brief Skip the mask + * + * @details This return true if all the bits in the mask is 0 + * + * @param[in] pMap corMask + * + * @param[in] maskIndex Index of the mask + * + * @param[in] processorMap ProcessorMap + * + * @return bool + */ + + bool skipMask(CoreMask& pMap, + size_t& maskIndex, + const std::vector& processorMap) + { + if (pMap.first == 0 && maskIndex == processorMap.size()) { + maskIndex = 0; + return true; + } else if (pMap.first == 0 && maskIndex < processorMap.size()) { + pMap = processorMap[maskIndex]; + maskIndex++; + } + return false; + } + /** + * @brief Create a vector + * + * @details This function creates a vector that equally distributes + * the threads among the processors. + * + * @param[out] procVect Vector to store the spread affinity + * + * @param[in] tListStart Start index of threadList + * + * @param[in] tListEnd End index of threadList + * + * @param[in] pListStart Start index of processorList + * + * @param[in] pListEnd End index of processorList + * + * @return void + */ + void createVector(std::vector& procVect, + int tListStart, + int tListEnd, + int pListStart, + int pListEnd) + { + if (tListStart > tListEnd + || pListStart > pListEnd) // Base case: no elements left in + // threadList or processorList + return; + if (tListStart + == tListEnd) // Base case: There are more processors than threads + { + // Pin each thread as spread out as possible + procVect[tListStart] = pListStart; + return; + } + if (pListStart + == pListEnd) // Base case: There are more threads than processors + { + // Equally distribute the threads among the processors to the extend + // possible + for (int index = tListStart; index <= tListEnd; index++) + procVect[index] = pListStart; + return; + } + int tListMiddle = (tListEnd - tListStart) / 2 + + tListStart; // Middle index of threadList + int pListMiddle = (pListEnd - pListStart) / 2 + + pListStart; // Middle index of processorList + + // Recursively process the left and right halves of the threadList and + // processorList + createVector(procVect, + tListStart, + tListMiddle, + pListStart, + pListMiddle); // Left half + createVector(procVect, + tListMiddle + 1, + tListEnd, + pListMiddle + 1, + pListEnd); // Right half + } + + // clang-format off + /** + * @brief Update the final affinity vector + * + * @details This function updates the affinity vector by + * distributing the threads in the procVectPerCache among the cores in the + * coreList + * + * @param[out] procVect Vector to store the affinity + * + * @param[in] procVectPerCache Affinity vector for a cache[ holds + * the index of cores in the coreList] + * Example + * coreList = [8, 9, 10, 11, 12, 13, 14, 15] + * procVectPerCache = [0, 2, 4, 6] + * Implies, threadindices at indices 0,1,2,3 of threads vector are pinned to + * cores 8, 10, 12, 14 + * Example + * threads = [0, 1, 5, 6] + * Implies + * + * thread at 0th index in threads is pinned to core at 0th index of coreList, + * thread at 1st index in threads is pinned to core at 2nd index of coreList, + * thread at 5th index in threads is pinned to core at 4th index of coreList, + * thread at 6th index in threads is pinned to core at 6th index of coreList + * + * threads holds the indices of the threads in the input threadlist to be + * pinned to the cores procVectPerCache holds the indices of the cores in + * the coreList to which the threads are to be pinned there is a one to one + * mapping between the threads and procVectPerCache + * @param[in] coreList List of core numbers sharing the + * cache + * + * @param[in] threads List of threadindices to be pinned + * to the cores sharing the cache. + */ + // clang-format on + void updateprocVect(std::vector& procVect, + const std::vector& procVectPerCache, + const std::vector& coreList, + const std::vector& threads) + { + int index = 0; + for (auto thread : threads) { + int item = procVectPerCache[index++]; + int coreNum = coreList[item]; + procVect[thread] = coreNum; + } + } + + /** + * @brief Update the final affinity vector + * + * @details This function updates the affinity vector based on the + * processorMap and the threadCount + * It updates the affinity vector by picking one core from + * a processor at a time and then moving to the next + * processor. + * + * @param[out] procVect Vector to store the affinity + * + * @param[in] processorMap The processor topology + * + * @param[in] pMap A single core mask corresponding to each + * processor (Processors can have multiple coremasks of 64 bits each) + * + * @param[in] maskIndex Index of the coremask in the processor's + * mask list + * + * @param[in] threadCount Number of threads to pin + * + * @param[in,out] threadId Index of the thread to pin + */ + void updateprocVect(std::vector& procVect, + const std::vector>& processorMap, + std::vector& pMap, + std::vector& maskIndex, + int threadCount, + int& threadId) + { + + for (size_t coreId = 0; coreId < processorMap.size(); coreId++) { + if (skipMask(pMap[coreId], maskIndex[coreId], processorMap[coreId])) + continue; + + procVect.push_back( + calculateCoreNum(pMap[coreId]) + + calculateOffset(pMap[coreId].second, cpuInfo.groupMap)); + updateMap(pMap[coreId], calculateCoreNum(pMap[coreId])); + + threadId++; + if (threadId == threadCount) + return; + } + } + + public: + AffinityVector(const CpuTopology& Info = CpuTopology::get()) + : cpuInfo{ Info } + { + } + + /** + * @brief Get the spread affinity vector + * + * @details This function creates a vector that maps the threads to + * cache groups. + * + * @param[out] procVect Vector to store the spread affinity + * + * @return void + */ + void getSpreadAffinityVectory(std::vector& procVect) + { + std::map> cacheMap; + getCacheAffinityMap(procVect.size(), cacheMap); + + for (auto& cache : cacheMap) { + if (cpuInfo.cacheMap.size() != 0){ + auto processorMap = cpuInfo.cacheMap[cache.first]; + std::vector coreList; + coreMapToCoreList(processorMap, coreList); + + int threadCount = cache.second.size(); + std::vector procVectPerCache(threadCount); + createVector( + procVectPerCache, 0, threadCount - 1, 0, coreList.size() - 1); + if (procVectPerCache.size() != 0 && coreList.size() != 0) + updateprocVect(procVect, procVectPerCache, coreList, cache.second); + } + } + } + /** + * @brief Get the core affinity vector + * + * @details This function creates a vector that maps the threads to + * physical cores. + * + * @param[out] procVect Vector to store the core affinity + * + * @return void + */ + void getCoreAffinityVector(std::vector& procVect) + { + auto processorMap = cpuInfo.processorMap; + int threadCount = procVect.size(); + int threadId = 0; + + std::vector maskIndex(processorMap.size(), 1); + std::vector pMap; + for (const auto& core : processorMap) { + pMap.push_back(core[0]); + } + + procVect.clear(); + while (threadId < threadCount) { + if (isReset(processorMap)) { + // if all the cores are used, reset the processorMap + processorMap = cpuInfo.processorMap; + } + updateprocVect( + procVect, processorMap, pMap, maskIndex, threadCount, threadId); + } + } + + /** + * @brief Get the logical core affinity vector + * + * @details This function creates a vector that maps the threads to + * logical cores. + * + * @param[out] procVect Vector to store the logical core affinity + * + * @return void + */ + void getLogicalAffinityVector(std::vector& procVect) + { + int threadCount = procVect.size(); + + procVect.clear(); + for (int threadId = 0; threadId < threadCount; threadId++) { + procVect.push_back(threadId % cpuInfo.active_processors); + } + } + + /** + * @brief getAffinityVector + * + * @details Get the affinity vector based on the pinning strategy + * + * @param[in] pinStrategyIndex 0 - spread , 1 - Core, 2 - Logical + * Processor + * + * @param[out] processPinGroup Vector to store the affinity vector + * + * @return None + */ + void getAffinityVector(std::vector& processPinGroup, + int pinStrategyIndex) + { + switch (pinStrategyIndex) { + case pinStrategy::SPREAD: + getSpreadAffinityVectory(processPinGroup); + break; + case pinStrategy::CORE: + getCoreAffinityVector(processPinGroup); + break; + case pinStrategy::LOGICAL: + getLogicalAffinityVector(processPinGroup); + break; + default: + break; + } + } + + /** @brief setAffinity + * + * @details Pin Threads to a specific processor group. + * + * @param[in] threadList ThreadIds to pin + * + * @param[in] processorList List of processors to pin the threads + */ + void setAffinity(std::vector const& threadList, + std::vector const& processorList) + { + for (size_t i = 0; i < threadList.size(); i++) { + // Pin the thread to the processor + AUD_ASSERT(processorList[i] < std::thread::hardware_concurrency(), + "Invalid processor Id"); +#ifdef __linux__ + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(processorList[i], &cpuset); + pthread_setaffinity_np(threadList[i], sizeof(cpu_set_t), &cpuset); +#else + GROUP_AFFINITY groupAffinity; + ZeroMemory(&groupAffinity, sizeof(GROUP_AFFINITY)); + // calculate the group and mask from the processor number and + // cpuInfo.groupMap + int core = 0; + int group = 0; + for (auto gMap : cpuInfo.groupMap) { + if (processorList[i] > core + gMap.second - 1) { + core = core + gMap.second; + group++; + } else { + break; + } + } + + groupAffinity.Mask = 1ull << (processorList[i] - core); + groupAffinity.Group = group; + HANDLE hThread = (HANDLE)threadList[i]; + auto result = + SetThreadGroupAffinity(hThread, &groupAffinity, nullptr); + if (!result) { + std::cout << "SetThreadGroupAffinity Failed\n"; + } +#endif + std::cout << "Thread " << threadList[i] << " is pinned to processor " + << processorList[i] << std::endl; + + } + } +}; +} // namespace Au diff --git a/Library/Private/Au/ThreadPinning/Windows/CpuTopology.hh b/Library/Private/Au/ThreadPinning/Windows/CpuTopology.hh new file mode 100644 index 0000000..4bff659 --- /dev/null +++ b/Library/Private/Au/ThreadPinning/Windows/CpuTopology.hh @@ -0,0 +1,215 @@ +/* + * Copyright(c) 2024 Advanced Micro Devices, Inc.All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this softwareand 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 noticeand 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 "Au/Config.h" +#include +#include +#include +#include +#include +#include +#include + +namespace Au { +typedef std::pair CoreMask; +using SLPIEX = SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX; +// if compiler is msvc +/** + * @brief Advance a pointer by a number of bytes. + * + * @details Utility function to iterate through the processor information + * buffer. + * + * @param[in] p Pointer to the current position in the buffer. + * @param[in] cb Number of bytes to advance the pointer. + * + * @return Pointer to the new position in the buffer. + */ +template +T* +AdvanceBytes(T* p, SIZE_T cb) +{ + return reinterpret_cast(reinterpret_cast(p) + cb); +} + +/** + * @brief Class to iterate through the logical processor information + * buffer. + * + * @details This class is used to iterate through the logical processor + * information buffer. + * + * @param[in] Relationship The type of information to retrieve. + * + */ +class LogicalProcessorInformation +{ + public: + LogicalProcessorInformation(LOGICAL_PROCESSOR_RELATIONSHIP Relationship) + : m_bufferBase(nullptr) + , m_bufferCurrent(nullptr) + , m_bufferRemaining(0) + { + DWORD bufferSize = 0; + if (GetLogicalProcessorInformationEx( + Relationship, nullptr, &bufferSize)) + return; + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + return; + m_bufferBase = + reinterpret_cast( + LocalAlloc(LMEM_FIXED, bufferSize)); + if (!m_bufferBase) + return; + if (!GetLogicalProcessorInformationEx( + Relationship, m_bufferBase, &bufferSize)) + return; + m_bufferCurrent = m_bufferBase; + m_bufferRemaining = bufferSize; + } + + ~LogicalProcessorInformation() { LocalFree(m_bufferBase); } + + /** + * @brief Move to the next logical processor information entry. + * + * @details This function moves the iterator to the next logical + * processor information entry. + * + * @return void + */ + void MoveNext() + { + if (m_bufferCurrent) { + m_bufferRemaining -= m_bufferCurrent->Size; + if (m_bufferRemaining) { + m_bufferCurrent = + AdvanceBytes(m_bufferCurrent, m_bufferCurrent->Size); + } else { + m_bufferCurrent = nullptr; + } + } + } + + /** + * @brief Get the current logical processor information entry. + * + * @details This function returns the current logical processor + * information entry. + * + * @return Pointer to the current logical processor information entry. + */ + SLPIEX* Current() { return m_bufferCurrent; } + + private: + SLPIEX* m_bufferBase; + SLPIEX* m_bufferCurrent; + DWORD m_bufferRemaining; +}; + +class CpuTopology +{ + public: + uint32_t active_processors; + std::vector> processorMap; + std::vector> cacheMap; + std::vector groupMap; + + static const CpuTopology& get() + { + static const CpuTopology info; + return info; + } + + CpuTopology() + : active_processors(0) + , processorMap{} + , cacheMap{} + , groupMap{} + { + active_processors = GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); + LogicalProcessorInformation processorInfo(RelationProcessorCore); + LogicalProcessorInformation cacheInfo(RelationCache); + LogicalProcessorInformation groupInfo(RelationGroup); + +#ifdef AU_COMPILER_IS_MSVC + for (; auto pInfo = processorInfo.Current(); processorInfo.MoveNext()) { + // Collect the physical core -> logical core mapping + processorMap.push_back( + { std::make_pair(pInfo->u.Processor.GroupMask->Mask, + pInfo->u.Processor.GroupMask->Group) }); + } + + for (; auto cInfo = cacheInfo.Current(); cacheInfo.MoveNext()) { + // Collect the L3 Cache --> Logical core mapping + if (cInfo->u.Cache.Level == 3 + && (cInfo->u.Cache.Type == CacheData + || cInfo->u.Cache.Type == CacheUnified)) { + std::vector cachePMap; + for (auto i = 0; i < cInfo->u.Cache.GroupCount; i++) + cachePMap.push_back( + std::make_pair(cInfo->u.Cache.u.GroupMasks[i].Mask, + cInfo->u.Cache.u.GroupMasks[i].Group)); + if (cachePMap.size() != 0) + cacheMap.push_back(cachePMap); + } + } + for (; auto gInfo = groupInfo.Current(); groupInfo.MoveNext()) { + // Collect the Group --> Logical core mapping + for (auto i = 0; i < gInfo->u.Group.ActiveGroupCount; i++) + groupMap.push_back(std::make_pair( + gInfo->u.Group.GroupInfo[i].ActiveProcessorMask, + gInfo->u.Group.GroupInfo[i].ActiveProcessorCount)); + } +#else + for (; auto pInfo = processorInfo.Current(); processorInfo.MoveNext()) { + // Collect the physical core -> logical core mapping + processorMap.push_back( + { std::make_pair(pInfo->Processor.GroupMask->Mask, + pInfo->Processor.GroupMask->Group) }); + } + + for (; auto cInfo = cacheInfo.Current(); cacheInfo.MoveNext()) { + // Collect the L3 Cache --> Logical core mapping + std::vector cachePMap; + if (cInfo->Cache.Level == 3 + && (cInfo->Cache.Type == CacheData + || cInfo->Cache.Type == CacheUnified)) { + for (auto i = 0; i < cInfo->Cache.GroupCount; i++) + cachePMap.push_back( + std::make_pair(cInfo->Cache.GroupMasks[i].Mask, + cInfo->Cache.GroupMasks[i].Group)); + if (cachePMap.size() != 0) + cacheMap.push_back(cachePMap); + } + } + for (; auto gInfo = groupInfo.Current(); groupInfo.MoveNext()) { + // Collect the Group --> Logical core mapping + for (auto i = 0; i < gInfo->Group.ActiveGroupCount; i++) + groupMap.push_back(std::make_pair( + gInfo->Group.GroupInfo[i].ActiveProcessorMask, + gInfo->Group.GroupInfo[i].ActiveProcessorCount)); + } +#endif + } +}; +} // namespace Au diff --git a/Library/Private/Os/DynamicLoader_Linux.hh b/Library/Private/Os/DynamicLoader_Linux.hh new file mode 100644 index 0000000..b6c91f6 --- /dev/null +++ b/Library/Private/Os/DynamicLoader_Linux.hh @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#pragma once + +#include "Au/Au.hh" +#include "Au/DynamicLoader.hh" +#include "Au/Status.hh" + +#include + +namespace Au { + +class DynamicLibrary::Impl +{ + public: + Impl(String const& path) + : m_handle{ nullptr } + { + } + + ~Impl() { unload(); } + + Status load(String const& name) const; + void* getSymbol(String const& name) const; + void unload() const; + + /******* + * Delete copy/assignment + *******/ + Impl(const Au::DynamicLibrary::Impl&) = delete; + Impl& operator=(const Au::DynamicLibrary::Impl&) = delete; + + private: + mutable void* m_handle; + // String m_path; +}; + +} // namespace Au diff --git a/Library/Private/Os/Env.hh b/Library/Private/Os/Env.hh new file mode 100644 index 0000000..cea490f --- /dev/null +++ b/Library/Private/Os/Env.hh @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include "Au/Config.h" + +#include "Au/Au.hh" +#include + +#ifdef AU_TARGET_OS_IS_LINUX +#include +extern const char** environ; +#else +#include +#endif + +#include +#include +#include + +namespace Au { namespace Os::Env { + + using env_map = std::map>; + + const String spaces = "\t\n\r "; + static inline String& trim_left(String& sv) + { + sv.erase(0, sv.find_first_not_of(spaces)); + return sv; + } + + static inline String& trim_right(String& sv) + { + sv.erase(sv.find_last_not_of(spaces) + 1); + return sv; + } + + static inline String trim(String sv) + { + return trim_left(trim_right(sv)); + } + + using env_tuple = std::tuple; + static inline env_tuple split(String sv) + { + auto pos = sv.find('='); + AUD_ASSERT(pos > 0 && pos < sv.length(), "Invalid pos"); + auto key = trim(sv.substr(0, pos)); + auto val = trim(sv.substr(pos + 1, sv.length())); + + return std::make_tuple(key, val); + } + + static env_map _getAll() + { + env_map __env; + auto envp = environ; + + for (; envp && *envp; ++envp) { + String s(*envp); + auto keyval = split(s); + auto& [key, val] = keyval; + __env[key] = val; + } + + return __env; + } + + env_map getAll() + { + return _getAll(); + } +}} // namespace Au::Os::Env diff --git a/Library/Private/Os/Thread.hh b/Library/Private/Os/Thread.hh new file mode 100644 index 0000000..22ae7f4 --- /dev/null +++ b/Library/Private/Os/Thread.hh @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/Au.hh" + +#include +#include + +#if defined(AU_OS_IS_LINUX) +#include +#define +#else /* WIN32 */ +#include "System.h" +#endif + +namespace Au::Os { + +#if defined(AU_OS_IS_LINUX) +using ThreadIdT = pthread_t; +using ThreadFuncT = std::function; +#else +using ThreadIdT = void*; +using ThreadFuncT = void (*)(); +#endif + +ThreadIdT +getId() +{ +} + +} // namespace Au::Os diff --git a/Library/Tests/.clang-tidy b/Library/Tests/.clang-tidy new file mode 100644 index 0000000..ae204c1 --- /dev/null +++ b/Library/Tests/.clang-tidy @@ -0,0 +1,7 @@ +# File: project/external/.clang-tidy + +# Disable all checks in this folder. +# +Checks: '-*,misc-definitions-in-headers' +CheckOptions: + {HeaderFileExtensions: "x" } diff --git a/Library/Tests/BitMapTest.cc b/Library/Tests/BitMapTest.cc new file mode 100644 index 0000000..f6ec87e --- /dev/null +++ b/Library/Tests/BitMapTest.cc @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/BitMap.hh" + +#include "gtest/gtest.h" + +namespace { + +using namespace Au; + +TEST(BitMap, Construct) +{ + BitMap b(10); + EXPECT_EQ(b.size(), 10); + + /* This should fail for 0 size in debug mode */ + if (AU_ENABLE_ASSERTIONS) { + ASSERT_ANY_THROW({ + BitMap b1(0); + EXPECT_EQ(b1.size(), 0); + EXPECT_EQ(b1.count(), 0); + b1.set(0); + }); + } + + BitMap b2(1); + EXPECT_EQ(b2.size(), 1); + b2.set(0); + EXPECT_EQ(b2.count(), 1); +} + +TEST(BitMap, Zero) +{ + BitMap b(10); + + EXPECT_TRUE(b.isZero()); + + b.set(1); + EXPECT_FALSE(b.isZero()); +} + +TEST(BitMap, isFullApi) +{ + { /* Test for 1 bit */ + BitMap one(1); + one.set(); + EXPECT_TRUE(one.isFull()); + } + + { /* Some randome length within a 'word' */ + BitMap eleven(11); + eleven.set(); + EXPECT_TRUE(eleven.isFull()); + } + + { /* At word boundary */ + BitMap b1(64); + b1.set(); + EXPECT_TRUE(b1.isFull()); + } + + { /* just crossing word boundary */ + BitMap b2(65); + b2.set(); + EXPECT_TRUE(b2.isFull()); + } +} + +TEST(BitMap, SetApi) +{ + /* Test set() API */ + BitMap b1(11); + + b1.set(); + EXPECT_EQ(b1.count(), 11); + + /* TODO: Add word-boundary tests + * - width 63 + * - width 64 (one bit in next word) + */ +} + +TEST(BitMap, SetPosApi) +{ + /* Test set(pos) API */ + BitMap b(12); + + b.set(0); + EXPECT_EQ(b.count(), 1); + b.set(1); + EXPECT_EQ(b.count(), 2); + b.set(9); + EXPECT_EQ(b.count(), 3); + /* out of bound, count should remain as before */ + if (AU_ENABLE_ASSERTIONS) { + ASSERT_ANY_THROW(b.set(13)); + EXPECT_EQ(b.count(), 3); + } + + BitMap b1(63); + /* Around word boundary */ + b1.set(62); + EXPECT_EQ(b1.count(), 1); + + /* out of bound, count() should remain as before */ + if (AU_ENABLE_ASSERTIONS) { + ASSERT_ANY_THROW({ + b1.set(64); + EXPECT_EQ(b1.count(), 1); + }); + } +} + +/* Test setting bits from another bit map, equal in size */ +TEST(BitMap, SetBitMapApi) +{ + BitMap b(14); + b.set(); /* set-all bits */ + EXPECT_EQ(b.count(), 14); + EXPECT_TRUE(b.isFull()); + + BitMap b1(14); + b1.set(b); + EXPECT_EQ(b1.count(), 14); + EXPECT_TRUE(b1.isFull()); +} + +/* word-boundary crossing tests + * - consider 2 bitmaps a, b + * - b.size() > a.size(), 'b' width 63, 64 + */ +TEST(BitMap, SetBitMapApiGreater) +{ + { + BitMap b(14); + b.set(); /* set-all bits */ + EXPECT_TRUE(b.isFull()); + + BitMap b1(12); + b1.set(b); + EXPECT_EQ(b1.count(), 12); + EXPECT_TRUE(b1.isFull()); + } // namespace + + { /* One cross, other is exact or */ + BitMap b(64), b1(63); + b.set(); + + b1.set(b); + EXPECT_EQ(b1.count(), 63); + EXPECT_TRUE(b1.isFull()); + } + + { + BitMap b(66), b1(64); + b.set(); + + b1.set(b); + EXPECT_EQ(b1.count(), 64); + EXPECT_TRUE(b1.isFull()); + } +} + +/* Add word-boundary crossing tests + * - consider 2 bitmaps a, b + * - b.size() < a.size(), 'b' width 63, 64 + */ +TEST(BitMap, SetBitMapApiLesser) +{ + BitMap b(12); + b.set(); /* set-all bits */ + EXPECT_TRUE(b.isFull()); + + BitMap b1(14); + b1.set(b); + EXPECT_EQ(b1.count(), 12); + EXPECT_FALSE(b1.isFull()); +} + +TEST(BitMap, CountApi) +{ + BitMap b(13); + + b.set(1); + EXPECT_EQ(b.count(), 1); + + b.set(9); + EXPECT_EQ(b.count(), 2); + + /* Crossing boundary */ + BitMap b1(65); + EXPECT_EQ(b1.size(), 65); + b1.set(); + EXPECT_EQ(b1.count(), 65); + b1.clear(); + EXPECT_EQ(b1.count(), 0); + b1.set(64); + b1.set(1); + EXPECT_EQ(b1.count(), 2); +} + +TEST(BitMap, ClearApi) +{ + BitMap b(14); + b.set(0); + b.set(13); + EXPECT_EQ(b.count(), 2); + + b.clear(); + EXPECT_EQ(b.count(), 0); +} + +TEST(BitMap, ClearPosApi) +{ + BitMap b(14); + b.set(0); + b.set(13); + EXPECT_EQ(b.count(), 2); + + b.clear(0); + EXPECT_EQ(b.count(), 1); + b.clear(13); + EXPECT_EQ(b.count(), 0); + EXPECT_TRUE(b.isZero()); +} + +TEST(BitMap, ClearBitMapApi) +{ + BitMap b(14), b1(14); + b.set(); /* set-all bits */ + EXPECT_TRUE(b.isFull()); + + b1.set(b); /* set all 14 bits */ + EXPECT_EQ(b1.count(), 14); + EXPECT_TRUE(b1.isFull()); + + b1.clear(b); /* clear all 14 bits */ + EXPECT_TRUE(b1.isZero()); + EXPECT_EQ(b1.count(), 0); +} + +TEST(BitMap, ClearBitMapApiGreater) +{ + { + BitMap b(14), b1(16); + b.set(); /* set-all bits */ + EXPECT_TRUE(b.isFull()); + + b1.set(); /* set all bits */ + b1.clear(b); /* clear 14 bits */ + EXPECT_TRUE(b1.isClear(0)); + EXPECT_TRUE(b1.isSet(14)); + EXPECT_TRUE(b1.isSet(15)); + EXPECT_EQ(b1.count(), 2); + } + + { + BitMap b(16), b1(14); + b.set(); /* set-all bits */ + EXPECT_TRUE(b.isFull()); + + b1.set(); /* set all bits */ + b1.clear(b); /* clear 14 bits */ + EXPECT_TRUE(b1.isZero()); + EXPECT_EQ(b1.count(), 0); + } + + { + BitMap c(63), c1(66); + c.set(); /* set-all bits */ + EXPECT_TRUE(c.isFull()); + + c1.set(); /* set all bits */ + c1.clear(c); /* clear 63 bits */ + EXPECT_TRUE(c1.isSet(63)); + EXPECT_TRUE(c1.isSet(64)); + EXPECT_TRUE(c1.isSet(65)); + EXPECT_EQ(c1.count(), 3); + } + + { + BitMap d(66), d1(63); + d.set(); /* set-all bits */ + EXPECT_TRUE(d.isFull()); + + d1.set(); /* set all bits */ + d1.clear(d); /* clear 14 bits */ + EXPECT_TRUE(d1.isZero()); + } +} + +} // namespace diff --git a/Library/Tests/BufferTest.cc b/Library/Tests/BufferTest.cc new file mode 100644 index 0000000..cf913b8 --- /dev/null +++ b/Library/Tests/BufferTest.cc @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2022-2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/Buffer.hh" + +#include "gtest/gtest.h" + +namespace { + +using namespace Au; +using namespace Au::Memory; + +TEST(BufferView, Create) +{ + std::byte buf[100]; + BufferView bp{ buf, sizeof(buf) }; + + EXPECT_EQ(bp.ptr(), &buf[0]); +} + +TEST(BufferView, Size) +{ + std::byte buf[100]; + BufferView bp{ buf, sizeof(buf) }; + + EXPECT_EQ(bp.size(), sizeof(buf)); +} + +TEST(BufferView, Erase) +{ + std::byte buf[100]; + BufferView bp{ buf, sizeof(buf) }; + + EXPECT_EQ(bp.size(), sizeof(buf)); +} + +TEST(Buffer, Create) +{ + Buffer b{ 100 }; + EXPECT_TRUE(b.ptr() == nullptr); +} + +/* We dont support allocation yet */ +TEST(Buffer, Allocate) +{ + Buffer b{ 100 }; + EXPECT_TRUE(b.ptr() == nullptr); + + EXPECT_TRUE(b.allocate(10, 8) != nullptr); + EXPECT_TRUE(b.ptr() != nullptr); + EXPECT_TRUE(b.size() == 10); + EXPECT_TRUE(b.alignment() == 8); +} + +TEST(BufferLocal, Create) +{ + constexpr Uint32 SIZE = 512; + BufferLocal bos{ SIZE }; + + EXPECT_EQ(bos.size(), SIZE); + + bos.ptr()[10] = (std::byte)0xff; + EXPECT_TRUE(bos.ptr()[10] == static_cast(0xff)); +} + +TEST(BufferLocal, Erase) +{ + constexpr Uint32 SIZE = 512; + BufferLocal bos{ SIZE }; + + EXPECT_TRUE(bos.ptr()[10] == static_cast(0xff)); + bos.erase(); + EXPECT_TRUE(bos.ptr()[10] == static_cast(0x0)); +} + +} // namespace diff --git a/Library/Tests/CMakeLists.txt b/Library/Tests/CMakeLists.txt new file mode 100644 index 0000000..c52afca --- /dev/null +++ b/Library/Tests/CMakeLists.txt @@ -0,0 +1,167 @@ +# +# Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +set(BASE_TEST_FILES + #DynamicLoaderTest.cc + ErrorTest.cc + EnvTest.cc + StatusTest.cc + StatusOrTest.cc + #BitOpsTest.cc + BitMapTest.cc +) + +set(MEMORY_TEST_FILES + #Memory/LocalBufferTest.cc + #Memory/BufferViewTest.cc +) + +set(CPUID_TEST_FILES + Cpuid/CpuidTest.cc + Cpuid/CapiTest.cc + Cpuid/Mock/CpuidUtilsTest.cc + Cpuid/Mock/X86CpuTest.cc + Cpuid/CpuidQemuTest.cc +) + +set(OTHER_TEST_FILES +) + +set(THREAD_PINNING_TEST_FILES + ThreadPinning/ThreadPinningTest.cc + ThreadPinning/ThreadPinningCapiTest.cc + ThreadPinning/ThreadPinningMockTest.cc +) +set(ALL_TEST_FILES + ${MEMORY_TEST_FILES} + ${BASE_TEST_FILES} + ${OTHER_TEST_FILES} + ${THREAD_PINNING_TEST_FILES} +) + +# Single test Files gets added in a Loop, more complex ones are below +# message(" Total Test Files: " ${ALL_TEST_FILES}) +foreach(testFile IN LISTS ALL_TEST_FILES) + get_filename_component(__TestName ${testFile} NAME_WE) + get_filename_component(__TestFile ${testFile} NAME) + + #cmake_path(GET testFile ROOT_NAME __path_root_name) + #message("path_root_name - " ${__path_root_name}) + #cmake_path(GET testFile ROOT_DIRECTORY __path_root_dir) + #message("path_root_dir - " ${__path_root_dir}) + #cmake_path(GET testFile ROOT_PATH __path_root_path) + #message("path_root_path - " ${__path_root_path}) + #cmake_path(GET testFile FILENAME __path_filename) + #message("path_filename - " ${__path_filename}) + #cmake_path(GET testFile STEM LAST_ONLY __path_stem) + #message("path_stem - " ${__path_stem}) + #cmake_path(GET testFile RELATIVE_PART __path_relative) + #message("path_relative - " ${__path_relative}) + #cmake_path(GET testFile PARENT_PATH __path_parent) + #message("path_parent - " ${__path_parent}) + + cmake_path(GET testFile PARENT_PATH __parent_path) + #message("parent_path - " ${__parent_path}) + cmake_path( + RELATIVE_PATH __parent_path + BASE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE __TestDir + ) + # message("Test-> " ${__TestName} + # " file-> " ${__TestFile} + # " dir -> " ${__TestDir} + # ) + au_cc_test(${__TestName} + SOURCES "${__TestFile}" + DIRECTORY ${__parent_path} + DEPENDS + au::aoclutils + #au_provider + ) +endforeach() + +########## +# Provider Tests +########## + +#list(FIND "provider" AU_MODULES_LIST EXISTS__) +#if (${EXISTS__} GREATER -1) +au_module_exists("provider" EXISTS__) +message("Exists " ${EXISTS__}) +if (${EXISTS__}) + set(PROVIDER_TEST_FILES + ProviderTest.cc + ) + set(PROVIDER_DIR "Provider") + set(PRVDR_FILES ${PROVIDER_TEST_FILES}) + list(TRANSFORM PRVDR_FILES PREPEND "${PROVIDER_DIR}/") + set_source_files_properties( + ${PRVDR_FILES} + PROPERTIES + #DIRECTORY "Provider" + INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/Library" + ) + + au_cc_test(ProviderTest + DIRECTORY + ${PROVIDER_DIR} + SOURCES + ${PROVIDER_TEST_FILES} + DEPENDS + au::provider + ) +endif() + +#au_cc_test(Base64Test +# DIRECTORY +# . +# SOURCES +# Base64Test.cc +# DEPENDS +# au::base64 +#) + +au_cc_test(CpuidTest + SOURCES + ${CPUID_TEST_FILES} + HEADERS Mock/MockTest.hh QemuTest.hh + DEPENDS + au::cpuid + EXTLIBRARY + Python3 +) +########## +# Dynamic Loader Tests +########## + +# au_cc_test(DynLoadTest +# #WINDOWS_DISABLED +# DIRECTORY tests/ +# SOURCES tests/DynamicLoaderTest.cc +# #HEADERS DynamicLoader.hh +# DEPENDS _module_lib +# ) diff --git a/Library/Tests/Cpuid/CapiTest.cc b/Library/Tests/Cpuid/CapiTest.cc new file mode 100644 index 0000000..0ceb9f3 --- /dev/null +++ b/Library/Tests/Cpuid/CapiTest.cc @@ -0,0 +1,227 @@ + +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Capi/au/cpuid/cpuid.h" +#include "Capi/au/enum.h" +#include "CpuidTest.hh" +#include "gtest/gtest.h" +#include +#include + +namespace { +using namespace Au; + +/** + * Tests that can run on host, DISABLED by default since tests doesn't add any + * value as the result is unknown on a physical machine + * The disabled tests are used by the QemuTest to verify the results of the + * Cpuid emulation in Qemu. + */ +TEST(CapiX86Cpuid, DISABLED_isAMD) +{ + EXPECT_TRUE(au_cpuid_is_amd(0)); +} +TEST(CapiX86Cpuid, DISABLED_hasFlagPositive) +{ + std::vector flags = readFromFile("FlagsT.txt"); + std::vector flagsArray; + flagsArray.reserve(flags.size() + 1); + + for (size_t i = 0; i < flags.size(); ++i) + flagsArray.push_back(flags[i].c_str()); + + auto result = au_cpuid_has_flags(0, flagsArray.data(), flags.size()); + EXPECT_TRUE(result); +} + +TEST(CapiX86Cpuid, DISABLED_hasFlagNegative) +{ + std::vector flags = readFromFile("FlagsF.txt"); + std::vector flagsArray; + + flagsArray.reserve(flags.size() + 1); + for (size_t i = 0; i < flags.size(); ++i) + flagsArray.push_back(flags[i].c_str()); + + auto result = au_cpuid_has_flags(0, flagsArray.data(), flags.size()); + EXPECT_FALSE(result); +} + +TEST(CapiX86Cpuid, hasFlags) +{ + String testflag; + if (AU_ENABLE_ASSERTIONS) { + std::vector testFlags = { testflag.data() }; + EXPECT_ANY_THROW(au_cpuid_has_flags(0, testFlags.data(), 1)); + // update testflag to have an invalid flag + testflag.assign("Test"); + testFlags = { testflag.data() }; + EXPECT_ANY_THROW(au_cpuid_has_flags(0, testFlags.data(), 1)); + EXPECT_ANY_THROW(au_cpuid_has_flags(0, testFlags.data(), 0)); + testflag.assign("avx512f"); + testFlags.push_back(testflag.data()); + EXPECT_ANY_THROW(au_cpuid_has_flags(0, testFlags.data(), 2)); + } +} + +TEST(CapiX86Cpuid, DISABLED_isUarch) +{ + EUarch uarch = readFromFile("Uarch.txt").front(); + + // verify the uarch passed from the qemu testcase. + if (uarch == EUarch::Zen) { + EXPECT_TRUE(au_cpuid_arch_is_zen(0)); + EXPECT_FALSE(au_cpuid_arch_is_zenplus(0)); + EXPECT_FALSE(au_cpuid_arch_is_zen2(0)); + EXPECT_FALSE(au_cpuid_arch_is_zen3(0)); + EXPECT_FALSE(au_cpuid_arch_is_zen4(0)); + EXPECT_FALSE(au_cpuid_arch_is_zen5(0)); + } else if (uarch == EUarch::ZenPlus) { + EXPECT_TRUE(au_cpuid_arch_is_zen(0)); + EXPECT_TRUE(au_cpuid_arch_is_zenplus(0)); + EXPECT_FALSE(au_cpuid_arch_is_zen2(0)); + EXPECT_FALSE(au_cpuid_arch_is_zen3(0)); + EXPECT_FALSE(au_cpuid_arch_is_zen4(0)); + EXPECT_FALSE(au_cpuid_arch_is_zen5(0)); + } else if (uarch == EUarch::Zen2) { + EXPECT_TRUE(au_cpuid_arch_is_zen(0)); + EXPECT_TRUE(au_cpuid_arch_is_zenplus(0)); + EXPECT_TRUE(au_cpuid_arch_is_zen2(0)); + EXPECT_FALSE(au_cpuid_arch_is_zen3(0)); + EXPECT_FALSE(au_cpuid_arch_is_zen4(0)); + EXPECT_FALSE(au_cpuid_arch_is_zen5(0)); + } else if (uarch == EUarch::Zen3) { + EXPECT_TRUE(au_cpuid_arch_is_zen(0)); + EXPECT_TRUE(au_cpuid_arch_is_zenplus(0)); + EXPECT_TRUE(au_cpuid_arch_is_zen2(0)); + EXPECT_TRUE(au_cpuid_arch_is_zen3(0)); + EXPECT_FALSE(au_cpuid_arch_is_zen4(0)); + EXPECT_FALSE(au_cpuid_arch_is_zen5(0)); + } else if (uarch == EUarch::Zen4) { + EXPECT_TRUE(au_cpuid_arch_is_zen(0)); + EXPECT_TRUE(au_cpuid_arch_is_zenplus(0)); + EXPECT_TRUE(au_cpuid_arch_is_zen2(0)); + EXPECT_TRUE(au_cpuid_arch_is_zen3(0)); + EXPECT_TRUE(au_cpuid_arch_is_zen4(0)); + EXPECT_FALSE(au_cpuid_arch_is_zen5(0)); + } else if (uarch == EUarch::Zen5) { + EXPECT_TRUE(au_cpuid_arch_is_zen(0)); + EXPECT_TRUE(au_cpuid_arch_is_zenplus(0)); + EXPECT_TRUE(au_cpuid_arch_is_zen2(0)); + EXPECT_TRUE(au_cpuid_arch_is_zen3(0)); + EXPECT_TRUE(au_cpuid_arch_is_zen4(0)); + EXPECT_TRUE(au_cpuid_arch_is_zen5(0)); + } +} + +TEST(CapiX86Cpuid, DISABLED_getVendorInfo) +{ + char buf[sizeof(VendorInfo) + 1]; + au_cpuid_get_vendor(0, buf, sizeof(buf)); + + String vInfo(buf); + String token; + std::stringstream ss(vInfo); + std::vector vendorInfo = {}; + int element = 0; + while (getline(ss, token, '\n')) { + element++; + vendorInfo.push_back(stoi(token)); + if (element == 5) { + break; + } + } + auto iter = vendorInfo.begin(); + + writeToFile::iterator>( + "VendorInfoC.txt", { iter, iter + 1, iter + 2, iter + 3, iter + 4 }); +} +TEST(CapiX86Cpuid, BCTEST) +{ + int core_num = 0; + if (alci_is_amd(core_num)) { + printf("AMD CPU detected...\n"); + } else { + // Intel Apis are not exposed. + printf("Unknown CPU detected...\n"); + } + printf("\nGetting ISA information for core 0\n"); + if (alci_arch_is_zen5(core_num)) { + printf("CPU supports zen5 ISA\n"); + } else if (alci_arch_is_zen4(core_num)) { + printf("CPU supports zen4 ISA\n"); + } else if (alci_arch_is_zen3(core_num)) { + printf("CPU supports zen3 ISA\n"); + } else if (alci_arch_is_zen2(core_num)) { + printf("CPU supports zen2 ISA\n"); + } else if (alci_arch_is_zen(core_num)) { + printf("CPU supports zen ISA\n"); + } else { + printf("CPU does not support zen or higher ISA or this Cpu is not " + "supported\n"); + } + printf("\nCpu Feature Identification...\n"); + // clang-format off + printf("TSC_ADJUST : %s\n", (alci_cpu_has_flag(core_num, ALC_E_FLAG_TSC_ADJUST) ? "yes" : "no")); + printf("AVX : %s\n", (alci_cpu_has_flag(core_num, ALC_E_FLAG_AVX) ? "yes" : "no")); + printf("AVXVNNI : %s\n", (alci_cpu_has_flag(core_num, ALC_E_FLAG_AVXVNNI) ? "yes" : "no")); + printf("AVX2 : %s\n", (alci_cpu_has_flag(core_num, ALC_E_FLAG_AVX2) ? "yes" : "no")); + printf("AVX512 : %s\n", (alci_cpu_has_flag(core_num, ALC_E_FLAG_AVX512F) ? "yes" : "no")); + // clang-format on + printf("checking alcpu apis\n"); + if (alcpu_is_amd()) { + printf("AMD CPU detected...\n"); + } else { + // Intel Apis are not exposed. + printf("Unknown CPU detected...\n"); + } + printf("\nGetting ISA information for core 0\n"); + if (alcpu_arch_is_zen5()) { + printf("CPU supports zen5 ISA\n"); + } else if (alcpu_arch_is_zen4()) { + printf("CPU supports zen4 ISA\n"); + } else if (alcpu_arch_is_zen3()) { + printf("CPU supports zen3 ISA\n"); + } else if (alcpu_arch_is_zen2()) { + printf("CPU supports zen2 ISA\n"); + } else if (alcpu_arch_is_zen()) { + printf("CPU supports zen ISA\n"); + } else { + printf("CPU does not support zen or higher ISA or this Cpu is not " + "supported\n"); + } + printf("\nCpu Feature Identification...\n"); + // clang-format off + printf("TSC_ADJUST : %s\n", (alcpu_flag_is_available(ALC_E_FLAG_TSC_ADJUST) ? "yes" : "no")); + printf("AVX : %s\n", (alcpu_flag_is_available(ALC_E_FLAG_AVX) ? "yes" : "no")); + printf("AVXVNNI : %s\n", (alcpu_flag_is_available(ALC_E_FLAG_AVXVNNI) ? "yes" : "no")); + printf("AVX2 : %s\n", (alcpu_flag_is_available(ALC_E_FLAG_AVX2) ? "yes" : "no")); + printf("AVX512 : %s\n", (alcpu_flag_is_available(ALC_E_FLAG_AVX512F) ? "yes" : "no")); +} +} // namespace diff --git a/Library/Tests/Cpuid/CpuidQemuTest.cc b/Library/Tests/Cpuid/CpuidQemuTest.cc new file mode 100644 index 0000000..d515050 --- /dev/null +++ b/Library/Tests/Cpuid/CpuidQemuTest.cc @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "Au/Types.hh" +#include "CpuidTest.hh" +#include "QemuTest.hh" + +namespace { +using namespace Au; +class QemuTest + : public QemuTestBase + , public ::testing::WithParamInterface< + std::tuple, EUarch>> +{ + protected: + /** + * @brief Run all the tests in testNames on the emulated cpu. + * @param cpuType The type of the cpu to emulate + * @param testNames The names of the tests to run + * + * @return std::vector The results of the tests + */ + static std::vector testAll(const String& cpuType, + const std::vector& testNames) + { + std::vector results; + for (const auto& testName : testNames) { + bool result = callQemuEmulator(cpuType.c_str(), testName.c_str()); + results.push_back(result); + } + return results; + } + + /** + * @brief Check if the emulated cpu has all the flags in the flags vector + * @param cpuType The type of the cpu to emulate + * + * @return bool The result of the test + */ + static bool hasFlagPositive(const String& cpuType) + { + String simnowdataPath = PROJECT_SOURCE_DIR; + simnowdataPath += "/Library/Tests/Cpuid/Mock/simnowdata/"; + std::filesystem::copy(simnowdataPath + cpuType + "/FlagsT.txt", + "FlagsT.txt"); + return callQemuEmulator(cpuType.c_str(), "hasFlagPositive"); + } + + /** + * @brief Check if the emulated cpu does not have any of the flags in the + * flags vector + * @param cpuType The type of the cpu to emulate + * + * @return bool The result of the test + */ + static bool hasFlagNegative(const String& cpuType) + { + String simnowdataPath = PROJECT_SOURCE_DIR; + simnowdataPath += "/Library/Tests/Cpuid/Mock/simnowdata/"; + std::filesystem::copy(simnowdataPath + cpuType + "/FlagsF.txt", + "FlagsF.txt"); + + return callQemuEmulator(cpuType.c_str(), "hasFlagNegative"); + } + + /** + * @brief Verifies the Uarch APIs for the emulated CPU + * @param cpuType The type of the cpu to emulate + * @param Uarch The type of the cpu to emulate + * + * @return bool The result of the test + */ + static bool TestUarch(const String& cpuType, const EUarch Uarch) + { + writeToFile("Uarch.txt", { Uarch }); + return callQemuEmulator(cpuType.c_str(), "Uarch"); + } +}; + +INSTANTIATE_TEST_SUITE_P(QemuTestSuite, + QemuTest, + ::testing::ValuesIn(testParametersX86Cpu)); + +TEST_P(QemuTest, CpuTypeTest) +{ +#if defined(AU_TARGET_OS_IS_LINUX) + const auto params = GetParam(); + const auto cpuType = std::get<0>(params); + const auto expectedResults = std::get<1>(params); + const auto uarch = std::get<2>(params); + + std::cout << "Emulating " << cpuType << std::endl; + const std::vector testNames = { "X86Cpuid.DISABLED_isAMD", + "X86Cpuid.DISABLED_isIntel", + "X86Cpuid.DISABLED_isX86_64v2", + "X86Cpuid.DISABLED_isX86_64v3", + "X86Cpuid.DISABLED_isX86_64v4" }; + + auto results = testAll(cpuType, testNames); + results.push_back(hasFlagPositive(cpuType)); + results.push_back(hasFlagNegative(cpuType)); + results.push_back(TestUarch(cpuType, uarch)); + EXPECT_EQ(results, expectedResults); + // Read the Uarch test result from the file + // and compare it with the Uarch value of the emulated CPU. + auto uarchResult = readFromFile("UarchResult.txt"); + if (!uarchResult.empty()) { + EXPECT_EQ(uarchResult[0], uarch); + } +#endif + return; +} + +class QemuTestVendorInfo + : public QemuTestBase + , public ::testing::WithParamInterface> +{ + protected: + /** + * @brief Runs the getVendorInfo test on the emulated cpu. + * @param cpuType The type of the cpu to emulate + * + * @return bool The result of the test + */ + bool TestVendorInfo(const String& cpuType) + { + return callQemuEmulator(cpuType.c_str(), "DISABLED_getVendorInfo"); + } +}; + +INSTANTIATE_TEST_SUITE_P(QemuTestSuite, + QemuTestVendorInfo, + ::testing::ValuesIn(testParametersVendorInfo)); +TEST_P(QemuTestVendorInfo, CpuTypeTest) +{ +#if defined(AU_TARGET_OS_IS_LINUX) + const auto params = GetParam(); + const auto cpuType = std::get<0>(params); + const auto expectedResults = std::get<1>(params); + std::vector vendorInfo = { + enumToValue(expectedResults.m_mfg), + enumToValue(expectedResults.m_family), + expectedResults.m_model, + expectedResults.m_stepping, + enumToValue(expectedResults.m_uarch) + }; + EXPECT_TRUE(TestVendorInfo(cpuType)); + std::vector vendorInfoResultC = + readFromFile("VendorInfoC.txt"); + std::vector vendorInfoResultCpp = + readFromFile("VendorInfoCpp.txt"); + EXPECT_EQ(vendorInfo, vendorInfoResultC); + EXPECT_EQ(vendorInfo, vendorInfoResultCpp); +#endif + return; +} +} // namespace diff --git a/Library/Tests/Cpuid/CpuidTest.cc b/Library/Tests/Cpuid/CpuidTest.cc new file mode 100644 index 0000000..8b67f42 --- /dev/null +++ b/Library/Tests/Cpuid/CpuidTest.cc @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "CpuidTest.hh" +#include "Au/Cpuid/Enum.hh" + +#include +#include +#include + +namespace { +using namespace Au; + +/** + * Tests that can run on host, DISABLED by default since tests doesn't add any + * value as the result is unknown on a physical machine + * The disabled tests are used by the QemuTest to verify the results of the + * Cpuid emulation in Qemu. + */ +TEST(X86Cpuid, DISABLED_isAMD) +{ + X86Cpu cpu{ 0 }; + EXPECT_TRUE(cpu.isAMD() == true); +} + +TEST(X86Cpuid, DISABLED_isX86_64v2) +{ + + X86Cpu cpu{ 0 }; + EXPECT_TRUE(cpu.isX86_64v2() == true); +} + +TEST(X86Cpuid, DISABLED_isX86_64v3) +{ + + X86Cpu cpu{ 0 }; + EXPECT_TRUE(cpu.isX86_64v3() == true); +} + +TEST(X86Cpuid, DISABLED_isX86_64v4) +{ + + X86Cpu cpu{ 0 }; + EXPECT_TRUE(cpu.isX86_64v4() == true); +} + +TEST(X86Cpuid, DISABLED_isIntel) +{ + + X86Cpu cpu{ 0 }; + EXPECT_TRUE(cpu.isIntel() == true); +} + +TEST(X86Cpuid, DISABLED_hasFlagPositive) +{ + X86Cpu cpu{ 0 }; + auto flags = readFromFile("FlagsT.txt"); + String token; + std::stringstream ss; + + ss << flags; + while (std::getline(ss, token, ':')) { + auto flag = stoi(token); + auto cpuid_flag = valueToEnum(flag); + EXPECT_TRUE(cpu.hasFlag(cpuid_flag)); + } +} + +TEST(X86Cpuid, DISABLED_hasFlagNegative) +{ + X86Cpu cpu{ 0 }; + auto flags = readFromFile("FlagsF.txt"); + String token; + std::stringstream ss; + + ss << flags; + while (std::getline(ss, token, ':')) { + auto flag = stoi(token); + auto cpuid_flag = valueToEnum(flag); + EXPECT_FALSE(cpu.hasFlag(cpuid_flag)); + } +} + +TEST(X86Cpuid, DISABLED_isUarch) +{ + EUarch uarch; + X86Cpu cpu{ 0 }; + + // verify the uarch passed from the qemu testcase. + uarch = readFromFile("Uarch.txt").front(); + EXPECT_TRUE(cpu.isUarch(uarch)); + + // Verify isUarch returns False for any microarchitecure higher than the + // current one + uarch = static_cast(static_cast(uarch) + 1); + EXPECT_FALSE(cpu.isUarch(uarch)); + + // Verify isUarch returns True for any microarchitecure lower than the + // current one. + uarch = static_cast(static_cast(uarch) - 2); + EXPECT_TRUE(cpu.isUarch(uarch)); + + // Verify isUarch returns false for any microarchitecure lower than the + // current one in strict mode + EXPECT_FALSE(cpu.isUarch(uarch, true)); + writeToFile("UarchResult.txt", { cpu.getUarch() }); +} + +TEST(X86Cpuid, DISABLED_getVendorInfo) +{ + X86Cpu cpu{ 0 }; + auto result = cpu.getVendorInfo(); + + std::vector vendorInfo = { + enumToValue(result.m_mfg), + enumToValue(result.m_family), + result.m_model, + result.m_stepping, + enumToValue(result.m_uarch) + }; + + auto iter = vendorInfo.begin(); + writeToFile::iterator>( + "VendorInfoCpp.txt", { iter, iter + 1, iter + 2, iter + 3, iter + 4 }); +} +TEST(X86Cpuid, CheckCpuNumber) +{ +// Verify that the core is set to the correct CPU +#ifdef __linux__ + cpu_set_t currentMask; + int tid = gettid(); + CpuNumT m_cpu = 0; + + sched_getaffinity(tid, sizeof(cpu_set_t), ¤tMask); + + for (m_cpu = 0; m_cpu < CPU_SETSIZE; ++m_cpu) { + if (CPU_ISSET(m_cpu, ¤tMask)) { + break; + } + } +#else + DWORD threadId = GetCurrentThreadId(); + CpuNumT m_cpu = 1; + // setThreadAffinityMask returns the current mask befor setting mask. + auto mask = (static_cast(1) << m_cpu); + auto currentMask = SetThreadAffinityMask(&threadId, mask); +#endif + if (m_cpu < std::thread::hardware_concurrency()) { + X86Cpu cpu2{ m_cpu + 1 }; + } else { + X86Cpu cpu2{ m_cpu - 1 }; + } + checkAffinity(currentMask); + // Verify that an exception is thrown when the core number is greater + // than the number of phycal cores. + if (AU_ENABLE_ASSERTIONS) { + auto nthreads = std::thread::hardware_concurrency(); + EXPECT_ANY_THROW(X86Cpu cpu3{ nthreads + 1 }); + } +} + +TEST(X86Cpu, BCTEST) +{ + alci::Cpu core{ 0 }; + + std::cout << "----- Platform details -----\n"; + std::cout << "Core info:\n----------\n"; + // The function name changed older api is core.isAmd + // std::cout << "Is AMD : " << (core.isAMD() ? "YES" : "NO") << + // "\n"; + // The function name and signature changed. older api is getVendor + // std::cout << "Vendor : " << core.getVendorInfo() << "\n"; + // The return value of the function changed. + std::cout << "Architecture : " << static_cast(core.getUarch()) + << "\n"; + + std::cout << "isUarchZen : " + << (core.isUarch(Uarch::eZen) ? "YES" : "NO") << "\n"; + std::cout << "isUarchZen2 : " + << (core.isUarch(Uarch::eZen2) ? "YES" : "NO") << "\n"; + std::cout << "isUarchZen3 : " + << (core.isUarch(Uarch::eZen3) ? "YES" : "NO") << "\n"; + std::cout << "isUarchZen4 : " + << (core.isUarch(Uarch::eZen4) ? "YES" : "NO") << "\n"; + std::cout << "isUarchZen5 : " + << (core.isUarch(Uarch::eZen5) ? "YES" : "NO") << "\n"; + + std::cout << "Features supported:\n-------------------\n"; + std::cout << "AVX support : " + << (core.isAvailable(ALC_E_FLAG_AVX) ? "YES" : "NO") << "\n"; + std::cout << "AVX2 support : " + << (core.isAvailable(ALC_E_FLAG_AVX2) ? "YES" : "NO") << "\n"; + std::cout << "AVX512 support: " + << (core.isAvailable(ALC_E_FLAG_AVX512F) ? "YES" : "NO") << "\n"; + + if (core.isAvailable(ALC_E_FLAG_AVX512F)) { + std::cout << " AVX512DQ : " + << (core.isAvailable(ALC_E_FLAG_AVX512DQ) ? "YES" : "NO") + << "\n"; + std::cout << " AVX512PF : " + << (core.isAvailable(ALC_E_FLAG_AVX512PF) ? "YES" : "NO") + << "\n"; + std::cout << " AVX512ER : " + << (core.isAvailable(ALC_E_FLAG_AVX512ER) ? "YES" : "NO") + << "\n"; + std::cout << " AVX512CD : " + << (core.isAvailable(ALC_E_FLAG_AVX512CD) ? "YES" : "NO") + << "\n"; + std::cout << " AVX512BW : " + << (core.isAvailable(ALC_E_FLAG_AVX512BW) ? "YES" : "NO") + << "\n"; + std::cout << " AVX512VL : " + << (core.isAvailable(ALC_E_FLAG_AVX512VL) ? "YES" : "NO") + << "\n"; + std::cout << " AVX512_IFMA : " + << (core.isAvailable(ALC_E_FLAG_AVX512_IFMA) ? "YES" : "NO") + << "\n"; + std::cout << " AVX512_VNNI : " + << (core.isAvailable(ALC_E_FLAG_AVX512_VNNI) ? "YES" : "NO") + << "\n"; + std::cout << " AVX512_BITALG : " + << (core.isAvailable(ALC_E_FLAG_AVX512_BITALG) ? "YES" : "NO") + << "\n"; + std::cout << " AVX512_VBMI : " + << (core.isAvailable(ALC_E_FLAG_AVX512_VBMI) ? "YES" : "NO") + << "\n"; + std::cout << " AVX512_VBMI2 : " + << (core.isAvailable(ALC_E_FLAG_AVX512_VBMI2) ? "YES" : "NO") + << "\n"; + std::cout << " AVX512_VPOPCNTDQ : " + << (core.isAvailable(ALC_E_FLAG_AVX512_VPOPCNTDQ) ? "YES" + : "NO") + << "\n"; + } +} +} // namespace diff --git a/Library/Tests/Cpuid/CpuidTest.hh b/Library/Tests/Cpuid/CpuidTest.hh new file mode 100644 index 0000000..85a21d1 --- /dev/null +++ b/Library/Tests/Cpuid/CpuidTest.hh @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file CpuidTest.hh + * @brief Utility functions common to Cpuid tests + */ + +#include "Au/Cpuid/X86Cpu.hh" +#include "Au/Misc.hh" +#include "gtest/gtest.h" +#include +#ifdef __linux__ +#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 30 +#include +#define gettid() syscall(SYS_gettid) +#endif +#else +#include +#endif +namespace { +using namespace Au; + +/** + * @brief Utility function to write the data to a file + * + * @param[in] fileName The name of the file to write to + * @param[in] items The data to write to the file + * + * @return void + */ +template +static void +writeToFile(const String& fileName, const std::vector& items) +{ + std::ofstream file(fileName); + if (!file.is_open()) { + std::cout << "Error opening file" << fileName << std::endl; + } else { + for (auto item : items) { + file << *item << std::endl; + } + } +} +/** + * @brief Utility function to read data from a file + * @param fileName The absolute path of the file + * @return vector The flags read from the file + */ +template +inline std::vector +readFromFile(const String& fileName) +{ + std::ifstream file(fileName); + String data; + std::vector items{}; + + if (!file.is_open()) { + std::cout << "Error opening file" << fileName << std::endl; + } else { + while (getline(file, data)) { + auto value = data.substr(0, data.find(' ')); + auto item = static_cast(atoi(value.c_str())); + items.push_back(item); + } + } + + file.close(); + return items; +} + +template<> +inline std::vector +readFromFile(const String& fileName) +{ + std::ifstream file(fileName); + String data; + std::vector items; + + if (!file.is_open()) { + std::cout << "Error opening file" << fileName << std::endl; + } else { + while (getline(file, data)) { + auto value = data.substr(0, data.find(' ')); + items.push_back(value); + } + } + file.close(); + return items; +} + +static inline void +#ifdef __linux__ +checkAffinity(cpu_set_t Mask) +{ + cpu_set_t cpuSet; + auto tid = gettid(); + sched_getaffinity(tid, sizeof(cpuSet), &cpuSet); + EXPECT_TRUE(cpuSet.__bits[0] == Mask.__bits[0]); +#else +checkAffinity(DWORD_PTR Mask) +{ + DWORD threadId = GetCurrentThreadId(); + auto currentMask = SetThreadAffinityMask(&threadId, Mask); + EXPECT_TRUE(currentMask == Mask); +#endif +} +} // namespace diff --git a/Library/Tests/Cpuid/CpuidTest.py b/Library/Tests/Cpuid/CpuidTest.py new file mode 100644 index 0000000..5cae487 --- /dev/null +++ b/Library/Tests/Cpuid/CpuidTest.py @@ -0,0 +1,67 @@ +#!/bin/python3.11 +""" + Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +""" + +import subprocess +import json +import sys +import shutil + +def run_qemu(architecture="x86_64", cpu_model="EPYC", binary_path="", test_name=""): + path = shutil.which("qemu-" + architecture) + if path is None: + print("Qemu is not installed") + return False + qemu_cmd = [ + f"qemu-" + architecture, + "-cpu", cpu_model, + binary_path, + "--gtest_filter=*" + test_name + "*", + "--gtest_output=json:result.json", + "--gtest_also_run_disabled_tests" + ] + #print("Running test: " + test_name) + #print(" ".join(qemu_cmd)) + qemu_process = subprocess.run(qemu_cmd, capture_output=True, timeout=1) + #print(qemu_process.stderr.decode()) + if qemu_process.stdout: + print(qemu_process.stdout.decode()) + result = open('result.json') + data = json.load(result) + return False if data["failures"] else True + else: + print("Test failed due to infrastructure error") + return False + + +if __name__ == "__main__": + if len(sys.argv) >= 3: + cpu_model, test_name = sys.argv[1], sys.argv[2] + print("SUCCESS" if run_qemu(cpu_model=cpu_model, + binary_path="./Release/aoclutils_CpuidTest", test_name=test_name) else "FAILURE") + else: + print("Usage: python script.py from the build folder") diff --git a/Library/Tests/Cpuid/CpuidUnitTestPlan.md b/Library/Tests/Cpuid/CpuidUnitTestPlan.md new file mode 100644 index 0000000..e15c75e --- /dev/null +++ b/Library/Tests/Cpuid/CpuidUnitTestPlan.md @@ -0,0 +1,214 @@ +# The cpuid module unit testplan + +## The cpuid module + +The cpuid module provides details of underlying cpu architecture by reading and interpreting the cpuid register of the system. + +## The objective + +The testplan is to have a comprehensive test coverage for all components in the module. + +## Classes of testcases + +* **qemu tests** + Qemu cpu emulator is used to emulate cpus to test both capis and cpp apis. + Native tests corresponing to this is disabled by default as it doesn't make sense to run natively. +* **mock tests** + Mock tests are used to test cpp apis and utility functions by mocking the cpuid register call. + Mocked data is stored in simnow folder. + The content of the folder is organised as follows. + +``` console +simnowdata +└─── + └─── + └───FlagsT.txt + └───FlagsF.txt + * The \ file consists of cpuid register read corresponding to the particular cpuid for a set of inputs, + in the form {request} : {response} + * These files are shared by both qemu tests and mocktests. + * FlagsT.txt and FlagsF.txt files are shared by all the hasflags tests. + * Flags in FlagsT.txt marks the set of flags that should be present in the cpu + * Flags in FlagsF.txt marks the set of flags that should not be present in the cpu. +``` + +* **native tests** + Few native testcases are written to check edge cases and negative cases. More test are to be added for full coverage. + +### List of cpp apis + +* isamd +* isintel +* isx86v2 +* isx86v3 +* isx86v4 +* hasflag +* isuarch +* getuarch +* getvendorinfo + +### List of capis + +* au_cpuid_is_amd +* au_cupid_has_flag +* au_cpuid_get_vendor +* au_cpuid_arch_is_zen +* au_cpuid_arch_is_zenplus +* au_cpuid_arch_is_zen2 +* au_cpuid_arch_is_zen3 +* au_cpuid_arch_is_zen4 +* au_cpuid_arch_is_zen5 + +for all the amd cpu modules provided by qemu +and below intel cpus, + +* broadwell-v1 +* denverton-v1 +* conroe-v1 +* skylake-server-v1 + +The above c and cpp apis are tested using qemu testcases and mock tests. + +Apart from that, +the utility functions that directly use the cpuid register read results to fill data \ +in different datastructures used by above functions are tested with mocked up (cpuid register read) data. +Those functions are, + +### List of utility functions + +* getmfginfo +* getfamily +* getmodel +* getstepping +* hasflag +* updatecacheview +* updatecacheinfo + +## The test matrix for c/cpp apis + +### cpu features + +#### amd cpus + +| cpu type/function name | epyc-genoa-v1 | epyc-milan-v1 | epyc-milan-v2 | epyc-rome-v1 | epyc-rome-v2 | +|------------------------|---------------|---------------|---------------|--------------|--------------| +|isamd |true |true | true | true |true | +|isintel |false |false | false | false |false | +|isx86_64v2 |true |true | true | true |true | +|isx86_64v3 |true |true | true | true |true | +|isx86_64v4 |true |false | false | false |false | +|getuarch |zen4 |zen3 | zen3 | zen2 |zen2 | + +amd cpus(continued) + + | cpu type/function name | epyc-rome-v3 | epyc-rome-v4 | epyc-v1 | epyc-v2 | epyc-v3 | epyc-v4 | opteron_g1-v1 | + |------------------------|--------------|--------------|---------|---------|---------|---------|----------------| + |isamd |true |true |true |true |true |true | true | + |isintel |false |false |false |false |false |false | false | + |isx86_64v2 |true |true |true |true |true |true | false | + |isx86_64v3 |true |true |true |true |true |true | false | + |isx86_64v4 |false |false |false |false |false |false | false | + |getUarch |zen2 |zen2 |zen |zen |zen |zen | unknown | + +amd cpus(continued) + +|cpu type/function name | opteron_g2-v1|opteron_g3-v1|opteron_g4-v1|opteron_g5-v1|phenom-v1| +|-----------------------| -------------|-------------|-------------|-------------|---------| +|isamd | true |true |true |true |true | +|isintel | false |false |false |false |false | +|isx86_64v2 | false |false |true |true |false | +|isx86_64v3 | false |false |false |false |false | +|isx86_64v4 | false |false |false |false |false | +|getUarch | unknown |unknown |unknown |unknown |unknown | + +#### intel cpus + +|cpu type/function name |broadwell-v1|denverton-v1|conroe-v1|skylake-server-v1| +|-----------------------|------------|------------|---------|-----------------| +|isamd |false |false |false |false | +|isintel |true |true |true |true | +|isx86_64v2 |true |true |false |true | +|isx86_64v3 |true |false |false |true | +|isx86_64v4 |false |false |false |true | +|getUarch | unknown |unknown |unknown |unknown | + +### isa features + +#### x86_64v2 + +| cpu type/flag | epyc-genoa-v1 | epyc-rome-v1 | opteron_g4-v1 | phenom-v1 | skylake-server-v1 | broadwell-v1 | denverton-v1 | conroe-v1 | +| ------------- | ------------- | ------------ | ------------- | --------- | ----------------- | ------------ | ------------ | --------- | +| cx16 | true | true | true | false | true | true | true | false | +| lahf_lm | true | true | true | false | true | true | true | false | +| popcnt | true | true | true | false | true | true | true | false | +| sse4_1 | true | true | true | false | true | true | true | false | +| sse4_2 | true | true | true | false | true | true | true | false | +| ssse3 | true | true | true | false | true | true | true | false | + +#### x86_64v3 + +| cpu type/flag | epyc-genoa-v1 | epyc-rome-v1 | opteron_g4-v1 | phenom-v1 | skylake-server-v1 | broadwell-v1 | denverton-v1 | conroe-v1 | +| ------------- | ------------- | ------------ | ------------- | --------- | ----------------- | ------------ | ------------ | --------- | +| avx | true | true | false | false | true | true | false | false | +| avx2 | true | true | false | false | true | true | false | false | +| bmi1 | true | true | false | false | true | true | false | false | +| bmi2 | true | true | false | false | true | true | false | false | +| f16c | true | true | false | false | true | true | false | false | +| fma | true | true | false | false | true | true | false | false | +| abm | true | true | false | false | true | true | false | false | +| movbe | true | true | false | false | true | true | false | false | +| xsave | true | true | false | false | true | true | false | false | + +#### x86_64v4 + +| cpu type/flag | epyc-genoa-v1 | epyc-rome-v1 | opteron_g4-v1 | phenom-v1 | skylake-server-v1 | broadwell-v1 | denverton-v1 | conroe-v1 | +| ------------- | ------------- | ------------ | ------------- | --------- | ----------------- | ------------ | ------------ | --------- | +| avx512f | true | false | false | false | true | false | false | false | +| avx512bw | true | false | false | false | true | false | false | false | +| avx512cd | true | false | false | false | true | false | false | false | +| avx512dq | true | false | false | false | true | false | false | false | +| avx512vl | true | false | false | false | true | false | | | + +## Utility function test matrix + + | CpuType/VendorInfo| Vendor| Family | Model | Stepping | Uarch | + | ----------------- | ----- | -------| ---- | ---------- |-------- | + | EPYC-Genoa-v1 | Amd | Zen4 | 0x11 |0x0 | zen4 | + | EPYC-Milan-v1 | Amd | Zen4 | 0x01 |0x1 | zen3 | + | EPYC-Milan-v2 | Amd | Zen4 | 0x01 |0x1 | zen3 | + | EPYC-Rome-v1 | Amd | Zen2 | 0x31 |0x0 | zen2 | + | EPYC-Rome-v2 | Amd | Zen2 | 0x31 |0x0 | zen2 | + | EPYC-Rome-v3 | Amd | Zen2 | 0x31 |0x0 | zen2 | + | EPYC-Rome-v4 | Amd | Zen2 | 0x31 |0x0 | zen2 | + | EPYC-v1 | Amd | Zen2 | 0x01 |0x2 | zen | + | EPYC-v2 | Amd | Zen2 | 0x01 |0x2 | zen | + | EPYC-v3 | Amd | Zen2 | 0x01 |0x2 | zen | + | EPYC-v4 | Amd | Zen2 | 0x01 |0x2 | zen | + | Opteron_G1-v1 | Amd | Unknown| 0x06 |0x1 | Unknown | + | Opteron_G2-v1 | Amd | Unknown| 0x06 |0x1 | Unknown | + | Opteron_G3-v1 | Amd | Unknown| 0x02 |0x3 | Unknown | + | Opteron_G4-v1 | Amd | Unknown| 0x01 |0x2 | Unknown | + | Opteron_G5-v1 | Amd | Unknown| 0x02 |0x0 | Unknown | + | phenom-v1 | Amd | Unknown| 0x02 |0x3 | Unknown | + | Broadwell-v1 | Intel| Unknown| 0X3D |0x2 | Unknown | + | Denverton-v1 | Intel| Unknown| 0x5F |0x1 | Unknown | + | Conroe-v1 | Intel| Unknown| 0x0F |0x3 | Unknown | + | Skylake-Server-v1 | Intel| Unknown| 0x55 |0x4 | Unknown | + +## Integration tests + +## How to run the tests + +`ctest` runs all the tests by default along with other tests. if running independently, call `core_cpuidtests`. it has to be done from the build folder as `./release/core_cpuidtest`. + +**Note to developer:** +the test creates the x86cpu test suites with all the unit test cases for functions listed in the scope of the test. these tests are disabled by default because it doesn't make sense to run them on the host whose architecture might be unknown. use the `--gtest_also_run_disabled_tests` flag if these need to be enabled on the host. + +a python script is written to invoke tests in the x86cpu test suite to run on different qemu emulated cpus. the script is placed in the same folder as the test sources. the script can be run as follows: + +```bash +python ../library/tests/cpuid/cpuidtest.py epyc x86cpuid.disabled_isamd + +``` + +the qemutest suites run by invoking the above python script to run on different emulated cpus. \ No newline at end of file diff --git a/Library/Tests/Cpuid/Mock/CpuidUtilsTest.cc b/Library/Tests/Cpuid/Mock/CpuidUtilsTest.cc new file mode 100644 index 0000000..228545d --- /dev/null +++ b/Library/Tests/Cpuid/Mock/CpuidUtilsTest.cc @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/Cpuid/X86Cpu.hh" +#include "MockTest.hh" + +namespace { + +using namespace Au; + +class MockCpuidUtil + : public MockCpuidBase + , public ::testing::WithParamInterface> +{}; + +INSTANTIATE_TEST_SUITE_P(CupidUtilstTestSuite, + MockCpuidUtil, + ::testing::ValuesIn(testParametersCpuidUtils)); +/** + * Testcase for CpuidUtils + * Tests all the CpuidUtils Functions + * from the mocked data in the simnowdata folder. + * Takes testParametersCpuidUtils as input + * Containing the CPU type and the expected results in VendorInfo structure. + */ + +TEST_P(MockCpuidUtil, CpuidUtilsTest) +{ + const auto params = GetParam(); + const String cpuType = std::get<0>(params); + const VendorInfo expectedResults = std::get<1>(params); + filename = cpuType; + auto reqRespData = Configure(); + + std::cout << "Mocking " << cpuType << std::endl; + EXPECT_EQ(mockCpuidUtils.getMfgInfo(reqRespData[RequestT{ 0, 0, 0, 0 }]), + (expectedResults.m_mfg)); + EXPECT_EQ(mockCpuidUtils.getFamily(reqRespData[RequestT{ 1, 0, 0, 0 }].eax), + (expectedResults.m_family)); + EXPECT_EQ(mockCpuidUtils.getModel(reqRespData[RequestT{ 1, 0, 0, 0 }].eax), + expectedResults.m_model); + EXPECT_EQ( + mockCpuidUtils.getStepping(reqRespData[RequestT{ 1, 0, 0, 0 }].eax), + expectedResults.m_stepping); +} + +} // namespace diff --git a/Library/Tests/Cpuid/Mock/MockTest.hh b/Library/Tests/Cpuid/Mock/MockTest.hh new file mode 100644 index 0000000..c26facd --- /dev/null +++ b/Library/Tests/Cpuid/Mock/MockTest.hh @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "Au/Cpuid/X86Cpu.hh" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace { + +using namespace Au; + +/** + * Test parameters for X86Cpu Mock Test + * Vector containing the following parameters: + * 1. Name of the CPU model to be mocked using simnowdata + * 2. Vector containing the following parameters: + * 1. Name of the CPU model to be mocked using simnowdata + * 2. Vector of boolean values that marks the expected results of + * {is_AMD, is_Intel, is_X86_64v2, is_X86_64v3, is_X86_64v4} APIs + * and true for hasFlags(Positive/Negative) and isUarch api tests + * 3. Expected architecture of the CPU + */ +// clang-format off +auto isAmd=true, isIntel=true, isX86_64v2=true, isX86_64v3=true, isX86_64v4=true, flagPresent=true,flagAbsent=true, isUarch=true; +const std::vector, EUarch>> testParametersX86Cpu = { + { "EPYC-Genoa-v1", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen4 }, + { "EPYC-Milan-v1", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen3 }, + { "EPYC-Milan-v2", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen3 }, + { "EPYC-Rome-v1", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen2 }, + { "EPYC-Rome-v2", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen2 }, + { "EPYC-Rome-v3", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen2 }, + { "EPYC-Rome-v4", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen2 }, + { "EPYC-v1", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen }, + { "EPYC-v2", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen }, + { "EPYC-v3", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen }, + { "EPYC-v4", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen }, + { "Opteron_G1-v1", { isAmd, !isIntel, !isX86_64v2, !isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Unknown }, + { "Opteron_G2-v1", { isAmd, !isIntel, !isX86_64v2, !isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Unknown }, + { "Opteron_G3-v1", { isAmd, !isIntel, !isX86_64v2, !isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Unknown }, + { "Opteron_G4-v1", { isAmd, !isIntel, isX86_64v2, !isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Unknown }, + { "Opteron_G5-v1", { isAmd, !isIntel, isX86_64v2, !isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Unknown }, + { "phenom-v1", { isAmd, !isIntel, !isX86_64v2, !isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Unknown }, + // { "Broadwell-v1", { !isAmd, isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Unknown }, + { "Denverton-v1", { !isAmd, isIntel, isX86_64v2, !isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Unknown }, + { "Conroe-v1", { !isAmd, isIntel, !isX86_64v2, !isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Unknown }, + // { "Skylake-Server-v1", { !isAmd, isIntel, isX86_64v2, isX86_64v3, isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Unknown } +}; +// clang-format on +/** + * Test parameters for CpuidUtils Mock Test + * Vector contains the following parameters: + * 1. Name of the CPU model to be mocked using simnowdata + * 2. VendorInfo structure containing the expected results. + */ +// clang-format off +const std::vector> testParametersCpuidUtils = { + { "EPYC-Genoa-v1", { VendorInfo{ EVendor::Amd, EFamily::Zen4, 0x11, 0x0 } } }, + { "EPYC-Milan-v1", { VendorInfo{ EVendor::Amd, EFamily::Zen4, 0x01, 0x1 } } }, + { "EPYC-Milan-v2", { VendorInfo{ EVendor::Amd, EFamily::Zen4, 0x01, 0x1 } } }, + { "EPYC-Rome-v1", { VendorInfo{ EVendor::Amd, EFamily::Zen2, 0x31, 0x0 } } }, + { "EPYC-Rome-v2", { VendorInfo{ EVendor::Amd, EFamily::Zen2, 0x31, 0x0 } } }, + { "EPYC-Rome-v3", { VendorInfo{ EVendor::Amd, EFamily::Zen2, 0x31, 0x0 } } }, + { "EPYC-Rome-v4", { VendorInfo{ EVendor::Amd, EFamily::Zen2, 0x31, 0x0 } } }, + { "EPYC-v1", { VendorInfo{ EVendor::Amd, EFamily::Zen2, 0x01, 0x2 } } }, + { "EPYC-v2", { VendorInfo{ EVendor::Amd, EFamily::Zen2, 0x01, 0x2 } } }, + { "EPYC-v3", { VendorInfo{ EVendor::Amd, EFamily::Zen2, 0x01, 0x2 } } }, + { "EPYC-v4", { VendorInfo{ EVendor::Amd, EFamily::Zen2, 0x01, 0x2 } } }, + { "Opteron_G1-v1", { VendorInfo{ EVendor::Amd, EFamily::Unknown, 0x06, 0x1 } } }, + { "Opteron_G2-v1", { VendorInfo{ EVendor::Amd, EFamily::Unknown, 0x06, 0x1 } } }, + { "Opteron_G3-v1", { VendorInfo{ EVendor::Amd, EFamily::Unknown, 0x02, 0x3 } } }, + { "Opteron_G4-v1", { VendorInfo{ EVendor::Amd, EFamily::Unknown, 0x01, 0x2 } } }, + { "Opteron_G5-v1", { VendorInfo{ EVendor::Amd, EFamily::Unknown, 0x02, 0x0 } } }, + { "phenom-v1", { VendorInfo{ EVendor::Amd, EFamily::Unknown, 0x02, 0x3 } } }, + { "Broadwell-v1", { VendorInfo{ EVendor::Intel, EFamily::Unknown, 0X3D, 0x2 } } }, + { "Denverton-v1", { VendorInfo{ EVendor::Intel, EFamily::Unknown, 0x5F, 0x1 } } }, + { "Conroe-v1", { VendorInfo{ EVendor::Intel, EFamily::Unknown, 0x0F, 0x3 } } }, + { "Skylake-Server-v1", { VendorInfo{ EVendor::Intel, EFamily::Unknown, 0x55, 0x4 } } }, + // clang-format on +}; + +/** + * The MockCpuidUtils class is used to mock the CpuidUtils class + */ +class MockCpuidUtils : public CpuidUtils +{ + public: + MockCpuidUtils() + : CpuidUtils() + { + } + MOCK_METHOD(ResponseT, __raw_cpuid, (RequestT & req), (override)){}; +}; + +/** + * The Base class for both X86Cpu and CpuidUtils Mock tests + * It contains the common functions and data for both the tests + */ +class MockCpuidBase : public testing::Test +{ + private: + /** + * @brief parseCSV function is used to parse the CSV file and populate the + * map with the request and response data + * The format of the file is assumed to be: + * {1,0,0,0}:{329300,2048,4294586883,126614525} + * where the first{} represents the request and the second{} represents the + * response + * @param filename is the name of the file to be parsed + * + * @return map is the map containing the request and + * response data + */ + std::map parseCSV(const String& filename) + { + std::map data; + + std::cout << "Processing" << filename << std::endl; + std::ifstream file(filename); + if (!file.is_open()) { + std::cerr << "Error opening file: " << filename << std::endl; + return data; // Return an empty vector if the file cannot be opened + } + + String line; + while (getline(file, line)) { + std::istringstream lineStream(line); + String requestStr, respStr; + + // Assuming the CSV structure is + // {1,0,0,0}:{329300,2048,4294586883,126614525} + getline(lineStream, requestStr, ':'); + getline(lineStream, respStr, ':'); + // Extract values between curly braces and populate structures + ResponseT request{}; // The request needs to be updated, hence not + // using RequestT here. + ResponseT response{}; + + sscanf(requestStr.c_str(), + "{%x,%x,%x,%x}", + &request.eax, + &request.ebx, + &request.ecx, + &request.edx); + sscanf(respStr.c_str(), + "{%x,%x,%x,%x}", + &response.eax, + &response.ebx, + &response.ecx, + &response.edx); + + data[request] = response; + } + + file.close(); + return data; + } + + protected: + /** + * @brief Configure Mocks the __raw_cpuid function by specifying the + * expected request and response data by parsing the CSV file corresponding + * to the CPU. + * + */ + std::map Configure() + { + String projectDir = PROJECT_SOURCE_DIR; + String testDir = "/Library/Tests/Cpuid/Mock/simnowdata/"; + String dataFilename = projectDir + testDir + filename + "/" + filename; + + std::map csvData = parseCSV(dataFilename); + for (const auto& entry : csvData) { + ON_CALL(mockCpuidUtils, __raw_cpuid(entry.first)) + .WillByDefault(testing::Return(entry.second)); + } + return csvData; + } + + public: + MockCpuidBase() + : mockCpuidUtils() + , filename{} + { + } + MockCpuidUtils mockCpuidUtils; + String filename; +}; +} // namespace diff --git a/Library/Tests/Cpuid/Mock/X86CpuTest.cc b/Library/Tests/Cpuid/Mock/X86CpuTest.cc new file mode 100644 index 0000000..973bf88 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/X86CpuTest.cc @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/Cpuid/X86Cpu.hh" +#include "../CpuidTest.hh" +#include "MockTest.hh" + +namespace { + +using namespace Au; +class MockX86Cpu + : public MockCpuidBase + , public ::testing::WithParamInterface< + std::tuple, EUarch>> +{ + protected: + void SetUp() override + { + // The number of times __raw_cpuid expected to in the code flow. + auto callCount = 12; + EXPECT_CALL(mockCpuidUtils, __raw_cpuid(testing::_)).Times(callCount); + } +}; + +INSTANTIATE_TEST_SUITE_P(MockX86CpuTestSuite, + MockX86Cpu, + ::testing::ValuesIn(testParametersX86Cpu)); +/** + * Testcase for X86Cpu + * Tests all the X86Cpu Functions + * from the mocked data in the simnowdata folder. + * Takes testParametersX86Cpu as input containing the CPU type and the expected + * results vector. + */ +TEST_P(MockX86Cpu, MockX86CpuTest) +{ + + const auto params = GetParam(); + const auto cpuType = std::get<0>(params); + const auto expectedResults = std::get<1>(params); + const auto uarch = std::get<2>(params); + auto resultT = true; + auto resultF = false; + std::vector results; + + filename = cpuType; + auto reqRespData = Configure(); + X86Cpu cpu{ &mockCpuidUtils, 0 }; + + std::cout << "Mocking " << cpuType << std::endl; + results.push_back(cpu.isAMD()); + results.push_back(cpu.isIntel()); + results.push_back(cpu.isX86_64v2()); + results.push_back(cpu.isX86_64v3()); + results.push_back(cpu.isX86_64v4()); + + // Has flag tests + String srcDir = PROJECT_SOURCE_DIR; + String simnowData = "/Library/Tests/Cpuid/Mock/simnowdata/"; + String absPath = srcDir + simnowData + cpuType + "/FlagsT.txt"; + auto flags = readFromFile(absPath); + String token; + std::stringstream ss; + ss << flags; + while (std::getline(ss, token, ':')) { + auto flag = stoi(token); + auto cpuid_flag = valueToEnum(flag); + resultT = resultT & (cpu.hasFlag(cpuid_flag)); + } + results.push_back(resultT); + + absPath = srcDir + simnowData + cpuType + "/FlagsF.txt"; + flags = readFromFile(absPath); + ss.clear(); + ss << flags; + + while (std::getline(ss, token, ':')) { + auto flag = stoi(token); + auto cpuid_flag = valueToEnum(flag); + resultF = resultF | (cpu.hasFlag(cpuid_flag)); + } + results.push_back(!resultF); + + std::cout << "Checking Uarch" << std::endl; + results.push_back(cpu.isUarch(uarch)); + EXPECT_EQ(results, expectedResults); + EXPECT_EQ(cpu.getUarch(), uarch); +} +} // namespace diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Broadwell-v1/Broadwell-v1 b/Library/Tests/Cpuid/Mock/simnowdata/Broadwell-v1/Broadwell-v1 new file mode 100644 index 0000000..fcea823 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Broadwell-v1/Broadwell-v1 @@ -0,0 +1,11 @@ +{0x1,0x0,0x0,0x0}:{0x306d2,0x800,0xfffa3203,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0xd,0x756e6547,0x6c65746e,0x49656e69} +{0x6,0x0,0x0,0x0}:{0x4,0x0,0x0,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x1c07a9,0x0,0x0} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x80000001,0x0,0x0,0x0}:{0x306d2,0x0,0x121,0x28100800} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x1,0x340,0x0,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Broadwell-v1/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/Broadwell-v1/FlagsF.txt new file mode 100644 index 0000000..94724d9 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Broadwell-v1/FlagsF.txt @@ -0,0 +1,96 @@ +dtes64 +monitor +dscpl +vmx +smx +est +tm2 +cid +xtpr +pdcm +dca +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +tsc_adjust +hle +rtm +mpx +avx512f +avx512dq +avx512ifma +pcommit +clflushopt +clwb +avx512pf +avx512er +avx512cd +sha_ni +avx512bw +avx512vl +avx512vbmi +umip +pku +ospke +avx512_vpopcntdq +la57 +rdpid +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +svm +extapic +cr8legacy +sse4a +misalignsse +osvw +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +mmxext +fxsr_opt +pdpe1gb +_3dnowext +_3dnow +invtsc +npt +lbrv +svm_lock +nrip_save +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Broadwell-v1/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/Broadwell-v1/FlagsT.txt new file mode 100644 index 0000000..eb5b37d --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Broadwell-v1/FlagsT.txt @@ -0,0 +1,58 @@ +sse3 +pclmulqdq +ssse3 +fma +cx16 +pcid +sse4_1 +sse4_2 +x2apic +movbe +popcnt +tsc_deadline +aes +xsave +osxsave +avx +f16c +rdrand +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +arat +fsgsbase +bmi1 +avx2 +smep +bmi2 +erms +invpcid +rdseed +adx +smap +lahf_lm +abm +_3dnowprefetch +syscall +nxxd +rdtscp +lmi64 diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Conroe-v1/Conroe-v1 b/Library/Tests/Cpuid/Mock/simnowdata/Conroe-v1/Conroe-v1 new file mode 100644 index 0000000..5d22939 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Conroe-v1/Conroe-v1 @@ -0,0 +1,11 @@ +{0x1,0x0,0x0,0x0}:{0x6f3,0x800,0x80000201,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0xa,0x756e6547,0x6c65746e,0x49656e69} +{0x6,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x80000001,0x0,0x0,0x0}:{0x6f3,0x0,0x1,0x20100800} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Conroe-v1/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/Conroe-v1/FlagsF.txt new file mode 100644 index 0000000..aa18db4 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Conroe-v1/FlagsF.txt @@ -0,0 +1,126 @@ +pclmulqdq +dtes64 +monitor +dscpl +vmx +smx +est +tm2 +cid +fma +cx16 +xtpr +pdcm +pcid +dca +sse4_1 +sse4_2 +x2apic +movbe +popcnt +tsc_deadline +aes +xsave +osxsave +avx +f16c +rdrand +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +arat +fsgsbase +tsc_adjust +bmi1 +hle +avx2 +smep +bmi2 +erms +invpcid +rtm +mpx +avx512f +avx512dq +rdseed +adx +smap +avx512ifma +pcommit +clflushopt +clwb +avx512pf +avx512er +avx512cd +sha_ni +avx512bw +avx512vl +avx512vbmi +umip +pku +ospke +avx512_vpopcntdq +la57 +rdpid +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +svm +extapic +cr8legacy +abm +sse4a +misalignsse +_3dnowprefetch +osvw +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +mmxext +fxsr_opt +pdpe1gb +rdtscp +_3dnowext +_3dnow +invtsc +npt +lbrv +svm_lock +nrip_save +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Conroe-v1/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/Conroe-v1/FlagsT.txt new file mode 100644 index 0000000..0bcacc9 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Conroe-v1/FlagsT.txt @@ -0,0 +1,28 @@ +sse3 +ssse3 +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +lahf_lm +syscall +nxxd +lmi64 diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Denverton-v1/Denverton-v1 b/Library/Tests/Cpuid/Mock/simnowdata/Denverton-v1/Denverton-v1 new file mode 100644 index 0000000..6e27fc0 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Denverton-v1/Denverton-v1 @@ -0,0 +1,11 @@ +{0x1,0x0,0x0,0x0}:{0x506f1,0x800,0xcff8220b,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0x15,0x756e6547,0x6c65746e,0x49656e69} +{0x6,0x0,0x0,0x0}:{0x4,0x0,0x0,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x20944281,0x0,0xa4000000} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x80000001,0x0,0x0,0x0}:{0x506f1,0x0,0x101,0x2c100800} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Denverton-v1/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/Denverton-v1/FlagsF.txt new file mode 100644 index 0000000..1df8b78 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Denverton-v1/FlagsF.txt @@ -0,0 +1,101 @@ +dtes64 +dscpl +vmx +smx +est +tm2 +cid +fma +xtpr +pdcm +pcid +dca +avx +f16c +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +tsc_adjust +bmi1 +hle +avx2 +bmi2 +invpcid +rtm +avx512f +avx512dq +adx +avx512ifma +pcommit +clwb +avx512pf +avx512er +avx512cd +avx512bw +avx512vl +avx512vbmi +umip +pku +ospke +avx512_vpopcntdq +la57 +rdpid +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +svm +extapic +cr8legacy +abm +sse4a +misalignsse +osvw +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +mmxext +fxsr_opt +_3dnowext +_3dnow +invtsc +npt +lbrv +svm_lock +nrip_save +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Denverton-v1/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/Denverton-v1/FlagsT.txt new file mode 100644 index 0000000..a27c272 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Denverton-v1/FlagsT.txt @@ -0,0 +1,53 @@ +sse3 +pclmulqdq +monitor +ssse3 +cx16 +sse4_1 +sse4_2 +x2apic +movbe +popcnt +tsc_deadline +aes +xsave +osxsave +rdrand +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +arat +fsgsbase +smep +erms +mpx +rdseed +smap +clflushopt +sha_ni +lahf_lm +_3dnowprefetch +syscall +nxxd +pdpe1gb +rdtscp +lmi64 diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Genoa-v1/EPYC-Genoa-v1 b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Genoa-v1/EPYC-Genoa-v1 new file mode 100644 index 0000000..46710d2 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Genoa-v1/EPYC-Genoa-v1 @@ -0,0 +1,13 @@ +{0x1,0x0,0x0,0x0}:{0xa10f10,0x800,0xfeda320b,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0xd,0x68747541,0x444d4163,0x69746e65} +{0x1,0x0,0x0,0x0}:{0xa10f10,0x800,0xfeda320b,0x78bfbfd} +{0x6,0x0,0x0,0x0}:{0x4,0x0,0x0,0x0} +{0x7,0x0,0x0,0x0}:{0x1,0x219c07a9,0x41020c,0x10} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x80000001,0x0,0x0,0x0}:{0xa10f10,0x0,0x375,0x2fd3fbfd} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x1,0x10,0x0,0x12000009} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x122,0x1c0003f,0x3f,0x1} +{0x8000001d,0x0,0x2,0x0}:{0x0,0x0,0x0,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Genoa-v1/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Genoa-v1/FlagsF.txt new file mode 100644 index 0000000..feddbac --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Genoa-v1/FlagsF.txt @@ -0,0 +1,81 @@ +dtes64 +dscpl +vmx +smx +est +tm2 +cid +xtpr +pdcm +dca +x2apic +tsc_deadline +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +tsc_adjust +hle +rtm +mpx +avx512f +avx512dq +avx512ifma +pcommit +avx512pf +avx512er +avx512cd +avx512bw +avx512vl +avx512vbmi +ospke +avx512_vpopcntdq +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +extapic +misalignsse +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +_3dnowext +_3dnow +invtsc +lbrv +svm_lock +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Genoa-v1/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Genoa-v1/FlagsT.txt new file mode 100644 index 0000000..8f9ba60 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Genoa-v1/FlagsT.txt @@ -0,0 +1,73 @@ +sse3 +pclmulqdq +monitor +ssse3 +fma +cx16 +pcid +sse4_1 +sse4_2 +movbe +popcnt +aes +xsave +osxsave +avx +f16c +rdrand +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +arat +fsgsbase +bmi1 +avx2 +smep +bmi2 +erms +invpcid +rdseed +adx +smap +clflushopt +clwb +sha_ni +umip +pku +la57 +rdpid +lahf_lm +svm +cr8legacy +abm +sse4a +_3dnowprefetch +osvw +syscall +nxxd +mmxext +fxsr_opt +pdpe1gb +rdtscp +lmi64 +npt +nrip_save diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Milan-v1/EPYC-Milan-v1 b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Milan-v1/EPYC-Milan-v1 new file mode 100644 index 0000000..52977f7 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Milan-v1/EPYC-Milan-v1 @@ -0,0 +1,12 @@ +{0x1,0x0,0x0,0x0}:{0xa00f11,0x800,0xfeda320b,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0xd,0x68747541,0x444d4163,0x69746e65} +{0x6,0x0,0x0,0x0}:{0x4,0x0,0x0,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x219c07a9,0x40000c,0x10} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x80000001,0x0,0x0,0x0}:{0xa00f11,0x0,0x375,0x2fd3fbfd} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x1,0x10,0x0,0x10000009} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x122,0x1c0003f,0x3f,0x1} +{0x8000001d,0x0,0x2,0x0}:{0x0,0x0,0x0,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Milan-v1/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Milan-v1/FlagsF.txt new file mode 100644 index 0000000..ac00268 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Milan-v1/FlagsF.txt @@ -0,0 +1,81 @@ +dtes64 +dscpl +vmx +smx +est +tm2 +cid +xtpr +pdcm +dca +x2apic +tsc_deadline +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +tsc_adjust +hle +rtm +mpx +avx512f +avx512dq +avx512ifma +pcommit +avx512pf +avx512er +avx512cd +avx512bw +avx512vl +avx512vbmi +ospke +avx512_vpopcntdq +la57 +avx512_4vnniw +avx512_4fmaps +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +extapic +misalignsse +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +_3dnowext +_3dnow +invtsc +lbrv +svm_lock +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Milan-v1/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Milan-v1/FlagsT.txt new file mode 100644 index 0000000..9571224 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Milan-v1/FlagsT.txt @@ -0,0 +1,72 @@ +sse3 +pclmulqdq +monitor +ssse3 +fma +cx16 +pcid +sse4_1 +sse4_2 +movbe +popcnt +aes +xsave +osxsave +avx +f16c +rdrand +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +arat +fsgsbase +bmi1 +avx2 +smep +bmi2 +erms +invpcid +rdseed +adx +smap +clflushopt +clwb +sha_ni +umip +pku +rdpid +lahf_lm +svm +cr8legacy +abm +sse4a +_3dnowprefetch +osvw +syscall +nxxd +mmxext +fxsr_opt +pdpe1gb +rdtscp +lmi64 +npt +nrip_save diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Milan-v2/EPYC-Milan-v2 b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Milan-v2/EPYC-Milan-v2 new file mode 100644 index 0000000..7f1d89b --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Milan-v2/EPYC-Milan-v2 @@ -0,0 +1,12 @@ +{0x1,0x0,0x0,0x0}:{0xa00f11,0x800,0xfeda320b,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0xd,0x68747541,0x444d4163,0x69746e65} +{0x6,0x0,0x0,0x0}:{0x4,0x0,0x0,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x219c07a9,0x40020c,0x10} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x80000001,0x0,0x0,0x0}:{0xa00f11,0x0,0x375,0x2fd3fbfd} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x1,0x10,0x0,0x10000009} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x122,0x1c0003f,0x3f,0x1} +{0x8000001d,0x0,0x2,0x0}:{0x0,0x0,0x0,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Milan-v2/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Milan-v2/FlagsF.txt new file mode 100644 index 0000000..9aba385 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Milan-v2/FlagsF.txt @@ -0,0 +1,82 @@ +dtes64 +dscpl +vmx +smx +est +tm2 +cid +xtpr +pdcm +dca +x2apic +tsc_deadline +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +tsc_adjust +hle +rtm +mpx +avx512f +avx512dq +avx512ifma +pcommit +avx512pf +avx512er +avx512cd +avx512bw +avx512vl +avx512vbmi +ospke +avx512_vpopcntdq +la57 +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +extapic +misalignsse +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +_3dnowext +_3dnow +invtsc +lbrv +svm_lock +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Milan-v2/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Milan-v2/FlagsT.txt new file mode 100644 index 0000000..9571224 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Milan-v2/FlagsT.txt @@ -0,0 +1,72 @@ +sse3 +pclmulqdq +monitor +ssse3 +fma +cx16 +pcid +sse4_1 +sse4_2 +movbe +popcnt +aes +xsave +osxsave +avx +f16c +rdrand +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +arat +fsgsbase +bmi1 +avx2 +smep +bmi2 +erms +invpcid +rdseed +adx +smap +clflushopt +clwb +sha_ni +umip +pku +rdpid +lahf_lm +svm +cr8legacy +abm +sse4a +_3dnowprefetch +osvw +syscall +nxxd +mmxext +fxsr_opt +pdpe1gb +rdtscp +lmi64 +npt +nrip_save diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v1/EPYC-Rome-v1 b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v1/EPYC-Rome-v1 new file mode 100644 index 0000000..5d02118 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v1/EPYC-Rome-v1 @@ -0,0 +1,12 @@ +{0x1,0x0,0x0,0x0}:{0x830f10,0x800,0xfed8320b,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0xd,0x68747541,0x444d4163,0x69746e65} +{0x6,0x0,0x0,0x0}:{0x4,0x0,0x0,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x219c01a9,0x400004,0x0} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x80000001,0x0,0x0,0x0}:{0x830f10,0x0,0x375,0x2fd3fbfd} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x1,0x10,0x0,0x9} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x122,0x1c0003f,0x3f,0x1} +{0x8000001d,0x0,0x2,0x0}:{0x0,0x0,0x0,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v1/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v1/FlagsF.txt new file mode 100644 index 0000000..387c071 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v1/FlagsF.txt @@ -0,0 +1,86 @@ +dtes64 +dscpl +vmx +smx +est +tm2 +cid +xtpr +pdcm +pcid +dca +x2apic +tsc_deadline +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +tsc_adjust +hle +erms +invpcid +rtm +mpx +avx512f +avx512dq +avx512ifma +pcommit +avx512pf +avx512er +avx512cd +avx512bw +avx512vl +avx512vbmi +pku +ospke +avx512_vpopcntdq +la57 +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +extapic +misalignsse +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +_3dnowext +_3dnow +invtsc +lbrv +svm_lock +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v1/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v1/FlagsT.txt new file mode 100644 index 0000000..801ba29 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v1/FlagsT.txt @@ -0,0 +1,68 @@ +sse3 +pclmulqdq +monitor +ssse3 +fma +cx16 +sse4_1 +sse4_2 +movbe +popcnt +aes +xsave +osxsave +avx +f16c +rdrand +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +arat +fsgsbase +bmi1 +avx2 +smep +bmi2 +rdseed +adx +smap +clflushopt +clwb +sha_ni +umip +rdpid +lahf_lm +svm +cr8legacy +abm +sse4a +_3dnowprefetch +osvw +syscall +nxxd +mmxext +fxsr_opt +pdpe1gb +rdtscp +lmi64 +npt +nrip_save diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v2/EPYC-Rome-v2 b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v2/EPYC-Rome-v2 new file mode 100644 index 0000000..5d02118 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v2/EPYC-Rome-v2 @@ -0,0 +1,12 @@ +{0x1,0x0,0x0,0x0}:{0x830f10,0x800,0xfed8320b,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0xd,0x68747541,0x444d4163,0x69746e65} +{0x6,0x0,0x0,0x0}:{0x4,0x0,0x0,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x219c01a9,0x400004,0x0} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x80000001,0x0,0x0,0x0}:{0x830f10,0x0,0x375,0x2fd3fbfd} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x1,0x10,0x0,0x9} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x122,0x1c0003f,0x3f,0x1} +{0x8000001d,0x0,0x2,0x0}:{0x0,0x0,0x0,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v2/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v2/FlagsF.txt new file mode 100644 index 0000000..387c071 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v2/FlagsF.txt @@ -0,0 +1,86 @@ +dtes64 +dscpl +vmx +smx +est +tm2 +cid +xtpr +pdcm +pcid +dca +x2apic +tsc_deadline +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +tsc_adjust +hle +erms +invpcid +rtm +mpx +avx512f +avx512dq +avx512ifma +pcommit +avx512pf +avx512er +avx512cd +avx512bw +avx512vl +avx512vbmi +pku +ospke +avx512_vpopcntdq +la57 +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +extapic +misalignsse +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +_3dnowext +_3dnow +invtsc +lbrv +svm_lock +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v2/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v2/FlagsT.txt new file mode 100644 index 0000000..801ba29 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v2/FlagsT.txt @@ -0,0 +1,68 @@ +sse3 +pclmulqdq +monitor +ssse3 +fma +cx16 +sse4_1 +sse4_2 +movbe +popcnt +aes +xsave +osxsave +avx +f16c +rdrand +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +arat +fsgsbase +bmi1 +avx2 +smep +bmi2 +rdseed +adx +smap +clflushopt +clwb +sha_ni +umip +rdpid +lahf_lm +svm +cr8legacy +abm +sse4a +_3dnowprefetch +osvw +syscall +nxxd +mmxext +fxsr_opt +pdpe1gb +rdtscp +lmi64 +npt +nrip_save diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v3/EPYC-Rome-v3 b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v3/EPYC-Rome-v3 new file mode 100644 index 0000000..5d02118 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v3/EPYC-Rome-v3 @@ -0,0 +1,12 @@ +{0x1,0x0,0x0,0x0}:{0x830f10,0x800,0xfed8320b,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0xd,0x68747541,0x444d4163,0x69746e65} +{0x6,0x0,0x0,0x0}:{0x4,0x0,0x0,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x219c01a9,0x400004,0x0} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x80000001,0x0,0x0,0x0}:{0x830f10,0x0,0x375,0x2fd3fbfd} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x1,0x10,0x0,0x9} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x122,0x1c0003f,0x3f,0x1} +{0x8000001d,0x0,0x2,0x0}:{0x0,0x0,0x0,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v3/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v3/FlagsF.txt new file mode 100644 index 0000000..387c071 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v3/FlagsF.txt @@ -0,0 +1,86 @@ +dtes64 +dscpl +vmx +smx +est +tm2 +cid +xtpr +pdcm +pcid +dca +x2apic +tsc_deadline +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +tsc_adjust +hle +erms +invpcid +rtm +mpx +avx512f +avx512dq +avx512ifma +pcommit +avx512pf +avx512er +avx512cd +avx512bw +avx512vl +avx512vbmi +pku +ospke +avx512_vpopcntdq +la57 +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +extapic +misalignsse +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +_3dnowext +_3dnow +invtsc +lbrv +svm_lock +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v3/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v3/FlagsT.txt new file mode 100644 index 0000000..801ba29 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v3/FlagsT.txt @@ -0,0 +1,68 @@ +sse3 +pclmulqdq +monitor +ssse3 +fma +cx16 +sse4_1 +sse4_2 +movbe +popcnt +aes +xsave +osxsave +avx +f16c +rdrand +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +arat +fsgsbase +bmi1 +avx2 +smep +bmi2 +rdseed +adx +smap +clflushopt +clwb +sha_ni +umip +rdpid +lahf_lm +svm +cr8legacy +abm +sse4a +_3dnowprefetch +osvw +syscall +nxxd +mmxext +fxsr_opt +pdpe1gb +rdtscp +lmi64 +npt +nrip_save diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v4/EPYC-Rome-v4 b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v4/EPYC-Rome-v4 new file mode 100644 index 0000000..5d02118 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v4/EPYC-Rome-v4 @@ -0,0 +1,12 @@ +{0x1,0x0,0x0,0x0}:{0x830f10,0x800,0xfed8320b,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0xd,0x68747541,0x444d4163,0x69746e65} +{0x6,0x0,0x0,0x0}:{0x4,0x0,0x0,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x219c01a9,0x400004,0x0} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x80000001,0x0,0x0,0x0}:{0x830f10,0x0,0x375,0x2fd3fbfd} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x1,0x10,0x0,0x9} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x122,0x1c0003f,0x3f,0x1} +{0x8000001d,0x0,0x2,0x0}:{0x0,0x0,0x0,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v4/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v4/FlagsF.txt new file mode 100644 index 0000000..387c071 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v4/FlagsF.txt @@ -0,0 +1,86 @@ +dtes64 +dscpl +vmx +smx +est +tm2 +cid +xtpr +pdcm +pcid +dca +x2apic +tsc_deadline +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +tsc_adjust +hle +erms +invpcid +rtm +mpx +avx512f +avx512dq +avx512ifma +pcommit +avx512pf +avx512er +avx512cd +avx512bw +avx512vl +avx512vbmi +pku +ospke +avx512_vpopcntdq +la57 +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +extapic +misalignsse +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +_3dnowext +_3dnow +invtsc +lbrv +svm_lock +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v4/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v4/FlagsT.txt new file mode 100644 index 0000000..801ba29 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-Rome-v4/FlagsT.txt @@ -0,0 +1,68 @@ +sse3 +pclmulqdq +monitor +ssse3 +fma +cx16 +sse4_1 +sse4_2 +movbe +popcnt +aes +xsave +osxsave +avx +f16c +rdrand +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +arat +fsgsbase +bmi1 +avx2 +smep +bmi2 +rdseed +adx +smap +clflushopt +clwb +sha_ni +umip +rdpid +lahf_lm +svm +cr8legacy +abm +sse4a +_3dnowprefetch +osvw +syscall +nxxd +mmxext +fxsr_opt +pdpe1gb +rdtscp +lmi64 +npt +nrip_save diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v1/EPYC-v1 b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v1/EPYC-v1 new file mode 100644 index 0000000..33bf8b2 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v1/EPYC-v1 @@ -0,0 +1,12 @@ +{0x1,0x0,0x0,0x0}:{0x800f12,0x800,0xfed8320b,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0xd,0x68747541,0x444d4163,0x69746e65} +{0x6,0x0,0x0,0x0}:{0x4,0x0,0x0,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x209c01a9,0x0,0x0} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x80000001,0x0,0x0,0x0}:{0x800f12,0x0,0x375,0x2fd3fbfd} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x1,0x10,0x0,0x9} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x122,0xc0003f,0xff,0x1} +{0x8000001d,0x0,0x2,0x0}:{0x0,0x0,0x0,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v1/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v1/FlagsF.txt new file mode 100644 index 0000000..fe98e12 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v1/FlagsF.txt @@ -0,0 +1,89 @@ +dtes64 +dscpl +vmx +smx +est +tm2 +cid +xtpr +pdcm +pcid +dca +x2apic +tsc_deadline +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +tsc_adjust +hle +erms +invpcid +rtm +mpx +avx512f +avx512dq +avx512ifma +pcommit +clwb +avx512pf +avx512er +avx512cd +avx512bw +avx512vl +avx512vbmi +umip +pku +ospke +avx512_vpopcntdq +la57 +rdpid +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +extapic +misalignsse +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +_3dnowext +_3dnow +invtsc +lbrv +svm_lock +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v1/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v1/FlagsT.txt new file mode 100644 index 0000000..1574224 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v1/FlagsT.txt @@ -0,0 +1,65 @@ +sse3 +pclmulqdq +monitor +ssse3 +fma +cx16 +sse4_1 +sse4_2 +movbe +popcnt +aes +xsave +osxsave +avx +f16c +rdrand +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +arat +fsgsbase +bmi1 +avx2 +smep +bmi2 +rdseed +adx +smap +clflushopt +sha_ni +lahf_lm +svm +cr8legacy +abm +sse4a +_3dnowprefetch +osvw +syscall +nxxd +mmxext +fxsr_opt +pdpe1gb +rdtscp +lmi64 +npt +nrip_save diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v2/EPYC-v2 b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v2/EPYC-v2 new file mode 100644 index 0000000..33bf8b2 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v2/EPYC-v2 @@ -0,0 +1,12 @@ +{0x1,0x0,0x0,0x0}:{0x800f12,0x800,0xfed8320b,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0xd,0x68747541,0x444d4163,0x69746e65} +{0x6,0x0,0x0,0x0}:{0x4,0x0,0x0,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x209c01a9,0x0,0x0} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x80000001,0x0,0x0,0x0}:{0x800f12,0x0,0x375,0x2fd3fbfd} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x1,0x10,0x0,0x9} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x122,0xc0003f,0xff,0x1} +{0x8000001d,0x0,0x2,0x0}:{0x0,0x0,0x0,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v2/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v2/FlagsF.txt new file mode 100644 index 0000000..fe98e12 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v2/FlagsF.txt @@ -0,0 +1,89 @@ +dtes64 +dscpl +vmx +smx +est +tm2 +cid +xtpr +pdcm +pcid +dca +x2apic +tsc_deadline +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +tsc_adjust +hle +erms +invpcid +rtm +mpx +avx512f +avx512dq +avx512ifma +pcommit +clwb +avx512pf +avx512er +avx512cd +avx512bw +avx512vl +avx512vbmi +umip +pku +ospke +avx512_vpopcntdq +la57 +rdpid +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +extapic +misalignsse +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +_3dnowext +_3dnow +invtsc +lbrv +svm_lock +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v2/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v2/FlagsT.txt new file mode 100644 index 0000000..1574224 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v2/FlagsT.txt @@ -0,0 +1,65 @@ +sse3 +pclmulqdq +monitor +ssse3 +fma +cx16 +sse4_1 +sse4_2 +movbe +popcnt +aes +xsave +osxsave +avx +f16c +rdrand +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +arat +fsgsbase +bmi1 +avx2 +smep +bmi2 +rdseed +adx +smap +clflushopt +sha_ni +lahf_lm +svm +cr8legacy +abm +sse4a +_3dnowprefetch +osvw +syscall +nxxd +mmxext +fxsr_opt +pdpe1gb +rdtscp +lmi64 +npt +nrip_save diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v3/EPYC-v3 b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v3/EPYC-v3 new file mode 100644 index 0000000..33bf8b2 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v3/EPYC-v3 @@ -0,0 +1,12 @@ +{0x1,0x0,0x0,0x0}:{0x800f12,0x800,0xfed8320b,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0xd,0x68747541,0x444d4163,0x69746e65} +{0x6,0x0,0x0,0x0}:{0x4,0x0,0x0,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x209c01a9,0x0,0x0} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x80000001,0x0,0x0,0x0}:{0x800f12,0x0,0x375,0x2fd3fbfd} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x1,0x10,0x0,0x9} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x122,0xc0003f,0xff,0x1} +{0x8000001d,0x0,0x2,0x0}:{0x0,0x0,0x0,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v3/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v3/FlagsF.txt new file mode 100644 index 0000000..fe98e12 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v3/FlagsF.txt @@ -0,0 +1,89 @@ +dtes64 +dscpl +vmx +smx +est +tm2 +cid +xtpr +pdcm +pcid +dca +x2apic +tsc_deadline +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +tsc_adjust +hle +erms +invpcid +rtm +mpx +avx512f +avx512dq +avx512ifma +pcommit +clwb +avx512pf +avx512er +avx512cd +avx512bw +avx512vl +avx512vbmi +umip +pku +ospke +avx512_vpopcntdq +la57 +rdpid +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +extapic +misalignsse +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +_3dnowext +_3dnow +invtsc +lbrv +svm_lock +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v3/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v3/FlagsT.txt new file mode 100644 index 0000000..1574224 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v3/FlagsT.txt @@ -0,0 +1,65 @@ +sse3 +pclmulqdq +monitor +ssse3 +fma +cx16 +sse4_1 +sse4_2 +movbe +popcnt +aes +xsave +osxsave +avx +f16c +rdrand +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +arat +fsgsbase +bmi1 +avx2 +smep +bmi2 +rdseed +adx +smap +clflushopt +sha_ni +lahf_lm +svm +cr8legacy +abm +sse4a +_3dnowprefetch +osvw +syscall +nxxd +mmxext +fxsr_opt +pdpe1gb +rdtscp +lmi64 +npt +nrip_save diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v4/EPYC-v4 b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v4/EPYC-v4 new file mode 100644 index 0000000..33bf8b2 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v4/EPYC-v4 @@ -0,0 +1,12 @@ +{0x1,0x0,0x0,0x0}:{0x800f12,0x800,0xfed8320b,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0xd,0x68747541,0x444d4163,0x69746e65} +{0x6,0x0,0x0,0x0}:{0x4,0x0,0x0,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x209c01a9,0x0,0x0} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x80000001,0x0,0x0,0x0}:{0x800f12,0x0,0x375,0x2fd3fbfd} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x1,0x10,0x0,0x9} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x122,0xc0003f,0xff,0x1} +{0x8000001d,0x0,0x2,0x0}:{0x0,0x0,0x0,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v4/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v4/FlagsF.txt new file mode 100644 index 0000000..fe98e12 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v4/FlagsF.txt @@ -0,0 +1,89 @@ +dtes64 +dscpl +vmx +smx +est +tm2 +cid +xtpr +pdcm +pcid +dca +x2apic +tsc_deadline +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +tsc_adjust +hle +erms +invpcid +rtm +mpx +avx512f +avx512dq +avx512ifma +pcommit +clwb +avx512pf +avx512er +avx512cd +avx512bw +avx512vl +avx512vbmi +umip +pku +ospke +avx512_vpopcntdq +la57 +rdpid +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +extapic +misalignsse +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +_3dnowext +_3dnow +invtsc +lbrv +svm_lock +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v4/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v4/FlagsT.txt new file mode 100644 index 0000000..1574224 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/EPYC-v4/FlagsT.txt @@ -0,0 +1,65 @@ +sse3 +pclmulqdq +monitor +ssse3 +fma +cx16 +sse4_1 +sse4_2 +movbe +popcnt +aes +xsave +osxsave +avx +f16c +rdrand +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +arat +fsgsbase +bmi1 +avx2 +smep +bmi2 +rdseed +adx +smap +clflushopt +sha_ni +lahf_lm +svm +cr8legacy +abm +sse4a +_3dnowprefetch +osvw +syscall +nxxd +mmxext +fxsr_opt +pdpe1gb +rdtscp +lmi64 +npt +nrip_save diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G1-v1/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G1-v1/FlagsF.txt new file mode 100644 index 0000000..2d12f2e --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G1-v1/FlagsF.txt @@ -0,0 +1,127 @@ +pclmulqdq +dtes64 +monitor +dscpl +vmx +smx +est +tm2 +ssse3 +cid +fma +cx16 +xtpr +pdcm +pcid +dca +sse4_1 +sse4_2 +x2apic +movbe +popcnt +tsc_deadline +aes +xsave +osxsave +avx +f16c +rdrand +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +arat +fsgsbase +tsc_adjust +bmi1 +hle +avx2 +smep +bmi2 +erms +invpcid +rtm +mpx +avx512f +avx512dq +rdseed +adx +smap +avx512ifma +pcommit +clflushopt +clwb +avx512pf +avx512er +avx512cd +sha_ni +avx512bw +avx512vl +umip +pku +ospke +avx512_vpopcntdq +la57 +rdpid +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +lahf_lm +cmp_legacy +svm +extapic +cr8legacy +abm +sse4a +misalignsse +_3dnowprefetch +osvw +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +mmxext +fxsr_opt +pdpe1gb +rdtscp +_3dnowext +_3dnow +invtsc +npt +lbrv +svm_lock +nrip_save +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G1-v1/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G1-v1/FlagsT.txt new file mode 100644 index 0000000..0b49e35 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G1-v1/FlagsT.txt @@ -0,0 +1,27 @@ +sse3 +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +avx512vbmi +syscall +nxxd +lmi64 diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G1-v1/Opteron_G1-v1 b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G1-v1/Opteron_G1-v1 new file mode 100644 index 0000000..fb89023 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G1-v1/Opteron_G1-v1 @@ -0,0 +1,11 @@ +{0x1,0x0,0x0,0x0}:{0xf61,0x800,0x80000001,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0x5,0x68747541,0x444d4163,0x69746e65} +{0x6,0x0,0x0,0x0}:{0x0,0x0,0x3,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x0,0x3,0x0} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x3,0x0} +{0x80000001,0x0,0x0,0x0}:{0xf61,0x0,0x0,0x2193fbfd} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x0,0x0,0x3,0x0} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x3,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x0,0x0,0x3,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G2-v1/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G2-v1/FlagsF.txt new file mode 100644 index 0000000..1e788a0 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G2-v1/FlagsF.txt @@ -0,0 +1,124 @@ +pclmulqdq +dtes64 +monitor +dscpl +vmx +smx +est +tm2 +ssse3 +cid +fma +xtpr +pdcm +pcid +dca +sse4_1 +sse4_2 +x2apic +movbe +popcnt +tsc_deadline +aes +xsave +osxsave +avx +f16c +rdrand +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +arat +fsgsbase +tsc_adjust +bmi1 +hle +avx2 +smep +bmi2 +erms +invpcid +rtm +mpx +avx512f +avx512dq +rdseed +adx +smap +avx512ifma +pcommit +clflushopt +clwb +avx512pf +avx512er +avx512cd +sha_ni +avx512bw +avx512vl +umip +pku +ospke +avx512_vpopcntdq +la57 +rdpid +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +extapic +cr8legacy +abm +sse4a +misalignsse +_3dnowprefetch +osvw +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +mmxext +fxsr_opt +pdpe1gb +rdtscp +_3dnowext +_3dnow +invtsc +npt +lbrv +svm_lock +nrip_save +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G2-v1/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G2-v1/FlagsT.txt new file mode 100644 index 0000000..bdaa14d --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G2-v1/FlagsT.txt @@ -0,0 +1,30 @@ +sse3 +cx16 +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +avx512vbmi +lahf_lm +svm +syscall +nxxd +lmi64 diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G2-v1/Opteron_G2-v1 b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G2-v1/Opteron_G2-v1 new file mode 100644 index 0000000..e230293 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G2-v1/Opteron_G2-v1 @@ -0,0 +1,11 @@ +{0x1,0x0,0x0,0x0}:{0xf61,0x800,0x80002001,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0x5,0x68747541,0x444d4163,0x69746e65} +{0x6,0x0,0x0,0x0}:{0x0,0x0,0x3,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x0,0x3,0x0} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x3,0x0} +{0x80000001,0x0,0x0,0x0}:{0xf61,0x0,0x5,0x2193fbfd} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x1,0x10,0x0,0x0} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x3,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x0,0x0,0x3,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G3-v1/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G3-v1/FlagsF.txt new file mode 100644 index 0000000..9731767 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G3-v1/FlagsF.txt @@ -0,0 +1,119 @@ +pclmulqdq +dtes64 +dscpl +vmx +smx +est +tm2 +ssse3 +cid +fma +xtpr +pdcm +pcid +dca +sse4_1 +sse4_2 +x2apic +movbe +tsc_deadline +aes +xsave +osxsave +avx +f16c +rdrand +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +arat +fsgsbase +tsc_adjust +bmi1 +hle +avx2 +smep +bmi2 +erms +invpcid +rtm +mpx +avx512f +avx512dq +rdseed +adx +smap +avx512ifma +pcommit +clflushopt +clwb +avx512pf +avx512er +avx512cd +sha_ni +avx512bw +avx512vl +umip +pku +ospke +avx512_vpopcntdq +la57 +rdpid +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +extapic +cr8legacy +misalignsse +_3dnowprefetch +osvw +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +mmxext +fxsr_opt +pdpe1gb +_3dnowext +_3dnow +invtsc +npt +lbrv +svm_lock +nrip_save +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G3-v1/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G3-v1/FlagsT.txt new file mode 100644 index 0000000..d9b39b9 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G3-v1/FlagsT.txt @@ -0,0 +1,35 @@ +sse3 +monitor +cx16 +popcnt +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +avx512vbmi +lahf_lm +svm +abm +sse4a +syscall +nxxd +rdtscp +lmi64 diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G3-v1/Opteron_G3-v1 b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G3-v1/Opteron_G3-v1 new file mode 100644 index 0000000..dd3a0d9 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G3-v1/Opteron_G3-v1 @@ -0,0 +1,11 @@ +{0x1,0x0,0x0,0x0}:{0x100f23,0x800,0x80802009,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0x5,0x68747541,0x444d4163,0x69746e65} +{0x6,0x0,0x0,0x0}:{0x0,0x0,0x3,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x0,0x3,0x0} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x3,0x0} +{0x80000001,0x0,0x0,0x0}:{0x100f23,0x0,0x65,0x2993fbfd} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x1,0x10,0x0,0x0} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x3,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x0,0x0,0x3,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G4-v1/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G4-v1/FlagsF.txt new file mode 100644 index 0000000..c0a0ebd --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G4-v1/FlagsF.txt @@ -0,0 +1,109 @@ +dtes64 +monitor +dscpl +vmx +smx +est +tm2 +cid +fma +xtpr +pdcm +pcid +dca +x2apic +movbe +tsc_deadline +f16c +rdrand +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +arat +fsgsbase +tsc_adjust +bmi1 +hle +avx2 +smep +bmi2 +erms +invpcid +rtm +mpx +avx512f +avx512dq +rdseed +adx +smap +avx512ifma +pcommit +clflushopt +clwb +avx512pf +avx512er +avx512cd +sha_ni +avx512bw +avx512vl +avx512vbmi +umip +pku +ospke +avx512_vpopcntdq +la57 +rdpid +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +extapic +cr8legacy +misalignsse +osvw +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +mmxext +fxsr_opt +_3dnowext +_3dnow +invtsc +lbrv +svm_lock +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G4-v1/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G4-v1/FlagsT.txt new file mode 100644 index 0000000..8aabad4 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G4-v1/FlagsT.txt @@ -0,0 +1,45 @@ +sse3 +pclmulqdq +ssse3 +cx16 +sse4_1 +sse4_2 +popcnt +aes +xsave +osxsave +avx +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +lahf_lm +svm +abm +sse4a +_3dnowprefetch +syscall +nxxd +pdpe1gb +rdtscp +lmi64 +npt +nrip_save diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G4-v1/Opteron_G4-v1 b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G4-v1/Opteron_G4-v1 new file mode 100644 index 0000000..dc1cb56 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G4-v1/Opteron_G4-v1 @@ -0,0 +1,11 @@ +{0x1,0x0,0x0,0x0}:{0x600f12,0x800,0x9e982203,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0xd,0x68747541,0x444d4163,0x69746e65} +{0x6,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x80000001,0x0,0x0,0x0}:{0x600f12,0x0,0x165,0x2d93fbfd} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x1,0x10,0x0,0x9} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x0,0x340,0x0,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G5-v1/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G5-v1/FlagsF.txt new file mode 100644 index 0000000..979e34e --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G5-v1/FlagsF.txt @@ -0,0 +1,107 @@ +dtes64 +monitor +dscpl +vmx +smx +est +tm2 +cid +xtpr +pdcm +pcid +dca +x2apic +movbe +tsc_deadline +rdrand +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +arat +fsgsbase +tsc_adjust +bmi1 +hle +avx2 +smep +bmi2 +erms +invpcid +rtm +mpx +avx512f +avx512dq +rdseed +adx +smap +avx512ifma +pcommit +clflushopt +clwb +avx512pf +avx512er +avx512cd +sha_ni +avx512bw +avx512vl +avx512vbmi +umip +pku +ospke +avx512_vpopcntdq +la57 +rdpid +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +extapic +cr8legacy +misalignsse +osvw +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +mmxext +fxsr_opt +_3dnowext +_3dnow +invtsc +lbrv +svm_lock +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G5-v1/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G5-v1/FlagsT.txt new file mode 100644 index 0000000..0499534 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G5-v1/FlagsT.txt @@ -0,0 +1,47 @@ +sse3 +pclmulqdq +ssse3 +fma +cx16 +sse4_1 +sse4_2 +popcnt +aes +xsave +osxsave +avx +f16c +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +lahf_lm +svm +abm +sse4a +_3dnowprefetch +syscall +nxxd +pdpe1gb +rdtscp +lmi64 +npt +nrip_save diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G5-v1/Opteron_G5-v1 b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G5-v1/Opteron_G5-v1 new file mode 100644 index 0000000..bac96a4 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Opteron_G5-v1/Opteron_G5-v1 @@ -0,0 +1,11 @@ +{0x1,0x0,0x0,0x0}:{0x600f20,0x800,0xbe983203,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0xd,0x68747541,0x444d4163,0x69746e65} +{0x6,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x80000001,0x0,0x0,0x0}:{0x600f20,0x0,0x165,0x2d93fbfd} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x1,0x10,0x0,0x9} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x0,0x340,0x0,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Skylake-Server-v1/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/Skylake-Server-v1/FlagsF.txt new file mode 100644 index 0000000..fc142a0 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Skylake-Server-v1/FlagsF.txt @@ -0,0 +1,91 @@ +dtes64 +monitor +dscpl +vmx +smx +est +tm2 +cid +xtpr +pdcm +dca +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +tsc_adjust +hle +rtm +mpx +avx512f +avx512dq +avx512ifma +pcommit +avx512pf +avx512er +avx512cd +sha_ni +avx512bw +avx512vl +avx512vbmi +umip +ospke +avx512_vpopcntdq +la57 +rdpid +avx512_4vnniw +avx512_4fmaps +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +svm +extapic +cr8legacy +sse4a +misalignsse +osvw +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +mmxext +fxsr_opt +_3dnowext +_3dnow +invtsc +npt +lbrv +svm_lock +nrip_save +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Skylake-Server-v1/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/Skylake-Server-v1/FlagsT.txt new file mode 100644 index 0000000..6ac1f2b --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Skylake-Server-v1/FlagsT.txt @@ -0,0 +1,63 @@ +sse3 +pclmulqdq +ssse3 +fma +cx16 +pcid +sse4_1 +sse4_2 +x2apic +movbe +popcnt +tsc_deadline +aes +xsave +osxsave +avx +f16c +rdrand +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +arat +fsgsbase +bmi1 +avx2 +smep +bmi2 +erms +invpcid +rdseed +adx +smap +clflushopt +clwb +pku +avx512_bf16 +lahf_lm +abm +_3dnowprefetch +syscall +nxxd +pdpe1gb +rdtscp +lmi64 diff --git a/Library/Tests/Cpuid/Mock/simnowdata/Skylake-Server-v1/Skylake-Server-v1 b/Library/Tests/Cpuid/Mock/simnowdata/Skylake-Server-v1/Skylake-Server-v1 new file mode 100644 index 0000000..0acb870 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/Skylake-Server-v1/Skylake-Server-v1 @@ -0,0 +1,11 @@ +{0x1,0x0,0x0,0x0}:{0x50654,0x800,0xfffa3203,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0xd,0x756e6547,0x6c65746e,0x49656e69} +{0x6,0x0,0x0,0x0}:{0x4,0x0,0x0,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x19c07a9,0x8,0x0} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x80000001,0x0,0x0,0x0}:{0x50654,0x0,0x121,0x2c100800} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x5,0x988,0x0,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/Mock/simnowdata/phenom-v1/FlagsF.txt b/Library/Tests/Cpuid/Mock/simnowdata/phenom-v1/FlagsF.txt new file mode 100644 index 0000000..827b7c9 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/phenom-v1/FlagsF.txt @@ -0,0 +1,113 @@ +pclmulqdq +dtes64 +dscpl +vmx +smx +est +tm2 +ssse3 +cid +fma +xtpr +pdcm +pcid +dca +sse4_1 +sse4_2 +x2apic +movbe +tsc_deadline +aes +xsave +osxsave +avx +f16c +rdrand +vme +pn +ds +acpi +ss +ht +tm +ia64 +pbe +arat +fsgsbase +tsc_adjust +bmi1 +hle +avx2 +smep +bmi2 +erms +invpcid +rtm +mpx +avx512f +avx512dq +rdseed +adx +smap +avx512ifma +pcommit +clflushopt +clwb +avx512pf +avx512er +avx512cd +sha_ni +avx512bw +avx512vl +umip +pku +ospke +avx512_vpopcntdq +la57 +rdpid +avx512_4vnniw +avx512_4fmaps +avx512_bf16 +avxvnni +xsaveopt +xsavec +xgetbv1 +xsaves +cmp_legacy +extapic +cr8legacy +misalignsse +_3dnowprefetch +osvw +ibs +xop +skinit +wdt +lwp +fma4 +tce +nodeid_msr +tbm +topoext +perfctr_core +perfctr_nb +invtsc +lbrv +svm_lock +nrip_save +tsc_scale +vmcb_clean +flushbyasid +decodeassists +pause_filter +pfthreshold +xstore +xstore_en +xcrypt +xcrypt_en +ace2 +ace2_en +phe +phe_en +pmm +pmm_en diff --git a/Library/Tests/Cpuid/Mock/simnowdata/phenom-v1/FlagsT.txt b/Library/Tests/Cpuid/Mock/simnowdata/phenom-v1/FlagsT.txt new file mode 100644 index 0000000..5a36925 --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/phenom-v1/FlagsT.txt @@ -0,0 +1,41 @@ +sse3 +monitor +cx16 +popcnt +hypervisor +fpu +de +pse +tsc +msr +pae +mce +cx8 +apic +sep +mtrr +pge +mca +cmov +pat +pse36 +clflush +mmx +fxsr +sse +sse2 +avx512vbmi +lahf_lm +svm +abm +sse4a +syscall +nxxd +mmxext +fxsr_opt +pdpe1gb +rdtscp +lmi64 +_3dnowext +_3dnow +npt diff --git a/Library/Tests/Cpuid/Mock/simnowdata/phenom-v1/phenom-v1 b/Library/Tests/Cpuid/Mock/simnowdata/phenom-v1/phenom-v1 new file mode 100644 index 0000000..f04f93c --- /dev/null +++ b/Library/Tests/Cpuid/Mock/simnowdata/phenom-v1/phenom-v1 @@ -0,0 +1,11 @@ +{0x1,0x0,0x0,0x0}:{0x100f23,0x800,0x80802009,0x78bfbfd} +{0x0,0x0,0x0,0x0}:{0x5,0x68747541,0x444d4163,0x69746e65} +{0x6,0x0,0x0,0x0}:{0x0,0x0,0x3,0x0} +{0x7,0x0,0x0,0x0}:{0x0,0x0,0x3,0x0} +{0xd,0x0,0x0,0x0}:{0x0,0x0,0x3,0x0} +{0x80000001,0x0,0x0,0x0}:{0x100f23,0x0,0x65,0xefd3fbfd} +{0x80000007,0x0,0x0,0x0}:{0x0,0x0,0x0,0x0} +{0x8000000a,0x0,0x0,0x0}:{0x1,0x10,0x0,0x1} +{0xc0000001,0x0,0x0,0x0}:{0x0,0x0,0x3,0x0} +{0x8000001d,0x0,0x1,0x0}:{0x0,0x0,0x3,0x0} +{0x7,0x0,0x1,0x0}:{0x0,0x0,0x0,0x0} diff --git a/Library/Tests/Cpuid/QemuTest.hh b/Library/Tests/Cpuid/QemuTest.hh new file mode 100644 index 0000000..7cc013f --- /dev/null +++ b/Library/Tests/Cpuid/QemuTest.hh @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#if defined(AU_TARGET_OS_IS_LINUX) +#include +#endif +#include "Au/Cpuid/X86Cpu.hh" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace { +using namespace Au; +/** + * Test parameters for X86Cpu Qemu test + * 1. Name of the CPU model to be emulated by Qemu + * 2. Vector containing the following parameters: + * 1. Name of the CPU model to be emulated by Qemu + * 2. Vector of boolean values that marks the expected results of + * {is_AMD, is_Intel, is_X86_64v2, is_X86_64v3, is_X86_64v4} APIs + * 3. The Uarch(microarchitecutre) of the CPU. + */ +// clang-format off +auto isAmd=true, isIntel=true, isX86_64v2=true, isX86_64v3=true, isX86_64v4=true, flagPresent=true, flagAbsent=true, isUarch=true; +const std::vector, EUarch>> testParametersX86Cpu = { + { "EPYC-Genoa-v1", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen4 }, + { "EPYC-Milan-v1", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen3 }, + { "EPYC-Milan-v2", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen3 }, + { "EPYC-Rome-v1", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen2 }, + { "EPYC-Rome-v2", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen2 }, + { "EPYC-Rome-v3", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen2 }, + { "EPYC-Rome-v4", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen2 }, + { "EPYC-v1", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen }, + { "EPYC-v2", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen }, + { "EPYC-v3", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen }, + { "EPYC-v4", { isAmd, !isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, isUarch }, EUarch::Zen }, + { "Opteron_G1-v1", { isAmd, !isIntel, !isX86_64v2, !isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, !isUarch }, EUarch::Unknown }, + { "Opteron_G2-v1", { isAmd, !isIntel, !isX86_64v2, !isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, !isUarch }, EUarch::Unknown }, + { "Opteron_G3-v1", { isAmd, !isIntel, !isX86_64v2, !isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, !isUarch }, EUarch::Unknown }, + { "Opteron_G4-v1", { isAmd, !isIntel, isX86_64v2, !isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, !isUarch }, EUarch::Unknown }, + { "Opteron_G5-v1", { isAmd, !isIntel, isX86_64v2, !isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, !isUarch }, EUarch::Unknown }, + { "phenom-v1", { isAmd, !isIntel, !isX86_64v2, !isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, !isUarch }, EUarch::Unknown }, + //{ "Broadwell-v1", { !isAmd, isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, !isUarch }, EUarch::Unknown }, + { "Denverton-v1", { !isAmd, isIntel, isX86_64v2, !isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, !isUarch }, EUarch::Unknown }, + { "Conroe-v1", { !isAmd, isIntel, !isX86_64v2, !isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, !isUarch }, EUarch::Unknown }, + //{ "Skylake-Server-v1", { !isAmd, isIntel, isX86_64v2, isX86_64v3, !isX86_64v4, flagPresent, flagAbsent, !isUarch }, EUarch::Unknown } +}; +// clang-format on + +/** + * Test parameters to verify getVendorInfo Api + * Vector contains the following parameters: + * 1. Name of the CPU model to be emulated using Qemu + * 2. VendorInfo structure containing the expected results. + */ +// clang-format off +const std::vector> testParametersVendorInfo = { + { "EPYC-Genoa-v1", { VendorInfo{ EVendor::Amd, EFamily::Zen4, 0x11, 0x0, EUarch::Zen4 } } }, + { "EPYC-Milan-v1", { VendorInfo{ EVendor::Amd, EFamily::Zen4, 0x01, 0x1, EUarch::Zen3 } } }, + { "EPYC-Milan-v2", { VendorInfo{ EVendor::Amd, EFamily::Zen4, 0x01, 0x1, EUarch::Zen3 } } }, + { "EPYC-Rome-v1", { VendorInfo{ EVendor::Amd, EFamily::Zen2, 0x31, 0x0, EUarch::Zen2 } } }, + { "EPYC-Rome-v2", { VendorInfo{ EVendor::Amd, EFamily::Zen2, 0x31, 0x0, EUarch::Zen2 } } }, + { "EPYC-Rome-v3", { VendorInfo{ EVendor::Amd, EFamily::Zen2, 0x31, 0x0, EUarch::Zen2 } } }, + { "EPYC-Rome-v4", { VendorInfo{ EVendor::Amd, EFamily::Zen2, 0x31, 0x0, EUarch::Zen2 } } }, + { "EPYC-v1", { VendorInfo{ EVendor::Amd, EFamily::Zen2, 0x01, 0x2, EUarch::Zen } } }, + { "EPYC-v2", { VendorInfo{ EVendor::Amd, EFamily::Zen2, 0x01, 0x2, EUarch::Zen } } }, + { "EPYC-v3", { VendorInfo{ EVendor::Amd, EFamily::Zen2, 0x01, 0x2, EUarch::Zen } } }, + { "EPYC-v4", { VendorInfo{ EVendor::Amd, EFamily::Zen2, 0x01, 0x2, EUarch::Zen } } }, + { "Opteron_G1-v1", { VendorInfo{ EVendor::Amd, EFamily::Unknown, 0x06, 0x1, EUarch::Unknown } } }, + { "Opteron_G2-v1", { VendorInfo{ EVendor::Amd, EFamily::Unknown, 0x06, 0x1, EUarch::Unknown } } }, + { "Opteron_G3-v1", { VendorInfo{ EVendor::Amd, EFamily::Unknown, 0x02, 0x3, EUarch::Unknown } } }, + { "Opteron_G4-v1", { VendorInfo{ EVendor::Amd, EFamily::Unknown, 0x01, 0x2, EUarch::Unknown } } }, + { "Opteron_G5-v1", { VendorInfo{ EVendor::Amd, EFamily::Unknown, 0x02, 0x0, EUarch::Unknown } } }, + { "phenom-v1", { VendorInfo{ EVendor::Amd, EFamily::Unknown, 0x02, 0x3, EUarch::Unknown } } }, + { "Broadwell-v1", { VendorInfo{ EVendor::Intel, EFamily::Unknown, 0X3D, 0x2, EUarch::Unknown } } }, + { "Denverton-v1", { VendorInfo{ EVendor::Intel, EFamily::Unknown, 0x5F, 0x1, EUarch::Unknown } } }, + { "Conroe-v1", { VendorInfo{ EVendor::Intel, EFamily::Unknown, 0x0F, 0x3, EUarch::Unknown } } }, + { "Skylake-Server-v1", { VendorInfo{ EVendor::Intel, EFamily::Unknown, 0x55, 0x4, EUarch::Unknown } } } +}; + +class QemuTestBase :public testing::Test +{ + protected: + /** + * @brief Call the Qemu emulator to run the tests + * Implemented in a python module named CpuidTest. + * @param[in] cpu The type of the cpu to emulate + * @param[in] testName The name of the test to runi + * + * @return bool The result of the test run on the emulated cpu + */ + static bool callQemuEmulator(const char* cpu, const char* testName) + { + auto ret = false; + +#if defined(AU_TARGET_OS_IS_LINUX) + Py_Initialize(); + if (Py_IsInitialized() == 0) { + std::cerr << "Failed to initialize the Python interpreter"; + } + /* Update PYTHONPATH with the path of the python module to be loaded*/ + std::string srcPath = PROJECT_SOURCE_DIR; + srcPath += "/Library/Tests/Cpuid/"; + PyObject* sys = PyImport_ImportModule("sys"); + PyObject* sysPath = PyObject_GetAttrString(sys, "path"); + PyObject* folderPath = PyUnicode_FromString(srcPath.c_str()); + PyList_Append(sysPath, folderPath); + + /*Load The test module */ + PyObject* pModule = PyImport_ImportModule("CpuidTest"); + + if (pModule != NULL) { + PyObject* pFunc = PyObject_GetAttrString(pModule, "run_qemu"); + + if (pFunc != NULL && PyCallable_Check(pFunc) != 0) { + /* Call the run_qemu function with arguments */ + std::string binaryPath = PROJECT_BUILD_DIR; + std::string releaseType; + if (AU_BUILD_TYPE_RELEASE) + releaseType = "Release"; + if (AU_BUILD_TYPE_DEBUG) + releaseType = "Debug"; + if (AU_BUILD_TYPE_DEVELOPER) + releaseType = "Library/Tests"; + + binaryPath += "/" + releaseType + "/aoclutils_CpuidTest"; + + PyObject* pArgs = + PyTuple_Pack(4, + PyUnicode_DecodeFSDefault("x86_64"), + PyUnicode_DecodeFSDefault(cpu), + PyUnicode_DecodeFSDefault(binaryPath.c_str()), + PyUnicode_DecodeFSDefault(testName)); + PyObject* pValue = PyObject_CallObject(pFunc, pArgs); + + if (pValue != NULL) { + ret = PyLong_AsLong(pValue) != 0; + } + } + } + /* Finalize the Python interpreter */ + Py_Finalize(); +#endif + return ret; + } + /** + * @brief Clean up the test environment + * + * @return void + */ + void TearDown() override + { + std::string cleanPath = PROJECT_SOURCE_DIR; + cleanPath += "/Library/Tests/Cpuid/__pycache__/"; + std::filesystem::remove_all(cleanPath); + std::remove("FlagsT.txt"); + std::remove("FlagsF.txt"); + std::remove("Uarch.txt"); + std::remove("UarchResult.txt"); + std::remove("VendorInfoC.txt"); + std::remove("VendorInfoCpp.txt"); + } +}; +} // namespace diff --git a/Library/Tests/Cpuid/__pycache__/CpuidTest.cpython-312.pyc b/Library/Tests/Cpuid/__pycache__/CpuidTest.cpython-312.pyc new file mode 100644 index 0000000..a8d0715 Binary files /dev/null and b/Library/Tests/Cpuid/__pycache__/CpuidTest.cpython-312.pyc differ diff --git a/Library/Tests/DynamicLoaderTest.cc b/Library/Tests/DynamicLoaderTest.cc new file mode 100644 index 0000000..ed5fb6e --- /dev/null +++ b/Library/Tests/DynamicLoaderTest.cc @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2022-2022, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "gtest/gtest.h" + +#include "Au/DynamicLoader.hh" + +namespace { +using namespace Au; + +TEST(DynLibrary, DefaultConstruct) +{ + // Construct a DynamicLibraryObject + // Give some path + // Query name, should match filename + GTEST_FAIL(); +} + +TEST(DynLibrary, GetSuffix) +{ + // Create a DynamicLibrary + // query its suffix + // should match file extension (on Linux and windows) + GTEST_FAIL(); +} + +TEST(DynLibrary, GetPath) +{ + // Create Library + // Qeury the path, + // should match what is provided + GTEST_FAIL(); +} + +TEST(DynLibrary, Load_via_Loader) +{ + // Construct a loader + // load a library + // search if the library exist + // validated name + GTEST_FAIL(); +} + +TEST(DynLoader, DefaultConstructor) +{ + DynamicLoader dld; + + auto dl = DynamicLibrary{ "/lib/ld-linux.so" }; + auto s = dld.load(&dl); + + EXPECT_TRUE(s.ok()); +} + +TEST(DynLoader, SearchNonExistingName) +{ + // Create a Dynamic Loader object + // Search for some dummy name + // should return not found + GTEST_FAIL(); +} + +TEST(DynLoader, SearchWithName) +{ + // Create a valid DynamicLibrary Object with path + // Create a Loader + // Load with DynamicLibrary object with Loader + // Search Loader with name (file name) + // should find the name + GTEST_FAIL(); +} + +TEST(DynLoader, InvalidLoad) +{ + // Try to load an non-exitant library + // and check appropriate error code. + GTEST_FAIL(); +} + +TEST(DynLoader, UnloadOnDestructor) +{ + // Create a DynamicLibrary object with path + // Create a dynamicLoader + // Load a DynamicLibrary object with loader + // + GTEST_FAIL(); +} + +} // namespace diff --git a/Library/Tests/EnvTest.cc b/Library/Tests/EnvTest.cc new file mode 100644 index 0000000..dc3d22b --- /dev/null +++ b/Library/Tests/EnvTest.cc @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2022-2022, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/Environ.hh" + +#include "gtest/gtest.h" + +#include + +#if defined(WIN32) || defined(_WINDOWS) + auto homeEnv = "USERPROFILE"; +#else + auto homeEnv = "HOME"; +#endif + +namespace { +using namespace Au; + +/** + * IMPORTANT: + * Since we use the global environment of application, + * The test will modify its own environment. + * Hence the order of these tests are important + * be mindful of Env::init() being called. + */ + +TEST(Environ, getUserEnv) +{ + // Get a user environment ($USER, or $HOME) + auto home = Env::get(homeEnv); + + EXPECT_STREQ(home.data(), std::getenv(homeEnv)); +} + +TEST(Environ, setNewUserEnv) +{ + const auto nss = "not-so-sweet"; + Env::set("SWEETHOME", nss); + auto shome = Env::get("SWEETHOME"); + + /* Comparing returned pointer */ + EXPECT_EQ(shome, nss); + + /* Comparing text */ + EXPECT_STREQ(shome.data(), nss); +} + +TEST(Environ, checkInit) +{ + Env::set("SWEETHOME", "yes-it-is-sweet"); + + EXPECT_TRUE(Env::get("SWEETHOME").length() > 1); + + { + const char* envp[] = { + NULL, + }; + Env::init(envp); + } + + EXPECT_STREQ(Env::get("SWEETHOME").data(), ""); +} + +TEST(Environ, setExistingUserEnv) +{ + auto orig_home = Env::get(homeEnv); + auto dummytxt = "abcd"; + + Env::set(homeEnv, dummytxt); + EXPECT_EQ(Env::get(homeEnv), dummytxt); + + Env::set(homeEnv, String(orig_home)); + EXPECT_EQ(Env::get(homeEnv), orig_home); +} + +TEST(Environ, setUserEmpty) +{ + const char* envp[] = { NULL }; + + Env::init(envp); /* get fresh userenv */ + + /* in fresh env, we expect no SWEETHOME key */ + EXPECT_STREQ(Env::get("SWEETHOME").data(), ""); + + Env::set("SWEETHOME", "not-so-sweet"); + EXPECT_STREQ(Env::get("SWEETHOME").data(), "not-so-sweet"); + + Env::set("SWEETHOME", ""); + EXPECT_STREQ(Env::get("SWEETHOME").data(), ""); +} + +TEST(Environ, checkExists) +{ + const char* envp[] = { + "MYHOME=/foo/bar", + "MYNAME=foobar", + "MYJOB=barfoo", + NULL, + }; + + Env::init(envp); + + EXPECT_STREQ(Env::get("MYHOME").data(), "/foo/bar"); + EXPECT_STREQ(Env::get("MYNAME").data(), "foobar"); + EXPECT_STREQ(Env::get("MYJOB").data(), "barfoo"); +} + +TEST(Environ, checkSpaces) +{ + const char* envp[] = { + "MYHOME = /foo/bar", + " MYNAME = foobar", + "MYJOB = barfoo ", + " MYCAR = bugati ", + NULL, + }; + + Env::init(envp); + + EXPECT_EQ(Env::get("MYHOME"), "/foo/bar"); + EXPECT_EQ(Env::get("MYNAME"), "foobar"); + EXPECT_EQ(Env::get("MYJOB"), "barfoo"); + EXPECT_EQ(Env::get("MYCAR"), "bugati"); +} + +TEST(Environ, checkSystemEnv) +{ + // modifications to Userenv + // should not change system env + + auto orig_home = Env::get(homeEnv); + + Env::set(homeEnv, "abcd"); + EXPECT_STREQ(Env::get(homeEnv).data(), "abcd"); + + // std::getenv gets it from system environment, independent of our + // cached values. + EXPECT_STRNE(Env::get(homeEnv).data(), std::getenv(homeEnv)); + + Env::set(homeEnv, orig_home.data()); + EXPECT_STREQ(Env::get(homeEnv).data(), std::getenv(homeEnv)); +} + +TEST(Environ, checkScopedString) +{ + // We want to test if the stored 'std::string' in Env is a copy + { + { + const char* envp[] = { + NULL, + }; + Env::init(envp); + Env::set("SWEETHOME", "yes-it-is-sweet"); + } + } + + EXPECT_STREQ(Env::get("SWEETHOME").data(), "yes-it-is-sweet"); +} + +} // namespace diff --git a/Library/Tests/ErrorTest.cc b/Library/Tests/ErrorTest.cc new file mode 100644 index 0000000..db5e122 --- /dev/null +++ b/Library/Tests/ErrorTest.cc @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2022-2022, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "Au/Au.hh" + +#include "Au/Error.hh" + +#include "gtest/gtest.h" + +using namespace Au; + +namespace { + +TEST(Error, check_noerror) +{ + auto& er = Au::NoError(); + + EXPECT_EQ(er.code(), 0); + + EXPECT_FALSE(Au::AlreadyExistsError().code() == er.code()); + EXPECT_FALSE(Au::InternalError().code() == er.code()); + EXPECT_FALSE(Au::InvalidArgumentError().code() == er.code()); + EXPECT_FALSE(Au::NotFoundError().code() == er.code()); + EXPECT_FALSE(Au::NotImplementedError().code() == er.code()); + EXPECT_FALSE(Au::NotAvailableError().code() == er.code()); + EXPECT_FALSE(Au::UnknownError().code() == er.code()); +} + +TEST(Error, check_eexists) +{ + auto& er = Au::AlreadyExistsError(); + + EXPECT_FALSE(Au::InternalError().code() == er.code()); + EXPECT_FALSE(Au::InvalidArgumentError().code() == er.code()); + EXPECT_FALSE(Au::NotFoundError().code() == er.code()); + EXPECT_FALSE(Au::NotImplementedError().code() == er.code()); + EXPECT_FALSE(Au::NotAvailableError().code() == er.code()); + EXPECT_FALSE(Au::UnknownError().code() == er.code()); + EXPECT_FALSE(Au::NoError().code() == er.code()); +} + +TEST(Error, check_einternal) +{ + auto& er = Au::InternalError(); + + // EXPECT_FALSE(Au::InternalError().code() == er.code()); + EXPECT_FALSE(Au::AlreadyExistsError().code() == er.code()); + EXPECT_FALSE(Au::InvalidArgumentError().code() == er.code()); + EXPECT_FALSE(Au::NotFoundError().code() == er.code()); + EXPECT_FALSE(Au::NotImplementedError().code() == er.code()); + EXPECT_FALSE(Au::NotAvailableError().code() == er.code()); + EXPECT_FALSE(Au::UnknownError().code() == er.code()); + EXPECT_FALSE(Au::NoError().code() == er.code()); +} + +TEST(Error, check_einvalidarg) +{ + auto& er = Au::InvalidArgumentError(); + + EXPECT_FALSE(Au::InternalError().code() == er.code()); + EXPECT_FALSE(Au::AlreadyExistsError().code() == er.code()); + // EXPECT_FALSE(Au::InvalidArgumentError().code() == er.code()); + EXPECT_FALSE(Au::NotFoundError().code() == er.code()); + EXPECT_FALSE(Au::NotImplementedError().code() == er.code()); + EXPECT_FALSE(Au::NotAvailableError().code() == er.code()); + EXPECT_FALSE(Au::UnknownError().code() == er.code()); + EXPECT_FALSE(Au::NoError().code() == er.code()); +} + +TEST(Error, check_enotfound) +{ + auto& er = Au::NotFoundError(); + + EXPECT_FALSE(Au::InternalError().code() == er.code()); + EXPECT_FALSE(Au::AlreadyExistsError().code() == er.code()); + EXPECT_FALSE(Au::InvalidArgumentError().code() == er.code()); + // EXPECT_FALSE(Au::NotFoundError().code() == er.code()); + EXPECT_FALSE(Au::NotImplementedError().code() == er.code()); + EXPECT_FALSE(Au::NotAvailableError().code() == er.code()); + EXPECT_FALSE(Au::UnknownError().code() == er.code()); + EXPECT_FALSE(Au::NoError().code() == er.code()); +} + +TEST(Error, check_enotimpl) +{ + auto& er = Au::NotImplementedError(); + + EXPECT_FALSE(Au::InternalError().code() == er.code()); + EXPECT_FALSE(Au::AlreadyExistsError().code() == er.code()); + EXPECT_FALSE(Au::InvalidArgumentError().code() == er.code()); + EXPECT_FALSE(Au::NotFoundError().code() == er.code()); + // EXPECT_FALSE(Au::NotImplementedError().code() == er.code()); + EXPECT_FALSE(Au::NotAvailableError().code() == er.code()); + EXPECT_FALSE(Au::UnknownError().code() == er.code()); + EXPECT_FALSE(Au::NoError().code() == er.code()); +} + +TEST(Error, check_enotavail) +{ + auto& er = Au::NotAvailableError(); + + EXPECT_FALSE(Au::InternalError().code() == er.code()); + EXPECT_FALSE(Au::AlreadyExistsError().code() == er.code()); + EXPECT_FALSE(Au::InvalidArgumentError().code() == er.code()); + EXPECT_FALSE(Au::NotFoundError().code() == er.code()); + EXPECT_FALSE(Au::NotImplementedError().code() == er.code()); + // EXPECT_FALSE(Au::NotAvailableError().code() == er.code()); + EXPECT_FALSE(Au::UnknownError().code() == er.code()); + EXPECT_FALSE(Au::NoError().code() == er.code()); +} + +TEST(Error, check_unknown) +{ + auto& er = Au::UnknownError(); + + EXPECT_FALSE(Au::InternalError().code() == er.code()); + EXPECT_FALSE(Au::AlreadyExistsError().code() == er.code()); + EXPECT_FALSE(Au::InvalidArgumentError().code() == er.code()); + EXPECT_FALSE(Au::NotFoundError().code() == er.code()); + EXPECT_FALSE(Au::NotImplementedError().code() == er.code()); + EXPECT_FALSE(Au::NotAvailableError().code() == er.code()); + // EXPECT_FALSE(Au::UnknownError().code() == er.code()); + EXPECT_FALSE(Au::NoError().code() == er.code()); +} + +} // namespace diff --git a/Library/Tests/SourceLocationTest.cc b/Library/Tests/SourceLocationTest.cc new file mode 100644 index 0000000..e69de29 diff --git a/Library/Tests/StatusOrTest.cc b/Library/Tests/StatusOrTest.cc new file mode 100644 index 0000000..bccf656 --- /dev/null +++ b/Library/Tests/StatusOrTest.cc @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2022-2022, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "Au/StatusOr.hh" + +#include "type_traits" + +#include "gtest/gtest.h" + +namespace Au { + +using namespace Au; + +TEST(StatusOr, ElementType) +{ + static_assert(std::is_same::value_type, int>(), ""); + static_assert(std::is_same::value_type, char>(), ""); +} + +// Check operator arrow +TEST(StatusOr, ArrowOperator) +{ + const StatusOr const_val("AOCL Utils"); + EXPECT_STREQ(std::string("AOCL Utils").c_str(), const_val->c_str()); +} + +TEST(StatusOr, Value) +{ + int v = 10; + + StatusOr sts{ v }; + EXPECT_EQ(sts.value(), v); + + { + std::unique_ptr ten = std::make_unique(10); + StatusOr sts1{ std::move(*ten) }; + EXPECT_EQ(sts1.value(), 10); + } + + { + StatusOr> sts_unq_int = std::make_unique(10); + std::unique_ptr tenn = std::move(sts_unq_int.value()); + EXPECT_EQ(*tenn, 10); + } +} + +TEST(StatusOr, asdf) {} + +TEST(StatusOr, WithQualifierStar) +{ + static_assert( + std::is_same&>())>(), + "invalid qualifiers"); + + static_assert( + std::is_same&>())>(), + "invalid qualifier"); + + static_assert( + std::is_same&&>())>(), + "invalid qualifier"); + + static_assert( + std::is_same&&>())>(), + "invalid qualifier"); +} + +// Operator arrow with qualifiers +TEST(StatusOr, WithQualifierArrow) +{ + static_assert( + std::is_same< + const int*, + decltype(std::declval&>().operator->())>(), + "invalid qualifiers"); + static_assert( + std::is_same&>().operator->())>(), + "invalid qualifier"); + + static_assert( + std::is_same< + const int*, + decltype(std::declval&&>().operator->())>(), + "invalid qualifier"); + + static_assert( + std::is_same&&>().operator->())>(), + "invalid qualifier"); +} + +} // namespace Au diff --git a/Library/Tests/StatusTest.cc b/Library/Tests/StatusTest.cc new file mode 100644 index 0000000..c873cce --- /dev/null +++ b/Library/Tests/StatusTest.cc @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2022,2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "Au/Error.hh" +#include "Au/Status.hh" +#include "Au/Types.hh" + +#include "gtest/gtest.h" + +namespace { + +using namespace Au; +bool +endsWith(String mainString, String subString) +{ + return mainString.compare(mainString.size() - subString.size(), + subString.size(), + subString) + == 0; +} +TEST(Status, check_eok) +{ + Status sts = StatusOk(); + + EXPECT_EQ(sts.code(), NoError().code()); +} + +TEST(Status, check_eexists) +{ + String s{ "here" }; + Status sts = StatusAlreadyExists(s); + + EXPECT_EQ(sts.code(), AlreadyExistsError().code()); + EXPECT_TRUE(endsWith(sts.message(), s)); +} + +TEST(Status, check_einvalid) +{ + String s{ "my_var is invalid" }; + Status sts = StatusInvalidArgument(s); + + EXPECT_EQ(sts.code(), InvalidArgumentError().code()); + EXPECT_TRUE(endsWith(sts.message(), s)); +} + +TEST(Status, check_enotfound) +{ + String s{ "exhausted" }; + Status sts = StatusNotFound(s); + + EXPECT_EQ(sts.code(), NotFoundError().code()); + EXPECT_TRUE(endsWith(sts.message(), s)); +} + +TEST(Status, check_enotavail) +{ + String s{ "list exhausted" }; + Status sts = StatusNotAvailable(s); + + EXPECT_EQ(sts.code(), NotAvailableError().code()); + EXPECT_TRUE(endsWith(sts.message(), s)); +} + +TEST(Status, check_enotimpl) +{ + String s{ "myimpl" }; + Status sts = StatusNotImplemented(s); + + EXPECT_EQ(sts.code(), NotImplementedError().code()); + EXPECT_TRUE(endsWith(sts.message(), s)); +} + +TEST(Status, check_eunknown) +{ + String s{ "Known" }; + Status sts = StatusUnknown(s); + + EXPECT_EQ(sts.code(), UnknownError().code()); + EXPECT_TRUE(endsWith(sts.message(), s)); +} + +} // namespace diff --git a/Library/Tests/ThreadPinning/MockTest.hh b/Library/Tests/ThreadPinning/MockTest.hh new file mode 100644 index 0000000..189f1eb --- /dev/null +++ b/Library/Tests/ThreadPinning/MockTest.hh @@ -0,0 +1,1050 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "Au/ThreadPinning.hh" +#include "Au/ThreadPinning/ThreadPinning.hh" +#include "Au/Types.hh" +#include "gtest/gtest.h" + +namespace { +using namespace Au; + +typedef std::tuple>, + std::vector>, + std::vector, + std::vector, + std::vector, + std::vector> + testParameterType; +class ThreadPinningTest : public ::testing::TestWithParam +{}; + +/** + * @brief getCoreMask + * + * @details Get the core mask for the given core count, group + * count and hyperthreading status + * + * @param coreCount Number of items in the return vector + * + * @param groupCount group number of the cores + * + * @param isHyperThreading Hyperthreading status + * + * @param isLinux OS type + * + * @param groupOffset group offset + * + * @return vector of core mask + * + */ +std::vector> +getCoreMask(int coreCount, + int groupCount, + bool isHyperThreading, + bool isLinux, + int groupOffset) +{ + std::vector> coreMask; + if (!isHyperThreading) { + for (int i = 0; i < coreCount; i++) { + coreMask.push_back({ std::make_pair(1ULL << i, groupCount) }); + } + return coreMask; + } else { + if (isLinux) { + for (int i = 0; i < coreCount; i++) { + coreMask.push_back( + { std::make_pair(1ULL << i, groupCount), + std::make_pair(1ULL << i, groupCount + groupOffset) }); + } + return coreMask; + } else { + for (int i = 0; i < coreCount; i++) { + coreMask.push_back( + { std::make_pair(0b11ULL << i * 2, groupCount) }); + } + return coreMask; + } + } +} + +/** + * @brief concatCoreMasks + * + * @details Concatenate two core masks + * + * @param coremask1 core mask 1 + * + * @param coremask2 core mask 2 + * + * @return vector of core mask + */ +std::vector> +concatCoreMasks(std::vector> coremask1, + std::vector> coremask2) +{ + std::vector> coremask; + coremask.insert(coremask.end(), coremask1.begin(), coremask1.end()); + coremask.insert(coremask.end(), coremask2.begin(), coremask2.end()); + return coremask; +} +// clang-format off +auto testParametersCpuTopology = { + // Test case 1: No hyperThreading Singlecache number of threads less than + // number of processors + std::make_tuple( + String("Test1"), 8, 2, + getCoreMask(8, 0, false, false, 0), + std::vector>{ { std::make_pair(0b11111111, 0) } }, + std::vector{ std::make_pair(0b11111111, 8) }, + std::vector{ 0, 1 }, + std::vector{ 0, 1 }, + std::vector{ 0, 4 }), + + // Test case 2: No hyperThreading Singlecache number of threads greater than + // number of processors + std::make_tuple( + String("Test2"), 8, 16, + getCoreMask(8, 0, false, false, 0), + std::vector>{ { std::make_pair(0b11111111, 0) } }, + std::vector{ std::make_pair(0b11111111, 8) }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7 }, + std::vector{ 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7 }), + + // Test case 3: No hyperThreading Singlecache number of threads equal to + // number of processors + std::make_tuple( + String("Test3"), 8, 8, + getCoreMask(8, 0, false, false, 0), + std::vector>{ { std::make_pair(0b11111111, 0) } }, + std::vector{ std::make_pair(0b11111111, 8) }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7 }), + + // Test case 4: No hyperThreading Multicache number of threads less than + // number of processors + std::make_tuple( + String("Test4"), 32, 15, + getCoreMask(32, 0, false, false, 0), + std::vector>{ + { std::make_pair(0b1111111111111111, 0), }, + { std::make_pair(0b11111111111111110000000000000000, 0), }, + }, + std::vector{ std::make_pair(0b11111111111111111111111111111111, 32) }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }, + std::vector{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28 }), + + // Test case 5: No hyperThreading Multicache number of threads greater than + // number of processors + std::make_tuple( + String("Test5"), 16, 35, + getCoreMask(16, 0, false, false, 0), + std::vector>{ + { std::make_pair(0b11111111, 0), }, + { std::make_pair(0b1111111100000000, 0), }, + }, + std::vector{ std::make_pair(0b111111111111111, 16) }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2 }, + std::vector{ 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, + 5, 5, 6, 6, 7, 7, 8, 8, 8, 9, 9, 10, + 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15 }), + + // Test case 6: No HyperThreading Multicache number of threads equal to + // number of processors + std::make_tuple(String("Test6"), 16, 16, + getCoreMask(16, 0, false, false, 0), + std::vector>{ + { std::make_pair(0b11111111, 0), }, + { std::make_pair(0b1111111100000000, 0),}, + }, + std::vector{ std::make_pair(0b111111111111111, 16) }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }), + + // Test case 7: No HyperThreading Multicache multicore group number of + // threads less than number of processors + std::make_tuple( + String("Test7"), 96, 15, + concatCoreMasks(getCoreMask(64, 0, false, false, 0), + getCoreMask(32, 1, false, false, 64)), + std::vector>{ + { std::make_pair((((1ULL << 63) - 1) << 1) | 1, 0)}, + { std::make_pair((1ULL << 32) - 1, 1)} + }, + std::vector{ + { std::make_pair((((1ULL << 63) - 1) << 1) | 1, 64)}, + std::make_pair((1ULL << 32) - 1, 32) + }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }, + std::vector{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 68, 72, 76, 80, 84, 88 }), + + // Test case 8: No HyperThreading Multicache multicore group number of + // threads greater than number of processors + std::make_tuple( + String("Test8"), 96, 100, + concatCoreMasks(getCoreMask(64, 0, false, false, 0), + getCoreMask(32, 1, false, false, 64)), + std::vector>{ + { std::make_pair((((1ULL << 63) - 1) << 1) | 1, 0)}, + { std::make_pair((1ULL << 32) - 1, 1)} + }, + std::vector{ + { std::make_pair((((1ULL << 63) - 1) << 1) | 1, 64)}, + std::make_pair((1ULL << 32) - 1, 32) + }, + std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 0, 1, 2, 3 }, + std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 0, 1, 2, 3 }, + std::vector{ + 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18, 20, + 21, 22, 24, 25, 26, 28, 29, 30, 32, 33, 34, 35, 36, 37, 38, 40, 41, + 42, 44, 45, 46, 48, 49, 50, 52, 53, 54, 56, 57, 58, 60, 61, 62, 64, + 64, 65, 65, 66, 66, 67, 68, 68, 69, 70, 70, 71, 72, 72, 73, 74, 74, + 75, 76, 76, 77, 78, 78, 79, 80, 80, 81, 81, 82, 82, 83, 84, 84, 85, + 86, 86, 87, 88, 88, 89, 90, 90, 91, 92, 92, 93, 94, 94, 95 }), + + // Test case 9: No HyperThreading Multicache multicore group number of + // threads equal to number of processors + std::make_tuple( + String("Test9"), 96, 96, + concatCoreMasks(getCoreMask(64, 0, false, false, 0), + getCoreMask(32, 1, false, false, 64)), + std::vector>{ + { std::make_pair((((1ULL << 63) - 1) << 1) | 1, 0)}, + { std::make_pair((1ULL << 32) - 1, 1)} + }, + std::vector{ + { std::make_pair((((1ULL << 63) - 1) << 1) | 1, 64)}, + std::make_pair((1ULL << 32) - 1, 32) + }, + std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95}, + std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95}, + std::vector{ + 0 , 1 , 2 , 4 , 5 , 6 , 8 , 9 , 10, 12, 13, 14, 16, 17, 18, 20, 21, + 22, 24, 25, 26, 28, 29, 30, 32, 33, 34, 36, 37, 38, 40, 41, 42, 44, + 45, 46, 48, 49, 50, 52, 53, 54, 56, 57, 58, 60, 61, 62, 64, 64, 65, + 66, 66, 67, 68, 68, 69, 70, 70, 71, 72, 72, 73, 74, 74, 75, 76, 76, + 77, 78, 78, 79, 80, 80, 81, 82, 82, 83, 84, 84, 85, 86, 86, 87, 88, + 88, 89, 90, 90, 91, 92, 92, 93, 94, 94, 95}), + // Test case 10: No HyperThreading Singlecache multicore group number of + // threads less than number of processors + /** The current facilities in windows indicates that an L3 cache is shared by + * maximum of 64 cores, see GroupMask.Mask from _CACHE_RELATIONSHIP structure + * for now we will test core group containing 16 cores each. for all of them + * sharing same cache + */ + std::make_tuple( + String("Test 10"), 32, 15, + concatCoreMasks(getCoreMask(16, 0, false, false, 0), + getCoreMask(16, 1, false, false, 0)), + std::vector>{ { std::make_pair((1ULL << 32) - 1, 0) } }, + std::vector{ std::make_pair((1ULL << 16) - 1, 16), + std::make_pair((1ULL << 16) - 1, 16) }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }, + std::vector{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28 }), + + // Test case 11: No HyperThreading Singlecache multicore group number of + // threads greater than number of processors + std::make_tuple( + String("Test11"), 32, 35, + concatCoreMasks(getCoreMask(16, 0, false, false, 0), + getCoreMask(16, 1, false, false, 0)), + std::vector>{ { std::make_pair((1ULL << 32) - 1, 0) } }, + std::vector{ std::make_pair((1ULL << 16) - 1, 16), + std::make_pair((1ULL << 16) - 1, 16) }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2 }, + std::vector{ 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }), + + // Test case 12: No HyperThreading Singlecache multicore group number of + // threads equal to number of processors + std::make_tuple( + String("Test12"), 32, 32, + concatCoreMasks(getCoreMask(16, 0, false, false, 0), + getCoreMask(16, 1, false, false, 0)), + std::vector>{ { std::make_pair((1ULL << 32) - 1, 0) } }, + std::vector{ std::make_pair((1ULL << 16) - 1, 16), + std::make_pair((1ULL << 16) - 1, 16) }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31}, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31}, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31}), + + // Test case 13: HyperThreading Singlecache number of threads less than + // number of processors + std::make_tuple( + String("Test13"), 16, 9, + getCoreMask(8, 0, true, false, 0), + std::vector>{{ std::make_pair((1ULL << 16) - 1, 0) } }, + std::vector{ std::make_pair((1ULL << 16) - 1, 16) }, + std::vector{ 0, 2, 4, 6, 8, 10, 12, 14, 1 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8 }, + std::vector{ 0, 1, 2, 4, 6, 8, 10, 12, 14 }), + + // Test case 14: HyperThreading Singlecache number of threads greater than + // number of processors + std::make_tuple( + String("Test14"), 16, 18, + getCoreMask(8, 0, true, false, 0), + std::vector>{ { std::make_pair((1ULL << 16) - 1, 0) } }, + std::vector{ std::make_pair((1ULL << 16) - 1, 16) }, + std::vector{ 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15, 0, 2 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1 }, + std::vector{ 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11, 12, 13, 14, 15 }), + + // Test case 15: HyperThreading Singlecache number of threads equal to + // number of processors + std::make_tuple( + String("Test15"), 16, 16, + getCoreMask(8, 0, true, false, 0), + std::vector>{ + { std::make_pair(0b1111111111111111, 0) } }, + std::vector{ std::make_pair(0b1111111111111111, 16) }, + std::vector{ 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }), + + // Test case 16: HyperThreading Multicache Singlecore group number of + // threads less than number of processors + std::make_tuple( + String("Test16"), 32, 15, + getCoreMask(32, 0, true, false, 0), + std::vector>{ + { std::make_pair(0b1111111111111111, 0), }, + { std::make_pair(0b11111111111111110000000000000000, 0), }, + }, + std::vector{ std::make_pair(0b11111111111111111111111111111111, 32) }, + std::vector{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }, + std::vector{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28 }), + + // Test case 17: HyperThreading Multicache Singlecore group number of + // threads greater than number of processors + std::make_tuple( + String("Test17"), 16, 35, + getCoreMask(8, 0, true, false, 0), + std::vector>{ + { std::make_pair(0b11111111, 0),}, + { std::make_pair(0b1111111100000000, 0), }, + }, + std::vector{ std::make_pair(0b1111111111111111, 16) }, + std::vector{ 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, + 9, 11, 13, 15, 0, 2, 4, 6, 8, 10, 12, 14, + 1, 3, 5, 7, 9, 11, 13, 15, 0, 2, 4 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2 }, + std::vector{ 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, + 5, 5, 6, 6, 7, 7, 8, 8, 8, 9, 9, 10, + 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15 }), + + // Test case 18: HyperThreading Multicache Singlecore group number of + // threads equal to number of processors + std::make_tuple( + String("Test18"), 16, 16, + getCoreMask(8, 0, true, false, 0), + std::vector>{ + { std::make_pair(0b11111111, 0), }, + { std::make_pair(0b1111111100000000, 0), } + }, + std::vector{ std::make_pair(0b1111111111111111, 16) }, + std::vector{ 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }), + + // Test case 19: HyperThreading Multicache multicore group number of threads + // less than number of processors + std::make_tuple( + String("Test19"), 96, 15, + concatCoreMasks(getCoreMask(32, 0, true, false, 0), + getCoreMask(16, 1, true, false, 0)), + std::vector>{ + { std::make_pair((((1ULL << 63) - 1) << 1) | 1, 0)}, + { std::make_pair((1ULL << 32) - 1, 1) } }, + std::vector{ + { std::make_pair((((1ULL << 63) - 1) << 1) | 1, 64)}, + std::make_pair((1ULL << 32) - 1, 32) }, + std::vector{ + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }, + std::vector{ + 0, 8, 16, 24, 32, 40, 48, 56, 64, 68, 72, 76, 80, 84, 88 }), + + // Test case 20: HyperThreading Multicache multicore group number of threads + // greater than number of processors + std::make_tuple( + String("Test20"), 96, 100, + concatCoreMasks(getCoreMask(32, 0, true, false, 0), + getCoreMask(16, 1, true, false, 0)), + std::vector>{ + { std::make_pair((((1ULL << 63) - 1) << 1) | 1, 0)}, + { std::make_pair((1ULL << 32) - 1, 1) } }, + std::vector{ + { std::make_pair((((1ULL << 63) - 1) << 1) | 1, 64)}, + std::make_pair((1ULL << 32) - 1, 32) }, + std::vector{ + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, + 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, + 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 1, 3, 5, + 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, + 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, + 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95, 0, 2, 4, 6 }, + std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 0, 1, 2, 3 }, + std::vector{ + 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18, 20, + 21, 22, 24, 25, 26, 28, 29, 30, 32, 33, 34, 35, 36, 37, 38, 40, 41, + 42, 44, 45, 46, 48, 49, 50, 52, 53, 54, 56, 57, 58, 60, 61, 62, 64, + 64, 65, 65, 66, 66, 67, 68, 68, 69, 70, 70, 71, 72, 72, 73, 74, 74, + 75, 76, 76, 77, 78, 78, 79, 80, 80, 81, 81, 82, 82, 83, 84, 84, 85, + 86, 86, 87, 88, 88, 89, 90, 90, 91, 92, 92, 93, 94, 94, 95 }), + + // Test case 21: HyperThreading Multicache multicore group number of threads + // equal to number of processors + std::make_tuple( + String("Test21"), 96, 96, + concatCoreMasks(getCoreMask(32, 0, true, false, 0), + getCoreMask(16, 1, true, false, 0)), + std::vector>{ + { std::make_pair((((1ULL << 63) - 1) << 1) | 1, 0)}, + { std::make_pair((1ULL << 32) - 1, 1) } }, + std::vector{ + { std::make_pair((((1ULL << 63) - 1) << 1) | 1, 64)}, + std::make_pair((1ULL << 32) - 1, 32) }, + std::vector{ + 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, + 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, + 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 1, 3, 5, + 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, + 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, + 75, 77, 79, 81, 83, 85, 87, 89, 91, 93, 95}, + std::vector{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95}, + std::vector{ + 0 , 1 , 2 , 4 , 5 , 6 , 8 , 9 , 10, 12, 13, 14, 16, 17, 18, 20, 21, + 22, 24, 25, 26, 28, 29, 30, 32, 33, 34, 36, 37, 38, 40, 41, 42, 44, + 45, 46, 48, 49, 50, 52, 53, 54, 56, 57, 58, 60, 61, 62, 64, 64, 65, + 66, 66, 67, 68, 68, 69, 70, 70, 71, 72, 72, 73, 74, 74, 75, 76, 76, + 77, 78, 78, 79, 80, 80, 81, 82, 82, 83, 84, 84, 85, 86, 86, 87, 88, + 88, 89, 90, 90, 91, 92, 92, 93, 94, 94, 95}), + + // Test case 22: HyperThreading Singlecache multicore group number of + // threads less than number of processors + std::make_tuple( + String("Test22"), 32, 30, + concatCoreMasks(getCoreMask(8, 0, true, false, 0), + getCoreMask(8, 1, true, false, 0)), + std::vector>{ + { std::make_pair(0b11111111111111111111111111111111, 0) } }, + std::vector{ std::make_pair(0b1111111111111111, 16), + std::make_pair(0b1111111111111111, 16) }, + std::vector{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, + 20, 22, 24, 26, 28, 30, 1, 3, 5, 7, + 9, 11, 13, 15, 17, 19, 21, 23, 25, 27 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 }), + + // Test case 23: HyperThreading Singlecache multicore group number of + // threads greater than number of processors + std::make_tuple( + String("Test23"), 32, 35, + concatCoreMasks(getCoreMask(8, 0, true, false, 0), + getCoreMask(8, 1, true, false, 0)), + std::vector>{ + { std::make_pair(0b11111111111111111111111111111111, 0) } }, + std::vector{ std::make_pair(0b1111111111111111, 16), + std::make_pair(0b1111111111111111, 16) }, + std::vector{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, + 24, 26, 28, 30, 1, 3, 5, 7, 9, 11, 13, 15, + 17, 19, 21, 23, 25, 27, 29, 31, 0, 2, 4 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 0, 1, 2 }, + std::vector{ 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }), + + // Test case 24: HyperThreading Singlecache multicore group number of + // threads equal to number of processors + std::make_tuple( + String("Test23"), 32, 32, + concatCoreMasks(getCoreMask(8, 0, true, false, 0), + getCoreMask(8, 1, true, false, 0)), + std::vector>{ + { std::make_pair(0b11111111111111111111111111111111, 0) } }, + std::vector{ std::make_pair(0b1111111111111111, 16), + std::make_pair(0b1111111111111111, 16) }, + std::vector{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, + 24, 26, 28, 30, 1, 3, 5, 7, 9, 11, 13, 15, + 17, 19, 21, 23, 25, 27, 29, 31}, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31}, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31}), + + // Test case 25: No HyperThreading multicache uneven distribution single + // coregroup. Number of threads less than number of processors + std::make_tuple( + String("Test25"), 15, 2, + getCoreMask(15, 0, false, false, 0), + std::vector>{ + { std::make_pair(0b1111111111, 0), }, + { std::make_pair(0b111110000000000, 0) } }, + std::vector{ std::make_pair(0b111111111111111, 15) }, + std::vector{ 0, 1 }, + std::vector{ 0, 1 }, + std::vector{ 0, 10 }), + std::make_tuple( + String("Test25b"), 15, 7, + getCoreMask(15, 0, false, false, 0), + std::vector>{ + { std::make_pair(0b1111111111, 0) }, + { std::make_pair(0b111110000000000, 0) } }, + std::vector{ std::make_pair(0b111111111111111, 15) }, + std::vector{ 0, 1, 2, 3, 4, 5, 6 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6 }, + std::vector{ 0, 3, 5, 8, 10, 12, 13 }), + + // Test case 26: No HyperThreading multicache uneven distribution single + // coregroup. Number of threads greater than number of processors + std::make_tuple( + String("Test26"), 15, 18, + getCoreMask(15, 0, false, false, 0), + std::vector>{ + { std::make_pair(0b111111111111, 0), }, + { std::make_pair(0b111000000000000, 0) } }, + std::vector{ std::make_pair(0b111111111111111, 15) }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 1, 2 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 1, 2 }, + std::vector{ 0, 1, 2, 3, 5, 6, 8, 9, 11, 12, 12, 12, 13, 13, 14, 14, 14, 14 }), + + // Test case 27: No HyperThreading multicache uneven distribution single + // coregroup. Number of threads equal to number of processors + std::make_tuple( + String("Test27"), 15, 15, + getCoreMask(15, 0, false, false, 0), + std::vector>{ + { std::make_pair(0b1111111111, 0) }, + { std::make_pair(0b111110000000000, 0) } }, + std::vector{ std::make_pair(0b111111111111111, 15) }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }, + std::vector{ 0, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 12, 13, 13, 14 }), + + // Test case 28: HyperThreading multicache uneven distribution single + // coregroup. Number of threads less than number of processors + std::make_tuple(String("Test28"), 30, 2, + getCoreMask(15, 0, true, false, 0), + std::vector>{ + { std::make_pair(0b1111111111, 0),}, + { std::make_pair(0b111111111111111111110000000000, 0) }, + }, + std::vector{ std::make_pair(0b1111111111111111111111111111111, 30) }, + std::vector{ 0, 2 }, + std::vector{ 0, 1 }, + std::vector{ 0, 10 }), + + // Test case 29: HyperThreading multicache uneven distribution single + // coregroup. Number of threads greater than number of processors + std::make_tuple( + String("Test29"), 30, 32, + getCoreMask(15, 0, true, false, 0), + std::vector>{ + { std::make_pair(0b1111111111, 0), }, + { std::make_pair(0b111111111111111111110000000000, 0) }, + }, + std::vector{ + std::make_pair(0b1111111111111111111111111111111, 30) }, + std::vector{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, + 22, 24, 26, 28, 1, 3, 5, 7, 9, 11, 13, + 15, 17, 19, 21, 23, 25, 27, 29, 0, 2 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 0, 1 }, + std::vector{ 0, 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, + 7, 8, 8, 9, 9, 10, 12, 13, 14, 15, 17, + 18, 19, 20, 22, 23, 24, 25, 27, 28, 29 }), + + // Test case 30: HyperThreading multicache uneven distribution single + // coregroup. Number of threads equal to number of processors + std::make_tuple(String("Test30"), 30, 30, + getCoreMask(15, 0, true, false, 0), + std::vector>{ + { std::make_pair(0b1111111111, 0), }, + { std::make_pair(0b111111111111111111110000000000, 0) }, + }, + std::vector{ + std::make_pair(0b1111111111111111111111111111111, 30) }, + std::vector{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, + 20, 22, 24, 26, 28, 1, 3, 5, 7, 9, + 11, 13, 15, 17, 19, 21, 23, 25, 27, 29 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 }, + std::vector{ 0, 1, 2, 2, 3, 3, 4, 4, 5, 6, + 7, 7, 8, 8, 9, 10, 12, 13, 14, 15, + 17, 18, 19, 20, 22, 23, 24, 25, 27, 28 }), + + + // # ***************Tests targetted for linux systems******************** #/ + // Test case 31: HyperThreading singlecache nonneighbouring siblings and + // total number of cores less than 32. + // Number of threads greater than number of processors + std::make_tuple( + String("Test31"), 12, 15, + std::vector>{ + { std::make_pair(0b1000001, 0), }, + { std::make_pair(0b10000010, 0), }, + { std::make_pair(0b100000100, 0), }, + { std::make_pair(0b1000001000, 0), }, + { std::make_pair(0b10000010000, 0), }, + { std::make_pair(0b100000100000, 0), }, + }, + std::vector>{ + { std::make_pair(0b111111111111, 0) }, + }, + std::vector{ std::make_pair(0b111111111111, 12) }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2 }, + std::vector{ 0, 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 8, 9, 10, 11 }), + + // Test case 31: HyperThreading singlecache nonneighbouring siblings and + // total number of cores less than 32. + // Number of threads less than number of processors + std::make_tuple( + String("Test32"), 12, 10, + std::vector>{ + { std::make_pair(0b1000001, 0), }, + { std::make_pair(0b10000010, 0), }, + { std::make_pair(0b100000100, 0), }, + { std::make_pair(0b1000001000, 0), }, + { std::make_pair(0b10000010000, 0), }, + { std::make_pair(0b100000100000, 0), }, + }, + std::vector>{ + { std::make_pair(0b111111111111, 0) }, + }, + std::vector{ std::make_pair(0b111111111111, 12) }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, + std::vector{ 0, 1, 2, 3, 5, 6, 7, 8, 9, 11 }), + + // Test case 33: HyperThreading singlecache nonneighbouring siblings and + // total number of cores less than 32. + // Number of threads equal to number of processors + std::make_tuple( + String("Test33"), 12, 12, + std::vector>{ + { std::make_pair(0b1000001, 0),}, + { std::make_pair(0b10000010, 0),}, + { std::make_pair(0b100000100, 0),}, + { std::make_pair(0b1000001000, 0),}, + { std::make_pair(0b10000010000, 0),}, + { std::make_pair(0b100000100000, 0),}, + }, + std::vector>{ { std::make_pair(0b111111111111, 0)},}, + std::vector{ std::make_pair(0b111111111111, 12) }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }), + + std::make_tuple( + String("Test34"), 12, 9, + std::vector>{ + { std::make_pair(0b1000001, 0),}, + { std::make_pair(0b10000010, 0),}, + { std::make_pair(0b100000100, 0),}, + { std::make_pair(0b1000001000, 0),}, + { std::make_pair(0b10000010000, 0),}, + { std::make_pair(0b100000100000, 0),}, + }, + std::vector>{ { std::make_pair(0b111111111111, 0)},}, + std::vector{ std::make_pair(0b111111111111, 12) }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8 }, + std::vector{ 0, 1, 2, 3, 5, 6, 8, 9, 11 }), + + std::make_tuple( + String("Test35"), 12, 16, + getCoreMask(6, 0, true, false, 0), + std::vector>{ { std::make_pair(0b111111111111, 0) } }, + std::vector{ std::make_pair(0b11111111111111, 12) }, + std::vector{ 0, 2, 4, 6, 8, 10, 1, 3, 5, 7, 9, 11, 0, 2, 4, 6 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3 }, + std::vector{ 0, 1, 2, 2, 3, 4, 5, 5, 6, 7, 8, 8, 9, 10, 11, 11 }), + /* + * Test case 42 : lib-genoa-09 + * CPU(s): 384 + * On-line CPU(s) list: 0-191 + * Off-line CPU(s) list: 192-383 + * Vendor ID: AuthenticAMD + * Model name: AMD Eng Sample: 100-000000999 + * CPU family: 25 + * Model: 17 + * Thread(s) per core: 1 + * Core(s) per socket: 96 + * Socket(s): 2 + * Stepping: 1 + * Caches (sum of all): + * L1d: 6 MiB (192 instances) + * L1i: 6 MiB (192 instances) + * L2: 192 MiB (192 instances) + * L3: 768 MiB (24 instances) + */ + std::make_tuple( + String("Test38: lib-genoa-09"), 192, 16, + concatCoreMasks( + concatCoreMasks( + concatCoreMasks(getCoreMask(32, 0, false, false, 0), + getCoreMask(32, 1, false, false, 1)), + concatCoreMasks(getCoreMask(32, 0, false, false, 2), + getCoreMask(32, 1, false, false, 3))), + concatCoreMasks(getCoreMask(32, 0, false, false, 4), + getCoreMask(32, 1, false, false, 5))), + std::vector>{ + { std::make_pair(0b00000000000000000000000011111111, 0) }, + { std::make_pair(0b00000000000000001111111100000000, 0) }, + { std::make_pair(0b00000000111111110000000000000000, 0) }, + { std::make_pair(0b11111111000000000000000000000000, 0) }, + { std::make_pair(0b00000000000000000000000011111111, 1) }, + { std::make_pair(0b00000000000000001111111100000000, 1) }, + { std::make_pair(0b00000000111111110000000000000000, 1) }, + { std::make_pair(0b11111111000000000000000000000000, 1) }, + { std::make_pair(0b00000000000000000000000011111111, 2) }, + { std::make_pair(0b00000000000000001111111100000000, 2) }, + { std::make_pair(0b00000000111111110000000000000000, 2) }, + { std::make_pair(0b11111111000000000000000000000000, 2) }, + { std::make_pair(0b00000000000000000000000011111111, 3) }, + { std::make_pair(0b00000000000000001111111100000000, 3) }, + { std::make_pair(0b00000000111111110000000000000000, 3) }, + { std::make_pair(0b11111111000000000000000000000000, 3) }, + { std::make_pair(0b00000000000000000000000011111111, 4) }, + { std::make_pair(0b00000000000000001111111100000000, 4) }, + { std::make_pair(0b00000000111111110000000000000000, 4) }, + { std::make_pair(0b11111111000000000000000000000000, 4) }, + { std::make_pair(0b00000000000000000000000011111111, 5) }, + { std::make_pair(0b00000000000000001111111100000000, 5) }, + { std::make_pair(0b00000000111111110000000000000000, 5) }, + { std::make_pair(0b11111111000000000000000000000000, 5) }, + }, + std::vector{ + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + std::vector{ 0, 16, 24, 40, 48, 64, 72, 88, 96, 112, 120, 136, 144, 160, 168, 184 }), + std::make_tuple( + String("Test43: lib-genoa-09-tweak-cachegroups"), 192, 16, + concatCoreMasks( + concatCoreMasks( + concatCoreMasks(getCoreMask(32, 0, false, false, 0), + getCoreMask(32, 1, false, false, 1)), + concatCoreMasks(getCoreMask(32, 0, false, false, 2), + getCoreMask(32, 1, false, false, 3))), + concatCoreMasks(getCoreMask(32, 0, false, false, 4), + getCoreMask(32, 1, false, false, 5))), + std::vector>{ + { std::make_pair(0b00000000000000000000000011111111, 0), + std::make_pair(0b00000000000000000000000011111111, 3) }, + { std::make_pair(0b00000000000000001111111100000000, 0), + std::make_pair(0b00000000000000001111111100000000, 3) }, + { std::make_pair(0b00000000111111110000000000000000, 0), + std::make_pair(0b00000000111111110000000000000000, 3) }, + { std::make_pair(0b11111111000000000000000000000000, 0), + std::make_pair(0b11111111000000000000000000000000, 3) }, + { std::make_pair(0b00000000000000000000000011111111, 1), + std::make_pair(0b00000000000000000000000011111111, 4) }, + { std::make_pair(0b00000000000000001111111100000000, 1), + std::make_pair(0b00000000000000001111111100000000, 4) }, + { std::make_pair(0b00000000111111110000000000000000, 1), + std::make_pair(0b00000000111111110000000000000000, 4) }, + { std::make_pair(0b11111111000000000000000000000000, 1), + std::make_pair(0b11111111000000000000000000000000, 4) }, + { std::make_pair(0b00000000000000000000000011111111, 2), + std::make_pair(0b00000000000000000000000011111111, 5) }, + { std::make_pair(0b00000000000000001111111100000000, 2), + std::make_pair(0b00000000000000001111111100000000, 5) }, + { std::make_pair(0b00000000111111110000000000000000, 2), + std::make_pair(0b00000000111111110000000000000000, 5) }, + { std::make_pair(0b11111111000000000000000000000000, 2), + std::make_pair(0b11111111000000000000000000000000, 5) }, + }, + std::vector{ + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + std::vector{ 0, 8, 16, 112, 24, 32, 40, 136, 48, 56, 64, 160, 72, 80, 88, 184 }), + std::make_tuple( + String("Test44: lib-genoa-10"), 512, 16, + concatCoreMasks( + concatCoreMasks( + concatCoreMasks(getCoreMask(16, 0, true, true, 8), + getCoreMask(16, 1, true, true, 8) + ), + concatCoreMasks(getCoreMask(16, 2, true, true, 8), + getCoreMask(16, 3, true, true, 8) + ) + ), + concatCoreMasks( + concatCoreMasks(getCoreMask(16, 4, true, true, 8), + getCoreMask(16, 5, true, true, 8) + ), + concatCoreMasks(getCoreMask(16, 6, true, true, 8), + getCoreMask(16, 7, true, true, 8) + ) + ) + ), + std::vector>{ + { + std::make_pair(0b00000000000000000000000011111111, 0), + std::make_pair(0b00000000000000000000000011111111, 8), + }, + { + std::make_pair(0b00000000000000001111111100000000, 0), + std::make_pair(0b00000000000000001111111100000000, 8), + }, + { + std::make_pair(0b00000000111111110000000000000000, 0), + std::make_pair(0b00000000111111110000000000000000, 8), + }, + { + std::make_pair(0b11111111000000000000000000000000, 0), + std::make_pair(0b11111111000000000000000000000000, 8), + }, + { + std::make_pair(0b00000000000000000000000011111111, 1), + std::make_pair(0b00000000000000000000000011111111, 9), + }, + { + std::make_pair(0b00000000000000001111111100000000, 1), + std::make_pair(0b00000000000000001111111100000000, 9), + }, + { + std::make_pair(0b00000000111111110000000000000000, 1), + std::make_pair(0b00000000111111110000000000000000, 9), + }, + { + std::make_pair(0b11111111000000000000000000000000, 1), + std::make_pair(0b11111111000000000000000000000000, 9), + }, + { + std::make_pair(0b00000000000000000000000011111111, 2), + std::make_pair(0b00000000000000000000000011111111, 10), + }, + { + std::make_pair(0b00000000000000001111111100000000, 2), + std::make_pair(0b00000000000000001111111100000000, 10), + }, + { + std::make_pair(0b00000000111111110000000000000000, 2), + std::make_pair(0b00000000111111110000000000000000, 10), + }, + { + std::make_pair(0b11111111000000000000000000000000, 2), + std::make_pair(0b11111111000000000000000000000000, 10), + }, + { + std::make_pair(0b00000000000000000000000011111111, 3), + std::make_pair(0b00000000000000000000000011111111, 11), + }, + { + std::make_pair(0b00000000000000001111111100000000, 3), + std::make_pair(0b00000000000000001111111100000000, 11), + }, + { + std::make_pair(0b00000000111111110000000000000000, 3), + std::make_pair(0b00000000111111110000000000000000, 11), + }, + { + std::make_pair(0b11111111000000000000000000000000, 3), + std::make_pair(0b11111111000000000000000000000000, 11), + }, + { + std::make_pair(0b00000000000000000000000011111111, 4), + std::make_pair(0b00000000000000000000000011111111, 12), + }, + { + std::make_pair(0b00000000000000001111111100000000, 4), + std::make_pair(0b00000000000000001111111100000000, 12), + }, + { + std::make_pair(0b00000000111111110000000000000000, 4), + std::make_pair(0b00000000111111110000000000000000, 12), + }, + { + std::make_pair(0b11111111000000000000000000000000, 4), + std::make_pair(0b11111111000000000000000000000000, 12), + }, + { + std::make_pair(0b00000000000000000000000011111111, 5), + std::make_pair(0b00000000000000000000000011111111, 13), + }, + { + std::make_pair(0b00000000000000001111111100000000, 5), + std::make_pair(0b00000000000000001111111100000000, 13), + }, + { + std::make_pair(0b00000000111111110000000000000000, 5), + std::make_pair(0b00000000111111110000000000000000, 13), + }, + { + std::make_pair(0b11111111000000000000000000000000, 5), + std::make_pair(0b11111111000000000000000000000000, 13), + }, + { + std::make_pair(0b00000000000000000000000011111111, 6), + std::make_pair(0b00000000000000000000000011111111, 14), + }, + { + std::make_pair(0b00000000000000001111111100000000, 6), + std::make_pair(0b00000000000000001111111100000000, 14), + }, + { + std::make_pair(0b00000000111111110000000000000000, 6), + std::make_pair(0b00000000111111110000000000000000, 14), + }, + { + std::make_pair(0b11111111000000000000000000000000, 6), + std::make_pair(0b11111111000000000000000000000000, 14), + }, + { + std::make_pair(0b00000000000000000000000011111111, 7), + std::make_pair(0b00000000000000000000000011111111, 15), + }, + { + std::make_pair(0b00000000000000001111111100000000, 7), + std::make_pair(0b00000000000000001111111100000000, 15), + }, + { + std::make_pair(0b00000000111111110000000000000000, 7), + std::make_pair(0b00000000111111110000000000000000, 15), + }, + { + std::make_pair(0b11111111000000000000000000000000, 7), + std::make_pair(0b11111111000000000000000000000000, 15), + }, + }, + std::vector{ + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + std::make_pair(0b11111111111111111111111111111111, 32), + }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + std::vector{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + std::vector{ 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224,240 }), +}; +// clang-format on +} // namespace diff --git a/Library/Tests/ThreadPinning/ThreadPinningCapiTest.cc b/Library/Tests/ThreadPinning/ThreadPinningCapiTest.cc new file mode 100644 index 0000000..8e583e9 --- /dev/null +++ b/Library/Tests/ThreadPinning/ThreadPinningCapiTest.cc @@ -0,0 +1,139 @@ + +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Capi/au/threadpinning.h" +#include "ThreadPinningTest.hh" +namespace { + +TEST_F(PinThreadsTest, capiVerifySpread) +{ + // Test spread strategy + strategy = pinStrategy::SPREAD; + pthread_t* threadList = &thread_ids[0]; + au_pin_threads_spread(threadList, thread_ids.size()); + EXPECT_TRUE(VerifyAffinity()); +} + +TEST_F(PinThreadsTest, capiVerifyCore) +{ + // Test core strategy + strategy = pinStrategy::CORE; + pthread_t* threadList = &thread_ids[0]; + au_pin_threads_core(threadList, thread_ids.size()); + EXPECT_TRUE(VerifyAffinity()); +} + +TEST_F(PinThreadsTest, capiVerifyLogical) +{ + // Test logical strategy + strategy = pinStrategy::LOGICAL; + pthread_t* threadList = &thread_ids[0]; + au_pin_threads_logical(threadList, thread_ids.size()); + EXPECT_TRUE(VerifyAffinity()); +} + +TEST_F(PinThreadsTest, capiVerifyCustom) +{ + // Test custom strategy + pthread_t* threadList = &thread_ids[0]; + std::vector affinityVector{}; + + // initilize the affinity vector with random numbers less than hardware + // concurrency + for (int i = 0; i < num_threads; i++) { + affinityVector.push_back(rand() + % (std::thread::hardware_concurrency() - 1)); + } + au_pin_threads_custom(threadList, + thread_ids.size(), + &affinityVector[0], + affinityVector.size()); + EXPECT_TRUE(VerifyAffinity(affinityVector)); +} + +#if AU_ENABLE_ASSERTS == 1 +// Negative test case +TEST_F(PinThreadsNegativeTest, capiVerifyInvalidcorenumber) +{ + // Test custom strategy + pthread_t* threadList = &thread_ids[0]; + std::vector affinityVector(thread_ids.size(), + std::thread::hardware_concurrency() + 1); + + EXPECT_ANY_THROW(au_pin_threads_custom(threadList, + thread_ids.size(), + &affinityVector[0], + affinityVector.size())); +} + +TEST_F(PinThreadsNegativeTest, capiVerifyNullThreadList) +{ + // Test custom strategy + pthread_t* threadList = nullptr; + std::vector affinityVector{}; + + // initilize the affinity vector with random numbers less than hardware + // concurrency + for (int i = 0; i < num_threads; i++) { + affinityVector.push_back(rand() + % (std::thread::hardware_concurrency() - 1)); + } + EXPECT_ANY_THROW(au_pin_threads_custom(threadList, + thread_ids.size(), + &affinityVector[0], + affinityVector.size())); +} +// Null affinity vector +TEST_F(PinThreadsNegativeTest, capiVerifyNullAffintyVector) +{ + // Test custom strategy + pthread_t* threadList = &thread_ids[0]; + EXPECT_ANY_THROW( + au_pin_threads_custom(threadList, thread_ids.size(), nullptr, 0)); +} +// unequally sized thread list and affinity vector +TEST_F(PinThreadsNegativeTest, capiVerifyInvalidAffinityVector) +{ + // Test custom strategy + pthread_t* threadList = &thread_ids[0]; + std::vector affinityVector{}; + + // initilize the affinity vector with random numbers less than hardware + // concurrency + for (int i = 0; i < num_threads; i++) { + affinityVector.push_back(rand() + % (std::thread::hardware_concurrency() - 1)); + } + EXPECT_ANY_THROW(au_pin_threads_custom(threadList, + thread_ids.size(), + &affinityVector[0], + affinityVector.size() - 1)); +} +#endif +} // namespace diff --git a/Library/Tests/ThreadPinning/ThreadPinningMockTest.cc b/Library/Tests/ThreadPinning/ThreadPinningMockTest.cc new file mode 100644 index 0000000..1fa2032 --- /dev/null +++ b/Library/Tests/ThreadPinning/ThreadPinningMockTest.cc @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "MockTest.hh" +#include + +namespace { + +using namespace Au; +class MockCpuTopology : public CpuTopology +{ + public: + MockCpuTopology(){}; + + void setActiveProcessors(int num) { active_processors = num; } + void setPMap(std::vector>> pMap) + { + processorMap = pMap; + } + void setCMap(std::vector>> cMap) + { + cacheMap = cMap; + } + void setGMap(std::vector> gMap) + { + groupMap = gMap; + } +}; + +INSTANTIATE_TEST_SUITE_P( + ThreadPinningTests, + ThreadPinningTest, + ::testing::ValuesIn(std::move(testParametersCpuTopology))); + +TEST_P(ThreadPinningTest, affinityVectorTest) +{ + std::vector>> pMap, cMap; + std::vector> gMap; + std::vector coreResult, LogicalResult, SpreadResult; + int activeProcessors, numberofThreads; + String name; + std::ofstream logFile; + + std::tie(name, + activeProcessors, + numberofThreads, + pMap, + cMap, + gMap, + coreResult, + LogicalResult, + SpreadResult) = GetParam(); + MockCpuTopology mockCT; + mockCT.setActiveProcessors(activeProcessors); + mockCT.setPMap(pMap); + mockCT.setCMap(cMap); + mockCT.setGMap(gMap); + + auto av = AffinityVector(mockCT); + std::vector processPinGroup(numberofThreads); + processPinGroup.reserve(numberofThreads); + std::cout << "Thread Pinning for " << name << std::endl; + // write to log file + logFile.open("ThreadPinningMockTest.log", std::ios::app); + logFile << "Thread Pinning for " << name << std::endl; + logFile << "Topology : " << std::endl; + logFile << "Active Processors : " << activeProcessors << std::endl; + logFile << "Number of Threads : " << numberofThreads << std::endl; + logFile << "Processor Map : " << std::endl; + for (long unsigned int i = 0; i < pMap.size(); i++) { + logFile << "Processor " << i << " : "; + for (long unsigned j = 0; j < pMap[i].size(); j++) { + logFile << pMap[i][j].first << "<--------->" << pMap[i][j].second + << " "; + } + logFile << std::endl; + } + for (long unsigned int i = 0; i < cMap.size(); i++) { + logFile << "Cache " << i << " : "; + for (long unsigned int j = 0; j < cMap[i].size(); j++) { + logFile << cMap[i][j].first << "<--------->" << cMap[i][j].second + << " "; + } + logFile << std::endl; + } + for (long unsigned int i = 0; i < gMap.size(); i++) { + logFile << "Group " << i << " : "; + logFile << gMap[i].first << "'<---------->" << gMap[i].second + << std::endl; + } + + logFile << "Core :" << std::endl; + std::cout << "Core :" << std::endl; + av.getAffinityVector(processPinGroup, 1); // core + for (int i = 0; i < numberofThreads; i++) { + logFile << processPinGroup[i] << "<--------->" << coreResult[i] + << std::endl; + } + logFile << std::endl; + EXPECT_EQ(processPinGroup, coreResult); + std::cout << " Pass" << std::endl; + logFile << " Pass" << std::endl; + logFile << "Logical :" << std::endl; + std::cout << "Logical :"; + av.getAffinityVector(processPinGroup, 2); // Logical + EXPECT_EQ(processPinGroup, LogicalResult); + for (int i = 0; i < numberofThreads; i++) { + logFile << processPinGroup[i] << "<--------->" << LogicalResult[i] + << std::endl; + } + logFile << std::endl; + std::cout << " Pass" << std::endl; + logFile << " Pass" << std::endl; + + std::cout << "Spread :"; + logFile << "Spread :" << std::endl; + av.getAffinityVector(processPinGroup, 0); // Spread + for (int i = 0; i < numberofThreads; i++) { + logFile << processPinGroup[i] << "<--------->" << SpreadResult[i] + << std ::endl; + } + logFile << std::endl; + std::cout << " Pass" << std::endl; + logFile << " Pass" << std::endl; + EXPECT_EQ(processPinGroup, SpreadResult); +} + +} // namespace diff --git a/Library/Tests/ThreadPinning/ThreadPinningTest.cc b/Library/Tests/ThreadPinning/ThreadPinningTest.cc new file mode 100644 index 0000000..156b29e --- /dev/null +++ b/Library/Tests/ThreadPinning/ThreadPinningTest.cc @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "ThreadPinningTest.hh" +namespace { + +TEST_F(PinThreadsTest, verifySpread) +{ + // Test spread strategy + strategy = pinStrategy::SPREAD; + verifyStrategy(); +} + +TEST_F(PinThreadsTest, verifyCore) +{ + // Test core strategy + strategy = pinStrategy::CORE; + verifyStrategy(); +} + +TEST_F(PinThreadsTest, verifyLogical) +{ + // Test logical strategy + strategy = pinStrategy::LOGICAL; + verifyStrategy(); +} +TEST_F(PinThreadsTest, verifyCustom) +{ + // Test custom strategy + std::vector AffinityVector{}; + verifyStrategy(AffinityVector); +} +#if AU_ENABLE_ASSERTIONS == 1 +TEST_F(PinThreadsNegativeTest, verifyInvalidStrategy) +{ + // Test invalid strategy + int strategy = 5; + EXPECT_ANY_THROW(tp.pinThreads(thread_ids, strategy)); +} + +TEST_F(PinThreadsNegativeTest, verifyInvalidAffinity) +{ + // Test invalid affinity + std::vector AffinityVector(thread_ids.size(), + std::thread::hardware_concurrency() + 1); + EXPECT_ANY_THROW(tp.pinThreads(thread_ids, AffinityVector)); +} + +TEST_F(PinThreadsNegativeTest, verifyInvalidAffinitySize) +{ + // Test invalid affinity size + std::vector AffinityVector = { 0, 1, 2, 3, 4 }; + EXPECT_ANY_THROW(tp.pinThreads(thread_ids, AffinityVector)); +} + +TEST_F(PinThreadsNegativeTest, verifyNullAffinity) +{ + // Test null affinity + std::vector AffinityVector; + EXPECT_ANY_THROW(tp.pinThreads(thread_ids, AffinityVector)); +} + +TEST_F(PinThreadsNegativeTest, verifyNullThreadList) +{ + // Test null thread list + std::vector thread_ids; + EXPECT_ANY_THROW(tp.pinThreads(thread_ids, strategy)); +} +#endif +} // namespace diff --git a/Library/Tests/ThreadPinning/ThreadPinningTest.hh b/Library/Tests/ThreadPinning/ThreadPinningTest.hh new file mode 100644 index 0000000..a57de6d --- /dev/null +++ b/Library/Tests/ThreadPinning/ThreadPinningTest.hh @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#include "Au/ThreadPinning.hh" +#include "Au/ThreadPinning/ThreadPinning.hh" +#include // for CHAR_BIT +#include +#include +#include +#include +#ifdef _WIN32 +#include +#else +#include +#include +#endif +namespace { +using namespace Au; + +// Test fixture class +class PinThreadsTest : public ::testing::Test +{ + public: + PinThreadsTest() + : thread_ids() + , tp() + , num_threads(0) + , strategy(pinStrategy::SPREAD) + , threads(){}; + + std::vector thread_ids; + ThreadPinning tp; + + protected: + int num_threads; + pinStrategy strategy; + std::vector threads; + + protected: + /** + * @brief SetUp + * + * @details Set up the test fixture by creating threads for the + * test + * + * @param void + * + * @return void + */ + void SetUp() override + { + + num_threads = std::thread::hardware_concurrency() + + rand() % (std::thread::hardware_concurrency() - 1); + createThreads(); + for (int i = 0; i < num_threads; ++i) { + pthread_t handle = threads[i].native_handle(); + thread_ids.push_back(handle); + } + } + + /** + * @brief TearDown + * + * @details Tear down the test fixture by joining the threads + * + * @param void + * + * @return void + */ + void TearDown() override + { + for (auto& thread : threads) { + if (thread.joinable()) { + thread.join(); + } + } + } + + private: + /** + * @brief printThreadId + * + * @details Thread function + * + * @return void + */ + void printThreadId() + { + std::this_thread::sleep_for( + std::chrono::milliseconds(num_threads * 10)); + } + + /** + * @brief createThreads + * + * @details Create threads. + * + * @param void + * + * @return void + */ + void createThreads() + { + for (int i = 0; i < num_threads; ++i) { + threads.push_back( + std::thread(&PinThreadsTest::printThreadId, this)); + } + } + + /** + * @brief getCoreAffinity + * + * @details Get the core affinity of the thread + * + * @param threadHandle + * + * @return int + */ +#ifdef _WIN32 + int getCoreAffinity(HANDLE threadHandle) + { + GROUP_AFFINITY groupAffinity; + BOOL result = GetThreadGroupAffinity(threadHandle, &groupAffinity); + if (!result) { + std::cerr << "Error reading thread affinity for thread " + << std::endl; + } else { + for (size_t core = 0; core < sizeof(groupAffinity.Mask) * CHAR_BIT; + ++core) { + if (groupAffinity.Mask & (1ULL << core)) { + int offset = 0; + for (int i = 0; i < groupAffinity.Group; ++i) { + offset = offset + CpuTopology::get().groupMap[i].second; + } + return core + offset; + } + } + } + return -1; + } +#else + int getCoreAffinity(pthread_t threadHandle) + { + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + pthread_getaffinity_np(threadHandle, sizeof(cpu_set_t), &cpuset); + + for (int core = 0; core < CPU_SETSIZE; ++core) { + if (CPU_ISSET(core, &cpuset)) { + return core; + } + } + return -1; + } +#endif + public: + /** + * @brief VerifyAffinity + * + * @details Verify the core affinity of each thread matches the + * expected core + * + * @param affinityVector + * + * @return bool + */ + bool VerifyAffinity(std::vector affinityVector) + { + + for (int i = 0; i < num_threads; ++i) { + int expectedCore = affinityVector[i]; + int actualCore = getCoreAffinity(thread_ids[i]); + if (expectedCore != actualCore) + return false; + } + return true; + } + + /** + * @brief VerifyAffinity + * + * @details Verify the core affinity of each thread matches the + * expected core + * + * @return bool + */ + bool VerifyAffinity() + { + + AffinityVector av; + auto ret = true; + std::vector affinityVector(num_threads); + av.getAffinityVector(affinityVector, strategy); + + for (int i = 0; i < num_threads; ++i) { + int expectedCore = affinityVector[i]; + int actualCore = getCoreAffinity(thread_ids[i]); + if (expectedCore != actualCore) { + ret = false; + break; + } + } + auto Info = CpuTopology::get(); + std::ofstream logFile; + logFile.open("ThreadPinningTest.log", std::ios::app); + logFile << "Strategy : " << strategy << std::endl; + logFile << "Topology : " << std::endl; + logFile << "Active Processors : " << Info.active_processors + << std::endl; + logFile << "Number of Threads : " << num_threads << std::endl; + logFile << "Processor Map : " << std::endl; + for (long unsigned int i = 0; i < Info.processorMap.size(); i++) { + logFile << "Processor " << i << " : "; + for (long unsigned j = 0; j < Info.processorMap[i].size(); j++) { + logFile << Info.processorMap[i][j].first << "<--------->" + << Info.processorMap[i][j].second << " "; + } + logFile << std::endl; + } + for (long unsigned int i = 0; i < Info.cacheMap.size(); i++) { + logFile << "Cache " << i << " : "; + for (long unsigned int j = 0; j < Info.cacheMap[i].size(); j++) { + logFile << Info.cacheMap[i][j].first << "<--------->" + << Info.cacheMap[i][j].second << " "; + } + logFile << std::endl; + } + for (long unsigned int i = 0; i < Info.groupMap.size(); i++) { + logFile << "Group " << i << " : "; + logFile << Info.groupMap[i].first << "'<---------->" + << Info.groupMap[i].second << std::endl; + } + for (int i = 0; i < num_threads; i++) { + logFile << "Thread " << i << " : "; + int expectedCore = affinityVector[i]; + int actualCore = getCoreAffinity(thread_ids[i]); + logFile << "Expected Core : " << expectedCore << " "; + logFile << "Actual Core : " << actualCore << std::endl; + } + return ret; + } + + /** + * @brief verifyStrategy + * + * @details Verify the pinning strategy + * + * @param void + * + * @return void + */ + void verifyStrategy() + { + // with number of threads more than hardware concurrency + tp.pinThreads(thread_ids, strategy); + EXPECT_TRUE(VerifyAffinity()); + + // with number of threads equal to hardware concurrency + num_threads = std::thread::hardware_concurrency(); + std::vector threadIds1(thread_ids.begin(), + thread_ids.begin() + num_threads); + tp.pinThreads(threadIds1, strategy); + EXPECT_TRUE(VerifyAffinity()); + + // with number of threads less than hardware concurrency + num_threads = std::thread::hardware_concurrency() + - (rand() % std::thread::hardware_concurrency() - 1); + std::vector threadIds2(thread_ids.begin(), + thread_ids.begin() + num_threads); + tp.pinThreads(threadIds2, strategy); + EXPECT_TRUE(VerifyAffinity()); + } + + /** + * @brief verifyStrategy + * + * @details Verify the pinning strategy + * + * @param affinityVector + * + * @return void + */ + void verifyStrategy(std::vector& affinityVector) + { + // initilize the affinity vector with random numbers less than hardware + // concurrency + for (int i = 0; i < num_threads; i++) { + affinityVector.push_back( + rand() % (std::thread::hardware_concurrency() - 1)); + } + // with number of threads more than hardware concurrency + tp.pinThreads(thread_ids, affinityVector); + EXPECT_TRUE(VerifyAffinity(affinityVector)); + + // with number of threads equal to hardware concurrency + num_threads = std::thread::hardware_concurrency(); + affinityVector.clear(); + for (int i = 0; i < num_threads; i++) { + affinityVector.push_back( + rand() % (std::thread::hardware_concurrency() - 1)); + } + std::vector threadIds1(thread_ids.begin(), + thread_ids.begin() + num_threads); + tp.pinThreads(threadIds1, affinityVector); + EXPECT_TRUE(VerifyAffinity(affinityVector)); + + // with number of threads less than hardware concurrency + num_threads = std::thread::hardware_concurrency() + - (rand() % std::thread::hardware_concurrency() - 1); + affinityVector.clear(); + for (int i = 0; i < num_threads; i++) { + affinityVector.push_back( + rand() % (std::thread::hardware_concurrency() - 1)); + } + std::vector threadIds2(thread_ids.begin(), + thread_ids.begin() + num_threads); + tp.pinThreads(threadIds2, affinityVector); + EXPECT_TRUE(VerifyAffinity(affinityVector)); + } +}; + +class PinThreadsNegativeTest : public PinThreadsTest +{ + public: + PinThreadsNegativeTest() + : PinThreadsTest() + { + } +}; + +} // namespace diff --git a/Library/Tests/ThreadPinning/ThreadPinningUnitTestPlan.md b/Library/Tests/ThreadPinning/ThreadPinningUnitTestPlan.md new file mode 100644 index 0000000..b2a93b4 --- /dev/null +++ b/Library/Tests/ThreadPinning/ThreadPinningUnitTestPlan.md @@ -0,0 +1,137 @@ +# The Threadpinning module testplan + +## The thread pinning module + +The thread pinning module provides an interface that can facilitate pinning threads to cores based on the pinning strategy requested. + +## The objective + +To have a compreshensive test coverage for the threadpinning API + +## Classes of testcases + +* **mock Tests** +* **native tests** + +## APIs tested + +``` bash +* ThreadPinning::pinThreads() -- Cpp API -- External API +* Affinity::getAffinityVector() -- Cpp API -- Internal Using mock tests +* au_pin_threads_core() -- C API -- External API +* au_pin_threads_logical() -- C API -- External API +* au_pin_threads_spread() -- C API -- External API +* au_pin_threads_custom() -- C API -- External API +``` + +## The test matrix for the threadpinning module mock tests + +combinations of 5 variables are tested. They are: + +* **Number of threads** +* **Number of cores** +* **Pinning strategy** +* **Hyperthreading** +* **Cache sharing** + +The below tests tests getAffinityVector() API which is an internal API by creating a mock environment described by each entry in the test matrix. +and verifies that the affinity vector returned is as expected. + +| ID | No. of core groups | Hyperthreading | Cache groups | No of threads | Pinning strategy | +|----|--------------------|----------------|--------------|---------------|------------------| +| 1 | 1 | NO HT | 1 | > no of cores | core | +| 2 | 1 | NO HT | 1 | > no of cores | Logical | +| 3 | 1 | NO HT | 1 | > no of cores | Spread | +| 4 | 1 | NO HT | 1 | < no of cores | core | +| 5 | 1 | NO HT | 1 | < no of cores | Logical | +| 6 | 1 | NO HT | 1 | < no of cores | Spread | +| 7 | 1 | NO HT | 1 | = no of cores | core | +| 8 | 1 | NO HT | 1 | = no of cores | Logical | +| 9 | 1 | NO HT | 1 | = no of cores | Spread | +| 10 | 1 | NO HT | Multi | > no of cores | core | +| 11 | 1 | NO HT | Multi | > no of cores | Logical | +| 12 | 1 | NO HT | Multi | > no of cores | Spread | +| 13 | 1 | NO HT | Multi | < no of cores | core | +| 14 | 1 | NO HT | Multi | < no of cores | Logical | +| 15 | 1 | NO HT | Multi | < no of cores | Spread | +| 16 | 1 | NO HT | Multi | = no of cores | core | +| 17 | 1 | NO HT | Multi | = no of cores | Logical | +| 18 | 1 | NO HT | Multi | = no of cores | Spread | +| 19 | 1 | HT | 1 | > no of cores | core | +| 20 | 1 | HT | 1 | > no of cores | Logical | +| 21 | 1 | HT | 1 | > no of cores | Spread | +| 22 | 1 | HT | 1 | < no of cores | core | +| 23 | 1 | HT | 1 | < no of cores | Logical | +| 24 | 1 | HT | 1 | < no of cores | Spread | +| 25 | 1 | HT | 1 | = no of cores | core | +| 26 | 1 | HT | 1 | = no of cores | Logical | +| 27 | 1 | HT | 1 | = no of cores | Spread | +| 28 | 1 | HT | Multi | > no of cores | core | +| 29 | 1 | HT | Multi | > no of cores | Logical | +| 30 | 1 | HT | 2 | > no of cores | Spread | +| 31 | 1 | HT | Multi | < no of cores | core | +| 32 | 1 | HT | Multi | < no of cores | Logical | +| 33 | 1 | HT | Multi | < no of cores | Spread | +| 34 | 1 | HT | Multi | = no of cores | core | +| 35 | 1 | HT | Multi | = no of cores | Logical | +| 36 | 1 | HT | Multi | = no of cores | Spread | +| 37 | Multi | NO HT | 1 | > no of cores | core | +| 38 | Multi | NO HT | 1 | > no of cores | Logical | +| 39 | Multi | NO HT | 1 | > no of cores | Spread | +| 40 | Multi | NO HT | 1 | < no of cores | core | +| 41 | Multi | NO HT | 1 | < no of cores | Logical | +| 42 | Multi | NO HT | 1 | < no of cores | Spread | +| 43 | Multi | NO HT | 1 | = no of cores | core | +| 44 | Multi | NO HT | 1 | = no of cores | Logical | +| 45 | Multi | NO HT | 1 | = no of cores | Spread | +| 46 | Multi | NO HT | Multi | > no of cores | core | +| 47 | Multi | NO HT | Multi | > no of cores | Logical | +| 48 | Multi | NO HT | Multi | > no of cores | Spread | +| 49 | Multi | NO HT | Multi | < no of cores | core | +| 50 | Multi | NO HT | Multi | < no of cores | Logical | +| 51 | Multi | NO HT | Multi | < no of cores | Spread | +| 52 | Multi | NO HT | Multi | = no of cores | core | +| 53 | Multi | NO HT | Multi | = no of cores | Logical | +| 54 | Multi | NO HT | Multi | = no of cores | Spread | +| 55 | Multi | HT | 1 | > no of cores | core | +| 56 | Multi | HT | 1 | > no of cores | Logical | +| 57 | Multi | HT | 1 | > no of cores | Spread | +| 58 | Multi | HT | 1 | < no of cores | core | +| 59 | Multi | HT | 1 | < no of cores | Logical | +| 60 | Multi | HT | 1 | < no of cores | Spread | +| 61 | Multi | HT | 1 | = no of cores | core | +| 62 | Multi | HT | 1 | = no of cores | Logical | +| 63 | Multi | HT | 1 | = no of cores | Spread | +| 64 | Multi | HT | Multi | > no of cores | core | +| 65 | Multi | HT | Multi | > no of cores | Logical | +| 66 | Multi | HT | Multi | > no of cores | Spread | +| 67 | Multi | HT | Multi | < no of cores | core | +| 68 | Multi | HT | Multi | < no of cores | Logical | +| 69 | Multi | HT | Multi | < no of cores | Spread | +| 70 | Multi | HT | Multi | = no of cores | core | +| 71 | Multi | HT | Multi | = no of cores | Logical | +| 72 | Multi | HT | Multi | = no of cores | Spread | + +## The test matrix for the threadpinning module native tests + +Native tests are run on the actual hardware. The test matrix is as follows: +Verifies that the thread pinning is done correctly on the actual hardware. +by checking the affinity of the threads to the cores. +Variables testsed are: + +* **Number of threads** +* **Pinning strategy** + +| ID | No of threads | Pinning strategy | +| ---|----------------|------------------| +| 1 | > no of cores | core | +| 2 | > no of cores | Logical | +| 3 | > no of cores | Spread | +| 4 | < no of cores | core | +| 5 | < no of cores | Logical | +| 6 | < no of cores | Spread | +| 7 | = no of cores | core | +| 8 | = no of cores | Logical | +| 9 | = no of cores | Spread | + +Similar tests are provided for individual capis. diff --git a/Library/Tests/copyrightcheck.py b/Library/Tests/copyrightcheck.py new file mode 100644 index 0000000..0783212 --- /dev/null +++ b/Library/Tests/copyrightcheck.py @@ -0,0 +1,75 @@ +#!/bin/python3.11 +""" + Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +""" +import os +import re +import sys + +def get_files(): + # execute command + # git diff --cached --name-only + # store the output + + cmd = "git diff --cached --name-only | sort -u" + files = os.popen(cmd).read() + return files + +def get_notice(file): + # open the file and read the first 5 lines + # if the line contains the word "Copyright" + # return the line + with open(file, 'r') as f: + for i in range(5): + line = f.readline() + if "Copyright" in line: + return line + return None + +def scan_files(files): + # for each file in the list + # check if it has a notice and the year 2024 + # if not, print the file name + found = False; + for file in files.split('\n'): + if os.path.isfile(file): + notice = get_notice(file) + if notice is None: + print(file) + found = True; + print("doesnot contain a notice"); + elif "2024" not in notice: + print(file) + found = True; + print("doesnot contain the modified year"); + return found + +def main(): + ret = scan_files(get_files()) + sys.exit(ret) + +if __name__ == "__main__": + main() diff --git a/Library/config.h.in b/Library/config.h.in new file mode 100644 index 0000000..afbf4b4 --- /dev/null +++ b/Library/config.h.in @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef _AU_CONFIG_H_INCLUDED +#define _AU_CONFIG_H_INCLUDED 2 + +// clang-format off + +#cmakedefine AU_CONFIG_LITTLE_ENDIAN + +// CPU Identification +#cmakedefine AU_ENABLE_AOCL_CPUID + +// AOCL Foundations Release Version +#cmakedefine AU_PACKAGE_VERSION "@AU_PACKAGE_VERSION@" +#cmakedefine AU_PACKAGE_SUFFIX "@AU_VERSION_PRERELEASE@" + +// AOCL Foundation Build type +#cmakedefine01 AU_BUILD_TYPE_RELEASE +#cmakedefine01 AU_BUILD_TYPE_DEBUG +#cmakedefine01 AU_BUILD_TYPE_DEVELOPER +#cmakedefine01 AU_CPU_ARCH_X86 + +// Compiler detection + +#cmakedefine AU_COMPILER_IS_GNU @AU_COMPILER_IS_GNU@ +#cmakedefine AU_COMPILER_IS_CLANG @AU_COMPILER_IS_CLANG@ +#cmakedefine AU_COMPILER_IS_MSVC @AU_COMPILER_IS_MSVC@ + +#cmakedefine AU_TARGET_OS_IS_LINUX +#cmakedefine AU_TARGET_OS_IS_WINDOWS + +#cmakedefine AU_TARGET_ENDIAN_BIG +#cmakedefine AU_TARGET_ENDIAN_LITTLE + +#cmakedefine AU_WARN_DEPRECATION +// enable assertion +#cmakedefine01 AU_ENABLE_ASSERTIONS +// clang-format on +#endif // _AU_CONFIG_H_INCLUDED diff --git a/Library/version.cc.in b/Library/version.cc.in new file mode 100644 index 0000000..b89cb09 --- /dev/null +++ b/Library/version.cc.in @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2022-2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/Config.h" + +#include + +// clang-format off +#if defined(AU_BUILD_TYPE_RELEASE) + +static const std::string au_version_str = "@AU_VERSION_MAJOR@" + \ + ".@AU_VERSION_MINOR@" + \ + ".@AU_VERSION_PATCH@" ; + +#else + +static const std::string au_version_str = "@AU_VERSION_STRING@" + "-git-" + \ + "@AU_GIT_HASH@"; + +#endif + + +static const Uint32 au_version_major = @AU_VERSION_MAJOR@; +static const Uint32 au_version_minor = @AU_VERSION_MINOR@; +static const Uint32 au_version_patch = @AU_VERSION_PATCH@; + + +#include "Capi/au/version.h" + +AUD_EXTERN_C_BEGIN + +/** + * @brief Return Version Major number + */ +Uint32 +au_get_version_major(void) +{ + return au_version_major; +} + +/** + * @brief Return Version Minor number + */ +Uint32 +au_get_version_minor(void) +{ + return au_version_minor; +} + +/** + * @brief Return Version Patch level + */ +Uint32 +au_get_version_patch(void) +{ + return au_version_patch; +} + +/** + * @brief returns version of library + * + */ +const char* const +au_get_version_str(void) +{ + return au_version_str; +} + +AUD_EXTERN_C_END + +//clang-format on diff --git a/License.txt b/License.txt new file mode 100644 index 0000000..4f9db76 --- /dev/null +++ b/License.txt @@ -0,0 +1,38 @@ +AMD copyrighted code (BSD-3-clause) +Copyright Statements +Copyright (C) 2008-2022,Advanced Micro Devices, Inc. All rights reserved. +Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. +License Text http://spdx.org/licenses/BSD-3-Clause +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +AMD copyrighted code (NCSA) +Copyright Statements +Copyright (c) 2017 Advanced Micro Devices, Inc. All rights reserved. +License Text https://spdx.org/licenses/NCSA.html +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal with the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimers. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimers in the documentation and/or other materials provided with the distribution. +* Neither the names of , nor the names of its contributors may be used to endorse or promote products derived from this Software without specific prior written permission. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE SOFTWARE + +AMD copyrighted code (MIT) +Copyright Statements +Copyright (c) 2019 - present Advanced Micro Devices, Inc. All rights reserved. +License Text http://spdx.org/licenses/MIT +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 NON-INFRINGEMENT. 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. + +google-googletest v-u (BSD-3-Clause) +Copyright Statements +Copyright 2008, Google Inc. All rights reserved. +License Text http://spdx.org/licenses/BSD-3-Clause +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md deleted file mode 100644 index 8a56b29..0000000 --- a/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# AOCL-Utils - -## OVERVIEW - -The library AOCL-Utils is intended to provide a uniform interface to all AOCL libraries to access CPU features, especially for AMD CPUs. The library provides the following features: - - * Core details - * Flags available/usable - * ISA available/usable - * Topology about L1/L2/L3 - -AOCL-Utils is designed to be integrated into other AOCL libraries. Each project has their own mechanism to identify CPU and provide necessary features such as "dynamic dispatch". The main purpose of this library is to provide a centralized mechanism to update/validate and provide information to the users of this library. - -## BUILDING - -Please refer to BUILD.md file for build instructions - -## Features -Currently supported: - -* ISA available/usable -* API to check following features: - – SHA, AES, and VAES availability - – RDSEED and RDRAND availability - – AVX2 availability - – AVX512 foundation and sub-feature flags -* APIs for cache topology: - - Cache size and line size - - Number of ways and sets - - Number of logical processors sharing cache - - Number of physical partitions - - Fully associative - - Self Initializing - - Cache Inclusive/Exclusive - -## Dependency - -Need explicit linking of stdc++ library while using libaoclutils.a -Needs GCC/Clang compiler versions which supports C11 and C++17 standards. - -## Important notes -Functions/members names may change in upcoming release of AOCL-Utils library. - -## Contacts -AOCL-UTILS is developed and maintained by AMD. For any issues/suggestions you can contact us on the email-id toolchainsupport@amd.com.  diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..c7385c0 --- /dev/null +++ b/Readme.md @@ -0,0 +1,209 @@ +# AOCL-UTILS + + An effort to factor out common functionality across libraries. + +## Table of Contents + +- [AOCL-UTILS](#aocl-utils) + - [Table of Contents](#table-of-contents) + - [Project structure](#project-structure) + - [BUILD AND INSTALL](#build-and-install) + - [Dependencies](#dependencies) + - [Getting started](#getting-started) + - [Checkout the latest code](#checkout-the-latest-code) + - [Configure](#configure) + - [Build](#build) + - [Install](#install) + - [Testing](#testing) + - [Examples](#examples) + - [List of build options](#list-of-build-options) + - [List of functionalities provided by each utils modules](#list-of-functionalities-provided-by-each-utils-modules) + - [au\_core (internal)](#au_core-internal) + - [Current API Stack(Core)](#current-api-stackcore) + - [au\_cpuid](#au_cpuid) + - [Current API Stack(Cpuid)](#current-api-stackcpuid) + - [aoclutils](#aoclutils) + - [Integration with other projects](#integration-with-other-projects) + - [CMAKE](#cmake) + - [Make](#make) + +## Project structure + +The project is structured as follows: + +- `Library`: This directory contains the source code for the project. + +- `SDK`: The release folder. + +- `Tests`: This directory contains the necessary unit tests for the project. + +- `Tools`: The necessary tools to work with the project. + +## BUILD AND INSTALL + +### Dependencies + +Refer [supported package matrix document](https://docs.amd.com/r/en-US/63866-AOCL-utils/Supported-package-Matrix) +(supported_package_matrix.md file) + +### Getting started + +Same commands can be used on both Linux and Windows. The only difference is the environment setup. The default compiler and generator used will be the platform defaults. + +For specific compiler and generator, use the following command: + +```console + cmake -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -G "Unix Makefiles" .. +``` + +**Note: Replace the compiler(clang) and generator(Unix Makefiles) with the required one.** + +Refer [supported_package_matrix.md file](./supported_package_matrix.md) for the supported compiler and generator. + +#### Checkout the latest code + +```console + git clone + cd aocl-utils +``` + +#### Configure + +```console + cmake -B default -DCMAKE_INSTALL_PREFIX=install_dir +``` + +#### Build + +```console + cmake --build default --config release -j +``` + +#### Install + +```console + cmake --install default --config release +``` + +This command creates + +1. The necessary header files in the \/includefolder +2. static and dynamic library files corresponding to modules core(au_core) and cpuid(au_cpuid) + Link with these libraries based on the functionality required. +**Note:** + 1. This command creates lib/lib64 directory for the binaries. To have custom library path, use CMAKE_INSTALL_LIBDIR. + 2. Rightly update the include path and library path in the project to link with the installed libraries. or use LD_LIBRARY_PATH to point to the installed library path.(PATH environment variable in windows) + 3. Refer to the [API documentation](https://docs.amd.com/r/en-US/63866-AOCL-utils/Cpuid-API-Reference) and examples in the Example folder to understand how to link and use the modules. + +**Important:** + +```console + 1. Most of the CPUID APIs(Along with the headers) from 4.2 release is deprecated and will be removed in the future release. Refer to the API documentation for the new APIs. + 2. The old APIs can be enabled using AU_ENABLE_OLD_API=ON during build, otherwise utils build will throw deprecated warnings. + 3. The aoclutils module is a combination of au_core and au_cpuid modules. + 4. The aoclutils module is the default module to be used for all the functionalities. +``` + +## Testing + +Build with AU_BUILD_TESTS=ON to run the tests. + +```console + ctest -C release +``` + +qemu-x86_64 is a dependency for running tests. Install it using the following command: + +```console + sudo apt-get install qemu-user # For Ubuntu + sudo dnf install qemu-user # For Fedora/RHEL/CentOS + # qemu tests are disable on windows as qemu-user is not available on windows +``` + +## Examples + +Build with AU_BUILD_EXAMPLES=ON to run the examples. + +```console + cmake -B default -DAU_BUILD_EXAMPLES=ON + cmake --build default --config release -j +``` + +The binaries are in the default/release folder. Refer to the SDK/Examples folder Readme.md for details on out of tree compilation. + +## List of build options + +```console +Build FLags Description Default Alternate Values +-------------------------------------------------------------------------------------------------- +AU_BUILD_DOCS Generate Docs during build OFF ON +AU_BUILD_EXAMPLES Build examples OFF ON +AU_BUILD_TESTS Build tests OFF ON +AU_BUILD_TYPE Build type Release Debug, Developer +AU_ENABLE_OLD_API Enable OLD alci_* APIs OFF ON Use to avoid deprecation warnings +AU_BUILD_SHARED_LIBS Build shared libraries ON OFF +AU_BUILD_STATIC_LIBS Build static libraries ON OFF +``` + +## List of functionalities provided by each utils modules + +### au_core (internal) + +| Functionality | Headerfiles(C) | Headerfiles(C++) | +| ------------- | -------------- | ---------------- | +| thread pinning| ThreadPinning.hh | threadpinning.h | + +#### Current API Stack(Core) + +1. ThreadPinning + +Current ThreadPinning API stack + +### au_cpuid + +| Functionality | Headerfiles(C) | Headerfiles(C++) | +| ------------- | -------------- | ---------------- | +| cpu architecture detection | cpuid.h | X86Cpu.hh | +| cpuid feature flag detection | cpuid.h | X86Cpu.hh | +| Deprecated APIs | arch.h | cpu.hh | + +#### Current API Stack(Cpuid) + +Current Cpuid API stack + +**Note** + +1. The APIs in the grey box are deprecated and will be removed in the future release. +2. X86Cpu.hh(CPP)/cpuid.h(C) is the new header file that contains the new APIs. + +### aoclutils + +- All features of au_cpuid and au_core combined. + +The C headers are in the \/include/Capi folder and the C++ headers are in the include/Au folder. +Deprecated APIs are in the include/alci folder. +**Note: Refer to [API documentation](https://docs.amd.com/r/en-US/63866-AOCL-utils/Cpuid-API-Reference) and Examples in Examples folder to understand how to link and use the modules.** + +## Integration with other projects + +Following are the build systems to integrate in library/application with AOCL-Utils: + +### CMAKE + +In the CMake file, use the following: + +```console +TARGET_INCLUDE_DIRECTORIES() – path of libaoclutils include directory + +TARGET_LINK_LIBRARIES() – path to link libaoclutils binaries +``` + +### Make + +In the compiler flags of Make file, use the following: + +```console +“–I†- path of libaoclutils include directory + +“-l, -L†- path to link libaoclutils binaries +``` diff --git a/include/alci/alci.h b/SDK/Bcl/alci/alci.h similarity index 82% rename from include/alci/alci.h rename to SDK/Bcl/alci/alci.h index 06c9e64..a94049f 100644 --- a/include/alci/alci.h +++ b/SDK/Bcl/alci/alci.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023, Advanced Micro Devices, Inc. All rights reserved. + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -26,21 +26,9 @@ * */ -#ifndef ALCI_H -#define ALCI_H +#ifndef __ALCI_H__ +#define __ALCI_H__ -#ifdef __cplusplus -#include "cxx/alci.hh" -namespace alci { -#endif +#include "Capi/au/au.h" -#include "alci/enum.h" -#include "alci/macros.h" -#include "alci_c.h" -#include - -#ifdef __cplusplus -} //namespace alci -#endif - -#endif /* ALCI_H */ +#endif /* __ALCI_H__ */ diff --git a/SDK/Bcl/alci/alci_c.h b/SDK/Bcl/alci/alci_c.h new file mode 100644 index 0000000..502ecd3 --- /dev/null +++ b/SDK/Bcl/alci/alci_c.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __ALCI_C_H__ +#define __ALCI_C_H__ + +#include "Capi/au/cpuid/cpuid.h" + +#endif /* __ALCI_C_H__ */ diff --git a/SDK/Bcl/alci/arch.h b/SDK/Bcl/alci/arch.h new file mode 100644 index 0000000..4153e1e --- /dev/null +++ b/SDK/Bcl/alci/arch.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __ARCH_H__ +#define __ARCH_H__ + +#include "Capi/au/cpuid/cpuid.h" + +#endif /* __ARCH_H__ */ diff --git a/SDK/Bcl/alci/cxx/cpu.hh b/SDK/Bcl/alci/cxx/cpu.hh new file mode 100644 index 0000000..881b86d --- /dev/null +++ b/SDK/Bcl/alci/cxx/cpu.hh @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __CPU_HH__ +#define __CPU_HH__ + +#include "Au/Cpuid/Enum.hh" + +#endif /* __CPU_HH__ */ diff --git a/SDK/Bcl/alci/cxx/enum.h b/SDK/Bcl/alci/cxx/enum.h new file mode 100644 index 0000000..c502861 --- /dev/null +++ b/SDK/Bcl/alci/cxx/enum.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __ENUM_H__ +#define __ENUM_H__ + +#include "Au/Cpuid/Enum.hh" + +#endif /* __ENUM_H__ */ diff --git a/SDK/Bcl/alci/enum.h b/SDK/Bcl/alci/enum.h new file mode 100644 index 0000000..1183e14 --- /dev/null +++ b/SDK/Bcl/alci/enum.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __ENUM_H__ +#define __ENUM_H__ + +#include "Capi/au/enum.h" + +#endif /* __ENUM_H__ */ diff --git a/SDK/Bcl/alci/macros.h b/SDK/Bcl/alci/macros.h new file mode 100644 index 0000000..74fd009 --- /dev/null +++ b/SDK/Bcl/alci/macros.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __MACROS_H__ +#define __MACROS_H__ + +#include "Capi/au/macros.h" + +#endif /* __MACROS_H__ */ diff --git a/SDK/CMake/af_examples.cmake b/SDK/CMake/af_examples.cmake new file mode 100644 index 0000000..558d739 --- /dev/null +++ b/SDK/CMake/af_examples.cmake @@ -0,0 +1,49 @@ +# +# Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# af_add_example( PACKAGE +# SOURCES source... +# [COMPONENTS component...] +function(af_add_example NAME) + set(fPrefix APP) + set(fOptions ) + set(fOneArg PACKAGE) + set(fMultiArgs "INCLUDES;SOURCES;COMPONENTS") + + + cmake_parse_arguments( + ${fPrefix} + "${fOptions}" + "${fOneArg}" + "${fMultiArgs}" + ${ARGN} + ) + + add_example(${NAME} ${APP_SOURCES}) + add_example(${NAME}_static ) + +endfunction(af_add_example) diff --git a/SDK/CMakeLists.txt b/SDK/CMakeLists.txt new file mode 100644 index 0000000..f9bc2e2 --- /dev/null +++ b/SDK/CMakeLists.txt @@ -0,0 +1,3 @@ +#find_package(lib_au REQUIRED QUIET) + +add_subdirectory(Examples) diff --git a/SDK/Examples/.clang-tidy b/SDK/Examples/.clang-tidy new file mode 100644 index 0000000..ae204c1 --- /dev/null +++ b/SDK/Examples/.clang-tidy @@ -0,0 +1,7 @@ +# File: project/external/.clang-tidy + +# Disable all checks in this folder. +# +Checks: '-*,misc-definitions-in-headers' +CheckOptions: + {HeaderFileExtensions: "x" } diff --git a/SDK/Examples/CMakeLists.txt b/SDK/Examples/CMakeLists.txt new file mode 100644 index 0000000..8396ebb --- /dev/null +++ b/SDK/Examples/CMakeLists.txt @@ -0,0 +1,72 @@ +# +# Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +cmake_minimum_required(VERSION 3.20...3.27) +project(cpuid_example_cpp) + +list(APPEND CMAKE_MODULE_PATH ${AUROOT}/lib/CMake) +list(APPEND AU_INCLUDE_DIRS ${AUROOT}/include) +link_directories(${AUROOT}/lib) +include(au_examples) + +# on windows platform, libname to be linked is libaoclutils. + +if(WIN32) + set(AU_LIBS libaoclutils) +else() + set(AU_LIBS aoclutils) +endif() + +au_add_application(cpuid_example_cpp + SOURCES cpuid_example.cc + LIBS ${AU_LIBS} + INCLUDES ${AU_INCLUDE_DIRS}) + +au_add_application(cpuid_deprecated_api_example_cpp + SOURCES cpuid_deprecated_api_example.cc + LIBS ${AU_LIBS} + INCLUDES ${AU_INCLUDE_DIRS}) + +project(thread_pinning_example_cpp) +au_add_application(thread_pinning_example_cpp + SOURCES thread_pinning_example.cc + LIBS ${AU_LIBS} + INCLUDES ${AU_INCLUDE_DIRS}) + +#if built inside the source tree, add dependencies. +if(AU_BUILD_EXAMPLES AND AU_BUILD_SHARED_LIBS) + if(WIN32) + add_dependencies(cpuid_example_cpp libaoclutils_shared au_cpuid_shared) + add_dependencies(cpuid_deprecated_api_example_cpp libaoclutils_shared au_cpuid_shared) + add_dependencies(thread_pinning_example_cpp libaoclutils_shared au_internal_core_shared) + else() + add_dependencies(cpuid_example_cpp aoclutils_shared au_cpuid_shared) + add_dependencies(cpuid_deprecated_api_example_cpp aoclutils_shared au_cpuid_shared) + add_dependencies(thread_pinning_example_cpp aoclutils_shared au_internal_core_shared) + endif() +endif() + +add_subdirectory(capi) diff --git a/SDK/Examples/Readme.md b/SDK/Examples/Readme.md new file mode 100644 index 0000000..0f783f6 --- /dev/null +++ b/SDK/Examples/Readme.md @@ -0,0 +1,8 @@ +# Building + +```sh +cmake . -B build -DAUROOT= +cmake --build build --config Release -j +``` +export LD_LIBRARY_PATH=/lib +where AUROOT is the AOCL-Utils install directory diff --git a/SDK/Examples/capi/CMakeLists.txt b/SDK/Examples/capi/CMakeLists.txt new file mode 100644 index 0000000..ebffc63 --- /dev/null +++ b/SDK/Examples/capi/CMakeLists.txt @@ -0,0 +1,66 @@ +# +# Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +cmake_minimum_required(VERSION 3.20...3.27) + +project(cpuid_example_c) +set_source_files_properties(cpuid_example.c PROPERTIES LANGUAGE CXX) +au_add_application(cpuid_example_c + SOURCES cpuid_example.c + LIBS ${AU_LIBS} + INCLUDES ${AU_INCLUDE_DIRS}) + +set_source_files_properties(cpuid_deprecated_api_example.c PROPERTIES LANGUAGE CXX) +au_add_application(cpuid_deprecated_api_example_c + SOURCES cpuid_deprecated_api_example.c + LIBS ${AU_LIBS} + INCLUDES ${AU_INCLUDE_DIRS}) + +if (NOT WIN32) + au_add_application(thread_pinning_example_c + SOURCES thread_pinning_example_linux.c + LIBS ${AU_LIBS} + INCLUDES ${AU_INCLUDE_DIRS}) +set_source_files_properties(thread_pinning_example_linux.c PROPERTIES LANGUAGE CXX) +else() + au_add_application(thread_pinning_example_c + SOURCES thread_pinning_example_windows.c + LIBS ${AU_LIBS} + INCLUDES ${AU_INCLUDE_DIRS}) + set_source_files_properties(thread_pinning_example_windows.c PROPERTIES LANGUAGE CXX) +endif() + +if(AU_BUILD_EXAMPLES AND AU_BUILD_SHARED_LIBS) + if(WIN32) + add_dependencies(cpuid_example_c libaoclutils_shared au_cpuid_shared) + add_dependencies(cpuid_deprecated_api_example_c libaoclutils_shared au_cpuid_shared) + add_dependencies(thread_pinning_example_c libaoclutils_shared au_internal_core_shared) + else() + add_dependencies(cpuid_example_c aoclutils_shared au_cpuid_shared) + add_dependencies(cpuid_deprecated_api_example_c aoclutils_shared au_cpuid_shared) + add_dependencies(thread_pinning_example_c aoclutils_shared au_internal_core_shared) + endif() +endif() diff --git a/SDK/Examples/capi/cpuid_deprecated_api_example.c b/SDK/Examples/capi/cpuid_deprecated_api_example.c new file mode 100644 index 0000000..52986f5 --- /dev/null +++ b/SDK/Examples/capi/cpuid_deprecated_api_example.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Capi/au/cpuid/cpuid.h" +#include "Capi/au/enum.h" + +#include +#include + +#define size 16 +static void +display_core_info() +{ + int core_num = 0; + char buf[size]; + const char* token = NULL; + int index = 0; + + memset(buf, 0, size * sizeof(char)); + const char* vendorInfo[13] = { "Vendor : ", + "Family : ", + "Model : ", + "Stepping : ", + "Uarch : " }; + + if (alci_is_amd(core_num)) { + printf("AMD CPU detected...\n"); + } else { + // Intel Apis are not exposed. + printf("Unknown CPU detected...\n"); + } + + printf("\nGetting CPU information for core 0\n"); + alci_cpu_get_vendor(core_num, buf, size); + + token = strtok(buf, "\r\n"); + while (token != NULL) { + printf("%s", vendorInfo[index++]); + printf("%s\n", token); + token = strtok(NULL, "\r\n"); + } +} + +static void +display_isa_info() +{ + int core_num = 0; + printf("\nGetting ISA information for core 0\n"); + if (alci_arch_is_zen4(core_num)) { + printf("CPU supports zen4 ISA\n"); + } else if (alci_arch_is_zen3(core_num)) { + printf("CPU supports zen3 ISA\n"); + } else if (alci_arch_is_zen2(core_num)) { + printf("CPU supports zen2 ISA\n"); + } else if (alci_arch_is_zen(core_num)) { + printf("CPU supports zen ISA\n"); + } else { + printf("CPU does not support zen or higher ISA or this Cpu is not " + "supported\n"); + } + printf("\nCpu Feature Identification...\n"); + // clang-format off + printf("TSC_ADJUST : %s\n", (alci_cpu_has_flag(core_num, ALC_E_FLAG_TSC_ADJUST) ? "yes" : "no")); + printf("AVX : %s\n", (alci_cpu_has_flag(core_num, ALC_E_FLAG_AVX) ? "yes" : "no")); + printf("AVXVNNI : %s\n", (alci_cpu_has_flag(core_num, ALC_E_FLAG_AVXVNNI) ? "yes" : "no")); + printf("AVX2 : %s\n", (alci_cpu_has_flag(core_num, ALC_E_FLAG_AVX2) ? "yes" : "no")); + printf("AVX512 : %s\n", (alci_cpu_has_flag(core_num, ALC_E_FLAG_AVX512F) ? "yes" : "no")); + // clang-format on + + printf("\nCpu Feature Identification...\n"); + // clang-format off + const char* const flags_array[] = {"tsc_adjust", "avx", "avxvnni", "avx2", + "avx512f"}; + bool *result = au_cpuid_has_flag(core_num, flags_array, 5); + printf("TSC_ADJUST : %s\n", (result[0] ? "yes" : "no")); + printf("AVX : %s\n", (result[1] ? "yes" : "no")); + printf("AVXVNNI : %s\n", (result[2] ? "yes" : "no")); + printf("AVX2 : %s\n", (result[3] ? "yes" : "no")); + printf("AVX512 : %s\n", (result[4] ? "yes" : "no")); + // explictly free the result array to avoid memory leak + free(result); + // clang-format on +} +int +main(void) +{ + display_core_info(); + + display_isa_info(); + + return 0; +} diff --git a/SDK/Examples/capi/cpuid_example.c b/SDK/Examples/capi/cpuid_example.c new file mode 100644 index 0000000..143b9eb --- /dev/null +++ b/SDK/Examples/capi/cpuid_example.c @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Capi/au/cpuid/cpuid.h" + +#include +#include + +#define size 16 +static void +display_core_info() +{ + int core_num = 0; + char buf[size]; + const char* token = NULL; + int index = 0; + + memset(buf, 0, size * sizeof(char)); + const char* vendorInfo[13] = { "Vendor : ", + "Family : ", + "Model : ", + "Stepping : ", + "Uarch : " }; + + if (au_cpuid_is_amd(core_num)) { + printf("AMD CPU detected...\n"); + } else { + // Intel Apis are not exposed. + printf("Unknown CPU detected...\n"); + } + + printf("\nGetting CPU information for core 0\n"); + au_cpuid_get_vendor(core_num, buf, size); + + token = strtok(buf, "\r\n"); + while (token != NULL) { + printf("%s", vendorInfo[index++]); + printf("%s\n", token); + token = strtok(NULL, "\r\n"); + } +} + +static void +display_isa_info() +{ + int core_num = 0; + printf("\nGetting ISA information for core 0\n"); + if (au_cpuid_arch_is_zen5(core_num)) { + printf("CPU supports zen5 ISA\n"); + } else if (au_cpuid_arch_is_zen4(core_num)) { + printf("CPU supports zen4 ISA\n"); + } else if (au_cpuid_arch_is_zen3(core_num)) { + printf("CPU supports zen3 ISA\n"); + } else if (au_cpuid_arch_is_zen2(core_num)) { + printf("CPU supports zen2 ISA\n"); + } else if (au_cpuid_arch_is_zenplus(core_num)) { + printf("CPU supports zenplus ISA\n"); + } else if (au_cpuid_arch_is_zen(core_num)) { + printf("CPU supports zen ISA\n"); + } else { + printf("CPU does not support zen or higher ISA or this Cpu is not " + "supported\n"); + } + printf("\nCpu Feature Identification...\n"); + const char* const flags_array[] = { + "tsc_adjust", "avx", "avxvnni", "avx2", "avx512f" + }; + bool result = au_cpuid_has_flags(core_num, flags_array, 5); + printf("Checking for TSC_ADJUST, AVX, AVXVNNI, AVX2, AVX512...\n"); + printf("%s\n", + (result ? "All are present" + : "One or more of the flags are not present")); +} + +int +main(void) +{ + display_core_info(); + + display_isa_info(); + + return 0; +} diff --git a/SDK/Examples/capi/thread_pinning_example_linux.c b/SDK/Examples/capi/thread_pinning_example_linux.c new file mode 100644 index 0000000..087a4eb --- /dev/null +++ b/SDK/Examples/capi/thread_pinning_example_linux.c @@ -0,0 +1,101 @@ +/* + * Copyright(c) 2024 Advanced Micro Devices, Inc.All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this softwareand 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 noticeand 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 "Capi/au/threadpinning.h" + +#include +#include +#include +#include +#include +#include + +#define NUM_THREADS 5 + +void* +threadFunction(void* arg) +{ + int id = *((int*)arg); + printf("Thread started with ID: %d\n", id); + sleep(3); + return NULL; +} + +void +checkThreadAffinity(pthread_t thread) +{ + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + if (pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuset) != 0) { + printf("Error reading thread affinity on Linux\n"); + } else { + printf("Affinity mask: %lu\n", cpuset.__bits[0]); + } +} + +int +main() +{ + int thread_ids[NUM_THREADS]; + pthread_t threads[NUM_THREADS]; + + for (int i = 0; i < NUM_THREADS; ++i) { + thread_ids[i] = i; + if (pthread_create(&threads[i], NULL, threadFunction, &thread_ids[i]) + != 0) { + printf("Error creating thread %d\n", i); + return 1; + } + } + + // Pin threads to the processor group using different strategies + // CORE, LOGICAL, SPREAD, CUSTOM + printf( + "Pinning threads to the processor group using different strategies\n"); + printf("CORE\n"); + au_pin_threads_core(threads, NUM_THREADS); + for (int i = 0; i < NUM_THREADS; ++i) { + checkThreadAffinity(threads[i]); + } + printf("LOGICAL\n"); + au_pin_threads_logical(threads, NUM_THREADS); + for (int i = 0; i < NUM_THREADS; ++i) { + checkThreadAffinity(threads[i]); + } + printf("SPREAD\n"); + au_pin_threads_spread(threads, NUM_THREADS); + for (int i = 0; i < NUM_THREADS; ++i) { + checkThreadAffinity(threads[i]); + } + printf("CUSTOM\n"); + int affinityVector[NUM_THREADS] = { 0, 1, 4, 6, 7 }; + au_pin_threads_custom(threads, NUM_THREADS, affinityVector, NUM_THREADS); + for (int i = 0; i < NUM_THREADS; ++i) { + checkThreadAffinity(threads[i]); + } + + for (int i = 0; i < NUM_THREADS; ++i) { + pthread_join(threads[i], NULL); + } + + return 0; +} diff --git a/SDK/Examples/capi/thread_pinning_example_windows.c b/SDK/Examples/capi/thread_pinning_example_windows.c new file mode 100644 index 0000000..2b2a9f8 --- /dev/null +++ b/SDK/Examples/capi/thread_pinning_example_windows.c @@ -0,0 +1,107 @@ +/* + * Copyright(c) 2024 Advanced Micro Devices, Inc.All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this softwareand 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 noticeand 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 "Capi/au/threadpinning.h" + +#include +#include +#include + +#define NUM_THREADS 5 + +DWORD WINAPI +threadFunction(LPVOID lpParam) +{ + int id = *((int*)lpParam); + printf("Thread started with ID: %d\n", id); + Sleep(3); + return 0; +} + +void +checkThreadAffinity(HANDLE handle) +{ + // Get the native handle of the thread + + // Get thread group affinity + GROUP_AFFINITY groupAffinity; + BOOL result = GetThreadGroupAffinity(handle, &groupAffinity); + if (!result) { + printf("Error reading thread affinity for thread on Windows\n"); + } else { + printf("groupAffinity.mask %llu \n", groupAffinity.Mask); + } +} + +int +main() +{ + int thread_ids[NUM_THREADS]; + HANDLE threads[NUM_THREADS]; + DWORD threadID; + + // Create threads + for (int i = 0; i < NUM_THREADS; ++i) { + thread_ids[i] = i; + threads[i] = + CreateThread(NULL, 0, threadFunction, &thread_ids[i], 0, &threadID); + if (threads[i] == NULL) { + printf("Error creating thread %d\n", i); + return 1; + } + } + + // Pin threads to the processor group using different strategies + // CORE, LOGICAL, SPREAD, CUSTOM + printf( + "Pinning threads to the processor group using different strategies\n"); + printf("CORE\n"); + au_pin_threads_core(threads, NUM_THREADS); + for (int i = 0; i < NUM_THREADS; ++i) { + checkThreadAffinity(threads[i]); + } + printf("LOGICAL\n"); + au_pin_threads_logical(threads, NUM_THREADS); + for (int i = 0; i < NUM_THREADS; ++i) { + checkThreadAffinity(threads[i]); + } + + printf("SPREAD\n"); + au_pin_threads_spread(threads, NUM_THREADS); + for (int i = 0; i < NUM_THREADS; ++i) { + checkThreadAffinity(threads[i]); + } + + printf("CUSTOM\n"); + int affinityVector[NUM_THREADS] = { 0, 1, 4, 6, 7 }; + au_pin_threads_custom(threads, NUM_THREADS, affinityVector, NUM_THREADS); + for (int i = 0; i < NUM_THREADS; ++i) { + checkThreadAffinity(threads[i]); + } + + for (int i = 0; i < NUM_THREADS; ++i) { + WaitForSingleObject(threads[i], INFINITE); + CloseHandle(threads[i]); + } + + return 0; +} diff --git a/SDK/Examples/capi/version_example.c b/SDK/Examples/capi/version_example.c new file mode 100644 index 0000000..f22cd7e --- /dev/null +++ b/SDK/Examples/capi/version_example.c @@ -0,0 +1,10 @@ + +#include "Capi/af/version.h" + +int +main(void) +{ + printf("Version String: %s\n", au_version_get_str()); + + return 0; +} diff --git a/SDK/Examples/cpuid_deprecated_api_example.cc b/SDK/Examples/cpuid_deprecated_api_example.cc new file mode 100644 index 0000000..0cb2a18 --- /dev/null +++ b/SDK/Examples/cpuid_deprecated_api_example.cc @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/Cpuid/CacheInfo.hh" +#include "Au/Cpuid/X86Cpu.hh" + +#include + +using namespace Au; + +static void +display_core_info() +{ + X86Cpu cpu{ 0 }; + if (cpu.isAMD()) { + std::cout << "AMD CPU detected..." << std::endl; + } else if (cpu.isIntel()) { + std::cout << "Intel CPU detected..." << std::endl; + } else { + std::cout << "Unknown CPU detected..." << std::endl; + } + + std::cout << "\nGetting CPU information for core 0" << std::endl; + auto vInfo = cpu.getVendorInfo(); + std::cout << "Vendor : " << static_cast(vInfo.m_mfg) << std::endl; + std::cout << "Family : " << static_cast(vInfo.m_family) + << std::endl; + std::cout << "Model : " << vInfo.m_model << std::endl; + std::cout << "Stepping : " << vInfo.m_stepping << std::endl; + std::cout << "Uarch : " << static_cast(vInfo.m_uarch) + << std::endl; +} + +static void +display_isa_info() +{ + X86Cpu cpu{ 0 }; + + std::cout << "\nGetting ISA information for core 0" << std::endl; + if (cpu.isX86_64v4()) { + std::cout << "CPU supports x86-64v4 ISA" << std::endl; + } + if (cpu.isX86_64v3()) { + std::cout << "CPU supports x86-64v3 ISA" << std::endl; + } + if (cpu.isX86_64v2()) { + std::cout << "CPU supports x86-64v2 ISA" << std::endl; + } else { + std::cout << "CPU does not support x86-64v2 or higher ISA" << std::endl; + } + std::cout << "\nCpu Feature Identification..." << std::endl; + // clang-format off + std::cout << "TSC_ADJUST : " << (cpu.isAvailable(ECpuidFlag::tsc_adjust) ? "yes" : "no") << std::endl; + std::cout << "AVX : " << (cpu.isAvailable(ECpuidFlag::avx) ? "yes" : "no") << std::endl; + std::cout << "AVXVNNI : " << (cpu.isAvailable(ECpuidFlag::avxvnni) ? "yes" : "no") << std::endl; + std::cout << "AVX2 : " << (cpu.isAvailable(ECpuidFlag::avx2) ? "yes" : "no") << std::endl; + std::cout << "AVX512 : " << (cpu.isAvailable(ECpuidFlag::avx512f) ? "yes" : "no") << std::endl; + // clang-format on +} + +int +main(void) +{ + // Note: Only isAvailable API is deprecated. Use hasFlag API instead. + display_core_info(); + + display_isa_info(); + + return 0; +} diff --git a/SDK/Examples/cpuid_example.cc b/SDK/Examples/cpuid_example.cc new file mode 100644 index 0000000..bcdab20 --- /dev/null +++ b/SDK/Examples/cpuid_example.cc @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/Cpuid/CacheInfo.hh" +#include "Au/Cpuid/X86Cpu.hh" + +#include + +using namespace Au; + +static void +display_core_info() +{ + X86Cpu cpu{ 0 }; + + if (cpu.isAMD()) { + std::cout << "AMD CPU detected..." << std::endl; + } else if (cpu.isIntel()) { + std::cout << "Intel CPU detected..." << std::endl; + } else { + std::cout << "Unknown CPU detected..." << std::endl; + } + + std::cout << "\nGetting CPU information for core 0" << std::endl; + auto vInfo = cpu.getVendorInfo(); + std::cout << "Vendor : " << static_cast(vInfo.m_mfg) << std::endl; + std::cout << "Family : " << static_cast(vInfo.m_family) + << std::endl; + std::cout << "Model : " << vInfo.m_model << std::endl; + std::cout << "Stepping : " << vInfo.m_stepping << std::endl; + std::cout << "Uarch : " << static_cast(vInfo.m_uarch) + << std::endl; +} + +static void +display_isa_info() +{ + X86Cpu cpu{ 0 }; + + std::cout << "\nGetting ISA information for core 0" << std::endl; + if (cpu.isX86_64v4()) { + std::cout << "CPU supports x86-64v4 ISA" << std::endl; + } + if (cpu.isX86_64v3()) { + std::cout << "CPU supports x86-64v3 ISA" << std::endl; + } + if (cpu.isX86_64v2()) { + std::cout << "CPU supports x86-64v2 ISA" << std::endl; + } else { + std::cout << "CPU does not support x86-64v2 or higher ISA" << std::endl; + } + std::cout << "\nCpu Feature Identification..." << std::endl; + // clang-format off + std::cout << "TSC_ADJUST : " << (cpu.hasFlag(ECpuidFlag::tsc_adjust) ? "yes" : "no") << std::endl; + std::cout << "AVX : " << (cpu.hasFlag(ECpuidFlag::avx) ? "yes" : "no") << std::endl; + std::cout << "AVXVNNI : " << (cpu.hasFlag(ECpuidFlag::avxvnni) ? "yes" : "no") << std::endl; + std::cout << "AVX2 : " << (cpu.hasFlag(ECpuidFlag::avx2) ? "yes" : "no") << std::endl; + std::cout << "AVX512 : " << (cpu.hasFlag(ECpuidFlag::avx512f) ? "yes" : "no") << std::endl; + // clang-format on +} + +int +main(void) +{ + display_core_info(); + + display_isa_info(); + + return 0; +} diff --git a/SDK/Examples/thread_pinning_example.cc b/SDK/Examples/thread_pinning_example.cc new file mode 100644 index 0000000..540eaa4 --- /dev/null +++ b/SDK/Examples/thread_pinning_example.cc @@ -0,0 +1,127 @@ +/* + * Copyright(c) 2024 Advanced Micro Devices, Inc.All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this softwareand 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 noticeand 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 "Au/ThreadPinning.hh" +#include +#include +#include + +#ifdef _WIN32 +#include +#else +#include +#include +#endif + +using namespace Au; + +// Function for the thread to execute +void +printThreadId(int id) +{ + std::cout << "Thread started with ID: " << id << std::endl; + std::this_thread::sleep_for(std::chrono::milliseconds(1)); +} + +void +checkThreadAffinity(std::thread& thread) +{ +#ifdef _WIN32 + // Get the native handle of the thread + HANDLE handle = (HANDLE)thread.native_handle(); + + // Get thread group affinity + GROUP_AFFINITY groupAffinity; + BOOL result = GetThreadGroupAffinity(handle, &groupAffinity); + if (!result) { + std::cerr << "Error reading thread affinity for thread on Windows" + << std::endl; + } else { + std::cout << "groupAffinity.mask" << groupAffinity.Mask << std::endl; + } +#else + // Get the native handle of the thread + pthread_t handle = thread.native_handle(); + // Create a CPU set and get the current affinity + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + int result = pthread_getaffinity_np(handle, sizeof(cpu_set_t), &cpuset); + if (result != 0) { + std::cerr << "Error reading thread affinity for thread on Linux" + << std::endl; + } else { + std::cout << " affinity mask: " << cpuset.__bits[0] << std::endl; + } +#endif +} + +int +main() +{ + int n = 5; // Number of threads + std::vector threads; + + // Create n threads + for (int i = 0; i < n; ++i) { + threads.push_back(std::thread(printThreadId, i)); + } + + ThreadPinning tp; + std::vector threadList; + for (int i = 0; i < n; i++) { + threadList.push_back(threads[i].native_handle()); + } + std::cout << "Pinning threads using custom pin strategy" << std::endl; + // pin threads using the custom strategy. + tp.pinThreads(threadList, { 0, 5, 2, 10, 4 }); + for (int i = 0; i < n; ++i) { + checkThreadAffinity(threads[i]); + } + std::cout << "Pinning threads using spread pin strategy" << std::endl; + // pin threads using the spread strategy + tp.pinThreads(threadList, 0); + // Verify thread affinity for each thread + for (int i = 0; i < n; ++i) { + checkThreadAffinity(threads[i]); + } + std::cout << "Pinning threads using core pin strategy" << std::endl; + // pin threads using the core strategy + tp.pinThreads(threadList, 1); + // Verify thread affinity for each thread + for (int i = 0; i < n; ++i) { + checkThreadAffinity(threads[i]); + } + + std::cout << "Pinning threads using logical pin strategy" << std::endl; + // pin threads using the Logical strategy + tp.pinThreads(threadList, 2); + // Verify thread affinity for each thread + for (int i = 0; i < n; ++i) { + checkThreadAffinity(threads[i]); + } + // Join all threads + for (auto& th : threads) { + th.join(); + } + + return 0; +} diff --git a/SDK/Include/Au/Au.hh b/SDK/Include/Au/Au.hh new file mode 100644 index 0000000..a7e5e75 --- /dev/null +++ b/SDK/Include/Au/Au.hh @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include "Au/Config.h" + +#include "Au/Defs.hh" +#include "Au/Types.hh" + +#include +#include +#include + +namespace Au { + +#if defined(__GNUC__) || defined(CLANG) || defined(AU_TARGET_OS_IS_WINDOWS) + +template +String +formatter(Args&&... args) +{ + std::stringstream oss; + // using fold expression + (oss << ... << args); + return oss.str(); +} + +#else + +String +formatter(const char* format, ...) printf(format, __VA_ARGS__); + +String +va_formatter(const char* format, va_list ap) vprintf(format, ap); + +String +va_formatter(const char* format, va_list ap) vprintf(format, ap); +#endif + +} // namespace Au diff --git a/SDK/Include/Au/BitMap.hh b/SDK/Include/Au/BitMap.hh new file mode 100644 index 0000000..c2ad43f --- /dev/null +++ b/SDK/Include/Au/BitMap.hh @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include "Au/Au.hh" +#include "Types.hh" + +#include +#include +#include +#include +#include + +namespace Au { + +class BitMap +{ + public: + /** + * @brief Returns the number of bits set + * + * @param + * + * @return A count of all the bits that are set in the bit mask + */ + Uint32 count() const; + + /** + * @brief Size of the bitmask + * (total number of bits that can be represented) + * + * @return Total number of bits + */ + Uint32 size() const; + + /** + * @brief Set all bits in the bitmap + * + * @param + * + * @return none + */ + void set(); + + /** + * @brief Set a specific bit in the bitmap + * + * @details Provided bit position should be less than size() + * + * @param[in] bitpos Bit position that needs to be set + * if the bit is already set, no action will be taken + * if the bit is clear, it will be set + * + * @return none + */ + void set(Uint32 bitpos); + + /** + * @brief Set all the bits in the provided bitmap + * + * @detail Can copy from another only if the size of source is less + * than or equal to that of current bitmap + * + * @param[in] other Bitmap which works as bits to set, cleared bits + * not cleared in 'this', irrespective of size of + * 'other', extra bits are ignored if larger. + * + * @return none + */ + void set(BitMap const& other); + + /** + * @brief Check if a given bitpos is set + * + * @param[in] bitpos Bit position that needs to be checked for set + * + * @return none + */ + bool isSet(Uint32 bitpos) const; + + /** + * @brief Check if a given bitpos is clear + * + * @param[in] bitpos Bit position that needs to be checked for clear + * + * @return none + */ + bool isClear(Uint32 bitpos) const; + + /** + * @brief Clear all bits of a bitmask + * + * @param None + * + * @return None + */ + void clear(); + + /** + * @brief Clear a specific bit in the bitmap + * + * @param[in] bitpos Bit position of the bit that + * will be cleared, if the bit is + * already 0, no action is done + * + * @return none + */ + void clear(Uint32 bitpos); + + /** + * @brief Clear a specific bit in the bitmap + * + * @detail The other.size() should be less or equal + * to that of this->size() + * + * @param[in] other Bitmap which works as bits to clear, cleared bits are + * ignored, irrespective of size of 'other', extra bits + * are ignored if larger. + * @return none + */ + void clear(BitMap const& other); + + /** + * @brief Flip all bits of a bitmask + * + * @param + * + * @return none + */ + void flip(); + + /** + * @brief Clear a specific bit in the bitmap + * + * @param[in] bitpos Bit position of the bit that will be cleared, if the + * bit is already 0, no action is done + * + * @return none + */ + void flip(Uint32 bitpos); + + /** + * @brief Clear a specific bit in the bitmap + * + * @detail The other.size() should be less or equal + * to that of this->size() + * + * @param[in] other Bitmap which works as bits to flip, no + * restriction on the size of bits if the bitmap is + * equal or less in size, the rest of of the bits + * in 'this' are untouched, if the bitmap is larger + * in size the rest of bits in 'other' are ignored + * @return none + */ + void flip(BitMap const& other); + + /** + * @brief Check if this bitmap is all zeroes + */ + bool isZero() const; + + /** + * @brief Check if this bitmap is all ones + */ + bool isFull() const; + + /** + * @brief Check if 'other' is a subset of 'this' + */ + bool isSubset(BitMap const& other); + + public: /* Operators */ + BitMap& operator|(BitMap const& other); + BitMap& operator&(BitMap const& other); + BitMap& operator^(BitMap const& other); + bool operator==(BitMap const& other) const; + BitMap& operator!(); + + public: /* Iterator trait */ + BitMap& begin(); + BitMap& end(); + + public: + explicit BitMap(Uint32 size); + ~BitMap(); + + private: + using BitMapWordT = Uint64; + + /* Returns bits in a BitMapWordT */ + template>> + constexpr unsigned bitsPerWord() const + { + return std::numeric_limits::digits; + } + + /* All bits set to 1 in a given integer type, default BitMapWordT */ + template>> + constexpr T getAllSetMask() const + { + return std::numeric_limits::max(); + } + + /* returns [0..n] bits set in a word, i.e BitMapWordT */ + BitMapWordT getNBitMask(Uint32 n) const + { + return ((BitMapWordT)1 << n) - 1; + } + + /* Perform operation Set or Clear */ + void doSetOrClear(bool doclear); + + /* Perfor operation Set or Clear w.r.t a given BitMap */ + void doSetOrClear(BitMap const& other, bool doclear = false); + + /* Calculate word position and bit position in a word */ + std::pair getWordIdxPair(Uint32 bitpos) const + { + auto word_idx = bitpos / bitsPerWord(); + auto pos_in_word = bitpos % bitsPerWord(); + + return std::pair(word_idx, pos_in_word); + } + + inline bool isValidPos(Uint32 bitpos) const { return bitpos < m_size; } + + private: + Uint32 m_size; + Uint32 m_nwords; + /* TODO: replace eventually by Array */ + std::vector m_bit_words; + + mutable std::mutex m_lock; +}; + +} // namespace Au diff --git a/SDK/Include/Au/Buffer.hh b/SDK/Include/Au/Buffer.hh new file mode 100644 index 0000000..fa8ab9d --- /dev/null +++ b/SDK/Include/Au/Buffer.hh @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include "Au/BufferBase.hh" +#include "Au/Memory/BufferLocal.hh" +#include "Au/Memory/BufferView.hh" + +namespace Au::Memory { + +template +class Buffer final : protected BufferBase +{ + using valueT = T; + using pointerT = T*; + using constPointerT = const T*; + using referenceT = T&; + using constReferenceT = const T&; + + public: + pointerT allocate(std::size_t size, size_t alignment = 1); + void free(); +}; + +} // namespace Au::Memory diff --git a/SDK/Include/Au/BufferBase.hh b/SDK/Include/Au/BufferBase.hh new file mode 100644 index 0000000..dafc41c --- /dev/null +++ b/SDK/Include/Au/BufferBase.hh @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#pragma once + +#include "Au/Au.hh" +#include "Au/Interface/IBuffer.hh" +#include "Au/Pattern/DisableMoveCopy.hh" + +namespace Au::Memory { + +template +class BufferView; + +template +class BufferBase + : public IBuffer + , public DisableCopyMove +{ + using valueT = T; + using pointerT = T*; + using constPointerT = const T*; + using referenceT = T&; + using constReferenceT = const T&; + + public: + BufferBase(pointerT ptr, size_t size) + : m_size{ size } + , m_ptr{ ptr } + { + } + + virtual ~BufferBase(); + + BufferBase(const BufferBase&) = delete; + BufferBase& operator=(const BufferBase&) = delete; + + public: + // void copyFrom(); + + /** + * @brief return a pointer to byte sized memory + * @param N/A + * + * @return byte * A pointer to location of byte 0 + */ + pointerT ptr() { return m_ptr; } + constPointerT ptr() const { return m_ptr; } + + /** + * @brief clear the contents pointed m_ptr + * @return none + */ + void erase(); + + /** + * @brief */ + BufferView getRange(size_t offset, size_t size) const; + + constPointerT const data() const { return m_ptr; } + pointerT data() { return m_ptr; } + size_t size() const { return m_size; } + + size_t len() const { return m_size * sizeof(valueT); } + bool isAllocated() const { return m_ptr != nullptr && m_size != 0; } + + operator valueT*() const { return m_ptr; } + + private: + size_t m_size = 0; + pointerT m_ptr; // = nullptr; +}; + +template +BufferBase::~BufferBase() +{ +} + +} // namespace Au::Memory diff --git a/SDK/Include/Au/Cpuid/CacheInfo.hh b/SDK/Include/Au/Cpuid/CacheInfo.hh new file mode 100644 index 0000000..ec312a9 --- /dev/null +++ b/SDK/Include/Au/Cpuid/CacheInfo.hh @@ -0,0 +1,262 @@ +/* + * Copyright (C) 2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include "Au/Defs.hh" + +#include "Au/Au.hh" +#include "Au/Types.hh" + +#include +#include + +namespace Au { + +namespace cache_attr { + /** + * \enum WritePolicy + * \brief Cache policy. + */ + enum class EWritePolicy : Uint32 + { + WriteBack = 1, /**< Write back. */ + WriteThrough /**< Write through. */ + }; + + /** + * @enum AllocatePolicy + * @brief Cache allocation type. + */ + enum class EAllocatePolicy : Uint32 + { + ReadAllocate = 1, /**< Read allocate. */ + WriteAllocate /**< Write allocate. */ + }; + + /** + * @enum alc_cache_level_t + * @brief Cache levels. + */ + enum class ELevel + { + L1 = 1, /**< L1 cache.*/ + L2, /**< L2 cache.*/ + L3, /**< L3 cache.*/ + L4, /**< L4 cache.*/ + L5, /**< L5 cache.*/ + Unknown /**< Unknown cache.*/ + }; + + /** + * @enum alc_cache_type_t + * @brief Cache types. + */ + enum class EType + { + ICache = 1, /**< Instruction Cache. */ + DCache, /**< Data Cache. */ + Unified, /**< Unified Cache. */ + Unknown /**< Unable to determine. */ + }; +} // namespace cache_attr + +std::ostream& +operator<<(std::ostream& os, cache_attr::ELevel const& lvl); + +std::ostream& +operator<<(std::ostream& os, cache_attr::EWritePolicy const& lvl); + +std::ostream& +operator<<(std::ostream& os, cache_attr::EAllocatePolicy const& lvl); + +std::ostream& +operator<<(std::ostream& os, cache_attr::EType const& lvl); + +/** + * \class CacheInfo + * \brief Class to get cache info. + * + * Details include core size, type, level, line size, number of ways. + */ +class CacheInfo +{ + public: + using CacheLevel = cache_attr::ELevel; + using CacheType = cache_attr::EType; + + /** + * @brief Constructor + * @param[in] level Cache level. + * @param[in] type Cache type. + * + */ + CacheInfo(CacheLevel level, CacheType type); + + /** + * @brief Get Cache size (Kb) based on Cache Level and Cache Type. + * + * @param[in] level Cache level. + * @param[in] type Cache type. + * + * @return Returns cache size in Kb. + */ + size_t getSize() const { return m_size; } + + /** + * @brief Get number of ways to access Cache based on Cache Level and + * Cache Type. + * + * Ex: 4-way cache will have 4 cache blocks. + * + * @return Returns number of ways to access Cache. + */ + Uint64 getWay() const { return m_way; } + + /** + * @brief Get cache line size (in bytes) to access Cache based on + * Cache Level and Cache Type. + * + * Ex: 4-way cache will have 4 cache blocks. Each block size is called + * as cache line size. + * + * @return Returns cache line size. + */ + Uint64 getLane() const { return m_lane; } + + /** + * @brief + * FIXME: Documentation + */ + CacheLevel getLevel() const { return m_level; } + + /** + * @brief + * FIXME: Documentation + */ + CacheType getType() const { return m_type; } + + /** + * @brief + * FIXME: Documentation + */ + Uint64 getSets() const { return m_set; } + + friend bool operator==(CacheInfo const& a, CacheInfo const& b) + { + return a.m_level == b.m_level && a.m_type == b.m_type; + } + + /** + * @brief Set Cache level based on the information from cpuid instruction. + * @param[in] lvl Cache level. + * + * @return void + */ + void setLevel(CacheLevel lvl); + + /** + * @brief Set Cache type based on the information from cpuid instruction. + * @param[in] ct Cache type. + * + * return void + */ + void setType(CacheType ct); + + /** + * @brief Set Cache size based on the number of ways partitions lanes and + * sets. + * @param[in] size Cache size. + * + * return void + */ + void setSize(Uint64 size); + + /** + * @brief Set Cache way based on the information from the cpuid instruction. + * @param[in] way_size Cache way size. + * + * return void + */ + void setWay(Uint64 way_size); + + /** + * @brief Set Cache lane based on the information from the cpuid + * instruction. + * @param[in] lane_size Cache lane size. + * + * return void + */ + void setLane(Uint64 lane_size); + + /** + * @brief Set Cache sets based on the information from the cpuid + * instruction. + * @param[in] sets Cache sets. + * + * return void + */ + void setSets(Uint64 sets); + + private: + CacheLevel m_level; /**< Identifies the cache level - L1/L2/L3. */ + CacheType m_type; /**< Identifies as D-cache, I-cache, etc.. */ + Uint64 m_size = 0; /**< Cache size in bytes. */ + Uint64 m_set = 0; /**< Cache number of sets. */ + Uint64 m_lane = 0; /**< Cache line size in bytes. */ + Uint64 m_way = 0; /**< Cache number of ways. */ + + /* TODO: add support for the following if needed */ + // uint64_t m_partitions; /**< Cache physical line partitions + // uint8_t m_associativity; /**< 1 = fully associative cache + // uint8_t m_self_initialization; /**< 1 = Cache is self initializing; + // cache does not need + // software initialization + // +}; + +class AUD_API_EXPORT CacheView final +{ + public: + using member = std::vector; + + CacheView() + : m_cache_info_list{} + { + } + + size_t getNumLevels() const { return m_cache_info_list.size(); } + + const member::iterator begin() { return m_cache_info_list.begin(); } + const member::iterator end() { return m_cache_info_list.end(); } + + private: + std::vector m_cache_info_list; +}; + +} // namespace Au diff --git a/SDK/Include/Au/Cpuid/Cpuid.hh b/SDK/Include/Au/Cpuid/Cpuid.hh new file mode 100644 index 0000000..2382841 --- /dev/null +++ b/SDK/Include/Au/Cpuid/Cpuid.hh @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#pragma once + +#include "Au/Au.hh" +#include "Au/Interface/Cpuid/ICpu.hh" + +#include + +namespace Au { + +#define AU_CPUID_OVERRIDE "AU_CPUID_OVERRIDE" + +/** + * @brief placeholder for ICpu, to return 'something' + * */ +class CpuInfo : public ICpu +{ + public: + explicit CpuInfo(CpuNumT idx); + + virtual ~CpuInfo() {} + + /** + * @brief Interface to get Freqency scaling governer + * + * @return EGoverner type + */ + virtual EGoverner getGoverner() const override = 0; + + public: + /* FIXME: All the virtual from ICpu */ + virtual String getFreq() const override { return "Unknown-Freq"; } + + virtual String getName() const override { return "Unknown-Name"; } + + virtual String getModel() const override { return "Unknown-Model"; } + + virtual CpuNumT getLogicalIdx() const override { return 0; } + + virtual CpuNumT getPhysicalIdx() const override { return 0; } + + virtual Uint32 getNumCores() const override { return 0; } + + protected: + void setLogicalIdx(CpuNumT physicalId) { m_physical_core_num = physicalId; } + + void setPhysicalIdx(CpuNumT logicalId) { m_logical_core_num = logicalId; } + + private: + CpuNumT m_logical_core_num; + CpuNumT m_physical_core_num; +}; + +} // namespace Au diff --git a/SDK/Include/Au/Cpuid/CpuidUtils.hh b/SDK/Include/Au/Cpuid/CpuidUtils.hh new file mode 100644 index 0000000..a015bef --- /dev/null +++ b/SDK/Include/Au/Cpuid/CpuidUtils.hh @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include "Au/Au.hh" +#include "Au/Cpuid/CacheInfo.hh" +#include "Au/Types.hh" + +#include +#include + +namespace Au { +/* ID return values */ +struct CpuidRegs +{ + Uint32 eax; + Uint32 ebx; + Uint32 ecx; + Uint32 edx; + + bool operator==(CpuidRegs const& Reg) const + { + return eax == Reg.eax && ebx == Reg.ebx && ecx == Reg.ecx + && edx == Reg.edx; + } + + /* following is required for making this key in a std::map */ + bool operator<(CpuidRegs const& Reg) const + { + /* Windows requires all comparators to follow strict weak ordering. + * The below definition follows the constraint. + * Note: The overflow that might occur doesn't affect the usecase, + * as this is used for the ordering of keys in the map and the order + * is insignificant. + */ + return eax + ebx + ecx + edx < Reg.eax + Reg.ebx + Reg.ecx + Reg.edx; + } + + CpuidRegs const operator&(CpuidRegs const& Reg) const + { + return { + (eax & Reg.eax), (ebx & Reg.ebx), (ecx & Reg.ecx), (edx & Reg.edx) + }; + } +}; +using RequestT = const CpuidRegs; +using ResponseT = CpuidRegs; + +using CacheLevel = CacheInfo::CacheLevel; +using CacheType = CacheInfo::CacheType; +/** + * @enum Vendor + * @brief CPU vendors. + */ +enum class EVendor : Uint32 +{ + Amd = 1, /**< AMD. */ + Intel, /**< Intel. */ + Other /**< Others. */ +}; + +/* Processor family info */ +enum class EFamily : Uint16 +{ + Unknown = 0x0, + Zen = 0x17, + Zen_Plus = 0x17, + Zen2 = 0x17, + Zen3 = 0x19, + Zen4 = 0x19, + Zen5 = 0x1A, + Max = 0x1A, /* Always set to latest family ID */ +}; + +class CpuidUtils +{ + public: + virtual ~CpuidUtils() {} + /** + * \brief Function to query CPUID instruction based on EAX input + * parameter. + * + * Function which has assembly code to query CPUID instruction + * based on EAX input value. EAX should have valid value to + * get CPUID information and other EBX, ECX, EDX should have 0s. + * In some cases, ECX also will have valid values. + * + * \param[in] req Request structure containing EAX, EBX, ECX, EDX values. + * \param[out] resp regs pointer which has EAX, EBX, ECX, EDX values. + */ + virtual ResponseT __raw_cpuid(RequestT& req); + /** + * \brief Get CPU Vendor info from CPUID instruction. + * + * It identifies AMD and Intel Cpus. Tags anyother vendor as Other. + * + * \param[in] ResponseT The CPUID Register Data. + * @return The EVendor [AMD, Intel or Other] + */ + EVendor getMfgInfo(ResponseT const& regs); + /** + * \brief Get Family ID from given 32-bit input value. + * + * Family[7:0] = (ExtendedFamily[7:0] + {0000b,BaseFamily[3:0]}) + * where ExtendedFamily[7:0] = var[27:20], BaseFamily[3:0] = var[11, 8] + * + * \param[in] var 32-bit value. + * + * \return Returns Family ID value. + * Note: Returns the minimum value of the family ID. + * Eg: Zen, ZenPlus and zen2 has same family ID. even if the CPU belongs to + * the Zen2 family, it returns Zen2 the function return Zen + */ + EFamily getFamily(Uint32 var); + /** + * \brief Get Model number from given input value. + * + * Model[7:0] = {ExtendedModel[3:0],BaseModel[3:0]} + * where ExtendedModel[3:0] = var[29:16], BaseModel[3:0] = var[7, 4] + * + * \param[in] var 32-bit value. + * + * \return Returns Model number value. + */ + Uint16 getModel(Uint32 var); + /** + * \brief Get Stepping ID from given input value. + * + * Get Stepping ID from given input value. + * Model[7:0] = {ExtendedModel[3:0],BaseModel[3:0]} + * where ExtendedModel[3:0] = var[29:16], BaseModel[3:0] = var[7, 4] + * For now, model number is stepping. TODO: need to revisit for each family. + * + * \param[in] var 32-bit value. + * + * \return Returns Stepping ID value. + */ + Uint16 getStepping(Uint32 var); + /** + * @details Issues the cpuid instruction using EAX/ECX gets response and + * checks a flag in appropriate register + * + * @param[in] expected Expected bit(s) to check + * + * @param[in] actual Actula value of E{A,B,C,D}X after 'cpuid' issued + * + * @return true if cpu has flag, false otherwise + */ + bool hasFlag(ResponseT const& expected, ResponseT const& actual); + void updateCacheView(CacheView& cView); + void updateCacheInfo(CacheInfo& cInfo, ResponseT const& resp); +}; +} // namespace Au diff --git a/SDK/Include/Au/Cpuid/Enum.hh b/SDK/Include/Au/Cpuid/Enum.hh new file mode 100644 index 0000000..3178db1 --- /dev/null +++ b/SDK/Include/Au/Cpuid/Enum.hh @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include "Au/Cpuid/CpuidUtils.hh" +#include "Au/Cpuid/X86Cpu.hh" + +namespace Au { + +#define alci Au +using Cpu = X86Cpu; +using Vendor = EVendor; +#define eIntel Intel +#define eAmd Amd +#define Other Other + +using Uarch = EUarch; + +#define eZen Zen +#define eZen2 Zen2 +#define eZen3 Zen3 +#define eZen4 Zen4 +#define eZen5 Zen5 +#define eOther Unknown + +#ifdef ALC_E_FLAG_SSSE3 +#undef ALC_E_FLAG_SSSE3 +#endif +#define ALC_E_FLAG_SSSE3 ECpuidFlag::sse3 + +#ifdef ALC_E_FLAG_AES +#undef ALC_E_FLAG_AES +#endif +#define ALC_E_FLAG_AES ECpuidFlag::aes + +#ifdef ALC_E_FLAG_AVX +#undef ALC_E_FLAG_AVX +#endif +#define ALC_E_FLAG_AVX ECpuidFlag::avx + +#ifdef ALC_E_FLAG_RDRAND +#undef ALC_E_FLAG_RDRAND +#endif +#define ALC_E_FLAG_RDRAND ECpuidFlag::rdrand + +#ifdef ALC_E_FLAG_TSC_ADJUST +#undef ALC_E_FLAG_TSC_ADJUST +#endif +#define ALC_E_FLAG_TSC_ADJUST ECpuidFlag::tsc_adjust + +#ifdef ALC_E_FLAG_AVX2 +#undef ALC_E_FLAG_AVX2 +#endif +#define ALC_E_FLAG_AVX2 ECpuidFlag::avx2 + +#ifdef ALC_E_FLAG_BMI2 +#undef ALC_E_FLAG_BMI2 +#endif +#define ALC_E_FLAG_BMI2 ECpuidFlag::bmi2 + +#ifdef ALC_E_FLAG_AVX512F +#undef ALC_E_FLAG_AVX512F +#endif +#define ALC_E_FLAG_AVX512F ECpuidFlag::avx512f + +#ifdef ALC_E_FLAG_AVX512DQ +#undef ALC_E_FLAG_AVX512DQ +#endif +#define ALC_E_FLAG_AVX512DQ ECpuidFlag::avx512dq + +#ifdef ALC_E_FLAG_RDSEED +#undef ALC_E_FLAG_RDSEED +#endif +#define ALC_E_FLAG_RDSEED ECpuidFlag::rdseed + +#ifdef ALC_E_FLAG_ADX +#undef ALC_E_FLAG_ADX +#endif +#define ALC_E_FLAG_ADX ECpuidFlag::adx + +#ifdef ALC_E_FLAG_AVX512_IFMA +#undef ALC_E_FLAG_AVX512_IFMA +#endif +#define ALC_E_FLAG_AVX512_IFMA ECpuidFlag::avx512ifma + +#ifdef ALC_E_FLAG_AVX512PF +#undef ALC_E_FLAG_AVX512PF +#endif +#define ALC_E_FLAG_AVX512PF ECpuidFlag::avx512pf + +#ifdef ALC_E_FLAG_AVX512ER +#undef ALC_E_FLAG_AVX512ER +#endif +#define ALC_E_FLAG_AVX512ER ECpuidFlag::avx512er + +#ifdef ALC_E_FLAG_AVX512CD +#undef ALC_E_FLAG_AVX512CD +#endif +#define ALC_E_FLAG_AVX512CD ECpuidFlag::avx512cd + +#ifdef ALC_E_FLAG_SHA +#undef ALC_E_FLAG_SHA +#endif +#define ALC_E_FLAG_SHA ECpuidFlag::sha_ni + +#ifdef ALC_E_FLAG_SHA_NI +#undef ALC_E_FLAG_SHA_NI +#endif +#define ALC_E_FLAG_SHA_NI ECpuidFlag::sha_ni + +#ifdef ALC_E_FLAG_AVX512BW +#undef ALC_E_FLAG_AVX512BW +#endif +#define ALC_E_FLAG_AVX512BW ECpuidFlag::avx512bw + +#ifdef ALC_E_FLAG_AVX512VL +#undef ALC_E_FLAG_AVX512VL +#endif +#define ALC_E_FLAG_AVX512VL ECpuidFlag::avx512vl + +#ifdef ALC_E_FLAG_AVX512_VBMI +#undef ALC_E_FLAG_AVX512_VBMI +#endif +#define ALC_E_FLAG_AVX512_VBMI ECpuidFlag::avx512vbmi + +#ifdef ALC_E_FLAG_AVX512_VPOPCNTDQ +#undef ALC_E_FLAG_AVX512_VPOPCNTDQ +#endif +#define ALC_E_FLAG_AVX512_VPOPCNTDQ ECpuidFlag::avx512_vpopcntdq + +#ifdef ALC_E_FLAG_AVXVNNI +#undef ALC_E_FLAG_AVXVNNI +#endif +#define ALC_E_FLAG_AVXVNNI ECpuidFlag::avxvnni + +#ifdef ALC_E_FLAG_VAES +#undef ALC_E_FLAG_VAES +#endif +#define ALC_E_FLAG_VAES ECpuidFlag::vaes + +#ifdef ALC_E_FLAG_VPCLMULQDQ +#undef ALC_E_FLAG_VPCLMULQDQ +#endif +#define ALC_E_FLAG_VPCLMULQDQ ECpuidFlag::vpclmulqdq + +#ifdef ALC_E_FLAG_AVX512_VNNI +#undef ALC_E_FLAG_AVX512_VNNI +#endif +#define ALC_E_FLAG_AVX512_VNNI ECpuidFlag::avx512_vnni + +#ifdef ALC_E_FLAG_AVX512_BITALG +#undef ALC_E_FLAG_AVX512_BITALG +#endif +#define ALC_E_FLAG_AVX512_BITALG ECpuidFlag::avx512_bitalg + +#ifdef ALC_E_FLAG_AVX512_VBMI2 +#undef ALC_E_FLAG_AVX512_VBMI2 +#endif +#define ALC_E_FLAG_AVX512_VBMI2 ECpuidFlag::avx512vbmi2 + +#ifdef ALC_E_FLAG_MOVDIRI +#undef ALC_E_FLAG_MOVDIRI +#endif +#define ALC_E_FLAG_MOVDIRI ECpuidFlag::movdiri + +#ifdef ALC_E_FLAG_MOVDIR64B +#undef ALC_E_FLAG_MOVDIR64B +#endif +#define ALC_E_FLAG_MOVDIR64B ECpuidFlag::movdir64b + +#ifdef ALC_E_FLAG_AVX512VPINTERSECT +#undef ALC_E_FLAG_AVX512VPINTERSECT +#endif +#define ALC_E_FLAG_AVX512VPINTERSECT ECpuidFlag::avx512_vpintersect + +#ifdef ALC_E_FLAG_X2AVIC +#undef ALC_E_FLAG_X2AVIC +#endif +#define ALC_E_FLAG_X2AVIC ECpuidFlag::x2avic + +#ifdef ALC_CPUID_FLAG_MAX +#undef ALC_CPUID_FLAG_MAX +#endif +#define ALC_CPUID_FLAG_MAX ECpuidFlag::Max + +} // namespace Au diff --git a/SDK/Include/Au/Cpuid/Platform.hh b/SDK/Include/Au/Cpuid/Platform.hh new file mode 100644 index 0000000..e69de29 diff --git a/SDK/Include/Au/Cpuid/X86Cpu.hh b/SDK/Include/Au/Cpuid/X86Cpu.hh new file mode 100644 index 0000000..14dfaa5 --- /dev/null +++ b/SDK/Include/Au/Cpuid/X86Cpu.hh @@ -0,0 +1,431 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#ifdef WIN32 +#include +#endif + +#include "Au/Cpuid/Cpuid.hh" +#include "Au/Cpuid/CpuidUtils.hh" +#include "Au/Interface/Cpuid/ICpu.hh" + +#include +#include +#include + +#define AUD_DEFINE_ENUM(name, type, ...) \ + enum class name : type \ + { \ + Min, \ + __VA_ARGS__, \ + Max, \ + }; \ + inline std::stringstream& operator<<(std::stringstream& os, \ + std::vector values) \ + { \ + String str = #__VA_ARGS__; \ + std::map flags; \ + Uint64 flagsCounter = 1; \ + std::stringstream ss(str); \ + String token; \ + std::getline(ss, token, ','); \ + flags[token] = flagsCounter++; \ + while (std::getline(ss, token, ',')) { \ + token = token.substr(1, token.length() - 1); \ + flags[token] = flagsCounter++; \ + } \ + for (auto value : values) { \ + os << flags[value] << ":"; \ + } \ + return os; \ + } + +namespace Au { + +/* Processor Micro architecure info */ +enum class EUarch : Uint16 +{ + Unknown = 0, + Zen, + ZenPlus, + Zen2, + Zen3, + Zen4, + Zen5, + Max = Zen5, +}; + +/** + * @struct VendorInfo + * + * @brief CPU core info. + */ +class VendorInfo +{ + /* TODO: Make this private and provide accessors */ + public: + EVendor m_mfg; /**< CPU manufacturing vendor. */ + EFamily m_family; /**< CPU family ID. */ + Uint16 m_model; /**< CPU model number. */ + Uint16 m_stepping; /**< CPU stepping. */ + EUarch m_uarch; /**< CPU microarchitecture. */ +}; + +/** + * @enum ECpuidFlag + * + * @brief Flags supported by CPU as features. + */ +AUD_DEFINE_ENUM(ECpuidFlag, + Uint64, + sse3, + pclmulqdq, + dtes64, + monitor, + dscpl, + vmx, + smx, + est, + tm2, + ssse3, + cid, + fma, + cx16, + xtpr, + pdcm, + pcid, + dca, + sse4_1, + sse4_2, + x2apic, + movbe, + popcnt, + tsc_deadline, + aes, + xsave, + osxsave, + avx, + f16c, + rdrand, + hypervisor, + fpu, + vme, + de, + pse, + tsc, + msr, + pae, + mce, + cx8, + apic, + sep, + mtrr, + pge, + mca, + cmov, + pat, + pse36, + pn, + clflush, + ds, + acpi, + mmx, + fxsr, + sse, + sse2, + ss, + ht, + tm, + ia64, + pbe, + arat, + fsgsbase, + tsc_adjust, + bmi1, + hle, + avx2, + smep, + bmi2, + erms, + invpcid, + rtm, + mpx, + avx512f, + avx512dq, + rdseed, + adx, + smap, + avx512ifma, + pcommit, + clflushopt, + clwb, + avx512pf, + avx512er, + avx512cd, + sha_ni, + avx512bw, + avx512vl, + avx512vbmi, + umip, + pku, + ospke, + avx512_vpopcntdq, + la57, + rdpid, + avx512_4vnniw, + avx512_4fmaps, + avx512_bf16, + avxvnni, + xsaveopt, + xsavec, + xgetbv1, + xsaves, + lahf_lm, + cmp_legacy, + svm, + extapic, + cr8legacy, + abm, + sse4a, + misalignsse, + _3dnowprefetch, + osvw, + ibs, + xop, + skinit, + wdt, + lwp, + fma4, + tce, + nodeid_msr, + tbm, + topoext, + perfctr_core, + perfctr_nb, + syscall, + nxxd, + mmxext, + fxsr_opt, + pdpe1gb, + rdtscp, + lmi64, + _3dnowext, + _3dnow, + invtsc, + npt, + lbrv, + svm_lock, + nrip_save, + tsc_scale, + vmcb_clean, + flushbyasid, + decodeassists, + pause_filter, + pfthreshold, + xstore, + xstore_en, + xcrypt, + xcrypt_en, + ace2, + ace2_en, + phe, + phe_en, + pmm, + pmm_en, + vaes, + vpclmulqdq, + avx512_vnni, + avx512_bitalg, + avx512vbmi2, + movdiri, + movdir64b, + avx512_vpintersect, + x2avic) + +class AUD_API_EXPORT X86Cpu final : public CpuInfo +{ + public: + X86Cpu(CpuidUtils* cUtils, CpuNumT num); + /** + * @brief Default constructor. + * + * @return None + * + * @note Default behaviour is invoked by passing AU_CURRENT_CPU_NUM, + * In default behaviour the thread is not pinned to any core, + * cpuid fetches the current thread on which the code is running. + */ + X86Cpu(CpuNumT num = AU_CURRENT_CPU_NUM); + ~X86Cpu(); + + /** + * @brief Check if vendor is AMD + * + * @return true if 'num' was an AMD x86-64, false otherwise + */ + bool isAMD() const; + + /** + * @brief Checks if processor is x86_64-v2 compliant + * + * @details Based on GCC following flags account for x86_64-v2 + * + * cx16 lahf_lm + * popcnt sse4_1 + * sse4_2 ssse3 + * + * @param none + * + * @return true if cpu supports all features above, + * false otherwise + */ + bool isX86_64v2() const; + /** + * @brief Checks if processor is x86_64-v3 compliant + * + * @details Based on GCC following flags account for x86_64-v3 + * + * (in addition to x86_64-v2) + * + * avx avx2 bmi1 + * bmi2 f16c fma + * abm movbe xsave + * + * @param none + * + * @return true if cpu supports all features above, + * false otherwise + */ + bool isX86_64v3() const; + /** + * @brief Checks if processor is x86_64-v4 compliant + * + * @details Based on GCC following flags account for x86_64-v4 + * + * (in addition to x86_64-v2 + x86_64-v3) + * avx512f avx512bw avx512cd + * avx512dq avx512vl + * + * @param none + * + * @return true if cpu supports all features above, + * false otherwise + */ + bool isX86_64v4() const; + + /** + * @brief Check if vendor is Intel + * + * @param none + * + * @return true if 'num' was an Intel x86-64, false otherwise + */ + bool isIntel() const; + + /** + * @brief Check if a given x86 cpu has a needed flag + * + * @param[in] eflag ECpuidFlag that needs to be checked + * + * @return true if eflag is present in the availableflags and usable + * flags, false otherwise + */ + bool hasFlag(ECpuidFlag const& eflag) const; + + /** + * @brief Check if a given x86 cpu has a needed flag + * + * Note: The api is deprecated. Use hasFlag instead. + * + * @param[in] eflag ECpuidFlag that needs to be checked + * + * @return true if eflag is present in the availableflags and usable + * flags, false otherwise + */ +#ifdef AU_WARN_DEPRECATION + [[deprecated("Use hasFlag instead.")]] bool +#else + bool +#endif + isAvailable(ECpuidFlag const& eflag) const; + + /** + * @brief Get microarchitecture of CPU from CPUID instruction. + * + * @param none + * + * @return Returns microarchitecture of CPU. + */ + EUarch getUarch() const; + + /** + * @brief Checks microarchitecture from CPUID instruction and compare + * with input Like Zen, Zen2, Zen3 etc. + * + * @param[in] arch Microarchitecture input to check for. + * @param[in] strict If true, then exact match is checked. + * + * @return Returns true if CPU microarchitecture is matched with input. + */ + bool isUarch(EUarch uarch, bool strict = false) const; + + /** + * @brief Get the VendorInfo object + * + * @param none + * + * @return VendorInfo + */ + VendorInfo getVendorInfo() const; + + /** + * @brief Re-read all the cpuid functions and upate internal structures + * + * @param none + * + * @return none + */ + void update(); + + virtual EGoverner getGoverner() const override + { + return EGoverner::eUnknown; + } + + CacheView getCacheView() const; + + private: + class Impl; + const Impl* pImpl() const { return m_pimpl.get(); } + Impl* pImpl() { return m_pimpl.get(); } + std::unique_ptr m_pimpl; +}; + +} // namespace Au diff --git a/SDK/Include/Au/Defs.hh b/SDK/Include/Au/Defs.hh new file mode 100644 index 0000000..166419c --- /dev/null +++ b/SDK/Include/Au/Defs.hh @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2022-2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +/** + * @brief AUD_ALIGNED() macro + * Helps to mark a variable aligned + */ +#if defined(_MSC_VER) +#define AUD_ALIGNED(x) __declspec(align(x)) +#else +#if defined(__GNUC__) || defined(CLANG) +#define AUD_ALIGNED(x) __attribute__((aligned(x))) +#endif +#endif + +/** + * @brief AU_MUST_USE_RETURN + * Attribute to mandate use of return values. + */ +#if defined(_MSC_VER) +#define AUD_MUST_USE_RETURN +#else +#define AUD_MUST_USE_RETURN [[nodiscard]] +#endif + +/** + * @brief AUD_OFFSET_OF() macro + * Helps to mark a function, variable, parameter as unused + */ +#define AUD_OFFSET_OF(type, field) \ + (reinterpret_cast( \ + reinterpret_cast(&(reinterpret_cast(10)->field))) \ + - 10) + +/** + * @brief AUD_UNUSED() macro + * Helps to mark a function, variable, parameter as unused + */ +#if defined(_MSC_VER) +#define AUD_UNUSED(x) ((void)(x)) +#else +#if defined(__GNUC__) || defined(CLANG) +#define AUD_UNUSED(x) __attribute__((unused)) +#endif +#endif + +/** + * dllexport helps to explicitly export symbols on Windows. + * Therefore, any new API's must first be declared with ALCP_API_EXPORT to load + * on Windows. + */ +#if defined(WIN32) || defined(_MSC_VER) +#define AUD_API_EXPORT __declspec(dllexport) +#else +#define AUD_API_EXPORT +#endif + +/* + * Some class Constroctor (CTOR) and + * Destructor(DTOR) helper macros, to be readable + */ + +#ifndef AUD_DISABLE_COPY_CTOR +#define AUD_DISABLE_COPY_CTOR(CLASS_NAME) CLASS_NAME(const CLASS_NAME&) = delete +#endif + +#ifndef AUD_DISABLE_MOVE_CTOR +#define AUD_DISABLE_MOVE_CTOR(CLASS_NAME) CLASS_NAME(CLASS_NAME \ &&) = delete +#endif + +#ifndef AUD_DISABLE_MOVE_ASSIGNMENT +#define AUD_DISABLE_MOVE_ASSIGNMENT(CLASS_NAME) \ + CLASS_NAME& operator=(CLASS_NAME&&) = delete +#endif + +#ifndef AUD_DISABLE_ASSIGNMENT +#define AUD_DISABLE_ASSIGNMENT(CLASS_NAME) \ + CLASS_NAME& operator=(const CLASS_NAME&) = delete +#endif + +// Disable the copy constructor and assignment operator +// Useful macro to simply do the necessary in a single line +#ifndef AUD_DISABLE_COPY_AND_ASSIGNMENT +#define AUD_DISABLE_COPY_AND_ASSIGNMENT(CLASS_NAME) \ + AUD_DISABLE_COPY_CTOR(CLASS_NAME); \ + AUD_DISABLE_ASSIGNMENT(CLASS_NAME) +#endif + +// Disable the copy CTOR and assignment operator +// Useful macro to simply do the necessary in a single line +#ifndef AUD_DEFAULT_COPY_AND_ASSIGNMENT +#define AUD_DEFAULT_COPY_AND_ASSIGNMENT(CLASS_NAME) \ + CLASS_NAME(const CLASS_NAME&) = default; \ + CLASS_NAME& operator=(const CLASS_NAME&) = default +#endif + +#define AUD_CONCAT_TOKEN(a, b, c) AUD_CONCAT_TOKEN_IMPL(a, b, c) +#define AUD_CONCAT_TOKEN_IMPL(a, b, c) a##b##c + +#define AUD_STRINGIZE(x) #x + +// Switching off clang-format as the formatter +// clubs the '~' with CLASS_NAME, +// clang-format off +#ifndef AUD_DEFAULT_CTOR +#define AUD_DEFAULT_CTOR(CLASS_NAME) \ + CLASS_NAME () = default +#endif + +#ifndef AUD_DEFAULT_DTOR +#define AUD_DEFAULT_DTOR(CLASS_NAME) \ + ~ CLASS_NAME () = default +#endif + +#ifndef AUD_DEFAULT_CTOR_DTOR +#define AUD_DEFAULT_CTOR_AND_DTOR(CLASS_NAME) \ + AUD_DEFAULT_CTOR(CLASS_NAME); \ + AUD_DEFAULT_DTOR(CLASS_NAME) +#endif + +#ifndef AUD_DEFAULT_CTOR_AND_VIRTUAL_DTOR +#define AUD_DEFAULT_CTOR_AND_VIRTUAL_DTOR(CLASS_NAME) \ + CLASS_NAME () = default; \ + virtual ~ CLASS_NAME() {} +#endif + +#ifndef AUD_VIRTUAL_DTOR +#define AUD_VIRTUAL_DTOR(CLASS_NAME) \ + virtual ~ CLASS_NAME() = 0; +#endif + +#ifndef AUD_DEFAULT_MOVE_CTOR +#define AUD_DEFAULT_MOVE_CTOR(CLASS_NAME) \ + CLASS_NAME(CLASS_NAME &&) = default; +#endif + +#ifndef AUD_DECLARE_CTOR +#define AUD_DECLARE_CTOR(CLASS_NAME) \ + CLASS_NAME () +#endif + +#ifndef AUD_DECLARE_DTOR +#define AUD_DECLARE_DTOR(CLASS_NAME) \ + ~ CLASS_NAME () +#endif + + +#ifndef AUD_DECLARE_CTOR_AND_DTOR +#define AUD_DECLARE_CTOR_AND_DTOR(CLASS_NAME) \ + AUD_DECLARE_CTOR(CLASS_NAME); \ + AUD_DECLARE_DTOR(CLASS_NAME) +#endif + +// clang-format on diff --git a/SDK/Include/Au/DynamicLoader.hh b/SDK/Include/Au/DynamicLoader.hh new file mode 100644 index 0000000..616b34c --- /dev/null +++ b/SDK/Include/Au/DynamicLoader.hh @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include "Au/Au.hh" +#include "Status.hh" +#include "Types.hh" + +#include "Au/Pattern/DisableMoveCopy.hh" + +#include +#include +#include + +namespace Au { + +class DynamicLibrary : public DisableCopyMove +{ + public: + /** + * @brief constructor + * @param[in] path indicating + * + * @return none + */ + DynamicLibrary(String const& path); + + virtual ~DynamicLibrary(); + + /** + * @brief check if a symbol exists + * @param[in] name indicating name of a symbol + * + * @return true if symbol exists + */ + bool hasSymbol(String const& name); + + /** + * @brief Get address of a function symbol + * @param[in] name name of the function to search + * + * @return void* handle + */ + void* getSymbol(String const& name); + + /** + * @brief Get suffix of filename + * @return String of filename suffix like .dll or .so + */ + String getSuffix() const; + + /** + * @brief return path of the Dynamic Library + * @return path as + */ + std::filesystem::path const path() const { return m_path; } + + /** + * @brief get name of the library + * + * @return String name of the library (filename with extension) + */ + String name() const { return m_path.filename().string(); } + + /** + * @brief Load this library + * + * @return Status returns appropriate errors defined in + * DynamicLoaderError.hh + */ + Status load() const; + + /** + * @brief Unload this library + * + * @return none + */ + void unload() const; + + private: + class Impl; + std::filesystem::path m_path; + std::unique_ptr m_pimpl; + + private: + Impl* pImpl() { return m_pimpl.get(); } + Impl const* pImpl() const { return m_pimpl.get(); } +}; + +class DynamicLoader : public DisableCopyMove +{ + public: + enum class Flags : Uint16 + { + eNone, + eIgnoreVersion, + }; + + public: + DynamicLoader(); + ~DynamicLoader(); + + /** + * @brief Load a dynamic library + * @details + * @param[in] dll A DynamicLibrary object + */ + Status load(DynamicLibrary const* dll); + + /** + * @brief Load dynamiclibrary with flags + * @detail + * @param[in] path path of the library + * @param[in] flags Flag from the above + * + * @return Status + */ + Status load(DynamicLibrary const& path, Flags const flags[]); + + /** + * @brief unload a library + * + * @return none + */ + Status unload(DynamicLibrary const& dll); + + /** + * @brief Query if a library is loaded + * @param[in] DynamicLibrary object checked if loaded + * + * @return true if library is loaded, false otherwise + */ + bool isLoaded(DynamicLibrary const& dll) const; + + private: + std::list m_dyn_lib_list; + mutable std::mutex m_lock; + +#if 0 + class Impl; + std::unique_ptr m_pimpl; + Impl* pImpl() { return m_pimpl.get(); } + Impl const* pImpl() const { return m_pimpl.get(); } +#endif +}; + +} // namespace Au diff --git a/SDK/Include/Au/Environ.hh b/SDK/Include/Au/Environ.hh new file mode 100644 index 0000000..95edd2b --- /dev/null +++ b/SDK/Include/Au/Environ.hh @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2022-2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include "Au/Au.hh" + +#include +#include +#include + +namespace Au { + +class Environ +{ + public: + AUD_DECLARE_CTOR_AND_DTOR(Environ); + void init(const char** envp); + + public: + /** + * @brief 'get' usual getter functions, retrieves the environment + * variable's value + * + * @param[in] key Readonly reference to a String like object + * + * @return String Environtment Variables value or a null string + */ + StringView const get(StringView key) const; + // StringView get(StringView key) const; + + public: + /** + * @brief 'set' function will update if the key exists, creates + * new key-value pair otherwise + * + * @param[in] key Environment variable + * @param[in] value Environment variable's value + * + * @return nothing + */ + void set(String const& key, String const& value); + + /** + * @brief 'unset' a key in the user environment + * The modifications are limited to user-env + * + * @param[in] key name of the key to be unset + * + * return nothing + */ + void unset(String const& key); + + /** + * @brief search if a key exists in current environ + * + * @param key Environment variable key + * + * @return true if key exists + * false if not + */ + bool exists(StringView const& key) const; + + private: + void _set(String const& key, String const& val); + + using env_mapT = std::map>; + env_mapT m_environ; + mutable std::mutex m_lock; + const String m_empty_string{ "" }; +}; + +class Env +{ + + /** + * @brief Getters for the User Env and System Env + */ + static Environ& getUserEnv(); + static Environ& getSystemEnv(); + + public: + /** + * @brief Getter for environment variable + * + * @details The preference is given to UserEnv as it is subjected to + * modification if the key is not present in UserEnv then SystemEnv is + * searched + * + * @param[in] key Name of the key to get + * + * return StringView of the value for given 'key' + */ + static StringView const get(StringView const& key); + + /** + * @brief Setter for environment variable + * + * @details Only UserEnv is subjected to modification + * + * @param[in] key Name of the key to get + * @param[in] val Value of the environment variable + * + * return StringView of the value for given 'key' + */ + static void set(String const& key, String const& val); + + /** + * @brief Setter for environment variable + * + * @details Only UserEnv is subjected to modification + * + * @param[in] key Name of the key to get + * @param[in] val Value of the environment variable + * + * return StringView of the value for given 'key' + */ + static void unset(String const& key); + + /** + * @brief Initialize new UserEnv from a given array of string values + * + * @details Only UserEnv is subjected to modification + * + * @param[in] key Name of the key to get + * @param[in] val Value of the environment variable + * + * return StringView of the value for given 'key' + */ + static void init(const char** envp); +}; + +} // namespace Au diff --git a/SDK/Include/Au/Error.hh b/SDK/Include/Au/Error.hh new file mode 100644 index 0000000..a432488 --- /dev/null +++ b/SDK/Include/Au/Error.hh @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2022-2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "Au/Au.hh" +#include "Au/ErrorBase.hh" + +namespace Au { + +using ErrorCodeGeneric = Uint16; + +class GenericError final : public ErrorBase +{ + public: + GenericError(); + GenericError(ErrorCodeGeneric ecode); + + AUD_DEFAULT_DTOR(GenericError); + virtual String message() const override; + + protected: + virtual Uint16 getModuleId() const override { return 0; } +}; + +/* + * Easy to use creators + * usage: + * Status my_func() + * { + * return Status{Aborted("")}; + * } + */ +// clang-format off +IError const& Aborted(); +IError const& AlreadyExistsError(); +IError const& InternalError(); +IError const& InvalidArgumentError(); +IError const& NotFoundError(); +IError const& NotAvailableError(); +IError const& NotImplementedError(); +IError const& UnknownError(); +IError const& NoError(); + +} // namespace Au diff --git a/SDK/Include/Au/ErrorBase.hh b/SDK/Include/Au/ErrorBase.hh new file mode 100644 index 0000000..a43f0e6 --- /dev/null +++ b/SDK/Include/Au/ErrorBase.hh @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2022-2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "Au/Interface/IError.hh" +#include "Au/Types.hh" + +namespace Au { +/** + * @name ErrorBase + * @detail + * ErrorBase class is designed to work with different Error classes. + * The errors are extendable to support dynamic module loading (plugin system). + * + */ +class ErrorBase : public IError +{ + + public: + typedef Uint16 ModuleType; + + ErrorBase() + : m_error{ 0 } + { + } + + ErrorBase(Uint16 code) + : ErrorBase{} + { + m_error.field.module_error = code; + } + + ErrorBase(Uint64 code) + : m_error{ code } + { + } + + /** + * @brief Overriden function to return code as 64-bit integer + * @param none + * @return A combined Uint64 + */ + virtual Uint64 code() const override final { return m_error.val; } + + /** + * @brief Register a module specific error handler + * + * @param[in] mt Module type + * @param[in] ie Error Interface to the module error handler + * + * @return boolean Status of whether the registration was success + */ + static bool registerModuleError(ModuleType mt, IError& ie); + + protected: + ErrorBase(Uint16 module_id, Uint16 module_error) + : ErrorBase{} + { + m_error.field.module_id = module_id; + m_error.field.module_error = module_error; + } + + void setModuleError(Uint16 error) { m_error.field.module_error = error; } + Uint16 getModuleError() const { return m_error.field.module_error; } + + /** + * @brief Getter function for module id + * + * @return Module id of a particular module + */ + void setModuleId(Uint16 mid) { m_error.field.module_id = mid; } + + /** + * @brief virtual function to get derived class's module id + * + * @return an Uint16 compatible with module_id + */ + virtual Uint16 getModuleId() const { return m_error.field.module_id; }; + + virtual bool isEq(IError const& lhs, IError const& rhs) const override final + { + return lhs.code() == rhs.code(); + } + + protected: + union + { + Uint64 val; + + struct + { + Uint64 base_error : 16; + Uint64 module_error : 16; + Uint64 module_id : 16; + Uint64 __reserved : 16; + } field; + } m_error; + + // static std::unordered_map m_dispatcher_map; +}; +} // namespace Au diff --git a/SDK/Include/Au/Interface/Cpuid/ICpu.hh b/SDK/Include/Au/Interface/Cpuid/ICpu.hh new file mode 100644 index 0000000..d3bdf92 --- /dev/null +++ b/SDK/Include/Au/Interface/Cpuid/ICpu.hh @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include "Au/Au.hh" + +namespace Au { + +enum class EGoverner +{ + ePerformance, + ePowersave, + eUserspace, + eOndemand, + eUnknown +}; +std::ostream& +operator<<(std::ostream& os, const EGoverner& gov); + +#if defined(cpu_num_t) +typedef cpu_num_t CpuNumT; +#else +typedef Uint32 CpuNumT; +#endif + +/** + * Sample information that can be gathered + * + * Package Info: + * Sockets : 02 + * Cores : 10 (per socket) + * Threads : 04 (per core) + * + * CPU Info: + * Vendor : AMD + * Name : Ryzen 7 PRO 2700U w/ Radeon Vega Mobile Gfx + * Family : 0x17 (Zen/Zen+) + * Frequency : 1.8 GHz + * Governer : Performance + * Model : 12 (Zen+) + * Stepping : 0 + * ID : 0:2:3 (Socket:Core:Thread) + * + * Cache Info: + * L1 Cache (D) : + * L1 Cache (I) : 24 KB (2-way set-associative) + * L2 Cache (U) : 01 MB (fully associative) + * L3 Cache (U) : 32 MB (fully associative) + */ + +class AUD_API_EXPORT ICpu +{ + protected: + virtual ~ICpu(){}; + + public: + /** + * @brief Interface to get frequency + * + * @return String containing frequency of processor + */ + virtual String getFreq() const = 0; + + /** + * @brief Interface to get Name of processor + * + * @return Full name of the processor + */ + virtual String getName() const = 0; + + /** + * @brief Interface to get Model of processor + * + * @return String containing frequency of processor + */ + virtual String getModel() const = 0; + + /** + * @brief Interface to get numerical index, as seen by the Operating system + * + * @return Numerical identifier of given processor + */ + virtual CpuNumT getLogicalIdx() const = 0; + + /** + * @brief Interface to get numerical index, as assigned by Firmware/BIOS + * + * @return Numerical identifier as assigned by BIOS + */ + virtual CpuNumT getPhysicalIdx() const = 0; + + /** + * @brief Interface to get number of cores in this processor. + * + * @return Integer specifying number of cores. + */ + virtual Uint32 getNumCores() const = 0; + + /** + * @brief Interface to get Freqency scaling governer + * + * @return EGoverner type + */ + virtual EGoverner getGoverner() const = 0; +}; + +} // namespace Au diff --git a/SDK/Include/Au/Logger.hh b/SDK/Include/Au/Logger.hh new file mode 100644 index 0000000..9c51937 --- /dev/null +++ b/SDK/Include/Au/Logger.hh @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include +#include +#include // for std::hex +#include +#include +#include + +#include "Au/Config.h" +#include "Au/Logger.hh" +#include "Au/Types.hh" + +namespace Au { +enum class LogLevel +{ + DEBUG, + INFO, + WARNING, + ERROR, + CRITICAL +}; + +class Logger +{ + private: + LogLevel m_logLevel; + bool m_logToFile; + Logger(LogLevel level = LogLevel::CRITICAL, bool logToFile = false) + : m_logLevel{ level } + , m_logToFile{ logToFile } + { + if (level < LogLevel::CRITICAL) { + m_logLevel = level; + return; + } + if (AU_BUILD_TYPE_RELEASE) + m_logLevel = LogLevel::CRITICAL; + else if (AU_BUILD_TYPE_DEBUG) + m_logLevel = LogLevel::INFO; + else if (AU_BUILD_TYPE_DEVELOPER) + m_logLevel = LogLevel::DEBUG; + } + + /** + * @brief Append variables to the message + * @param stream The stringstream to append to + * @param value The value to append + * @param args The rest of the values to append + * + * @return void + */ + template + void appendVariables(std::stringstream& stream, T&& value, Args&&... args) + { + stream << " " << value; + appendVariables(stream, std::forward(args)...); + } + + /** + * @brief Append variables to the message, The terminal condition for + * appendVariables recursion + * @param stream The stringstream to append to + * + * @return void + */ + void appendVariables(std::stringstream& stream) {} + + /** + * @brief Write the message to the log file + * @param message The message to write + * + * @return void + */ + void writeToLogFile(const String& message) + { + std::ofstream logFile; + logFile.open("cpuidlog.txt", std::ios_base::app); + if (logFile.is_open()) { + logFile << message << std::endl; + } + } + + /** + * @brief Write the message to the console + * @param message The message to write + * + * @return void + */ + void writeToConsole(const String& message) + { + std::cout << message << std::endl; + } + + public: + Logger(Logger const&) = delete; + void operator=(Logger const&) = delete; + + /** + * @brief Get the logger instance + * @return The logger instance + */ + static Logger& getInstance() + { + static Logger instance; + return instance; + } + + /** + * @brief Set the log level + * @param level The log level + * @param logToFile If true, log to file + * @return void + */ + void setLevel(LogLevel level, bool logToFile = false) + { + this->m_logLevel = level; + this->m_logToFile = logToFile; + } + + /** + * @brief Log a message + * @param level The log level + * @param message The message to log + * @param args The arguments to log + * std::hex can be used to print variables in hex format + * Example usage: log(LogLevel::DEBUG, "Value is: ", std::hex, value); + * + * @return void + */ + template + void log(LogLevel level, const String& message, Args&&... args) + { + if (level < m_logLevel) + return; + String logLevelStr; + switch (level) { + case LogLevel::DEBUG: + logLevelStr = "[DEBUG]"; + break; + case LogLevel::INFO: + logLevelStr = "[INFO]"; + break; + case LogLevel::WARNING: + logLevelStr = "[WARNING]"; + break; + case LogLevel::ERROR: + logLevelStr = "[ERROR]"; + break; + case LogLevel::CRITICAL: + logLevelStr = "[CRITICAL]"; + break; + } + + std::time_t now = std::time(nullptr); + String timestamp = std::asctime(std::localtime(&now)); + timestamp = + timestamp.substr(0, timestamp.length() - 1); // Remove newline + + std::stringstream logMessageStream; + logMessageStream << timestamp << " " << logLevelStr << " " << message; + appendVariables(logMessageStream, std::forward(args)...); + + String logMessage = logMessageStream.str(); + if (m_logToFile) + writeToLogFile(logMessage); + writeToConsole(logMessage); + } +}; + +// Overload << operator for std::ostream to print variables in hex format +template>> +std::ostream& +operator<<(std::ostream& os, const T& value) +{ + if constexpr (std::is_enum_v) { + os << std::hex << std::showbase + << static_cast>(value); + } else { + os << std::hex << std::showbase << value; + } + return os; +} + +} // namespace Au diff --git a/SDK/Include/Au/Memory/.clang-tidy b/SDK/Include/Au/Memory/.clang-tidy new file mode 100644 index 0000000..ae204c1 --- /dev/null +++ b/SDK/Include/Au/Memory/.clang-tidy @@ -0,0 +1,7 @@ +# File: project/external/.clang-tidy + +# Disable all checks in this folder. +# +Checks: '-*,misc-definitions-in-headers' +CheckOptions: + {HeaderFileExtensions: "x" } diff --git a/SDK/Include/Au/Memory/BufferLocal.hh b/SDK/Include/Au/Memory/BufferLocal.hh new file mode 100644 index 0000000..760c661 --- /dev/null +++ b/SDK/Include/Au/Memory/BufferLocal.hh @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2022-2022, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "Au/Assert.hh" +#include "Au/Au.hh" +#include "Au/BufferBase.hh" + +#include + +namespace Au::Memory { + +/** + * @details Creates a Buffer on the stack, similar to one using an + * array on the stack. Gets automatically de-allocated + * at the end of scope + * + * { + * BufferLocal u20{}; + * u20[2] = 5; + * u20[21] = 8; // should fail, at least in assert build + * } + * + * + */ +template +class BufferLocal final : public BufferBase +{ + using valueT = T; + using pointerT = T*; + using constPointerT = const T*; + using referenceT = T&; + using constReferenceT = const T&; + + public: + BufferLocal() + : BufferBase{ m_buf.data(), SIZE } + , m_buf{} + { + AUD_ASSERT(SIZE >= 0, "Size is not 0 or possitive"); + } + ~BufferLocal(); + + // Disable all heap allocations + void* operator new(std::size_t) = delete; + void* operator new[](std::size_t) = delete; + + referenceT operator[](size_t index) + { + AUD_ASSERT(index <= BufferBase::size(), "Index out of bounds"); + return m_buf[index]; + } + + private: +#if 0 + struct _Deleter + { + void operator()(pointerT p) + { + /* + * We'll not call free() or delete here, as the memory + * owned is locally on the stack, will be freed upon + * exit from the scope + */ + } + }; + using uniquePtrT = std::unique_ptr; +#endif + private: + std::array m_buf; + // uniquePtrT m_ptr; + // const std::size_t m_size; +}; + +template +BufferLocal::~BufferLocal() +{ +} + +} // namespace Au::Memory diff --git a/SDK/Include/Au/Memory/BufferView.hh b/SDK/Include/Au/Memory/BufferView.hh new file mode 100644 index 0000000..5e87fc1 --- /dev/null +++ b/SDK/Include/Au/Memory/BufferView.hh @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2022-2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#pragma once + +#include "Au/Assert.hh" +#include "Au/Au.hh" +#include "Au/BufferBase.hh" + +namespace Au::Memory { + +/** + * @details BufferView is similar to std::string_view, a non-owning buffer + * Easy to work with of pre-allocated memory block from other parts + * For eg: A C-application owning a block sends it across. This + * provides Safe way to access the memory with bounds checks + */ +template +class BufferView final : public BufferBase +{ + using valueT = T; + using pointerT = T*; + using constPointerT = const T*; + using referenceT = T&; + using constReferenceT = const T&; + + public: + explicit BufferView(pointerT mem_block, size_t c_size) + : BufferBase{ mem_block, c_size } + { + AUD_ASSERT(BufferBase::data() != nullptr, "Invalid Pointer"); + AUD_ASSERT(BufferBase::size() >= 0, "Invalid size"); + } + + BufferView(const BufferView& other) = delete; + + /** + * @brief We do not allow copy of buffer across objects + * + * @param other A BufferView type to copy from + * + * @return BufferView Returns reference to self + */ + BufferView& operator=(const BufferView& other) = delete; + + T& operator[](size_t idx) + { + auto arr = reinterpret_cast(BufferBase::data()); + AUD_ASSERT(idx < BufferBase::size(), "Index out of bound"); + return arr[idx]; + } + + // Disable all heap allocations + void* operator new(std::size_t) = delete; + void* operator new[](std::size_t) = delete; + + ~BufferView() override = default; + + private: + // void* const m_ptr; // pointer to existing memory block + // size_t m_size; + // const size_t m_allocated_size; // whatever we got from user +}; + +} // namespace Au::Memory diff --git a/lib/capi/c_error.cc b/SDK/Include/Au/Memory/ObjectPool.hh similarity index 75% rename from lib/capi/c_error.cc rename to SDK/Include/Au/Memory/ObjectPool.hh index 69a3276..283f139 100644 --- a/lib/capi/c_error.cc +++ b/SDK/Include/Au/Memory/ObjectPool.hh @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023, Advanced Micro Devices, Inc. All rights reserved. + * Copyright (C) 2023, Advanced Micro Devices. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -26,30 +26,19 @@ * */ -#include "alci/alci.h" -#include "alci/enum.h" -#include "alci/macros.h" - -#include /* for int32_t */ - -using namespace alci; - -EXTERN_C_BEGIN +#pragma once /** - * \brief Portable API to check if an error has occured + * FIXME: + * https://howardhinnant.github.io/allocator_boilerplate.html * - * \param err Actual error number + * https://github.com/TileDB-Inc/TileDB/blob/dev/tiledb/sm/misc/resource_pool.h + * + * NCBI implementation + * https://www.ncbi.nlm.nih.gov/IEB/ToolBox/CPP_DOC/lxr/source/src/corelib/ncbimempool.cpp * - * \return 1/true if error occorured, false otherwise. */ -bool -alci_is_error(alc_cpuid_error_t err) -{ - if (static_cast(err)) - return true; - - return false; -} -EXTERN_C_END \ No newline at end of file +template +class ObjectPool +{}; diff --git a/SDK/Include/Au/Memory/ThreadPool.hh b/SDK/Include/Au/Memory/ThreadPool.hh new file mode 100644 index 0000000..3d8f972 --- /dev/null +++ b/SDK/Include/Au/Memory/ThreadPool.hh @@ -0,0 +1,5 @@ +/** + +* https://www.ncbi.nlm.nih.gov/IEB/ToolBox/CPP_DOC/lxr/source/include/util/thread_pool.hpp + +*/ diff --git a/SDK/Include/Au/Size.hh b/SDK/Include/Au/Size.hh new file mode 100644 index 0000000..a48ce56 --- /dev/null +++ b/SDK/Include/Au/Size.hh @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include "Au/Au.hh" +#include + +namespace Au { + +template>> +class Size +{ + using LDouble = long double; + + public: + explicit Size(T s) + : m_size{ static_cast(s) } + { + } + + auto KiB() { return m_size / 1024.0; } + + auto MiB() { return KiB() / 1024.0; } + + auto GiB() { return MiB() / 1024.0; } + + private: + LDouble m_size; +}; + +template>> +class Frequency +{ + using LDouble = long double; + + public: + explicit Frequency(T s) + : m_freq{ static_cast(s) } + { + } + + auto KHz() { return m_freq / 1000.0; } + auto MHz() { return KHz() / 1000.0; } + auto GHz() { return MHz() / 1000.0; } + + private: + LDouble m_freq; + +} // namespace Au diff --git a/SDK/Include/Au/Status.hh b/SDK/Include/Au/Status.hh new file mode 100644 index 0000000..3c7af08 --- /dev/null +++ b/SDK/Include/Au/Status.hh @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2022-2022, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include "Au/Au.hh" +#include "Au/Interface/IError.hh" + +namespace Au { + +/* + * Example: + * + * Au::Status sts = DoSomething(); + * if (!sts.ok()) { + * LOG(ERROR) << sts; + * } + */ + +class Status final +{ + public: + Status(IError const& ie) + : m_code{ ie.code() } + , m_message{ ie.message() } + { + } + + Status(IError&& ie) + : m_code{ ie.code() } + , m_message{ ie.message() } + { + } + + explicit Status(IError const& ie, StringView msg) + : Status{ ie } + { + m_message = makeMessage(ie.message(), msg); + } + + AUD_DEFAULT_CTOR_AND_DTOR(Status); + AUD_DEFAULT_COPY_AND_ASSIGNMENT(Status); + + bool operator==(const Status& other) const; + bool operator!=(const Status& other) const; + + // Status::ok() + // All is Well !!! if m_error is eOk or eNone + AUD_MUST_USE_RETURN bool ok() const; + String message() const { return m_message; } + + /** + * @name code() + * + * @detail + * Returns encoded error code + * + * @params + * n/a + * + * @result Uint64 encoded error code + */ + Uint64 code() const { return m_code; } + + /** + * @name update() + * + * @detail + * Update the error code and message only if there was no error earlier; + * this is done to presever the very first error that happens + * + * @param[in] ie IError interface from any component + * + * @return boolean Indication if the update was successful + */ + bool update(IError& ie, const String& msg) + { + if (m_code) + return false; + + m_code = ie.code(); + m_message = makeMessage(ie.message(), msg); + return true; + } + + private: + String& makeMessage(const String& module_error, const String& details) + { + m_message = module_error + String(" ") + details; + return m_message; + } + + String& makeMessage(const StringView& module_error, + const StringView& details) + { + m_message = String(module_error) + String(" ") + String(details); + return m_message; + } + + Uint64 m_code; + String m_message; + + // StringView m_err_message, m_err_specifics; +}; + +/** + * @brief StatusOk() + * Useful function when returning from a function + * + * Status some_function(some_arg_t arg) + * { + * // .. do something important .. + * + * return StatusOk(); + * } + */ +inline Status +StatusOk() +{ + auto& ie = NoError(); + + return Status{ ie }; +} + +inline bool +Status::operator==(const Status& other) const +{ + return this->m_code == other.m_code; +} + +inline bool +Status::ok() const +{ + return m_code == 0; +} + +// clang-format off +/* + * Easy to use chekers + */ +AUD_MUST_USE_RETURN bool IsAborted(const Status& status); +AUD_MUST_USE_RETURN bool IsAlreadyExists(const Status& status); +AUD_MUST_USE_RETURN bool IsInternal(const Status& status); +AUD_MUST_USE_RETURN bool IsInvalidArgument(const Status& status); +AUD_MUST_USE_RETURN bool IsNotFound(const Status& status); +AUD_MUST_USE_RETURN bool IsNotAvailable(const Status& status); +AUD_MUST_USE_RETURN bool IsNotImplemented(const Status& status); +AUD_MUST_USE_RETURN bool IsUnknown(const Status& status); + + +Status StatusAlreadyExists(StringView msg); +Status StatusInternalError(StringView msg); +Status StatusInvalidArgument(StringView msg); +Status StatusNotFound(StringView msg); +Status StatusNotAvailable(StringView msg); +Status StatusNotImplemented(StringView msg); +Status StatusUnknown(StringView msg); +// clang-format on + +} // namespace Au diff --git a/SDK/Include/Au/StatusOr.hh b/SDK/Include/Au/StatusOr.hh new file mode 100644 index 0000000..e2c220e --- /dev/null +++ b/SDK/Include/Au/StatusOr.hh @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2022-2022, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include "Au/Assert.hh" +#include "Au/Error.hh" +#include "Au/Status.hh" + +#include "Error.hh" + +#include + +namespace Au { + +template +class StatusOr +{ + public: + using value_type = T; + using type = T; + + public: + inline StatusOr(); + inline StatusOr(Au::Status& sts); + + inline StatusOr(const T& val); // copy ctor + inline StatusOr(T&& val); // move ctor + + AUD_DEFAULT_COPY_AND_ASSIGNMENT(StatusOr); + + template + StatusOr(const StatusOr& sts); + + template + const StatusOr& operator=(const StatusOr& sts); + + /** + * @brief status() will return the underlying status + * Status doWork() + * { + * StatusOr sts = Aes::Build("aes-256-cbc") + * + * if (!sts.ok()) { + * return sts.status(); + * } + * + * auto val = *sts; + * + * // ... do something with val which is an 'Aes256Context' + * } + * + * @return const Status& + */ + inline const Status& status() const { return m_status; } + + inline void set(Status const& st) + { + if (ok()) + m_status = st; + } + + inline void set(T& v) + { + if (ok()) + m_value = v; + } + + /** + * @brief ok() will return if underlaying status was ok + * + * @return true if actual status was ok(), false otherwise + */ + inline bool ok() const { return m_status.ok(); } + + T* operator->() { return &(m_value.value()); } + const T* operator->() const { return &(m_value.value()); } + + T& operator*() & { return *m_value; } + T const& operator*() const& { return *m_value; } + T&& operator*() && { return *std::move(m_value); } + T const&& operator*() const&& { return *std::move(m_value); } + + inline T const& value() const& { return m_value; } + inline T& value() & { return *m_value; } + inline T const&& value() const&& { return *std::move(m_value); } + inline T&& value() && { return *std::move(m_value); } + + private: + Status m_status; + std::optional m_value; + + template + friend class StatusOr; + + private: + inline bool assertNotOk() const + { + AUD_ASSERT(!m_status.ok(), m_status.message()); + return true; + } +}; + +template +inline StatusOr::StatusOr() + : m_status{ UnknownError() } +{ +} + +template +inline StatusOr::StatusOr(Au::Status& sts) + : m_status{ sts } +{ + AUD_ASSERT(!m_status.ok(), "Assigned status not ok!!"); +} + +template +inline StatusOr::StatusOr(const T& value) + : m_status{ StatusOk() } + , m_value{ value } +{ +} + +template +inline StatusOr::StatusOr(T&& value) + : m_status{ StatusOk() } + , m_value{ std::move(value) } +{ +} + +template +template +inline StatusOr::StatusOr(const StatusOr& sts) + : m_status{ sts.m_status } + , m_value{ sts.m_value } +{ +} +} // namespace Au diff --git a/SDK/Include/Au/Thread.hh b/SDK/Include/Au/Thread.hh new file mode 100644 index 0000000..9a376e4 --- /dev/null +++ b/SDK/Include/Au/Thread.hh @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Au/Au.hh" + +#include "Os/Thread.hh" + +namespace Au { + +class ThreadBase +{ + + public: + using ThreadIdT = Os::ThreadIdT; + static constexpr Uint32 NR_CPUS = 1024; + + public: + AUD_DEFAULT_CTOR_AND_VIRTUAL_DTOR(ThreadBase); + + explicit ThreadBase(ThreadIdT tid) + : m_thread_id{ tid } {}; + + protected: + ThreadIdT m_thread_id; +}; + +class Thread final + : public ThreadBase + , public std::thread +{ + public: + using ThreadFuncT = Os::ThreadFuncT; + + public: + /** + * @brief: + * @param: + * @return + */ + ThreadIdT getId() const; + + /** + * @brief: + * @param: + * @return + */ + void sleep() const; + + /** + * @brief Start the thread with given function parameter + * @param[in] tfptr Pointer to a function to run + * @return nothing + */ + void start(ThreadFuncT tfptr); + + /** + * @brief Join the thread + * @param + * @return + */ + + private: + ThreadIdT __getId() const; +}; + +} // namespace Au diff --git a/SDK/Include/Au/ThreadPinning.hh b/SDK/Include/Au/ThreadPinning.hh new file mode 100644 index 0000000..bce9561 --- /dev/null +++ b/SDK/Include/Au/ThreadPinning.hh @@ -0,0 +1,81 @@ +/* + * Copyright(c) 2024 Advanced Micro Devices, Inc.All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this softwareand 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 noticeand 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 "Au/Config.h" +#include +#include + +// Define DWORD +typedef unsigned long DWORD; +#ifdef AU_TARGET_OS_IS_WINDOWS +#include +typedef HANDLE pthread_t; +#endif +namespace Au { +enum pinStrategy +{ + SPREAD, + CORE, + LOGICAL +}; + +class ThreadPinning +{ + public: + ThreadPinning(); + ~ThreadPinning(); + /** + * @brief PinThreads + * + * @details Pin Threads to a specific processor group. + * + * @param[in] threadList ThreadIds to pin + * + * @param[in] pinStrategyIndex 0 - spread , 1 - Core, 2 - Logical + * Processor + * + * @return None + */ + void pinThreads(std::vector const& threadList, + int pinStrategyIndex); + + /** + * @brief pinThreads + * + * @details Pin Threads to a specific processor group. + * + * @param[in] threadList ThreadIds to pin + * + * @param[in] processPinGroup Processor Group to pin the threads + * + */ + void pinThreads(std::vector const& threadList, + std::vector const& processPinGroup); + + private: + class Impl; + const Impl* pImpl() const { return m_pimpl.get(); } + Impl* pImpl() { return m_pimpl.get(); } + std::unique_ptr m_pimpl; +}; +} // namespace Au diff --git a/SDK/Include/Au/Types.hh b/SDK/Include/Au/Types.hh new file mode 100644 index 0000000..116cf61 --- /dev/null +++ b/SDK/Include/Au/Types.hh @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#include +#include +#include + +namespace Au { + +#define AU_CURRENT_CPU_NUM UINT32_MAX +using Uint8 = ::uint8_t; +using Int8 = ::int8_t; +using pUint8 = ::int8_t*; +using pInt8 = ::int8_t*; + +using Uint16 = ::uint16_t; +using Int16 = ::int16_t; +using pUint16 = ::int16_t*; +using pInt16 = ::int16_t*; + +using Uint32 = ::uint32_t; +using Int32 = ::int32_t; +using pUint32 = ::int32_t*; +using pInt32 = ::int32_t*; + +using Uint64 = ::uint64_t; +using Int64 = ::int64_t; +using pUint64 = ::int64_t*; +using pInt64 = ::int64_t*; + +using Float32 = float; +using Float64 = double; + +// +// Some useful aliases +// + +using String = std::string; +using StringView = std::string_view; +// +// +// +// + +/** + * Some useful macros: + * + * template >> + * class Size { + * public: + * explicit Size(T s) + * :m_size{static_cast(s)} + * {} + * + * auto KiB() + * { + * return m_size / 1024.0; + * } + * }; + * + */ + +template +using enableIf = typename std::enable_if::type; + +template +using disableIf = typename std::enable_if::type; + +} // namespace Au diff --git a/SDK/Include/Capi/au/.clang-tidy b/SDK/Include/Capi/au/.clang-tidy new file mode 100644 index 0000000..ae204c1 --- /dev/null +++ b/SDK/Include/Capi/au/.clang-tidy @@ -0,0 +1,7 @@ +# File: project/external/.clang-tidy + +# Disable all checks in this folder. +# +Checks: '-*,misc-definitions-in-headers' +CheckOptions: + {HeaderFileExtensions: "x" } diff --git a/SDK/Include/Capi/au/au.h b/SDK/Include/Capi/au/au.h new file mode 100644 index 0000000..1e2e74f --- /dev/null +++ b/SDK/Include/Capi/au/au.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __AU_H__ +#define __AU_H__ + +#include "Capi/au/enum.h" +#include "Capi/au/macros.h" +#include "Capi/au/types.h" +// #include "Capi/au/" + +#endif /* __AU_H__ */ diff --git a/SDK/Include/Capi/au/cpuid/cache.h b/SDK/Include/Capi/au/cpuid/cache.h new file mode 100644 index 0000000..542ee95 --- /dev/null +++ b/SDK/Include/Capi/au/cpuid/cache.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __AU_CAPI_CACHE_H__ +#define __AU_CAPI_CACHE_H__ + +#include "Capi/au/au.h" +#include "Capi/au/macros.h" + +AUD_EXTERN_C_BEGIN + +typedef enum +{ + AU_CPU_CACHE_LEVEL_UNKNOWN, + AU_CPU_CACHE_LEVEL_L1, + AU_CPU_CACHE_LEVEL_L2, + AU_CPU_CACHE_LEVEL_L3, + AU_CPU_CACHE_LEVEL_L4, + AU_CPU_CACHE_LEVEL_MAX, +} au_cpu_cache_level_t; + +typedef enum +{ + AU_CPU_CACHE_TYPE_UNKNOWN, + AU_CPU_CACHE_TYPE_INST, + AU_CPU_CACHE_TYPE_DATA, + AU_CPU_CACHE_TYPE_UNIFIED, + AU_CPU_CACHE_TYPE_MAX, +} au_cpu_cache_type_t; + +/** + * @brief + * + * @param + * + * @return + **/ +au_error_t +au_cpu_cache_get_size(); + +/** + * @brief + * + * @param + * + * @return + **/ +au_error_t +au_cpu_cache_get_way(); + +/** + * @brief + * + * @param + * + * @return + **/ +au_error_t +au_cpu_cache_get_lane(); + +AUD_EXTERN_C_END + +#endif diff --git a/SDK/Include/Capi/au/cpuid/cpuid.h b/SDK/Include/Capi/au/cpuid/cpuid.h new file mode 100644 index 0000000..c490832 --- /dev/null +++ b/SDK/Include/Capi/au/cpuid/cpuid.h @@ -0,0 +1,306 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __AU_CPUID_CPUID_H__ +#define __AU_CPUID_CPUID_H__ + +#include "Au/Config.h" +#include "Au/Defs.hh" +#include "Capi/au/au.h" + +#include +#include + +AUD_EXTERN_C_BEGIN + +#if !defined(au_cpu_num_t) +typedef Uint32 au_cpu_num_t; +typedef Uint32 au_cpu_flag_t; +#endif + +/** + * @brief Check if the processor vendor is AMD. + * + * @param[in] cpu_num CPU number. + * + * @return 1/true if processor vendor is AMD. + */ +AUD_API_EXPORT bool +au_cpuid_is_amd(au_cpu_num_t cpu_num); + +/** + * @brief Get Cpu vendor info. + * + * @param[in] cpu_num CPU number. + * @param[in, out] vend_info Vendor info array. + * @param[in] size Size of Vendor info array. + * + * @return None + */ +AUD_API_EXPORT void +au_cpuid_get_vendor(au_cpu_num_t cpu_num, char* vend_info, size_t size); + +/** + * @brief Allows caller to check if the processor arch is ZEN. + * + * @param[in] cpu_num CPU number. + * + * @return 1/true if processor architecture is AMD ZEN. + */ +AUD_API_EXPORT bool +au_cpuid_arch_is_zen(au_cpu_num_t cpu_num); + +/** + * @brief Allows caller to check if the processor arch is ZENPLUS. + * + * @param[in] cpu_num CPU number. + * + * @return 1/true if processor architecture is AMD ZENPLUS. + */ +AUD_API_EXPORT bool +au_cpuid_arch_is_zenplus(au_cpu_num_t cpu_num); + +/** + * @brief Allows caller to check if the processor arch is ZEN2. + * + * @param[in] cpu_num CPU number. + * + * @return 1/true if processor architecture is AMD ZEN2. + */ +AUD_API_EXPORT bool +au_cpuid_arch_is_zen2(au_cpu_num_t cpu_num); + +/** + * @brief Allows caller to check if the processor arch is ZEN3. + * + * @param[in] cpu_num CPU number. + * + * @return 1/true if processor architecture is AMD ZEN3. + */ +AUD_API_EXPORT bool +au_cpuid_arch_is_zen3(au_cpu_num_t cpu_num); + +/** + * @brief Allows caller to check if the processor arch is ZEN4. + * + * @param[in] cpu_num CPU number. + * + * @return 1/true if processor architecture is AMD ZEN4. + */ +AUD_API_EXPORT bool +au_cpuid_arch_is_zen4(au_cpu_num_t cpu_num); + +/** + * @brief Allows caller to check if the processor arch is ZEN5. + * + * @param[in] cpu_num CPU number. + * + * @return 1/true if processor architecture is AMD ZEN5. + */ +AUD_API_EXPORT bool +au_cpuid_arch_is_zen5(au_cpu_num_t cpu_num); + +/** + * @brief Allows caller to check if the flags are available. + * + * Note: The api is deprecated. Use au_cpuid_has_flags + * instead. + * + * @param[in] cpu_num CPU number. + * @param[in] flag_array CPU feature flag names. + * @param[in] count Number of flags in the list. + * + * @return an array indicating feature availability + */ +AU_DEPRECATED_API_X("Use au_cpuid_has_flags instead.") +AUD_API_EXPORT bool* +au_cpuid_has_flag(au_cpu_num_t cpu_num, + const char* const flag_array[], + int count); + +/** + * @brief Allows caller to check if the flag is available. + * + * @param[in] cpu_num CPU number. + * @param[in] flag_array CPU feature flag names. + * @param[in] count Number of flags in the list. + * + * @return A boolean indicating presence or absence of the features + */ +AUD_API_EXPORT bool +au_cpuid_has_flags(au_cpu_num_t cpu_num, + const char* const flag_array[], + int count); +/** + * @brief Portable API to check if an error has occured + * + * @param err Actual error number + * + * @return 1/true if error occorured, false otherwise. + */ +AUD_API_EXPORT bool +au_cpuid_is_error(au_error_t err); + +/******* OLD APIs ********/ + +/** + * @brief Allows caller to check if the processor vendor is AMD. + * + * Note: The api is deprecated. Use au_cpuid_is_amd + * instead. + * + * @param cpu_num CPU number. + * + * @return 1/true if processor vendor is AMD. + */ +AU_DEPRECATED_API_X("Use au_cpuid_is_amd instead.") +AUD_API_EXPORT bool +alci_is_amd(au_cpu_num_t cpu_num); + +/** + * @brief Get Cpu vendor info. + * + * Note: The api is deprecated. Use au_cpuid_get_vendor + * instead. + * + * @param[in] cpu_num CPU number. + * @param[out] arr Vendor info array. + * @param[in] size Size of Vendor info array. + * + * @return 1/true if getting vendor info is successful. + */ +AU_DEPRECATED_API_X("Use au_cpu_get_vendor instead.") +AUD_API_EXPORT au_error_t +alci_cpu_get_vendor(au_cpu_num_t cpu_num, char* arr, size_t size); + +/** + * @brief Allows caller to check if the processor arch is ZEN. + * + * Note: The api is deprecated. Use au_cpuid_arch_is_zen + * instead. + * + * @param cpu_num CPU number. + * + * @return 1/true if processor architecture is AMD ZEN. + */ +AU_DEPRECATED_API_X("Use au_cpuid_arch_is_zen instead.") +AUD_API_EXPORT bool +alci_arch_is_zen(au_cpu_num_t cpu_num); + +/** + * @brief Allows caller to check if the processor arch is ZEN2. + * + * Note: The api is deprecated. Use au_cpuid_arch_is_zen2 + * instead. + * + * @param cpu_num CPU number. + * + * @return 1/true if processor architecture is AMD ZEN2. + */ +AU_DEPRECATED_API_X("Use au_cpuid_arch_is_zen2 instead.") +AUD_API_EXPORT bool +alci_arch_is_zen2(au_cpu_num_t cpu_num); + +/** + * @brief Allows caller to check if the processor arch is ZEN3. + * + * Note: The api is deprecated. Use au_cpuid_arch_is_zen3 + * instead. + * + * @param cpu_num CPU number. + * + * @return 1/true if processor architecture is AMD ZEN3. + */ +AU_DEPRECATED_API_X("Use au_cpuid_arch_is_zen3 instead.") +AUD_API_EXPORT bool +alci_arch_is_zen3(au_cpu_num_t cpu_num); + +/** + * @brief Allows caller to check if the processor arch is ZEN4. + * + * Note: The api is deprecated. Use au_cpuid_arch_is_zen4 + * instead. + * + * @param cpu_num CPU number. + * + * @return 1/true if processor architecture is AMD ZEN4. + */ +AU_DEPRECATED_API_X("Use au_cpuid_arch_is_zen4 instead.") +AUD_API_EXPORT bool +alci_arch_is_zen4(au_cpu_num_t cpu_num); + +/** + * @brief Allows caller to check if the processor arch is ZEN5. + * + * Note: The api is deprecated. Use au_cpuid_arch_is_zen5 + * instead. + * + * @param cpu_num CPU number. + * + * @return 1/true if processor architecture is AMD ZEN5. + */ +AU_DEPRECATED_API_X("Use au_cpuid_arch_is_zen5 instead.") +AUD_API_EXPORT bool +alci_arch_is_zen5(au_cpu_num_t cpu_num); + +/** + * @brief Allows caller to check if the flag is available. + * + * Note: The api is deprecated. Use au_cpuid_has_flag + * instead. + * + * @param flag CPU feature flag. + * + * @return 1/true if feature is available. + */ +AU_DEPRECATED_API_X("Use au_cpuid_has_flag instead.") +AUD_API_EXPORT bool +alci_cpu_has_flag(au_cpu_num_t cpu_num, au_cpu_flag_t flag); + +/** + * @brief Get last level cache. + * + * @param[in] core CPU core number. + * + * @return Returns last level cache. + */ +AUD_API_EXPORT uint32_t +alci_cpu_get_last_cache_level(au_cpu_num_t core); + +#define alcpu_is_amd() alci_is_amd(ALCI_CURRENT_CPU_NUM) +#define alcpu_arch_is_zen() alci_arch_is_zen(ALCI_CURRENT_CPU_NUM) +#define alcpu_arch_is_zen2() alci_arch_is_zen2(ALCI_CURRENT_CPU_NUM) +#define alcpu_arch_is_zen3() alci_arch_is_zen3(ALCI_CURRENT_CPU_NUM) +#define alcpu_arch_is_zen4() alci_arch_is_zen4(ALCI_CURRENT_CPU_NUM) +#define alcpu_arch_is_zen5() alci_arch_is_zen5(ALCI_CURRENT_CPU_NUM) +#define alcpu_flag_is_available(flag) \ + alci_cpu_has_flag(ALCI_CURRENT_CPU_NUM, flag) + +AUD_EXTERN_C_END + +#endif /* __AU_CPUID_CPUID_H__ */ diff --git a/SDK/Include/Capi/au/enum.h b/SDK/Include/Capi/au/enum.h new file mode 100644 index 0000000..9e5effc --- /dev/null +++ b/SDK/Include/Capi/au/enum.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#pragma once + +#define ALC_E_FLAG_SSSE3 1 // ECpuidFlag::sse3 +#define ALC_E_FLAG_AES 24 // ECpuidFlag::aes +#define ALC_E_FLAG_AVX 26 // ECpuidFlag::avx +#define ALC_E_FLAG_RDRAND 29 // ECpuidFlag::rdrand +#define ALC_E_FLAG_TSC_ADJUST 63 // ECpuidFlag::tsc_adjust +#define ALC_E_FLAG_AVX2 66 // ECpuidFlag::avx2 +#define ALC_E_FLAG_BMI2 68 // ECpuidFlag::bmi2 +#define ALC_E_FLAG_TSX 71 // EFlag::rtm // its pointing to ALC_E_FLAG_RTM +#define ALC_E_FLAG_AVX512F 73 // ECpuidFlag::avx512f +#define ALC_E_FLAG_AVX512DQ 74 // ECpuidFlag::avx512dq +#define ALC_E_FLAG_RDSEED 75 // ECpuidFlag::rdseed +#define ALC_E_FLAG_ADX 76 // ECpuidFlag::adx +#define ALC_E_FLAG_AVX512_IFMA 78 // ECpuidFlag::avx512ifma +#define ALC_E_FLAG_AVX512PF 82 // ECpuidFlag::avx512pf +#define ALC_E_FLAG_AVX512ER 83 // ECpuidFlag::avx512er +#define ALC_E_FLAG_AVX512CD 84 // ECpuidFlag::avx512cd +#define ALC_E_FLAG_SHA 85 // ECpuidFlag::sha_ni +#define ALC_E_FLAG_SHA_NI 85 // ECpuidFlag::sha_ni +#define ALC_E_FLAG_AVX512BW 86 // ECpuidFlag::avx512bw +#define ALC_E_FLAG_AVX512VL 87 // ECpuidFlag::avx512vl +#define ALC_E_FLAG_AVX512_VBMI 88 // ECpuidFlag::avx512vbmi +#define ALC_E_FLAG_AVX512_VPOPCNTDQ 92 // ECpuidFlag::avx512_vpopcntdq +#define ALC_E_FLAG_AVXVNNI 98 // ECpuidFlag::avxvnni +#define ALC_E_FLAG_VAES 155 // ECpuidFlag::vaes +#define ALC_E_FLAG_VPCLMULQDQ 156 // ECpuidFlag::vpclmulqdq +#define ALC_E_FLAG_AVX512_VNNI 157 // ECpuidFlag::avx512_vnni +#define ALC_E_FLAG_AVX512_BITALG 158 // ECpuidFlag::avx512_bitalg +#define ALC_E_FLAG_AVX512_VBMI2 159 // ECpuidFlag::avx512_vbmi2 +#define ALC_E_FLAG_MOVDIRI 160 // ECpuidFlag::movdiri +#define ALC_E_FLAG_MOVDIR64B 161 // ECpuidFlag::movdir64b +#define ALC_E_FLAG_AVX512VPINTERSECT 162 // ECpuidFlag::avx512_vpintersect +#define ALC_E_FLAG_X2AVIC 163 // ECpuidFlag::x2avic +#define ALC_CPUID_FLAG_MAX 164 // ECpuidFlag::Max diff --git a/SDK/Include/Capi/au/environ.h b/SDK/Include/Capi/au/environ.h new file mode 100644 index 0000000..49b5915 --- /dev/null +++ b/SDK/Include/Capi/au/environ.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __AU_CAPI_ENVIRON_H__ +#define __AU_CAPI_ENVIRON_H__ + +#include "Au/Defs.hh" +#include "Capi/au/au.h" +#include "Capi/au/error.h" +#include "Capi/au/macros.h" + +AUD_EXTERN_C_BEGIN + +/** + * @brief Initialize environment from applications's "const char * envp[]" + * + * @param[in] Pointer to array of strings (null-terminated) + * + * @return None + */ +AUD_API_EXPORT void +au_env_init(const char** envp); + +/** + * @brief Get an environment variable + * + * @detail Searches in system env, and user env + * When set in both environments, User env overrides system env. + * + * @param[in] name Name of the environment varible to search + * + * @return NULL if the environment is not set + * pointer to char array (null-terminated)string if set. + */ +AUD_API_EXPORT const char* +au_env_get(const char* name); + +/** + * @brief Set an environment variable + * + * @detail Sets the User Env variable + * + * @param[in] name Name of the environment varible to set + * @param[in] val Value of the variable as string + * + * @return NULL if the environment is not set + * pointer to char array (null-terminated)string if set. + */ +AUD_API_EXPORT const char* +au_env_set(const char* name, const char* val); + +/** + * @brief Unset a variable, delete from list + * + * @details if the 'name' exists it will be deleted from user env. + * @param[in] name name of the variable to be unset + * + * @return void + */ +AUD_API_EXPORT void +au_env_unset(const char* name); + +/** + * @brief Check if a given environment variable is enabled. + * + * @details Variable can be set with case insensitive values from command line + * + * AU_BLIS_DEBUG=YES + * AU_BLIS_DEBUG=ON + * AU_BLIS_DEBUG=1 + * AU_BLIS_DEBUG=TRUE + * all above will return 'true' or 1 when called like below + * @example + * if (au_env_is_enabled("AU_BLIS_DEBUG")) { + * } + * + * However it will return 'false' for following cases (string values are case- + * insensitive) + * AU_BLIS_DEBUG=0 + * AU_BLIS_DEBUG=OFF + * AU_BLIS_DEBUG=FALSE + * AU_BLIS_DEBUG=NO + */ +bool AUD_API_EXPORT +au_env_is_enabled(const char*); + +/** + * @brief Check if a given environment variable is set. + * + * @details Variable can be set from command line as + * AU_BLIS_DEBUG=YES/NO + * AU_BLIS_DEBUG=ON/OFF + * AU_BLIS_DEBUG=1/0 + * AU_BLIS_DEBUG=TRUE/FALSE + * all above will return 'true' or 1 when called like below + * + * @example + * if (au_env_is_set("AU_BLIS_DEBUG")) { + * } + * + * However it will return 'false' only if the variable is empty or not set. + */ +AUD_API_EXPORT bool +au_env_is_set(const char*); + +AUD_EXTERN_C_END + +#endif /* AU_CAPI_ENVIRON_H */ diff --git a/SDK/Include/Capi/au/error.h b/SDK/Include/Capi/au/error.h new file mode 100644 index 0000000..a4563b7 --- /dev/null +++ b/SDK/Include/Capi/au/error.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __AU_ERROR_H__ +#define __AU_ERROR_H__ + +#include "Capi/au/macros.h" +#include "Capi/au/types.h" + +AUD_EXTERN_C_BEGIN + +#define AUD_BAD_PTR_ERR_RET(ptr, err) \ + do { \ + if (nullptr == ptr) { \ + return (au_error_t)eError_BadPointer; \ + } \ + } while (0) + +#define AUD_ZERO_LEN_ERR_RET(len, err) \ + do { \ + if (0 == len) { \ + return (au_error_t)eError_InvalidArgument; \ + } \ + } while (0) + +typedef enum __au_error_code +{ + eError_Ok = 0, + eError_None = eError_Ok, + + eError_Generic, + + eError_NotSupported, + + eError_InvalidArgument, + + eError_BadPointer, + + eError_NoMemory, + + eError_InvalidSize, +} au_error_code_t; + +#if !defined(au_error_t) +typedef Uint64 au_error_t; +#endif + +#ifndef __cplusplus +#ifndef bool +typedef enum __au_bool +{ + false = 0, + true +} bool; +#endif +#endif + +/** + * @brief Checks if an value returned by an API is an error + * + * @param[in] err an au_error_t + * + * @returns true if an error has occured, false otherwise + */ +bool +au_is_error(const au_error_t err); + +AUD_EXTERN_C_END + +#endif /* __AU_ERROR_H__ */ diff --git a/SDK/Include/Capi/au/macros.h b/SDK/Include/Capi/au/macros.h new file mode 100644 index 0000000..9c0b800 --- /dev/null +++ b/SDK/Include/Capi/au/macros.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef __AU_MACROS_H__ +#define __AU_MACROS_H__ + +#ifdef __cplusplus +#ifndef AUD_EXTERN_C_BEGIN +#define AUD_EXTERN_C_BEGIN \ + extern "C" \ + { +#endif + +#define AUD_EXTERN_C_BEGIN1() \ + extern "C" \ + { +#ifndef AUD_EXTERN_C_END +#define AUD_EXTERN_C_END } +#endif +#define AUD_EXTERN_C_END1() } + +#ifndef AUD_EXTERN_C +#define AUD_EXTERN_C extern "C" +#endif +#else +#define AUD_EXTERN_C_BEGIN +#define AUD_EXTERN_C_END +#define AUD_EXTERN_C +#endif +#if defined(AU_WARN_DEPRECATION) +#if defined(_MSC_VER) +#define AU_DEPRECATED_API \ + __declspec(deprecated("Deprecated, consult userguide.")) +#else +#define AU_DEPRECATED_API \ + __attribute__((deprecated("Deprecated, consult userguide."))) +#endif +#if defined(_MSC_VER) +#define AU_DEPRECATED_API_X(msg) __declspec(deprecated(msg)) +#else +#define AU_DEPRECATED_API_X(msg) __attribute__((deprecated(msg))) +#endif +#else +#define AU_DEPRECATED_API +#define AU_DEPRECATED_API_X(msg) +#endif + +#endif /* __AU_MACROS_H__ */ diff --git a/SDK/Include/Capi/au/threadpinning.h b/SDK/Include/Capi/au/threadpinning.h new file mode 100644 index 0000000..066056f --- /dev/null +++ b/SDK/Include/Capi/au/threadpinning.h @@ -0,0 +1,95 @@ +/* + * Copyright(c) 2024 Advanced Micro Devices, Inc.All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this softwareand 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 noticeand 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. + */ + +#ifndef __AU_THREAD_PINNING_H__ +#define __AU_THREAD_PINNING_H__ + +#include "Au/Config.h" +#include "Au/Defs.hh" +#include "Capi/au/macros.h" + +AUD_EXTERN_C_BEGIN + +#ifdef AU_TARGET_OS_IS_WINDOWS +#include +typedef HANDLE pthread_t; +#else +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include +#include +#include +#endif + +/** + * @brief Pin threads to the processor group using pinStrateg::CORE. + * @param[in] threadList List of threads to pin. + * @param[in] threadListSize Number of threads in the list. + * + * @return void + */ +AUD_API_EXPORT +void +au_pin_threads_core(pthread_t* threadList, size_t threadListSize); + +/** + * @brief Pin threads to the processor group using pinStrateg::LOGICAL. + * @param[in] threadList List of threads to pin. + * @param[in] threadListSize Number of threads in the list. + * + * @return void + */ +AUD_API_EXPORT +void +au_pin_threads_logical(pthread_t* threadList, size_t threadListSize); + +/** + * @brief Pin threads to the processor group using pinStrateg::SPREAD. + * @param[in] threadList List of threads to pin. + * @param[in] threadListSize Number of threads in the list. + * + * @return void + */ +AUD_API_EXPORT +void +au_pin_threads_spread(pthread_t* threadList, size_t threadListSize); + +/** + * @brief Pin threads to the processor group using custom affinity + * vector. + * @param[in] threadList List of threads to pin. + * @param[in] threadListSize Number of threads in the list. + * @param[in] affinityVector Custom affinity vector. + * @param[in] affinityVectorSize Size of the affinity vector. + * + * @return void + */ +AUD_API_EXPORT +void +au_pin_threads_custom(pthread_t* threadList, + size_t threadListSize, + int* affinityVector, + size_t affinityVectorSize); + +AUD_EXTERN_C_END +#endif // __AU_THREAD_PINNING_H__ diff --git a/SDK/Include/Capi/au/types.h b/SDK/Include/Capi/au/types.h new file mode 100644 index 0000000..4b87cb5 --- /dev/null +++ b/SDK/Include/Capi/au/types.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __AU_TYPES_H__ +#define __AU_TYPES_H__ +#include "Au/Config.h" + +#ifdef __cplusplus +#include +#include +#include +#else +#include +#include +#include +#endif + +#define ALCI_CURRENT_CPU_NUM UINT32_MAX +typedef int8_t Int8; +typedef int16_t Int16; +typedef int32_t Int32; +typedef int64_t Int64; + +typedef uint8_t Uint8; +typedef uint16_t Uint16; +typedef uint32_t Uint32; +typedef uint64_t Uint64; + +/* Pointers */ +typedef void* pVoid; +typedef int8_t* pInt8; +typedef int16_t* pInt16; +typedef int32_t* pInt32; +typedef int64_t* pInt64; +typedef uint8_t* pUint8; +typedef uint16_t* pUint16; +typedef uint32_t* pUint32; +typedef uint64_t* pUint64; + +/** + * @brief Generic handle that the library needs + */ +typedef void* au_handle_t; + +typedef Uint32 au_cpu_num_t; + +typedef Uint64 au_error_t; + +#endif /* __AU_TYPES_H__ */ diff --git a/include/alci/arch.h b/SDK/Include/Capi/au/version.h similarity index 56% rename from include/alci/arch.h rename to SDK/Include/Capi/au/version.h index 8233f49..2835ee8 100644 --- a/include/alci/arch.h +++ b/SDK/Include/Capi/au/version.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023, Advanced Micro Devices, Inc. All rights reserved. + * Copyright (C) 2023-2024, Advanced Micro Devices. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -25,64 +25,44 @@ * POSSIBILITY OF SUCH DAMAGE. * */ -#ifndef ALCI_ARCH_H -#define ALCI_ARCH_H -#include "alci/enum.h" -#include "alci/macros.h" +#ifndef __CAPI_AU_VERSION_H__ +#define __CAPI_AU_VERSION_H__ -EXTERN_C_BEGIN +#include "Capi/au/macros.h" +#include "Capi/au/types.h" -/** - * \brief Allows caller to check if the processor vendor is AMD. - * - * \return 1/true if processor vendor is AMD. - */ -bool -alcpu_is_amd(void); +AUD_EXTERN_C_BEGIN /** - * \brief Allows caller to check if the processor arch is ZEN. - * - * \return 1/true if processor architecture is AMD ZEN. + * @brief Return Version Major number */ -bool -alcpu_arch_is_zen(void); +AUD_API_EXPORT +Uint32 +au_get_version_major(void); /** - * \brief Allows caller to check if the processor arch is ZEN2. - * - * \return 1/true if processor architecture is AMD ZEN2. + * @brief Return Version Minor number */ -bool -alcpu_arch_is_zen2(void); +AUD_API_EXPORT +Uint32 +au_get_version_minor(void); /** - * \brief Allows caller to check if the processor arch is ZEN3. - * - * \return 1/true if processor architecture is AMD ZEN3. + * @brief Return Version Patch level */ -bool -alcpu_arch_is_zen3(void); +AUD_API_EXPORT +Uint32 +au_get_version_patch(void); /** - * \brief Allows caller to check if the processor arch is ZEN4. - * - * \return 1/true if processor architecture is AMD ZEN4. - */ -bool -alcpu_arch_is_zen4(void); - -/** - * \brief Allows caller to check if the flag is available. - * - * \param flag CPU feature flag. + * @brief returns version of library * - * \return 1/true if feature is available. */ -bool -alcpu_flag_is_available(alc_flag_t flag); +AUD_API_EXPORT +const char* const +au_get_version_str(void); -EXTERN_C_END +AUD_EXTERN_C_END -#endif /* ALCI_ARCH_H */ +#endif /* __CAPI_AU_VERSION_H__ */ diff --git a/SupportedPackageMatrix.md b/SupportedPackageMatrix.md new file mode 100644 index 0000000..5bacd2d --- /dev/null +++ b/SupportedPackageMatrix.md @@ -0,0 +1,84 @@ +# AOCL-Utils Supported Packages Matrix + +One of the compilers and generators on the platform has to be installed to build the library, along with atleast the minimum version of cmake. The following table lists the supported compilers and generators for the library. + +**Note** Use same compiler to build utils and the application that uses utils. + +## Supported Compilers and Generators + +**Note** Other versions may or may not work. + +## Windows + +| Package | Version | Notes | +| ------- | ---------------| ----- | +| clang | 12.0 - 18.0 | Pass -A x64 during configure| +| msvc | 2019 and 2022 | | +| cmake | 3.22 - 3.30 | | +| ninja | 1.10 | | +| visualstudio | 2019 and 2022 | | + +## Linux + +| Package | Version | Notes | +| ------- | ------------------------------ | ----- | +| clang | 12.0 - 18.0 | | +| aocc | 4.2(clang-16) and 5.0(clang-17)| Download from | +| gcc | 8.5 - 13.1 | 8.5 requires "-lstdc++fs" to be supplied on commandline. | +| cmake | 3.22 - 3.30 | | +| ninja | 1.10 | | +| clang-tidy | 12.0 -17.0 | | + +### Standard Libraries + +The library uses the standard C++ libraries and does not have any external dependencies. The library is tested with the following standard libraries: + +#### au_cpuid + +| Package |Notes | +| -----------|----- | +| libstdc++ | | +| libc++ | | + +#### au_core + +| Package |Notes | +| -----------|----- | +| libstdc++ | | +| libc++ | | +| libpthread | | + +#### tests + +| Package | Version | Notes | +| ------- | ------- | ----- | +| python | 3.9 -3.12| | +| qemu-user| | | + +**Note: One might have to install the required packages based on the platform. and explicitly link the depency libraries.** + +## Checklist + +1. **While linking to the new combined binary** + 1. The combined binary is a combination of all the modules in utils. It is going to be larger in size. + 1. Will have to link explicitly to libstdc++ libpthread, -ldl -lutil explicitly.[section 2 for more details] + 2. Make sure that headers used are corresponding to the compiler being used for compilation and uses the same glibc as the binary. + 2. Backward compatibility issues. + 1. Libraries linking with libaoclutils are good here, but if somebody moved to au_cpuid, the backward compatibility breaks. + 2. Use version.txt document to find the version and link to libaoclutils if version is 4.2 otherwise libau_cpuid + +2. **Common issues and solutions.** + +| Sl no | Issue | Root cause | Solution | +|--------------|------------------------------------------------------------------------------------|---------------------------------------------------------------------------|--------------------------------------------------------------------------------------| +| 1 | Could NOT find Python3 (missing: Python3_INCLUDE_DIRS Python3_LIBRARIES | Not python3 or python3-devel package not present. | Install python3 and devel package. | +| | | Older cmake(3.22, 3.23 and 3.24) unable to find python3 library. | PYTHON_LIBRARIES = path to the python library PYTHON_INCLUDE_PATH = path to where Python.h is found PYTHON_EXECUTABLE = path to the Python interpreter | +| 2 | failing cmake --build command with python related issues. | Older python not able to find stdlibs | Compile utils with -DCMAKE_CXX_STANDARD_LIBRARIES="-ldl -lutil" | +| 3 | Missing symbol from aoclutils | Not able to find the library(libaoclutils) in the std path | Update LD_LIBRARY_PATH on linux update PATH on windows. | +| 4 | Missing symbols and errors related to types and type_traits | unable to link to libstdc++ automatically on older oses. | DCMAKE_CXX_STANDARD_LIBRARIES="-libstdc++" | +| 5 | | < glibc2.34 has libpthread as a separate library. | gcc 10 and below or if the compiler is linking to glibc version < 2.34 explicitly link to lpthread while compiling utils. | +| 6 | Missing symbols related to pthreads | Not able to link to libpthread automatically on older oses. | DCMAKE_CXX_STANDARD_LIBRARIES="-lpthread" | + +3. **Testing.** + 1. Testing requires qemu-x86_64 (qemu-user package) to be installed to run. Make sure that this is installed before running the test. Do a clean build after installation. + 2. Cupid test depends on python too. Make sure that python3 and python-dev(el) package is installed. diff --git a/TP_API_STACK.png b/TP_API_STACK.png new file mode 100644 index 0000000..0133439 Binary files /dev/null and b/TP_API_STACK.png differ diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt new file mode 100644 index 0000000..073d121 --- /dev/null +++ b/Tests/CMakeLists.txt @@ -0,0 +1,82 @@ +# +# Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +au_module("integration") + +set(INTEGRATION_TEST_FILES + environ_tests.cc + # cpuid_test.cc +) + +set(OTHER_TEST_FILES +) + +set(ALL_TEST_FILES + ${INTEGRATION_TEST_FILES} + ${OTHER_TEST_FILES} +) + +# Single test Files gets added in a Loop, more complex ones are below +# message(" Total Test Files: " ${ALL_TEST_FILES}) +foreach(testFile IN LISTS ALL_TEST_FILES) + get_filename_component(__TestName ${testFile} NAME_WE) + get_filename_component(__TestFile ${testFile} NAME) + + #cmake_path(GET testFile ROOT_NAME __path_root_name) + #message("path_root_name - " ${__path_root_name}) + #cmake_path(GET testFile ROOT_DIRECTORY __path_root_dir) + #message("path_root_dir - " ${__path_root_dir}) + #cmake_path(GET testFile ROOT_PATH __path_root_path) + #message("path_root_path - " ${__path_root_path}) + #cmake_path(GET testFile FILENAME __path_filename) + #message("path_filename - " ${__path_filename}) + #cmake_path(GET testFile STEM LAST_ONLY __path_stem) + #message("path_stem - " ${__path_stem}) + #cmake_path(GET testFile RELATIVE_PART __path_relative) + #message("path_relative - " ${__path_relative}) + #cmake_path(GET testFile PARENT_PATH __path_parent) + #message("path_parent - " ${__path_parent}) + + cmake_path(GET testFile PARENT_PATH __parent_path) + #message("parent_path - " ${__parent_path}) + cmake_path( + RELATIVE_PATH __parent_path + BASE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + OUTPUT_VARIABLE __TestDir + ) + # message("Test-> " ${__TestName} + # " file-> " ${__TestFile} + # " dir -> " ${__TestDir} + # ) + au_cc_test(${__TestName} + SOURCES "${__TestFile}" + DIRECTORY ${__parent_path} + DEPENDS + au::aoclutils + #au_provider + ) +endforeach() diff --git a/Tests/Dockerfile b/Tests/Dockerfile new file mode 100644 index 0000000..a382cc4 --- /dev/null +++ b/Tests/Dockerfile @@ -0,0 +1,34 @@ +# Use an official Ubuntu as a parent image +FROM ubuntu:24.04 + +# Use build arguments for Ubuntu version and GCC version +ARG C_COMPILER=gcc-12 +ARG CXX_COMPILER=g++-12 + +RUN echo "Ubuntu version: $UBUNTU_VERSION" +RUN echo "C compiler: $C_COMPILER" +RUN echo "C++ compiler: $CXX_COMPILER" + +# Set environment variables to avoid prompts during package installations +ENV DEBIAN_FRONTEND=noninteractive + +# Update and install necessary packages +RUN apt-get update && apt-get install -y \ + build-essential \ + software-properties-common \ + qemu-user \ + $C_COMPILER \ + $CXX_COMPILER \ + python3 \ + python3-dev \ + git \ + wget \ + ninja-build \ + clang-tidy \ + && rm -rf /var/lib/apt/lists/* +RUN add-apt-repository universe && apt-get update +# Set the working directory inside the container +VOLUME /usr/src/app +WORKDIR /usr/src/app + +CMD sh Tests/build_sanity_tests/build_sanity_test.sh $CMAKE_VERSION $C_COMPILER $CXX_COMPILER diff --git a/Tests/README.md b/Tests/README.md new file mode 100644 index 0000000..efa3bb9 --- /dev/null +++ b/Tests/README.md @@ -0,0 +1,3 @@ +# Integration Tests + +Integration tests mostly work on the C-API. diff --git a/Tests/build_sanity_tests/Readme.md b/Tests/build_sanity_tests/Readme.md new file mode 100644 index 0000000..1d27b0b --- /dev/null +++ b/Tests/build_sanity_tests/Readme.md @@ -0,0 +1,29 @@ +## Introduction + +The build sanity test is a test suite that is run on the build artifacts to ensure that the build is not broken. It runs on different supported packages and checks if the build is successful. The test suite is run on the following packages: + +All combinations of cmake 3.22 to 3.30, and gcc 14, 13, 12, 11, 10, 9 and clang 17, 16, 15, 14 along with clang-tidy validations +with make and ninja generators on ubuntu24.04. base docker image using robot framework. + +## TODO + +- Windows support. +- RHEL support. +- Aocc support. + +## Steps to run the build sanity test + +1. Install the required packages + 1. docker + 2. git + 3. python3 + 4. robotframework + 5. pipx + 6. parobots +2. Clone this repository +3. pabot --testlevelsplit --processes 9 Tests/build_sanity_tests/docker/build_sanity_test.robot from project root directory. + 1. Run individual test cases: + + ```console + python3 Tests/build_sanity_tests/run_build_sanity_test.py c_compiler cxx_compiler cmake_version + ``` diff --git a/Tests/build_sanity_tests/build_sanity_test.py b/Tests/build_sanity_tests/build_sanity_test.py new file mode 100755 index 0000000..c6188f1 --- /dev/null +++ b/Tests/build_sanity_tests/build_sanity_test.py @@ -0,0 +1,157 @@ +# +# Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# python script to run sanity test on build +# Creat docker image, run docker container, run sanity test +# and clean up the docker container + +import os +import sys +import subprocess +import time +import re +from tqdm import tqdm +import threading + +def run_cmd(cmd): + try: + output = subprocess.check_output(cmd, shell=True) + return output + except subprocess.CalledProcessError as e: + print("Error: " + e.output.decode('utf-8')) + pass + +def get_docker_container_status(container_name): + cmd = "docker inspect --format='{{.State.Status}}' " + container_name + status = run_cmd(cmd) + return status + + +def get_docker_container_exit_code(container_name): + cmd = "docker inspect --format='{{.State.ExitCode}}' " + container_name + exit_code = run_cmd(cmd) + return exit_code + + +def get_docker_container_logs(container_name): + cmd = "docker logs " + container_name + print("Running command: " + cmd) + logs = run_cmd(cmd) + return logs + + +def create_docker_image(image_name, dockerfile, c_compiler, cxx_compiler): + cmd = "docker buildx build -t " + image_name + " -f " \ + + dockerfile + " . --network=host --build-arg C_COMPILER=" + c_compiler + \ + " --build-arg CXX_COMPILER=" + cxx_compiler + \ + " --build-arg CXX_COMPILER=" + cxx_compiler + print("Running command: " + cmd) + try: + run_cmd(cmd) + except subprocess.CalledProcessError as e: + print("Error: " + e.output.decode('utf-8')) + remove_docker_image(image_name) + sys.exit(1) + + +def run_docker_container(image_name, container_name, cmd): + cmd = "docker run -e WORKDIR=/usr/src/app " + cmd + \ + " --mount src=" + os.curdir + ",target=/usr/src/app,type=bind --network=host -t" + \ + " --name " + container_name + " " + image_name + print("Running command: " + cmd) + try: + run_cmd(cmd) + # catch the exception if the command fails + except subprocess.CalledProcessError as e: + print("Error: " + e.output.decode('utf-8')) + remove_docker_container(container_name) + sys.exit(1) + + +def stop_docker_container(container_name): + cmd = "docker stop " + container_name + run_cmd(cmd) + + +def remove_docker_container(container_name): + cmd = "docker rm " + container_name + run_cmd(cmd) + + +def remove_docker_image(image_name): + cmd = "docker rmi " + image_name + run_cmd(cmd) + + +def test_cmake_version(image_name, c_compiler, cxx_compiler, cmake_version): + container_name = image_name + "_" + cmake_version + cmd = "-e CMAKE_VERSION=" + cmake_version + \ + " -e C_COMPILER=" + c_compiler + " -e CXX_COMPILER=" + cxx_compiler + run_docker_container(image_name, container_name, cmd) + # Get the container status + status = get_docker_container_status(container_name) + print("Container status: " + status.decode('utf-8')) + # Get the container exit code + exit_code = get_docker_container_exit_code(container_name) + print("Container exit code: " + exit_code.decode('utf-8')) + return_code = 0 + if exit_code.decode('utf-8').strip() != "0": + print("Sanity test failed") + return_code = 1 + else: + print("Sanity test passed") + print("COmbination: " + c_compiler + " " + + cxx_compiler + " " + cmake_version) + print("Cleaning up...") + print("Stopping container...") + stop_docker_container(container_name) + print("Removing container...") + remove_docker_container(container_name) + sys.exit(return_code) + + +def main(): + dockerfile = "Tests/Dockerfile" + if len(sys.argv) != 4: + print("Usage: script.py arg1 arg2 arg3") + sys.exit(1) + + c_compiler = sys.argv[1] + cxx_compiler = sys.argv[2] + cmake_version = sys.argv[3] + print("C Compiler: " + c_compiler) + print("CXX Compiler: " + cxx_compiler) + image_name = "build_sanity_test_" + c_compiler + create_docker_image(image_name, dockerfile, c_compiler, cxx_compiler) + test_cmake_version(image_name, c_compiler, cxx_compiler, cmake_version) + time.sleep(5) + # print("Removing image...") + # remove_docker_image(image_name) + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/Tests/build_sanity_tests/build_sanity_test.sh b/Tests/build_sanity_tests/build_sanity_test.sh new file mode 100644 index 0000000..6b89c1c --- /dev/null +++ b/Tests/build_sanity_tests/build_sanity_test.sh @@ -0,0 +1,107 @@ +#!/bin/bash +# +# Copyright (C) 2022-2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# This script is used to build the sanity test for the project +# The sanity test is a simple test that checks if the project builds correctly + +# check if the cmake is installed +WORKDIR=/usr/src/app +CMAKE_VERSION=$1 +C_COMPILER=$2 +CXX_COMPILER=$3 + +mkdir -p Tests/sanity_test/cmake-$CMAKE_VERSION/$C_COMPILER +log_folder=Tests/sanity_test/cmake-$CMAKE_VERSION/$C_COMPILER + +cd Tests/sanity_test +if [ ! -d "cmake-$CMAKE_VERSION.0-linux-x86_64" ]; then + wget https://cmake.org/files/v$CMAKE_VERSION/cmake-$CMAKE_VERSION.0-linux-x86_64.tar.gz + tar -xf cmake-$CMAKE_VERSION.0-linux-x86_64.tar.gz +fi +cd - + +# install llvm and clang-tidy of the same version as the compiler if the compiler is clang + +# extract the compiler name +compiler_name=$(echo $C_COMPILER | sed -e 's/[^clang]//g') +echo "compiler_name: $compiler_name" + +# extract the compiler version +compiler_version=$(echo $C_COMPILER | sed -e 's/[^0-9]//g') + +## FIXME: The clang-tidy version same as the compiler version is not available in the repo +if [ "$compiler_name" = "clang" ]; then + # install clang-tidy and llvm of compiler_version and make it the default clang-tidy from repo + apt-get install -y clang-tidy-$compiler_version + # make the installed clang-tidy the default clang-tidy + update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-$compiler_version 100 +fi + +touch environment.log +# update the environment.log +echo "************C_COMPILER: --version***************************" >$log_folder/environment.log +$C_COMPILER --version >>$log_folder/environment.log +echo "************CXX_COMPILER: --version*************************" >>$log_folder/environment.log +$CXX_COMPILER --version >>$log_folder/environment.log +echo "************CMAKE_VERSION: cmake --version******************" >>$log_folder/environment.log +$CMAKE_VERSION --version >>$log_folder/environment.log +echo "************CLANG-TIDY VERSION: clang-tidy --version********" >>$log_folder/environment.log +clang-tidy --version >>$log_folder/environment.log +echo "************NINJA VERSION ninja --version******************" >>$log_folder/environment.log +ninja --version >>$log_folder/environment.log +Tests/sanity_test/cmake-$CMAKE_VERSION.0-linux-x86_64/bin/cmake --version >>$log_folder/environment.log + +set -e +# configure the project +Tests/sanity_test/cmake-$CMAKE_VERSION.0-linux-x86_64/bin/cmake -DAU_ENABLE_OLD_API=TRUE -DAU_BUILD_TESTS=TRUE -DAU_BUILD_EXAMPLES=TRUE -DCMAKE_BUILD_TYPE=RELEASE \ + -B Tests/sanity_test/cmake-$CMAKE_VERSION/build-${C_COMPILER}_make -DCMAKE_C_COMPILER=/usr/bin/$C_COMPILER -DCMAKE_CXX_COMPILER=/usr/bin/$CXX_COMPILER 2>&1 >$log_folder/configure_make.log + +Tests/sanity_test/cmake-$CMAKE_VERSION.0-linux-x86_64/bin/cmake -G Ninja -DAU_ENABLE_OLD_API=TRUE -DAU_BUILD_TESTS=TRUE -DAU_BUILD_EXAMPLES=TRUE -DCMAKE_BUILD_TYPE=RELEASE \ + -B Tests/sanity_test/cmake-$CMAKE_VERSION/build-${C_COMPILER}_ninja -DCMAKE_C_COMPILER=/usr/bin/$C_COMPILER -DCMAKE_CXX_COMPILER=/usr/bin/$CXX_COMPILER 2>&1 >$log_folder/configure_ninja.log + +# build the project +touch build_make.log +Tests/sanity_test/cmake-$CMAKE_VERSION.0-linux-x86_64/bin/cmake --build \ + Tests/sanity_test/cmake-$CMAKE_VERSION/build-${C_COMPILER}_make --config Release -j 2>&1 >$log_folder/build_make.log + +touch build_ninja.log +Tests/sanity_test/cmake-$CMAKE_VERSION.0-linux-x86_64/bin/cmake --build \ + Tests/sanity_test/cmake-$CMAKE_VERSION/build-${C_COMPILER}_ninja --config Release -j 2>&1 >$log_folder/build_ninja.log + +# test the project +touch test_make.log +export PYTHONPYCACHEPREFIX=Tests/sanity_test/cmake-$CMAKE_VERSION/build-${C_COMPILER}_make; Tests/sanity_test/cmake-$CMAKE_VERSION.0-linux-x86_64/bin/ctest -C release \ + --test-dir Tests/sanity_test/cmake-$CMAKE_VERSION/build-${C_COMPILER}_make 2>&1 >$log_folder/test_make.log +#touch test_ninja.log +#ninja test + +# if failure log existst copy LastLog.txt to the host +if [ -f Tests/sanity_test/cmake-$CMAKE_VERSION/build-$C_COMPILER/Testing/Temporary/LastTestsFailed.log ]; then + cp Tests/sanity_test/cmake-$CMAKE_VERSION/build-$C_COMPILER/Testing/Temporary/LastTest.log $log_folder/ + cp Tests/sanity_test/cmake-$CMAKE_VERSION/build-$C_COMPILER/Testing/Temporary/LastTestsFailed.log $log_folder/ +fi diff --git a/Tests/build_sanity_tests/docker/build_sanity_test.robot b/Tests/build_sanity_tests/docker/build_sanity_test.robot new file mode 100644 index 0000000..65eb512 --- /dev/null +++ b/Tests/build_sanity_tests/docker/build_sanity_test.robot @@ -0,0 +1,415 @@ + +*** Settings *** +Library Process +Library OperatingSystem +Test Template Run Compiler And CMake Test + +*** Keywords *** +# TODO Add teardown that deletes all docker images created. +# run build_sanity_test.py +Run Compiler And CMake Test + [Arguments] ${compiler} ${cxx_compiler} ${cmake_version} + + ${logfolder}= Set Variable ./Tests/sanity_test/cmake-${cmake_version}/${compiler} + + ${result}= Run Process python Tests/build_sanity_tests/build_sanity_test.py ${compiler} ${cxx_compiler} ${cmake_version} stdout=/tmp/stdout.txt stderr=/tmp/stderr.txt + + Create File ${logfolder}/environment.log + Create File ${logfolder}/configure_make.log + Create File ${logfolder}/build_make.log + Create File ${logfolder}/configure_ninja.log + Create File ${logfolder}/build_ninja.log + Create File ${logfolder}/test_make.log + + ${rc} = Set Variable ${result.rc} + + ${stdout} = Get File /tmp/stdout.txt + Log ${stdout} + ${stderr} = Get File /tmp/stderr.txt + Log ${stderr} + ${stdout} = Get File /tmp/stdout.txt + Log ${stdout} + ${stderr} = Get File /tmp/stderr.txt + Log ${stderr} + ${environment.log} = Get File ${logfolder}/environment.log + Log ${environment.log} + ${configure_make.log} = Get File ${logfolder}/configure_make.log + Log ${configure_make.log} + ${build_make.log} = Get File ${logfolder}/build_make.log + Log ${build_make.log} + ${configure_ninja.log} = Get File ${logfolder}/configure_ninja.log + Log ${configure_ninja.log} + ${build_ninja.log} = Get File ${logfolder}/build_ninja.log + Log ${build_ninja.log} + ${make_last.log} = Get File ${logfolder}/../build-${compiler}_make/Testing/Temporary/LastTest.log + Log ${make_last.log} + #${ninja_last.log} = Get File ${logfolder}/../build-${compiler}_ninja/Testing/Temporary/LastTest.log + #Log ${ninja_last.log} + ${test_make.log} = Get File ${logfolder}/test_make.log + Log ${test_make.log} + Should Be Equal As Numbers ${rc} 0 + #${test_ninja.log} = Get File ${logfolder}/test_ninja.log + #Log ${test_ninja.log} + + + +***Test Cases*** + +Gcc-9 CMake-3.22 + [Tags] gcc-9 cmake-3.22 + gcc-9 g++-9 3.22 + +Gcc-9 CMake-3.23 + [Tags] gcc-9 cmake-3.23 + gcc-9 g++-9 3.23 + +Gcc-9 CMake-3.24 + [Tags] gcc-9 cmake-3.24 + gcc-9 g++-9 3.24 + +Gcc-9 CMake-3.25 + [Tags] gcc-9 cmake-3.25 + gcc-9 g++-9 3.25 + +Gcc-9 CMake-3.26 + [Tags] gcc-9 cmake-3.26 + gcc-9 g++-9 3.26 + +Gcc-9 CMake-3.27 + [Tags] gcc-9 cmake-3.27 + gcc-9 g++-9 3.27 + +Gcc-9 CMake-3.28 + [Tags] gcc-9 cmake-3.28 + gcc-9 g++-9 3.28 + +Gcc-9 CMake-3.29 + [Tags] gcc-9 cmake-3.29 + gcc-9 g++-9 3.29 + +Gcc-9 CMake-3.30 + [Tags] gcc-9 cmake-3.30 + gcc-9 g++-9 3.30 + +Gcc-10 CMake-3.22 + [Tags] gcc-10 cmake-3.22 + gcc-10 g++-10 3.22 + +Gcc-10 CMake-3.23 + [Tags] gcc-10 cmake-3.23 + gcc-10 g++-10 3.23 + +Gcc-10 CMake-3.24 + [Tags] gcc-10 cmake-3.24 + gcc-10 g++-10 3.24 + +Gcc-10 CMake-3.25 + [Tags] gcc-10 cmake-3.25 + gcc-10 g++-10 3.25 + +Gcc-10 CMake-3.26 + [Tags] gcc-10 cmake-3.26 + gcc-10 g++-10 3.26 + +Gcc-10 CMake-3.27 + [Tags] gcc-10 cmake-3.27 + gcc-10 g++-10 3.27 + +Gcc-10 CMake-3.28 + [Tags] gcc-10 cmake-3.28 + gcc-10 g++-10 3.28 + +Gcc-10 CMake-3.29 + [Tags] gcc-10 cmake-3.29 + gcc-10 g++-10 3.29 + +Gcc-10 CMake-3.30 + [Tags] gcc-10 cmake-3.30 + gcc-10 g++-10 3.30 + +Gcc-11 CMake-3.22 + [Tags] gcc-11 cmake-3.22 + gcc-11 g++-11 3.22 + +Gcc-11 CMake-3.23 + [Tags] gcc-11 cmake-3.23 + gcc-11 g++-11 3.23 + +Gcc-11 CMake-3.24 + [Tags] gcc-11 cmake-3.24 + gcc-11 g++-11 3.24 + +Gcc-11 CMake-3.25 + [Tags] gcc-11 cmake-3.25 + gcc-11 g++-11 3.25 + +Gcc-11 CMake-3.26 + [Tags] gcc-11 cmake-3.26 + gcc-11 g++-11 3.26 + +Gcc-11 CMake-3.27 + [Tags] gcc-11 cmake-3.27 + gcc-11 g++-11 3.27 + +Gcc-11 CMake-3.28 + [Tags] gcc-11 cmake-3.28 + gcc-11 g++-11 3.28 + +Gcc-11 CMake-3.29 + [Tags] gcc-11 cmake-3.29 + gcc-11 g++-11 3.29 + +Gcc-11 CMake-3.30 + [Tags] gcc-11 cmake-3.30 + gcc-11 g++-11 3.30 + +Gcc-12 CMake-3.22 + [Tags] gcc-12 cmake-3.22 + gcc-12 g++-12 3.22 + +Gcc-12 CMake-3.23 + [Tags] gcc-12 cmake-3.23 + gcc-12 g++-12 3.23 + +Gcc-12 CMake-3.24 + [Tags] gcc-12 cmake-3.24 + gcc-12 g++-12 3.24 + +Gcc-12 CMake-3.25 + [Tags] gcc-12 cmake-3.25 + gcc-12 g++-12 3.25 + +Gcc-12 CMake-3.26 + [Tags] gcc-12 cmake-3.26 + gcc-12 g++-12 3.26 + +Gcc-12 CMake-3.27 + [Tags] gcc-12 cmake-3.27 + gcc-12 g++-12 3.27 + +Gcc-12 CMake-3.28 + [Tags] gcc-12 cmake-3.28 + gcc-12 g++-12 3.28 + +Gcc-12 CMake-3.29 + [Tags] gcc-12 cmake-3.29 + gcc-12 g++-12 3.29 + +Gcc-12 CMake-3.30 + [Tags] gcc-12 cmake-3.30 + gcc-12 g++-12 3.30 + +Gcc-13 CMake-3.22 + [Tags] gcc-13 cmake-3.22 + gcc-13 g++-13 3.22 + +Gcc-13 CMake-3.23 + [Tags] gcc-13 cmake-3.23 + gcc-13 g++-13 3.23 + +Gcc-13 CMake-3.24 + [Tags] gcc-13 cmake-3.24 + gcc-13 g++-13 3.24 + +Gcc-13 CMake-3.25 + [Tags] gcc-13 cmake-3.25 + gcc-13 g++-13 3.25 + +Gcc-13 CMake-3.26 + [Tags] gcc-13 cmake-3.26 + gcc-13 g++-13 3.26 + +Gcc-13 CMake-3.27 + [Tags] gcc-13 cmake-3.27 + gcc-13 g++-13 3.27 + +Gcc-13 CMake-3.28 + [Tags] gcc-13 cmake-3.28 + gcc-13 g++-13 3.28 + +Gcc-13 CMake-3.29 + [Tags] gcc-13 cmake-3.29 + gcc-13 g++-13 3.29 + +Gcc-13 CMake-3.30 + [Tags] gcc-13 cmake-3.30 + gcc-13 g++-13 3.30 + +Gcc-14 CMake-3.22 + [Tags] gcc-14 cmake-3.22 + gcc-14 g++-14 3.22 + +Gcc-14 CMake-3.23 + [Tags] gcc-14 cmake-3.23 + gcc-14 g++-14 3.23 + +Gcc-14 CMake-3.24 + [Tags] gcc-14 cmake-3.24 + gcc-14 g++-14 3.24 + +Gcc-14 CMake-3.25 + [Tags] gcc-14 cmake-3.25 + gcc-14 g++-14 3.25 + +Gcc-14 CMake-3.26 + [Tags] gcc-14 cmake-3.26 + gcc-14 g++-14 3.26 + +Gcc-14 CMake-3.27 + [Tags] gcc-14 cmake-3.27 + gcc-14 g++-14 3.27 + +Gcc-14 CMake-3.28 + [Tags] gcc-14 cmake-3.28 + gcc-14 g++-14 3.28 + +Gcc-14 CMake-3.29 + [Tags] gcc-14 cmake-3.29 + gcc-14 g++-14 3.29 + +Gcc-14 CMake-3.30 + [Tags] gcc-14 cmake-3.30 + gcc-14 g++-14 3.30 +Clang-14 CMake-3.22 + [Tags] clang-14 cmake-3.22 + clang-14 clang++-14 3.22 + +Clang-14 CMake-3.23 + [Tags] clang-14 cmake-3.23 + clang-14 clang++-14 3.23 + +Clang-14 CMake-3.24 + [Tags] clang-14 cmake-3.24 + clang-14 clang++-14 3.24 + +Clang-14 CMake-3.25 + [Tags] clang-14 cmake-3.25 + clang-14 clang++-14 3.25 + +Clang-14 CMake-3.26 + [Tags] clang-14 cmake-3.26 + clang-14 clang++-14 3.26 + +Clang-14 CMake-3.27 + [Tags] clang-14 cmake-3.27 + clang-14 clang++-14 3.27 + +Clang-14 CMake-3.28 + [Tags] clang-14 cmake-3.28 + clang-14 clang++-14 3.28 + +Clang-14 CMake-3.29 + [Tags] clang-14 cmake-3.29 + clang-14 clang++-14 3.29 + +Clang-14 CMake-3.30 + [Tags] clang-14 cmake-3.30 + clang-14 clang++-14 3.30 + +Clang-15 CMake-3.22 + [Tags] clang-15 cmake-3.22 + clang-15 clang++-15 3.22 + +Clang-15 CMake-3.23 + [Tags] clang-15 cmake-3.23 + clang-15 clang++-15 3.23 + +Clang-15 CMake-3.24 + [Tags] clang-15 cmake-3.24 + clang-15 clang++-15 3.24 + +Clang-15 CMake-3.25 + [Tags] clang-15 cmake-3.25 + clang-15 clang++-15 3.25 + +Clang-15 CMake-3.26 + [Tags] clang-15 cmake-3.26 + clang-15 clang++-15 3.26 + +Clang-15 CMake-3.27 + [Tags] clang-15 cmake-3.27 + clang-15 clang++-15 3.27 + +Clang-15 CMake-3.28 + [Tags] clang-15 cmake-3.28 + clang-15 clang++-15 3.28 + +Clang-15 CMake-3.29 + [Tags] clang-15 cmake-3.29 + clang-15 clang++-15 3.29 + +Clang-15 CMake-3.30 + [Tags] clang-15 cmake-3.30 + clang-15 clang++-15 3.30 + +Clang-16 CMake-3.22 + [Tags] clang-16 cmake-3.22 + clang-16 clang++-16 3.22 + +Clang-16 CMake-3.23 + [Tags] clang-16 cmake-3.23 + clang-16 clang++-16 3.23 + +Clang-16 CMake-3.24 + [Tags] clang-16 cmake-3.24 + clang-16 clang++-16 3.24 + +Clang-16 CMake-3.25 + [Tags] clang-16 cmake-3.25 + clang-16 clang++-16 3.25 + +Clang-16 CMake-3.26 + [Tags] clang-16 cmake-3.26 + clang-16 clang++-16 3.26 + +Clang-16 CMake-3.27 + [Tags] clang-16 cmake-3.27 + clang-16 clang++-16 3.27 + +Clang-16 CMake-3.28 + [Tags] clang-16 cmake-3.28 + clang-16 clang++-16 3.28 + +Clang-16 CMake-3.29 + [Tags] clang-16 cmake-3.29 + clang-16 clang++-16 3.29 + +Clang-16 CMake-3.30 + [Tags] clang-16 cmake-3.30 + clang-16 clang++-16 3.30 + +Clang-17 CMake-3.22 + [Tags] clang-17 cmake-3.22 + clang-17 clang++-17 3.22 + +Clang-17 CMake-3.23 + [Tags] clang-17 cmake-3.23 + clang-17 clang++-17 3.23 + +Clang-17 CMake-3.24 + [Tags] clang-17 cmake-3.24 + clang-17 clang++-17 3.24 + +Clang-17 CMake-3.25 + [Tags] clang-17 cmake-3.25 + clang-17 clang++-17 3.25 + +Clang-17 CMake-3.26 + [Tags] clang-17 cmake-3.26 + clang-17 clang++-17 3.26 + +Clang-17 CMake-3.27 + [Tags] clang-17 cmake-3.27 + clang-17 clang++-17 3.27 + +Clang-17 CMake-3.28 + [Tags] clang-17 cmake-3.28 + clang-17 clang++-17 3.28 + +Clang-17 CMake-3.29 + [Tags] clang-17 cmake-3.29 + clang-17 clang++-17 3.29 + +Clang-17 CMake-3.30 + [Tags] clang-17 cmake-3.30 + clang-17 clang++-17 3.30 diff --git a/Tests/environ_tests.cc b/Tests/environ_tests.cc new file mode 100644 index 0000000..9cd15fb --- /dev/null +++ b/Tests/environ_tests.cc @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2023, Advanced Micro Devices. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "Capi/au/environ.h" + +#include "gtest/gtest.h" + +#include + +#if defined(WIN32) || defined(_WINDOWS) + auto homeEnv = "USERPROFILE"; +#else + auto homeEnv = "HOME"; +#endif + +namespace { + +TEST(Integration, au_env_get) +{ + EXPECT_STREQ(au_env_get(homeEnv), std::getenv(homeEnv)); +} + +TEST(Integration, au_env_set) +{ + au_env_set("MYNAME", "AOCL"); + EXPECT_STREQ(au_env_get("MYNAME"), "AOCL"); + + /* cleanup */ + au_env_unset("MYNAME"); +} + +TEST(Integration, au_env_is_enabled_true) +{ + { /* test uppercase TRUE */ + au_env_set("MYOPTION1", "TRUE"); + EXPECT_TRUE(au_env_is_enabled("MYOPTION1")); + au_env_unset("MYOPTION2"); + } + + { /* test lowercase 'true' */ + au_env_set("MYOPTION4", "true"); + EXPECT_TRUE(au_env_is_enabled("MYOPTION4")); + au_env_unset("MYOPTION4"); + } + + { /* mixed case 'TrUe' */ + au_env_set("MYOPTION31", "TrUe"); + EXPECT_TRUE(au_env_is_enabled("MYOPTION31")); + au_env_unset("MYOPTION31"); + } +} + +TEST(Integration, au_env_is_enabled_yes) +{ + { /* test for YES */ + au_env_set("MYOPTION3", "YES"); + EXPECT_TRUE(au_env_is_enabled("MYOPTION3")); + au_env_unset("MYOPTION3"); + } + { /* test lowercase 'yes' */ + au_env_set("MYOPTION5", "yes"); + EXPECT_TRUE(au_env_is_enabled("MYOPTION5")); + au_env_unset("MYOPTION5"); + } + + { /* test mixed 'yes' */ + au_env_set("MYOPTION51", "yEs"); + EXPECT_TRUE(au_env_is_enabled("MYOPTION51")); + au_env_unset("MYOPTION51"); + } +} + +TEST(Integration, au_env_is_enabled_on) +{ + { /* test lowercase 'on' */ + au_env_set("MYOPTION6", "on"); + EXPECT_TRUE(au_env_is_enabled("MYOPTION6")); + au_env_unset("MYOPTION6"); + } + { /* set to ON */ + au_env_set("MYOPTION2", "ON"); + EXPECT_TRUE(au_env_is_enabled("MYOPTION2")); + au_env_unset("MYOPTION2"); + } + + { /* set to 1 */ + au_env_set("MYOPTION21", "1"); + EXPECT_TRUE(au_env_is_enabled("MYOPTION21")); + au_env_unset("MYOPTION21"); + } +} + +TEST(Integration, au_env_is_enabled_other) +{ + + { /* garbage, should return false */ + au_env_set("MYOPTION4", "gArbAge"); + EXPECT_FALSE(au_env_is_enabled("MYOPTION4")); + au_env_unset("MYOPTION4"); + } + + { + au_env_set("MYOPTION41", "10"); + EXPECT_FALSE(au_env_is_enabled("MYOPTION41")); + au_env_unset("MYOPTION41"); + } + + { + au_env_set("MYOPTION42", "15.03"); + EXPECT_FALSE(au_env_is_enabled("MYOPTION42")); + au_env_unset("MYOPTION42"); + } +} + +TEST(Integration, au_env_is_set) +{ + + { /* garbage, should return false */ + EXPECT_FALSE(au_env_is_set("MYENV")); + au_env_set("MYENV", "gArbAge"); + EXPECT_TRUE(au_env_is_set("MYENV")); + au_env_unset("MYENV"); + } +} + +} // namespace diff --git a/docs/doxygen/Doxyfile b/docs/.doxygen/Doxyfile similarity index 95% rename from docs/doxygen/Doxyfile rename to docs/.doxygen/Doxyfile index edf2342..c3d30f3 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/.doxygen/Doxyfile @@ -1,4 +1,4 @@ -# Doxyfile 1.9.7 +# Doxyfile 1.10.0 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -42,13 +42,13 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = AOCL_Utils 4.2 +PROJECT_NAME = "AOCL UTILS" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = +PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a @@ -61,14 +61,20 @@ PROJECT_BRIEF = # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. -PROJECT_LOGO = AMD_Logo.png +PROJECT_LOGO = + +# With the PROJECT_ICON tag one can specify an icon that is included in the tabs +# when the HTML document is shown. Doxygen will copy the logo to the output +# directory. + +PROJECT_ICON = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. -OUTPUT_DIRECTORY = . +OUTPUT_DIRECTORY = /home/abhiram/aocl-utils-wt/AOCL-5.0-RC/build/docs/doxygen/ # If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096 # sub-directories (in 2 levels) under the output directory of each output format @@ -200,7 +206,7 @@ STRIP_FROM_INC_PATH = # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. -SHORT_NAMES = YES +SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief @@ -366,9 +372,9 @@ TOC_INCLUDE_HEADINGS = 5 # The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to # generate identifiers for the Markdown headings. Note: Every identifier is # unique. -# Possible values are: DOXYGEN Use a fixed 'autotoc_md' string followed by a -# sequence number starting at 0. and GITHUB Use the lower case version of title -# with any whitespace replaced by '-' and punctations characters removed.. +# Possible values are: DOXYGEN use a fixed 'autotoc_md' string followed by a +# sequence number starting at 0 and GITHUB use the lower case version of title +# with any whitespace replaced by '-' and punctuation characters removed. # The default value is: DOXYGEN. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. @@ -689,7 +695,7 @@ SORT_MEMBER_DOCS = YES # this will also influence the order of the classes in the class list. # The default value is: NO. -SORT_BRIEF_DOCS = YES +SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and @@ -701,7 +707,7 @@ SORT_BRIEF_DOCS = YES # detailed member documentation. # The default value is: NO. -SORT_MEMBERS_CTORS_1ST = YES +SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will @@ -718,7 +724,7 @@ SORT_GROUP_NAMES = NO # list. # The default value is: NO. -SORT_BY_SCOPE_NAME = YES +SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between @@ -777,14 +783,14 @@ MAX_INITIALIZER_LINES = 30 # list will mention the files that were used to generate the documentation. # The default value is: YES. -SHOW_USED_FILES = NO +SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. -SHOW_FILES = NO +SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the @@ -943,10 +949,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = ../../include/alci \ - BUILD.md \ - README.md - +INPUT = /home/abhiram/aocl-utils-wt/AOCL-5.0-RC/docs/.. # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv @@ -978,18 +981,22 @@ INPUT_FILE_ENCODING = # Note the list of default checked file patterns might differ from the list of # default file extension mappings. # -# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, -# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, -# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C -# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, -# *.vhdl, *.ucf, *.qsf and *.ice. +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cxxm, +# *.cpp, *.cppm, *.ccm, *.c++, *.c++m, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, +# *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.ixx, *.l, *.cs, *.d, +# *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to +# be provided as doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. FILE_PATTERNS = *.c \ *.cc \ *.cxx \ + *.cxxm \ *.cpp \ + *.cppm \ + *.ccm \ *.c++ \ + *.c++m \ *.java \ *.ii \ *.ixx \ @@ -1004,6 +1011,7 @@ FILE_PATTERNS = *.c \ *.hxx \ *.hpp \ *.h++ \ + *.ixx \ *.l \ *.cs \ *.d \ @@ -1045,7 +1053,7 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = +EXCLUDE = /home/abhiram/aocl-utils-wt/AOCL-5.0-RC/build # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded @@ -1069,7 +1077,7 @@ EXCLUDE_PATTERNS = # wildcard * is used, a substring. Examples: ANamespace, AClass, # ANamespace::AClass, ANamespace::*Test -EXCLUDE_SYMBOLS = +EXCLUDE_SYMBOLS = Impl # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include @@ -1181,7 +1189,8 @@ FORTRAN_COMMENT_AFTER = 72 SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, -# classes and enums directly into the documentation. +# multi-line macros, enums or list initialized variables directly into the +# documentation. # The default value is: NO. INLINE_SOURCES = NO @@ -1251,7 +1260,7 @@ USE_HTAGS = NO # See also: Section \class. # The default value is: YES. -VERBATIM_HEADERS = YES +VERBATIM_HEADERS = NO # If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the # clang parser (see: @@ -1302,7 +1311,7 @@ CLANG_DATABASE_PATH = # classes, structs, unions or interfaces. # The default value is: YES. -ALPHABETICAL_INDEX = NO +ALPHABETICAL_INDEX = YES # The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes) # that should be ignored while generating the index headers. The IGNORE_PREFIX @@ -1355,7 +1364,7 @@ HTML_FILE_EXTENSION = .html # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_HEADER = header.html +HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard @@ -1365,7 +1374,7 @@ HTML_HEADER = header.html # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_FOOTER = footer.html +HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of @@ -1395,8 +1404,7 @@ HTML_STYLESHEET = # documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_STYLESHEET = doxygen-awesome.css \ - doxygen-awesome-sidebar-only.css +HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note @@ -1406,8 +1414,7 @@ HTML_EXTRA_STYLESHEET = doxygen-awesome.css \ # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_FILES = doxygen-fragment-copy-button.js \ - doxygen-interactive-toc.js +HTML_EXTRA_FILES = # The HTML_COLORSTYLE tag can be used to specify if the generated HTML output # should be rendered with a dark or light theme. @@ -1471,6 +1478,33 @@ HTML_DYNAMIC_MENUS = YES HTML_DYNAMIC_SECTIONS = NO +# If the HTML_CODE_FOLDING tag is set to YES then classes and functions can be +# dynamically folded and expanded in the generated HTML source code. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_CODE_FOLDING = YES + +# If the HTML_COPY_CLIPBOARD tag is set to YES then doxygen will show an icon in +# the top right corner of code and text fragments that allows the user to copy +# its content to the clipboard. Note this only works if supported by the browser +# and the web page is served via a secure context (see: +# https://www.w3.org/TR/secure-contexts/), i.e. using the https: or file: +# protocol. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COPY_CLIPBOARD = YES + +# Doxygen stores a couple of settings persistently in the browser (via e.g. +# cookies). By default these settings apply to all HTML pages generated by +# doxygen across all projects. The HTML_PROJECT_COOKIE tag can be used to store +# the settings under a project specific key, such that the user preferences will +# be stored separately. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_PROJECT_COOKIE = + # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to @@ -1721,7 +1755,7 @@ DISABLE_INDEX = NO # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. -GENERATE_TREEVIEW = YES +GENERATE_TREEVIEW = NO # When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the # FULL_SIDEBAR option determines if the side bar is limited to only the treeview @@ -1743,7 +1777,7 @@ FULL_SIDEBAR = NO # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. -ENUM_VALUES_PER_LINE = 1 +ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. @@ -2099,7 +2133,7 @@ PDF_HYPERLINKS = YES USE_PDFLATEX = YES -# The LATEX_BATCHMODE tag ignals the behavior of LaTeX in case of an error. +# The LATEX_BATCHMODE tag signals the behavior of LaTeX in case of an error. # Possible values are: NO same as ERROR_STOP, YES same as BATCH, BATCH In batch # mode nothing is printed on the terminal, errors are scrolled as if is # hit at every error; missing files that TeX tries to input or request from @@ -2245,7 +2279,7 @@ MAN_LINKS = NO # captures the structure of the code including all documentation. # The default value is: NO. -GENERATE_XML = NO +GENERATE_XML = YES # The XML_OUTPUT tag is used to specify where the XML pages will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of @@ -2305,6 +2339,28 @@ GENERATE_AUTOGEN_DEF = NO # Configuration options related to Sqlite3 output #--------------------------------------------------------------------------- +# If the GENERATE_SQLITE3 tag is set to YES doxygen will generate a Sqlite3 +# database with symbols found by doxygen stored in tables. +# The default value is: NO. + +GENERATE_SQLITE3 = NO + +# The SQLITE3_OUTPUT tag is used to specify where the Sqlite3 database will be +# put. If a relative path is entered the value of OUTPUT_DIRECTORY will be put +# in front of it. +# The default directory is: sqlite3. +# This tag requires that the tag GENERATE_SQLITE3 is set to YES. + +SQLITE3_OUTPUT = sqlite3 + +# The SQLITE3_RECREATE_DB tag is set to YES, the existing doxygen_sqlite3.db +# database file will be recreated with each doxygen run. If set to NO, doxygen +# will warn if a database file is already found and not modify it. +# The default value is: YES. +# This tag requires that the tag GENERATE_SQLITE3 is set to YES. + +SQLITE3_RECREATE_DB = YES + #--------------------------------------------------------------------------- # Configuration options related to the Perl module output #--------------------------------------------------------------------------- @@ -2368,7 +2424,7 @@ MACRO_EXPANSION = YES # The default value is: NO. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -EXPAND_ONLY_PREDEF = YES +EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES, the include files in the # INCLUDE_PATH will be searched if a #include is found. @@ -2383,7 +2439,7 @@ SEARCH_INCLUDES = YES # RECURSIVE has no effect here. # This tag requires that the tag SEARCH_INCLUDES is set to YES. -INCLUDE_PATH = +INCLUDE_PATH =/home/abhiram/aocl-utils-wt/AOCL-5.0-RC/docs/../Library/Private /home/abhiram/aocl-utils-wt/AOCL-5.0-RC/docs/../SDK/Include # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the @@ -2401,7 +2457,7 @@ INCLUDE_FILE_PATTERNS = # recursively expanded use the := operator instead of the = operator. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -PREDEFINED = +PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The @@ -2447,15 +2503,15 @@ TAGFILES = GENERATE_TAGFILE = -# If the ALLEXTERNALS tag is set to YES, all external class will be listed in -# the class index. If set to NO, only the inherited external classes will be -# listed. +# If the ALLEXTERNALS tag is set to YES, all external classes and namespaces +# will be listed in the class and namespace index. If set to NO, only the +# inherited external classes will be listed. # The default value is: NO. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will be +# in the topic index. If set to NO, only the current project's groups will be # listed. # The default value is: YES. @@ -2540,7 +2596,11 @@ DOT_FONTPATH = # the CLASS_GRAPH tag is set to YES and HAVE_DOT is disabled or if the # CLASS_GRAPH tag is set to BUILTIN, then the built-in generator will be used. # If the CLASS_GRAPH tag is set to TEXT the direct and indirect inheritance -# relations will be shown as texts / links. +# relations will be shown as texts / links. Explicit enabling an inheritance +# graph or choosing a different representation for an inheritance graph of a +# specific class, can be accomplished by means of the command \inheritancegraph. +# Disabling an inheritance graph can be accomplished by means of the command +# \hideinheritancegraph. # Possible values are: NO, YES, TEXT, GRAPH and BUILTIN. # The default value is: YES. @@ -2549,15 +2609,21 @@ CLASS_GRAPH = YES # If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a # graph for each documented class showing the direct and indirect implementation # dependencies (inheritance, containment, and class references variables) of the -# class with other documented classes. +# class with other documented classes. Explicit enabling a collaboration graph, +# when COLLABORATION_GRAPH is set to NO, can be accomplished by means of the +# command \collaborationgraph. Disabling a collaboration graph can be +# accomplished by means of the command \hidecollaborationgraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for -# groups, showing the direct groups dependencies. See also the chapter Grouping -# in the manual. +# groups, showing the direct groups dependencies. Explicit enabling a group +# dependency graph, when GROUP_GRAPHS is set to NO, can be accomplished by means +# of the command \groupgraph. Disabling a directory graph can be accomplished by +# means of the command \hidegroupgraph. See also the chapter Grouping in the +# manual. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2599,8 +2665,8 @@ DOT_UML_DETAILS = NO # The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters # to display on a single line. If the actual line length exceeds this threshold -# significantly it will wrapped across multiple lines. Some heuristics are apply -# to avoid ugly line breaks. +# significantly it will be wrapped across multiple lines. Some heuristics are +# applied to avoid ugly line breaks. # Minimum value: 0, maximum value: 1000, default value: 17. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2617,7 +2683,9 @@ TEMPLATE_RELATIONS = NO # If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to # YES then doxygen will generate a graph for each documented file showing the # direct and indirect include dependencies of the file with other documented -# files. +# files. Explicit enabling an include graph, when INCLUDE_GRAPH is is set to NO, +# can be accomplished by means of the command \includegraph. Disabling an +# include graph can be accomplished by means of the command \hideincludegraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2626,7 +2694,10 @@ INCLUDE_GRAPH = YES # If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are # set to YES then doxygen will generate a graph for each documented file showing # the direct and indirect include dependencies of the file with other documented -# files. +# files. Explicit enabling an included by graph, when INCLUDED_BY_GRAPH is set +# to NO, can be accomplished by means of the command \includedbygraph. Disabling +# an included by graph can be accomplished by means of the command +# \hideincludedbygraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2666,7 +2737,10 @@ GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the # dependencies a directory has on other directories in a graphical way. The # dependency relations are determined by the #include relations between the -# files in the directories. +# files in the directories. Explicit enabling a directory graph, when +# DIRECTORY_GRAPH is set to NO, can be accomplished by means of the command +# \directorygraph. Disabling a directory graph can be accomplished by means of +# the command \hidedirectorygraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/docs/.sphinx/_toc.yml b/docs/.sphinx/_toc.yml new file mode 100644 index 0000000..dde9257 --- /dev/null +++ b/docs/.sphinx/_toc.yml @@ -0,0 +1 @@ +root: index \ No newline at end of file diff --git a/docs/.sphinx/_toc.yml.in b/docs/.sphinx/_toc.yml.in new file mode 100644 index 0000000..dde9257 --- /dev/null +++ b/docs/.sphinx/_toc.yml.in @@ -0,0 +1 @@ +root: index \ No newline at end of file diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt new file mode 100644 index 0000000..cdde7f8 --- /dev/null +++ b/docs/CMakeLists.txt @@ -0,0 +1,87 @@ +# +# Copyright (C) 2024, Advanced Micro Devices. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMake") +include(FindSphinx) +find_package(Sphinx) +find_package(Doxygen REQUIRED) +find_package(Sphinx REQUIRED) + + +set(DOXYGEN_INPUT_DIR ${PROJECT_SOURCE_DIR}) +set(DOXYGEN_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/doxygen) +set(DOXYGEN_INDEX_FILE ${DOXYGEN_OUTPUT_DIR}/xml/index.xml) +set(DOXYFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in) +set(DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) +set(DOXYFILE_OUT ${CMAKE_CURRENT_SOURCE_DIR}/.doxygen/Doxyfile) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/.doxygen) +file(MAKE_DIRECTORY ${DOXYGEN_OUTPUT_DIR}) +file(MAKE_DIRECTORY ${DOXYGEN_OUTPUT_DIR}/xml) +file(MAKE_DIRECTORY ${DOXYGEN_OUTPUT_DIR}/html) +# Replace variables inside @@ with the current values +message(${DOXYFILE_IN}) +message(${DOXYFILE_OUT}) +configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY) + +# Doxygen won't create this for us + +# Only regenerate Doxygen when the Doxyfile or public headers change +add_custom_command(OUTPUT ${DOXYGEN_INDEX_FILE} + COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT} + MAIN_DEPENDENCY ${DOXYFILE_OUT} ${DOXYFILE_IN} + COMMENT "Generating docs" + VERBATIM) + +# Nice named target so we can run the job easily +add_custom_target(Doxygen ALL DEPENDS ${DOXYGEN_INDEX_FILE}) + +set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}) +file(MAKE_DIRECTORY ${SPHINX_SOURCE}/.sphinx) +set(SPHINX_BUILD ${SPHINX_SOURCE}/sphinx/_build/html) +set(SPHINX_INDEX_FILE ${SPHINX_BUILD}/index.html) + +add_custom_command(OUTPUT ${SPHINX_INDEX_FILE} + COMMAND + ${SPHINX_EXECUTABLE} -b html + # Tell Breathe where to find the Doxygen output + -Dbreathe_projects.aoclutils=${DOXYGEN_OUTPUT_DIR}/xml + ${SPHINX_SOURCE} ${SPHINX_BUILD} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS + # Other docs files you want to track should go here (or in some variable) + ${CMAKE_CURRENT_SOURCE_DIR}/index.rst + ${DOXYGEN_INDEX_FILE} + MAIN_DEPENDENCY ${SPHINX_SOURCE}/conf.py + COMMENT "Generating documentation with Sphinx") + +# Nice named target so we can run the job easily +add_custom_target(Sphinx ALL DEPENDS ${SPHINX_INDEX_FILE}) + +# Add an install target to install the docs +include(GNUInstallDirs) +install(DIRECTORY ${SPHINX_BUILD} +DESTINATION ${CMAKE_INSTALL_DOCDIR}) diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in new file mode 100644 index 0000000..9d22a52 --- /dev/null +++ b/docs/Doxyfile.in @@ -0,0 +1,2893 @@ +# Doxyfile 1.10.0 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). +# +# Note: +# +# Use doxygen to compare the used configuration file with the template +# configuration file: +# doxygen -x [configFile] +# Use doxygen to compare the used configuration file with the template +# configuration file without replacing the environment variables or CMake type +# replacement variables: +# doxygen -x_noenv [configFile] + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "AOCL UTILS" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# With the PROJECT_ICON tag one can specify an icon that is included in the tabs +# when the HTML document is shown. Doxygen will copy the logo to the output +# directory. + +PROJECT_ICON = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = @CMAKE_CURRENT_BINARY_DIR@/doxygen/ + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096 +# sub-directories (in 2 levels) under the output directory of each output format +# and will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to +# control the number of sub-directories. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# Controls the number of sub-directories that will be created when +# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every +# level increment doubles the number of directories, resulting in 4096 +# directories at level 8 which is the default and also the maximum value. The +# sub-directories are organized in 2 levels, the first level always has a fixed +# number of 16 directories. +# Minimum value: 0, maximum value: 8, default value: 8. +# This tag requires that the tag CREATE_SUBDIRS is set to YES. + +CREATE_SUBDIRS_LEVEL = 8 + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian, +# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English +# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek, +# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with +# English messages), Korean, Korean-en (Korean with English messages), Latvian, +# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, +# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, +# Swedish, Turkish, Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# By default Python docstrings are displayed as preformatted text and doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:^^" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". Note that you cannot put \n's in the value part of an alias +# to insert newlines (in the resulting output). You can put ^^ in the value part +# of an alias to insert a newline as if a physical newline was in the original +# file. When you need a literal { or } or , in the value part of an alias you +# have to escape them by means of a backslash (\), this can lead to conflicts +# with the commands \{ and \} for these it is advised to use the version @{ and +# @} or use a double escape (\\{ and \\}) + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, +# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files). For instance to make doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + +# The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to +# generate identifiers for the Markdown headings. Note: Every identifier is +# unique. +# Possible values are: DOXYGEN use a fixed 'autotoc_md' string followed by a +# sequence number starting at 0 and GITHUB use the lower case version of title +# with any whitespace replaced by '-' and punctuation characters removed. +# The default value is: DOXYGEN. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +MARKDOWN_ID_STYLE = DOXYGEN + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use +# during processing. When set to 0 doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which effectively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 + +# If the TIMESTAMP tag is set different from NO then each generated page will +# contain the date or date and time when the page was generated. Setting this to +# NO can help when comparing the output of multiple runs. +# Possible values are: YES, NO, DATETIME and DATE. +# The default value is: NO. + +TIMESTAMP = NO + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# will also hide undocumented C++ concepts if enabled. This option has no effect +# if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# declarations. If set to NO, these declarations will be included in the +# documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and MacOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. +# Possible values are: SYSTEM, NO and YES. +# The default value is: SYSTEM. + +CASE_SENSE_NAMES = SYSTEM + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class +# will show which file needs to be included to use the class. +# The default value is: YES. + +SHOW_HEADERFILE = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. See also section "Changing the +# layout of pages" for information. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as documenting some parameters in +# a documented function twice, or documenting parameters that don't exist or +# using markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete +# function parameter documentation. If set to NO, doxygen will accept that some +# parameters have no documentation without warning. +# The default value is: YES. + +WARN_IF_INCOMPLETE_DOC = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong parameter +# documentation, but not about the absence of documentation. If EXTRACT_ALL is +# set to YES then this flag will automatically be disabled. See also +# WARN_IF_INCOMPLETE_DOC +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about +# undocumented enumeration values. If set to NO, doxygen will accept +# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: NO. + +WARN_IF_UNDOC_ENUM_VAL = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then doxygen behaves +# like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined doxygen will not +# write the warning messages in between other messages but write them at the end +# of a run, in case a WARN_LOGFILE is defined the warning messages will be +# besides being in the defined file also be shown at the end of a run, unless +# the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case +# the behavior will remain as with the setting FAIL_ON_WARNINGS. +# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# See also: WARN_LINE_FORMAT +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# In the $text part of the WARN_FORMAT command it is possible that a reference +# to a more specific place is given. To make it easier to jump to this place +# (outside of doxygen) the user can define a custom "cut" / "paste" string. +# Example: +# WARN_LINE_FORMAT = "'vi $file +$line'" +# See also: WARN_FORMAT +# The default value is: at line $line of file $file. + +WARN_LINE_FORMAT = "at line $line of file $file" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). In case the file specified cannot be opened for writing the +# warning and error messages are written to standard error. When as file - is +# specified the warning and error messages are written to standard output +# (stdout). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = @CMAKE_CURRENT_SOURCE_DIR@/.. +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# See also: INPUT_FILE_ENCODING +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify +# character encoding on a per file pattern basis. Doxygen will compare the file +# name with each pattern and apply the encoding instead of the default +# INPUT_ENCODING) if there is a match. The character encodings are a list of the +# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding +# "INPUT_ENCODING" for further information on supported encodings. + +INPUT_FILE_ENCODING = + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cxxm, +# *.cpp, *.cppm, *.ccm, *.c++, *.c++m, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, +# *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.ixx, *.l, *.cs, *.d, +# *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to +# be provided as doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cxxm \ + *.cpp \ + *.cppm \ + *.ccm \ + *.c++ \ + *.c++m \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.ixx \ + *.l \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f18 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.ice + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = @CMAKE_BINARY_DIR@ + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# ANamespace::AClass, ANamespace::*Test + +EXCLUDE_SYMBOLS = Impl + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that doxygen will use the data processed and written to standard output +# for further processing, therefore nothing else, like debug statements or used +# commands (so in case of a Windows batch file always use @echo OFF), should be +# written to standard output. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +# The Fortran standard specifies that for fixed formatted Fortran code all +# characters from position 72 are to be considered as comment. A common +# extension is to allow longer lines before the automatic comment starts. The +# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can +# be processed before the automatic comment starts. +# Minimum value: 7, maximum value: 10000, default value: 72. + +FORTRAN_COMMENT_AFTER = 72 + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# multi-line macros, enums or list initialized variables directly into the +# documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = NO + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: +# http://clang.llvm.org/) for more accurate parsing at the cost of reduced +# performance. This can be particularly helpful with template rich C++ code for +# which doxygen's built-in parser lacks the necessary type information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS +# tag is set to YES then doxygen will add the directory of each input to the +# include path. +# The default value is: YES. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_ADD_INC_PATHS = YES + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the directory containing a file called compile_commands.json. This +# file is the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the +# options used when the source files were built. This is equivalent to +# specifying the -p option to a clang tool, such as clang-check. These options +# will then be passed to the parser. Any options specified with CLANG_OPTIONS +# will be added as well. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes) +# that should be ignored while generating the index headers. The IGNORE_PREFIX +# tag works for classes, function and member names. The entity will be placed in +# the alphabetical list under the first letter of the entity name that remains +# after removing the prefix. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). +# Note: Since the styling of scrollbars can currently not be overruled in +# Webkit/Chromium, the styling will be left out of the default doxygen.css if +# one or more extra stylesheets have been specified. So if scrollbar +# customization is desired it has to be added explicitly. For an example see the +# documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output +# should be rendered with a dark or light theme. +# Possible values are: LIGHT always generate light mode output, DARK always +# generate dark mode output, AUTO_LIGHT automatically set the mode according to +# the user preference, use light mode if no preference is set (the default), +# AUTO_DARK automatically set the mode according to the user preference, use +# dark mode if no preference is set and TOGGLE allow to user to switch between +# light and dark mode via a button. +# The default value is: AUTO_LIGHT. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE = AUTO_LIGHT + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a color-wheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use gray-scales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# If the HTML_CODE_FOLDING tag is set to YES then classes and functions can be +# dynamically folded and expanded in the generated HTML source code. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_CODE_FOLDING = YES + +# If the HTML_COPY_CLIPBOARD tag is set to YES then doxygen will show an icon in +# the top right corner of code and text fragments that allows the user to copy +# its content to the clipboard. Note this only works if supported by the browser +# and the web page is served via a secure context (see: +# https://www.w3.org/TR/secure-contexts/), i.e. using the https: or file: +# protocol. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COPY_CLIPBOARD = YES + +# Doxygen stores a couple of settings persistently in the browser (via e.g. +# cookies). By default these settings apply to all HTML pages generated by +# doxygen across all projects. The HTML_PROJECT_COOKIE tag can be used to store +# the settings under a project specific key, such that the user preferences will +# be stored separately. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_PROJECT_COOKIE = + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag determines the URL of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDURL = + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# on Windows. In the beginning of 2021 Microsoft took the original page, with +# a.o. the download links, offline the HTML help workshop was already many years +# in maintenance mode). You can download the HTML help workshop from the web +# archives at Installation executable (see: +# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo +# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the main .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# The SITEMAP_URL tag is used to specify the full URL of the place where the +# generated documentation will be placed on the server by the user during the +# deployment of the documentation. The generated sitemap is called sitemap.xml +# and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL +# is specified no sitemap is generated. For information about the sitemap +# protocol see https://www.sitemaps.org +# This tag requires that the tag GENERATE_HTML is set to YES. + +SITEMAP_URL = + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# run qhelpgenerator on the generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine tune the look of the index (see "Fine-tuning the output"). As an +# example, the default style sheet generated by doxygen has an example that +# shows how to put an image at the root of the tree instead of the PROJECT_NAME. +# Since the tree basically has the same information as the tab index, you could +# consider setting DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the +# FULL_SIDEBAR option determines if the side bar is limited to only the treeview +# area (value NO) or if it should extend to the full height of the window (value +# YES). Setting this to YES gives a layout similar to +# https://docs.readthedocs.io with more room for contents, but less room for the +# project logo, title, and description. If either GENERATE_TREEVIEW or +# DISABLE_INDEX is set to NO, this option has no effect. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FULL_SIDEBAR = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email +# addresses. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +OBFUSCATE_EMAILS = YES + +# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side JavaScript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# With MATHJAX_VERSION it is possible to specify the MathJax version to be used. +# Note that the different versions of MathJax have different requirements with +# regards to the different settings, so it is possible that also other MathJax +# settings have to be changed when switching between the different MathJax +# versions. +# Possible values are: MathJax_2 and MathJax_3. +# The default value is: MathJax_2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_VERSION = MathJax_2 + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. For more details about the output format see MathJax +# version 2 (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 +# (see: +# http://docs.mathjax.org/en/latest/web/components/output.html). +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility. This is the name for Mathjax version 2, for MathJax version 3 +# this will be translated into chtml), NativeMML (i.e. MathML. Only supported +# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This +# is the name for Mathjax version 3, for MathJax version 2 this will be +# translated into HTML-CSS) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. The default value is: +# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 +# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# for MathJax version 2 (see +# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# For example for MathJax version 3 (see +# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): +# MATHJAX_EXTENSIONS = ams +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /