From 4c2b0fbc4563c02832dfe63851333bc5a9fd0390 Mon Sep 17 00:00:00 2001 From: Anthony Arnold Date: Thu, 18 Sep 2014 00:50:44 +1000 Subject: [PATCH 1/3] Testing for ARM and SSE to compile for armhf --- CMakeLists.txt | 46 +++++++--- cmake/Modules/TestForARM.cmake | 83 +++++++++++++++++++ cmake/Modules/TestForSSE.cmake | 36 ++++++++ .../gps_l1_ca_dll_pll_optim_tracking_cc.cc | 2 +- src/algorithms/tracking/libs/CMakeLists.txt | 4 + src/algorithms/tracking/libs/correlator.cc | 4 +- src/algorithms/tracking/libs/correlator.h | 5 +- 7 files changed, 164 insertions(+), 16 deletions(-) create mode 100644 cmake/Modules/TestForARM.cmake create mode 100644 cmake/Modules/TestForSSE.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index b31b4b4ec..c1d1b287d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,8 @@ cmake_minimum_required(VERSION 2.8) project(gnss-sdr CXX C) list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) file(RELATIVE_PATH RELATIVE_CMAKE_CALL ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) +include(TestForARM) +include(TestForSSE) ######################################################################## @@ -71,6 +73,7 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") else(ARCH_64BITS) set(ARCH_ "(32 bits)") endif(ARCH_64BITS) + if(EXISTS "/etc/lsb-release") execute_process(COMMAND cat /etc/lsb-release COMMAND grep DISTRIB_ID @@ -526,6 +529,8 @@ if(OS_IS_LINUX) /usr/lib/gcc/i686-linux-gnu/4.7 /usr/lib/gcc/x86_64-linux-gnu/4.8 /usr/lib/gcc/i686-linux-gnu/4.8 + /usr/lib/gcc/x86_64-linux-gnu/4.9 + /usr/lib/gcc/i686-linux-gnu/4.9 /usr/lib/gcc/x86_64-redhat-linux/4.7.2 # Fedora 18 /usr/lib/gcc/i686-redhat-linux/4.7.2 /usr/lib/gcc/x86_64-redhat-linux/4.8.1 # Fedora 19 @@ -541,6 +546,7 @@ if(OS_IS_LINUX) /usr/lib/gcc/i486-linux-gnu/4.6 /usr/lib/gcc/i486-linux-gnu/4.7 /usr/lib/gcc/i486-linux-gnu/4.8 + /usr/lib/gcc/i486-linux-gnu/4.9 ) if(NOT GFORTRAN) message(" The gfortran library has not been found.") @@ -840,18 +846,34 @@ endif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") # Processor-architecture related flags # See http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86_002d64-Options.html#i386-and-x86_002d64-Options -# Change to '-mtune=generic' when building for distribution -if(CMAKE_COMPILER_IS_GNUCXX AND NOT WIN32) - if(OS_IS_MACOSX) - set(MY_CXX_FLAGS "${MY_CXX_FLAGS} -march=corei7 -mfpmath=sse") - else(OS_IS_MACOSX) - if(ENABLE_GENERIC_ARCH) - set(MY_CXX_FLAGS "${MY_CXX_FLAGS} -mtune=generic") - else(ENABLE_GENERIC_ARCH) - set(MY_CXX_FLAGS "${MY_CXX_FLAGS} -march=native -mfpmath=sse") - endif(ENABLE_GENERIC_ARCH) - endif(OS_IS_MACOSX) -endif(CMAKE_COMPILER_IS_GNUCXX AND NOT WIN32) +# Change to '-mtune=generic' when building for distribution (except when compiling for arm) +if (NOT ARCH_COMPILER_FLAGS) + if(CMAKE_COMPILER_IS_GNUCXX AND NOT WIN32) + if(OS_IS_MACOSX) + set(ARCH_COMPILER_FLAGS "-march=corei7 -mfpmath=sse") + else(OS_IS_MACOSX) + if(ENABLE_GENERIC_ARCH) + if (IS_ARM) + set(ARCH_COMPILER_FLAGS "-mtune=generic-arm") + else (IS_ARM) + set(ARCH_COMPILER_FLAGS "-mtune=generic") + endif(IS_ARM) + else(ENABLE_GENERIC_ARCH) + if (IS_ARM) + if (ARM_VERSION STREQUAL "arm") + # Unknown arm version - try our best to detect + set(ARCH_COMPILER_FLAGS "-mcpu=native") + else (ARM_VERSION STREQUAL "arm") + set(ARCH_COMPILER_FLAGS "-march=${ARM_VERSION}") + endif (ARM_VERSION STREQUAL "arm") + else (IS_ARM) + set(ARCH_COMPILER_FLAGS "-march=native -mfpmath=sse") + endif (IS_ARM) + endif(ENABLE_GENERIC_ARCH) + endif(OS_IS_MACOSX) + endif(CMAKE_COMPILER_IS_GNUCXX AND NOT WIN32) +endif (NOT ARCH_COMPILER_FLAGS) +set(MY_CXX_FLAGS "${MY_CXX_FLAGS} ${ARCH_COMPILER_FLAGS}") if(CMAKE_COMPILER_IS_GNUCXX AND NOT WIN32) #http://gcc.gnu.org/wiki/Visibility diff --git a/cmake/Modules/TestForARM.cmake b/cmake/Modules/TestForARM.cmake new file mode 100644 index 000000000..dd9d512bf --- /dev/null +++ b/cmake/Modules/TestForARM.cmake @@ -0,0 +1,83 @@ +############################################################################## +# check if the compiler defines the architecture as ARM and set the +# version, if found. +# +# - Anthony Arnold +############################################################################## + +if (__TEST_FOR_ARM_INCLUDED) + return () +endif() +set(__TEST_FOR_ARM_INCLUDED TRUE) + +# Function checks if the input string defines ARM version and sets the +# output variable if found. +function(check_arm_version ppdef input_string version output_var) + string(REGEX MATCH "${ppdef}" _VERSION_MATCH "${input_string}") + if (NOT _VERSION_MATCH STREQUAL "") + set(${output_var} "${version}" PARENT_SCOPE) + endif(NOT _VERSION_MATCH STREQUAL "") +endfunction() + +message(STATUS "Checking for ARM") + +set (IS_ARM NO) +set (ARM_VERSION "") + +if (CMAKE_COMPILER_IS_GNUCXX) + execute_process(COMMAND echo "int main(){}" + COMMAND ${CMAKE_CXX_COMPILER} -dM -E - + OUTPUT_VARIABLE TEST_FOR_ARM_RESULTS) + + string(REGEX MATCH "__arm" ARM_FOUND "${TEST_FOR_ARM_RESULTS}") + + if (NOT ARM_FOUND STREQUAL "") + set(IS_ARM YES) + message(STATUS "ARM system detected") + + # detect the version + check_arm_version("__ARM_ARCH_2__" ${TEST_FOR_ARM_RESULTS} "armv2" ARM_VERSION) + check_arm_version("__ARM_ARCH_2A__" ${TEST_FOR_ARM_RESULTS} "armv2a" ARM_VERSION) + check_arm_version("__ARM_ARCH_3__" ${TEST_FOR_ARM_RESULTS} "armv3" ARM_VERSION) + check_arm_version("__ARM_ARCH_3M__" ${TEST_FOR_ARM_RESULTS} "armv3m" ARM_VERSION) + check_arm_version("__ARM_ARCH_4__" ${TEST_FOR_ARM_RESULTS} "armv4" ARM_VERSION) + check_arm_version("__ARM_ARCH_4T__" ${TEST_FOR_ARM_RESULTS} "armv4t" ARM_VERSION) + check_arm_version("__ARM_ARCH_5__" ${TEST_FOR_ARM_RESULTS} "armv5" ARM_VERSION) + check_arm_version("__ARM_ARCH_5T__" ${TEST_FOR_ARM_RESULTS} "armv5t" ARM_VERSION) + check_arm_version("__ARM_ARCH_5E__" ${TEST_FOR_ARM_RESULTS} "armv5e" ARM_VERSION) + check_arm_version("__ARM_ARCH_5TE__" ${TEST_FOR_ARM_RESULTS} "armv5te" ARM_VERSION) + check_arm_version("__ARM_ARCH_6__" ${TEST_FOR_ARM_RESULTS} "armv6" ARM_VERSION) + check_arm_version("__ARM_ARCH_6J__" ${TEST_FOR_ARM_RESULTS} "armv6j" ARM_VERSION) + check_arm_version("__ARM_ARCH_6K__" ${TEST_FOR_ARM_RESULTS} "armv6k" ARM_VERSION) + check_arm_version("__ARM_ARCH_6T2__" ${TEST_FOR_ARM_RESULTS} "armv6t2" ARM_VERSION) + check_arm_version("__ARM_ARCH_6Z__" ${TEST_FOR_ARM_RESULTS} "armv6z" ARM_VERSION) + check_arm_version("__ARM_ARCH_6ZK__" ${TEST_FOR_ARM_RESULTS} "armv6zk" ARM_VERSION) + check_arm_version("__ARM_ARCH_6M__" ${TEST_FOR_ARM_RESULTS} "armv6-m" ARM_VERSION) + check_arm_version("__ARM_ARCH_7__" ${TEST_FOR_ARM_RESULTS} "armv7" ARM_VERSION) + check_arm_version("__ARM_ARCH_7A__" ${TEST_FOR_ARM_RESULTS} "armv7-a" ARM_VERSION) + check_arm_version("__ARM_ARCH_7M__" ${TEST_FOR_ARM_RESULTS} "armv7-m" ARM_VERSION) + check_arm_version("__ARM_ARCH_7R__" ${TEST_FOR_ARM_RESULTS} "armv7-r" ARM_VERSION) + check_arm_version("__ARM_ARCH_7EM_" ${TEST_FOR_ARM_RESULTS} "armv7e-m" ARM_VERSION) + check_arm_version("__ARM_ARCH_7VE__" ${TEST_FOR_ARM_RESULTS} "armv7ve" ARM_VERSION) + check_arm_version("__ARM_ARCH_8A__" ${TEST_FOR_ARM_RESULTS} "armv8-a" ARM_VERSION) + + # anything else just define as arm + if (ARM_VERSION STREQUAL "") + message(STATUS "Couldn't detect ARM version. Setting to 'arm'") + set(ARM_VERSION "arm") + else (ARM_VERSION STREQUAL "") + message(STATUS "ARM version ${ARM_VERSION} detected") + endif (ARM_VERSION STREQUAL "") + + else (NOT ARM_FOUND STREQUAL "") + message(STATUS "System is not ARM") + endif(NOT ARM_FOUND STREQUAL "") + +else (CMAKE_COMPILE_IS_GNUCXX) + # TODO: Other compilers + message(STATUS "Not detecting ARM on non-GNUCXX compiler. Defaulting to false") + message(STATUS "If you are compiling for ARM, set IS_ARM=ON manually") +endif(CMAKE_COMPILER_IS_GNUCXX) + +set(IS_ARM ${IS_ARM} CACHE BOOL "Compiling for ARM") +set(ARM_VERSION ${ARM_VERSION} CACHE STRING "ARM version") diff --git a/cmake/Modules/TestForSSE.cmake b/cmake/Modules/TestForSSE.cmake new file mode 100644 index 000000000..9d9192f27 --- /dev/null +++ b/cmake/Modules/TestForSSE.cmake @@ -0,0 +1,36 @@ +############################################################################### +# Test for availability of SSE +# +# - Anthony Arnold +############################################################################### + + +function (test_for_sse h_file result_var name) + if (NOT DEFINED ${result_var}) + execute_process(COMMAND echo "#include <${h_file}>" + COMMAND ${CMAKE_CXX_COMPILER} -c -x c++ - + RESULT_VARIABLE COMPILE_RESULT + OUTPUT_QUIET ERROR_QUIET) + + if (COMPILE_RESULT EQUAL 0) + message(STATUS "Detected ${name}") + endif(COMPILE_RESULT EQUAL 0) + set(${result_var} ${compile_result} CACHE INTERNAL "${name} Available") + endif (NOT DEFINED ${result_var}) +endfunction(test_for_sse) + +message(STATUS "Testing for SIMD extensions") + +enable_language(C) + +test_for_sse("ammintrin.h" SSE4A_AVAILABLE "SSE4A") +test_for_sse("nmmintrin.h" SSE4_2_AVAILABLE "SSE4.2") +test_for_sse("smmintrin.h" SSE4_1_AVAILABLE "SSE4.1") +test_for_sse("tmmintrin.h" SSSE3_AVAILABLE "SSSE3") +test_for_sse("pmmintrin.h" SSE3_AVAILABLE "SSE3") +test_for_sse("emmintrin.h" SSE2_AVAILABLE "SSE2") +test_for_sse("xmmintrin.h" SSE_AVAILABLE "SSE1") +test_for_sse("mmintrin.h" MMX_AVAILABLE "MMX") +test_for_sse("wmmintrin.h" AES_AVAILABLE "AES") +test_for_sse("immintrin.h" AVX_AVAILABLE "AVX") + diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_optim_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_optim_tracking_cc.cc index 374b3a6fb..4ea6d91ea 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_optim_tracking_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_optim_tracking_cc.cc @@ -376,7 +376,7 @@ int Gps_L1_Ca_Dll_Pll_Optim_Tracking_cc::general_work (int noutput_items, gr_vec update_local_carrier(); // perform Early, Prompt and Late correlation -#ifndef GENERIC_ARCH +#if USING_VOLK_CW_EPL_CORR_CUSTOM d_correlator.Carrier_wipeoff_and_EPL_volk_custom(d_current_prn_length_samples, in, d_carr_sign, diff --git a/src/algorithms/tracking/libs/CMakeLists.txt b/src/algorithms/tracking/libs/CMakeLists.txt index c4da7d0a2..136d61c59 100644 --- a/src/algorithms/tracking/libs/CMakeLists.txt +++ b/src/algorithms/tracking/libs/CMakeLists.txt @@ -40,6 +40,10 @@ if(ENABLE_GENERIC_ARCH) add_definitions( -DGENERIC_ARCH=1 ) endif(ENABLE_GENERIC_ARCH) +if (SSE3_AVAILABLE) + add_definitions( -DHAVE_SSE3=1 ) +endif(SSE3_AVAILABLE) + file(GLOB TRACKING_LIB_HEADERS "*.h") add_library(tracking_lib ${TRACKING_LIB_SOURCES} ${TRACKING_LIB_HEADERS}) source_group(Headers FILES ${TRACKING_LIB_HEADERS}) diff --git a/src/algorithms/tracking/libs/correlator.cc b/src/algorithms/tracking/libs/correlator.cc index 1e5825683..2e9b0def7 100644 --- a/src/algorithms/tracking/libs/correlator.cc +++ b/src/algorithms/tracking/libs/correlator.cc @@ -36,7 +36,7 @@ #include "correlator.h" #include -#ifndef GENERIC_ARCH +#if USING_VOLK_CW_EPL_CORR_CUSTOM #define LV_HAVE_SSE3 #include "volk_cw_epl_corr.h" #endif @@ -189,7 +189,7 @@ void Correlator::Carrier_wipeoff_and_EPL_volk_IQ(int signal_length_samples ,cons } -#ifndef GENERIC_ARCH +#if USING_VOLK_CW_EPL_CORR_CUSTOM void Correlator::Carrier_wipeoff_and_EPL_volk_custom(int signal_length_samples, const gr_complex* input, gr_complex* carrier,gr_complex* E_code, gr_complex* P_code, gr_complex* L_code, gr_complex* E_out, gr_complex* P_out, gr_complex* L_out, bool input_vector_unaligned) { volk_cw_epl_corr_u(input, carrier, E_code, P_code, L_code, E_out, P_out, L_out, signal_length_samples); diff --git a/src/algorithms/tracking/libs/correlator.h b/src/algorithms/tracking/libs/correlator.h index f00189fa9..7196c8b70 100644 --- a/src/algorithms/tracking/libs/correlator.h +++ b/src/algorithms/tracking/libs/correlator.h @@ -41,6 +41,9 @@ #include #include +#if !defined(GENERIC_ARCH) && HAVE_SSE3 +#define USING_VOLK_CW_EPL_CORR_CUSTOM 1 +#endif /*! * \brief Class that implements carrier wipe-off and correlators. @@ -60,7 +63,7 @@ public: void Carrier_wipeoff_and_EPL_volk_IQ(int signal_length_samples, const gr_complex* input, gr_complex* carrier, gr_complex* E_code, gr_complex* P_code, gr_complex* L_code, gr_complex* P_data_code, gr_complex* E_out, gr_complex* P_out, gr_complex* L_out, gr_complex* P_data_out, bool input_vector_unaligned); Correlator(); ~Correlator(); -#ifndef GENERIC_ARCH +#ifndef USING_VOLK_CW_EPL_CORR void Carrier_wipeoff_and_EPL_volk_custom(int signal_length_samples, const gr_complex* input, gr_complex* carrier, gr_complex* E_code, gr_complex* P_code, gr_complex* L_code, gr_complex* E_out, gr_complex* P_out, gr_complex* L_out, bool input_vector_unaligned); #endif From 2478a43b0ad10d5d9fc2f41c964a76a773ce7c38 Mon Sep 17 00:00:00 2001 From: Anthony Arnold Date: Thu, 18 Sep 2014 01:04:58 +1000 Subject: [PATCH 2/3] Flags for ARM --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c1d1b287d..83afa3637 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -859,7 +859,7 @@ if (NOT ARCH_COMPILER_FLAGS) set(ARCH_COMPILER_FLAGS "-mtune=generic") endif(IS_ARM) else(ENABLE_GENERIC_ARCH) - if (IS_ARM) + if (IS_ARM) # ARM-specific options (https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html) if (ARM_VERSION STREQUAL "arm") # Unknown arm version - try our best to detect set(ARCH_COMPILER_FLAGS "-mcpu=native") From 7ded93f93e1d397267a3dc274ee8b063c32961db Mon Sep 17 00:00:00 2001 From: Anthony Arnold Date: Wed, 24 Sep 2014 08:23:32 +1000 Subject: [PATCH 3/3] Fixing preprocessor directive. --- src/algorithms/tracking/libs/correlator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algorithms/tracking/libs/correlator.h b/src/algorithms/tracking/libs/correlator.h index f7a82aa8f..b90123f9a 100644 --- a/src/algorithms/tracking/libs/correlator.h +++ b/src/algorithms/tracking/libs/correlator.h @@ -63,7 +63,7 @@ public: void Carrier_wipeoff_and_EPL_volk_IQ(int signal_length_samples, const gr_complex* input, gr_complex* carrier, gr_complex* E_code, gr_complex* P_code, gr_complex* L_code, gr_complex* P_data_code, gr_complex* E_out, gr_complex* P_out, gr_complex* L_out, gr_complex* P_data_out); Correlator(); ~Correlator(); -#ifndef USING_VOLK_CW_EPL_CORR +#if USING_VOLK_CW_EPL_CORR_CUSTOM void Carrier_wipeoff_and_EPL_volk_custom(int signal_length_samples, const gr_complex* input, gr_complex* carrier, gr_complex* E_code, gr_complex* P_code, gr_complex* L_code, gr_complex* E_out, gr_complex* P_out, gr_complex* L_out, bool input_vector_unaligned); #endif