diff --git a/CMakeLists.txt b/CMakeLists.txt index 321529d52..8385d8a7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -329,7 +329,7 @@ set(GNSSSDR_GPSTK_LOCAL_VERSION "3.0.0") set(GNSSSDR_MATIO_LOCAL_VERSION "1.5.18") set(GNSSSDR_PUGIXML_LOCAL_VERSION "1.10") set(GNSSSDR_PROTOCOLBUFFERS_LOCAL_VERSION "3.13.0") -set(GNSSSDR_BENCHMARK_LOCAL_VERSION "1.5.1") +set(GNSSSDR_BENCHMARK_LOCAL_VERSION "1.5.2") if(CMAKE_VERSION VERSION_LESS "3.0.2") set(GNSSSDR_GFLAGS_LOCAL_VERSION "2.2.1") # Fix for CentOS 7 @@ -1117,6 +1117,7 @@ if(NOT VOLKGNSSSDR_FOUND) ) endif() endif() + include(GNUInstallDirs) if(CMAKE_VERSION VERSION_LESS 3.2) ExternalProject_Add(volk_gnsssdr_module PREFIX ${CMAKE_BINARY_DIR}/volk_gnsssdr_module @@ -1143,6 +1144,7 @@ if(NOT VOLKGNSSSDR_FOUND) BUILD_COMMAND ${VOLK_GNSSSDR_BUILD_COMMAND} volk_gnsssdr_profile BUILD_BYPRODUCTS ${CMAKE_BINARY_DIR}/volk_gnsssdr_module/install/lib/${CMAKE_FIND_LIBRARY_PREFIXES}volk_gnsssdr${CMAKE_STATIC_LIBRARY_SUFFIX} ${CMAKE_BINARY_DIR}/volk_gnsssdr_module/install/bin/volk_gnsssdr_profile + ${CMAKE_BINARY_DIR}/volk_gnsssdr_module/install/${CMAKE_INSTALL_LIBDIR}/${CMAKE_FIND_LIBRARY_PREFIXES}cpu_features${CMAKE_STATIC_LIBRARY_SUFFIX} INSTALL_DIR ${CMAKE_BINARY_DIR}/volk_gnsssdr_module/install ) endif() @@ -1168,6 +1170,11 @@ if(NOT VOLKGNSSSDR_FOUND) INTERFACE_INCLUDE_DIRECTORIES "${VOLK_GNSSSDR_INCLUDE_DIRS}" INTERFACE_LINK_LIBRARIES "${VOLK_GNSSSDR_LIBRARIES}" ) + if(CMAKE_VERSION VERSION_GREATER 3.0) + set_target_properties(Volkgnsssdr::volkgnsssdr PROPERTIES + INTERFACE_LINK_LIBRARIES ${CMAKE_BINARY_DIR}/volk_gnsssdr_module/install/${CMAKE_INSTALL_LIBDIR}/${CMAKE_FIND_LIBRARY_PREFIXES}cpu_features${CMAKE_STATIC_LIBRARY_SUFFIX} + ) + endif() endif() if(CMAKE_VERSION VERSION_LESS 3.2) diff --git a/LICENSES/Apache-2.0.txt b/LICENSES/Apache-2.0.txt new file mode 100644 index 000000000..4ed90b952 --- /dev/null +++ b/LICENSES/Apache-2.0.txt @@ -0,0 +1,208 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, +AND DISTRIBUTION + + 1. Definitions. + + + +"License" shall mean the terms and conditions for use, reproduction, and distribution +as defined by Sections 1 through 9 of this document. + + + +"Licensor" shall mean the copyright owner or entity authorized by the copyright +owner that is granting the License. + + + +"Legal Entity" shall mean the union of the acting entity and all other entities +that control, are controlled by, or are under common control with that entity. +For the purposes of this definition, "control" means (i) the power, direct +or indirect, to cause the direction or management of such entity, whether +by contract or otherwise, or (ii) ownership of fifty percent (50%) or more +of the outstanding shares, or (iii) beneficial ownership of such entity. + + + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions +granted by this License. + + + +"Source" form shall mean the preferred form for making modifications, including +but not limited to software source code, documentation source, and configuration +files. + + + +"Object" form shall mean any form resulting from mechanical transformation +or translation of a Source form, including but not limited to compiled object +code, generated documentation, and conversions to other media types. + + + +"Work" shall mean the work of authorship, whether in Source or Object form, +made available under the License, as indicated by a copyright notice that +is included in or attached to the work (an example is provided in the Appendix +below). + + + +"Derivative Works" shall mean any work, whether in Source or Object form, +that is based on (or derived from) the Work and for which the editorial revisions, +annotations, elaborations, or other modifications represent, as a whole, an +original work of authorship. For the purposes of this License, Derivative +Works shall not include works that remain separable from, or merely link (or +bind by name) to the interfaces of, the Work and Derivative Works thereof. + + + +"Contribution" shall mean any work of authorship, including the original version +of the Work and any modifications or additions to that Work or Derivative +Works thereof, that is intentionally submitted to Licensor for inclusion in +the Work by the copyright owner or by an individual or Legal Entity authorized +to submit on behalf of the copyright owner. For the purposes of this definition, +"submitted" means any form of electronic, verbal, or written communication +sent to the Licensor or its representatives, including but not limited to +communication on electronic mailing lists, source code control systems, and +issue tracking systems that are managed by, or on behalf of, the Licensor +for the purpose of discussing and improving the Work, but excluding communication +that is conspicuously marked or otherwise designated in writing by the copyright +owner as "Not a Contribution." + + + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf +of whom a Contribution has been received by Licensor and subsequently incorporated +within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this +License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable copyright license to reproduce, prepare +Derivative Works of, publicly display, publicly perform, sublicense, and distribute +the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, +each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) patent +license to make, have made, use, offer to sell, sell, import, and otherwise +transfer the Work, where such license applies only to those patent claims +licensable by such Contributor that are necessarily infringed by their Contribution(s) +alone or by combination of their Contribution(s) with the Work to which such +Contribution(s) was submitted. If You institute patent litigation against +any entity (including a cross-claim or counterclaim in a lawsuit) alleging +that the Work or a Contribution incorporated within the Work constitutes direct +or contributory patent infringement, then any patent licenses granted to You +under this License for that Work shall terminate as of the date such litigation +is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or +Derivative Works thereof in any medium, with or without modifications, and +in Source or Object form, provided that You meet the following conditions: + +(a) You must give any other recipients of the Work or Derivative Works a copy +of this License; and + +(b) You must cause any modified files to carry prominent notices stating that +You changed the files; and + +(c) You must retain, in the Source form of any Derivative Works that You distribute, +all copyright, patent, trademark, and attribution notices from the Source +form of the Work, excluding those notices that do not pertain to any part +of the Derivative Works; and + +(d) If the Work includes a "NOTICE" text file as part of its distribution, +then any Derivative Works that You distribute must include a readable copy +of the attribution notices contained within such NOTICE file, excluding those +notices that do not pertain to any part of the Derivative Works, in at least +one of the following places: within a NOTICE text file distributed as part +of the Derivative Works; within the Source form or documentation, if provided +along with the Derivative Works; or, within a display generated by the Derivative +Works, if and wherever such third-party notices normally appear. The contents +of the NOTICE file are for informational purposes only and do not modify the +License. You may add Your own attribution notices within Derivative Works +that You distribute, alongside or as an addendum to the NOTICE text from the +Work, provided that such additional attribution notices cannot be construed +as modifying the License. + +You may add Your own copyright statement to Your modifications and may provide +additional or different license terms and conditions for use, reproduction, +or distribution of Your modifications, or for any such Derivative Works as +a whole, provided Your use, reproduction, and distribution of the Work otherwise +complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any +Contribution intentionally submitted for inclusion in the Work by You to the +Licensor shall be under the terms and conditions of this License, without +any additional terms or conditions. Notwithstanding the above, nothing herein +shall supersede or modify the terms of any separate license agreement you +may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, +trademarks, service marks, or product names of the Licensor, except as required +for reasonable and customary use in describing the origin of the Work and +reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to +in writing, Licensor provides the Work (and each Contributor provides its +Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied, including, without limitation, any warranties +or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR +A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness +of using or redistributing the Work and assume any risks associated with Your +exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether +in tort (including negligence), contract, or otherwise, unless required by +applicable law (such as deliberate and grossly negligent acts) or agreed to +in writing, shall any Contributor be liable to You for damages, including +any direct, indirect, special, incidental, or consequential damages of any +character arising as a result of this License or out of the use or inability +to use the Work (including but not limited to damages for loss of goodwill, +work stoppage, computer failure or malfunction, or any and all other commercial +damages or losses), even if such Contributor has been advised of the possibility +of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work +or Derivative Works thereof, You may choose to offer, and charge a fee for, +acceptance of support, warranty, indemnity, or other liability obligations +and/or rights consistent with this License. However, in accepting such obligations, +You may act only on Your own behalf and on Your sole responsibility, not on +behalf of any other Contributor, and only if You agree to indemnify, defend, +and hold each Contributor harmless for any liability incurred by, or claims +asserted against, such Contributor by reason of your accepting any such warranty +or additional liability. END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate +notice, with the fields enclosed by brackets "[]" replaced with your own identifying +information. (Don't include the brackets!) The text should be enclosed in +the appropriate comment syntax for the file format. We also recommend that +a file or class name and description of purpose be included on the same "printed +page" as the copyright notice for easier identification within third-party +archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); + +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software + +distributed under the License is distributed on an "AS IS" BASIS, + +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +See the License for the specific language governing permissions and + +limitations under the License. diff --git a/docs/changelog.md b/docs/changelog.md index 5a365509f..02fd9c432 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -31,6 +31,15 @@ SPDX-FileCopyrightText: 2011-2020 Carles Fernandez-Prades = 5.2 - // arma::mat C_e_n = {{-sin_lat * cos_long, -sin_lat * sin_long, cos_lat}, - // {-sin_long, cos_long, 0}, - // {-cos_lat * cos_long, -cos_lat * sin_long, -sin_lat}}; //ECEF to Geo - arma::mat C_e_n = arma::zeros(3, 3); - C_e_n << -sin_lat * cos_long << -sin_lat * sin_long << cos_lat << arma::endr - << -sin_long << cos_long << 0 << arma::endr - << -cos_lat * cos_long << -cos_lat * sin_long << -sin_lat << arma::endr; // ECEF to Geo + + arma::mat C_e_n = {{-sin_lat * cos_long, -sin_lat * sin_long, cos_lat}, + {-sin_long, cos_long, 0}, + {-cos_lat * cos_long, -cos_lat * sin_long, -sin_lat}}; // ECEF to Geo + // Transform velocity using (2.73) v_eb_n = C_e_n * v_eb_e; @@ -417,14 +408,9 @@ void Geo_to_ECEF(const arma::vec &LLH, const arma::vec &v_eb_n, const arma::mat ((1 - e * e) * R_E + LLH(2)) * sin_lat}; // Calculate ECEF to Geo coordinate transformation matrix using (2.150) - // C++11 and arma>=5.2 - // arma::mat C_e_n = {{-sin_lat * cos_long, -sin_lat * sin_long, cos_lat}, - // {-sin_long, cos_long, 0}, - // {-cos_lat * cos_long, -cos_lat * sin_long, -sin_lat}}; - arma::mat C_e_n = arma::zeros(3, 3); - C_e_n << -sin_lat * cos_long << -sin_lat * sin_long << cos_lat << arma::endr - << -sin_long << cos_long << 0 << arma::endr - << -cos_lat * cos_long << -cos_lat * sin_long << -sin_lat << arma::endr; + arma::mat C_e_n = {{-sin_lat * cos_long, -sin_lat * sin_long, cos_lat}, + {-sin_long, cos_long, 0}, + {-cos_lat * cos_long, -cos_lat * sin_long, -sin_lat}}; // Transform velocity using (2.73) v_eb_e = C_e_n.t() * v_eb_n; @@ -453,10 +439,9 @@ void pv_Geo_to_ECEF(double L_b, double lambda_b, double h_b, const arma::vec &v_ ((1 - pow(e, 2)) * R_E + h_b) * sin_lat}; // Calculate ECEF to Geo coordinate transformation matrix using (2.150) - arma::mat C_e_n = arma::zeros(3, 3); - C_e_n << -sin_lat * cos_long << -sin_lat * sin_long << cos_lat << arma::endr - << -sin_long << cos_long << 0 << arma::endr - << -cos_lat * cos_long << -cos_lat * sin_long << -sin_lat << arma::endr; + arma::mat C_e_n = {{-sin_lat * cos_long, -sin_lat * sin_long, cos_lat}, + {-sin_long, cos_long, 0.0}, + {-cos_lat * cos_long, -cos_lat * sin_long, -sin_lat}}; // Transform velocity using (2.73) v_eb_e = C_e_n.t() * v_eb_n; diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/.gitignore b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/.gitignore index d7aaca528..1a5b58e41 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/.gitignore +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/.gitignore @@ -8,3 +8,4 @@ build/ .project .cproject /.DS_Store +/gen/volk_gnsssdr_arch_defs.py diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/CMakeLists.txt b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/CMakeLists.txt index 3e830bdb8..7efcab86c 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/CMakeLists.txt +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/CMakeLists.txt @@ -227,6 +227,16 @@ endif() # Dependencies setup ######################################################################## +# cpu_features +if(CMAKE_VERSION VERSION_GREATER 3.0) + set(BUILD_PIC ON CACHE BOOL + "Build cpu_features with Position Independent Code (PIC)." + FORCE + ) + set(USE_CPU_FEATURES ON) + add_subdirectory(cpu_features) +endif() + # Python include(VolkPython) # sets PYTHON_EXECUTABLE volk_python_check_module("python >= 2.7" sys "sys.version.split()[0] >= '2.7'" PYTHON_MIN_VER_FOUND) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/CMakeLists.txt b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/CMakeLists.txt index 77a359912..9fac8694a 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/CMakeLists.txt +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/apps/CMakeLists.txt @@ -53,7 +53,7 @@ target_include_directories(volk_gnsssdr_profile PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ) -if(NOT ${FILESYSTEM_FOUND}) +if(NOT FILESYSTEM_FOUND) target_include_directories(volk_gnsssdr_profile PUBLIC ${Boost_INCLUDE_DIRS} ) @@ -61,7 +61,7 @@ if(NOT ${FILESYSTEM_FOUND}) endif() -if(${FILESYSTEM_FOUND}) +if(FILESYSTEM_FOUND) add_definitions(-DHAS_STD_FILESYSTEM=1) if(${find_experimental}) add_definitions(-DHAS_STD_FILESYSTEM_EXPERIMENTAL=1) @@ -70,9 +70,9 @@ if(${FILESYSTEM_FOUND}) endif() if(ENABLE_STATIC_LIBS) - target_link_libraries(volk_gnsssdr_profile PUBLIC volk_gnsssdr_static ${orc_lib}) + target_link_libraries(volk_gnsssdr_profile PRIVATE volk_gnsssdr_static ${orc_lib}) else() - target_link_libraries(volk_gnsssdr_profile PUBLIC volk_gnsssdr ${orc_lib}) + target_link_libraries(volk_gnsssdr_profile PRIVATE volk_gnsssdr ${orc_lib}) add_dependencies(volk_gnsssdr_profile volk_gnsssdr) endif() @@ -122,8 +122,8 @@ install( # Launch volk_gnsssdr_profile if requested to do so if(ENABLE_PROFILING) if(DEFINED VOLK_CONFIGPATH) - set( VOLK_CONFIG_ARG "-p${VOLK_CONFIGPATH}" ) - set( VOLK_CONFIG "${VOLK_CONFIGPATH}/volk_gnsssdr_config" ) + set(VOLK_CONFIG_ARG "-p${VOLK_CONFIGPATH}") + set(VOLK_CONFIG "${VOLK_CONFIGPATH}/volk_gnsssdr_config") endif() add_custom_command(OUTPUT ${VOLK_CONFIG} COMMAND volk_gnsssdr_profile "${VOLK_CONFIG_ARG}" diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cmake/Toolchains/aarch64-linux-gnu.cmake b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cmake/Toolchains/aarch64-linux-gnu.cmake index b2553b76d..55b0ab9b9 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cmake/Toolchains/aarch64-linux-gnu.cmake +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cmake/Toolchains/aarch64-linux-gnu.cmake @@ -7,7 +7,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_PROCESSOR ARM) +set(CMAKE_SYSTEM_PROCESSOR aarch64) if(MINGW OR CYGWIN OR WIN32) set(UTIL_SEARCH_CMD where) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cmake/Toolchains/arm-linux-gnueabihf.cmake b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cmake/Toolchains/arm-linux-gnueabihf.cmake index 2a2cc79c3..1a674ce98 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cmake/Toolchains/arm-linux-gnueabihf.cmake +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cmake/Toolchains/arm-linux-gnueabihf.cmake @@ -7,7 +7,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_PROCESSOR ARM) +set(CMAKE_SYSTEM_PROCESSOR arm) if(MINGW OR CYGWIN OR WIN32) set(UTIL_SEARCH_CMD where) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/CMakeLists.txt b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/CMakeLists.txt new file mode 100644 index 000000000..f9f5baf72 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/CMakeLists.txt @@ -0,0 +1,265 @@ +# SPDX-FileCopyrightText: 2017 Google Inc. +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.0) + +# option() honors normal variables. +# see: https://cmake.org/cmake/help/git-stage/policy/CMP0077.html +if(POLICY CMP0077) + cmake_policy(SET CMP0077 NEW) +endif() + +project(CpuFeatures VERSION 0.6.0 LANGUAGES C) + +set(CMAKE_C_STANDARD 99) +if(CMAKE_VERSION LESS "3.1") + add_compile_options("$<$,C>:-std=gnu99>") +endif() + +# Default Build Type to be Release +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release" CACHE STRING + "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." + FORCE) +endif() + +# BUILD_TESTING is a standard CMake variable, but we declare it here to make it +# prominent in the GUI. +option(BUILD_TESTING "Enable test (depends on googletest)." OFF) +# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to make +# it prominent in the GUI. +# cpu_features uses bit-fields which are - to some extends - implementation-defined (see https://en.cppreference.com/w/c/language/bit_field). +# As a consequence it is discouraged to use cpu_features as a shared library because different compilers may interpret the code in different ways. +# Prefer static linking from source whenever possible. +option(BUILD_SHARED_LIBS "Build library as shared." OFF) +# PIC +option(BUILD_PIC "Build with Position Independant Code." OFF) # Default is off at least for GCC + +# Force PIC on unix when building shared libs +# see: https://en.wikipedia.org/wiki/Position-independent_code +if(BUILD_SHARED_LIBS AND UNIX) + set(BUILD_PIC ON) +endif() + +include(CheckIncludeFile) +include(CheckSymbolExists) +include(GNUInstallDirs) + +macro(setup_include_and_definitions TARGET_NAME) + target_include_directories(${TARGET_NAME} + PUBLIC $ + PRIVATE $ + ) + target_compile_definitions(${TARGET_NAME} + PUBLIC STACK_LINE_READER_BUFFER_SIZE=1024 + ) +endmacro() + +set(PROCESSOR_IS_MIPS FALSE) +set(PROCESSOR_IS_ARM FALSE) +set(PROCESSOR_IS_AARCH64 FALSE) +set(PROCESSOR_IS_X86 FALSE) +set(PROCESSOR_IS_POWER FALSE) + +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips") + set(PROCESSOR_IS_MIPS TRUE) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm") + set(PROCESSOR_IS_ARM TRUE) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64") + set(PROCESSOR_IS_AARCH64 TRUE) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86_64)|(AMD64|amd64)|(^i.86$)") + set(PROCESSOR_IS_X86 TRUE) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)") + set(PROCESSOR_IS_POWER TRUE) +endif() + +macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME) + list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpu_features_macros.h) + list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpu_features_cache_info.h) + if(PROCESSOR_IS_MIPS) + list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_mips.h) + list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_mips.c) + elseif(PROCESSOR_IS_ARM) + list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_arm.h) + list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_arm.c) + elseif(PROCESSOR_IS_AARCH64) + list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_aarch64.h) + list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_aarch64.c) + elseif(PROCESSOR_IS_X86) + list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_x86.h) + list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/cpuid_x86.h) + list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_x86.c) + elseif(PROCESSOR_IS_POWER) + list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_ppc.h) + list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/src/cpuinfo_ppc.c) + else() + message(FATAL_ERROR "Unsupported architectures ${CMAKE_SYSTEM_PROCESSOR}") + endif() +endmacro() + +# +# library : utils +# + +add_library(utils OBJECT + ${PROJECT_SOURCE_DIR}/include/internal/bit_utils.h + ${PROJECT_SOURCE_DIR}/include/internal/filesystem.h + ${PROJECT_SOURCE_DIR}/include/internal/stack_line_reader.h + ${PROJECT_SOURCE_DIR}/include/internal/string_view.h + ${PROJECT_SOURCE_DIR}/src/filesystem.c + ${PROJECT_SOURCE_DIR}/src/stack_line_reader.c + ${PROJECT_SOURCE_DIR}/src/string_view.c +) +set_property(TARGET utils PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC}) +setup_include_and_definitions(utils) + +# +# library : unix_based_hardware_detection +# + +if(UNIX) + add_library(unix_based_hardware_detection OBJECT + ${PROJECT_SOURCE_DIR}/include/internal/hwcaps.h + ${PROJECT_SOURCE_DIR}/src/hwcaps.c + ) + setup_include_and_definitions(unix_based_hardware_detection) + check_include_file(dlfcn.h HAVE_DLFCN_H) + if(HAVE_DLFCN_H) + target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_DLFCN_H) + endif() + check_symbol_exists(getauxval "sys/auxv.h" HAVE_STRONG_GETAUXVAL) + if(HAVE_STRONG_GETAUXVAL) + target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_STRONG_GETAUXVAL) + endif() + set_property(TARGET unix_based_hardware_detection PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC}) +endif() + +# +# library : cpu_features +# +set(CPU_FEATURES_HDRS) +set(CPU_FEATURES_SRCS) +add_cpu_features_headers_and_sources(CPU_FEATURES_HDRS CPU_FEATURES_SRCS) +list(APPEND CPU_FEATURES_SRCS $) +if(NOT PROCESSOR_IS_X86 AND UNIX) + list(APPEND CPU_FEATURES_SRCS $) +endif() +add_library(cpu_features ${CPU_FEATURES_HDRS} ${CPU_FEATURES_SRCS}) +set_target_properties(cpu_features PROPERTIES PUBLIC_HEADER "${CPU_FEATURES_HDRS}") +setup_include_and_definitions(cpu_features) +target_link_libraries(cpu_features PUBLIC ${CMAKE_DL_LIBS}) +set_property(TARGET cpu_features PROPERTY POSITION_INDEPENDENT_CODE ${BUILD_PIC}) +target_include_directories(cpu_features + PUBLIC $ +) +if(PROCESSOR_IS_X86) + if(APPLE) + target_compile_definitions(cpu_features PRIVATE HAVE_SYSCTLBYNAME) + endif() +endif() +add_library(CpuFeature::cpu_features ALIAS cpu_features) + +# +# program : list_cpu_features +# + +add_executable(list_cpu_features ${PROJECT_SOURCE_DIR}/src/utils/list_cpu_features.c) +target_link_libraries(list_cpu_features PRIVATE cpu_features) +add_executable(CpuFeature::list_cpu_features ALIAS list_cpu_features) + +# +# ndk_compat +# + +if(ANDROID) +add_subdirectory(ndk_compat) +endif() + +# +# tests +# + +include(CTest) +if(BUILD_TESTING) + # Automatically incorporate googletest into the CMake Project if target not + # found. + enable_language(CXX) + + set(CMAKE_CXX_STANDARD 11) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + set(CMAKE_CXX_EXTENSIONS OFF) # prefer use of -std11 instead of -gnustd11 + + if(NOT TARGET gtest OR NOT TARGET gmock_main) + # Download and unpack googletest at configure time. + configure_file( + cmake/googletest.CMakeLists.txt.in + googletest-download/CMakeLists.txt + ) + + execute_process( + COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download) + + if(result) + message(FATAL_ERROR "CMake step for googletest failed: ${result}") + endif() + + execute_process( + COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download) + + if(result) + message(FATAL_ERROR "Build step for googletest failed: ${result}") + endif() + + # Prevent overriding the parent project's compiler/linker settings on + # Windows. + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + + # Add googletest directly to our build. This defines the gtest and + # gtest_main targets. + add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src + ${CMAKE_BINARY_DIR}/googletest-build + EXCLUDE_FROM_ALL) + endif() + + add_subdirectory(test) +endif() + +# +# Install cpu_features and list_cpu_features +# + +include(GNUInstallDirs) +install(TARGETS cpu_features list_cpu_features + EXPORT CpuFeaturesTargets + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cpu_features + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) +install(EXPORT CpuFeaturesTargets + NAMESPACE CpuFeatures:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures + COMPONENT Devel +) +include(CMakePackageConfigHelpers) +configure_package_config_file(cmake/CpuFeaturesConfig.cmake.in + "${PROJECT_BINARY_DIR}/CpuFeaturesConfig.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures" + NO_SET_AND_CHECK_MACRO + NO_CHECK_REQUIRED_COMPONENTS_MACRO +) +write_basic_package_version_file( + "${PROJECT_BINARY_DIR}/CpuFeaturesConfigVersion.cmake" + COMPATIBILITY SameMajorVersion +) +install( + FILES + "${PROJECT_BINARY_DIR}/CpuFeaturesConfig.cmake" + "${PROJECT_BINARY_DIR}/CpuFeaturesConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures" + COMPONENT Devel +) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/README.md b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/README.md new file mode 100644 index 000000000..032edd196 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/README.md @@ -0,0 +1,222 @@ +# cpu_features + + +[comment]: # ( +SPDX-License-Identifier: Apache-2.0 +) + +[comment]: # ( +SPDX-FileCopyrightText: 2017 Google LLC +) + + +A cross-platform C library to retrieve CPU features (such as available +instructions) at runtime. + +## Table of Contents + +- [Design Rationale](#rationale) +- [Code samples](#codesample) +- [Running sample code](#usagesample) +- [What's supported](#support) +- [Android NDK's drop in replacement](#ndk) +- [License](#license) +- [Build with cmake](#cmake) + + + +## Design Rationale + +- **Simple to use.** See the snippets below for examples. +- **Extensible.** Easy to add missing features or architectures. +- **Compatible with old compilers** and available on many architectures so it + can be used widely. To ensure that cpu_features works on as many platforms as + possible, we implemented it in a highly portable version of C: C99. +- **Sandbox-compatible.** The library uses a variety of strategies to cope with + sandboxed environments or when `cpuid` is unavailable. This is useful when + running integration tests in hermetic environments. +- **Thread safe, no memory allocation, and raises no exceptions.** cpu_features + is suitable for implementing fundamental libc functions like `malloc`, + `memcpy`, and `memcmp`. +- **Unit tested.** + + + +## Code samples + +**Note:** For C++ code, the library functions are defined in the `CpuFeatures` +namespace. + +### Checking features at runtime + +Here's a simple example that executes a codepath if the CPU supports both the +AES and the SSE4.2 instruction sets: + +```c +#include "cpuinfo_x86.h" + +// For C++, add `using namespace CpuFeatures;` +static const X86Features features = GetX86Info().features; + +void Compute(void) { + if (features.aes && features.sse4_2) { + // Run optimized code. + } else { + // Run standard code. + } +} +``` + +### Caching for faster evaluation of complex checks + +If you wish, you can read all the features at once into a global variable, and +then query for the specific features you care about. Below, we store all the ARM +features and then check whether AES and NEON are supported. + +```c +#include +#include "cpuinfo_arm.h" + +// For C++, add `using namespace CpuFeatures;` +static const ArmFeatures features = GetArmInfo().features; +static const bool has_aes_and_neon = features.aes && features.neon; + +// use has_aes_and_neon. +``` + +This is a good approach to take if you're checking for combinations of features +when using a compiler that is slow to extract individual bits from bit-packed +structures. + +### Checking compile time flags + +The following code determines whether the compiler was told to use the AVX +instruction set (e.g., `g++ -mavx`) and sets `has_avx` accordingly. + +```c +#include +#include "cpuinfo_x86.h" + +// For C++, add `using namespace CpuFeatures;` +static const X86Features features = GetX86Info().features; +static const bool has_avx = CPU_FEATURES_COMPILED_X86_AVX || features.avx; + +// use has_avx. +``` + +`CPU_FEATURES_COMPILED_X86_AVX` is set to 1 if the compiler was instructed to +use AVX and 0 otherwise, combining compile time and runtime knowledge. + +### Rejecting poor hardware implementations based on microarchitecture + +On x86, the first incarnation of a feature in a microarchitecture might not be +the most efficient (e.g. AVX on Sandy Bridge). We provide a function to retrieve +the underlying microarchitecture so you can decide whether to use it. + +Below, `has_fast_avx` is set to 1 if the CPU supports the AVX instruction +set—but only if it's not Sandy Bridge. + +```c +#include +#include "cpuinfo_x86.h" + +// For C++, add `using namespace CpuFeatures;` +static const X86Info info = GetX86Info(); +static const X86Microarchitecture uarch = GetX86Microarchitecture(&info); +static const bool has_fast_avx = info.features.avx && uarch != INTEL_SNB; + +// use has_fast_avx. +``` + +This feature is currently available only for x86 microarchitectures. + + + +### Running sample code + +Building `cpu_features` (check [quickstart](#quickstart) below) brings a small +executable to test the library. + +```shell + % ./build/list_cpu_features +arch : x86 +brand : Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz +family : 6 (0x06) +model : 45 (0x2D) +stepping : 7 (0x07) +uarch : INTEL_SNB +flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3 +``` + +```shell +% ./build/list_cpu_features --json +{"arch":"x86","brand":" Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz","family":6,"model":45,"stepping":7,"uarch":"INTEL_SNB","flags":["aes","avx","cx16","smx","sse4_1","sse4_2","ssse3"]} +``` + + + +## What's supported + +| | x86³ | ARM | AArch64 | MIPS⁴ | POWER | +| ------- | :--: | :-----: | :-----: | :---: | :---: | +| Android | yes² | yes¹ | yes¹ | yes¹ | N/A | +| iOS | N/A | not yet | not yet | N/A | N/A | +| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ | +| MacOs | yes² | N/A | not yet | N/A | no | +| Windows | yes² | not yet | not yet | N/A | N/A | + +1. **Features revealed from Linux.** We gather data from several sources + depending on availability: + - from glibc's + [getauxval](https://www.gnu.org/software/libc/manual/html_node/Auxiliary-Vector.html) + - by parsing `/proc/self/auxv` + - by parsing `/proc/cpuinfo` +2. **Features revealed from CPU.** features are retrieved by using the `cpuid` + instruction. +3. **Microarchitecture detection.** On x86 some features are not always + implemented efficiently in hardware (e.g. AVX on Sandybridge). Exposing the + microarchitecture allows the client to reject particular microarchitectures. +4. All flavors of Mips are supported, little and big endian as well as 32/64 + bits. + + + +## Android NDK's drop in replacement + +[cpu_features](https://github.com/google/cpu_features) is now officially +supporting Android and offers a drop in replacement of for the NDK's +[cpu-features.h](https://android.googlesource.com/platform/ndk/+/master/sources/android/cpufeatures/cpu-features.h) +, see [ndk_compat](ndk_compat) folder for details. + + + +## License + +The cpu_features library is licensed under the terms of the Apache license. See +[LICENSE](LICENSE) for more information. + + + +## Build with CMake + +Please check the [CMake build instructions](cmake/README.md). + + + +### Quickstart with `Ninja` + +- build `list_cpu_features` + +``` + cmake -B/tmp/cpu_features -H. -GNinja -DCMAKE_BUILD_TYPE=Release + ninja -C/tmp/cpu_features + /tmp/cpu_features/list_cpu_features --json +``` + +- run tests + +``` + cmake -B/tmp/cpu_features -H. -GNinja -DBUILD_TESTING=ON + ninja -C/tmp/cpu_features + ninja -C/tmp/cpu_features test +``` diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/cmake/CpuFeaturesConfig.cmake.in b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/cmake/CpuFeaturesConfig.cmake.in new file mode 100644 index 000000000..71a79a924 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/cmake/CpuFeaturesConfig.cmake.in @@ -0,0 +1,6 @@ +# SPDX-FileCopyrightText: 2017 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +# CpuFeatures CMake configuration file + +include("${CMAKE_CURRENT_LIST_DIR}/CpuFeaturesTargets.cmake") diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/cmake/CpuFeaturesNdkCompatConfig.cmake.in b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/cmake/CpuFeaturesNdkCompatConfig.cmake.in new file mode 100644 index 000000000..ddf2fb71c --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/cmake/CpuFeaturesNdkCompatConfig.cmake.in @@ -0,0 +1,6 @@ +# SPDX-FileCopyrightText: 2017 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +# CpuFeaturesNdkCompat CMake configuration file + +include("${CMAKE_CURRENT_LIST_DIR}/CpuFeaturesNdkCompatTargets.cmake") diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/cmake/README.md b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/cmake/README.md new file mode 100644 index 000000000..3fcac9fcd --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/cmake/README.md @@ -0,0 +1,37 @@ +# CMake build instructions + + +[comment]: # ( +SPDX-License-Identifier: Apache-2.0 +) + +[comment]: # ( +SPDX-FileCopyrightText: 2017 Google LLC +) + + +## Recommended usage : Incorporating cpu_features into a CMake project + +For API / ABI compatibility reasons, it is recommended to build and use +cpu_features in a subdirectory of your project or as an embedded dependency. + +This is similar to the recommended usage of the googletest framework ( +https://github.com/google/googletest/blob/master/googletest/README.md ) + +Build and use step-by-step + +1- Download cpu_features and copy it in a sub-directory in your project. or add +cpu_features as a git-submodule in your project + +2- You can then use the cmake command `add_subdirectory()` to include +cpu_features directly and use the `cpu_features` target in your project. + +3- Add the `cpu_features` target to the `target_link_libraries()` section of +your executable or of your library. + +## Enabling tests + +CMake default options for cpu_features is Release built type with tests +disabled. To enable testing set cmake `BUILD_TESTING` variable to `ON`, +[.travis.yml](../.travis.yml) and [appveyor.yml](../appveyor.yml) have up to +date examples. diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/cmake/googletest.CMakeLists.txt.in b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/cmake/googletest.CMakeLists.txt.in new file mode 100644 index 000000000..66b17383e --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/cmake/googletest.CMakeLists.txt.in @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: 2017 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 2.8.2) + +project(googletest-download NONE) + +include(ExternalProject) +ExternalProject_Add(googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG master + SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src" + BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" +) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpu_features_cache_info.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpu_features_cache_info.h new file mode 100644 index 000000000..f80d0e12f --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpu_features_cache_info.h @@ -0,0 +1,46 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#ifndef CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_ +#define CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_ + +#include "cpu_features_macros.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +typedef enum +{ + CPU_FEATURE_CACHE_NULL = 0, + CPU_FEATURE_CACHE_DATA = 1, + CPU_FEATURE_CACHE_INSTRUCTION = 2, + CPU_FEATURE_CACHE_UNIFIED = 3, + CPU_FEATURE_CACHE_TLB = 4, + CPU_FEATURE_CACHE_DTLB = 5, + CPU_FEATURE_CACHE_STLB = 6, + CPU_FEATURE_CACHE_PREFETCH = 7 +} CacheType; + +typedef struct +{ + int level; + CacheType cache_type; + int cache_size; // Cache size in bytes + int ways; // Associativity, 0 undefined, 0xFF fully associative + int line_size; // Cache line size in bytes + int tlb_entries; // number of entries for TLB + int partitioning; // number of lines per sector +} CacheLevelInfo; + +// Increase this value if more cache levels are needed. +#ifndef CPU_FEATURES_MAX_CACHE_LEVEL +#define CPU_FEATURES_MAX_CACHE_LEVEL 10 +#endif +typedef struct +{ + int size; + CacheLevelInfo levels[CPU_FEATURES_MAX_CACHE_LEVEL]; +} CacheInfo; + +CPU_FEATURES_END_CPP_NAMESPACE + +#endif // CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_ diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpu_features_macros.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpu_features_macros.h new file mode 100644 index 000000000..5cad8743d --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpu_features_macros.h @@ -0,0 +1,208 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + + +#ifndef CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_ +#define CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_ + +//////////////////////////////////////////////////////////////////////////////// +// Architectures +//////////////////////////////////////////////////////////////////////////////// + +#if defined(__pnacl__) || defined(__CLR_VER) +#define CPU_FEATURES_ARCH_VM +#endif + +#if (defined(_M_IX86) || defined(__i386__)) && !defined(CPU_FEATURES_ARCH_VM) +#define CPU_FEATURES_ARCH_X86_32 +#endif + +#if (defined(_M_X64) || defined(__x86_64__)) && !defined(CPU_FEATURES_ARCH_VM) +#define CPU_FEATURES_ARCH_X86_64 +#endif + +#if defined(CPU_FEATURES_ARCH_X86_32) || defined(CPU_FEATURES_ARCH_X86_64) +#define CPU_FEATURES_ARCH_X86 +#endif + +#if (defined(__arm__) || defined(_M_ARM)) +#define CPU_FEATURES_ARCH_ARM +#endif + +#if defined(__aarch64__) +#define CPU_FEATURES_ARCH_AARCH64 +#endif + +#if (defined(CPU_FEATURES_ARCH_AARCH64) || defined(CPU_FEATURES_ARCH_ARM)) +#define CPU_FEATURES_ARCH_ANY_ARM +#endif + +#if defined(__mips64) +#define CPU_FEATURES_ARCH_MIPS64 +#endif + +#if defined(__mips__) && !defined(__mips64) // mips64 also declares __mips__ +#define CPU_FEATURES_ARCH_MIPS32 +#endif + +#if defined(CPU_FEATURES_ARCH_MIPS32) || defined(CPU_FEATURES_ARCH_MIPS64) +#define CPU_FEATURES_ARCH_MIPS +#endif + +#if defined(__powerpc__) +#define CPU_FEATURES_ARCH_PPC +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Os +//////////////////////////////////////////////////////////////////////////////// + +#if defined(__linux__) +#define CPU_FEATURES_OS_LINUX_OR_ANDROID +#endif + +#if defined(__ANDROID__) +#define CPU_FEATURES_OS_ANDROID +#endif + +#if (defined(_WIN64) || defined(_WIN32)) +#define CPU_FEATURES_OS_WINDOWS +#endif + +#if (defined(__apple__) || defined(__APPLE__) || defined(__MACH__)) +#define CPU_FEATURES_OS_DARWIN +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Compilers +//////////////////////////////////////////////////////////////////////////////// + +#if defined(__clang__) +#define CPU_FEATURES_COMPILER_CLANG +#endif + +#if defined(__GNUC__) && !defined(__clang__) +#define CPU_FEATURES_COMPILER_GCC +#endif + +#if defined(_MSC_VER) +#define CPU_FEATURES_COMPILER_MSC +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Cpp +//////////////////////////////////////////////////////////////////////////////// + +#if defined(__cplusplus) +#define CPU_FEATURES_START_CPP_NAMESPACE \ + namespace cpu_features \ + { \ + extern "C" \ + { +#define CPU_FEATURES_END_CPP_NAMESPACE \ + } \ + } +#else +#define CPU_FEATURES_START_CPP_NAMESPACE +#define CPU_FEATURES_END_CPP_NAMESPACE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Compiler flags +//////////////////////////////////////////////////////////////////////////////// + +// Use the following to check if a feature is known to be available at +// compile time. See README.md for an example. +#if defined(CPU_FEATURES_ARCH_X86) + +#if defined(__AES__) +#define CPU_FEATURES_COMPILED_X86_AES 1 +#else +#define CPU_FEATURES_COMPILED_X86_AES 0 +#endif // defined(__AES__) + +#if defined(__F16C__) +#define CPU_FEATURES_COMPILED_X86_F16C 1 +#else +#define CPU_FEATURES_COMPILED_X86_F16C 0 +#endif // defined(__F16C__) + +#if defined(__BMI__) +#define CPU_FEATURES_COMPILED_X86_BMI 1 +#else +#define CPU_FEATURES_COMPILED_X86_BMI 0 +#endif // defined(__BMI__) + +#if defined(__BMI2__) +#define CPU_FEATURES_COMPILED_X86_BMI2 1 +#else +#define CPU_FEATURES_COMPILED_X86_BMI2 0 +#endif // defined(__BMI2__) + +#if (defined(__SSE__) || (_M_IX86_FP >= 1)) +#define CPU_FEATURES_COMPILED_X86_SSE 1 +#else +#define CPU_FEATURES_COMPILED_X86_SSE 0 +#endif + +#if (defined(__SSE2__) || (_M_IX86_FP >= 2)) +#define CPU_FEATURES_COMPILED_X86_SSE2 1 +#else +#define CPU_FEATURES_COMPILED_X86_SSE2 0 +#endif + +#if defined(__SSE3__) +#define CPU_FEATURES_COMPILED_X86_SSE3 1 +#else +#define CPU_FEATURES_COMPILED_X86_SSE3 0 +#endif // defined(__SSE3__) + +#if defined(__SSSE3__) +#define CPU_FEATURES_COMPILED_X86_SSSE3 1 +#else +#define CPU_FEATURES_COMPILED_X86_SSSE3 0 +#endif // defined(__SSSE3__) + +#if defined(__SSE4_1__) +#define CPU_FEATURES_COMPILED_X86_SSE4_1 1 +#else +#define CPU_FEATURES_COMPILED_X86_SSE4_1 0 +#endif // defined(__SSE4_1__) + +#if defined(__SSE4_2__) +#define CPU_FEATURES_COMPILED_X86_SSE4_2 1 +#else +#define CPU_FEATURES_COMPILED_X86_SSE4_2 0 +#endif // defined(__SSE4_2__) + +#if defined(__AVX__) +#define CPU_FEATURES_COMPILED_X86_AVX 1 +#else +#define CPU_FEATURES_COMPILED_X86_AVX 0 +#endif // defined(__AVX__) + +#if defined(__AVX2__) +#define CPU_FEATURES_COMPILED_X86_AVX2 1 +#else +#define CPU_FEATURES_COMPILED_X86_AVX2 0 +#endif // defined(__AVX2__) + +#endif // defined(CPU_FEATURES_ARCH_X86) + +#if defined(CPU_FEATURES_ARCH_ANY_ARM) +#if defined(__ARM_NEON__) +#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 1 +#else +#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 0 +#endif // defined(__ARM_NEON__) +#endif // defined(CPU_FEATURES_ARCH_ANY_ARM) + +#if defined(CPU_FEATURES_ARCH_MIPS) +#if defined(__mips_msa) +#define CPU_FEATURES_COMPILED_MIPS_MSA 1 +#else +#define CPU_FEATURES_COMPILED_MIPS_MSA 0 +#endif // defined(__mips_msa) +#endif // defined(CPU_FEATURES_ARCH_MIPS) + +#endif // CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_ diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_aarch64.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_aarch64.h new file mode 100644 index 000000000..6f910c52f --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_aarch64.h @@ -0,0 +1,149 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + + +#ifndef CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_ +#define CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_ + +#include "cpu_features_cache_info.h" +#include "cpu_features_macros.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +typedef struct +{ + int fp : 1; // Floating-point. + int asimd : 1; // Advanced SIMD. + int evtstrm : 1; // Generic timer generated events. + int aes : 1; // Hardware-accelerated Advanced Encryption Standard. + int pmull : 1; // Polynomial multiply long. + int sha1 : 1; // Hardware-accelerated SHA1. + int sha2 : 1; // Hardware-accelerated SHA2-256. + int crc32 : 1; // Hardware-accelerated CRC-32. + int atomics : 1; // Armv8.1 atomic instructions. + int fphp : 1; // Half-precision floating point support. + int asimdhp : 1; // Advanced SIMD half-precision support. + int cpuid : 1; // Access to certain ID registers. + int asimdrdm : 1; // Rounding Double Multiply Accumulate/Subtract. + int jscvt : 1; // Support for JavaScript conversion. + int fcma : 1; // Floating point complex numbers. + int lrcpc : 1; // Support for weaker release consistency. + int dcpop : 1; // Data persistence writeback. + int sha3 : 1; // Hardware-accelerated SHA3. + int sm3 : 1; // Hardware-accelerated SM3. + int sm4 : 1; // Hardware-accelerated SM4. + int asimddp : 1; // Dot product instruction. + int sha512 : 1; // Hardware-accelerated SHA512. + int sve : 1; // Scalable Vector Extension. + int asimdfhm : 1; // Additional half-precision instructions. + int dit : 1; // Data independent timing. + int uscat : 1; // Unaligned atomics support. + int ilrcpc : 1; // Additional support for weaker release consistency. + int flagm : 1; // Flag manipulation instructions. + int ssbs : 1; // Speculative Store Bypass Safe PSTATE bit. + int sb : 1; // Speculation barrier. + int paca : 1; // Address authentication. + int pacg : 1; // Generic authentication. + int dcpodp : 1; // Data cache clean to point of persistence. + int sve2 : 1; // Scalable Vector Extension (version 2). + int sveaes : 1; // SVE AES instructions. + int svepmull : 1; // SVE polynomial multiply long instructions. + int svebitperm : 1; // SVE bit permute instructions. + int svesha3 : 1; // SVE SHA3 instructions. + int svesm4 : 1; // SVE SM4 instructions. + int flagm2 : 1; // Additional flag manipulation instructions. + int frint : 1; // Floating point to integer rounding. + int svei8mm : 1; // SVE Int8 matrix multiplication instructions. + int svef32mm : 1; // SVE FP32 matrix multiplication instruction. + int svef64mm : 1; // SVE FP64 matrix multiplication instructions. + int svebf16 : 1; // SVE BFloat16 instructions. + int i8mm : 1; // Int8 matrix multiplication instructions. + int bf16 : 1; // BFloat16 instructions. + int dgh : 1; // Data Gathering Hint instruction. + int rng : 1; // True random number generator support. + int bti : 1; // Branch target identification. + + // Make sure to update Aarch64FeaturesEnum below if you add a field here. +} Aarch64Features; + +typedef struct +{ + Aarch64Features features; + int implementer; + int variant; + int part; + int revision; +} Aarch64Info; + +Aarch64Info GetAarch64Info(void); + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +typedef enum +{ + AARCH64_FP, + AARCH64_ASIMD, + AARCH64_EVTSTRM, + AARCH64_AES, + AARCH64_PMULL, + AARCH64_SHA1, + AARCH64_SHA2, + AARCH64_CRC32, + AARCH64_ATOMICS, + AARCH64_FPHP, + AARCH64_ASIMDHP, + AARCH64_CPUID, + AARCH64_ASIMDRDM, + AARCH64_JSCVT, + AARCH64_FCMA, + AARCH64_LRCPC, + AARCH64_DCPOP, + AARCH64_SHA3, + AARCH64_SM3, + AARCH64_SM4, + AARCH64_ASIMDDP, + AARCH64_SHA512, + AARCH64_SVE, + AARCH64_ASIMDFHM, + AARCH64_DIT, + AARCH64_USCAT, + AARCH64_ILRCPC, + AARCH64_FLAGM, + AARCH64_SSBS, + AARCH64_SB, + AARCH64_PACA, + AARCH64_PACG, + AARCH64_DCPODP, + AARCH64_SVE2, + AARCH64_SVEAES, + AARCH64_SVEPMULL, + AARCH64_SVEBITPERM, + AARCH64_SVESHA3, + AARCH64_SVESM4, + AARCH64_FLAGM2, + AARCH64_FRINT, + AARCH64_SVEI8MM, + AARCH64_SVEF32MM, + AARCH64_SVEF64MM, + AARCH64_SVEBF16, + AARCH64_I8MM, + AARCH64_BF16, + AARCH64_DGH, + AARCH64_RNG, + AARCH64_BTI, + AARCH64_LAST_, +} Aarch64FeaturesEnum; + +int GetAarch64FeaturesEnumValue(const Aarch64Features* features, + Aarch64FeaturesEnum value); + +const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum); + +CPU_FEATURES_END_CPP_NAMESPACE + +#if !defined(CPU_FEATURES_ARCH_AARCH64) +#error "Including cpuinfo_aarch64.h from a non-aarch64 target." +#endif + +#endif // CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_ diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_arm.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_arm.h new file mode 100644 index 000000000..0571fe7ee --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_arm.h @@ -0,0 +1,113 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + + +#ifndef CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_ +#define CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_ + +#include "cpu_features_cache_info.h" +#include "cpu_features_macros.h" +#include // uint32_t + +CPU_FEATURES_START_CPP_NAMESPACE + +typedef struct +{ + int swp : 1; // SWP instruction (atomic read-modify-write) + int half : 1; // Half-word loads and stores + int thumb : 1; // Thumb (16-bit instruction set) + int _26bit : 1; // "26 Bit" Model (Processor status register folded into + // program counter) + int fastmult : 1; // 32x32->64-bit multiplication + int fpa : 1; // Floating point accelerator + int vfp : 1; // Vector Floating Point. + int edsp : 1; // DSP extensions (the 'e' variant of the ARM9 CPUs, and all + // others above) + int java : 1; // Jazelle (Java bytecode accelerator) + int iwmmxt : 1; // Intel Wireless MMX Technology. + int crunch : 1; // MaverickCrunch coprocessor + int thumbee : 1; // ThumbEE + int neon : 1; // Advanced SIMD. + int vfpv3 : 1; // VFP version 3 + int vfpv3d16 : 1; // VFP version 3 with 16 D-registers + int tls : 1; // TLS register + int vfpv4 : 1; // VFP version 4 with fast context switching + int idiva : 1; // SDIV and UDIV hardware division in ARM mode. + int idivt : 1; // SDIV and UDIV hardware division in Thumb mode. + int vfpd32 : 1; // VFP with 32 D-registers + int lpae : 1; // Large Physical Address Extension (>4GB physical memory on + // 32-bit architecture) + int evtstrm : 1; // kernel event stream using generic architected timer + int aes : 1; // Hardware-accelerated Advanced Encryption Standard. + int pmull : 1; // Polynomial multiply long. + int sha1 : 1; // Hardware-accelerated SHA1. + int sha2 : 1; // Hardware-accelerated SHA2-256. + int crc32 : 1; // Hardware-accelerated CRC-32. + + // Make sure to update ArmFeaturesEnum below if you add a field here. +} ArmFeatures; + +typedef struct +{ + ArmFeatures features; + int implementer; + int architecture; + int variant; + int part; + int revision; +} ArmInfo; + +// TODO(user): Add macros to know which features are present at compile +// time. + +ArmInfo GetArmInfo(void); + +// Compute CpuId from ArmInfo. +uint32_t GetArmCpuId(const ArmInfo* const info); + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +typedef enum +{ + ARM_SWP, + ARM_HALF, + ARM_THUMB, + ARM_26BIT, + ARM_FASTMULT, + ARM_FPA, + ARM_VFP, + ARM_EDSP, + ARM_JAVA, + ARM_IWMMXT, + ARM_CRUNCH, + ARM_THUMBEE, + ARM_NEON, + ARM_VFPV3, + ARM_VFPV3D16, + ARM_TLS, + ARM_VFPV4, + ARM_IDIVA, + ARM_IDIVT, + ARM_VFPD32, + ARM_LPAE, + ARM_EVTSTRM, + ARM_AES, + ARM_PMULL, + ARM_SHA1, + ARM_SHA2, + ARM_CRC32, + ARM_LAST_, +} ArmFeaturesEnum; + +int GetArmFeaturesEnumValue(const ArmFeatures* features, ArmFeaturesEnum value); + +const char* GetArmFeaturesEnumName(ArmFeaturesEnum); + +CPU_FEATURES_END_CPP_NAMESPACE + +#if !defined(CPU_FEATURES_ARCH_ARM) +#error "Including cpuinfo_arm.h from a non-arm target." +#endif + +#endif // CPU_FEATURES_INCLUDE_CPUINFO_ARM_H_ diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_mips.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_mips.h new file mode 100644 index 000000000..c935e5a91 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_mips.h @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + + +#ifndef CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_ +#define CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_ + +#include "cpu_features_cache_info.h" +#include "cpu_features_macros.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +typedef struct +{ + int msa : 1; // MIPS SIMD Architecture + // https://www.mips.com/products/architectures/ase/simd/ + int eva : 1; // Enhanced Virtual Addressing + // https://www.mips.com/products/architectures/mips64/ + int r6 : 1; // True if is release 6 of the processor. + + // Make sure to update MipsFeaturesEnum below if you add a field here. +} MipsFeatures; + +typedef struct +{ + MipsFeatures features; +} MipsInfo; + +MipsInfo GetMipsInfo(void); + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +typedef enum +{ + MIPS_MSA, + MIPS_EVA, + MIPS_R6, + MIPS_LAST_, +} MipsFeaturesEnum; + +int GetMipsFeaturesEnumValue(const MipsFeatures* features, + MipsFeaturesEnum value); + +const char* GetMipsFeaturesEnumName(MipsFeaturesEnum); + +CPU_FEATURES_END_CPP_NAMESPACE + +#if !defined(CPU_FEATURES_ARCH_MIPS) +#error "Including cpuinfo_mips.h from a non-mips target." +#endif + +#endif // CPU_FEATURES_INCLUDE_CPUINFO_MIPS_H_ diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_ppc.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_ppc.h new file mode 100644 index 000000000..2a9ab2ba8 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_ppc.h @@ -0,0 +1,140 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + + +#ifndef CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_ +#define CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_ + +#include "cpu_features_cache_info.h" +#include "cpu_features_macros.h" +#include "internal/hwcaps.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +typedef struct +{ + int ppc32 : 1; + int ppc64 : 1; + int ppc601 : 1; + int altivec : 1; + int fpu : 1; + int mmu : 1; + int mac_4xx : 1; + int unifiedcache : 1; + int spe : 1; + int efpsingle : 1; + int efpdouble : 1; + int no_tb : 1; + int power4 : 1; + int power5 : 1; + int power5plus : 1; + int cell : 1; + int booke : 1; + int smt : 1; + int icachesnoop : 1; + int arch205 : 1; + int pa6t : 1; + int dfp : 1; + int power6ext : 1; + int arch206 : 1; + int vsx : 1; + int pseries_perfmon_compat : 1; + int truele : 1; + int ppcle : 1; + int arch207 : 1; + int htm : 1; + int dscr : 1; + int ebb : 1; + int isel : 1; + int tar : 1; + int vcrypto : 1; + int htm_nosc : 1; + int arch300 : 1; + int ieee128 : 1; + int darn : 1; + int scv : 1; + int htm_no_suspend : 1; + + // Make sure to update PPCFeaturesEnum below if you add a field here. +} PPCFeatures; + +typedef struct +{ + PPCFeatures features; +} PPCInfo; + +// This function is guaranteed to be malloc, memset and memcpy free. +PPCInfo GetPPCInfo(void); + +typedef struct +{ + char platform[64]; // 0 terminated string + char model[64]; // 0 terminated string + char machine[64]; // 0 terminated string + char cpu[64]; // 0 terminated string + PlatformType type; +} PPCPlatformStrings; + +PPCPlatformStrings GetPPCPlatformStrings(void); + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +typedef enum +{ + PPC_32, /* 32 bit mode execution */ + PPC_64, /* 64 bit mode execution */ + PPC_601_INSTR, /* Old POWER ISA */ + PPC_HAS_ALTIVEC, /* SIMD Unit*/ + PPC_HAS_FPU, /* Floating Point Unit */ + PPC_HAS_MMU, /* Memory management unit */ + PPC_HAS_4xxMAC, + PPC_UNIFIED_CACHE, /* Unified instruction and data cache */ + PPC_HAS_SPE, /* Signal processing extention unit */ + PPC_HAS_EFP_SINGLE, /* SPE single precision fpu */ + PPC_HAS_EFP_DOUBLE, /* SPE double precision fpu */ + PPC_NO_TB, /* No timebase */ + PPC_POWER4, + PPC_POWER5, + PPC_POWER5_PLUS, + PPC_CELL, /* Cell broadband engine */ + PPC_BOOKE, /* Embedded ISA */ + PPC_SMT, /* Simultaneous multi-threading */ + PPC_ICACHE_SNOOP, + PPC_ARCH_2_05, /* ISA 2.05 - POWER6 */ + PPC_PA6T, /* PA Semi 6T core ISA */ + PPC_HAS_DFP, /* Decimal floating point unit */ + PPC_POWER6_EXT, + PPC_ARCH_2_06, /* ISA 2.06 - POWER7 */ + PPC_HAS_VSX, /* Vector-scalar extension */ + PPC_PSERIES_PERFMON_COMPAT, /* Set of backwards compatibile performance + monitoring events */ + PPC_TRUE_LE, + PPC_PPC_LE, + PPC_ARCH_2_07, /* ISA 2.07 - POWER8 */ + PPC_HTM, /* Hardware Transactional Memory */ + PPC_DSCR, /* Data stream control register */ + PPC_EBB, /* Event base branching */ + PPC_ISEL, /* Integer select instructions */ + PPC_TAR, /* Target address register */ + PPC_VEC_CRYPTO, /* Vector cryptography instructions */ + PPC_HTM_NOSC, /* Transactions aborted when syscall made*/ + PPC_ARCH_3_00, /* ISA 3.00 - POWER9 */ + PPC_HAS_IEEE128, /* VSX IEEE Binary Float 128-bit */ + PPC_DARN, /* Deliver a random number instruction */ + PPC_SCV, /* scv syscall */ + PPC_HTM_NO_SUSPEND, /* TM w/out suspended state */ + PPC_LAST_, +} PPCFeaturesEnum; + +int GetPPCFeaturesEnumValue(const PPCFeatures* features, PPCFeaturesEnum value); + +const char* GetPPCFeaturesEnumName(PPCFeaturesEnum); + +CPU_FEATURES_END_CPP_NAMESPACE + +#if !defined(CPU_FEATURES_ARCH_PPC) +#error "Including cpuinfo_ppc.h from a non-ppc target." +#endif + +#endif // CPU_FEATURES_INCLUDE_CPUINFO_PPC_H_ diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_x86.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_x86.h new file mode 100644 index 000000000..649595345 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/cpuinfo_x86.h @@ -0,0 +1,224 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + + +#ifndef CPU_FEATURES_INCLUDE_CPUINFO_X86_H_ +#define CPU_FEATURES_INCLUDE_CPUINFO_X86_H_ + +#include "cpu_features_cache_info.h" +#include "cpu_features_macros.h" + +CPU_FEATURES_START_CPP_NAMESPACE + +// See https://en.wikipedia.org/wiki/CPUID for a list of x86 cpu features. +// The field names are based on the short name provided in the wikipedia tables. +typedef struct +{ + int fpu : 1; + int tsc : 1; + int cx8 : 1; + int clfsh : 1; + int mmx : 1; + int aes : 1; + int erms : 1; + int f16c : 1; + int fma4 : 1; + int fma3 : 1; + int vaes : 1; + int vpclmulqdq : 1; + int bmi1 : 1; + int hle : 1; + int bmi2 : 1; + int rtm : 1; + int rdseed : 1; + int clflushopt : 1; + int clwb : 1; + + int sse : 1; + int sse2 : 1; + int sse3 : 1; + int ssse3 : 1; + int sse4_1 : 1; + int sse4_2 : 1; + int sse4a : 1; + + int avx : 1; + int avx2 : 1; + + int avx512f : 1; + int avx512cd : 1; + int avx512er : 1; + int avx512pf : 1; + int avx512bw : 1; + int avx512dq : 1; + int avx512vl : 1; + int avx512ifma : 1; + int avx512vbmi : 1; + int avx512vbmi2 : 1; + int avx512vnni : 1; + int avx512bitalg : 1; + int avx512vpopcntdq : 1; + int avx512_4vnniw : 1; + int avx512_4vbmi2 : 1; + int avx512_second_fma : 1; + int avx512_4fmaps : 1; + int avx512_bf16 : 1; + int avx512_vp2intersect : 1; + int amx_bf16 : 1; + int amx_tile : 1; + int amx_int8 : 1; + + int pclmulqdq : 1; + int smx : 1; + int sgx : 1; + int cx16 : 1; // aka. CMPXCHG16B + int sha : 1; + int popcnt : 1; + int movbe : 1; + int rdrnd : 1; + + int dca : 1; + int ss : 1; + // Make sure to update X86FeaturesEnum below if you add a field here. +} X86Features; + +typedef struct +{ + X86Features features; + int family; + int model; + int stepping; + char vendor[13]; // 0 terminated string +} X86Info; + +// Calls cpuid and returns an initialized X86info. +// This function is guaranteed to be malloc, memset and memcpy free. +X86Info GetX86Info(void); + +// Returns cache hierarchy informations. +// Can call cpuid multiple times. +// Only works on Intel CPU at the moment. +// This function is guaranteed to be malloc, memset and memcpy free. +CacheInfo GetX86CacheInfo(void); + +typedef enum +{ + X86_UNKNOWN, + INTEL_CORE, // CORE + INTEL_PNR, // PENRYN + INTEL_NHM, // NEHALEM + INTEL_ATOM_BNL, // BONNELL + INTEL_WSM, // WESTMERE + INTEL_SNB, // SANDYBRIDGE + INTEL_IVB, // IVYBRIDGE + INTEL_ATOM_SMT, // SILVERMONT + INTEL_HSW, // HASWELL + INTEL_BDW, // BROADWELL + INTEL_SKL, // SKYLAKE + INTEL_ATOM_GMT, // GOLDMONT + INTEL_KBL, // KABY LAKE + INTEL_CFL, // COFFEE LAKE + INTEL_WHL, // WHISKEY LAKE + INTEL_CNL, // CANNON LAKE + INTEL_ICL, // ICE LAKE + INTEL_TGL, // TIGER LAKE + INTEL_SPR, // SAPPHIRE RAPIDS + AMD_HAMMER, // K8 + AMD_K10, // K10 + AMD_BOBCAT, // K14 + AMD_BULLDOZER, // K15 + AMD_JAGUAR, // K16 + AMD_ZEN, // K17 +} X86Microarchitecture; + +// Returns the underlying microarchitecture by looking at X86Info's vendor, +// family and model. +X86Microarchitecture GetX86Microarchitecture(const X86Info* info); + +// Calls cpuid and fills the brand_string. +// - brand_string *must* be of size 49 (beware of array decaying). +// - brand_string will be zero terminated. +// - This function calls memcpy. +void FillX86BrandString(char brand_string[49]); + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +typedef enum +{ + X86_FPU, + X86_TSC, + X86_CX8, + X86_CLFSH, + X86_MMX, + X86_AES, + X86_ERMS, + X86_F16C, + X86_FMA4, + X86_FMA3, + X86_VAES, + X86_VPCLMULQDQ, + X86_BMI1, + X86_HLE, + X86_BMI2, + X86_RTM, + X86_RDSEED, + X86_CLFLUSHOPT, + X86_CLWB, + X86_SSE, + X86_SSE2, + X86_SSE3, + X86_SSSE3, + X86_SSE4_1, + X86_SSE4_2, + X86_SSE4A, + X86_AVX, + X86_AVX2, + X86_AVX512F, + X86_AVX512CD, + X86_AVX512ER, + X86_AVX512PF, + X86_AVX512BW, + X86_AVX512DQ, + X86_AVX512VL, + X86_AVX512IFMA, + X86_AVX512VBMI, + X86_AVX512VBMI2, + X86_AVX512VNNI, + X86_AVX512BITALG, + X86_AVX512VPOPCNTDQ, + X86_AVX512_4VNNIW, + X86_AVX512_4VBMI2, + X86_AVX512_SECOND_FMA, + X86_AVX512_4FMAPS, + X86_AVX512_BF16, + X86_AVX512_VP2INTERSECT, + X86_AMX_BF16, + X86_AMX_TILE, + X86_AMX_INT8, + X86_PCLMULQDQ, + X86_SMX, + X86_SGX, + X86_CX16, + X86_SHA, + X86_POPCNT, + X86_MOVBE, + X86_RDRND, + X86_DCA, + X86_SS, + X86_LAST_, +} X86FeaturesEnum; + +int GetX86FeaturesEnumValue(const X86Features* features, X86FeaturesEnum value); + +const char* GetX86FeaturesEnumName(X86FeaturesEnum); + +const char* GetX86MicroarchitectureName(X86Microarchitecture); + +CPU_FEATURES_END_CPP_NAMESPACE + +#if !defined(CPU_FEATURES_ARCH_X86) +#error "Including cpuinfo_x86.h from a non-x86 target." +#endif + +#endif // CPU_FEATURES_INCLUDE_CPUINFO_X86_H diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/bit_utils.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/bit_utils.h new file mode 100644 index 000000000..5957dd117 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/bit_utils.h @@ -0,0 +1,31 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + + +#ifndef CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_ +#define CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_ + +#include "cpu_features_macros.h" +#include +#include +#include + +CPU_FEATURES_START_CPP_NAMESPACE + +inline static bool IsBitSet(uint32_t reg, uint32_t bit) +{ + return (reg >> bit) & 0x1; +} + +inline static uint32_t ExtractBitRange(uint32_t reg, uint32_t msb, + uint32_t lsb) +{ + const uint64_t bits = msb - lsb + 1ULL; + const uint64_t mask = (1ULL << bits) - 1ULL; + assert(msb >= lsb); + return (reg >> lsb) & mask; +} + +CPU_FEATURES_END_CPP_NAMESPACE + +#endif // CPU_FEATURES_INCLUDE_INTERNAL_BIT_UTILS_H_ diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/cpuid_x86.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/cpuid_x86.h new file mode 100644 index 000000000..c675a9468 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/cpuid_x86.h @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + + +#ifndef CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_ +#define CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_ + +#include "cpu_features_macros.h" +#include + +CPU_FEATURES_START_CPP_NAMESPACE + +// A struct to hold the result of a call to cpuid. +typedef struct +{ + uint32_t eax, ebx, ecx, edx; +} Leaf; + +// Returns the result of a call to the cpuid instruction. +Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx); + +// Returns the eax value of the XCR0 register. +uint32_t GetXCR0Eax(void); + +CPU_FEATURES_END_CPP_NAMESPACE + +#endif // CPU_FEATURES_INCLUDE_INTERNAL_CPUID_X86_H_ diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/filesystem.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/filesystem.h new file mode 100644 index 000000000..f8593fd66 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/filesystem.h @@ -0,0 +1,28 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + + +// An interface for the filesystem that allows mocking the filesystem in +// unittests. +#ifndef CPU_FEATURES_INCLUDE_INTERNAL_FILESYSTEM_H_ +#define CPU_FEATURES_INCLUDE_INTERNAL_FILESYSTEM_H_ + +#include "cpu_features_macros.h" +#include +#include + +CPU_FEATURES_START_CPP_NAMESPACE + +// Same as linux "open(filename, O_RDONLY)", retries automatically on EINTR. +int CpuFeatures_OpenFile(const char* filename); + +// Same as linux "read(file_descriptor, buffer, buffer_size)", retries +// automatically on EINTR. +int CpuFeatures_ReadFile(int file_descriptor, void* buffer, size_t buffer_size); + +// Same as linux "close(file_descriptor)". +void CpuFeatures_CloseFile(int file_descriptor); + +CPU_FEATURES_END_CPP_NAMESPACE + +#endif // CPU_FEATURES_INCLUDE_INTERNAL_FILESYSTEM_H_ diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/hwcaps.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/hwcaps.h new file mode 100644 index 000000000..831c342df --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/hwcaps.h @@ -0,0 +1,177 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + + +// Interface to retrieve hardware capabilities. It relies on Linux's getauxval +// or `/proc/self/auxval` under the hood. +#ifndef CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_ +#define CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_ + +#include "cpu_features_macros.h" +#include +#include + +CPU_FEATURES_START_CPP_NAMESPACE + +// To avoid depending on the linux kernel we reproduce the architecture specific +// constants here. + +// http://elixir.free-electrons.com/linux/latest/source/arch/arm64/include/uapi/asm/hwcap.h +#define AARCH64_HWCAP_FP (1UL << 0) +#define AARCH64_HWCAP_ASIMD (1UL << 1) +#define AARCH64_HWCAP_EVTSTRM (1UL << 2) +#define AARCH64_HWCAP_AES (1UL << 3) +#define AARCH64_HWCAP_PMULL (1UL << 4) +#define AARCH64_HWCAP_SHA1 (1UL << 5) +#define AARCH64_HWCAP_SHA2 (1UL << 6) +#define AARCH64_HWCAP_CRC32 (1UL << 7) +#define AARCH64_HWCAP_ATOMICS (1UL << 8) +#define AARCH64_HWCAP_FPHP (1UL << 9) +#define AARCH64_HWCAP_ASIMDHP (1UL << 10) +#define AARCH64_HWCAP_CPUID (1UL << 11) +#define AARCH64_HWCAP_ASIMDRDM (1UL << 12) +#define AARCH64_HWCAP_JSCVT (1UL << 13) +#define AARCH64_HWCAP_FCMA (1UL << 14) +#define AARCH64_HWCAP_LRCPC (1UL << 15) +#define AARCH64_HWCAP_DCPOP (1UL << 16) +#define AARCH64_HWCAP_SHA3 (1UL << 17) +#define AARCH64_HWCAP_SM3 (1UL << 18) +#define AARCH64_HWCAP_SM4 (1UL << 19) +#define AARCH64_HWCAP_ASIMDDP (1UL << 20) +#define AARCH64_HWCAP_SHA512 (1UL << 21) +#define AARCH64_HWCAP_SVE (1UL << 22) +#define AARCH64_HWCAP_ASIMDFHM (1UL << 23) +#define AARCH64_HWCAP_DIT (1UL << 24) +#define AARCH64_HWCAP_USCAT (1UL << 25) +#define AARCH64_HWCAP_ILRCPC (1UL << 26) +#define AARCH64_HWCAP_FLAGM (1UL << 27) +#define AARCH64_HWCAP_SSBS (1UL << 28) +#define AARCH64_HWCAP_SB (1UL << 29) +#define AARCH64_HWCAP_PACA (1UL << 30) +#define AARCH64_HWCAP_PACG (1UL << 31) + +#define AARCH64_HWCAP2_DCPODP (1UL << 0) +#define AARCH64_HWCAP2_SVE2 (1UL << 1) +#define AARCH64_HWCAP2_SVEAES (1UL << 2) +#define AARCH64_HWCAP2_SVEPMULL (1UL << 3) +#define AARCH64_HWCAP2_SVEBITPERM (1UL << 4) +#define AARCH64_HWCAP2_SVESHA3 (1UL << 5) +#define AARCH64_HWCAP2_SVESM4 (1UL << 6) +#define AARCH64_HWCAP2_FLAGM2 (1UL << 7) +#define AARCH64_HWCAP2_FRINT (1UL << 8) +#define AARCH64_HWCAP2_SVEI8MM (1UL << 9) +#define AARCH64_HWCAP2_SVEF32MM (1UL << 10) +#define AARCH64_HWCAP2_SVEF64MM (1UL << 11) +#define AARCH64_HWCAP2_SVEBF16 (1UL << 12) +#define AARCH64_HWCAP2_I8MM (1UL << 13) +#define AARCH64_HWCAP2_BF16 (1UL << 14) +#define AARCH64_HWCAP2_DGH (1UL << 15) +#define AARCH64_HWCAP2_RNG (1UL << 16) +#define AARCH64_HWCAP2_BTI (1UL << 17) + +// http://elixir.free-electrons.com/linux/latest/source/arch/arm/include/uapi/asm/hwcap.h +#define ARM_HWCAP_SWP (1UL << 0) +#define ARM_HWCAP_HALF (1UL << 1) +#define ARM_HWCAP_THUMB (1UL << 2) +#define ARM_HWCAP_26BIT (1UL << 3) +#define ARM_HWCAP_FAST_MULT (1UL << 4) +#define ARM_HWCAP_FPA (1UL << 5) +#define ARM_HWCAP_VFP (1UL << 6) +#define ARM_HWCAP_EDSP (1UL << 7) +#define ARM_HWCAP_JAVA (1UL << 8) +#define ARM_HWCAP_IWMMXT (1UL << 9) +#define ARM_HWCAP_CRUNCH (1UL << 10) +#define ARM_HWCAP_THUMBEE (1UL << 11) +#define ARM_HWCAP_NEON (1UL << 12) +#define ARM_HWCAP_VFPV3 (1UL << 13) +#define ARM_HWCAP_VFPV3D16 (1UL << 14) +#define ARM_HWCAP_TLS (1UL << 15) +#define ARM_HWCAP_VFPV4 (1UL << 16) +#define ARM_HWCAP_IDIVA (1UL << 17) +#define ARM_HWCAP_IDIVT (1UL << 18) +#define ARM_HWCAP_VFPD32 (1UL << 19) +#define ARM_HWCAP_LPAE (1UL << 20) +#define ARM_HWCAP_EVTSTRM (1UL << 21) +#define ARM_HWCAP2_AES (1UL << 0) +#define ARM_HWCAP2_PMULL (1UL << 1) +#define ARM_HWCAP2_SHA1 (1UL << 2) +#define ARM_HWCAP2_SHA2 (1UL << 3) +#define ARM_HWCAP2_CRC32 (1UL << 4) + +// http://elixir.free-electrons.com/linux/latest/source/arch/mips/include/uapi/asm/hwcap.h +#define MIPS_HWCAP_R6 (1UL << 0) +#define MIPS_HWCAP_MSA (1UL << 1) +#define MIPS_HWCAP_CRC32 (1UL << 2) + +// http://elixir.free-electrons.com/linux/latest/source/arch/powerpc/include/uapi/asm/cputable.h +#ifndef _UAPI__ASM_POWERPC_CPUTABLE_H +/* in AT_HWCAP */ +#define PPC_FEATURE_32 0x80000000 +#define PPC_FEATURE_64 0x40000000 +#define PPC_FEATURE_601_INSTR 0x20000000 +#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 +#define PPC_FEATURE_HAS_FPU 0x08000000 +#define PPC_FEATURE_HAS_MMU 0x04000000 +#define PPC_FEATURE_HAS_4xxMAC 0x02000000 +#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 +#define PPC_FEATURE_HAS_SPE 0x00800000 +#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 +#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 +#define PPC_FEATURE_NO_TB 0x00100000 +#define PPC_FEATURE_POWER4 0x00080000 +#define PPC_FEATURE_POWER5 0x00040000 +#define PPC_FEATURE_POWER5_PLUS 0x00020000 +#define PPC_FEATURE_CELL 0x00010000 +#define PPC_FEATURE_BOOKE 0x00008000 +#define PPC_FEATURE_SMT 0x00004000 +#define PPC_FEATURE_ICACHE_SNOOP 0x00002000 +#define PPC_FEATURE_ARCH_2_05 0x00001000 +#define PPC_FEATURE_PA6T 0x00000800 +#define PPC_FEATURE_HAS_DFP 0x00000400 +#define PPC_FEATURE_POWER6_EXT 0x00000200 +#define PPC_FEATURE_ARCH_2_06 0x00000100 +#define PPC_FEATURE_HAS_VSX 0x00000080 + +#define PPC_FEATURE_PSERIES_PERFMON_COMPAT 0x00000040 + +/* Reserved - do not use 0x00000004 */ +#define PPC_FEATURE_TRUE_LE 0x00000002 +#define PPC_FEATURE_PPC_LE 0x00000001 + +/* in AT_HWCAP2 */ +#define PPC_FEATURE2_ARCH_2_07 0x80000000 +#define PPC_FEATURE2_HTM 0x40000000 +#define PPC_FEATURE2_DSCR 0x20000000 +#define PPC_FEATURE2_EBB 0x10000000 +#define PPC_FEATURE2_ISEL 0x08000000 +#define PPC_FEATURE2_TAR 0x04000000 +#define PPC_FEATURE2_VEC_CRYPTO 0x02000000 +#define PPC_FEATURE2_HTM_NOSC 0x01000000 +#define PPC_FEATURE2_ARCH_3_00 0x00800000 +#define PPC_FEATURE2_HAS_IEEE128 0x00400000 +#define PPC_FEATURE2_DARN 0x00200000 +#define PPC_FEATURE2_SCV 0x00100000 +#define PPC_FEATURE2_HTM_NO_SUSPEND 0x00080000 +#endif + +typedef struct +{ + unsigned long hwcaps; + unsigned long hwcaps2; +} HardwareCapabilities; + +HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void); +bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask, + const HardwareCapabilities hwcaps); + +typedef struct +{ + char platform[64]; // 0 terminated string + char base_platform[64]; // 0 terminated string +} PlatformType; + +PlatformType CpuFeatures_GetPlatformType(void); + +CPU_FEATURES_END_CPP_NAMESPACE + +#endif // CPU_FEATURES_INCLUDE_INTERNAL_HWCAPS_H_ diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/stack_line_reader.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/stack_line_reader.h new file mode 100644 index 000000000..d2099066e --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/stack_line_reader.h @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + + +// Reads a file line by line and stores the data on the stack. This allows +// parsing files in one go without allocating. +#ifndef CPU_FEATURES_INCLUDE_INTERNAL_STACK_LINE_READER_H_ +#define CPU_FEATURES_INCLUDE_INTERNAL_STACK_LINE_READER_H_ + +#include "cpu_features_macros.h" +#include "internal/string_view.h" +#include + +CPU_FEATURES_START_CPP_NAMESPACE + +typedef struct +{ + char buffer[STACK_LINE_READER_BUFFER_SIZE]; + StringView view; + int fd; + bool skip_mode; +} StackLineReader; + +// Initializes a StackLineReader. +void StackLineReader_Initialize(StackLineReader* reader, int fd); + +typedef struct +{ + StringView line; // A view of the line. + bool eof; // Nothing more to read, we reached EOF. + bool full_line; // If false the line was truncated to + // STACK_LINE_READER_BUFFER_SIZE. +} LineResult; + +// Reads the file pointed to by fd and tries to read a full line. +LineResult StackLineReader_NextLine(StackLineReader* reader); + +CPU_FEATURES_END_CPP_NAMESPACE + +#endif // CPU_FEATURES_INCLUDE_INTERNAL_STACK_LINE_READER_H_ diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/string_view.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/string_view.h new file mode 100644 index 000000000..9fa0c9e25 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/include/internal/string_view.h @@ -0,0 +1,100 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + + +// A view over a piece of string. The view is not 0 terminated. +#ifndef CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_ +#define CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_ + +#include "cpu_features_macros.h" +#include +#include +#include + +CPU_FEATURES_START_CPP_NAMESPACE + +typedef struct +{ + const char* ptr; + size_t size; +} StringView; + +#ifdef __cplusplus +static const StringView kEmptyStringView = {NULL, 0}; +#else +static const StringView kEmptyStringView; +#endif + +// Returns a StringView from the provided string. +// Passing NULL is valid only if size is 0. +static inline StringView view(const char* str, const size_t size) +{ + StringView view; + view.ptr = str; + view.size = size; + return view; +} + +static inline StringView str(const char* str) { return view(str, strlen(str)); } + +// Returns the index of the first occurrence of c in view or -1 if not found. +int CpuFeatures_StringView_IndexOfChar(const StringView view, char c); + +// Returns the index of the first occurrence of sub_view in view or -1 if not +// found. +int CpuFeatures_StringView_IndexOf(const StringView view, + const StringView sub_view); + +// Returns whether a is equal to b (same content). +bool CpuFeatures_StringView_IsEquals(const StringView a, const StringView b); + +// Returns whether a starts with b. +bool CpuFeatures_StringView_StartsWith(const StringView a, const StringView b); + +// Removes count characters from the beginning of view or kEmptyStringView if +// count if greater than view.size. +StringView CpuFeatures_StringView_PopFront(const StringView str_view, + size_t count); + +// Removes count characters from the end of view or kEmptyStringView if count if +// greater than view.size. +StringView CpuFeatures_StringView_PopBack(const StringView str_view, + size_t count); + +// Keeps the count first characters of view or view if count if greater than +// view.size. +StringView CpuFeatures_StringView_KeepFront(const StringView str_view, + size_t count); + +// Retrieves the first character of view. If view is empty the behavior is +// undefined. +char CpuFeatures_StringView_Front(const StringView view); + +// Retrieves the last character of view. If view is empty the behavior is +// undefined. +char CpuFeatures_StringView_Back(const StringView view); + +// Removes leading and tailing space characters. +StringView CpuFeatures_StringView_TrimWhitespace(StringView view); + +// Convert StringView to positive integer. e.g. "42", "0x2a". +// Returns -1 on error. +int CpuFeatures_StringView_ParsePositiveNumber(const StringView view); + +// Copies src StringView to dst buffer. +void CpuFeatures_StringView_CopyString(const StringView src, char* dst, + size_t dst_size); + +// Checks if line contains the specified whitespace separated word. +bool CpuFeatures_StringView_HasWord(const StringView line, + const char* const word); + +// Get key/value from line. key and value are separated by ": ". +// key and value are cleaned up from leading and trailing whitespaces. +bool CpuFeatures_StringView_GetAttributeKeyValue(const StringView line, + StringView* key, + StringView* value); + +CPU_FEATURES_END_CPP_NAMESPACE + +#endif // CPU_FEATURES_INCLUDE_INTERNAL_STRING_VIEW_H_ diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/ndk_compat/CMakeLists.txt b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/ndk_compat/CMakeLists.txt new file mode 100644 index 000000000..13a9f66be --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/ndk_compat/CMakeLists.txt @@ -0,0 +1,62 @@ +# SPDX-FileCopyrightText: 2010 The Android Open Source Project +# SPDX-License-Identifier: BSD-2-Clause + +# +# library : NDK compat +# +find_package(Threads REQUIRED) +set(NDK_COMPAT_HDRS cpu-features.h) +set(NDK_COMPAT_SRCS + cpu-features.c + $ + $ +) +# Note that following `add_cpu_features_headers_and_sources` will use +# NDK_COMPAT_SRCS in lieu of NDK_COMPAT_HDRS because we don't want cpu_features +# headers to be installed alongside ndk_compat. +add_cpu_features_headers_and_sources(NDK_COMPAT_SRCS NDK_COMPAT_SRCS) +add_library(ndk_compat ${NDK_COMPAT_HDRS} ${NDK_COMPAT_SRCS}) +setup_include_and_definitions(ndk_compat) +target_include_directories(ndk_compat PUBLIC $) +target_link_libraries(ndk_compat PUBLIC ${CMAKE_DL_LIBS} ${CMAKE_THREAD_LIBS_INIT}) +set_target_properties(ndk_compat PROPERTIES PUBLIC_HEADER "${NDK_COMPAT_HDRS}") + +include(GNUInstallDirs) +install(TARGETS ndk_compat + EXPORT CpuFeaturesNdkCompatTargets + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ndk_compat + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) +install(EXPORT CpuFeaturesNdkCompatTargets + NAMESPACE CpuFeatures:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeaturesNdkCompat + COMPONENT Devel +) +include(CMakePackageConfigHelpers) +configure_package_config_file(${PROJECT_SOURCE_DIR}/cmake/CpuFeaturesNdkCompatConfig.cmake.in + "${PROJECT_BINARY_DIR}/CpuFeaturesNdkCompatConfig.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeaturesNdkCompat" + NO_SET_AND_CHECK_MACRO + NO_CHECK_REQUIRED_COMPONENTS_MACRO +) +write_basic_package_version_file( + "${PROJECT_BINARY_DIR}/CpuFeaturesNdkCompatConfigVersion.cmake" + COMPATIBILITY SameMajorVersion +) +install( + FILES + "${PROJECT_BINARY_DIR}/CpuFeaturesNdkCompatConfig.cmake" + "${PROJECT_BINARY_DIR}/CpuFeaturesNdkCompatConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeaturesNdkCompat" + COMPONENT Devel +) + +# +# program : NDK compat test program +# +if(ENABLE_TESTING) + add_executable(ndk-compat-test ndk-compat-test.c) + target_link_libraries(ndk-compat-test PRIVATE ndk_compat) +endif() diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/ndk_compat/README.md b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/ndk_compat/README.md new file mode 100644 index 000000000..8e07bd157 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/ndk_compat/README.md @@ -0,0 +1,16 @@ + +[comment]: # ( +SPDX-License-Identifier: BSD-2-Clause +) + +[comment]: # ( +SPDX-FileCopyrightText: 2010 The Android Open Source Project +) + + +Provides a header compatible with +[android's NDK cpu-features.h](https://android.googlesource.com/platform/ndk/+/master/sources/android/cpufeatures/cpu-features.h). + +It is intended to be a drop in replacement for this header and help users +transition from the NDK to +[Google's cpu_features library](https://github.com/google/cpu_features). diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/ndk_compat/cpu-features.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/ndk_compat/cpu-features.c new file mode 100644 index 000000000..4897f960a --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/ndk_compat/cpu-features.c @@ -0,0 +1,231 @@ +/* + * SPDX-FileCopyrightText: 2010 The Android Open Source Project + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "cpu-features.h" +#include "cpu_features_macros.h" +#include "internal/filesystem.h" +#include "internal/stack_line_reader.h" +#include "internal/string_view.h" +#include + +#if defined(CPU_FEATURES_ARCH_ARM) +#include "cpuinfo_arm.h" +#elif defined(CPU_FEATURES_ARCH_X86) +#include "cpuinfo_x86.h" +#elif defined(CPU_FEATURES_ARCH_MIPS) +#include "cpuinfo_mips.h" +#elif defined(CPU_FEATURES_ARCH_AARCH64) +#include "cpuinfo_aarch64.h" +#endif + +static pthread_once_t g_once; +static int g_inited; +static uint64_t g_cpuFeatures; +static int g_cpuCount; + +#ifdef CPU_FEATURES_ARCH_ARM +static uint32_t g_cpuIdArm; +#endif + +static void set_cpu_mask_bit(uint32_t index, uint32_t* cpu_mask) +{ + *cpu_mask |= 1UL << index; +} + +// Examples of valid inputs: "31", "4-31" +static void parse_cpu_mask(const StringView text, uint32_t* cpu_mask) +{ + int separator_index = CpuFeatures_StringView_IndexOfChar(text, '-'); + if (separator_index < 0) + { // A single cpu index + int cpu_index = CpuFeatures_StringView_ParsePositiveNumber(text); + if (cpu_index < 0) return; + set_cpu_mask_bit(cpu_index, cpu_mask); + } + else + { + int cpu_index_a = CpuFeatures_StringView_ParsePositiveNumber( + CpuFeatures_StringView_KeepFront(text, separator_index)); + int cpu_index_b = CpuFeatures_StringView_ParsePositiveNumber( + CpuFeatures_StringView_PopFront(text, separator_index + 1)); + int i; + if (cpu_index_a < 0 || cpu_index_b < 0) return; + for (i = cpu_index_a; i <= cpu_index_b; ++i) + { + if (i < 32) + { + set_cpu_mask_bit(i, cpu_mask); + } + } + } +} + +// Format specification from +// https://www.kernel.org/doc/Documentation/cputopology.txt +// Examples of valid inputs: "31", "2,4-31,32-63", "0-1,3" +static void parse_cpu_mask_line(const LineResult result, uint32_t* cpu_mask) +{ + if (!result.full_line || result.eof) return; + StringView line = result.line; + for (; line.size > 0;) + { + int next_entry_index = CpuFeatures_StringView_IndexOfChar(line, ','); + if (next_entry_index < 0) + { + parse_cpu_mask(line, cpu_mask); + break; + } + StringView entry = CpuFeatures_StringView_KeepFront(line, next_entry_index); + parse_cpu_mask(entry, cpu_mask); + line = CpuFeatures_StringView_PopFront(line, next_entry_index + 1); + } +} + +static void update_cpu_mask_from_file(const char* filename, + uint32_t* cpu_mask) +{ + const int fd = CpuFeatures_OpenFile(filename); + if (fd >= 0) + { + StackLineReader reader; + StackLineReader_Initialize(&reader, fd); + parse_cpu_mask_line(StackLineReader_NextLine(&reader), cpu_mask); + CpuFeatures_CloseFile(fd); + } +} + +static int get_cpu_count(void) +{ + uint32_t cpu_mask = 0; + update_cpu_mask_from_file("/sys/devices/system/cpu/present", &cpu_mask); + update_cpu_mask_from_file("/sys/devices/system/cpu/possible", &cpu_mask); + return __builtin_popcount(cpu_mask); +} + +static void android_cpuInit(void) +{ + g_cpuFeatures = 0; + g_cpuCount = 1; + g_inited = 1; + + g_cpuCount = get_cpu_count(); + if (g_cpuCount == 0) + { + g_cpuCount = 1; + } +#if defined(CPU_FEATURES_ARCH_ARM) + ArmInfo info = GetArmInfo(); + if (info.architecture == 7) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_ARMv7; + if (info.features.vfpv3) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3; + if (info.features.neon) + { + g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON; + g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFP_D32; + } + if (info.features.vfpv3d16) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFP_FP16; + if (info.features.idiva) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM; + if (info.features.idivt) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2; + if (info.features.iwmmxt) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_iWMMXt; + if (info.features.aes) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_AES; + if (info.features.pmull) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_PMULL; + if (info.features.sha1) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA1; + if (info.features.sha2) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA2; + if (info.features.crc32) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_CRC32; + if (info.architecture >= 6) + g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_LDREX_STREX; + if (info.features.vfp) g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2; + if (info.features.vfpv4) + { + g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFP_FMA; + g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON_FMA; + } + g_cpuIdArm = GetArmCpuId(&info); +#elif defined(CPU_FEATURES_ARCH_X86) + X86Info info = GetX86Info(); + if (info.features.ssse3) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSSE3; + if (info.features.popcnt) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_POPCNT; + if (info.features.movbe) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_MOVBE; + if (info.features.sse4_1) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSE4_1; + if (info.features.sse4_2) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSE4_2; + if (info.features.aes) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AES_NI; + if (info.features.avx) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AVX; + if (info.features.rdrnd) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_RDRAND; + if (info.features.avx2) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AVX2; + if (info.features.sha) g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SHA_NI; +#elif defined(CPU_FEATURES_ARCH_MIPS) + MipsInfo info = GetMipsInfo(); + if (info.features.r6) g_cpuFeatures |= ANDROID_CPU_MIPS_FEATURE_R6; + if (info.features.msa) g_cpuFeatures |= ANDROID_CPU_MIPS_FEATURE_MSA; +#elif defined(CPU_FEATURES_ARCH_AARCH64) + Aarch64Info info = GetAarch64Info(); + if (info.features.fp) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_FP; + if (info.features.asimd) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_ASIMD; + if (info.features.aes) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_AES; + if (info.features.pmull) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_PMULL; + if (info.features.sha1) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA1; + if (info.features.sha2) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA2; + if (info.features.crc32) g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_CRC32; +#endif +} + +AndroidCpuFamily android_getCpuFamily(void) +{ +#if defined(CPU_FEATURES_ARCH_ARM) + return ANDROID_CPU_FAMILY_ARM; +#elif defined(CPU_FEATURES_ARCH_X86_32) + return ANDROID_CPU_FAMILY_X86; +#elif defined(CPU_FEATURES_ARCH_MIPS64) + return ANDROID_CPU_FAMILY_MIPS64; +#elif defined(CPU_FEATURES_ARCH_MIPS32) + return ANDROID_CPU_FAMILY_MIPS; +#elif defined(CPU_FEATURES_ARCH_AARCH64) + return ANDROID_CPU_FAMILY_ARM64; +#elif defined(CPU_FEATURES_ARCH_X86_64) + return ANDROID_CPU_FAMILY_X86_64; +#else + return ANDROID_CPU_FAMILY_UNKNOWN; +#endif +} + +uint64_t android_getCpuFeatures(void) +{ + pthread_once(&g_once, android_cpuInit); + return g_cpuFeatures; +} + +int android_getCpuCount(void) +{ + pthread_once(&g_once, android_cpuInit); + return g_cpuCount; +} + +static void android_cpuInitDummy(void) { g_inited = 1; } + +int android_setCpu(int cpu_count, uint64_t cpu_features) +{ + /* Fail if the library was already initialized. */ + if (g_inited) return 0; + g_cpuCount = (cpu_count <= 0 ? 1 : cpu_count); + g_cpuFeatures = cpu_features; + pthread_once(&g_once, android_cpuInitDummy); + return 1; +} + +#ifdef CPU_FEATURES_ARCH_ARM + +uint32_t android_getCpuIdArm(void) +{ + pthread_once(&g_once, android_cpuInit); + return g_cpuIdArm; +} + +int android_setCpuArm(int cpu_count, uint64_t cpu_features, uint32_t cpu_id) +{ + if (!android_setCpu(cpu_count, cpu_features)) return 0; + g_cpuIdArm = cpu_id; + return 1; +} + +#endif // CPU_FEATURES_ARCH_ARM diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/ndk_compat/cpu-features.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/ndk_compat/cpu-features.h new file mode 100644 index 000000000..791b05ffd --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/ndk_compat/cpu-features.h @@ -0,0 +1,303 @@ +/* + * SPDX-FileCopyrightText: 2010 The Android Open Source Project + * SPDX-License-Identifier: BSD-2-Clause + */ + +#ifndef GOOGLE_CPU_FEATURES_H +#define GOOGLE_CPU_FEATURES_H +#include +#include + +__BEGIN_DECLS + +/* A list of valid values returned by android_getCpuFamily(). + * They describe the CPU Architecture of the current process. + */ +typedef enum +{ + ANDROID_CPU_FAMILY_UNKNOWN = 0, + ANDROID_CPU_FAMILY_ARM, + ANDROID_CPU_FAMILY_X86, + ANDROID_CPU_FAMILY_MIPS, + ANDROID_CPU_FAMILY_ARM64, + ANDROID_CPU_FAMILY_X86_64, + ANDROID_CPU_FAMILY_MIPS64, + ANDROID_CPU_FAMILY_MAX /* do not remove */ +} AndroidCpuFamily; + +/* Return the CPU family of the current process. + * + * Note that this matches the bitness of the current process. I.e. when + * running a 32-bit binary on a 64-bit capable CPU, this will return the + * 32-bit CPU family value. + */ +extern AndroidCpuFamily android_getCpuFamily(void); + +/* Return a bitmap describing a set of optional CPU features that are + * supported by the current device's CPU. The exact bit-flags returned + * depend on the value returned by android_getCpuFamily(). See the + * documentation for the ANDROID_CPU_*_FEATURE_* flags below for details. + */ +extern uint64_t android_getCpuFeatures(void); + +/* The list of feature flags for ANDROID_CPU_FAMILY_ARM that can be + * recognized by the library (see note below for 64-bit ARM). Value details + * are: + * + * VFPv2: + * CPU supports the VFPv2 instruction set. Many, but not all, ARMv6 CPUs + * support these instructions. VFPv2 is a subset of VFPv3 so this will + * be set whenever VFPv3 is set too. + * + * ARMv7: + * CPU supports the ARMv7-A basic instruction set. + * This feature is mandated by the 'armeabi-v7a' ABI. + * + * VFPv3: + * CPU supports the VFPv3-D16 instruction set, providing hardware FPU + * support for single and double precision floating point registers. + * Note that only 16 FPU registers are available by default, unless + * the D32 bit is set too. This feature is also mandated by the + * 'armeabi-v7a' ABI. + * + * VFP_D32: + * CPU VFP optional extension that provides 32 FPU registers, + * instead of 16. Note that ARM mandates this feature is the 'NEON' + * feature is implemented by the CPU. + * + * NEON: + * CPU FPU supports "ARM Advanced SIMD" instructions, also known as + * NEON. Note that this mandates the VFP_D32 feature as well, per the + * ARM Architecture specification. + * + * VFP_FP16: + * Half-width floating precision VFP extension. If set, the CPU + * supports instructions to perform floating-point operations on + * 16-bit registers. This is part of the VFPv4 specification, but + * not mandated by any Android ABI. + * + * VFP_FMA: + * Fused multiply-accumulate VFP instructions extension. Also part of + * the VFPv4 specification, but not mandated by any Android ABI. + * + * NEON_FMA: + * Fused multiply-accumulate NEON instructions extension. Optional + * extension from the VFPv4 specification, but not mandated by any + * Android ABI. + * + * IDIV_ARM: + * Integer division available in ARM mode. Only available + * on recent CPUs (e.g. Cortex-A15). + * + * IDIV_THUMB2: + * Integer division available in Thumb-2 mode. Only available + * on recent CPUs (e.g. Cortex-A15). + * + * iWMMXt: + * Optional extension that adds MMX registers and operations to an + * ARM CPU. This is only available on a few XScale-based CPU designs + * sold by Marvell. Pretty rare in practice. + * + * AES: + * CPU supports AES instructions. These instructions are only + * available for 32-bit applications running on ARMv8 CPU. + * + * CRC32: + * CPU supports CRC32 instructions. These instructions are only + * available for 32-bit applications running on ARMv8 CPU. + * + * SHA2: + * CPU supports SHA2 instructions. These instructions are only + * available for 32-bit applications running on ARMv8 CPU. + * + * SHA1: + * CPU supports SHA1 instructions. These instructions are only + * available for 32-bit applications running on ARMv8 CPU. + * + * PMULL: + * CPU supports 64-bit PMULL and PMULL2 instructions. These + * instructions are only available for 32-bit applications + * running on ARMv8 CPU. + * + * If you want to tell the compiler to generate code that targets one of + * the feature set above, you should probably use one of the following + * flags (for more details, see technical note at the end of this file): + * + * -mfpu=vfp + * -mfpu=vfpv2 + * These are equivalent and tell GCC to use VFPv2 instructions for + * floating-point operations. Use this if you want your code to + * run on *some* ARMv6 devices, and any ARMv7-A device supported + * by Android. + * + * Generated code requires VFPv2 feature. + * + * -mfpu=vfpv3-d16 + * Tell GCC to use VFPv3 instructions (using only 16 FPU registers). + * This should be generic code that runs on any CPU that supports the + * 'armeabi-v7a' Android ABI. Note that no ARMv6 CPU supports this. + * + * Generated code requires VFPv3 feature. + * + * -mfpu=vfpv3 + * Tell GCC to use VFPv3 instructions with 32 FPU registers. + * Generated code requires VFPv3|VFP_D32 features. + * + * -mfpu=neon + * Tell GCC to use VFPv3 instructions with 32 FPU registers, and + * also support NEON intrinsics (see ). + * Generated code requires VFPv3|VFP_D32|NEON features. + * + * -mfpu=vfpv4-d16 + * Generated code requires VFPv3|VFP_FP16|VFP_FMA features. + * + * -mfpu=vfpv4 + * Generated code requires VFPv3|VFP_FP16|VFP_FMA|VFP_D32 features. + * + * -mfpu=neon-vfpv4 + * Generated code requires VFPv3|VFP_FP16|VFP_FMA|VFP_D32|NEON|NEON_FMA + * features. + * + * -mcpu=cortex-a7 + * -mcpu=cortex-a15 + * Generated code requires VFPv3|VFP_FP16|VFP_FMA|VFP_D32| + * NEON|NEON_FMA|IDIV_ARM|IDIV_THUMB2 + * This flag implies -mfpu=neon-vfpv4. + * + * -mcpu=iwmmxt + * Allows the use of iWMMXt instrinsics with GCC. + * + * IMPORTANT NOTE: These flags should only be tested when + * android_getCpuFamily() returns ANDROID_CPU_FAMILY_ARM, i.e. this is a + * 32-bit process. + * + * When running a 64-bit ARM process on an ARMv8 CPU, + * android_getCpuFeatures() will return a different set of bitflags + */ +enum +{ + ANDROID_CPU_ARM_FEATURE_ARMv7 = (1 << 0), + ANDROID_CPU_ARM_FEATURE_VFPv3 = (1 << 1), + ANDROID_CPU_ARM_FEATURE_NEON = (1 << 2), + ANDROID_CPU_ARM_FEATURE_LDREX_STREX = (1 << 3), + ANDROID_CPU_ARM_FEATURE_VFPv2 = (1 << 4), + ANDROID_CPU_ARM_FEATURE_VFP_D32 = (1 << 5), + ANDROID_CPU_ARM_FEATURE_VFP_FP16 = (1 << 6), + ANDROID_CPU_ARM_FEATURE_VFP_FMA = (1 << 7), + ANDROID_CPU_ARM_FEATURE_NEON_FMA = (1 << 8), + ANDROID_CPU_ARM_FEATURE_IDIV_ARM = (1 << 9), + ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 = (1 << 10), + ANDROID_CPU_ARM_FEATURE_iWMMXt = (1 << 11), + ANDROID_CPU_ARM_FEATURE_AES = (1 << 12), + ANDROID_CPU_ARM_FEATURE_PMULL = (1 << 13), + ANDROID_CPU_ARM_FEATURE_SHA1 = (1 << 14), + ANDROID_CPU_ARM_FEATURE_SHA2 = (1 << 15), + ANDROID_CPU_ARM_FEATURE_CRC32 = (1 << 16), +}; + +/* The bit flags corresponding to the output of android_getCpuFeatures() + * when android_getCpuFamily() returns ANDROID_CPU_FAMILY_ARM64. Value details + * are: + * + * FP: + * CPU has Floating-point unit. + * + * ASIMD: + * CPU has Advanced SIMD unit. + * + * AES: + * CPU supports AES instructions. + * + * CRC32: + * CPU supports CRC32 instructions. + * + * SHA2: + * CPU supports SHA2 instructions. + * + * SHA1: + * CPU supports SHA1 instructions. + * + * PMULL: + * CPU supports 64-bit PMULL and PMULL2 instructions. + */ +enum +{ + ANDROID_CPU_ARM64_FEATURE_FP = (1 << 0), + ANDROID_CPU_ARM64_FEATURE_ASIMD = (1 << 1), + ANDROID_CPU_ARM64_FEATURE_AES = (1 << 2), + ANDROID_CPU_ARM64_FEATURE_PMULL = (1 << 3), + ANDROID_CPU_ARM64_FEATURE_SHA1 = (1 << 4), + ANDROID_CPU_ARM64_FEATURE_SHA2 = (1 << 5), + ANDROID_CPU_ARM64_FEATURE_CRC32 = (1 << 6), +}; + +/* The bit flags corresponding to the output of android_getCpuFeatures() + * when android_getCpuFamily() returns ANDROID_CPU_FAMILY_X86 or + * ANDROID_CPU_FAMILY_X86_64. + */ +enum +{ + ANDROID_CPU_X86_FEATURE_SSSE3 = (1 << 0), + ANDROID_CPU_X86_FEATURE_POPCNT = (1 << 1), + ANDROID_CPU_X86_FEATURE_MOVBE = (1 << 2), + ANDROID_CPU_X86_FEATURE_SSE4_1 = (1 << 3), + ANDROID_CPU_X86_FEATURE_SSE4_2 = (1 << 4), + ANDROID_CPU_X86_FEATURE_AES_NI = (1 << 5), + ANDROID_CPU_X86_FEATURE_AVX = (1 << 6), + ANDROID_CPU_X86_FEATURE_RDRAND = (1 << 7), + ANDROID_CPU_X86_FEATURE_AVX2 = (1 << 8), + ANDROID_CPU_X86_FEATURE_SHA_NI = (1 << 9), +}; + +/* The bit flags corresponding to the output of android_getCpuFeatures() + * when android_getCpuFamily() returns ANDROID_CPU_FAMILY_MIPS + * or ANDROID_CPU_FAMILY_MIPS64. Values are: + * + * R6: + * CPU executes MIPS Release 6 instructions natively, and + * supports obsoleted R1..R5 instructions only via kernel traps. + * + * MSA: + * CPU supports Mips SIMD Architecture instructions. + */ +enum +{ + ANDROID_CPU_MIPS_FEATURE_R6 = (1 << 0), + ANDROID_CPU_MIPS_FEATURE_MSA = (1 << 1), +}; + +/* Return the number of CPU cores detected on this device. + * Please note the current implementation supports up to 32 cpus. + */ +extern int android_getCpuCount(void); + +/* The following is used to force the CPU count and features + * mask in sandboxed processes. Under 4.1 and higher, these processes + * cannot access /proc, which is the only way to get information from + * the kernel about the current hardware (at least on ARM). + * + * It _must_ be called only once, and before any android_getCpuXXX + * function, any other case will fail. + * + * This function return 1 on success, and 0 on failure. + */ +extern int android_setCpu(int cpu_count, uint64_t cpu_features); + +#ifdef __arm__ + +/* Retrieve the ARM 32-bit CPUID value from the kernel. + * Note that this cannot work on sandboxed processes under 4.1 and + * higher, unless you called android_setCpuArm() before. + */ +extern uint32_t android_getCpuIdArm(void); + +/* An ARM-specific variant of android_setCpu() that also allows you + * to set the ARM CPUID field. + */ +extern int android_setCpuArm(int cpu_count, uint64_t cpu_features, + uint32_t cpu_id); + +#endif + +__END_DECLS +#endif /* GOOGLE_CPU_FEATURES_H */ diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/ndk_compat/ndk-compat-test.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/ndk_compat/ndk-compat-test.c new file mode 100644 index 000000000..431cc8aa2 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/ndk_compat/ndk-compat-test.c @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: 2010 The Android Open Source Project + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "cpu-features.h" +#include + +int main() +{ + printf("android_getCpuFamily()=%d\n", android_getCpuFamily()); + printf("android_getCpuFeatures()=0x%08llx\n", android_getCpuFeatures()); + printf("android_getCpuCount()=%d\n", android_getCpuCount()); +#ifdef __arm__ + printf("android_getCpuIdArm()=0x%04x\n", android_getCpuIdArm()); +#endif //__arm__ +} diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/scripts/run_integration.sh b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/scripts/run_integration.sh new file mode 100755 index 000000000..5ea6d9888 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/scripts/run_integration.sh @@ -0,0 +1,212 @@ +#!/usr/bin/env bash + +# SPDX-FileCopyrightText: 2017 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +readonly SCRIPT_FOLDER=$(cd -P -- "$(dirname -- "$0")" && pwd -P) +readonly PROJECT_FOLDER="${SCRIPT_FOLDER}/.." +readonly ARCHIVE_FOLDER=~/cpu_features_archives +readonly QEMU_INSTALL=${ARCHIVE_FOLDER}/qemu +readonly DEFAULT_CMAKE_ARGS=" -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON" + +function extract() { + case $1 in + *.tar.bz2) tar xjf "$1" ;; + *.tar.xz) tar xJf "$1" ;; + *.tar.gz) tar xzf "$1" ;; + *) + echo "don't know how to extract '$1'..." + exit 1 + esac +} + +function unpackifnotexists() { + mkdir -p "${ARCHIVE_FOLDER}" + cd "${ARCHIVE_FOLDER}" || exit + local URL=$1 + local RELATIVE_FOLDER=$2 + local DESTINATION="${ARCHIVE_FOLDER}/${RELATIVE_FOLDER}" + if [[ ! -d "${DESTINATION}" ]] ; then + local ARCHIVE_NAME=$(echo ${URL} | sed 's/.*\///') + test -f "${ARCHIVE_NAME}" || wget -q "${URL}" + extract "${ARCHIVE_NAME}" + rm -f "${ARCHIVE_NAME}" + fi +} + +function installqemuifneeded() { + local VERSION=${QEMU_VERSION:=2.11.1} + local ARCHES=${QEMU_ARCHES:=arm aarch64 i386 x86_64 mips mipsel mips64 mips64el} + local TARGETS=${QEMU_TARGETS:=$(echo "$ARCHES" | sed 's#$# #;s#\([^ ]*\) #\1-linux-user #g')} + + if echo "${VERSION} ${TARGETS}" | cmp --silent ${QEMU_INSTALL}/.build -; then + echo "qemu ${VERSION} up to date!" + return 0 + fi + + echo "VERSION: ${VERSION}" + echo "TARGETS: ${TARGETS}" + + rm -rf ${QEMU_INSTALL} + + # Checking for a tarball before downloading makes testing easier :-) + local QEMU_URL="http://wiki.qemu-project.org/download/qemu-${VERSION}.tar.xz" + local QEMU_FOLDER="qemu-${VERSION}" + unpackifnotexists ${QEMU_URL} ${QEMU_FOLDER} + cd ${QEMU_FOLDER} || exit + + ./configure \ + --prefix="${QEMU_INSTALL}" \ + --target-list="${TARGETS}" \ + --disable-docs \ + --disable-sdl \ + --disable-gtk \ + --disable-gnutls \ + --disable-gcrypt \ + --disable-nettle \ + --disable-curses \ + --static + + make -j4 + make install + + echo "$VERSION $TARGETS" > ${QEMU_INSTALL}/.build +} + +function assert_defined(){ + local VALUE=${1} + : "${VALUE?"${1} needs to be defined"}" +} + +function integrate() { + cd "${PROJECT_FOLDER}" + case "${OS}" in + "Windows_NT") CMAKE_BUILD_ARGS="--config Debug --target ALL_BUILD" + CMAKE_TEST_FILES="${BUILD_DIR}/test/Debug/*_test.exe" + DEMO=${BUILD_DIR}/Debug/list_cpu_features.exe + ;; + *) CMAKE_BUILD_ARGS="--target all" + CMAKE_TEST_FILES="${BUILD_DIR}/test/*_test" + DEMO=${BUILD_DIR}/list_cpu_features + ;; + esac + + # Generating CMake configuration + cmake -H. -B"${BUILD_DIR}" ${DEFAULT_CMAKE_ARGS} "${CMAKE_ADDITIONAL_ARGS[@]}" -G"${CMAKE_GENERATOR:-Unix Makefiles}" + + # Building + cmake --build "${BUILD_DIR}" ${CMAKE_BUILD_ARGS} + + # Running tests if needed + if [[ "${QEMU_ARCH}" == "DISABLED" ]]; then + return + fi + RUN_CMD="" + if [[ -n "${QEMU_ARCH}" ]]; then + installqemuifneeded + RUN_CMD="${QEMU_INSTALL}/bin/qemu-${QEMU_ARCH} ${QEMU_ARGS[@]}" + fi + for test_binary in ${CMAKE_TEST_FILES}; do + ${RUN_CMD} ${test_binary} + done + ${RUN_CMD} ${DEMO} +} + +function expand_linaro_config() { + assert_defined TARGET + local LINARO_ROOT_URL=https://releases.linaro.org/components/toolchain/binaries/7.2-2017.11 + + local GCC_URL=${LINARO_ROOT_URL}/${TARGET}/gcc-linaro-7.2.1-2017.11-x86_64_${TARGET}.tar.xz + local GCC_RELATIVE_FOLDER="gcc-linaro-7.2.1-2017.11-x86_64_${TARGET}" + unpackifnotexists "${GCC_URL}" "${GCC_RELATIVE_FOLDER}" + + local SYSROOT_URL=${LINARO_ROOT_URL}/${TARGET}/sysroot-glibc-linaro-2.25-2017.11-${TARGET}.tar.xz + local SYSROOT_RELATIVE_FOLDER=sysroot-glibc-linaro-2.25-2017.11-${TARGET} + unpackifnotexists "${SYSROOT_URL}" "${SYSROOT_RELATIVE_FOLDER}" + + local SYSROOT_FOLDER=${ARCHIVE_FOLDER}/${SYSROOT_RELATIVE_FOLDER} + local GCC_FOLDER=${ARCHIVE_FOLDER}/${GCC_RELATIVE_FOLDER} + + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_NAME=Linux) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_PROCESSOR=${TARGET}) + + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSROOT=${SYSROOT_FOLDER}) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER=${GCC_FOLDER}/bin/${TARGET}-gcc) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER=${GCC_FOLDER}/bin/${TARGET}-g++) + + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY) + + QEMU_ARGS+=(-L ${SYSROOT_FOLDER}) + QEMU_ARGS+=(-E LD_LIBRARY_PATH=/lib) +} + +function expand_codescape_config() { + assert_defined TARGET + local DATE=2017.10-08 + local CODESCAPE_URL=https://codescape.mips.com/components/toolchain/${DATE}/Codescape.GNU.Tools.Package.${DATE}.for.MIPS.MTI.Linux.CentOS-5.x86_64.tar.gz + local GCC_URL=${CODESCAPE_URL} + local GCC_RELATIVE_FOLDER="mips-mti-linux-gnu/${DATE}" + unpackifnotexists "${GCC_URL}" "${GCC_RELATIVE_FOLDER}" + + local GCC_FOLDER=${ARCHIVE_FOLDER}/${GCC_RELATIVE_FOLDER} + local MIPS_FLAGS="" + local LIBC_FOLDER_SUFFIX="" + local FLAVOUR="" + case "${TARGET}" in + "mips32") MIPS_FLAGS="-EB -mabi=32"; FLAVOUR="mips-r2-hard"; LIBC_FOLDER_SUFFIX="lib" ;; + "mips32el") MIPS_FLAGS="-EL -mabi=32"; FLAVOUR="mipsel-r2-hard"; LIBC_FOLDER_SUFFIX="lib" ;; + "mips64") MIPS_FLAGS="-EB -mabi=64"; FLAVOUR="mips-r2-hard"; LIBC_FOLDER_SUFFIX="lib64" ;; + "mips64el") MIPS_FLAGS="-EL -mabi=64"; FLAVOUR="mipsel-r2-hard"; LIBC_FOLDER_SUFFIX="lib64" ;; + *) echo 'unknown mips platform'; exit 1;; + esac + + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_FIND_ROOT_PATH=${GCC_FOLDER}) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_NAME=Linux) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_SYSTEM_PROCESSOR=${TARGET}) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER=mips-mti-linux-gnu-gcc) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER=mips-mti-linux-gnu-g++) + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_C_COMPILER_ARG1="${MIPS_FLAGS}") + CMAKE_ADDITIONAL_ARGS+=(-DCMAKE_CXX_COMPILER_ARG1="${MIPS_FLAGS}") + + local SYSROOT_FOLDER=${GCC_FOLDER}/sysroot/${FLAVOUR} + + # Keeping only the sysroot of interest to save on travis cache. + if [[ "${CONTINUOUS_INTEGRATION}" = "true" ]]; then + for folder in ${GCC_FOLDER}/sysroot/*; do + if [[ "${folder}" != "${SYSROOT_FOLDER}" ]]; then + rm -rf ${folder} + fi + done + fi + + local LIBC_FOLDER=${GCC_FOLDER}/mips-mti-linux-gnu/lib/${FLAVOUR}/${LIBC_FOLDER_SUFFIX} + QEMU_ARGS+=(-L ${SYSROOT_FOLDER}) + QEMU_ARGS+=(-E LD_PRELOAD=${LIBC_FOLDER}/libstdc++.so.6:${LIBC_FOLDER}/libgcc_s.so.1) +} + +function expand_environment_and_integrate() { + assert_defined PROJECT_FOLDER + assert_defined TARGET + + BUILD_DIR="${PROJECT_FOLDER}/cmake_build/${TARGET}" + mkdir -p "${BUILD_DIR}" + + declare -a CONFIG_NAMES=() + declare -a QEMU_ARGS=() + declare -a CMAKE_ADDITIONAL_ARGS=() + + case ${TOOLCHAIN} in + LINARO) expand_linaro_config ;; + CODESCAPE) expand_codescape_config ;; + NATIVE) QEMU_ARCH="" ;; + *) echo "Unknown toolchain '${TOOLCHAIN}'..."; exit 1;; + esac + integrate +} + +if [ "${CONTINUOUS_INTEGRATION}" = "true" ]; then + QEMU_ARCHES=${QEMU_ARCH} + expand_environment_and_integrate +fi diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/scripts/test_integration.sh b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/scripts/test_integration.sh new file mode 100755 index 000000000..2256de59e --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/scripts/test_integration.sh @@ -0,0 +1,109 @@ +#!/usr/bin/env bash + +# SPDX-FileCopyrightText: 2017 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +source "$(dirname -- "$0")"/run_integration.sh + +# Toolchains for little-endian, 64-bit ARMv8 for GNU/Linux systems +function set_aarch64-linux-gnu() { + TOOLCHAIN=LINARO + TARGET=aarch64-linux-gnu + QEMU_ARCH=aarch64 +} + +# Toolchains for little-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems +function set_arm-linux-gnueabihf() { + TOOLCHAIN=LINARO + TARGET=arm-linux-gnueabihf + QEMU_ARCH=arm +} + +# Toolchains for little-endian, 32-bit ARMv8 for GNU/Linux systems +function set_armv8l-linux-gnueabihf() { + TOOLCHAIN=LINARO + TARGET=armv8l-linux-gnueabihf + QEMU_ARCH=arm +} + +# Toolchains for little-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems +function set_arm-linux-gnueabi() { + TOOLCHAIN=LINARO + TARGET=arm-linux-gnueabi + QEMU_ARCH=arm +} + +# Toolchains for big-endian, 64-bit ARMv8 for GNU/Linux systems +function set_aarch64_be-linux-gnu() { + TOOLCHAIN=LINARO + TARGET=aarch64_be-linux-gnu + QEMU_ARCH=DISABLED +} + +# Toolchains for big-endian, hard-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems +function set_armeb-linux-gnueabihf() { + TOOLCHAIN=LINARO + TARGET=armeb-linux-gnueabihf + QEMU_ARCH=DISABLED +} + +# Toolchains for big-endian, soft-float, 32-bit ARMv7 (and earlier) for GNU/Linux systems +function set_armeb-linux-gnueabi() { + TOOLCHAIN=LINARO + TARGET=armeb-linux-gnueabi + QEMU_ARCH=DISABLED +} + +function set_mips32() { + TOOLCHAIN=CODESCAPE + TARGET=mips32 + QEMU_ARCH=mips +} + +function set_mips32el() { + TOOLCHAIN=CODESCAPE + TARGET=mips32el + QEMU_ARCH=mipsel +} + +function set_mips64() { + TOOLCHAIN=CODESCAPE + TARGET=mips64 + QEMU_ARCH=mips64 +} + +function set_mips64el() { + TOOLCHAIN=CODESCAPE + TARGET=mips64el + QEMU_ARCH=mips64el +} + +function set_native() { + TOOLCHAIN=NATIVE + TARGET=native + QEMU_ARCH="" +} + +ENVIRONMENTS=" + set_aarch64-linux-gnu + set_arm-linux-gnueabihf + set_armv8l-linux-gnueabihf + set_arm-linux-gnueabi + set_aarch64_be-linux-gnu + set_armeb-linux-gnueabihf + set_armeb-linux-gnueabi + set_mips32 + set_mips32el + set_mips64 + set_mips64el + set_native +" + +set -e + +CMAKE_GENERATOR="Ninja" + +for SET_ENVIRONMENT in ${ENVIRONMENTS}; do + ${SET_ENVIRONMENT} + expand_environment_and_integrate +done diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_aarch64.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_aarch64.c new file mode 100644 index 000000000..a62b35026 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_aarch64.c @@ -0,0 +1,158 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "cpuinfo_aarch64.h" +#include "internal/filesystem.h" +#include "internal/hwcaps.h" +#include "internal/stack_line_reader.h" +#include "internal/string_view.h" +#include +#include + +// Generation of feature's getters/setters functions and kGetters, kSetters, +// kCpuInfoFlags and kHardwareCapabilities global tables. +#define DEFINE_TABLE_FEATURES \ + FEATURE(AARCH64_FP, fp, "fp", AARCH64_HWCAP_FP, 0) \ + FEATURE(AARCH64_ASIMD, asimd, "asimd", AARCH64_HWCAP_ASIMD, 0) \ + FEATURE(AARCH64_EVTSTRM, evtstrm, "evtstrm", AARCH64_HWCAP_EVTSTRM, 0) \ + FEATURE(AARCH64_AES, aes, "aes", AARCH64_HWCAP_AES, 0) \ + FEATURE(AARCH64_PMULL, pmull, "pmull", AARCH64_HWCAP_PMULL, 0) \ + FEATURE(AARCH64_SHA1, sha1, "sha1", AARCH64_HWCAP_SHA1, 0) \ + FEATURE(AARCH64_SHA2, sha2, "sha2", AARCH64_HWCAP_SHA2, 0) \ + FEATURE(AARCH64_CRC32, crc32, "crc32", AARCH64_HWCAP_CRC32, 0) \ + FEATURE(AARCH64_ATOMICS, atomics, "atomics", AARCH64_HWCAP_ATOMICS, 0) \ + FEATURE(AARCH64_FPHP, fphp, "fphp", AARCH64_HWCAP_FPHP, 0) \ + FEATURE(AARCH64_ASIMDHP, asimdhp, "asimdhp", AARCH64_HWCAP_ASIMDHP, 0) \ + FEATURE(AARCH64_CPUID, cpuid, "cpuid", AARCH64_HWCAP_CPUID, 0) \ + FEATURE(AARCH64_ASIMDRDM, asimdrdm, "asimdrdm", AARCH64_HWCAP_ASIMDRDM, 0) \ + FEATURE(AARCH64_JSCVT, jscvt, "jscvt", AARCH64_HWCAP_JSCVT, 0) \ + FEATURE(AARCH64_FCMA, fcma, "fcma", AARCH64_HWCAP_FCMA, 0) \ + FEATURE(AARCH64_LRCPC, lrcpc, "lrcpc", AARCH64_HWCAP_LRCPC, 0) \ + FEATURE(AARCH64_DCPOP, dcpop, "dcpop", AARCH64_HWCAP_DCPOP, 0) \ + FEATURE(AARCH64_SHA3, sha3, "sha3", AARCH64_HWCAP_SHA3, 0) \ + FEATURE(AARCH64_SM3, sm3, "sm3", AARCH64_HWCAP_SM3, 0) \ + FEATURE(AARCH64_SM4, sm4, "sm4", AARCH64_HWCAP_SM4, 0) \ + FEATURE(AARCH64_ASIMDDP, asimddp, "asimddp", AARCH64_HWCAP_ASIMDDP, 0) \ + FEATURE(AARCH64_SHA512, sha512, "sha512", AARCH64_HWCAP_SHA512, 0) \ + FEATURE(AARCH64_SVE, sve, "sve", AARCH64_HWCAP_SVE, 0) \ + FEATURE(AARCH64_ASIMDFHM, asimdfhm, "asimdfhm", AARCH64_HWCAP_ASIMDFHM, 0) \ + FEATURE(AARCH64_DIT, dit, "dit", AARCH64_HWCAP_DIT, 0) \ + FEATURE(AARCH64_USCAT, uscat, "uscat", AARCH64_HWCAP_USCAT, 0) \ + FEATURE(AARCH64_ILRCPC, ilrcpc, "ilrcpc", AARCH64_HWCAP_ILRCPC, 0) \ + FEATURE(AARCH64_FLAGM, flagm, "flagm", AARCH64_HWCAP_FLAGM, 0) \ + FEATURE(AARCH64_SSBS, ssbs, "ssbs", AARCH64_HWCAP_SSBS, 0) \ + FEATURE(AARCH64_SB, sb, "sb", AARCH64_HWCAP_SB, 0) \ + FEATURE(AARCH64_PACA, paca, "paca", AARCH64_HWCAP_PACA, 0) \ + FEATURE(AARCH64_PACG, pacg, "pacg", AARCH64_HWCAP_PACG, 0) \ + FEATURE(AARCH64_DCPODP, dcpodp, "dcpodp", 0, AARCH64_HWCAP2_DCPODP) \ + FEATURE(AARCH64_SVE2, sve2, "sve2", 0, AARCH64_HWCAP2_SVE2) \ + FEATURE(AARCH64_SVEAES, sveaes, "sveaes", 0, AARCH64_HWCAP2_SVEAES) \ + FEATURE(AARCH64_SVEPMULL, svepmull, "svepmull", 0, AARCH64_HWCAP2_SVEPMULL) \ + FEATURE(AARCH64_SVEBITPERM, svebitperm, "svebitperm", 0, \ + AARCH64_HWCAP2_SVEBITPERM) \ + FEATURE(AARCH64_SVESHA3, svesha3, "svesha3", 0, AARCH64_HWCAP2_SVESHA3) \ + FEATURE(AARCH64_SVESM4, svesm4, "svesm4", 0, AARCH64_HWCAP2_SVESM4) \ + FEATURE(AARCH64_FLAGM2, flagm2, "flagm2", 0, AARCH64_HWCAP2_FLAGM2) \ + FEATURE(AARCH64_FRINT, frint, "frint", 0, AARCH64_HWCAP2_FRINT) \ + FEATURE(AARCH64_SVEI8MM, svei8mm, "svei8mm", 0, AARCH64_HWCAP2_SVEI8MM) \ + FEATURE(AARCH64_SVEF32MM, svef32mm, "svef32mm", 0, AARCH64_HWCAP2_SVEF32MM) \ + FEATURE(AARCH64_SVEF64MM, svef64mm, "svef64mm", 0, AARCH64_HWCAP2_SVEF64MM) \ + FEATURE(AARCH64_SVEBF16, svebf16, "svebf16", 0, AARCH64_HWCAP2_SVEBF16) \ + FEATURE(AARCH64_I8MM, i8mm, "i8mm", 0, AARCH64_HWCAP2_I8MM) \ + FEATURE(AARCH64_BF16, bf16, "bf16", 0, AARCH64_HWCAP2_BF16) \ + FEATURE(AARCH64_DGH, dgh, "dgh", 0, AARCH64_HWCAP2_DGH) \ + FEATURE(AARCH64_RNG, rng, "rng", 0, AARCH64_HWCAP2_RNG) \ + FEATURE(AARCH64_BTI, bti, "bti", 0, AARCH64_HWCAP2_BTI) +#define DEFINE_TABLE_FEATURE_TYPE Aarch64Features +#include "define_tables.h" + +static bool HandleAarch64Line(const LineResult result, + Aarch64Info* const info) +{ + StringView line = result.line; + StringView key, value; + if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) + { + if (CpuFeatures_StringView_IsEquals(key, str("Features"))) + { + for (size_t i = 0; i < AARCH64_LAST_; ++i) + { + kSetters[i](&info->features, + CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i])); + } + } + else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) + { + info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value); + } + else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) + { + info->variant = CpuFeatures_StringView_ParsePositiveNumber(value); + } + else if (CpuFeatures_StringView_IsEquals(key, str("CPU part"))) + { + info->part = CpuFeatures_StringView_ParsePositiveNumber(value); + } + else if (CpuFeatures_StringView_IsEquals(key, str("CPU revision"))) + { + info->revision = CpuFeatures_StringView_ParsePositiveNumber(value); + } + } + return !result.eof; +} + +static void FillProcCpuInfoData(Aarch64Info* const info) +{ + const int fd = CpuFeatures_OpenFile("/proc/cpuinfo"); + if (fd >= 0) + { + StackLineReader reader; + StackLineReader_Initialize(&reader, fd); + for (;;) + { + if (!HandleAarch64Line(StackLineReader_NextLine(&reader), info)) + { + break; + } + } + CpuFeatures_CloseFile(fd); + } +} + +static const Aarch64Info kEmptyAarch64Info; + +Aarch64Info GetAarch64Info(void) +{ + // capabilities are fetched from both getauxval and /proc/cpuinfo so we can + // have some information if the executable is sandboxed (aka no access to + // /proc/cpuinfo). + Aarch64Info info = kEmptyAarch64Info; + + FillProcCpuInfoData(&info); + const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities(); + for (size_t i = 0; i < AARCH64_LAST_; ++i) + { + if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) + { + kSetters[i](&info.features, true); + } + } + + return info; +} + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +int GetAarch64FeaturesEnumValue(const Aarch64Features* features, + Aarch64FeaturesEnum value) +{ + if (value >= AARCH64_LAST_) return false; + return kGetters[value](features); +} + +const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum value) +{ + if (value >= AARCH64_LAST_) return "unknown feature"; + return kCpuInfoFlags[value]; +} diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_arm.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_arm.c new file mode 100644 index 000000000..040aab95a --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_arm.c @@ -0,0 +1,234 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "cpuinfo_arm.h" +#include "internal/bit_utils.h" +#include "internal/filesystem.h" +#include "internal/hwcaps.h" +#include "internal/stack_line_reader.h" +#include "internal/string_view.h" +#include +#include + +// Generation of feature's getters/setters functions and kGetters, kSetters, +// kCpuInfoFlags and kHardwareCapabilities global tables. +#define DEFINE_TABLE_FEATURES \ + FEATURE(ARM_SWP, swp, "swp", ARM_HWCAP_SWP, 0) \ + FEATURE(ARM_HALF, half, "half", ARM_HWCAP_HALF, 0) \ + FEATURE(ARM_THUMB, thumb, "thumb", ARM_HWCAP_THUMB, 0) \ + FEATURE(ARM_26BIT, _26bit, "26bit", ARM_HWCAP_26BIT, 0) \ + FEATURE(ARM_FASTMULT, fastmult, "fastmult", ARM_HWCAP_FAST_MULT, 0) \ + FEATURE(ARM_FPA, fpa, "fpa", ARM_HWCAP_FPA, 0) \ + FEATURE(ARM_VFP, vfp, "vfp", ARM_HWCAP_VFP, 0) \ + FEATURE(ARM_EDSP, edsp, "edsp", ARM_HWCAP_EDSP, 0) \ + FEATURE(ARM_JAVA, java, "java", ARM_HWCAP_JAVA, 0) \ + FEATURE(ARM_IWMMXT, iwmmxt, "iwmmxt", ARM_HWCAP_IWMMXT, 0) \ + FEATURE(ARM_CRUNCH, crunch, "crunch", ARM_HWCAP_CRUNCH, 0) \ + FEATURE(ARM_THUMBEE, thumbee, "thumbee", ARM_HWCAP_THUMBEE, 0) \ + FEATURE(ARM_NEON, neon, "neon", ARM_HWCAP_NEON, 0) \ + FEATURE(ARM_VFPV3, vfpv3, "vfpv3", ARM_HWCAP_VFPV3, 0) \ + FEATURE(ARM_VFPV3D16, vfpv3d16, "vfpv3d16", ARM_HWCAP_VFPV3D16, 0) \ + FEATURE(ARM_TLS, tls, "tls", ARM_HWCAP_TLS, 0) \ + FEATURE(ARM_VFPV4, vfpv4, "vfpv4", ARM_HWCAP_VFPV4, 0) \ + FEATURE(ARM_IDIVA, idiva, "idiva", ARM_HWCAP_IDIVA, 0) \ + FEATURE(ARM_IDIVT, idivt, "idivt", ARM_HWCAP_IDIVT, 0) \ + FEATURE(ARM_VFPD32, vfpd32, "vfpd32", ARM_HWCAP_VFPD32, 0) \ + FEATURE(ARM_LPAE, lpae, "lpae", ARM_HWCAP_LPAE, 0) \ + FEATURE(ARM_EVTSTRM, evtstrm, "evtstrm", ARM_HWCAP_EVTSTRM, 0) \ + FEATURE(ARM_AES, aes, "aes", 0, ARM_HWCAP2_AES) \ + FEATURE(ARM_PMULL, pmull, "pmull", 0, ARM_HWCAP2_PMULL) \ + FEATURE(ARM_SHA1, sha1, "sha1", 0, ARM_HWCAP2_SHA1) \ + FEATURE(ARM_SHA2, sha2, "sha2", 0, ARM_HWCAP2_SHA2) \ + FEATURE(ARM_CRC32, crc32, "crc32", 0, ARM_HWCAP2_CRC32) +#define DEFINE_TABLE_FEATURE_TYPE ArmFeatures +#include "define_tables.h" + +typedef struct +{ + bool processor_reports_armv6; + bool hardware_reports_goldfish; +} ProcCpuInfoData; + +static int IndexOfNonDigit(StringView str) +{ + size_t index = 0; + while (str.size && isdigit(CpuFeatures_StringView_Front(str))) + { + str = CpuFeatures_StringView_PopFront(str, 1); + ++index; + } + return index; +} + +static bool HandleArmLine(const LineResult result, ArmInfo* const info, + ProcCpuInfoData* const proc_info) +{ + StringView line = result.line; + StringView key, value; + if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) + { + if (CpuFeatures_StringView_IsEquals(key, str("Features"))) + { + for (size_t i = 0; i < ARM_LAST_; ++i) + { + kSetters[i](&info->features, + CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i])); + } + } + else if (CpuFeatures_StringView_IsEquals(key, str("CPU implementer"))) + { + info->implementer = CpuFeatures_StringView_ParsePositiveNumber(value); + } + else if (CpuFeatures_StringView_IsEquals(key, str("CPU variant"))) + { + info->variant = CpuFeatures_StringView_ParsePositiveNumber(value); + } + else if (CpuFeatures_StringView_IsEquals(key, str("CPU part"))) + { + info->part = CpuFeatures_StringView_ParsePositiveNumber(value); + } + else if (CpuFeatures_StringView_IsEquals(key, str("CPU revision"))) + { + info->revision = CpuFeatures_StringView_ParsePositiveNumber(value); + } + else if (CpuFeatures_StringView_IsEquals(key, str("CPU architecture"))) + { + // CPU architecture is a number that may be followed by letters. e.g. + // "6TEJ", "7". + const StringView digits = + CpuFeatures_StringView_KeepFront(value, IndexOfNonDigit(value)); + info->architecture = CpuFeatures_StringView_ParsePositiveNumber(digits); + } + else if (CpuFeatures_StringView_IsEquals(key, str("Processor")) || + CpuFeatures_StringView_IsEquals(key, str("model name"))) + { + // Android reports this in a non-Linux standard "Processor" but sometimes + // also in "model name", Linux reports it only in "model name" + // see RaspberryPiZero (Linux) vs InvalidArmv7 (Android) test-cases + proc_info->processor_reports_armv6 = + CpuFeatures_StringView_IndexOf(value, str("(v6l)")) >= 0; + } + else if (CpuFeatures_StringView_IsEquals(key, str("Hardware"))) + { + proc_info->hardware_reports_goldfish = + CpuFeatures_StringView_IsEquals(value, str("Goldfish")); + } + } + return !result.eof; +} + +uint32_t GetArmCpuId(const ArmInfo* const info) +{ + return (ExtractBitRange(info->implementer, 7, 0) << 24) | + (ExtractBitRange(info->variant, 3, 0) << 20) | + (ExtractBitRange(info->part, 11, 0) << 4) | + (ExtractBitRange(info->revision, 3, 0) << 0); +} + +static void FixErrors(ArmInfo* const info, + ProcCpuInfoData* const proc_cpu_info_data) +{ + // Fixing Samsung kernel reporting invalid cpu architecture. + // http://code.google.com/p/android/issues/detail?id=10812 + if (proc_cpu_info_data->processor_reports_armv6 && info->architecture >= 7) + { + info->architecture = 6; + } + + // Handle kernel configuration bugs that prevent the correct reporting of CPU + // features. + switch (GetArmCpuId(info)) + { + case 0x4100C080: + // Special case: The emulator-specific Android 4.2 kernel fails to report + // support for the 32-bit ARM IDIV instruction. Technically, this is a + // feature of the virtual CPU implemented by the emulator. Note that it + // could also support Thumb IDIV in the future, and this will have to be + // slightly updated. + if (info->architecture >= 7 && + proc_cpu_info_data->hardware_reports_goldfish) + { + info->features.idiva = true; + } + break; + case 0x511004D0: + // https://crbug.com/341598. + info->features.neon = false; + break; + case 0x510006F2: + case 0x510006F3: + // The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report + // IDIV support. + info->features.idiva = true; + info->features.idivt = true; + break; + } + + // Propagate cpu features. + if (info->features.vfpv4) info->features.vfpv3 = true; + if (info->features.neon) info->features.vfpv3 = true; + if (info->features.vfpv3) info->features.vfp = true; +} + +static void FillProcCpuInfoData(ArmInfo* const info, + ProcCpuInfoData* proc_cpu_info_data) +{ + const int fd = CpuFeatures_OpenFile("/proc/cpuinfo"); + if (fd >= 0) + { + StackLineReader reader; + StackLineReader_Initialize(&reader, fd); + for (;;) + { + if (!HandleArmLine(StackLineReader_NextLine(&reader), info, + proc_cpu_info_data)) + { + break; + } + } + CpuFeatures_CloseFile(fd); + } +} + +static const ArmInfo kEmptyArmInfo; + +static const ProcCpuInfoData kEmptyProcCpuInfoData; + +ArmInfo GetArmInfo(void) +{ + // capabilities are fetched from both getauxval and /proc/cpuinfo so we can + // have some information if the executable is sandboxed (aka no access to + // /proc/cpuinfo). + ArmInfo info = kEmptyArmInfo; + ProcCpuInfoData proc_cpu_info_data = kEmptyProcCpuInfoData; + + FillProcCpuInfoData(&info, &proc_cpu_info_data); + const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities(); + for (size_t i = 0; i < ARM_LAST_; ++i) + { + if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) + { + kSetters[i](&info.features, true); + } + } + + FixErrors(&info, &proc_cpu_info_data); + + return info; +} + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +int GetArmFeaturesEnumValue(const ArmFeatures* features, + ArmFeaturesEnum value) +{ + if (value >= ARM_LAST_) return false; + return kGetters[value](features); +} + +const char* GetArmFeaturesEnumName(ArmFeaturesEnum value) +{ + if (value >= ARM_LAST_) return "unknown feature"; + return kCpuInfoFlags[value]; +} diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_mips.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_mips.c new file mode 100644 index 000000000..4d223d0e1 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_mips.c @@ -0,0 +1,92 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "cpuinfo_mips.h" +#include "internal/filesystem.h" +#include "internal/hwcaps.h" +#include "internal/stack_line_reader.h" +#include "internal/string_view.h" +#include + +// Generation of feature's getters/setters functions and kGetters, kSetters, +// kCpuInfoFlags and kHardwareCapabilities global tables. +#define DEFINE_TABLE_FEATURES \ + FEATURE(MIPS_MSA, msa, "msa", MIPS_HWCAP_MSA, 0) \ + FEATURE(MIPS_EVA, eva, "eva", 0, 0) \ + FEATURE(MIPS_R6, r6, "r6", MIPS_HWCAP_R6, 0) +#define DEFINE_TABLE_FEATURE_TYPE MipsFeatures +#include "define_tables.h" + +static bool HandleMipsLine(const LineResult result, + MipsFeatures* const features) +{ + StringView key, value; + // See tests for an example. + if (CpuFeatures_StringView_GetAttributeKeyValue(result.line, &key, &value)) + { + if (CpuFeatures_StringView_IsEquals(key, str("ASEs implemented"))) + { + for (size_t i = 0; i < MIPS_LAST_; ++i) + { + kSetters[i](features, + CpuFeatures_StringView_HasWord(value, kCpuInfoFlags[i])); + } + } + } + return !result.eof; +} + +static void FillProcCpuInfoData(MipsFeatures* const features) +{ + const int fd = CpuFeatures_OpenFile("/proc/cpuinfo"); + if (fd >= 0) + { + StackLineReader reader; + StackLineReader_Initialize(&reader, fd); + for (;;) + { + if (!HandleMipsLine(StackLineReader_NextLine(&reader), features)) + { + break; + } + } + CpuFeatures_CloseFile(fd); + } +} + +static const MipsInfo kEmptyMipsInfo; + +MipsInfo GetMipsInfo(void) +{ + // capabilities are fetched from both getauxval and /proc/cpuinfo so we can + // have some information if the executable is sandboxed (aka no access to + // /proc/cpuinfo). + MipsInfo info = kEmptyMipsInfo; + + FillProcCpuInfoData(&info.features); + const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities(); + for (size_t i = 0; i < MIPS_LAST_; ++i) + { + if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) + { + kSetters[i](&info.features, true); + } + } + return info; +} + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +int GetMipsFeaturesEnumValue(const MipsFeatures* features, + MipsFeaturesEnum value) +{ + if (value >= MIPS_LAST_) return false; + return kGetters[value](features); +} + +const char* GetMipsFeaturesEnumName(MipsFeaturesEnum value) +{ + if (value >= MIPS_LAST_) return "unknown feature"; + return kCpuInfoFlags[value]; +} diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_ppc.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_ppc.c new file mode 100644 index 000000000..efce92bdb --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_ppc.c @@ -0,0 +1,160 @@ +// SPDX-FileCopyrightText: 2018 IBM. +// SPDX-License-Identifier: Apache-2.0 + +#include "cpuinfo_ppc.h" +#include "internal/bit_utils.h" +#include "internal/filesystem.h" +#include "internal/stack_line_reader.h" +#include "internal/string_view.h" +#include +#include +#include + +// Generation of feature's getters/setters functions and kGetters, kSetters, +// kCpuInfoFlags and kHardwareCapabilities global tables. +#define DEFINE_TABLE_FEATURES \ + FEATURE(PPC_32, ppc32, "ppc32", PPC_FEATURE_32, 0) \ + FEATURE(PPC_64, ppc64, "ppc64", PPC_FEATURE_64, 0) \ + FEATURE(PPC_601_INSTR, ppc601, "ppc601", PPC_FEATURE_601_INSTR, 0) \ + FEATURE(PPC_HAS_ALTIVEC, altivec, "altivec", PPC_FEATURE_HAS_ALTIVEC, 0) \ + FEATURE(PPC_HAS_FPU, fpu, "fpu", PPC_FEATURE_HAS_FPU, 0) \ + FEATURE(PPC_HAS_MMU, mmu, "mmu", PPC_FEATURE_HAS_MMU, 0) \ + FEATURE(PPC_HAS_4xxMAC, mac_4xx, "4xxmac", PPC_FEATURE_HAS_4xxMAC, 0) \ + FEATURE(PPC_UNIFIED_CACHE, unifiedcache, "ucache", \ + PPC_FEATURE_UNIFIED_CACHE, 0) \ + FEATURE(PPC_HAS_SPE, spe, "spe", PPC_FEATURE_HAS_SPE, 0) \ + FEATURE(PPC_HAS_EFP_SINGLE, efpsingle, "efpsingle", \ + PPC_FEATURE_HAS_EFP_SINGLE, 0) \ + FEATURE(PPC_HAS_EFP_DOUBLE, efpdouble, "efpdouble", \ + PPC_FEATURE_HAS_EFP_DOUBLE, 0) \ + FEATURE(PPC_NO_TB, no_tb, "notb", PPC_FEATURE_NO_TB, 0) \ + FEATURE(PPC_POWER4, power4, "power4", PPC_FEATURE_POWER4, 0) \ + FEATURE(PPC_POWER5, power5, "power5", PPC_FEATURE_POWER5, 0) \ + FEATURE(PPC_POWER5_PLUS, power5plus, "power5+", PPC_FEATURE_POWER5_PLUS, 0) \ + FEATURE(PPC_CELL, cell, "cellbe", PPC_FEATURE_CELL, 0) \ + FEATURE(PPC_BOOKE, booke, "booke", PPC_FEATURE_BOOKE, 0) \ + FEATURE(PPC_SMT, smt, "smt", PPC_FEATURE_SMT, 0) \ + FEATURE(PPC_ICACHE_SNOOP, icachesnoop, "ic_snoop", PPC_FEATURE_ICACHE_SNOOP, \ + 0) \ + FEATURE(PPC_ARCH_2_05, arch205, "arch_2_05", PPC_FEATURE_ARCH_2_05, 0) \ + FEATURE(PPC_PA6T, pa6t, "pa6t", PPC_FEATURE_PA6T, 0) \ + FEATURE(PPC_HAS_DFP, dfp, "dfp", PPC_FEATURE_HAS_DFP, 0) \ + FEATURE(PPC_POWER6_EXT, power6ext, "power6x", PPC_FEATURE_POWER6_EXT, 0) \ + FEATURE(PPC_ARCH_2_06, arch206, "arch_2_06", PPC_FEATURE_ARCH_2_06, 0) \ + FEATURE(PPC_HAS_VSX, vsx, "vsx", PPC_FEATURE_HAS_VSX, 0) \ + FEATURE(PPC_PSERIES_PERFMON_COMPAT, pseries_perfmon_compat, "archpmu", \ + PPC_FEATURE_PSERIES_PERFMON_COMPAT, 0) \ + FEATURE(PPC_TRUE_LE, truele, "true_le", PPC_FEATURE_TRUE_LE, 0) \ + FEATURE(PPC_PPC_LE, ppcle, "ppcle", PPC_FEATURE_PPC_LE, 0) \ + FEATURE(PPC_ARCH_2_07, arch207, "arch_2_07", 0, PPC_FEATURE2_ARCH_2_07) \ + FEATURE(PPC_HTM, htm, "htm", 0, PPC_FEATURE2_HTM) \ + FEATURE(PPC_DSCR, dscr, "dscr", 0, PPC_FEATURE2_DSCR) \ + FEATURE(PPC_EBB, ebb, "ebb", 0, PPC_FEATURE2_EBB) \ + FEATURE(PPC_ISEL, isel, "isel", 0, PPC_FEATURE2_ISEL) \ + FEATURE(PPC_TAR, tar, "tar", 0, PPC_FEATURE2_TAR) \ + FEATURE(PPC_VEC_CRYPTO, vcrypto, "vcrypto", 0, PPC_FEATURE2_VEC_CRYPTO) \ + FEATURE(PPC_HTM_NOSC, htm_nosc, "htm-nosc", 0, PPC_FEATURE2_HTM_NOSC) \ + FEATURE(PPC_ARCH_3_00, arch300, "arch_3_00", 0, PPC_FEATURE2_ARCH_3_00) \ + FEATURE(PPC_HAS_IEEE128, ieee128, "ieee128", 0, PPC_FEATURE2_HAS_IEEE128) \ + FEATURE(PPC_DARN, darn, "darn", 0, PPC_FEATURE2_DARN) \ + FEATURE(PPC_SCV, scv, "scv", 0, PPC_FEATURE2_SCV) \ + FEATURE(PPC_HTM_NO_SUSPEND, htm_no_suspend, "htm-no-suspend", 0, \ + PPC_FEATURE2_HTM_NO_SUSPEND) +#define DEFINE_TABLE_FEATURE_TYPE PPCFeatures +#include "define_tables.h" + +static bool HandlePPCLine(const LineResult result, + PPCPlatformStrings* const strings) +{ + StringView line = result.line; + StringView key, value; + if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) + { + if (CpuFeatures_StringView_HasWord(key, "platform")) + { + CpuFeatures_StringView_CopyString(value, strings->platform, + sizeof(strings->platform)); + } + else if (CpuFeatures_StringView_IsEquals(key, str("model"))) + { + CpuFeatures_StringView_CopyString(value, strings->model, + sizeof(strings->platform)); + } + else if (CpuFeatures_StringView_IsEquals(key, str("machine"))) + { + CpuFeatures_StringView_CopyString(value, strings->machine, + sizeof(strings->platform)); + } + else if (CpuFeatures_StringView_IsEquals(key, str("cpu"))) + { + CpuFeatures_StringView_CopyString(value, strings->cpu, + sizeof(strings->platform)); + } + } + return !result.eof; +} + +static void FillProcCpuInfoData(PPCPlatformStrings* const strings) +{ + const int fd = CpuFeatures_OpenFile("/proc/cpuinfo"); + if (fd >= 0) + { + StackLineReader reader; + StackLineReader_Initialize(&reader, fd); + for (;;) + { + if (!HandlePPCLine(StackLineReader_NextLine(&reader), strings)) + { + break; + } + } + CpuFeatures_CloseFile(fd); + } +} + +static const PPCInfo kEmptyPPCInfo; + +PPCInfo GetPPCInfo(void) +{ + /* + * On Power feature flags aren't currently in cpuinfo so we only look at + * the auxilary vector. + */ + PPCInfo info = kEmptyPPCInfo; + const HardwareCapabilities hwcaps = CpuFeatures_GetHardwareCapabilities(); + for (size_t i = 0; i < PPC_LAST_; ++i) + { + if (CpuFeatures_IsHwCapsSet(kHardwareCapabilities[i], hwcaps)) + { + kSetters[i](&info.features, true); + } + } + return info; +} + +static const PPCPlatformStrings kEmptyPPCPlatformStrings; + +PPCPlatformStrings GetPPCPlatformStrings(void) +{ + PPCPlatformStrings strings = kEmptyPPCPlatformStrings; + + FillProcCpuInfoData(&strings); + strings.type = CpuFeatures_GetPlatformType(); + return strings; +} + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +int GetPPCFeaturesEnumValue(const PPCFeatures* features, + PPCFeaturesEnum value) +{ + if (value >= PPC_LAST_) return false; + return kGetters[value](features); +} + +const char* GetPPCFeaturesEnumName(PPCFeaturesEnum value) +{ + if (value >= PPC_LAST_) return "unknown feature"; + return kCpuInfoFlags[value]; +} diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_x86.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_x86.c new file mode 100644 index 000000000..e52172765 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/cpuinfo_x86.c @@ -0,0 +1,1684 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "cpuinfo_x86.h" +#include "internal/bit_utils.h" +#include "internal/cpuid_x86.h" +#include +#include + +#if !defined(CPU_FEATURES_ARCH_X86) +#error "Cannot compile cpuinfo_x86 on a non x86 platform." +#endif + +// Generation of feature's getters/setters functions and kGetters, kSetters, +// kCpuInfoFlags global tables. +#define DEFINE_TABLE_FEATURES \ + FEATURE(X86_FPU, fpu, "fpu", 0, 0) \ + FEATURE(X86_TSC, tsc, "tsc", 0, 0) \ + FEATURE(X86_CX8, cx8, "cx8", 0, 0) \ + FEATURE(X86_CLFSH, clfsh, "clfsh", 0, 0) \ + FEATURE(X86_MMX, mmx, "mmx", 0, 0) \ + FEATURE(X86_AES, aes, "aes", 0, 0) \ + FEATURE(X86_ERMS, erms, "erms", 0, 0) \ + FEATURE(X86_F16C, f16c, "f16c", 0, 0) \ + FEATURE(X86_FMA4, fma4, "fma4", 0, 0) \ + FEATURE(X86_FMA3, fma3, "fma3", 0, 0) \ + FEATURE(X86_VAES, vaes, "vaes", 0, 0) \ + FEATURE(X86_VPCLMULQDQ, vpclmulqdq, "vpclmulqdq", 0, 0) \ + FEATURE(X86_BMI1, bmi1, "bmi1", 0, 0) \ + FEATURE(X86_HLE, hle, "hle", 0, 0) \ + FEATURE(X86_BMI2, bmi2, "bmi2", 0, 0) \ + FEATURE(X86_RTM, rtm, "rtm", 0, 0) \ + FEATURE(X86_RDSEED, rdseed, "rdseed", 0, 0) \ + FEATURE(X86_CLFLUSHOPT, clflushopt, "clflushopt", 0, 0) \ + FEATURE(X86_CLWB, clwb, "clwb", 0, 0) \ + FEATURE(X86_SSE, sse, "sse", 0, 0) \ + FEATURE(X86_SSE2, sse2, "sse2", 0, 0) \ + FEATURE(X86_SSE3, sse3, "sse3", 0, 0) \ + FEATURE(X86_SSSE3, ssse3, "ssse3", 0, 0) \ + FEATURE(X86_SSE4_1, sse4_1, "sse4_1", 0, 0) \ + FEATURE(X86_SSE4_2, sse4_2, "sse4_2", 0, 0) \ + FEATURE(X86_SSE4A, sse4a, "sse4a", 0, 0) \ + FEATURE(X86_AVX, avx, "avx", 0, 0) \ + FEATURE(X86_AVX2, avx2, "avx2", 0, 0) \ + FEATURE(X86_AVX512F, avx512f, "avx512f", 0, 0) \ + FEATURE(X86_AVX512CD, avx512cd, "avx512cd", 0, 0) \ + FEATURE(X86_AVX512ER, avx512er, "avx512er", 0, 0) \ + FEATURE(X86_AVX512PF, avx512pf, "avx512pf", 0, 0) \ + FEATURE(X86_AVX512BW, avx512bw, "avx512bw", 0, 0) \ + FEATURE(X86_AVX512DQ, avx512dq, "avx512dq", 0, 0) \ + FEATURE(X86_AVX512VL, avx512vl, "avx512vl", 0, 0) \ + FEATURE(X86_AVX512IFMA, avx512ifma, "avx512ifma", 0, 0) \ + FEATURE(X86_AVX512VBMI, avx512vbmi, "avx512vbmi", 0, 0) \ + FEATURE(X86_AVX512VBMI2, avx512vbmi2, "avx512vbmi2", 0, 0) \ + FEATURE(X86_AVX512VNNI, avx512vnni, "avx512vnni", 0, 0) \ + FEATURE(X86_AVX512BITALG, avx512bitalg, "avx512bitalg", 0, 0) \ + FEATURE(X86_AVX512VPOPCNTDQ, avx512vpopcntdq, "avx512vpopcntdq", 0, 0) \ + FEATURE(X86_AVX512_4VNNIW, avx512_4vnniw, "avx512_4vnniw", 0, 0) \ + FEATURE(X86_AVX512_4VBMI2, avx512_4vbmi2, "avx512_4vbmi2", 0, 0) \ + FEATURE(X86_AVX512_SECOND_FMA, avx512_second_fma, "avx512_second_fma", 0, 0) \ + FEATURE(X86_AVX512_4FMAPS, avx512_4fmaps, "avx512_4fmaps", 0, 0) \ + FEATURE(X86_AVX512_BF16, avx512_bf16, "avx512_bf16", 0, 0) \ + FEATURE(X86_AVX512_VP2INTERSECT, avx512_vp2intersect, "avx512_vp2intersect", \ + 0, 0) \ + FEATURE(X86_AMX_BF16, amx_bf16, "amx_bf16", 0, 0) \ + FEATURE(X86_AMX_TILE, amx_tile, "amx_tile", 0, 0) \ + FEATURE(X86_AMX_INT8, amx_int8, "amx_int8", 0, 0) \ + FEATURE(X86_PCLMULQDQ, pclmulqdq, "pclmulqdq", 0, 0) \ + FEATURE(X86_SMX, smx, "smx", 0, 0) \ + FEATURE(X86_SGX, sgx, "sgx", 0, 0) \ + FEATURE(X86_CX16, cx16, "cx16", 0, 0) \ + FEATURE(X86_SHA, sha, "sha", 0, 0) \ + FEATURE(X86_POPCNT, popcnt, "popcnt", 0, 0) \ + FEATURE(X86_MOVBE, movbe, "movbe", 0, 0) \ + FEATURE(X86_RDRND, rdrnd, "rdrnd", 0, 0) \ + FEATURE(X86_DCA, dca, "dca", 0, 0) \ + FEATURE(X86_SS, ss, "ss", 0, 0) +#define DEFINE_TABLE_FEATURE_TYPE X86Features +#define DEFINE_TABLE_DONT_GENERATE_HWCAPS +#include "define_tables.h" + +// The following includes are necessary to provide SSE detections on pre-AVX +// microarchitectures. +#if defined(CPU_FEATURES_OS_WINDOWS) +#include // IsProcessorFeaturePresent +#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) +#include "internal/filesystem.h" // Needed to parse /proc/cpuinfo +#include "internal/stack_line_reader.h" // Needed to parse /proc/cpuinfo +#include "internal/string_view.h" // Needed to parse /proc/cpuinfo +#elif defined(CPU_FEATURES_OS_DARWIN) +#if !defined(HAVE_SYSCTLBYNAME) +#error "Darwin needs support for sysctlbyname" +#endif +#include +#else +#error "Unsupported OS" +#endif // CPU_FEATURES_OS + +//////////////////////////////////////////////////////////////////////////////// +// Definitions for CpuId and GetXCR0Eax. +//////////////////////////////////////////////////////////////////////////////// + +#if defined(CPU_FEATURES_MOCK_CPUID_X86) +// Implementation will be provided by test/cpuinfo_x86_test.cc. +#elif defined(CPU_FEATURES_COMPILER_CLANG) || defined(CPU_FEATURES_COMPILER_GCC) + +#include + +Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) +{ + Leaf leaf; + __cpuid_count(leaf_id, ecx, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx); + return leaf; +} + +uint32_t GetXCR0Eax(void) +{ + uint32_t eax, edx; + /* named form of xgetbv not supported on OSX, so must use byte form, see: + https://github.com/asmjit/asmjit/issues/78 + */ + __asm(".byte 0x0F, 0x01, 0xd0" + : "=a"(eax), "=d"(edx) + : "c"(0)); + return eax; +} + +#elif defined(CPU_FEATURES_COMPILER_MSC) + +#include +#include // For __cpuidex() + +Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) +{ + Leaf leaf; + int data[4]; + __cpuidex(data, leaf_id, ecx); + leaf.eax = data[0]; + leaf.ebx = data[1]; + leaf.ecx = data[2]; + leaf.edx = data[3]; + return leaf; +} + +uint32_t GetXCR0Eax(void) { return (uint32_t)_xgetbv(0); } + +#else +#error "Unsupported compiler, x86 cpuid requires either GCC, Clang or MSVC." +#endif + +static Leaf CpuId(uint32_t leaf_id) +{ + return GetCpuidLeaf(leaf_id, 0); +} + +static const Leaf kEmptyLeaf; + +static Leaf SafeCpuIdEx(uint32_t max_cpuid_leaf, uint32_t leaf_id, int ecx) +{ + if (leaf_id <= max_cpuid_leaf) + { + return GetCpuidLeaf(leaf_id, ecx); + } + else + { + return kEmptyLeaf; + } +} + +static Leaf SafeCpuId(uint32_t max_cpuid_leaf, uint32_t leaf_id) +{ + return SafeCpuIdEx(max_cpuid_leaf, leaf_id, 0); +} + +#define MASK_XMM 0x2 +#define MASK_YMM 0x4 +#define MASK_MASKREG 0x20 +#define MASK_ZMM0_15 0x40 +#define MASK_ZMM16_31 0x80 +#define MASK_XTILECFG 0x20000 +#define MASK_XTILEDATA 0x40000 + +static bool HasMask(uint32_t value, uint32_t mask) +{ + return (value & mask) == mask; +} + +// Checks that operating system saves and restores xmm registers during context +// switches. +static bool HasXmmOsXSave(uint32_t xcr0_eax) +{ + return HasMask(xcr0_eax, MASK_XMM); +} + +// Checks that operating system saves and restores ymm registers during context +// switches. +static bool HasYmmOsXSave(uint32_t xcr0_eax) +{ + return HasMask(xcr0_eax, MASK_XMM | MASK_YMM); +} + +// Checks that operating system saves and restores zmm registers during context +// switches. +static bool HasZmmOsXSave(uint32_t xcr0_eax) +{ + return HasMask(xcr0_eax, MASK_XMM | MASK_YMM | MASK_MASKREG | MASK_ZMM0_15 | + MASK_ZMM16_31); +} + +// Checks that operating system saves and restores AMX/TMUL state during context +// switches. +static bool HasTmmOsXSave(uint32_t xcr0_eax) +{ + return HasMask(xcr0_eax, MASK_XMM | MASK_YMM | MASK_MASKREG | MASK_ZMM0_15 | + MASK_ZMM16_31 | MASK_XTILECFG | MASK_XTILEDATA); +} + +static bool HasSecondFMA(uint32_t model) +{ + // Skylake server + if (model == 0x55) + { + char proc_name[49] = {0}; + FillX86BrandString(proc_name); + // detect Xeon + if (proc_name[9] == 'X') + { + // detect Silver or Bronze + if (proc_name[17] == 'S' || proc_name[17] == 'B') return false; + // detect Gold 5_20 and below, except for Gold 53__ + if (proc_name[17] == 'G' && proc_name[22] == '5') + return ((proc_name[23] == '3') || + (proc_name[24] == '2' && proc_name[25] == '2')); + // detect Xeon W 210x + if (proc_name[17] == 'W' && proc_name[21] == '0') return false; + // detect Xeon D 2xxx + if (proc_name[17] == 'D' && proc_name[19] == '2' && proc_name[20] == '1') + return false; + } + return true; + } + // Cannon Lake client + if (model == 0x66) return false; + // Ice Lake client + if (model == 0x7d || model == 0x7e) return false; + // This is the right default... + return true; +} + +static void SetVendor(const Leaf leaf, char* const vendor) +{ + *(uint32_t*)(vendor) = leaf.ebx; + *(uint32_t*)(vendor + 4) = leaf.edx; + *(uint32_t*)(vendor + 8) = leaf.ecx; + vendor[12] = '\0'; +} + +static int IsVendor(const Leaf leaf, const char* const name) +{ + const uint32_t ebx = *(const uint32_t*)(name); + const uint32_t edx = *(const uint32_t*)(name + 4); + const uint32_t ecx = *(const uint32_t*)(name + 8); + return leaf.ebx == ebx && leaf.ecx == ecx && leaf.edx == edx; +} + +static const CacheLevelInfo kEmptyCacheLevelInfo; + +static CacheLevelInfo GetCacheLevelInfo(const uint32_t reg) +{ + const int UNDEF = -1; + const int KiB = 1024; + const int MiB = 1024 * KiB; + switch (reg) + { + case 0x01: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 32, + .partitioning = 0}; + case 0x02: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * MiB, + .ways = 0xFF, + .line_size = UNDEF, + .tlb_entries = 2, + .partitioning = 0}; + case 0x03: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 64, + .partitioning = 0}; + case 0x04: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * MiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 8, + .partitioning = 0}; + case 0x05: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * MiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 32, + .partitioning = 0}; + case 0x06: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_INSTRUCTION, + .cache_size = 8 * KiB, + .ways = 4, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x08: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_INSTRUCTION, + .cache_size = 16 * KiB, + .ways = 4, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x09: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_INSTRUCTION, + .cache_size = 32 * KiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x0A: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 8 * KiB, + .ways = 2, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x0B: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * MiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 4, + .partitioning = 0}; + case 0x0C: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 16 * KiB, + .ways = 4, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x0D: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 16 * KiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x0E: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 24 * KiB, + .ways = 6, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x1D: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 128 * KiB, + .ways = 2, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x21: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 256 * KiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x22: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 512 * KiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 2}; + case 0x23: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 2}; + case 0x24: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * MiB, + .ways = 16, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x25: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 2 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 2}; + case 0x29: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 4 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 2}; + case 0x2C: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 32 * KiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x30: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_INSTRUCTION, + .cache_size = 32 * KiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x40: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = UNDEF, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x41: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 128 * KiB, + .ways = 4, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x42: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 256 * KiB, + .ways = 4, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x43: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 512 * KiB, + .ways = 4, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x44: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * MiB, + .ways = 4, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x45: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 2 * MiB, + .ways = 4, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x46: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 4 * MiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x47: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 8 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x48: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 3 * MiB, + .ways = 12, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x49: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 4 * MiB, + .ways = 16, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case (0x49 | (1 << 8)): + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 4 * MiB, + .ways = 16, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x4A: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 6 * MiB, + .ways = 12, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x4B: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 8 * MiB, + .ways = 16, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x4C: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 12 * MiB, + .ways = 12, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x4D: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 16 * MiB, + .ways = 16, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x4E: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 6 * MiB, + .ways = 24, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x4F: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = 32, + .partitioning = 0}; + case 0x50: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = 64, + .partitioning = 0}; + case 0x51: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = 128, + .partitioning = 0}; + case 0x52: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = 256, + .partitioning = 0}; + case 0x55: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 2 * MiB, + .ways = 0xFF, + .line_size = UNDEF, + .tlb_entries = 7, + .partitioning = 0}; + case 0x56: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * MiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 16, + .partitioning = 0}; + case 0x57: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 16, + .partitioning = 0}; + case 0x59: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 0xFF, + .line_size = UNDEF, + .tlb_entries = 16, + .partitioning = 0}; + case 0x5A: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 2 * MiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 32, + .partitioning = 0}; + case 0x5B: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = 64, + .partitioning = 0}; + case 0x5C: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = 128, + .partitioning = 0}; + case 0x5D: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = 256, + .partitioning = 0}; + case 0x60: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 16 * KiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x61: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 0xFF, + .line_size = UNDEF, + .tlb_entries = 48, + .partitioning = 0}; + case 0x63: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 2 * MiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 4, + .partitioning = 0}; + case 0x66: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 8 * KiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x67: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 16 * KiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x68: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 32 * KiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x70: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_INSTRUCTION, + .cache_size = 12 * KiB, + .ways = 8, + .line_size = UNDEF, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x71: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_INSTRUCTION, + .cache_size = 16 * KiB, + .ways = 8, + .line_size = UNDEF, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x72: + return (CacheLevelInfo){.level = 1, + .cache_type = CPU_FEATURE_CACHE_INSTRUCTION, + .cache_size = 32 * KiB, + .ways = 8, + .line_size = UNDEF, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x76: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 2 * MiB, + .ways = 0xFF, + .line_size = UNDEF, + .tlb_entries = 8, + .partitioning = 0}; + case 0x78: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * MiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x79: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 128 * KiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 2}; + case 0x7A: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 256 * KiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 2}; + case 0x7B: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 512 * KiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 2}; + case 0x7C: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 2}; + case 0x7D: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 2 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x7F: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 512 * KiB, + .ways = 2, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x80: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 512 * KiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x82: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 256 * KiB, + .ways = 8, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x83: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 512 * KiB, + .ways = 8, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x84: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * MiB, + .ways = 8, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x85: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 2 * MiB, + .ways = 8, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x86: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 512 * KiB, + .ways = 4, + .line_size = 32, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0x87: + return (CacheLevelInfo){.level = 2, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xA0: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_DTLB, + .cache_size = 4 * KiB, + .ways = 0xFF, + .line_size = UNDEF, + .tlb_entries = 32, + .partitioning = 0}; + case 0xB0: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 128, + .partitioning = 0}; + case 0xB1: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 2 * MiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 8, + .partitioning = 0}; + case 0xB2: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 64, + .partitioning = 0}; + case 0xB3: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 128, + .partitioning = 0}; + case 0xB4: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 256, + .partitioning = 0}; + case 0xB5: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 8, + .line_size = UNDEF, + .tlb_entries = 64, + .partitioning = 0}; + case 0xB6: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 8, + .line_size = UNDEF, + .tlb_entries = 128, + .partitioning = 0}; + case 0xBA: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 64, + .partitioning = 0}; + case 0xC0: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_TLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 8, + .partitioning = 0}; + case 0xC1: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_STLB, + .cache_size = 4 * KiB, + .ways = 8, + .line_size = UNDEF, + .tlb_entries = 1024, + .partitioning = 0}; + case 0xC2: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_DTLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 16, + .partitioning = 0}; + case 0xC3: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_STLB, + .cache_size = 4 * KiB, + .ways = 6, + .line_size = UNDEF, + .tlb_entries = 1536, + .partitioning = 0}; + case 0xCA: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_STLB, + .cache_size = 4 * KiB, + .ways = 4, + .line_size = UNDEF, + .tlb_entries = 512, + .partitioning = 0}; + case 0xD0: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 512 * KiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xD1: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * MiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xD2: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 2 * MiB, + .ways = 4, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xD6: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xD7: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 2 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xD8: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 4 * MiB, + .ways = 8, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xDC: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 1 * 1536 * KiB, + .ways = 12, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xDD: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 3 * MiB, + .ways = 12, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xDE: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 6 * MiB, + .ways = 12, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xE2: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 2 * MiB, + .ways = 16, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xE3: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 4 * MiB, + .ways = 16, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xE4: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 8 * MiB, + .ways = 16, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xEA: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 12 * MiB, + .ways = 24, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xEB: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 18 * MiB, + .ways = 24, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xEC: + return (CacheLevelInfo){.level = 3, + .cache_type = CPU_FEATURE_CACHE_DATA, + .cache_size = 24 * MiB, + .ways = 24, + .line_size = 64, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xF0: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_PREFETCH, + .cache_size = 64 * KiB, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xF1: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_PREFETCH, + .cache_size = 128 * KiB, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = UNDEF, + .partitioning = 0}; + case 0xFF: + return (CacheLevelInfo){.level = UNDEF, + .cache_type = CPU_FEATURE_CACHE_NULL, + .cache_size = UNDEF, + .ways = UNDEF, + .line_size = UNDEF, + .tlb_entries = UNDEF, + .partitioning = 0}; + default: + return kEmptyCacheLevelInfo; + } +} + +static void GetByteArrayFromRegister(uint32_t result[4], const uint32_t reg) +{ + for (int i = 0; i < 4; ++i) + { + result[i] = ExtractBitRange(reg, (i + 1) * 8, i * 8); + } +} + +static void ParseLeaf2(const int max_cpuid_leaf, CacheInfo* info) +{ + Leaf leaf = SafeCpuId(max_cpuid_leaf, 2); + uint32_t registers[] = {leaf.eax, leaf.ebx, leaf.ecx, leaf.edx}; + for (int i = 0; i < 4; ++i) + { + if (registers[i] & (1U << 31)) + { + continue; // register does not contains valid information + } + uint32_t bytes[4]; + GetByteArrayFromRegister(bytes, registers[i]); + for (int j = 0; j < 4; ++j) + { + if (bytes[j] == 0xFF) + break; // leaf 4 should be used to fetch cache information + info->levels[info->size] = GetCacheLevelInfo(bytes[j]); + } + info->size++; + } +} + +static void ParseLeaf4(const int max_cpuid_leaf, CacheInfo* info) +{ + info->size = 0; + for (int cache_id = 0; cache_id < CPU_FEATURES_MAX_CACHE_LEVEL; cache_id++) + { + const Leaf leaf = SafeCpuIdEx(max_cpuid_leaf, 4, cache_id); + CacheType cache_type = ExtractBitRange(leaf.eax, 4, 0); + if (cache_type == CPU_FEATURE_CACHE_NULL) + { + info->levels[cache_id] = kEmptyCacheLevelInfo; + continue; + } + int level = ExtractBitRange(leaf.eax, 7, 5); + int line_size = ExtractBitRange(leaf.ebx, 11, 0) + 1; + int partitioning = ExtractBitRange(leaf.ebx, 21, 12) + 1; + int ways = ExtractBitRange(leaf.ebx, 31, 22) + 1; + int tlb_entries = leaf.ecx + 1; + int cache_size = (ways * partitioning * line_size * (tlb_entries)); + info->levels[cache_id] = (CacheLevelInfo){.level = level, + .cache_type = cache_type, + .cache_size = cache_size, + .ways = ways, + .line_size = line_size, + .tlb_entries = tlb_entries, + .partitioning = partitioning}; + info->size++; + } +} + +// Internal structure to hold the OS support for vector operations. +// Avoid to recompute them since each call to cpuid is ~100 cycles. +typedef struct +{ + bool have_sse_via_os; + bool have_sse_via_cpuid; + bool have_avx; + bool have_avx512; + bool have_amx; +} OsSupport; + +static const OsSupport kEmptyOsSupport; + +static OsSupport CheckOsSupport(const uint32_t max_cpuid_leaf) +{ + const Leaf leaf_1 = SafeCpuId(max_cpuid_leaf, 1); + const bool have_xsave = IsBitSet(leaf_1.ecx, 26); + const bool have_osxsave = IsBitSet(leaf_1.ecx, 27); + const bool have_xcr0 = have_xsave && have_osxsave; + + OsSupport os_support = kEmptyOsSupport; + + if (have_xcr0) + { + // AVX capable cpu will expose XCR0. + const uint32_t xcr0_eax = GetXCR0Eax(); + os_support.have_sse_via_cpuid = HasXmmOsXSave(xcr0_eax); + os_support.have_avx = HasYmmOsXSave(xcr0_eax); + os_support.have_avx512 = HasZmmOsXSave(xcr0_eax); + os_support.have_amx = HasTmmOsXSave(xcr0_eax); + } + else + { + // Atom based or older cpus need to ask the OS for sse support. + os_support.have_sse_via_os = true; + } + + return os_support; +} + +#if defined(CPU_FEATURES_OS_WINDOWS) +#if defined(CPU_FEATURES_MOCK_CPUID_X86) +extern bool GetWindowsIsProcessorFeaturePresent(DWORD); +#else // CPU_FEATURES_MOCK_CPUID_X86 +static bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) +{ + return IsProcessorFeaturePresent(ProcessorFeature); +} +#endif +#endif // CPU_FEATURES_OS_WINDOWS + +#if defined(CPU_FEATURES_OS_DARWIN) +#if defined(CPU_FEATURES_MOCK_CPUID_X86) +extern bool GetDarwinSysCtlByName(const char*); +#else // CPU_FEATURES_MOCK_CPUID_X86 +static bool GetDarwinSysCtlByName(const char* name) +{ + int enabled; + size_t enabled_len = sizeof(enabled); + const int failure = sysctlbyname(name, &enabled, &enabled_len, NULL, 0); + return failure ? false : enabled; +} +#endif +#endif // CPU_FEATURES_OS_DARWIN + +static void DetectSseViaOs(X86Features* features) +{ +#if defined(CPU_FEATURES_OS_WINDOWS) + // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-isprocessorfeaturepresent + features->sse = + GetWindowsIsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE); + features->sse2 = + GetWindowsIsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE); + features->sse3 = + GetWindowsIsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE); +#elif defined(CPU_FEATURES_OS_DARWIN) + // Handling Darwin platform through sysctlbyname. + features->sse = GetDarwinSysCtlByName("hw.optional.sse"); + features->sse2 = GetDarwinSysCtlByName("hw.optional.sse2"); + features->sse3 = GetDarwinSysCtlByName("hw.optional.sse3"); + features->ssse3 = GetDarwinSysCtlByName("hw.optional.supplementalsse3"); + features->sse4_1 = GetDarwinSysCtlByName("hw.optional.sse4_1"); + features->sse4_2 = GetDarwinSysCtlByName("hw.optional.sse4_2"); +#elif defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) + // Handling Linux platform through /proc/cpuinfo. + const int fd = CpuFeatures_OpenFile("/proc/cpuinfo"); + if (fd >= 0) + { + StackLineReader reader; + StackLineReader_Initialize(&reader, fd); + for (;;) + { + const LineResult result = StackLineReader_NextLine(&reader); + const StringView line = result.line; + StringView key, value; + if (CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)) + { + if (CpuFeatures_StringView_IsEquals(key, str("flags"))) + { + features->sse = CpuFeatures_StringView_HasWord(value, "sse"); + features->sse2 = CpuFeatures_StringView_HasWord(value, "sse2"); + features->sse3 = CpuFeatures_StringView_HasWord(value, "sse3"); + features->ssse3 = CpuFeatures_StringView_HasWord(value, "ssse3"); + features->sse4_1 = CpuFeatures_StringView_HasWord(value, "sse4_1"); + features->sse4_2 = CpuFeatures_StringView_HasWord(value, "sse4_2"); + break; + } + } + if (result.eof) break; + } + CpuFeatures_CloseFile(fd); + } +#else +#error "Unsupported fallback detection of SSE OS support." +#endif +} + +// Reference https://en.wikipedia.org/wiki/CPUID. +static void ParseCpuId(const uint32_t max_cpuid_leaf, + const OsSupport os_support, X86Info* info) +{ + const Leaf leaf_1 = SafeCpuId(max_cpuid_leaf, 1); + const Leaf leaf_7 = SafeCpuId(max_cpuid_leaf, 7); + const Leaf leaf_7_1 = SafeCpuIdEx(max_cpuid_leaf, 7, 1); + + const uint32_t family = ExtractBitRange(leaf_1.eax, 11, 8); + const uint32_t extended_family = ExtractBitRange(leaf_1.eax, 27, 20); + const uint32_t model = ExtractBitRange(leaf_1.eax, 7, 4); + const uint32_t extended_model = ExtractBitRange(leaf_1.eax, 19, 16); + + X86Features* const features = &info->features; + + info->family = extended_family + family; + info->model = (extended_model << 4) + model; + info->stepping = ExtractBitRange(leaf_1.eax, 3, 0); + + features->fpu = IsBitSet(leaf_1.edx, 0); + features->tsc = IsBitSet(leaf_1.edx, 4); + features->cx8 = IsBitSet(leaf_1.edx, 8); + features->clfsh = IsBitSet(leaf_1.edx, 19); + features->mmx = IsBitSet(leaf_1.edx, 23); + features->ss = IsBitSet(leaf_1.edx, 27); + features->pclmulqdq = IsBitSet(leaf_1.ecx, 1); + features->smx = IsBitSet(leaf_1.ecx, 6); + features->cx16 = IsBitSet(leaf_1.ecx, 13); + features->dca = IsBitSet(leaf_1.ecx, 18); + features->movbe = IsBitSet(leaf_1.ecx, 22); + features->popcnt = IsBitSet(leaf_1.ecx, 23); + features->aes = IsBitSet(leaf_1.ecx, 25); + features->f16c = IsBitSet(leaf_1.ecx, 29); + features->rdrnd = IsBitSet(leaf_1.ecx, 30); + features->sgx = IsBitSet(leaf_7.ebx, 2); + features->bmi1 = IsBitSet(leaf_7.ebx, 3); + features->hle = IsBitSet(leaf_7.ebx, 4); + features->bmi2 = IsBitSet(leaf_7.ebx, 8); + features->erms = IsBitSet(leaf_7.ebx, 9); + features->rtm = IsBitSet(leaf_7.ebx, 11); + features->rdseed = IsBitSet(leaf_7.ebx, 18); + features->clflushopt = IsBitSet(leaf_7.ebx, 23); + features->clwb = IsBitSet(leaf_7.ebx, 24); + features->sha = IsBitSet(leaf_7.ebx, 29); + features->vaes = IsBitSet(leaf_7.ecx, 9); + features->vpclmulqdq = IsBitSet(leaf_7.ecx, 10); + + if (os_support.have_sse_via_os) + { + DetectSseViaOs(features); + } + else if (os_support.have_sse_via_cpuid) + { + features->sse = IsBitSet(leaf_1.edx, 25); + features->sse2 = IsBitSet(leaf_1.edx, 26); + features->sse3 = IsBitSet(leaf_1.ecx, 0); + features->ssse3 = IsBitSet(leaf_1.ecx, 9); + features->sse4_1 = IsBitSet(leaf_1.ecx, 19); + features->sse4_2 = IsBitSet(leaf_1.ecx, 20); + } + + if (os_support.have_avx) + { + features->fma3 = IsBitSet(leaf_1.ecx, 12); + features->avx = IsBitSet(leaf_1.ecx, 28); + features->avx2 = IsBitSet(leaf_7.ebx, 5); + } + + if (os_support.have_avx512) + { + features->avx512f = IsBitSet(leaf_7.ebx, 16); + features->avx512cd = IsBitSet(leaf_7.ebx, 28); + features->avx512er = IsBitSet(leaf_7.ebx, 27); + features->avx512pf = IsBitSet(leaf_7.ebx, 26); + features->avx512bw = IsBitSet(leaf_7.ebx, 30); + features->avx512dq = IsBitSet(leaf_7.ebx, 17); + features->avx512vl = IsBitSet(leaf_7.ebx, 31); + features->avx512ifma = IsBitSet(leaf_7.ebx, 21); + features->avx512vbmi = IsBitSet(leaf_7.ecx, 1); + features->avx512vbmi2 = IsBitSet(leaf_7.ecx, 6); + features->avx512vnni = IsBitSet(leaf_7.ecx, 11); + features->avx512bitalg = IsBitSet(leaf_7.ecx, 12); + features->avx512vpopcntdq = IsBitSet(leaf_7.ecx, 14); + features->avx512_4vnniw = IsBitSet(leaf_7.edx, 2); + features->avx512_4vbmi2 = IsBitSet(leaf_7.edx, 3); + features->avx512_second_fma = HasSecondFMA(info->model); + features->avx512_4fmaps = IsBitSet(leaf_7.edx, 3); + features->avx512_bf16 = IsBitSet(leaf_7_1.eax, 5); + features->avx512_vp2intersect = IsBitSet(leaf_7.edx, 8); + } + + if (os_support.have_amx) + { + features->amx_bf16 = IsBitSet(leaf_7.edx, 22); + features->amx_tile = IsBitSet(leaf_7.edx, 24); + features->amx_int8 = IsBitSet(leaf_7.edx, 25); + } +} + +// Reference +// https://en.wikipedia.org/wiki/CPUID#EAX=80000000h:_Get_Highest_Extended_Function_Implemented. +static void ParseExtraAMDCpuId(X86Info* info, OsSupport os_support) +{ + const Leaf leaf_80000000 = CpuId(0x80000000); + const uint32_t max_extended_cpuid_leaf = leaf_80000000.eax; + const Leaf leaf_80000001 = SafeCpuId(max_extended_cpuid_leaf, 0x80000001); + + X86Features* const features = &info->features; + + if (os_support.have_sse_via_cpuid) + { + features->sse4a = IsBitSet(leaf_80000001.ecx, 6); + } + + if (os_support.have_avx) + { + features->fma4 = IsBitSet(leaf_80000001.ecx, 16); + } +} + +static const X86Info kEmptyX86Info; +static const CacheInfo kEmptyCacheInfo; + +X86Info GetX86Info(void) +{ + X86Info info = kEmptyX86Info; + const Leaf leaf_0 = CpuId(0); + const bool is_intel = IsVendor(leaf_0, "GenuineIntel"); + const bool is_amd = IsVendor(leaf_0, "AuthenticAMD"); + SetVendor(leaf_0, info.vendor); + if (is_intel || is_amd) + { + const uint32_t max_cpuid_leaf = leaf_0.eax; + const OsSupport os_support = CheckOsSupport(max_cpuid_leaf); + ParseCpuId(max_cpuid_leaf, os_support, &info); + if (is_amd) + { + ParseExtraAMDCpuId(&info, os_support); + } + } + return info; +} + +CacheInfo GetX86CacheInfo(void) +{ + CacheInfo info = kEmptyCacheInfo; + const Leaf leaf_0 = CpuId(0); + const uint32_t max_cpuid_leaf = leaf_0.eax; + if (IsVendor(leaf_0, "GenuineIntel")) + { + ParseLeaf2(max_cpuid_leaf, &info); + ParseLeaf4(max_cpuid_leaf, &info); + } + return info; +} + +#define CPUID(FAMILY, MODEL) ((((FAMILY)&0xFF) << 8) | ((MODEL)&0xFF)) + +X86Microarchitecture GetX86Microarchitecture(const X86Info* info) +{ + if (memcmp(info->vendor, "GenuineIntel", sizeof(info->vendor)) == 0) + { + switch (CPUID(info->family, info->model)) + { + case CPUID(0x06, 0x35): + case CPUID(0x06, 0x36): + // https://en.wikipedia.org/wiki/Bonnell_(microarchitecture) + return INTEL_ATOM_BNL; + case CPUID(0x06, 0x37): + case CPUID(0x06, 0x4C): + // https://en.wikipedia.org/wiki/Silvermont + return INTEL_ATOM_SMT; + case CPUID(0x06, 0x5C): + // https://en.wikipedia.org/wiki/Goldmont + return INTEL_ATOM_GMT; + case CPUID(0x06, 0x0F): + case CPUID(0x06, 0x16): + // https://en.wikipedia.org/wiki/Intel_Core_(microarchitecture) + return INTEL_CORE; + case CPUID(0x06, 0x17): + case CPUID(0x06, 0x1D): + // https://en.wikipedia.org/wiki/Penryn_(microarchitecture) + return INTEL_PNR; + case CPUID(0x06, 0x1A): + case CPUID(0x06, 0x1E): + case CPUID(0x06, 0x1F): + case CPUID(0x06, 0x2E): + // https://en.wikipedia.org/wiki/Nehalem_(microarchitecture) + return INTEL_NHM; + case CPUID(0x06, 0x25): + case CPUID(0x06, 0x2C): + case CPUID(0x06, 0x2F): + // https://en.wikipedia.org/wiki/Westmere_(microarchitecture) + return INTEL_WSM; + case CPUID(0x06, 0x2A): + case CPUID(0x06, 0x2D): + // https://en.wikipedia.org/wiki/Sandy_Bridge#Models_and_steppings + return INTEL_SNB; + case CPUID(0x06, 0x3A): + case CPUID(0x06, 0x3E): + // https://en.wikipedia.org/wiki/Ivy_Bridge_(microarchitecture)#Models_and_steppings + return INTEL_IVB; + case CPUID(0x06, 0x3C): + case CPUID(0x06, 0x3F): + case CPUID(0x06, 0x45): + case CPUID(0x06, 0x46): + // https://en.wikipedia.org/wiki/Haswell_(microarchitecture) + return INTEL_HSW; + case CPUID(0x06, 0x3D): + case CPUID(0x06, 0x47): + case CPUID(0x06, 0x4F): + case CPUID(0x06, 0x56): + // https://en.wikipedia.org/wiki/Broadwell_(microarchitecture) + return INTEL_BDW; + case CPUID(0x06, 0x4E): + case CPUID(0x06, 0x55): + case CPUID(0x06, 0x5E): + // https://en.wikipedia.org/wiki/Skylake_(microarchitecture) + return INTEL_SKL; + case CPUID(0x06, 0x66): + // https://en.wikipedia.org/wiki/Cannon_Lake_(microarchitecture) + return INTEL_CNL; + case CPUID(0x06, 0x7D): // client + case CPUID(0x06, 0x7E): // client + case CPUID(0x06, 0x9D): // NNP-I + case CPUID(0x06, 0x6A): // server + case CPUID(0x06, 0x6C): // server + // https://en.wikipedia.org/wiki/Ice_Lake_(microprocessor) + return INTEL_ICL; + case CPUID(0x06, 0x8C): + case CPUID(0x06, 0x8D): + // https://en.wikipedia.org/wiki/Tiger_Lake_(microarchitecture) + return INTEL_TGL; + case CPUID(0x06, 0x8F): + // https://en.wikipedia.org/wiki/Sapphire_Rapids + return INTEL_SPR; + case CPUID(0x06, 0x8E): + switch (info->stepping) + { + case 9: + return INTEL_KBL; // https://en.wikipedia.org/wiki/Kaby_Lake + case 10: + return INTEL_CFL; // https://en.wikipedia.org/wiki/Coffee_Lake + case 11: + return INTEL_WHL; // https://en.wikipedia.org/wiki/Whiskey_Lake_(microarchitecture) + default: + return X86_UNKNOWN; + } + case CPUID(0x06, 0x9E): + if (info->stepping > 9) + { + // https://en.wikipedia.org/wiki/Coffee_Lake + return INTEL_CFL; + } + else + { + // https://en.wikipedia.org/wiki/Kaby_Lake + return INTEL_KBL; + } + default: + return X86_UNKNOWN; + } + } + if (memcmp(info->vendor, "AuthenticAMD", sizeof(info->vendor)) == 0) + { + switch (info->family) + { + // https://en.wikipedia.org/wiki/List_of_AMD_CPU_microarchitectures + case 0x0F: + return AMD_HAMMER; + case 0x10: + return AMD_K10; + case 0x14: + return AMD_BOBCAT; + case 0x15: + return AMD_BULLDOZER; + case 0x16: + return AMD_JAGUAR; + case 0x17: + return AMD_ZEN; + default: + return X86_UNKNOWN; + } + } + return X86_UNKNOWN; +} + +static void SetString(const uint32_t max_cpuid_ext_leaf, const uint32_t leaf_id, + char* buffer) +{ + const Leaf leaf = SafeCpuId(max_cpuid_ext_leaf, leaf_id); + // We allow calling memcpy from SetString which is only called when requesting + // X86BrandString. + memcpy(buffer, &leaf, sizeof(Leaf)); +} + +void FillX86BrandString(char brand_string[49]) +{ + const Leaf leaf_ext_0 = CpuId(0x80000000); + const uint32_t max_cpuid_leaf_ext = leaf_ext_0.eax; + SetString(max_cpuid_leaf_ext, 0x80000002, brand_string); + SetString(max_cpuid_leaf_ext, 0x80000003, brand_string + 16); + SetString(max_cpuid_leaf_ext, 0x80000004, brand_string + 32); + brand_string[48] = '\0'; +} + +//////////////////////////////////////////////////////////////////////////////// +// Introspection functions + +int GetX86FeaturesEnumValue(const X86Features* features, + X86FeaturesEnum value) +{ + if (value >= X86_LAST_) return false; + return kGetters[value](features); +} + +const char* GetX86FeaturesEnumName(X86FeaturesEnum value) +{ + if (value >= X86_LAST_) return "unknown_feature"; + return kCpuInfoFlags[value]; +} + +const char* GetX86MicroarchitectureName(X86Microarchitecture uarch) +{ + switch (uarch) + { + case X86_UNKNOWN: + return "X86_UNKNOWN"; + case INTEL_CORE: + return "INTEL_CORE"; + case INTEL_PNR: + return "INTEL_PNR"; + case INTEL_NHM: + return "INTEL_NHM"; + case INTEL_ATOM_BNL: + return "INTEL_ATOM_BNL"; + case INTEL_WSM: + return "INTEL_WSM"; + case INTEL_SNB: + return "INTEL_SNB"; + case INTEL_IVB: + return "INTEL_IVB"; + case INTEL_ATOM_SMT: + return "INTEL_ATOM_SMT"; + case INTEL_HSW: + return "INTEL_HSW"; + case INTEL_BDW: + return "INTEL_BDW"; + case INTEL_SKL: + return "INTEL_SKL"; + case INTEL_ATOM_GMT: + return "INTEL_ATOM_GMT"; + case INTEL_KBL: + return "INTEL_KBL"; + case INTEL_CFL: + return "INTEL_CFL"; + case INTEL_WHL: + return "INTEL_WHL"; + case INTEL_CNL: + return "INTEL_CNL"; + case INTEL_ICL: + return "INTEL_ICL"; + case INTEL_TGL: + return "INTEL_TGL"; + case INTEL_SPR: + return "INTEL_SPR"; + case AMD_HAMMER: + return "AMD_HAMMER"; + case AMD_K10: + return "AMD_K10"; + case AMD_BOBCAT: + return "AMD_BOBCAT"; + case AMD_BULLDOZER: + return "AMD_BULLDOZER"; + case AMD_JAGUAR: + return "AMD_JAGUAR"; + case AMD_ZEN: + return "AMD_ZEN"; + } + return "unknown microarchitecture"; +} diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/define_tables.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/define_tables.h new file mode 100644 index 000000000..b0a069d34 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/define_tables.h @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +// The following preprocessor constants must be defined before including this +// file: +// - DEFINE_TABLE_FEATURE_TYPE, the underlying type (e.g. X86Features) +// - DEFINE_TABLE_FEATURES, the list of FEATURE macros to be inserted. + +// This file is to be included once per `cpuinfo_XXX.c` in order to construct +// feature getters and setters functions as well as several enum indexed tables +// from the db file. +// - `kGetters` a table of getters function pointers from feature enum to +// retrieve a feature, +// - `kSetters` a table of setters function pointers from feature enum to set a +// feature, +// - `kCpuInfoFlags` a table of strings from feature enum to /proc/cpuinfo +// flags, +// - `kHardwareCapabilities` a table of HardwareCapabilities structs indexed by +// their feature enum. + +#ifndef SRC_DEFINE_TABLES_H_ +#define SRC_DEFINE_TABLES_H_ + +#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = CPUINFO_FLAG, +static const char* kCpuInfoFlags[] = {DEFINE_TABLE_FEATURES}; +#undef FEATURE + +#ifndef DEFINE_TABLE_DONT_GENERATE_HWCAPS +#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) \ + [ENUM] = (HardwareCapabilities){HWCAP, HWCAP2}, +static const HardwareCapabilities kHardwareCapabilities[] = { + DEFINE_TABLE_FEATURES}; +#undef FEATURE +#endif // DEFINE_TABLE_DONT_GENERATE_HWCAPS + +#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) \ + static void set_##ENUM(DEFINE_TABLE_FEATURE_TYPE* features, bool value) \ + { \ + features->NAME = value; \ + } \ + static int get_##ENUM(const DEFINE_TABLE_FEATURE_TYPE* features) \ + { \ + return features->NAME; \ + } +DEFINE_TABLE_FEATURES +#undef FEATURE + +#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = set_##ENUM, +static void (*const kSetters[])(DEFINE_TABLE_FEATURE_TYPE*, + bool) = {DEFINE_TABLE_FEATURES}; +#undef FEATURE + +#define FEATURE(ENUM, NAME, CPUINFO_FLAG, HWCAP, HWCAP2) [ENUM] = get_##ENUM, +static int (*const kGetters[])(const DEFINE_TABLE_FEATURE_TYPE*) = { + DEFINE_TABLE_FEATURES}; +#undef FEATURE + +#endif // SRC_DEFINE_TABLES_H_ diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/filesystem.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/filesystem.c new file mode 100644 index 000000000..602e98e26 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/filesystem.c @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "internal/filesystem.h" +#include +#include +#include +#include +#include + +#if defined(CPU_FEATURES_MOCK_FILESYSTEM) +// Implementation will be provided by test/filesystem_for_testing.cc. +#elif defined(_MSC_VER) +#include +int CpuFeatures_OpenFile(const char* filename) +{ + int fd = -1; + _sopen_s(&fd, filename, _O_RDONLY, _SH_DENYWR, _S_IREAD); + return fd; +} + +void CpuFeatures_CloseFile(int file_descriptor) { _close(file_descriptor); } + +int CpuFeatures_ReadFile(int file_descriptor, void* buffer, + size_t buffer_size) +{ + return _read(file_descriptor, buffer, (unsigned int)buffer_size); +} + +#else +#include + +int CpuFeatures_OpenFile(const char* filename) +{ + int result; + do + { + result = open(filename, O_RDONLY); + } + while (result == -1L && errno == EINTR); + return result; +} + +void CpuFeatures_CloseFile(int file_descriptor) { close(file_descriptor); } + +int CpuFeatures_ReadFile(int file_descriptor, void* buffer, + size_t buffer_size) +{ + int result; + do + { + result = read(file_descriptor, buffer, buffer_size); + } + while (result == -1L && errno == EINTR); + return result; +} + +#endif diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/hwcaps.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/hwcaps.c new file mode 100644 index 000000000..35b499487 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/hwcaps.c @@ -0,0 +1,190 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "internal/hwcaps.h" +#include "cpu_features_macros.h" +#include "internal/filesystem.h" +#include "internal/string_view.h" +#include +#include + +static bool IsSet(const uint32_t mask, const uint32_t value) +{ + if (mask == 0) return false; + return (value & mask) == mask; +} + +bool CpuFeatures_IsHwCapsSet(const HardwareCapabilities hwcaps_mask, + const HardwareCapabilities hwcaps) +{ + return IsSet(hwcaps_mask.hwcaps, hwcaps.hwcaps) || + IsSet(hwcaps_mask.hwcaps2, hwcaps.hwcaps2); +} + +#ifdef CPU_FEATURES_TEST +// In test mode, hwcaps_for_testing will define the following functions. +HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void); +PlatformType CpuFeatures_GetPlatformType(void); +#else + +// Debug facilities +#if defined(NDEBUG) +#define D(...) +#else +#include +#define D(...) \ + do \ + { \ + printf(__VA_ARGS__); \ + fflush(stdout); \ + } \ + while (0) +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Implementation of GetElfHwcapFromGetauxval +//////////////////////////////////////////////////////////////////////////////// + +#define AT_HWCAP 16 +#define AT_HWCAP2 26 +#define AT_PLATFORM 15 +#define AT_BASE_PLATFORM 24 + +#if defined(HAVE_STRONG_GETAUXVAL) +#include +static unsigned long GetElfHwcapFromGetauxval(uint32_t hwcap_type) +{ + return getauxval(hwcap_type); +} +#elif defined(HAVE_DLFCN_H) +// On Android we probe the system's C library for a 'getauxval' function and +// call it if it exits, or return 0 for failure. This function is available +// since API level 20. +// +// This code does *NOT* check for '__ANDROID_API__ >= 20' to support the edge +// case where some NDK developers use headers for a platform that is newer than +// the one really targetted by their application. This is typically done to use +// newer native APIs only when running on more recent Android versions, and +// requires careful symbol management. +// +// Note that getauxval() can't really be re-implemented here, because its +// implementation does not parse /proc/self/auxv. Instead it depends on values +// that are passed by the kernel at process-init time to the C runtime +// initialization layer. + +#include + +typedef unsigned long getauxval_func_t(unsigned long); + +static uint32_t GetElfHwcapFromGetauxval(uint32_t hwcap_type) +{ + uint32_t ret = 0; + void *libc_handle = NULL; + getauxval_func_t *func = NULL; + + dlerror(); // Cleaning error state before calling dlopen. + libc_handle = dlopen("libc.so", RTLD_NOW); + if (!libc_handle) + { + D("Could not dlopen() C library: %s\n", dlerror()); + return 0; + } + func = (getauxval_func_t *)dlsym(libc_handle, "getauxval"); + if (!func) + { + D("Could not find getauxval() in C library\n"); + } + else + { + // Note: getauxval() returns 0 on failure. Doesn't touch errno. + ret = (uint32_t)(*func)(hwcap_type); + } + dlclose(libc_handle); + return ret; +} +#else +#error "This platform does not provide hardware capabilities." +#endif + +// Implementation of GetHardwareCapabilities for OS that provide +// GetElfHwcapFromGetauxval(). + +// Fallback when getauxval is not available, retrieves hwcaps from +// "/proc/self/auxv". +static uint32_t GetElfHwcapFromProcSelfAuxv(uint32_t hwcap_type) +{ + struct + { + uint32_t tag; + uint32_t value; + } entry; + uint32_t result = 0; + const char filepath[] = "/proc/self/auxv"; + const int fd = CpuFeatures_OpenFile(filepath); + if (fd < 0) + { + D("Could not open %s\n", filepath); + return 0; + } + for (;;) + { + const int ret = CpuFeatures_ReadFile(fd, (char *)&entry, sizeof entry); + if (ret < 0) + { + D("Error while reading %s\n", filepath); + break; + } + // Detect end of list. + if (ret == 0 || (entry.tag == 0 && entry.value == 0)) + { + break; + } + if (entry.tag == hwcap_type) + { + result = entry.value; + break; + } + } + CpuFeatures_CloseFile(fd); + return result; +} + +// Retrieves hardware capabilities by first trying to call getauxval, if not +// available falls back to reading "/proc/self/auxv". +static unsigned long GetHardwareCapabilitiesFor(uint32_t type) +{ + unsigned long hwcaps = GetElfHwcapFromGetauxval(type); + if (!hwcaps) + { + D("Parsing /proc/self/auxv to extract ELF hwcaps!\n"); + hwcaps = GetElfHwcapFromProcSelfAuxv(type); + } + return hwcaps; +} + +HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) +{ + HardwareCapabilities capabilities; + capabilities.hwcaps = GetHardwareCapabilitiesFor(AT_HWCAP); + capabilities.hwcaps2 = GetHardwareCapabilitiesFor(AT_HWCAP2); + return capabilities; +} + +PlatformType kEmptyPlatformType; + +PlatformType CpuFeatures_GetPlatformType(void) +{ + PlatformType type = kEmptyPlatformType; + char *platform = (char *)GetHardwareCapabilitiesFor(AT_PLATFORM); + char *base_platform = (char *)GetHardwareCapabilitiesFor(AT_BASE_PLATFORM); + + if (platform != NULL) + CpuFeatures_StringView_CopyString(str(platform), type.platform, + sizeof(type.platform)); + if (base_platform != NULL) + CpuFeatures_StringView_CopyString(str(base_platform), type.base_platform, + sizeof(type.base_platform)); + return type; +} + +#endif // CPU_FEATURES_TEST diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/stack_line_reader.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/stack_line_reader.c new file mode 100644 index 000000000..f2e7ecb66 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/stack_line_reader.c @@ -0,0 +1,140 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "internal/stack_line_reader.h" +#include "internal/filesystem.h" +#include +#include +#include + +void StackLineReader_Initialize(StackLineReader* reader, int fd) +{ + reader->view.ptr = reader->buffer; + reader->view.size = 0; + reader->skip_mode = false; + reader->fd = fd; +} + +// Replaces the content of buffer with bytes from the file. +static int LoadFullBuffer(StackLineReader* reader) +{ + const int read = CpuFeatures_ReadFile(reader->fd, reader->buffer, + STACK_LINE_READER_BUFFER_SIZE); + assert(read >= 0); + reader->view.ptr = reader->buffer; + reader->view.size = read; + return read; +} + +// Appends with bytes from the file to buffer, filling the remaining space. +static int LoadMore(StackLineReader* reader) +{ + char* const ptr = reader->buffer + reader->view.size; + const size_t size_to_read = STACK_LINE_READER_BUFFER_SIZE - reader->view.size; + const int read = CpuFeatures_ReadFile(reader->fd, ptr, size_to_read); + assert(read >= 0); + assert(read <= (int)size_to_read); + reader->view.size += read; + return read; +} + +static int IndexOfEol(StackLineReader* reader) +{ + return CpuFeatures_StringView_IndexOfChar(reader->view, '\n'); +} + +// Relocate buffer's pending bytes at the beginning of the array and fills the +// remaining space with bytes from the file. +static int BringToFrontAndLoadMore(StackLineReader* reader) +{ + if (reader->view.size && reader->view.ptr != reader->buffer) + { + memmove(reader->buffer, reader->view.ptr, reader->view.size); + } + reader->view.ptr = reader->buffer; + return LoadMore(reader); +} + +// Loads chunks of buffer size from disks until it contains a newline character +// or end of file. +static void SkipToNextLine(StackLineReader* reader) +{ + for (;;) + { + const int read = LoadFullBuffer(reader); + if (read == 0) + { + break; + } + else + { + const int eol_index = IndexOfEol(reader); + if (eol_index >= 0) + { + reader->view = + CpuFeatures_StringView_PopFront(reader->view, eol_index + 1); + break; + } + } + } +} + +static LineResult CreateLineResult(bool eof, bool full_line, StringView view) +{ + LineResult result; + result.eof = eof; + result.full_line = full_line; + result.line = view; + return result; +} + +// Helper methods to provide clearer semantic in StackLineReader_NextLine. +static LineResult CreateEOFLineResult(StringView view) +{ + return CreateLineResult(true, true, view); +} + +static LineResult CreateTruncatedLineResult(StringView view) +{ + return CreateLineResult(false, false, view); +} + +static LineResult CreateValidLineResult(StringView view) +{ + return CreateLineResult(false, true, view); +} + +LineResult StackLineReader_NextLine(StackLineReader* reader) +{ + if (reader->skip_mode) + { + SkipToNextLine(reader); + reader->skip_mode = false; + } + { + const bool can_load_more = + reader->view.size < STACK_LINE_READER_BUFFER_SIZE; + int eol_index = IndexOfEol(reader); + if (eol_index < 0 && can_load_more) + { + const int read = BringToFrontAndLoadMore(reader); + if (read == 0) + { + return CreateEOFLineResult(reader->view); + } + eol_index = IndexOfEol(reader); + } + if (eol_index < 0) + { + reader->skip_mode = true; + return CreateTruncatedLineResult(reader->view); + } + { + StringView line = + CpuFeatures_StringView_KeepFront(reader->view, eol_index); + reader->view = + CpuFeatures_StringView_PopFront(reader->view, eol_index + 1); + return CreateValidLineResult(line); + } + } +} diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/string_view.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/string_view.c new file mode 100644 index 000000000..e60e7fefe --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/string_view.c @@ -0,0 +1,202 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "internal/string_view.h" +#include +#include +#include + +int CpuFeatures_StringView_IndexOfChar(const StringView view, char c) +{ + if (view.ptr && view.size) + { + const char* const found = (const char*)memchr(view.ptr, c, view.size); + if (found) + { + return (int)(found - view.ptr); + } + } + return -1; +} + +int CpuFeatures_StringView_IndexOf(const StringView view, + const StringView sub_view) +{ + if (sub_view.size) + { + StringView remainder = view; + while (remainder.size >= sub_view.size) + { + const int found_index = + CpuFeatures_StringView_IndexOfChar(remainder, sub_view.ptr[0]); + if (found_index < 0) break; + remainder = CpuFeatures_StringView_PopFront(remainder, found_index); + if (CpuFeatures_StringView_StartsWith(remainder, sub_view)) + { + return (int)(remainder.ptr - view.ptr); + } + remainder = CpuFeatures_StringView_PopFront(remainder, 1); + } + } + return -1; +} + +bool CpuFeatures_StringView_IsEquals(const StringView a, const StringView b) +{ + if (a.size == b.size) + { + return a.ptr == b.ptr || memcmp(a.ptr, b.ptr, b.size) == 0; + } + return false; +} + +bool CpuFeatures_StringView_StartsWith(const StringView a, const StringView b) +{ + return a.ptr && b.ptr && b.size && a.size >= b.size + ? memcmp(a.ptr, b.ptr, b.size) == 0 + : false; +} + +StringView CpuFeatures_StringView_PopFront(const StringView str_view, + size_t count) +{ + if (count > str_view.size) + { + return kEmptyStringView; + } + return view(str_view.ptr + count, str_view.size - count); +} + +StringView CpuFeatures_StringView_PopBack(const StringView str_view, + size_t count) +{ + if (count > str_view.size) + { + return kEmptyStringView; + } + return view(str_view.ptr, str_view.size - count); +} + +StringView CpuFeatures_StringView_KeepFront(const StringView str_view, + size_t count) +{ + return count <= str_view.size ? view(str_view.ptr, count) : str_view; +} + +char CpuFeatures_StringView_Front(const StringView view) +{ + assert(view.size); + assert(view.ptr); + return view.ptr[0]; +} + +char CpuFeatures_StringView_Back(const StringView view) +{ + assert(view.size); + return view.ptr[view.size - 1]; +} + +StringView CpuFeatures_StringView_TrimWhitespace(StringView view) +{ + while (view.size && isspace(CpuFeatures_StringView_Front(view))) + view = CpuFeatures_StringView_PopFront(view, 1); + while (view.size && isspace(CpuFeatures_StringView_Back(view))) + view = CpuFeatures_StringView_PopBack(view, 1); + return view; +} + +static int HexValue(const char c) +{ + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'a' && c <= 'f') return c - 'a' + 10; + if (c >= 'A' && c <= 'F') return c - 'A' + 10; + return -1; +} + +// Returns -1 if view contains non digits. +static int ParsePositiveNumberWithBase(const StringView view, int base) +{ + int result = 0; + StringView remainder = view; + for (; remainder.size; + remainder = CpuFeatures_StringView_PopFront(remainder, 1)) + { + const int value = HexValue(CpuFeatures_StringView_Front(remainder)); + if (value < 0 || value >= base) return -1; + result = (result * base) + value; + } + return result; +} + +int CpuFeatures_StringView_ParsePositiveNumber(const StringView view) +{ + if (view.size) + { + const StringView hex_prefix = str("0x"); + if (CpuFeatures_StringView_StartsWith(view, hex_prefix)) + { + const StringView span_no_prefix = + CpuFeatures_StringView_PopFront(view, hex_prefix.size); + return ParsePositiveNumberWithBase(span_no_prefix, 16); + } + return ParsePositiveNumberWithBase(view, 10); + } + return -1; +} + +void CpuFeatures_StringView_CopyString(const StringView src, char* dst, + size_t dst_size) +{ + if (dst_size > 0) + { + const size_t max_copy_size = dst_size - 1; + const size_t copy_size = + src.size > max_copy_size ? max_copy_size : src.size; + memcpy(dst, src.ptr, copy_size); + dst[copy_size] = '\0'; + } +} + +bool CpuFeatures_StringView_HasWord(const StringView line, + const char* const word_str) +{ + const StringView word = str(word_str); + StringView remainder = line; + for (;;) + { + const int index_of_word = CpuFeatures_StringView_IndexOf(remainder, word); + if (index_of_word < 0) + { + return false; + } + else + { + const StringView before = + CpuFeatures_StringView_KeepFront(line, index_of_word); + const StringView after = + CpuFeatures_StringView_PopFront(line, index_of_word + word.size); + const bool valid_before = + before.size == 0 || CpuFeatures_StringView_Back(before) == ' '; + const bool valid_after = + after.size == 0 || CpuFeatures_StringView_Front(after) == ' '; + if (valid_before && valid_after) return true; + remainder = + CpuFeatures_StringView_PopFront(remainder, index_of_word + word.size); + } + } + return false; +} + +bool CpuFeatures_StringView_GetAttributeKeyValue(const StringView line, + StringView* key, + StringView* value) +{ + const StringView sep = str(": "); + const int index_of_separator = CpuFeatures_StringView_IndexOf(line, sep); + if (index_of_separator < 0) return false; + *value = CpuFeatures_StringView_TrimWhitespace( + CpuFeatures_StringView_PopFront(line, index_of_separator + sep.size)); + *key = CpuFeatures_StringView_TrimWhitespace( + CpuFeatures_StringView_KeepFront(line, index_of_separator)); + return true; +} diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/utils/list_cpu_features.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/utils/list_cpu_features.c new file mode 100644 index 000000000..53aae4011 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/src/utils/list_cpu_features.c @@ -0,0 +1,471 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +// This program dumps current host data to the standard output. +// Output can be text or json if the `--json` flag is passed. + +#include "cpu_features_macros.h" +#include +#include +#include +#include +#include +#include +#include + +#if defined(CPU_FEATURES_ARCH_X86) +#include "cpuinfo_x86.h" +#elif defined(CPU_FEATURES_ARCH_ARM) +#include "cpuinfo_arm.h" +#elif defined(CPU_FEATURES_ARCH_AARCH64) +#include "cpuinfo_aarch64.h" +#elif defined(CPU_FEATURES_ARCH_MIPS) +#include "cpuinfo_mips.h" +#elif defined(CPU_FEATURES_ARCH_PPC) +#include "cpuinfo_ppc.h" +#endif + +// Design principles +// ----------------- +// We build a tree structure containing all the data to be displayed. +// Then depending on the output type (text or json) we walk the tree and display +// the data accordingly. + +// We use a bump allocator to allocate strings and nodes of the tree, +// Memory is not intended to be reclaimed. +typedef struct +{ + char* ptr; + size_t size; +} BumpAllocator; + +char gGlobalBuffer[64 * 1024]; +BumpAllocator gBumpAllocator = {.ptr = gGlobalBuffer, + .size = sizeof(gGlobalBuffer)}; + +static void internal_error() +{ + fputs("internal error\n", stderr); + exit(EXIT_FAILURE); +} + +#define ALIGN 8 + +static void assertAligned() +{ + if ((uintptr_t)(gBumpAllocator.ptr) % ALIGN) internal_error(); +} + +static void BA_Align() +{ + while (gBumpAllocator.size && (uintptr_t)(gBumpAllocator.ptr) % ALIGN) + { + --gBumpAllocator.size; + ++gBumpAllocator.ptr; + } + assertAligned(); +} + +// Update the available memory left in the BumpAllocator. +static void* BA_Bump(size_t size) +{ + assertAligned(); + // Align size to next 8B boundary. + size = (size + ALIGN - 1) / ALIGN * ALIGN; + if (gBumpAllocator.size < size) internal_error(); + void* ptr = gBumpAllocator.ptr; + gBumpAllocator.size -= size; + gBumpAllocator.ptr += size; + return ptr; +} + +// The type of the nodes in the tree. +typedef enum +{ + NT_INVALID, + NT_INT, + NT_MAP, + NT_MAP_ENTRY, + NT_ARRAY, + NT_ARRAY_ELEMENT, + NT_STRING, +} NodeType; + +// The node in the tree. +typedef struct Node +{ + NodeType type; + unsigned integer; + const char* string; + struct Node* value; + struct Node* next; +} Node; + +// Creates an initialized Node. +static Node* BA_CreateNode(NodeType type) +{ + Node* tv = (Node*)BA_Bump(sizeof(Node)); + assert(tv); + *tv = (Node){.type = type}; + return tv; +} + +// Adds an integer node. +static Node* CreateInt(int value) +{ + Node* tv = BA_CreateNode(NT_INT); + tv->integer = value; + return tv; +} + +// Adds a string node. +// `value` must outlive the tree. +static Node* CreateConstantString(const char* value) +{ + Node* tv = BA_CreateNode(NT_STRING); + tv->string = value; + return tv; +} + +// Adds a map node. +static Node* CreateMap() { return BA_CreateNode(NT_MAP); } + +// Adds an array node. +static Node* CreateArray() { return BA_CreateNode(NT_ARRAY); } + +// Adds a formatted string node. +static Node* CreatePrintfString(const char* format, ...) +{ + va_list arglist; + va_start(arglist, format); + char* const ptr = gBumpAllocator.ptr; + const int written = vsnprintf(ptr, gBumpAllocator.size, format, arglist); + va_end(arglist); + if (written < 0 || written >= (int)gBumpAllocator.size) internal_error(); + return CreateConstantString((char*)BA_Bump(written)); +} + +// Adds a string node. +static Node* CreateString(const char* value) +{ + return CreatePrintfString("%s", value); +} + +// Adds a map entry node. +static void AddMapEntry(Node* map, const char* key, Node* value) +{ + assert(map && map->type == NT_MAP); + Node* current = map; + while (current->next) current = current->next; + current->next = (Node*)BA_Bump(sizeof(Node)); + *current->next = (Node){.type = NT_MAP_ENTRY, .string = key, .value = value}; +} + +// Adds an array element node. +static void AddArrayElement(Node* array, Node* value) +{ + assert(array && array->type == NT_ARRAY); + Node* current = array; + while (current->next) current = current->next; + current->next = (Node*)BA_Bump(sizeof(Node)); + *current->next = (Node){.type = NT_ARRAY_ELEMENT, .value = value}; +} + +static int cmp(const void* p1, const void* p2) +{ + return strcmp(*(const char* const*)p1, *(const char* const*)p2); +} + +#define DEFINE_ADD_FLAGS(HasFeature, FeatureName, FeatureType, LastEnum) \ + static void AddFlags(Node* map, const FeatureType* features) \ + { \ + size_t i; \ + const char* ptrs[LastEnum] = {0}; \ + size_t count = 0; \ + for (i = 0; i < LastEnum; ++i) \ + { \ + if (HasFeature(features, i)) \ + { \ + ptrs[count] = FeatureName(i); \ + ++count; \ + } \ + } \ + qsort((void*)ptrs, count, sizeof(char*), cmp); \ + Node* const array = CreateArray(); \ + for (i = 0; i < count; ++i) \ + AddArrayElement(array, CreateConstantString(ptrs[i])); \ + AddMapEntry(map, "flags", array); \ + } + +#if defined(CPU_FEATURES_ARCH_X86) +DEFINE_ADD_FLAGS(GetX86FeaturesEnumValue, GetX86FeaturesEnumName, X86Features, + X86_LAST_) +#elif defined(CPU_FEATURES_ARCH_ARM) +DEFINE_ADD_FLAGS(GetArmFeaturesEnumValue, GetArmFeaturesEnumName, ArmFeatures, + ARM_LAST_) +#elif defined(CPU_FEATURES_ARCH_AARCH64) +DEFINE_ADD_FLAGS(GetAarch64FeaturesEnumValue, GetAarch64FeaturesEnumName, + Aarch64Features, AARCH64_LAST_) +#elif defined(CPU_FEATURES_ARCH_MIPS) +DEFINE_ADD_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName, + MipsFeatures, MIPS_LAST_) +#elif defined(CPU_FEATURES_ARCH_PPC) +DEFINE_ADD_FLAGS(GetPPCFeaturesEnumValue, GetPPCFeaturesEnumName, PPCFeatures, + PPC_LAST_) +#endif + +// Prints a json string with characters escaping. +static void printJsonString(const char* str) +{ + putchar('"'); + for (; str && *str; ++str) + { + switch (*str) + { + case '\"': + case '\\': + case '/': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + putchar('\\'); + } + putchar(*str); + } + putchar('"'); +} + +// Walks a Node and print it as json. +static void printJson(const Node* current) +{ + assert(current); + switch (current->type) + { + case NT_INVALID: + break; + case NT_INT: + printf("%d", current->integer); + break; + case NT_STRING: + printJsonString(current->string); + break; + case NT_ARRAY: + putchar('['); + if (current->next) printJson(current->next); + putchar(']'); + break; + case NT_MAP: + putchar('{'); + if (current->next) printJson(current->next); + putchar('}'); + break; + case NT_MAP_ENTRY: + printf("\"%s\":", current->string); + printJson(current->value); + if (current->next) + { + putchar(','); + printJson(current->next); + } + break; + case NT_ARRAY_ELEMENT: + printJson(current->value); + if (current->next) + { + putchar(','); + printJson(current->next); + } + break; + } +} + +// Walks a Node and print it as text. +static void printTextField(const Node* current) +{ + switch (current->type) + { + case NT_INVALID: + break; + case NT_INT: + printf("%3d (0x%02X)", current->integer, current->integer); + break; + case NT_STRING: + fputs(current->string, stdout); + break; + case NT_ARRAY: + if (current->next) printTextField(current->next); + break; + case NT_MAP: + if (current->next) + { + printf("{"); + printJson(current->next); + printf("}"); + } + break; + case NT_MAP_ENTRY: + printf("%-15s : ", current->string); + printTextField(current->value); + if (current->next) + { + putchar('\n'); + printTextField(current->next); + } + break; + case NT_ARRAY_ELEMENT: + printTextField(current->value); + if (current->next) + { + putchar(','); + printTextField(current->next); + } + break; + } +} + +static void printTextRoot(const Node* current) +{ + if (current->type == NT_MAP && current->next) printTextField(current->next); +} + +static void showUsage(const char* name) +{ + printf( + "\n" + "Usage: %s [options]\n" + " Options:\n" + " -h | --help Show help message.\n" + " -j | --json Format output as json instead of plain text.\n" + "\n", + name); +} + +static Node* GetCacheTypeString(CacheType cache_type) +{ + switch (cache_type) + { + case CPU_FEATURE_CACHE_NULL: + return CreateConstantString("null"); + case CPU_FEATURE_CACHE_DATA: + return CreateConstantString("data"); + case CPU_FEATURE_CACHE_INSTRUCTION: + return CreateConstantString("instruction"); + case CPU_FEATURE_CACHE_UNIFIED: + return CreateConstantString("unified"); + case CPU_FEATURE_CACHE_TLB: + return CreateConstantString("tlb"); + case CPU_FEATURE_CACHE_DTLB: + return CreateConstantString("dtlb"); + case CPU_FEATURE_CACHE_STLB: + return CreateConstantString("stlb"); + case CPU_FEATURE_CACHE_PREFETCH: + return CreateConstantString("prefetch"); + default: + return CreateConstantString("null"); + } +} + +static void AddCacheInfo(Node* root, const CacheInfo* cache_info) +{ + Node* array = CreateArray(); + for (int i = 0; i < cache_info->size; ++i) + { + CacheLevelInfo info = cache_info->levels[i]; + Node* map = CreateMap(); + AddMapEntry(map, "level", CreateInt(info.level)); + AddMapEntry(map, "cache_type", GetCacheTypeString(info.cache_type)); + AddMapEntry(map, "cache_size", CreateInt(info.cache_size)); + AddMapEntry(map, "ways", CreateInt(info.ways)); + AddMapEntry(map, "line_size", CreateInt(info.line_size)); + AddMapEntry(map, "tlb_entries", CreateInt(info.tlb_entries)); + AddMapEntry(map, "partitioning", CreateInt(info.partitioning)); + AddArrayElement(array, map); + } + AddMapEntry(root, "cache_info", array); +} + +static Node* CreateTree() +{ + Node* root = CreateMap(); +#if defined(CPU_FEATURES_ARCH_X86) + char brand_string[49]; + const X86Info info = GetX86Info(); + const CacheInfo cache_info = GetX86CacheInfo(); + FillX86BrandString(brand_string); + AddMapEntry(root, "arch", CreateString("x86")); + AddMapEntry(root, "brand", CreateString(brand_string)); + AddMapEntry(root, "family", CreateInt(info.family)); + AddMapEntry(root, "model", CreateInt(info.model)); + AddMapEntry(root, "stepping", CreateInt(info.stepping)); + AddMapEntry(root, "uarch", + CreateString( + GetX86MicroarchitectureName(GetX86Microarchitecture(&info)))); + AddFlags(root, &info.features); + AddCacheInfo(root, &cache_info); +#elif defined(CPU_FEATURES_ARCH_ARM) + const ArmInfo info = GetArmInfo(); + AddMapEntry(root, "arch", CreateString("ARM")); + AddMapEntry(root, "implementer", CreateInt(info.implementer)); + AddMapEntry(root, "architecture", CreateInt(info.architecture)); + AddMapEntry(root, "variant", CreateInt(info.variant)); + AddMapEntry(root, "part", CreateInt(info.part)); + AddMapEntry(root, "revision", CreateInt(info.revision)); + AddFlags(root, &info.features); +#elif defined(CPU_FEATURES_ARCH_AARCH64) + const Aarch64Info info = GetAarch64Info(); + AddMapEntry(root, "arch", CreateString("aarch64")); + AddMapEntry(root, "implementer", CreateInt(info.implementer)); + AddMapEntry(root, "variant", CreateInt(info.variant)); + AddMapEntry(root, "part", CreateInt(info.part)); + AddMapEntry(root, "revision", CreateInt(info.revision)); + AddFlags(root, &info.features); +#elif defined(CPU_FEATURES_ARCH_MIPS) + const MipsInfo info = GetMipsInfo(); + AddMapEntry(root, "arch", CreateString("mips")); + AddFlags(root, &info.features); +#elif defined(CPU_FEATURES_ARCH_PPC) + const PPCInfo info = GetPPCInfo(); + const PPCPlatformStrings strings = GetPPCPlatformStrings(); + AddMapEntry(root, "arch", CreateString("ppc")); + AddMapEntry(root, "platform", CreateString(strings.platform)); + AddMapEntry(root, "model", CreateString(strings.model)); + AddMapEntry(root, "machine", CreateString(strings.machine)); + AddMapEntry(root, "cpu", CreateString(strings.cpu)); + AddMapEntry(root, "instruction", CreateString(strings.type.platform)); + AddMapEntry(root, "microarchitecture", + CreateString(strings.type.base_platform)); + AddFlags(root, &info.features); +#endif + return root; +} + +int main(int argc, char** argv) +{ + BA_Align(); + const Node* const root = CreateTree(); + bool outputJson = false; + int i = 1; + for (; i < argc; ++i) + { + const char* arg = argv[i]; + if (strcmp(arg, "-j") == 0 || strcmp(arg, "--json") == 0) + { + outputJson = true; + } + else + { + showUsage(argv[0]); + if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) + return EXIT_SUCCESS; + return EXIT_FAILURE; + } + } + if (outputJson) + printJson(root); + else + printTextRoot(root); + putchar('\n'); + return EXIT_SUCCESS; +} diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/CMakeLists.txt b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/CMakeLists.txt new file mode 100644 index 000000000..aa30768d5 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/CMakeLists.txt @@ -0,0 +1,88 @@ +# SPDX-FileCopyrightText: 2017 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +# +# libraries for tests +# + +include_directories(../include) +add_definitions(-DCPU_FEATURES_TEST) + +##------------------------------------------------------------------------------ +add_library(string_view ../src/string_view.c) +##------------------------------------------------------------------------------ +add_library(filesystem_for_testing filesystem_for_testing.cc) +target_compile_definitions(filesystem_for_testing PUBLIC CPU_FEATURES_MOCK_FILESYSTEM) +##------------------------------------------------------------------------------ +add_library(hwcaps_for_testing hwcaps_for_testing.cc) +target_link_libraries(hwcaps_for_testing filesystem_for_testing) +##------------------------------------------------------------------------------ +add_library(stack_line_reader ../src/stack_line_reader.c) +target_compile_definitions(stack_line_reader PUBLIC STACK_LINE_READER_BUFFER_SIZE=1024) +target_link_libraries(stack_line_reader string_view) +##------------------------------------------------------------------------------ +add_library(stack_line_reader_for_test ../src/stack_line_reader.c) +target_compile_definitions(stack_line_reader_for_test PUBLIC STACK_LINE_READER_BUFFER_SIZE=16) +target_link_libraries(stack_line_reader_for_test string_view filesystem_for_testing) +##------------------------------------------------------------------------------ +add_library(all_libraries ../src/hwcaps.c ../src/stack_line_reader.c) +target_link_libraries(all_libraries hwcaps_for_testing stack_line_reader string_view) + +# +# tests +# +link_libraries(gtest gmock_main) + +## bit_utils_test +add_executable(bit_utils_test bit_utils_test.cc) +target_link_libraries(bit_utils_test) +add_test(NAME bit_utils_test COMMAND bit_utils_test) +##------------------------------------------------------------------------------ +## string_view_test +add_executable(string_view_test string_view_test.cc ../src/string_view.c) +target_link_libraries(string_view_test string_view) +add_test(NAME string_view_test COMMAND string_view_test) +##------------------------------------------------------------------------------ +## stack_line_reader_test +add_executable(stack_line_reader_test stack_line_reader_test.cc) +target_link_libraries(stack_line_reader_test stack_line_reader_for_test) +add_test(NAME stack_line_reader_test COMMAND stack_line_reader_test) +##------------------------------------------------------------------------------ +## cpuinfo_x86_test +if(PROCESSOR_IS_X86) + add_executable(cpuinfo_x86_test cpuinfo_x86_test.cc ../src/cpuinfo_x86.c) + target_compile_definitions(cpuinfo_x86_test PUBLIC CPU_FEATURES_MOCK_CPUID_X86) + if(APPLE) + target_compile_definitions(cpuinfo_x86_test PRIVATE HAVE_SYSCTLBYNAME) + endif() + target_link_libraries(cpuinfo_x86_test all_libraries) + add_test(NAME cpuinfo_x86_test COMMAND cpuinfo_x86_test) +endif() +##------------------------------------------------------------------------------ +## cpuinfo_arm_test +if(PROCESSOR_IS_ARM) + add_executable(cpuinfo_arm_test cpuinfo_arm_test.cc ../src/cpuinfo_arm.c) + target_link_libraries(cpuinfo_arm_test all_libraries) + add_test(NAME cpuinfo_arm_test COMMAND cpuinfo_arm_test) +endif() +##------------------------------------------------------------------------------ +## cpuinfo_aarch64_test +if(PROCESSOR_IS_AARCH64) + add_executable(cpuinfo_aarch64_test cpuinfo_aarch64_test.cc ../src/cpuinfo_aarch64.c) + target_link_libraries(cpuinfo_aarch64_test all_libraries) + add_test(NAME cpuinfo_aarch64_test COMMAND cpuinfo_aarch64_test) +endif() +##------------------------------------------------------------------------------ +## cpuinfo_mips_test +if(PROCESSOR_IS_MIPS) + add_executable(cpuinfo_mips_test cpuinfo_mips_test.cc ../src/cpuinfo_mips.c) + target_link_libraries(cpuinfo_mips_test all_libraries) + add_test(NAME cpuinfo_mips_test COMMAND cpuinfo_mips_test) +endif() +##------------------------------------------------------------------------------ +## cpuinfo_ppc_test +if(PROCESSOR_IS_POWER) + add_executable(cpuinfo_ppc_test cpuinfo_ppc_test.cc ../src/cpuinfo_ppc.c) + target_link_libraries(cpuinfo_ppc_test all_libraries) + add_test(NAME cpuinfo_ppc_test COMMAND cpuinfo_ppc_test) +endif() diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/bit_utils_test.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/bit_utils_test.cc new file mode 100644 index 000000000..6358fcd98 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/bit_utils_test.cc @@ -0,0 +1,48 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "gtest/gtest.h" +#include "internal/bit_utils.h" + +namespace cpu_features +{ +namespace +{ +TEST(UtilsTest, IsBitSet) +{ + for (size_t bit_set = 0; bit_set < 32; ++bit_set) + { + const uint32_t value = 1UL << bit_set; + for (uint32_t i = 0; i < 32; ++i) + { + EXPECT_EQ(IsBitSet(value, i), i == bit_set); + } + } + + // testing 0, all bits should be 0. + for (uint32_t i = 0; i < 32; ++i) + { + EXPECT_FALSE(IsBitSet(0, i)); + } + + // testing ~0, all bits should be 1. + for (uint32_t i = 0; i < 32; ++i) + { + EXPECT_TRUE(IsBitSet(-1, i)); + } +} + +TEST(UtilsTest, ExtractBitRange) +{ + // Extracting all bits gives the same number. + EXPECT_EQ(ExtractBitRange(123, 31, 0), 123); + // Extracting 1 bit gives parity. + EXPECT_EQ(ExtractBitRange(123, 0, 0), 1); + EXPECT_EQ(ExtractBitRange(122, 0, 0), 0); + + EXPECT_EQ(ExtractBitRange(0xF0, 7, 4), 0xF); + EXPECT_EQ(ExtractBitRange(0x42 << 2, 10, 2), 0x42); +} + +} // namespace +} // namespace cpu_features diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_aarch64_test.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_aarch64_test.cc new file mode 100644 index 000000000..2c29b5e7e --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_aarch64_test.cc @@ -0,0 +1,163 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "cpuinfo_aarch64.h" +#include "filesystem_for_testing.h" +#include "gtest/gtest.h" +#include "hwcaps_for_testing.h" + +namespace cpu_features +{ +namespace +{ +void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); } + +TEST(CpuinfoAarch64Test, FromHardwareCap) +{ + SetHardwareCapabilities(AARCH64_HWCAP_FP | AARCH64_HWCAP_AES, 0); + GetEmptyFilesystem(); // disabling /proc/cpuinfo + const auto info = GetAarch64Info(); + EXPECT_TRUE(info.features.fp); + EXPECT_FALSE(info.features.asimd); + EXPECT_FALSE(info.features.evtstrm); + EXPECT_TRUE(info.features.aes); + EXPECT_FALSE(info.features.pmull); + EXPECT_FALSE(info.features.sha1); + EXPECT_FALSE(info.features.sha2); + EXPECT_FALSE(info.features.crc32); + EXPECT_FALSE(info.features.atomics); + EXPECT_FALSE(info.features.fphp); + EXPECT_FALSE(info.features.asimdhp); + EXPECT_FALSE(info.features.cpuid); + EXPECT_FALSE(info.features.asimdrdm); + EXPECT_FALSE(info.features.jscvt); + EXPECT_FALSE(info.features.fcma); + EXPECT_FALSE(info.features.lrcpc); + EXPECT_FALSE(info.features.dcpop); + EXPECT_FALSE(info.features.sha3); + EXPECT_FALSE(info.features.sm3); + EXPECT_FALSE(info.features.sm4); + EXPECT_FALSE(info.features.asimddp); + EXPECT_FALSE(info.features.sha512); + EXPECT_FALSE(info.features.sve); + EXPECT_FALSE(info.features.asimdfhm); + EXPECT_FALSE(info.features.dit); + EXPECT_FALSE(info.features.uscat); + EXPECT_FALSE(info.features.ilrcpc); + EXPECT_FALSE(info.features.flagm); + EXPECT_FALSE(info.features.ssbs); + EXPECT_FALSE(info.features.sb); + EXPECT_FALSE(info.features.paca); + EXPECT_FALSE(info.features.pacg); +} + +TEST(CpuinfoAarch64Test, FromHardwareCap2) +{ + SetHardwareCapabilities(AARCH64_HWCAP_FP, + AARCH64_HWCAP2_SVE2 | AARCH64_HWCAP2_BTI); + GetEmptyFilesystem(); // disabling /proc/cpuinfo + const auto info = GetAarch64Info(); + EXPECT_TRUE(info.features.fp); + + EXPECT_TRUE(info.features.sve2); + EXPECT_TRUE(info.features.bti); + + EXPECT_FALSE(info.features.dcpodp); + EXPECT_FALSE(info.features.sveaes); + EXPECT_FALSE(info.features.svepmull); + EXPECT_FALSE(info.features.svebitperm); + EXPECT_FALSE(info.features.svesha3); + EXPECT_FALSE(info.features.svesm4); + EXPECT_FALSE(info.features.flagm2); + EXPECT_FALSE(info.features.frint); + EXPECT_FALSE(info.features.svei8mm); + EXPECT_FALSE(info.features.svef32mm); + EXPECT_FALSE(info.features.svef64mm); + EXPECT_FALSE(info.features.svebf16); + EXPECT_FALSE(info.features.i8mm); + EXPECT_FALSE(info.features.bf16); + EXPECT_FALSE(info.features.dgh); + EXPECT_FALSE(info.features.rng); +} + +TEST(CpuinfoAarch64Test, ARMCortexA53) +{ + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(Processor : AArch64 Processor rev 3 (aarch64) +processor : 0 +processor : 1 +processor : 2 +processor : 3 +processor : 4 +processor : 5 +processor : 6 +processor : 7 +Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 +CPU implementer : 0x41 +CPU architecture: AArch64 +CPU variant : 0x0 +CPU part : 0xd03 +CPU revision : 3)"); + const auto info = GetAarch64Info(); + EXPECT_EQ(info.implementer, 0x41); + EXPECT_EQ(info.variant, 0x0); + EXPECT_EQ(info.part, 0xd03); + EXPECT_EQ(info.revision, 3); + + EXPECT_TRUE(info.features.fp); + EXPECT_TRUE(info.features.asimd); + EXPECT_TRUE(info.features.evtstrm); + EXPECT_TRUE(info.features.aes); + EXPECT_TRUE(info.features.pmull); + EXPECT_TRUE(info.features.sha1); + EXPECT_TRUE(info.features.sha2); + EXPECT_TRUE(info.features.crc32); + + EXPECT_FALSE(info.features.atomics); + EXPECT_FALSE(info.features.fphp); + EXPECT_FALSE(info.features.asimdhp); + EXPECT_FALSE(info.features.cpuid); + EXPECT_FALSE(info.features.asimdrdm); + EXPECT_FALSE(info.features.jscvt); + EXPECT_FALSE(info.features.fcma); + EXPECT_FALSE(info.features.lrcpc); + EXPECT_FALSE(info.features.dcpop); + EXPECT_FALSE(info.features.sha3); + EXPECT_FALSE(info.features.sm3); + EXPECT_FALSE(info.features.sm4); + EXPECT_FALSE(info.features.asimddp); + EXPECT_FALSE(info.features.sha512); + EXPECT_FALSE(info.features.sve); + EXPECT_FALSE(info.features.asimdfhm); + EXPECT_FALSE(info.features.dit); + EXPECT_FALSE(info.features.uscat); + EXPECT_FALSE(info.features.ilrcpc); + EXPECT_FALSE(info.features.flagm); + EXPECT_FALSE(info.features.ssbs); + EXPECT_FALSE(info.features.sb); + EXPECT_FALSE(info.features.paca); + EXPECT_FALSE(info.features.pacg); + EXPECT_FALSE(info.features.dcpodp); + EXPECT_FALSE(info.features.sve2); + EXPECT_FALSE(info.features.sveaes); + EXPECT_FALSE(info.features.svepmull); + EXPECT_FALSE(info.features.svebitperm); + EXPECT_FALSE(info.features.svesha3); + EXPECT_FALSE(info.features.svesm4); + EXPECT_FALSE(info.features.flagm2); + EXPECT_FALSE(info.features.frint); + EXPECT_FALSE(info.features.svei8mm); + EXPECT_FALSE(info.features.svef32mm); + EXPECT_FALSE(info.features.svef64mm); + EXPECT_FALSE(info.features.svebf16); + EXPECT_FALSE(info.features.i8mm); + EXPECT_FALSE(info.features.bf16); + EXPECT_FALSE(info.features.dgh); + EXPECT_FALSE(info.features.rng); + EXPECT_FALSE(info.features.bti); +} + +} // namespace +} // namespace cpu_features diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_arm_test.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_arm_test.cc new file mode 100644 index 000000000..13c8eb4c8 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_arm_test.cc @@ -0,0 +1,344 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "cpuinfo_arm.h" +#include "filesystem_for_testing.h" +#include "gtest/gtest.h" +#include "hwcaps_for_testing.h" + +namespace cpu_features +{ +namespace +{ +void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); } + +TEST(CpuinfoArmTest, FromHardwareCap) +{ + SetHardwareCapabilities(ARM_HWCAP_NEON, ARM_HWCAP2_AES | ARM_HWCAP2_CRC32); + GetEmptyFilesystem(); // disabling /proc/cpuinfo + const auto info = GetArmInfo(); + EXPECT_TRUE(info.features.vfp); // triggered by vfpv3 + EXPECT_TRUE(info.features.vfpv3); // triggered by neon + EXPECT_TRUE(info.features.neon); + EXPECT_TRUE(info.features.aes); + EXPECT_TRUE(info.features.crc32); + + EXPECT_FALSE(info.features.vfpv4); + EXPECT_FALSE(info.features.iwmmxt); + EXPECT_FALSE(info.features.crunch); + EXPECT_FALSE(info.features.thumbee); + EXPECT_FALSE(info.features.vfpv3d16); + EXPECT_FALSE(info.features.idiva); + EXPECT_FALSE(info.features.idivt); + EXPECT_FALSE(info.features.pmull); + EXPECT_FALSE(info.features.sha1); + EXPECT_FALSE(info.features.sha2); + + // check some random features with EnumValue(): + EXPECT_TRUE(GetArmFeaturesEnumValue(&info.features, ARM_VFP)); + EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, ARM_VFPV4)); + // out of bound EnumValue() check + EXPECT_FALSE(GetArmFeaturesEnumValue(&info.features, (ArmFeaturesEnum)~0x0)); +} + +TEST(CpuinfoArmTest, ODroidFromCpuInfo) +{ + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"(processor : 0 +model name : ARMv7 Processor rev 3 (v71) +BogoMIPS : 120.00 +Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae +CPU implementer : 0x41 +CPU architecture: 7 +CPU variant : 0x2 +CPU part : 0xc0f +CPU revision : 3)"); + const auto info = GetArmInfo(); + EXPECT_EQ(info.implementer, 0x41); + EXPECT_EQ(info.variant, 0x2); + EXPECT_EQ(info.part, 0xc0f); + EXPECT_EQ(info.revision, 3); + EXPECT_EQ(info.architecture, 7); + + EXPECT_FALSE(info.features.swp); + EXPECT_TRUE(info.features.half); + EXPECT_TRUE(info.features.thumb); + EXPECT_FALSE(info.features._26bit); + EXPECT_TRUE(info.features.fastmult); + EXPECT_FALSE(info.features.fpa); + EXPECT_TRUE(info.features.vfp); + EXPECT_TRUE(info.features.edsp); + EXPECT_FALSE(info.features.java); + EXPECT_FALSE(info.features.iwmmxt); + EXPECT_FALSE(info.features.crunch); + EXPECT_FALSE(info.features.thumbee); + EXPECT_TRUE(info.features.neon); + EXPECT_TRUE(info.features.vfpv3); + EXPECT_FALSE(info.features.vfpv3d16); + EXPECT_TRUE(info.features.tls); + EXPECT_TRUE(info.features.vfpv4); + EXPECT_TRUE(info.features.idiva); + EXPECT_TRUE(info.features.idivt); + EXPECT_TRUE(info.features.vfpd32); + EXPECT_TRUE(info.features.lpae); + EXPECT_FALSE(info.features.evtstrm); + EXPECT_FALSE(info.features.aes); + EXPECT_FALSE(info.features.pmull); + EXPECT_FALSE(info.features.sha1); + EXPECT_FALSE(info.features.sha2); + EXPECT_FALSE(info.features.crc32); +} + +// Linux test-case +TEST(CpuinfoArmTest, RaspberryPiZeroFromCpuInfo) +{ + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"(processor : 0 +model name : ARMv6-compatible processor rev 7 (v6l) +BogoMIPS : 697.95 +Features : half thumb fastmult vfp edsp java tls +CPU implementer : 0x41 +CPU architecture: 7 +CPU variant : 0x0 +CPU part : 0xb76 +CPU revision : 7 +Hardware : BCM2835 +Revision : 9000c1 +Serial : 000000006cd946f3)"); + const auto info = GetArmInfo(); + EXPECT_EQ(info.implementer, 0x41); + EXPECT_EQ(info.variant, 0x0); + EXPECT_EQ(info.part, 0xb76); + EXPECT_EQ(info.revision, 7); + EXPECT_EQ(info.architecture, 6); + + EXPECT_FALSE(info.features.swp); + EXPECT_TRUE(info.features.half); + EXPECT_TRUE(info.features.thumb); + EXPECT_FALSE(info.features._26bit); + EXPECT_TRUE(info.features.fastmult); + EXPECT_FALSE(info.features.fpa); + EXPECT_TRUE(info.features.vfp); + EXPECT_TRUE(info.features.edsp); + EXPECT_TRUE(info.features.java); + EXPECT_FALSE(info.features.iwmmxt); + EXPECT_FALSE(info.features.crunch); + EXPECT_FALSE(info.features.thumbee); + EXPECT_FALSE(info.features.neon); + EXPECT_FALSE(info.features.vfpv3); + EXPECT_FALSE(info.features.vfpv3d16); + EXPECT_TRUE(info.features.tls); + EXPECT_FALSE(info.features.vfpv4); + EXPECT_FALSE(info.features.idiva); + EXPECT_FALSE(info.features.idivt); + EXPECT_FALSE(info.features.vfpd32); + EXPECT_FALSE(info.features.lpae); + EXPECT_FALSE(info.features.evtstrm); + EXPECT_FALSE(info.features.aes); + EXPECT_FALSE(info.features.pmull); + EXPECT_FALSE(info.features.sha1); + EXPECT_FALSE(info.features.sha2); + EXPECT_FALSE(info.features.crc32); +} + +TEST(CpuinfoArmTest, MarvellArmadaFromCpuInfo) +{ + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"(processor : 0 +model name : ARMv7 Processor rev 1 (v7l) +BogoMIPS : 50.00 +Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32 +CPU implementer : 0x41 +CPU architecture: 7 +CPU variant : 0x4 +CPU part : 0xc09 +CPU revision : 1 +processor : 1 +model name : ARMv7 Processor rev 1 (v7l) +BogoMIPS : 50.00 +Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32 +CPU implementer : 0x41 +CPU architecture: 7 +CPU variant : 0x4 +CPU part : 0xc09 +CPU revision : 1 +Hardware : Marvell Armada 380/385 (Device Tree) +Revision : 0000 +Serial : 0000000000000000)"); + const auto info = GetArmInfo(); + EXPECT_EQ(info.implementer, 0x41); + EXPECT_EQ(info.variant, 0x4); + EXPECT_EQ(info.part, 0xc09); + EXPECT_EQ(info.revision, 1); + EXPECT_EQ(info.architecture, 7); + + EXPECT_FALSE(info.features.swp); + EXPECT_TRUE(info.features.half); + EXPECT_TRUE(info.features.thumb); + EXPECT_FALSE(info.features._26bit); + EXPECT_TRUE(info.features.fastmult); + EXPECT_FALSE(info.features.fpa); + EXPECT_TRUE(info.features.vfp); + EXPECT_TRUE(info.features.edsp); + EXPECT_FALSE(info.features.java); + EXPECT_FALSE(info.features.iwmmxt); + EXPECT_FALSE(info.features.crunch); + EXPECT_FALSE(info.features.thumbee); + EXPECT_TRUE(info.features.neon); + EXPECT_TRUE(info.features.vfpv3); + EXPECT_FALSE(info.features.vfpv3d16); + EXPECT_TRUE(info.features.tls); + EXPECT_FALSE(info.features.vfpv4); + EXPECT_FALSE(info.features.idiva); + EXPECT_FALSE(info.features.idivt); + EXPECT_TRUE(info.features.vfpd32); + EXPECT_FALSE(info.features.lpae); + EXPECT_FALSE(info.features.evtstrm); + EXPECT_FALSE(info.features.aes); + EXPECT_FALSE(info.features.pmull); + EXPECT_FALSE(info.features.sha1); + EXPECT_FALSE(info.features.sha2); + EXPECT_FALSE(info.features.crc32); +} + +// Android test-case +// http://code.google.com/p/android/issues/detail?id=10812 +TEST(CpuinfoArmTest, InvalidArmv7) +{ + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(Processor : ARMv6-compatible processor rev 6 (v6l) +BogoMIPS : 199.47 +Features : swp half thumb fastmult vfp edsp java +CPU implementer : 0x41 +CPU architecture: 7 +CPU variant : 0x0 +CPU part : 0xb76 +CPU revision : 6 +Hardware : SPICA +Revision : 0020 +Serial : 33323613546d00ec )"); + const auto info = GetArmInfo(); + EXPECT_EQ(info.architecture, 6); + + EXPECT_TRUE(info.features.swp); + EXPECT_TRUE(info.features.half); + EXPECT_TRUE(info.features.thumb); + EXPECT_FALSE(info.features._26bit); + EXPECT_TRUE(info.features.fastmult); + EXPECT_FALSE(info.features.fpa); + EXPECT_TRUE(info.features.vfp); + EXPECT_TRUE(info.features.edsp); + EXPECT_TRUE(info.features.java); + EXPECT_FALSE(info.features.iwmmxt); + EXPECT_FALSE(info.features.crunch); + EXPECT_FALSE(info.features.thumbee); + EXPECT_FALSE(info.features.neon); + EXPECT_FALSE(info.features.vfpv3); + EXPECT_FALSE(info.features.vfpv3d16); + EXPECT_FALSE(info.features.tls); + EXPECT_FALSE(info.features.vfpv4); + EXPECT_FALSE(info.features.idiva); + EXPECT_FALSE(info.features.idivt); + EXPECT_FALSE(info.features.vfpd32); + EXPECT_FALSE(info.features.lpae); + EXPECT_FALSE(info.features.evtstrm); + EXPECT_FALSE(info.features.aes); + EXPECT_FALSE(info.features.pmull); + EXPECT_FALSE(info.features.sha1); + EXPECT_FALSE(info.features.sha2); + EXPECT_FALSE(info.features.crc32); +} + +// Android test-case +// https://crbug.com/341598. +TEST(CpuinfoArmTest, InvalidNeon) +{ + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(Processor: ARMv7 Processory rev 0 (v71) +processor: 0 +BogoMIPS: 13.50 +Processor: 1 +BogoMIPS: 13.50 +Features: swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt +CPU implementer : 0x51 +CPU architecture: 7 +CPU variant: 0x1 +CPU part: 0x04d +CPU revision: 0 +Hardware: SAMSUNG M2 +Revision: 0010 +Serial: 00001e030000354e)"); + const auto info = GetArmInfo(); + EXPECT_TRUE(info.features.swp); + EXPECT_FALSE(info.features.neon); +} + +// The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report IDIV +// support. +TEST(CpuinfoArmTest, Nexus4_0x510006f2) +{ + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(CPU implementer : 0x51 +CPU architecture: 7 +CPU variant : 0x0 +CPU part : 0x6f +CPU revision : 2)"); + const auto info = GetArmInfo(); + EXPECT_TRUE(info.features.idiva); + EXPECT_TRUE(info.features.idivt); + + EXPECT_EQ(GetArmCpuId(&info), 0x510006f2); +} + +// The Nexus 4 (Qualcomm Krait) kernel configuration forgets to report IDIV +// support. +TEST(CpuinfoArmTest, Nexus4_0x510006f3) +{ + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(CPU implementer : 0x51 +CPU architecture: 7 +CPU variant : 0x0 +CPU part : 0x6f +CPU revision : 3)"); + const auto info = GetArmInfo(); + EXPECT_TRUE(info.features.idiva); + EXPECT_TRUE(info.features.idivt); + + EXPECT_EQ(GetArmCpuId(&info), 0x510006f3); +} + +// The emulator-specific Android 4.2 kernel fails to report support for the +// 32-bit ARM IDIV instruction. Technically, this is a feature of the virtual +// CPU implemented by the emulator. +TEST(CpuinfoArmTest, EmulatorSpecificIdiv) +{ + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(Processor : ARMv7 Processor rev 0 (v7l) +BogoMIPS : 629.14 +Features : swp half thumb fastmult vfp edsp neon vfpv3 +CPU implementer : 0x41 +CPU architecture: 7 +CPU variant : 0x0 +CPU part : 0xc08 +CPU revision : 0 +Hardware : Goldfish +Revision : 0000 +Serial : 0000000000000000)"); + const auto info = GetArmInfo(); + EXPECT_TRUE(info.features.idiva); +} + +} // namespace +} // namespace cpu_features diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_mips_test.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_mips_test.cc new file mode 100644 index 000000000..0503d843d --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_mips_test.cc @@ -0,0 +1,119 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "cpuinfo_mips.h" +#include "filesystem_for_testing.h" +#include "gtest/gtest.h" +#include "hwcaps_for_testing.h" +#include "internal/stack_line_reader.h" +#include "internal/string_view.h" + +namespace cpu_features +{ +namespace +{ +void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); } + +TEST(CpuinfoMipsTest, FromHardwareCapBoth) +{ + SetHardwareCapabilities(MIPS_HWCAP_MSA | MIPS_HWCAP_R6, 0); + GetEmptyFilesystem(); // disabling /proc/cpuinfo + const auto info = GetMipsInfo(); + EXPECT_TRUE(info.features.msa); + EXPECT_FALSE(info.features.eva); + EXPECT_TRUE(info.features.r6); +} + +TEST(CpuinfoMipsTest, FromHardwareCapOnlyOne) +{ + SetHardwareCapabilities(MIPS_HWCAP_MSA, 0); + GetEmptyFilesystem(); // disabling /proc/cpuinfo + const auto info = GetMipsInfo(); + EXPECT_TRUE(info.features.msa); + EXPECT_FALSE(info.features.eva); +} + +TEST(CpuinfoMipsTest, Ci40) +{ + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"(system type : IMG Pistachio SoC (B0) +machine : IMG Marduk – Ci40 with cc2520 +processor : 0 +cpu model : MIPS interAptiv (multi) V2.0 FPU V0.0 +BogoMIPS : 363.72 +wait instruction : yes +microsecond timers : yes +tlb_entries : 64 +extra interrupt vector : yes +hardware watchpoint : yes, count: 4, address/irw mask: [0x0ffc, 0x0ffc, 0x0ffb, 0x0ffb] +isa : mips1 mips2 mips32r1 mips32r2 +ASEs implemented : mips16 dsp mt eva +shadow register sets : 1 +kscratch registers : 0 +package : 0 +core : 0 +VCED exceptions : not available +VCEI exceptions : not available +VPE : 0 +)"); + const auto info = GetMipsInfo(); + EXPECT_FALSE(info.features.msa); + EXPECT_TRUE(info.features.eva); +} + +TEST(CpuinfoMipsTest, AR7161) +{ + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(system type : Atheros AR7161 rev 2 +machine : NETGEAR WNDR3700/WNDR3800/WNDRMAC +processor : 0 +cpu model : MIPS 24Kc V7.4 +BogoMIPS : 452.19 +wait instruction : yes +microsecond timers : yes +tlb_entries : 16 +extra interrupt vector : yes +hardware watchpoint : yes, count: 4, address/irw mask: [0x0000, 0x0f98, 0x0f78, 0x0df8] +ASEs implemented : mips16 +shadow register sets : 1 +kscratch registers : 0 +core : 0 +VCED exceptions : not available +VCEI exceptions : not available +)"); + const auto info = GetMipsInfo(); + EXPECT_FALSE(info.features.msa); + EXPECT_FALSE(info.features.eva); +} + +TEST(CpuinfoMipsTest, Goldfish) +{ + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"(system type : MIPS-Goldfish +Hardware : goldfish +Revison : 1 +processor : 0 +cpu model : MIPS 24Kc V0.0 FPU V0.0 +BogoMIPS : 1042.02 +wait instruction : yes +microsecond timers : yes +tlb_entries : 16 +extra interrupt vector : yes +hardware watchpoint : yes, count: 1, address/irw mask: [0x0ff8] +ASEs implemented : +shadow register sets : 1 +core : 0 +VCED exceptions : not available +VCEI exceptions : not available +)"); + const auto info = GetMipsInfo(); + EXPECT_FALSE(info.features.msa); + EXPECT_FALSE(info.features.eva); +} + +} // namespace +} // namespace cpu_features diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_ppc_test.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_ppc_test.cc new file mode 100644 index 000000000..d657d9b6a --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_ppc_test.cc @@ -0,0 +1,107 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "cpuinfo_ppc.h" +#include "filesystem_for_testing.h" +#include "gtest/gtest.h" +#include "hwcaps_for_testing.h" +#include "internal/string_view.h" + +namespace cpu_features +{ +namespace +{ +void DisableHardwareCapabilities() { SetHardwareCapabilities(0, 0); } + +TEST(CpustringsPPCTest, FromHardwareCap) +{ + SetHardwareCapabilities(PPC_FEATURE_HAS_FPU | PPC_FEATURE_HAS_VSX, + PPC_FEATURE2_ARCH_3_00); + GetEmptyFilesystem(); // disabling /proc/cpuinfo + const auto info = GetPPCInfo(); + EXPECT_TRUE(info.features.fpu); + EXPECT_FALSE(info.features.mmu); + EXPECT_TRUE(info.features.vsx); + EXPECT_TRUE(info.features.arch300); + EXPECT_FALSE(info.features.power4); + EXPECT_FALSE(info.features.altivec); + EXPECT_FALSE(info.features.vcrypto); + EXPECT_FALSE(info.features.htm); +} + +TEST(CpustringsPPCTest, Blade) +{ + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(processor : 14 +cpu : POWER7 (architected), altivec supported +clock : 3000.000000MHz +revision : 2.1 (pvr 003f 0201) +processor : 15 +cpu : POWER7 (architected), altivec supported +clock : 3000.000000MHz +revision : 2.1 (pvr 003f 0201) +timebase : 512000000 +platform : pSeries +model : IBM,8406-70Y +machine : CHRP IBM,8406-70Y)"); + SetPlatformTypes("power7", "power8"); + const auto strings = GetPPCPlatformStrings(); + ASSERT_STREQ(strings.platform, "pSeries"); + ASSERT_STREQ(strings.model, "IBM,8406-70Y"); + ASSERT_STREQ(strings.machine, "CHRP IBM,8406-70Y"); + ASSERT_STREQ(strings.cpu, "POWER7 (architected), altivec supported"); + ASSERT_STREQ(strings.type.platform, "power7"); + ASSERT_STREQ(strings.type.base_platform, "power8"); +} + +TEST(CpustringsPPCTest, Firestone) +{ + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(processor : 126 +cpu : POWER8 (raw), altivec supported +clock : 2061.000000MHz +revision : 2.0 (pvr 004d 0200) +processor : 127 +cpu : POWER8 (raw), altivec supported +clock : 2061.000000MHz +revision : 2.0 (pvr 004d 0200) +timebase : 512000000 +platform : PowerNV +model : 8335-GTA +machine : PowerNV 8335-GTA +firmware : OPAL v3)"); + const auto strings = GetPPCPlatformStrings(); + ASSERT_STREQ(strings.platform, "PowerNV"); + ASSERT_STREQ(strings.model, "8335-GTA"); + ASSERT_STREQ(strings.machine, "PowerNV 8335-GTA"); + ASSERT_STREQ(strings.cpu, "POWER8 (raw), altivec supported"); +} + +TEST(CpustringsPPCTest, w8) +{ + DisableHardwareCapabilities(); + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", + R"(processor : 143 +cpu : POWER9, altivec supported +clock : 2300.000000MHz +revision : 2.2 (pvr 004e 1202) +timebase : 512000000 +platform : PowerNV +model : 0000000000000000 +machine : PowerNV 0000000000000000 +firmware : OPAL +MMU : Radix)"); + const auto strings = GetPPCPlatformStrings(); + ASSERT_STREQ(strings.platform, "PowerNV"); + ASSERT_STREQ(strings.model, "0000000000000000"); + ASSERT_STREQ(strings.machine, "PowerNV 0000000000000000"); + ASSERT_STREQ(strings.cpu, "POWER9, altivec supported"); +} + +} // namespace +} // namespace cpu_features diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_x86_test.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_x86_test.cc new file mode 100644 index 000000000..5d964ec64 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/cpuinfo_x86_test.cc @@ -0,0 +1,544 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "cpuinfo_x86.h" +#include +#include +#include +#include +#if defined(CPU_FEATURES_OS_WINDOWS) +#include // IsProcessorFeaturePresent +#endif // CPU_FEATURES_OS_WINDOWS + +#include "filesystem_for_testing.h" +#include "gtest/gtest.h" +#include "internal/cpuid_x86.h" + +namespace cpu_features +{ +class FakeCpu +{ +public: + Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) const + { + const auto itr = cpuid_leaves_.find(std::make_pair(leaf_id, ecx)); + if (itr != cpuid_leaves_.end()) + { + return itr->second; + } + return {0, 0, 0, 0}; + } + + uint32_t GetXCR0Eax() const { return xcr0_eax_; } + + void SetLeaves(std::map, Leaf> configuration) + { + cpuid_leaves_ = std::move(configuration); + } + + void SetOsBackupsExtendedRegisters(bool os_backups_extended_registers) + { + xcr0_eax_ = os_backups_extended_registers ? -1 : 0; + } + +#if defined(CPU_FEATURES_OS_DARWIN) + bool GetDarwinSysCtlByName(std::string name) const + { + return darwin_sysctlbyname_.count(name); + } + + void SetDarwinSysCtlByName(std::string name) + { + darwin_sysctlbyname_.insert(name); + } +#endif // CPU_FEATURES_OS_DARWIN + +#if defined(CPU_FEATURES_OS_WINDOWS) + bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) + { + return windows_isprocessorfeaturepresent_.count(ProcessorFeature); + } + + void SetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) + { + windows_isprocessorfeaturepresent_.insert(ProcessorFeature); + } +#endif // CPU_FEATURES_OS_WINDOWS + +private: + std::map, Leaf> cpuid_leaves_; +#if defined(CPU_FEATURES_OS_DARWIN) + std::set darwin_sysctlbyname_; +#endif // CPU_FEATURES_OS_DARWIN +#if defined(CPU_FEATURES_OS_WINDOWS) + std::set windows_isprocessorfeaturepresent_; +#endif // CPU_FEATURES_OS_WINDOWS + uint32_t xcr0_eax_; +}; + +FakeCpu* g_fake_cpu = nullptr; + +extern "C" Leaf GetCpuidLeaf(uint32_t leaf_id, int ecx) +{ + return g_fake_cpu->GetCpuidLeaf(leaf_id, ecx); +} + +extern "C" uint32_t GetXCR0Eax(void) { return g_fake_cpu->GetXCR0Eax(); } + +#if defined(CPU_FEATURES_OS_DARWIN) +extern "C" bool GetDarwinSysCtlByName(const char* name) +{ + return g_fake_cpu->GetDarwinSysCtlByName(name); +} +#endif // CPU_FEATURES_OS_DARWIN + +#if defined(CPU_FEATURES_OS_WINDOWS) +extern "C" bool GetWindowsIsProcessorFeaturePresent(DWORD ProcessorFeature) +{ + return g_fake_cpu->GetWindowsIsProcessorFeaturePresent(ProcessorFeature); +} +#endif // CPU_FEATURES_OS_WINDOWS + +namespace +{ +class CpuidX86Test : public ::testing::Test +{ +protected: + void SetUp() override { g_fake_cpu = new FakeCpu(); } + void TearDown() override { delete g_fake_cpu; } +}; + +TEST_F(CpuidX86Test, SandyBridge) +{ + g_fake_cpu->SetOsBackupsExtendedRegisters(true); + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x000206A6, 0x00100800, 0x1F9AE3BF, 0xBFEBFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + }); + const auto info = GetX86Info(); + EXPECT_STREQ(info.vendor, "GenuineIntel"); + EXPECT_EQ(info.family, 0x06); + EXPECT_EQ(info.model, 0x02A); + EXPECT_EQ(info.stepping, 0x06); + // Leaf 7 is zeroed out so none of the Leaf 7 flags are set. + const auto features = info.features; + EXPECT_FALSE(features.erms); + EXPECT_FALSE(features.avx2); + EXPECT_FALSE(features.avx512f); + EXPECT_FALSE(features.avx512cd); + EXPECT_FALSE(features.avx512er); + EXPECT_FALSE(features.avx512pf); + EXPECT_FALSE(features.avx512bw); + EXPECT_FALSE(features.avx512dq); + EXPECT_FALSE(features.avx512vl); + EXPECT_FALSE(features.avx512ifma); + EXPECT_FALSE(features.avx512vbmi); + EXPECT_FALSE(features.avx512vbmi2); + EXPECT_FALSE(features.avx512vnni); + EXPECT_FALSE(features.avx512bitalg); + EXPECT_FALSE(features.avx512vpopcntdq); + EXPECT_FALSE(features.avx512_4vnniw); + EXPECT_FALSE(features.avx512_4fmaps); + // All old cpu features should be set. + EXPECT_TRUE(features.aes); + EXPECT_TRUE(features.ssse3); + EXPECT_TRUE(features.sse4_1); + EXPECT_TRUE(features.sse4_2); + EXPECT_TRUE(features.avx); + EXPECT_FALSE(features.sha); + EXPECT_TRUE(features.popcnt); + EXPECT_FALSE(features.movbe); + EXPECT_FALSE(features.rdrnd); +} + +const int KiB = 1024; +const int MiB = 1024 * KiB; + +TEST_F(CpuidX86Test, SandyBridgeTestOsSupport) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000D, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x000206A6, 0x00100800, 0x1F9AE3BF, 0xBFEBFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + }); + // avx is disabled if os does not support backing up ymm registers. + g_fake_cpu->SetOsBackupsExtendedRegisters(false); + EXPECT_FALSE(GetX86Info().features.avx); + // avx is disabled if os does not support backing up ymm registers. + g_fake_cpu->SetOsBackupsExtendedRegisters(true); + EXPECT_TRUE(GetX86Info().features.avx); +} + +TEST_F(CpuidX86Test, SkyLake) +{ + g_fake_cpu->SetOsBackupsExtendedRegisters(true); + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}}, + }); + const auto info = GetX86Info(); + EXPECT_STREQ(info.vendor, "GenuineIntel"); + EXPECT_EQ(info.family, 0x06); + EXPECT_EQ(info.model, 0x04E); + EXPECT_EQ(info.stepping, 0x03); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_SKL); +} + +TEST_F(CpuidX86Test, Branding) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}}, + {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000121, 0x2C100000}}, + {{0x80000002, 0}, Leaf{0x65746E49, 0x2952286C, 0x726F4320, 0x4D542865}}, + {{0x80000003, 0}, Leaf{0x37692029, 0x3035362D, 0x43205530, 0x40205550}}, + {{0x80000004, 0}, Leaf{0x352E3220, 0x7A484730, 0x00000000, 0x00000000}}, + }); + char brand_string[49]; + FillX86BrandString(brand_string); + EXPECT_STREQ(brand_string, "Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz"); +} + +TEST_F(CpuidX86Test, KabyLakeCache) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}}, + {{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}}, + {{0x00000004, 1}, Leaf{0x1C004122, 0x01C0003F, 0x0000003F, 0x00000000}}, + {{0x00000004, 2}, Leaf{0x1C004143, 0x00C0003F, 0x000003FF, 0x00000000}}, + {{0x00000004, 3}, Leaf{0x1C03C163, 0x02C0003F, 0x00001FFF, 0x00000002}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}}, + {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000121, 0x2C100000}}, + {{0x80000002, 0}, Leaf{0x65746E49, 0x2952286C, 0x726F4320, 0x4D542865}}, + {{0x80000003, 0}, Leaf{0x37692029, 0x3035362D, 0x43205530, 0x40205550}}, + }); + const auto info = GetX86CacheInfo(); + EXPECT_EQ(info.size, 4); + EXPECT_EQ(info.levels[0].level, 1); + EXPECT_EQ(info.levels[0].cache_type, 1); + EXPECT_EQ(info.levels[0].cache_size, 32 * KiB); + EXPECT_EQ(info.levels[0].ways, 8); + EXPECT_EQ(info.levels[0].line_size, 64); + EXPECT_EQ(info.levels[0].tlb_entries, 64); + EXPECT_EQ(info.levels[0].partitioning, 1); + + EXPECT_EQ(info.levels[1].level, 1); + EXPECT_EQ(info.levels[1].cache_type, 2); + EXPECT_EQ(info.levels[1].cache_size, 32 * KiB); + EXPECT_EQ(info.levels[1].ways, 8); + EXPECT_EQ(info.levels[1].line_size, 64); + EXPECT_EQ(info.levels[1].tlb_entries, 64); + EXPECT_EQ(info.levels[1].partitioning, 1); + + EXPECT_EQ(info.levels[2].level, 2); + EXPECT_EQ(info.levels[2].cache_type, 3); + EXPECT_EQ(info.levels[2].cache_size, 256 * KiB); + EXPECT_EQ(info.levels[2].ways, 4); + EXPECT_EQ(info.levels[2].line_size, 64); + EXPECT_EQ(info.levels[2].tlb_entries, 1024); + EXPECT_EQ(info.levels[2].partitioning, 1); + + EXPECT_EQ(info.levels[3].level, 3); + EXPECT_EQ(info.levels[3].cache_type, 3); + EXPECT_EQ(info.levels[3].cache_size, 6 * MiB); + EXPECT_EQ(info.levels[3].ways, 12); + EXPECT_EQ(info.levels[3].line_size, 64); + EXPECT_EQ(info.levels[3].tlb_entries, 8192); + EXPECT_EQ(info.levels[3].partitioning, 1); +} + +TEST_F(CpuidX86Test, HSWCache) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000016, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x000406E3, 0x00100800, 0x7FFAFBBF, 0xBFEBFBFF}}, + {{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}}, + {{0x00000004, 1}, Leaf{0x1C004122, 0x01C0003F, 0x0000003F, 0x00000000}}, + {{0x00000004, 2}, Leaf{0x1C004143, 0x01C0003F, 0x000001FF, 0x00000000}}, + {{0x00000004, 3}, Leaf{0x1C03C163, 0x02C0003F, 0x00001FFF, 0x00000006}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x029C67AF, 0x00000000, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}}, + {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000121, 0x2C100000}}, + {{0x80000002, 0}, Leaf{0x65746E49, 0x2952286C, 0x726F4320, 0x4D542865}}, + {{0x80000003, 0}, Leaf{0x37692029, 0x3035362D, 0x43205530, 0x40205550}}, + }); + const auto info = GetX86CacheInfo(); + EXPECT_EQ(info.size, 4); + EXPECT_EQ(info.levels[0].level, 1); + EXPECT_EQ(info.levels[0].cache_type, 1); + EXPECT_EQ(info.levels[0].cache_size, 32 * KiB); + EXPECT_EQ(info.levels[0].ways, 8); + EXPECT_EQ(info.levels[0].line_size, 64); + EXPECT_EQ(info.levels[0].tlb_entries, 64); + EXPECT_EQ(info.levels[0].partitioning, 1); + + EXPECT_EQ(info.levels[1].level, 1); + EXPECT_EQ(info.levels[1].cache_type, 2); + EXPECT_EQ(info.levels[1].cache_size, 32 * KiB); + EXPECT_EQ(info.levels[1].ways, 8); + EXPECT_EQ(info.levels[1].line_size, 64); + EXPECT_EQ(info.levels[1].tlb_entries, 64); + EXPECT_EQ(info.levels[1].partitioning, 1); + + EXPECT_EQ(info.levels[2].level, 2); + EXPECT_EQ(info.levels[2].cache_type, 3); + EXPECT_EQ(info.levels[2].cache_size, 256 * KiB); + EXPECT_EQ(info.levels[2].ways, 8); + EXPECT_EQ(info.levels[2].line_size, 64); + EXPECT_EQ(info.levels[2].tlb_entries, 512); + EXPECT_EQ(info.levels[2].partitioning, 1); + + EXPECT_EQ(info.levels[3].level, 3); + EXPECT_EQ(info.levels[3].cache_type, 3); + EXPECT_EQ(info.levels[3].cache_size, 6 * MiB); + EXPECT_EQ(info.levels[3].ways, 12); + EXPECT_EQ(info.levels[3].line_size, 64); + EXPECT_EQ(info.levels[3].tlb_entries, 8192); + EXPECT_EQ(info.levels[3].partitioning, 1); +} + +// http://users.atw.hu/instlatx64/AuthenticAMD0630F81_K15_Godavari_CPUID.txt +TEST_F(CpuidX86Test, AMD_K15) +{ + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000D, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x00000001, 0}, Leaf{0x00630F81, 0x00040800, 0x3E98320B, 0x178BFBFF}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x8000001E, 0x68747541, 0x444D4163, 0x69746E65}}, + {{0x80000001, 0}, Leaf{0x00630F81, 0x10000000, 0x0FEBBFFF, 0x2FD3FBFF}}, + {{0x80000002, 0}, Leaf{0x20444D41, 0x372D3841, 0x4B303736, 0x64615220}}, + {{0x80000003, 0}, Leaf{0x206E6F65, 0x202C3752, 0x43203031, 0x75706D6F}}, + {{0x80000004, 0}, Leaf{0x43206574, 0x7365726F, 0x2B433420, 0x00204736}}, + {{0x80000005, 0}, Leaf{0xFF40FF18, 0xFF40FF30, 0x10040140, 0x60030140}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "AuthenticAMD"); + EXPECT_EQ(info.family, 0x15); + EXPECT_EQ(info.model, 0x38); + EXPECT_EQ(info.stepping, 0x01); + EXPECT_EQ(GetX86Microarchitecture(&info), + X86Microarchitecture::AMD_BULLDOZER); + + char brand_string[49]; + FillX86BrandString(brand_string); + EXPECT_STREQ(brand_string, "AMD A8-7670K Radeon R7, 10 Compute Cores 4C+6G "); +} + +// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel00106A1_Nehalem_CPUID.txt +TEST_F(CpuidX86Test, Nehalem) +{ + // Pre AVX cpus don't have xsave + g_fake_cpu->SetOsBackupsExtendedRegisters(false); +#if defined(CPU_FEATURES_OS_WINDOWS) + g_fake_cpu->SetWindowsIsProcessorFeaturePresent( + PF_XMMI_INSTRUCTIONS_AVAILABLE); + g_fake_cpu->SetWindowsIsProcessorFeaturePresent( + PF_XMMI64_INSTRUCTIONS_AVAILABLE); + g_fake_cpu->SetWindowsIsProcessorFeaturePresent( + PF_SSE3_INSTRUCTIONS_AVAILABLE); +#endif // CPU_FEATURES_OS_WINDOWS +#if defined(CPU_FEATURES_OS_DARWIN) + g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse"); + g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse2"); + g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse3"); + g_fake_cpu->SetDarwinSysCtlByName("hw.optional.supplementalsse3"); + g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_1"); + g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_2"); +#endif // CPU_FEATURES_OS_DARWIN +#if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"(processor : +flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 +)"); +#endif // CPU_FEATURES_OS_LINUX_OR_ANDROID + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x000106A2, 0x00100800, 0x00BCE3BD, 0xBFEBFBFF}}, + {{0x00000002, 0}, Leaf{0x55035A01, 0x00F0B0E3, 0x00000000, 0x09CA212C}}, + {{0x00000003, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {{0x00000004, 0}, Leaf{0x1C004121, 0x01C0003F, 0x0000003F, 0x00000000}}, + {{0x00000004, 0}, Leaf{0x1C004122, 0x00C0003F, 0x0000007F, 0x00000000}}, + {{0x00000004, 0}, Leaf{0x1C004143, 0x01C0003F, 0x000001FF, 0x00000000}}, + {{0x00000004, 0}, Leaf{0x1C03C163, 0x03C0003F, 0x00000FFF, 0x00000002}}, + {{0x00000005, 0}, Leaf{0x00000040, 0x00000040, 0x00000003, 0x00021120}}, + {{0x00000006, 0}, Leaf{0x00000001, 0x00000002, 0x00000001, 0x00000000}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {{0x00000008, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {{0x00000009, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {{0x0000000A, 0}, Leaf{0x07300403, 0x00000000, 0x00000000, 0x00000603}}, + {{0x0000000B, 0}, Leaf{0x00000001, 0x00000001, 0x00000100, 0x00000000}}, + {{0x0000000B, 0}, Leaf{0x00000004, 0x00000002, 0x00000201, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}}, + {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000001, 0x28100000}}, + {{0x80000002, 0}, Leaf{0x756E6547, 0x20656E69, 0x65746E49, 0x2952286C}}, + {{0x80000003, 0}, Leaf{0x55504320, 0x20202020, 0x20202020, 0x40202020}}, + {{0x80000004, 0}, Leaf{0x30303020, 0x20402030, 0x37382E31, 0x007A4847}}, + {{0x80000005, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {{0x80000006, 0}, Leaf{0x00000000, 0x00000000, 0x01006040, 0x00000000}}, + {{0x80000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000100}}, + {{0x80000008, 0}, Leaf{0x00003028, 0x00000000, 0x00000000, 0x00000000}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "GenuineIntel"); + EXPECT_EQ(info.family, 0x06); + EXPECT_EQ(info.model, 0x1A); + EXPECT_EQ(info.stepping, 0x02); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::INTEL_NHM); + + char brand_string[49]; + FillX86BrandString(brand_string); + EXPECT_STREQ(brand_string, "Genuine Intel(R) CPU @ 0000 @ 1.87GHz"); + + EXPECT_TRUE(info.features.sse); + EXPECT_TRUE(info.features.sse2); + EXPECT_TRUE(info.features.sse3); +#ifndef CPU_FEATURES_OS_WINDOWS + // Currently disabled on Windows as IsProcessorFeaturePresent do not support + // feature detection > sse3. + EXPECT_TRUE(info.features.ssse3); + EXPECT_TRUE(info.features.sse4_1); + EXPECT_TRUE(info.features.sse4_2); +#endif // CPU_FEATURES_OS_WINDOWS +} + +// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0030673_Silvermont3_CPUID.txt +TEST_F(CpuidX86Test, Atom) +{ + // Pre AVX cpus don't have xsave + g_fake_cpu->SetOsBackupsExtendedRegisters(false); +#if defined(CPU_FEATURES_OS_WINDOWS) + g_fake_cpu->SetWindowsIsProcessorFeaturePresent( + PF_XMMI_INSTRUCTIONS_AVAILABLE); + g_fake_cpu->SetWindowsIsProcessorFeaturePresent( + PF_XMMI64_INSTRUCTIONS_AVAILABLE); + g_fake_cpu->SetWindowsIsProcessorFeaturePresent( + PF_SSE3_INSTRUCTIONS_AVAILABLE); +#endif // CPU_FEATURES_OS_WINDOWS +#if defined(CPU_FEATURES_OS_DARWIN) + g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse"); + g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse2"); + g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse3"); + g_fake_cpu->SetDarwinSysCtlByName("hw.optional.supplementalsse3"); + g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_1"); + g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse4_2"); +#endif // CPU_FEATURES_OS_DARWIN +#if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"( +flags : fpu mmx sse sse2 sse3 ssse3 sse4_1 sse4_2 +)"); +#endif // CPU_FEATURES_OS_LINUX_OR_ANDROID + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x0000000B, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x00030673, 0x00100800, 0x41D8E3BF, 0xBFEBFBFF}}, + {{0x00000002, 0}, Leaf{0x61B3A001, 0x0000FFC2, 0x00000000, 0x00000000}}, + {{0x00000003, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {{0x00000004, 0}, Leaf{0x1C000121, 0x0140003F, 0x0000003F, 0x00000001}}, + {{0x00000004, 1}, Leaf{0x1C000122, 0x01C0003F, 0x0000003F, 0x00000001}}, + {{0x00000004, 2}, Leaf{0x1C00C143, 0x03C0003F, 0x000003FF, 0x00000001}}, + {{0x00000005, 0}, Leaf{0x00000040, 0x00000040, 0x00000003, 0x33000020}}, + {{0x00000006, 0}, Leaf{0x00000005, 0x00000002, 0x00000009, 0x00000000}}, + {{0x00000007, 0}, Leaf{0x00000000, 0x00002282, 0x00000000, 0x00000000}}, + {{0x00000008, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {{0x00000009, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {{0x0000000A, 0}, Leaf{0x07280203, 0x00000000, 0x00000000, 0x00004503}}, + {{0x0000000B, 0}, Leaf{0x00000001, 0x00000001, 0x00000100, 0x00000000}}, + {{0x0000000B, 1}, Leaf{0x00000004, 0x00000004, 0x00000201, 0x00000000}}, + {{0x80000000, 0}, Leaf{0x80000008, 0x00000000, 0x00000000, 0x00000000}}, + {{0x80000001, 0}, Leaf{0x00000000, 0x00000000, 0x00000101, 0x28100000}}, + {{0x80000002, 0}, Leaf{0x20202020, 0x6E492020, 0x286C6574, 0x43202952}}, + {{0x80000003, 0}, Leaf{0x72656C65, 0x52286E6F, 0x50432029, 0x4A202055}}, + {{0x80000004, 0}, Leaf{0x30303931, 0x20402020, 0x39392E31, 0x007A4847}}, + {{0x80000005, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000000}}, + {{0x80000006, 0}, Leaf{0x00000000, 0x00000000, 0x04008040, 0x00000000}}, + {{0x80000007, 0}, Leaf{0x00000000, 0x00000000, 0x00000000, 0x00000100}}, + {{0x80000008, 0}, Leaf{0x00003024, 0x00000000, 0x00000000, 0x00000000}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "GenuineIntel"); + EXPECT_EQ(info.family, 0x06); + EXPECT_EQ(info.model, 0x37); + EXPECT_EQ(info.stepping, 0x03); + EXPECT_EQ(GetX86Microarchitecture(&info), + X86Microarchitecture::INTEL_ATOM_SMT); + + char brand_string[49]; + FillX86BrandString(brand_string); + EXPECT_STREQ(brand_string, " Intel(R) Celeron(R) CPU J1900 @ 1.99GHz"); + + EXPECT_TRUE(info.features.sse); + EXPECT_TRUE(info.features.sse2); + EXPECT_TRUE(info.features.sse3); +#ifndef CPU_FEATURES_OS_WINDOWS + // Currently disabled on Windows as IsProcessorFeaturePresent do not support + // feature detection > sse3. + EXPECT_TRUE(info.features.ssse3); + EXPECT_TRUE(info.features.sse4_1); + EXPECT_TRUE(info.features.sse4_2); +#endif // CPU_FEATURES_OS_WINDOWS +} + +// https://github.com/InstLatx64/InstLatx64/blob/master/GenuineIntel/GenuineIntel0000673_P3_KatmaiDP_CPUID.txt +TEST_F(CpuidX86Test, P3) +{ + // Pre AVX cpus don't have xsave + g_fake_cpu->SetOsBackupsExtendedRegisters(false); +#if defined(CPU_FEATURES_OS_WINDOWS) + g_fake_cpu->SetWindowsIsProcessorFeaturePresent( + PF_XMMI_INSTRUCTIONS_AVAILABLE); +#endif // CPU_FEATURES_OS_WINDOWS +#if defined(CPU_FEATURES_OS_DARWIN) + g_fake_cpu->SetDarwinSysCtlByName("hw.optional.sse"); +#endif // CPU_FEATURES_OS_DARWIN +#if defined(CPU_FEATURES_OS_LINUX_OR_ANDROID) + auto& fs = GetEmptyFilesystem(); + fs.CreateFile("/proc/cpuinfo", R"( +flags : fpu mmx sse +)"); +#endif // CPU_FEATURES_OS_LINUX_OR_ANDROID + g_fake_cpu->SetLeaves({ + {{0x00000000, 0}, Leaf{0x00000003, 0x756E6547, 0x6C65746E, 0x49656E69}}, + {{0x00000001, 0}, Leaf{0x00000673, 0x00000000, 0x00000000, 0x0387FBFF}}, + {{0x00000002, 0}, Leaf{0x03020101, 0x00000000, 0x00000000, 0x0C040843}}, + {{0x00000003, 0}, Leaf{0x00000000, 0x00000000, 0x4CECC782, 0x00006778}}, + }); + const auto info = GetX86Info(); + + EXPECT_STREQ(info.vendor, "GenuineIntel"); + EXPECT_EQ(info.family, 0x06); + EXPECT_EQ(info.model, 0x07); + EXPECT_EQ(info.stepping, 0x03); + EXPECT_EQ(GetX86Microarchitecture(&info), X86Microarchitecture::X86_UNKNOWN); + + char brand_string[49]; + FillX86BrandString(brand_string); + EXPECT_STREQ(brand_string, ""); + + EXPECT_TRUE(info.features.mmx); + EXPECT_TRUE(info.features.sse); + EXPECT_FALSE(info.features.sse2); + EXPECT_FALSE(info.features.sse3); +#ifndef CPU_FEATURES_OS_WINDOWS + // Currently disabled on Windows as IsProcessorFeaturePresent do not support + // feature detection > sse3. + EXPECT_FALSE(info.features.ssse3); + EXPECT_FALSE(info.features.sse4_1); + EXPECT_FALSE(info.features.sse4_2); +#endif // CPU_FEATURES_OS_WINDOWS +} + +// TODO(user): test what happens when xsave/osxsave are not present. +// TODO(user): test what happens when xmm/ymm/zmm os support are not +// present. + +} // namespace +} // namespace cpu_features diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/filesystem_for_testing.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/filesystem_for_testing.cc new file mode 100644 index 000000000..2575e8da3 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/filesystem_for_testing.cc @@ -0,0 +1,104 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "filesystem_for_testing.h" +#include +#include +#include +#include +#include + +namespace cpu_features +{ +FakeFile::FakeFile(int file_descriptor, const char* content) + : file_descriptor_(file_descriptor), content_(content) {} + +FakeFile::~FakeFile() { assert(!opened_); } + +void FakeFile::Open() +{ + assert(!opened_); + opened_ = true; +} + +void FakeFile::Close() +{ + assert(opened_); + opened_ = false; +} + +int FakeFile::Read(int fd, void* buf, size_t count) +{ + assert(count < INT_MAX); + assert(fd == file_descriptor_); + const size_t remainder = content_.size() - head_index_; + const size_t read = count > remainder ? remainder : count; + memcpy(buf, content_.data() + head_index_, read); + head_index_ += read; + assert(read < INT_MAX); + return (int)read; +} + +void FakeFilesystem::Reset() { files_.clear(); } + +FakeFile* FakeFilesystem::CreateFile(const std::string& filename, + const char* content) +{ + auto& file = files_[filename]; + file = + std::unique_ptr(new FakeFile(next_file_descriptor_++, content)); + return file.get(); +} + +FakeFile* FakeFilesystem::FindFileOrNull(const std::string& filename) const +{ + const auto itr = files_.find(filename); + return itr == files_.end() ? nullptr : itr->second.get(); +} + +FakeFile* FakeFilesystem::FindFileOrDie(const int file_descriptor) const +{ + for (const auto& filename_file_pair : files_) + { + FakeFile* const file_ptr = filename_file_pair.second.get(); + if (file_ptr->GetFileDescriptor() == file_descriptor) + { + return file_ptr; + } + } + assert(false); + return nullptr; +} + +static FakeFilesystem* kFilesystem = new FakeFilesystem(); + +FakeFilesystem& GetEmptyFilesystem() +{ + kFilesystem->Reset(); + return *kFilesystem; +} + +extern "C" int CpuFeatures_OpenFile(const char* filename) +{ + auto* const file = kFilesystem->FindFileOrNull(filename); + if (file) + { + file->Open(); + return file->GetFileDescriptor(); + } + return -1; +} + +extern "C" void CpuFeatures_CloseFile(int file_descriptor) +{ + kFilesystem->FindFileOrDie(file_descriptor)->Close(); +} + +extern "C" int CpuFeatures_ReadFile(int file_descriptor, void* buffer, + size_t buffer_size) +{ + return kFilesystem->FindFileOrDie(file_descriptor) + ->Read(file_descriptor, buffer, buffer_size); +} + +} // namespace cpu_features diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/filesystem_for_testing.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/filesystem_for_testing.h new file mode 100644 index 000000000..f43994ae6 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/filesystem_for_testing.h @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +// Implements a fake filesystem, useful for tests. +#ifndef CPU_FEATURES_TEST_FILESYSTEM_FOR_TESTING_H_ +#define CPU_FEATURES_TEST_FILESYSTEM_FOR_TESTING_H_ + +#include "internal/filesystem.h" +#include +#include +#include + +namespace cpu_features +{ +class FakeFile +{ +public: + explicit FakeFile(int file_descriptor, const char* content); + ~FakeFile(); + + void Open(); + void Close(); + int Read(int fd, void* buf, size_t count); + + int GetFileDescriptor() const { return file_descriptor_; } + +private: + const int file_descriptor_; + const std::string content_; + bool opened_ = false; + size_t head_index_ = 0; +}; + +class FakeFilesystem +{ +public: + void Reset(); + FakeFile* CreateFile(const std::string& filename, const char* content); + FakeFile* FindFileOrDie(const int file_descriptor) const; + FakeFile* FindFileOrNull(const std::string& filename) const; + +private: + int next_file_descriptor_ = 0; + std::unordered_map> files_; +}; + +FakeFilesystem& GetEmptyFilesystem(); + +} // namespace cpu_features + +#endif // CPU_FEATURES_TEST_FILESYSTEM_FOR_TESTING_H_ diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/hwcaps_for_testing.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/hwcaps_for_testing.cc new file mode 100644 index 000000000..6a474108a --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/hwcaps_for_testing.cc @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "hwcaps_for_testing.h" +#include "internal/string_view.h" +#include + +namespace cpu_features +{ +namespace +{ +static auto* const g_hardware_capabilities = new HardwareCapabilities(); +static auto* const g_platform_types = new PlatformType(); +} // namespace + +void SetHardwareCapabilities(uint32_t hwcaps, uint32_t hwcaps2) +{ + g_hardware_capabilities->hwcaps = hwcaps; + g_hardware_capabilities->hwcaps2 = hwcaps2; +} + +HardwareCapabilities CpuFeatures_GetHardwareCapabilities(void) +{ + return *g_hardware_capabilities; +} + +void SetPlatformTypes(const char* platform, const char* base_platform) +{ + CpuFeatures_StringView_CopyString(str(platform), g_platform_types->platform, + sizeof(g_platform_types->platform)); + CpuFeatures_StringView_CopyString(str(base_platform), + g_platform_types->base_platform, + sizeof(g_platform_types->base_platform)); +} + +PlatformType CpuFeatures_GetPlatformType(void) { return *g_platform_types; } +} // namespace cpu_features diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/hwcaps_for_testing.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/hwcaps_for_testing.h new file mode 100644 index 000000000..327a8b42e --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/hwcaps_for_testing.h @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#ifndef CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_ +#define CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_ + +#include "internal/hwcaps.h" + +namespace cpu_features +{ +void SetHardwareCapabilities(uint32_t hwcaps, uint32_t hwcaps2); +void SetPlatformTypes(const char *platform, const char *base_platform); + +} // namespace cpu_features + +#endif // CPU_FEATURES_TEST_HWCAPS_FOR_TESTING_H_ diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/stack_line_reader_test.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/stack_line_reader_test.cc new file mode 100644 index 000000000..aecc2938e --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/stack_line_reader_test.cc @@ -0,0 +1,125 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "filesystem_for_testing.h" +#include "gtest/gtest.h" +#include "internal/stack_line_reader.h" + +namespace cpu_features +{ +bool operator==(const StringView& a, const StringView& b) +{ + return CpuFeatures_StringView_IsEquals(a, b); +} + +namespace +{ +std::string ToString(StringView view) { return {view.ptr, view.size}; } + +TEST(StackLineReaderTest, Empty) +{ + auto& fs = GetEmptyFilesystem(); + auto* file = fs.CreateFile("/proc/cpuinfo", ""); + StackLineReader reader; + StackLineReader_Initialize(&reader, file->GetFileDescriptor()); + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_TRUE(result.eof); + EXPECT_TRUE(result.full_line); + EXPECT_EQ(result.line, str("")); + } +} + +TEST(StackLineReaderTest, ManySmallLines) +{ + auto& fs = GetEmptyFilesystem(); + auto* file = fs.CreateFile("/proc/cpuinfo", "a\nb\nc"); + + StackLineReader reader; + StackLineReader_Initialize(&reader, file->GetFileDescriptor()); + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_FALSE(result.eof); + EXPECT_TRUE(result.full_line); + EXPECT_EQ(result.line, str("a")); + } + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_FALSE(result.eof); + EXPECT_TRUE(result.full_line); + EXPECT_EQ(result.line, str("b")); + } + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_TRUE(result.eof); + EXPECT_TRUE(result.full_line); + EXPECT_EQ(result.line, str("c")); + } +} + +TEST(StackLineReaderTest, TruncatedLine) +{ + auto& fs = GetEmptyFilesystem(); + auto* file = fs.CreateFile("/proc/cpuinfo", R"(First +Second +More than 16 characters, this will be truncated. +last)"); + + StackLineReader reader; + StackLineReader_Initialize(&reader, file->GetFileDescriptor()); + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_FALSE(result.eof); + EXPECT_TRUE(result.full_line); + EXPECT_EQ(result.line, str("First")); + } + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_FALSE(result.eof); + EXPECT_TRUE(result.full_line); + EXPECT_EQ(result.line, str("Second")); + } + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_FALSE(result.eof); + EXPECT_FALSE(result.full_line); + EXPECT_EQ(result.line, str("More than 16 cha")); + } + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_TRUE(result.eof); + EXPECT_TRUE(result.full_line); + EXPECT_EQ(result.line, str("last")); + } +} + +TEST(StackLineReaderTest, TruncatedLines) +{ + auto& fs = GetEmptyFilesystem(); + auto* file = fs.CreateFile("/proc/cpuinfo", R"(More than 16 characters +Another line that is too long)"); + + StackLineReader reader; + StackLineReader_Initialize(&reader, file->GetFileDescriptor()); + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_FALSE(result.eof); + EXPECT_FALSE(result.full_line); + EXPECT_EQ(result.line, str("More than 16 cha")); + } + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_FALSE(result.eof); + EXPECT_FALSE(result.full_line); + EXPECT_EQ(result.line, str("Another line tha")); + } + { + const auto result = StackLineReader_NextLine(&reader); + EXPECT_TRUE(result.eof); + EXPECT_TRUE(result.full_line); + EXPECT_EQ(result.line, str("")); + } +} + +} // namespace +} // namespace cpu_features diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/string_view_test.cc b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/string_view_test.cc new file mode 100644 index 000000000..59c906d37 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/cpu_features/test/string_view_test.cc @@ -0,0 +1,198 @@ +// SPDX-FileCopyrightText: 2017 Google LLC +// SPDX-License-Identifier: Apache-2.0 + +#include "gtest/gtest.h" +#include "internal/string_view.h" + +namespace cpu_features +{ +bool operator==(const StringView& a, const StringView& b) +{ + return CpuFeatures_StringView_IsEquals(a, b); +} + +namespace +{ +TEST(StringViewTest, Empty) +{ + EXPECT_EQ(kEmptyStringView.ptr, nullptr); + EXPECT_EQ(kEmptyStringView.size, 0); +} + +TEST(StringViewTest, Build) +{ + const auto view = str("test"); + EXPECT_EQ(view.ptr[0], 't'); + EXPECT_EQ(view.size, 4); +} + +TEST(StringViewTest, CpuFeatures_StringView_IndexOfChar) +{ + // Found. + EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 'e'), 1); + EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 't'), 0); + EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("beef"), 'e'), 1); + // Not found. + EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(str("test"), 'z'), -1); + // Empty. + EXPECT_EQ(CpuFeatures_StringView_IndexOfChar(kEmptyStringView, 'z'), -1); +} + +TEST(StringViewTest, CpuFeatures_StringView_IndexOf) +{ + // Found. + EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("es")), 1); + EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("test")), 0); + EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("tesstest"), str("test")), 4); + // Not found. + EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("test"), str("aa")), -1); + // Empty. + EXPECT_EQ(CpuFeatures_StringView_IndexOf(kEmptyStringView, str("aa")), -1); + EXPECT_EQ(CpuFeatures_StringView_IndexOf(str("aa"), kEmptyStringView), -1); +} + +TEST(StringViewTest, CpuFeatures_StringView_StartsWith) +{ + EXPECT_TRUE(CpuFeatures_StringView_StartsWith(str("test"), str("te"))); + EXPECT_TRUE(CpuFeatures_StringView_StartsWith(str("test"), str("test"))); + EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("st"))); + EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str("est"))); + EXPECT_FALSE(CpuFeatures_StringView_StartsWith(str("test"), str(""))); + EXPECT_FALSE( + CpuFeatures_StringView_StartsWith(str("test"), kEmptyStringView)); + EXPECT_FALSE( + CpuFeatures_StringView_StartsWith(kEmptyStringView, str("test"))); +} + +TEST(StringViewTest, CpuFeatures_StringView_IsEquals) +{ + EXPECT_TRUE( + CpuFeatures_StringView_IsEquals(kEmptyStringView, kEmptyStringView)); + EXPECT_TRUE(CpuFeatures_StringView_IsEquals(kEmptyStringView, str(""))); + EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str(""), kEmptyStringView)); + EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str("test"), str("test"))); + EXPECT_TRUE(CpuFeatures_StringView_IsEquals(str("a"), str("a"))); + EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), str("b"))); + EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("aa"), str("a"))); + EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), str("aa"))); + EXPECT_FALSE(CpuFeatures_StringView_IsEquals(str("a"), kEmptyStringView)); + EXPECT_FALSE(CpuFeatures_StringView_IsEquals(kEmptyStringView, str("a"))); +} + +TEST(StringViewTest, CpuFeatures_StringView_PopFront) +{ + EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 2), str("st")); + EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 0), str("test")); + EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 4), str("")); + EXPECT_EQ(CpuFeatures_StringView_PopFront(str("test"), 100), str("")); +} + +TEST(StringViewTest, CpuFeatures_StringView_PopBack) +{ + EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 2), str("te")); + EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 0), str("test")); + EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 4), str("")); + EXPECT_EQ(CpuFeatures_StringView_PopBack(str("test"), 100), str("")); +} + +TEST(StringViewTest, CpuFeatures_StringView_KeepFront) +{ + EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 2), str("te")); + EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 0), str("")); + EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 4), str("test")); + EXPECT_EQ(CpuFeatures_StringView_KeepFront(str("test"), 6), str("test")); +} + +TEST(StringViewTest, CpuFeatures_StringView_Front) +{ + EXPECT_EQ(CpuFeatures_StringView_Front(str("apple")), 'a'); + EXPECT_EQ(CpuFeatures_StringView_Front(str("a")), 'a'); +} + +TEST(StringViewTest, CpuFeatures_StringView_Back) +{ + EXPECT_EQ(CpuFeatures_StringView_Back(str("apple")), 'e'); + EXPECT_EQ(CpuFeatures_StringView_Back(str("a")), 'a'); +} + +TEST(StringViewTest, CpuFeatures_StringView_TrimWhitespace) +{ + EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str(" first middle last ")), + str("first middle last")); + EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str("first middle last ")), + str("first middle last")); + EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str(" first middle last")), + str("first middle last")); + EXPECT_EQ(CpuFeatures_StringView_TrimWhitespace(str("first middle last")), + str("first middle last")); +} + +TEST(StringViewTest, CpuFeatures_StringView_ParsePositiveNumber) +{ + EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("42")), 42); + EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2a")), 42); + EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2A")), 42); + EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2A2a")), 10794); + EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("0x2a2A")), 10794); + + EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("-10")), -1); + EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("-0x2A")), -1); + EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("abc")), -1); + EXPECT_EQ(CpuFeatures_StringView_ParsePositiveNumber(str("")), -1); +} + +TEST(StringViewTest, CpuFeatures_StringView_CopyString) +{ + char buf[4]; + buf[0] = 'X'; + + // Empty + CpuFeatures_StringView_CopyString(str(""), buf, sizeof(buf)); + EXPECT_STREQ(buf, ""); + + // Less + CpuFeatures_StringView_CopyString(str("a"), buf, sizeof(buf)); + EXPECT_STREQ(buf, "a"); + + // exact + CpuFeatures_StringView_CopyString(str("abc"), buf, sizeof(buf)); + EXPECT_STREQ(buf, "abc"); + + // More + CpuFeatures_StringView_CopyString(str("abcd"), buf, sizeof(buf)); + EXPECT_STREQ(buf, "abc"); +} + +TEST(StringViewTest, CpuFeatures_StringView_HasWord) +{ + // Find flags at beginning, middle and end. + EXPECT_TRUE( + CpuFeatures_StringView_HasWord(str("first middle last"), "first")); + EXPECT_TRUE( + CpuFeatures_StringView_HasWord(str("first middle last"), "middle")); + EXPECT_TRUE(CpuFeatures_StringView_HasWord(str("first middle last"), "last")); + // Do not match partial flags + EXPECT_FALSE( + CpuFeatures_StringView_HasWord(str("first middle last"), "irst")); + EXPECT_FALSE(CpuFeatures_StringView_HasWord(str("first middle last"), "mid")); + EXPECT_FALSE(CpuFeatures_StringView_HasWord(str("first middle last"), "las")); +} + +TEST(StringViewTest, CpuFeatures_StringView_GetAttributeKeyValue) +{ + const StringView line = str(" key : first middle last "); + StringView key, value; + EXPECT_TRUE(CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)); + EXPECT_EQ(key, str("key")); + EXPECT_EQ(value, str("first middle last")); +} + +TEST(StringViewTest, FailingGetAttributeKeyValue) +{ + const StringView line = str("key first middle last"); + StringView key, value; + EXPECT_FALSE(CpuFeatures_StringView_GetAttributeKeyValue(line, &key, &value)); +} + +} // namespace +} // namespace cpu_features diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/gen/archs.xml b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/gen/archs.xml index 13dcea3d4..cde79793b 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/gen/archs.xml +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/gen/archs.xml @@ -20,7 +20,7 @@ -funsafe-math-optimizations -funsafe-math-optimizations 16 - + @@ -29,14 +29,14 @@ -mfpu=neon -funsafe-math-optimizations 16 - + -funsafe-math-optimizations -funsafe-math-optimizations 16 - + @@ -45,57 +45,27 @@ - - 0x80000001 - - - 3 - 0x80000001 - 29 - + + + + + + + -m64 -m64 - - - 3 - 0x80000001 - 31 - - -m3dnow - -m3dnow - 8 - - - - - 3 - 0x80000001 - 5 - - -msse4.2 - -msse4.2 - 16 - - - - 2 - 0x00000001 - 23 - + -mpopcnt -mpopcnt /arch:AVX - - 3 - 0x00000001 - 23 - + -mmmx -mmmx /arch:SSE @@ -103,11 +73,7 @@ - - 2 - 0x00000001 - 12 - + -mfma -mfma /arch:AVX2 @@ -115,11 +81,7 @@ - - 3 - 0x00000001 - 25 - + -msse -msse /arch:SSE @@ -129,11 +91,7 @@ - - 3 - 0x00000001 - 26 - + -msse2 -msse2 /arch:SSE2 @@ -148,11 +106,7 @@ - - 2 - 0x00000001 - 0 - + -msse3 -msse3 /arch:AVX @@ -162,11 +116,7 @@ - - 2 - 0x00000001 - 9 - + -mssse3 -mssse3 /arch:AVX @@ -174,22 +124,14 @@ - - 2 - 0x80000001 - 6 - + -msse4a -msse4a 16 - - 2 - 0x00000001 - 19 - + -msse4.1 -msse4.1 /arch:AVX @@ -197,11 +139,7 @@ - - 2 - 0x00000001 - 20 - + -msse4.2 -msse4.2 /arch:AVX @@ -209,19 +147,7 @@ - - 2 - 0x00000001 - 28 - - - - 2 - 0x00000001 - 27 - - - + -mavx -mavx /arch:AVX @@ -229,20 +155,7 @@ - - 7 - 0 - 1 - 5 - - - - 2 - 0x00000001 - 27 - - - + -mavx2 -mavx2 /arch:AVX2 @@ -250,21 +163,7 @@ - - - 7 - 0 - 1 - 16 - - - - 2 - 0x00000001 - 27 - - - + -mavx512f -mavx512f /arch:AVX512F @@ -272,21 +171,7 @@ - - - 7 - 0 - 1 - 28 - - - - 2 - 0x00000001 - 27 - - - + -mavx512cd -mavx512cd /arch:AVX512CD diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/gen/archs_old.xml b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/gen/archs_old.xml new file mode 100644 index 000000000..13dcea3d4 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/gen/archs_old.xml @@ -0,0 +1,296 @@ + + + + + + + + + + -mfloat-abi=softfp + -mfloat-abi=softfp + + + + -mfloat-abi=hard + -mfloat-abi=hard + + + + -funsafe-math-optimizations + -funsafe-math-optimizations + 16 + + + + + -mfpu=neon + -funsafe-math-optimizations + -mfpu=neon + -funsafe-math-optimizations + 16 + + + + + -funsafe-math-optimizations + -funsafe-math-optimizations + 16 + + + + + -m32 + -m32 + + + + + 0x80000001 + + + 3 + 0x80000001 + 29 + + -m64 + -m64 + + + + + 3 + 0x80000001 + 31 + + -m3dnow + -m3dnow + 8 + + + + + 3 + 0x80000001 + 5 + + -msse4.2 + -msse4.2 + 16 + + + + + 2 + 0x00000001 + 23 + + -mpopcnt + -mpopcnt + /arch:AVX + + + + + 3 + 0x00000001 + 23 + + -mmmx + -mmmx + /arch:SSE + 8 + + + + + 2 + 0x00000001 + 12 + + -mfma + -mfma + /arch:AVX2 + 32 + + + + + 3 + 0x00000001 + 25 + + -msse + -msse + /arch:SSE + _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); + xmmintrin.h + 16 + + + + + 3 + 0x00000001 + 26 + + -msse2 + -msse2 + /arch:SSE2 + 16 + + + + + + + + + + + + 2 + 0x00000001 + 0 + + -msse3 + -msse3 + /arch:AVX + _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); + pmmintrin.h + 16 + + + + + 2 + 0x00000001 + 9 + + -mssse3 + -mssse3 + /arch:AVX + 16 + + + + + 2 + 0x80000001 + 6 + + -msse4a + -msse4a + 16 + + + + + 2 + 0x00000001 + 19 + + -msse4.1 + -msse4.1 + /arch:AVX + 16 + + + + + 2 + 0x00000001 + 20 + + -msse4.2 + -msse4.2 + /arch:AVX + 16 + + + + + 2 + 0x00000001 + 28 + + + + 2 + 0x00000001 + 27 + + + + -mavx + -mavx + /arch:AVX + 32 + + + + + 7 + 0 + 1 + 5 + + + + 2 + 0x00000001 + 27 + + + + -mavx2 + -mavx2 + /arch:AVX2 + 32 + + + + + + 7 + 0 + 1 + 16 + + + + 2 + 0x00000001 + 27 + + + + -mavx512f + -mavx512f + /arch:AVX512F + 64 + + + + + + 7 + 0 + 1 + 28 + + + + 2 + 0x00000001 + 27 + + + + -mavx512cd + -mavx512cd + /arch:AVX512CD + 64 + + + diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/gen/volk_gnsssdr_arch_defs.py b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/gen/volk_gnsssdr_arch_defs.py.in similarity index 96% rename from src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/gen/volk_gnsssdr_arch_defs.py rename to src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/gen/volk_gnsssdr_arch_defs.py.in index 22c33737b..e9d61a591 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/gen/volk_gnsssdr_arch_defs.py +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/gen/volk_gnsssdr_arch_defs.py.in @@ -53,7 +53,7 @@ def register_arch(**kwargs): from xml.dom import minidom import os gendir = os.path.dirname(__file__) -archs_xml = minidom.parse(os.path.join(gendir, 'archs.xml')).getElementsByTagName('arch') +archs_xml = minidom.parse(os.path.join(gendir, '@VOLK_GNSSSSDR_ARCHS_XML_FILE@')).getElementsByTagName('arch') for arch_xml in archs_xml: kwargs = dict() for attr in arch_xml.attributes.keys(): diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/CMakeLists.txt b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/CMakeLists.txt index 00c50bd7e..8e33f02aa 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/CMakeLists.txt +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/lib/CMakeLists.txt @@ -42,6 +42,13 @@ if(MSVC) # its not set otherwise set(COMPILER_NAME MSVC) endif() +# Assume "AppleClang == Clang". +string(TOLOWER ${COMPILER_NAME} COMPILER_NAME_LOWER) +string(REGEX MATCH "clang" COMPILER_NAME_LOWER ${COMPILER_NAME_LOWER}) +if(${COMPILER_NAME_LOWER} MATCHES "clang") + set(COMPILER_NAME "Clang") +endif() + message(STATUS "Compiler name: ${COMPILER_NAME}") if(NOT DEFINED COMPILER_NAME) @@ -82,6 +89,16 @@ endif() if(NOT PYTHON_DASH_B) set(PYTHON_DASH_B "") endif() +if(USE_CPU_FEATURES) + set(VOLK_GNSSSSDR_ARCHS_XML_FILE "archs.xml") +else() + set(VOLK_GNSSSSDR_ARCHS_XML_FILE "archs_old.xml") +endif() +configure_file(${PROJECT_SOURCE_DIR}/gen/volk_gnsssdr_arch_defs.py.in + ${PROJECT_SOURCE_DIR}/gen/volk_gnsssdr_arch_defs.py + @ONLY +) + execute_process( COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${PROJECT_SOURCE_DIR}/gen/volk_gnsssdr_compile_utils.py @@ -133,33 +150,8 @@ endmacro() # the xgetbv instruction, or {if not cross-compiling and the xgetbv # executable does not function correctly}. ######################################################################## -set(HAVE_XGETBV 0) set(HAVE_AVX_CVTPI32_PS 0) if(CPU_IS_x86) - # check to see if the compiler/linker works with xgetb instruction - if(NOT MSVC) - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv.c "#include \n unsigned long long _xgetbv(unsigned int index) { unsigned int eax, edx; __VOLK_ASM __VOLK_VOLATILE(\"xgetbv\" : \"=a\"(eax), \"=d\"(edx) : \"c\"(index)); return ((unsigned long long)edx << 32) | eax; } int main (void) { (void) _xgetbv(0); return (0); }") - set(_AUX_INCLUDE_FLAG -I${PROJECT_SOURCE_DIR}/include) - else() - # MSVC defines an intrinsic - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv.c "#include \n #include \n int main() { int avxSupported = 0; \n#if (_MSC_FULL_VER >= 160040219) \nint cpuInfo[4]; __cpuid(cpuInfo, 1);\nif ((cpuInfo[2] & (1 << 27) || 0) && (cpuInfo[2] & (1 << 28) || 0)) \n{\nunsigned long long xcrFeatureMask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);\n avxSupported = (xcrFeatureMask & 0x6) == 6;}\n#endif \n return 1- avxSupported; }") - endif() - execute_process(COMMAND ${CMAKE_C_COMPILER} ${_AUX_INCLUDE_FLAG} -o - ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv - ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv.c - OUTPUT_QUIET ERROR_QUIET - RESULT_VARIABLE avx_compile_result - ) - if(NOT ${avx_compile_result} EQUAL 0) - overrule_arch(avx "Compiler or linker missing xgetbv instruction") - else() - # compiler/linker seems to work; assume working - set(HAVE_XGETBV 1) - endif() - file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv - ${CMAKE_CURRENT_BINARY_DIR}/test_xgetbv.c - ) - ######################################################################### # eliminate AVX if cvtpi32_ps intrinsic fails like some versions of clang ######################################################################### @@ -205,10 +197,6 @@ if(CPU_IS_x86) endif() endif() -if(${HAVE_XGETBV}) - add_definitions(-DHAVE_XGETBV) -endif() - if(${HAVE_AVX_CVTPI32_PS}) add_definitions(-DHAVE_AVX_CVTPI32_PS) endif() @@ -338,6 +326,11 @@ message(STATUS "Available machines: ${available_machines}") # dependencies are all python, xml, and header implementation files file(GLOB xml_files ${PROJECT_SOURCE_DIR}/gen/*.xml) +if(USE_CPU_FEATURES) + list(REMOVE_ITEM xml_files ${PROJECT_SOURCE_DIR}/gen/archs_old.xml) +else() + list(REMOVE_ITEM xml_files ${PROJECT_SOURCE_DIR}/gen/archs.xml) +endif() list(SORT xml_files) file(GLOB py_files ${PROJECT_SOURCE_DIR}/gen/*.py) list(SORT py_files) @@ -361,7 +354,11 @@ gen_template(${PROJECT_SOURCE_DIR}/tmpl/volk_gnsssdr.tmpl.h ${PROJE gen_template(${PROJECT_SOURCE_DIR}/tmpl/volk_gnsssdr.tmpl.c ${PROJECT_BINARY_DIR}/lib/volk_gnsssdr.c) gen_template(${PROJECT_SOURCE_DIR}/tmpl/volk_gnsssdr_typedefs.tmpl.h ${PROJECT_BINARY_DIR}/include/volk_gnsssdr/volk_gnsssdr_typedefs.h) gen_template(${PROJECT_SOURCE_DIR}/tmpl/volk_gnsssdr_cpu.tmpl.h ${PROJECT_BINARY_DIR}/include/volk_gnsssdr/volk_gnsssdr_cpu.h) -gen_template(${PROJECT_SOURCE_DIR}/tmpl/volk_gnsssdr_cpu.tmpl.c ${PROJECT_BINARY_DIR}/lib/volk_gnsssdr_cpu.c) +if(USE_CPU_FEATURES) + gen_template(${PROJECT_SOURCE_DIR}/tmpl/volk_gnsssdr_cpu.tmpl.c ${PROJECT_BINARY_DIR}/lib/volk_gnsssdr_cpu.c) +else() + gen_template(${PROJECT_SOURCE_DIR}/tmpl/volk_gnsssdr_cpu.tmpl.old.c ${PROJECT_BINARY_DIR}/lib/volk_gnsssdr_cpu.c) +endif() gen_template(${PROJECT_SOURCE_DIR}/tmpl/volk_gnsssdr_config_fixed.tmpl.h ${PROJECT_BINARY_DIR}/include/volk_gnsssdr/volk_gnsssdr_config_fixed.h) gen_template(${PROJECT_SOURCE_DIR}/tmpl/volk_gnsssdr_machines.tmpl.h ${PROJECT_BINARY_DIR}/lib/volk_gnsssdr_machines.h) gen_template(${PROJECT_SOURCE_DIR}/tmpl/volk_gnsssdr_machines.tmpl.c ${PROJECT_BINARY_DIR}/lib/volk_gnsssdr_machines.c) @@ -553,6 +550,12 @@ if(NOT (CMAKE_GENERATOR STREQUAL Xcode)) PRIVATE ${CMAKE_CURRENT_BINARY_DIR} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ) + if(USE_CPU_FEATURES) + target_include_directories(volk_gnsssdr_obj + PRIVATE + $ + ) + endif() # Configure object target properties if(NOT MSVC) set_target_properties(volk_gnsssdr_obj PROPERTIES COMPILE_FLAGS "-fPIC") @@ -565,7 +568,14 @@ if(CMAKE_GENERATOR STREQUAL Xcode) else() add_library(volk_gnsssdr SHARED $) endif() -target_link_libraries(volk_gnsssdr PUBLIC ${volk_gnsssdr_libraries}) +if(USE_CPU_FEATURES) + target_link_libraries(volk_gnsssdr + PUBLIC ${volk_gnsssdr_libraries} + PRIVATE cpu_features + ) +else() + target_link_libraries(volk_gnsssdr PUBLIC ${volk_gnsssdr_libraries}) +endif() target_include_directories(volk_gnsssdr PUBLIC $ PUBLIC $ @@ -574,7 +584,12 @@ target_include_directories(volk_gnsssdr PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} PUBLIC $ ) - +if(USE_CPU_FEATURES) + target_include_directories(volk_gnsssdr + PRIVATE + $ + ) +endif() # Configure target properties if(NOT MSVC) target_link_libraries(volk_gnsssdr PUBLIC m) @@ -597,6 +612,11 @@ if(ENABLE_STATIC_LIBS) else() add_library(volk_gnsssdr_static STATIC $) endif() + if(USE_CPU_FEATURES) + target_link_libraries(volk_gnsssdr_static + PRIVATE cpu_features + ) + endif() target_link_libraries(volk_gnsssdr_static PUBLIC ${volk_gnsssdr_libraries} pthread) if(NOT MSVC) target_link_libraries(volk_gnsssdr_static PUBLIC m) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/tmpl/volk_gnsssdr_cpu.tmpl.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/tmpl/volk_gnsssdr_cpu.tmpl.c index 65af6b623..4af4031de 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/tmpl/volk_gnsssdr_cpu.tmpl.c +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/tmpl/volk_gnsssdr_cpu.tmpl.c @@ -14,204 +14,40 @@ #include // clang-format on +#include "cpu_features_macros.h" +#if defined(CPU_FEATURES_ARCH_X86) +#include "cpuinfo_x86.h" +#elif defined(CPU_FEATURES_ARCH_ARM) +#include "cpuinfo_arm.h" +#elif defined(CPU_FEATURES_ARCH_AARCH64) +#include "cpuinfo_aarch64.h" +#elif defined(CPU_FEATURES_ARCH_MIPS) +#include "cpuinfo_mips.h" +#elif defined(CPU_FEATURES_ARCH_PPC) +#include "cpuinfo_ppc.h" +#endif + +// This is required for MSVC +#if defined(__cplusplus) +using namespace cpu_features; +#endif + struct VOLK_CPU volk_gnsssdr_cpu; -#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64) -#define VOLK_CPU_x86 -#endif - -#if defined(VOLK_CPU_x86) - -//implement get cpuid for gcc compilers using a system or local copy of cpuid.h -#if defined(__GNUC__) -#include -#define cpuid_x86(op, r) __get_cpuid(op, (unsigned int *)r + 0, (unsigned int *)r + 1, (unsigned int *)r + 2, (unsigned int *)r + 3) -#define cpuid_x86_count(op, count, regs) __cpuid_count(op, count, *((unsigned int *)regs), *((unsigned int *)regs + 1), *((unsigned int *)regs + 2), *((unsigned int *)regs + 3)) - -/* Return Intel AVX extended CPU capabilities register. - * This function will bomb on non-AVX-capable machines, so - * check for AVX capability before executing. - */ -#if ((__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 2) || (__clang_major__ >= 3)) && defined(HAVE_XGETBV) -static inline unsigned long long _xgetbv(unsigned int index) -{ - unsigned int eax, edx; - __VOLK_ASM __VOLK_VOLATILE("xgetbv" - : "=a"(eax), "=d"(edx) - : "c"(index)); - return ((unsigned long long)edx << 32) | eax; -} -#define __xgetbv() _xgetbv(0) -#else -#define __xgetbv() 0 -#endif - -//implement get cpuid for MSVC compilers using __cpuid intrinsic -#elif defined(_MSC_VER) && defined(HAVE_INTRIN_H) -#include -#define cpuid_x86(op, r) __cpuid(((int *)r), op) -#define cpuid_x86_count(op, count, regs) __cpuidex((int *)regs, op, count) - -#if defined(_XCR_XFEATURE_ENABLED_MASK) -#define __xgetbv() _xgetbv(_XCR_XFEATURE_ENABLED_MASK) -#else -#define __xgetbv() 0 -#endif - -#else -#error "A get cpuid for volk_gnsssdr is not available on this compiler..." -#endif //defined(__GNUC__) - -#endif //defined(VOLK_CPU_x86) - -static inline unsigned int cpuid_count_x86_bit(unsigned int level, unsigned int count, unsigned int reg, unsigned int bit) -{ -#if defined(VOLK_CPU_x86) - unsigned int regs[4] = {0}; - cpuid_x86_count(level, count, regs); - return regs[reg] >> bit & 0x01; -#else - return 0; -#endif -} - -static inline unsigned int cpuid_x86_bit(unsigned int reg, unsigned int op, unsigned int bit) -{ -#if defined(VOLK_CPU_x86) - unsigned int regs[4]; - memset(regs, 0, sizeof(unsigned int) * 4); - cpuid_x86(op, regs); - return regs[reg] >> bit & 0x01; -#else - return 0; -#endif -} - -static inline unsigned int check_extended_cpuid(unsigned int val) -{ -#if defined(VOLK_CPU_x86) - unsigned int regs[4]; - memset(regs, 0, sizeof(unsigned int) * 4); - cpuid_x86(0x80000000, regs); - return regs[0] >= val; -#else - return 0; -#endif -} - -static inline unsigned int get_avx_enabled(void) -{ -#if defined(VOLK_CPU_x86) - return __xgetbv() & 0x6; -#else - return 0; -#endif -} - -static inline unsigned int get_avx2_enabled(void) -{ -#if defined(VOLK_CPU_x86) - return __xgetbv() & 0x6; -#else - return 0; -#endif -} - -static inline unsigned int get_avx512_enabled(void) -{ -#if defined(VOLK_CPU_x86) - return __xgetbv() & 0xE6; //check for zmm, xmm and ymm regs -#else - return 0; -#endif -} - -//neon detection is linux specific -#if defined(__arm__) && defined(__linux__) -#include -#include -#include -#define VOLK_CPU_ARMV7 -#endif - -static int has_neonv7(void) -{ -#if defined(VOLK_CPU_ARMV7) - FILE *auxvec_f; - unsigned long auxvec[2]; - unsigned int found_neon = 0; - auxvec_f = fopen("/proc/self/auxv", "rb"); - if (!auxvec_f) return 0; - - size_t r = 1; - //so auxv is basically 32b of ID and 32b of value - //so it goes like this - while (!found_neon && r) - { - r = fread(auxvec, sizeof(unsigned long), 2, auxvec_f); - if ((auxvec[0] == AT_HWCAP) && (auxvec[1] & HWCAP_NEON)) - found_neon = 1; - } - - fclose(auxvec_f); - return found_neon; -#else - return 0; -#endif -} - -//\todo: Fix this to really check for neon on aarch64 -//neon detection is linux specific -#if defined(__aarch64__) && defined(__linux__) -#include -#include -#include -#define VOLK_CPU_ARMV8 -#endif - -static int has_neonv8(void) -{ -#if defined(VOLK_CPU_ARMV8) - FILE *auxvec_f; - unsigned long auxvec[2]; - unsigned int found_neon = 0; - auxvec_f = fopen("/proc/self/auxv", "rb"); - if (!auxvec_f) return 0; - - size_t r = 1; - //so auxv is basically 32b of ID and 32b of value - //so it goes like this - while (!found_neon && r) - { - r = fread(auxvec, sizeof(unsigned long), 2, auxvec_f); - if ((auxvec[0] == AT_HWCAP) && (auxvec[1] & HWCAP_ASIMD)) - found_neon = 1; - } - - fclose(auxvec_f); - return found_neon; -#else - return 0; -#endif -} - -static int has_neon(void) -{ -#if defined(VOLK_CPU_ARMV8) || defined(VOLK_CPU_ARMV7) - if (has_neonv7() || has_neonv8()) - return 1; - else - return 0; -#else - return 0; -#endif -} // clang-format off %for arch in archs: static int i_can_has_${arch.name} (void) { %for check, params in arch.checks: - if (${check}(<% joined_params = ', '.join(params)%>${joined_params}) == 0) return 0; + %if "neon" in arch.name: +#if defined(CPU_FEATURES_ARCH_ARM) + if (GetArmInfo().features.${check} == 0){ return 0; } +#endif + %else: +#if defined(CPU_FEATURES_ARCH_X86) + if (GetX86Info().features.${check} == 0){ return 0; } +#endif + %endif %endfor return 1; } diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/tmpl/volk_gnsssdr_cpu.tmpl.old.c b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/tmpl/volk_gnsssdr_cpu.tmpl.old.c new file mode 100644 index 000000000..65af6b623 --- /dev/null +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/tmpl/volk_gnsssdr_cpu.tmpl.old.c @@ -0,0 +1,259 @@ +/* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software-defined Global Navigation Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +// clang-format off +#include +#include +#include +#include +// clang-format on + +struct VOLK_CPU volk_gnsssdr_cpu; + +#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64) +#define VOLK_CPU_x86 +#endif + +#if defined(VOLK_CPU_x86) + +//implement get cpuid for gcc compilers using a system or local copy of cpuid.h +#if defined(__GNUC__) +#include +#define cpuid_x86(op, r) __get_cpuid(op, (unsigned int *)r + 0, (unsigned int *)r + 1, (unsigned int *)r + 2, (unsigned int *)r + 3) +#define cpuid_x86_count(op, count, regs) __cpuid_count(op, count, *((unsigned int *)regs), *((unsigned int *)regs + 1), *((unsigned int *)regs + 2), *((unsigned int *)regs + 3)) + +/* Return Intel AVX extended CPU capabilities register. + * This function will bomb on non-AVX-capable machines, so + * check for AVX capability before executing. + */ +#if ((__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 2) || (__clang_major__ >= 3)) && defined(HAVE_XGETBV) +static inline unsigned long long _xgetbv(unsigned int index) +{ + unsigned int eax, edx; + __VOLK_ASM __VOLK_VOLATILE("xgetbv" + : "=a"(eax), "=d"(edx) + : "c"(index)); + return ((unsigned long long)edx << 32) | eax; +} +#define __xgetbv() _xgetbv(0) +#else +#define __xgetbv() 0 +#endif + +//implement get cpuid for MSVC compilers using __cpuid intrinsic +#elif defined(_MSC_VER) && defined(HAVE_INTRIN_H) +#include +#define cpuid_x86(op, r) __cpuid(((int *)r), op) +#define cpuid_x86_count(op, count, regs) __cpuidex((int *)regs, op, count) + +#if defined(_XCR_XFEATURE_ENABLED_MASK) +#define __xgetbv() _xgetbv(_XCR_XFEATURE_ENABLED_MASK) +#else +#define __xgetbv() 0 +#endif + +#else +#error "A get cpuid for volk_gnsssdr is not available on this compiler..." +#endif //defined(__GNUC__) + +#endif //defined(VOLK_CPU_x86) + +static inline unsigned int cpuid_count_x86_bit(unsigned int level, unsigned int count, unsigned int reg, unsigned int bit) +{ +#if defined(VOLK_CPU_x86) + unsigned int regs[4] = {0}; + cpuid_x86_count(level, count, regs); + return regs[reg] >> bit & 0x01; +#else + return 0; +#endif +} + +static inline unsigned int cpuid_x86_bit(unsigned int reg, unsigned int op, unsigned int bit) +{ +#if defined(VOLK_CPU_x86) + unsigned int regs[4]; + memset(regs, 0, sizeof(unsigned int) * 4); + cpuid_x86(op, regs); + return regs[reg] >> bit & 0x01; +#else + return 0; +#endif +} + +static inline unsigned int check_extended_cpuid(unsigned int val) +{ +#if defined(VOLK_CPU_x86) + unsigned int regs[4]; + memset(regs, 0, sizeof(unsigned int) * 4); + cpuid_x86(0x80000000, regs); + return regs[0] >= val; +#else + return 0; +#endif +} + +static inline unsigned int get_avx_enabled(void) +{ +#if defined(VOLK_CPU_x86) + return __xgetbv() & 0x6; +#else + return 0; +#endif +} + +static inline unsigned int get_avx2_enabled(void) +{ +#if defined(VOLK_CPU_x86) + return __xgetbv() & 0x6; +#else + return 0; +#endif +} + +static inline unsigned int get_avx512_enabled(void) +{ +#if defined(VOLK_CPU_x86) + return __xgetbv() & 0xE6; //check for zmm, xmm and ymm regs +#else + return 0; +#endif +} + +//neon detection is linux specific +#if defined(__arm__) && defined(__linux__) +#include +#include +#include +#define VOLK_CPU_ARMV7 +#endif + +static int has_neonv7(void) +{ +#if defined(VOLK_CPU_ARMV7) + FILE *auxvec_f; + unsigned long auxvec[2]; + unsigned int found_neon = 0; + auxvec_f = fopen("/proc/self/auxv", "rb"); + if (!auxvec_f) return 0; + + size_t r = 1; + //so auxv is basically 32b of ID and 32b of value + //so it goes like this + while (!found_neon && r) + { + r = fread(auxvec, sizeof(unsigned long), 2, auxvec_f); + if ((auxvec[0] == AT_HWCAP) && (auxvec[1] & HWCAP_NEON)) + found_neon = 1; + } + + fclose(auxvec_f); + return found_neon; +#else + return 0; +#endif +} + +//\todo: Fix this to really check for neon on aarch64 +//neon detection is linux specific +#if defined(__aarch64__) && defined(__linux__) +#include +#include +#include +#define VOLK_CPU_ARMV8 +#endif + +static int has_neonv8(void) +{ +#if defined(VOLK_CPU_ARMV8) + FILE *auxvec_f; + unsigned long auxvec[2]; + unsigned int found_neon = 0; + auxvec_f = fopen("/proc/self/auxv", "rb"); + if (!auxvec_f) return 0; + + size_t r = 1; + //so auxv is basically 32b of ID and 32b of value + //so it goes like this + while (!found_neon && r) + { + r = fread(auxvec, sizeof(unsigned long), 2, auxvec_f); + if ((auxvec[0] == AT_HWCAP) && (auxvec[1] & HWCAP_ASIMD)) + found_neon = 1; + } + + fclose(auxvec_f); + return found_neon; +#else + return 0; +#endif +} + +static int has_neon(void) +{ +#if defined(VOLK_CPU_ARMV8) || defined(VOLK_CPU_ARMV7) + if (has_neonv7() || has_neonv8()) + return 1; + else + return 0; +#else + return 0; +#endif +} +// clang-format off + +%for arch in archs: +static int i_can_has_${arch.name} (void) { + %for check, params in arch.checks: + if (${check}(<% joined_params = ', '.join(params)%>${joined_params}) == 0) return 0; + %endfor + return 1; +} +%endfor + +#if defined(HAVE_FENV_H) + #if defined(FE_TONEAREST) + #include + static inline void set_float_rounding(void){ + fesetround(FE_TONEAREST); + } + #else + static inline void set_float_rounding(void){ + //do nothing + } + #endif +#elif defined(_MSC_VER) + #include + static inline void set_float_rounding(void){ + unsigned int cwrd; + _controlfp_s(&cwrd, 0, 0); + _controlfp_s(&cwrd, _RC_NEAR, _MCW_RC); + } +#else + static inline void set_float_rounding(void){ + //do nothing + } +#endif + +void volk_gnsssdr_cpu_init() { + %for arch in archs: + volk_gnsssdr_cpu.has_${arch.name} = &i_can_has_${arch.name}; + %endfor + set_float_rounding(); +} + +unsigned int volk_gnsssdr_get_lvarch() { + unsigned int retval = 0; + volk_gnsssdr_cpu_init(); + %for arch in archs: + retval += volk_gnsssdr_cpu.has_${arch.name}() << LV_${arch.name.upper()}; + %endfor + return retval; +} +// clang-format on