diff --git a/CMakeLists.txt b/CMakeLists.txt index 05203f365..544f8cec5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -218,6 +218,7 @@ add_subdirectory(httpserver) add_subdirectory(logging) add_subdirectory(qrtplib) add_subdirectory(swagger) +add_subdirectory(liquiddsp) include_directories( ${CMAKE_CURRENT_BINARY_DIR} diff --git a/liquiddsp/CMakeLists.txt b/liquiddsp/CMakeLists.txt new file mode 100644 index 000000000..2741e4a17 --- /dev/null +++ b/liquiddsp/CMakeLists.txt @@ -0,0 +1,482 @@ +project(liquiddsp) + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules") + +file(READ "${LIQUIDDSPSRC}/include/liquid.h" liquid_h) +string(REGEX MATCH "\\#define LIQUID_VERSION[ ]+\"([0-9]+\\.[0-9]+\\.[0-9]+)\"" LIQUID_VERSION_MATCHES "${liquid_h}") +if(NOT LIQUID_VERSION_MATCHES) + message(FATAL_ERROR "Failed to extract version number from liquid.h") +endif(NOT LIQUID_VERSION_MATCHES) +set(LIQUID_VERSION ${CMAKE_MATCH_1}) + +message("-- Configuring for liquid-dsp ${LIQUID_VERSION}") + +include(CheckCPUID) +include(CheckRequiredFunction) +include(CheckTypeSize) + +include_directories(${LIQUIDDSPSRC}) +include_directories(${LIQUIDDSPSRC}/include) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) +include_directories(${CMAKE_CURRENT_BINARY_DIR}/include) + +CHECK_INCLUDE_FILE(sys/resource.h HAVE_SYS_RESOURCE_H) + +CHECK_INCLUDE_FILE(complex.h HAVE_COMPLEX_H) +CHECK_INCLUDE_FILE(float.h HAVE_FLOAT_H) +CHECK_INCLUDE_FILE(getopt.h HAVE_GETOPT_H) +CHECK_INCLUDE_FILE(inttypes.h HAVE_INTTYPES_H) +CHECK_INCLUDE_FILE(memory.h HAVE_MEMORY_H) +CHECK_INCLUDE_FILE(unistd.h HAVE_UNISTD_H) + +CHECK_INCLUDE_FILE(mmintrin.h HAVE_MMINTRIN_H) +CHECK_INCLUDE_FILE(emmintrin.h HAVE_EMMINTRIN_H) +CHECK_INCLUDE_FILE(immintrin.h HAVE_IMMINTRIN_H) +CHECK_INCLUDE_FILE(pmmintrin.h HAVE_PMMINTRIN_H) +CHECK_INCLUDE_FILE(smmintrin.h HAVE_SMMINTRIN_H) +CHECK_INCLUDE_FILE(tmmintrin.h HAVE_TMMINTRIN_H) +CHECK_INCLUDE_FILE(xmmintrin.h HAVE_XMMINTRIN_H) + +CHECK_INCLUDE_FILE(fec.h HAVE_FEC_H) +CHECK_INCLUDE_FILE(fftw3.h HAVE_FFTW3_H) + +CHECK_TYPE_SIZE(int SIZEOF_INT) +CHECK_TYPE_SIZE("unsigned int" SIZEOF_UNSIGNED_INT) + +CHECK_REQUIRED_FUNCTION(sinf m HAVE_SINF) +CHECK_REQUIRED_FUNCTION(cosf m HAVE_COSF) +CHECK_REQUIRED_FUNCTION(expf m HAVE_EXPF) +CHECK_REQUIRED_FUNCTION(cargf m HAVE_CARGF) +CHECK_REQUIRED_FUNCTION(cexpf m HAVE_CEXPF) +CHECK_REQUIRED_FUNCTION(crealf m HAVE_CREALF) +CHECK_REQUIRED_FUNCTION(cimagf m HAVE_CIMAGF) +CHECK_REQUIRED_FUNCTION(sqrtf m HAVE_SQRTF) + +CHECK_LIBRARY_EXISTS(m sqrtf "" HAVE_LIBM) +if (HAVE_FEC_H) + CHECK_LIBRARY_EXISTS(fec create_viterbi27 "" HAVE_LIBFEC) + if (NOT HAVE_LIBFEC) + unset(HAVE_FEC_H CACHE) + endif () +endif () +if (HAVE_FFTW3_H) + CHECK_LIBRARY_EXISTS(fftw3f fftwf_plan_dft_1d "" HAVE_LIBFFTW3F) + if (NOT HAVE_LIBFFTW3F) + unset(HAVE_FFTW3_H CACHE) + endif () +endif () + +CHECK_CPUID("mmx" HAVE_MMX ${LIQUID_FORCE_X86_MMX}) +CHECK_CPUID("sse" HAVE_SSE ${LIQUID_FORCE_X86_SSE}) +CHECK_CPUID("sse2" HAVE_SSE2 ${LIQUID_FORCE_X86_SSE2}) +CHECK_CPUID("sse3" HAVE_SSE3 ${LIQUID_FORCE_X86_SSE3}) +CHECK_CPUID("ssse3" HAVE_SSSE3 ${LIQUID_FORCE_X86_SSSE3}) +CHECK_CPUID("sse41" HAVE_SSE41 ${LIQUID_FORCE_X86_SSE41}) +CHECK_CPUID("sse42" HAVE_SSE42 ${LIQUID_FORCE_X86_SSE42}) +CHECK_CPUID("avx" HAVE_AVX ${LIQUID_FORCE_X86_AVX}) +CHECK_CPUID("vmx" HAVE_ALTIVEC ${LIQUID_FORCE_PPC_ALTIVEC}) +CHECK_CPUID("neon" HAVE_NEON ${LIQUID_FORCE_ARM_NEON}) +CHECK_CPUID("neon64" HAVE_NEON64 ${LIQUID_FORCE_ARM64_NEON}) + +# +# Build compilation extra flags +# +if (CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") + if (HAVE_AVX) + set(_EXTRA_C_FLAGS "-mavx") + elseif (HAVE_SSE42) + set(_EXTRA_C_FLAGS "-msse4.2") + elseif (HAVE_SSE41) + set(_EXTRA_C_FLAGS "-msse4.1") + elseif (HAVE_SSSE3) + set(_EXTRA_C_FLAGS "-mssse3") + elseif (HAVE_SSE3) + set(_EXTRA_C_FLAGS "-msse3") + elseif (HAVE_SSE2) + set(_EXTRA_C_FLAGS "-msse2") + elseif (HAVE_SSE) + set(_EXTRA_C_FLAGS "-msse") + elseif (HAVE_MMX) + set(_EXTRA_C_FLAGS "-mmmx") + elseif (HAVE_ALTIVEC) + if (CMAKE_SYSTEM_NAME MATCHES "Darwin") + set(_EXTRA_C_FLAGS "-fno-common -faltivec") + else () + set(_EXTRA_C_FLAGS "-maltivec") + endif () + elseif (HAVE_NEON) + set(_EXTRA_C_FLAGS "-mfpu=neon-vfpv4") + elseif (HAVE_NEON64) + # No extra flags needed + endif () + set(_EXTRA_C_FLAGS "${_EXTRA_C_FLAGS} -ffast-math") +endif () + +# +# MODULE : agc - automatic gain control +# + +set(agc_SOURCES + ${LIQUIDDSPSRC}/src/agc/src/agc_crcf.c + ${LIQUIDDSPSRC}/src/agc/src/agc_rrrf.c + ) + +# +# MODULE : audio +# + +set(audio_SOURCES + ${LIQUIDDSPSRC}/src/audio/src/cvsd.c + ) + +# +# MODULE : buffer +# + +set(buffer_SOURCES + ${LIQUIDDSPSRC}/src/buffer/src/bufferf.c + ${LIQUIDDSPSRC}/src/buffer/src/buffercf.c + ) + +# +# MODULE : channel +# + +set(channel_SOURCES + ${LIQUIDDSPSRC}/src/channel/src/channel_cccf.c + ) + +# +# MODULE : dotprod +# + +set(dotprod_C_SOURCES + ${LIQUIDDSPSRC}/src/dotprod/src/dotprod_cccf.c + ${LIQUIDDSPSRC}/src/dotprod/src/dotprod_crcf.c + ${LIQUIDDSPSRC}/src/dotprod/src/dotprod_rrrf.c + ${LIQUIDDSPSRC}/src/dotprod/src/sumsq.c + ) + +# PowerPC AltiVec +set(dotprod_ALTIVEC_SOURCES + ${LIQUIDDSPSRC}/src/dotprod/src/dotprod_cccf.c + ${LIQUIDDSPSRC}/src/dotprod/src/dotprod_crcf.av.c + ${LIQUIDDSPSRC}/src/dotprod/src/dotprod_rrrf.av.c + ${LIQUIDDSPSRC}/src/dotprod/src/sumsq.c + ) + +# Intel MMX/SSE/AVX +set(dotprod_SSE_SOURCES + ${LIQUIDDSPSRC}/src/dotprod/src/dotprod_cccf.mmx.c + ${LIQUIDDSPSRC}/src/dotprod/src/dotprod_crcf.mmx.c + ${LIQUIDDSPSRC}/src/dotprod/src/dotprod_rrrf.mmx.c + ${LIQUIDDSPSRC}/src/dotprod/src/sumsq.mmx.c + ) + +# ARM NEON +set(dotprod_NEON_SOURCES + ${LIQUIDDSPSRC}/src/dotprod/src/dotprod_cccf.neon.c + ${LIQUIDDSPSRC}/src/dotprod/src/dotprod_crcf.neon.c + ${LIQUIDDSPSRC}/src/dotprod/src/dotprod_rrrf.neon.c + ${LIQUIDDSPSRC}/src/dotprod/src/sumsq.c + ) + +if (LIQUID_SIMDOVERRIDE) + set(dotprod_SOURCES ${dotprod_C_SOURCES}) +elseif (HAVE_SSE41 AND HAVE_SMMINTRIN_H) + set(dotprod_SOURCES ${dotprod_SSE_SOURCES}) +elseif (HAVE_SSE3 AND HAVE_PMMINTRIN_H) + set(dotprod_SOURCES ${dotprod_SSE_SOURCES}) +elseif (HAVE_SSE2 AND HAVE_EMMINTRIN_H) + unset(HAVE_PMMINTRIN_H CACHE) # Unset otherwise SSE3 code kicks in. + set(dotprod_SOURCES ${dotprod_SSE_SOURCES}) +elseif (HAVE_ALTIVEC) + set(dotprod_SOURCES ${dotprod_ALTIVEC_SOURCES}) +elseif (HAVE_NEON OR HAVE_NEON64) + set(dotprod_SOURCES ${dotprod_NEON_SOURCES}) +else () + set(dotprod_SOURCES ${dotprod_C_SOURCES}) +endif () + +# +# MODULE : equalization +# + +set(equalization_SOURCES + ${LIQUIDDSPSRC}/src/equalization/src/equalizer_cccf.c + ${LIQUIDDSPSRC}/src/equalization/src/equalizer_rrrf.c + ) + +# +# MODULE : fec - forward error-correction +# +set(fec_SOURCES + ${LIQUIDDSPSRC}/src/fec/src/crc.c + ${LIQUIDDSPSRC}/src/fec/src/fec.c + ${LIQUIDDSPSRC}/src/fec/src/fec_conv.c + ${LIQUIDDSPSRC}/src/fec/src/fec_conv_poly.c + ${LIQUIDDSPSRC}/src/fec/src/fec_conv_pmatrix.c + ${LIQUIDDSPSRC}/src/fec/src/fec_conv_punctured.c + ${LIQUIDDSPSRC}/src/fec/src/fec_golay2412.c + ${LIQUIDDSPSRC}/src/fec/src/fec_hamming74.c + ${LIQUIDDSPSRC}/src/fec/src/fec_hamming84.c + ${LIQUIDDSPSRC}/src/fec/src/fec_hamming128.c + ${LIQUIDDSPSRC}/src/fec/src/fec_hamming1511.c + ${LIQUIDDSPSRC}/src/fec/src/fec_hamming3126.c + ${LIQUIDDSPSRC}/src/fec/src/fec_hamming128_gentab.c + ${LIQUIDDSPSRC}/src/fec/src/fec_pass.c + ${LIQUIDDSPSRC}/src/fec/src/fec_rep3.c + ${LIQUIDDSPSRC}/src/fec/src/fec_rep5.c + ${LIQUIDDSPSRC}/src/fec/src/fec_rs.c + ${LIQUIDDSPSRC}/src/fec/src/fec_secded2216.c + ${LIQUIDDSPSRC}/src/fec/src/fec_secded3932.c + ${LIQUIDDSPSRC}/src/fec/src/fec_secded7264.c + ${LIQUIDDSPSRC}/src/fec/src/interleaver.c + ${LIQUIDDSPSRC}/src/fec/src/packetizer.c + ${LIQUIDDSPSRC}/src/fec/src/sumproduct.c + ) + +# +# MODULE : fft - fast Fourier transforms, discrete sine/cosine transforms, etc. +# +set(fft_SOURCES + ${LIQUIDDSPSRC}/src/fft/src/fftf.c + ${LIQUIDDSPSRC}/src/fft/src/spgramcf.c + ${LIQUIDDSPSRC}/src/fft/src/spgramf.c + ${LIQUIDDSPSRC}/src/fft/src/fft_utilities.c + ) + +# +# MODULE : filter +# +set(filter_SOURCES + ${LIQUIDDSPSRC}/src/filter/src/bessel.c + ${LIQUIDDSPSRC}/src/filter/src/butter.c + ${LIQUIDDSPSRC}/src/filter/src/cheby1.c + ${LIQUIDDSPSRC}/src/filter/src/cheby2.c + ${LIQUIDDSPSRC}/src/filter/src/ellip.c + ${LIQUIDDSPSRC}/src/filter/src/filter_rrrf.c + ${LIQUIDDSPSRC}/src/filter/src/filter_crcf.c + ${LIQUIDDSPSRC}/src/filter/src/filter_cccf.c + ${LIQUIDDSPSRC}/src/filter/src/firdes.c + ${LIQUIDDSPSRC}/src/filter/src/firdespm.c + ${LIQUIDDSPSRC}/src/filter/src/fnyquist.c + ${LIQUIDDSPSRC}/src/filter/src/gmsk.c + ${LIQUIDDSPSRC}/src/filter/src/group_delay.c + ${LIQUIDDSPSRC}/src/filter/src/hM3.c + ${LIQUIDDSPSRC}/src/filter/src/iirdes.pll.c + ${LIQUIDDSPSRC}/src/filter/src/iirdes.c + ${LIQUIDDSPSRC}/src/filter/src/lpc.c + ${LIQUIDDSPSRC}/src/filter/src/rcos.c + ${LIQUIDDSPSRC}/src/filter/src/rkaiser.c + ${LIQUIDDSPSRC}/src/filter/src/rrcos.c + ) + +# +# MODULE : framing +# +set(framing_SOURCES + ${LIQUIDDSPSRC}/src/framing/src/bpacketgen.c + ${LIQUIDDSPSRC}/src/framing/src/bpacketsync.c + ${LIQUIDDSPSRC}/src/framing/src/bpresync_cccf.c + ${LIQUIDDSPSRC}/src/framing/src/bsync_rrrf.c + ${LIQUIDDSPSRC}/src/framing/src/bsync_crcf.c + ${LIQUIDDSPSRC}/src/framing/src/bsync_cccf.c + ${LIQUIDDSPSRC}/src/framing/src/detector_cccf.c + ${LIQUIDDSPSRC}/src/framing/src/framedatastats.c + ${LIQUIDDSPSRC}/src/framing/src/framesyncstats.c + ${LIQUIDDSPSRC}/src/framing/src/framegen64.c + ${LIQUIDDSPSRC}/src/framing/src/framesync64.c + ${LIQUIDDSPSRC}/src/framing/src/flexframegen.c + ${LIQUIDDSPSRC}/src/framing/src/flexframesync.c + ${LIQUIDDSPSRC}/src/framing/src/gmskframegen.c + ${LIQUIDDSPSRC}/src/framing/src/gmskframesync.c + ${LIQUIDDSPSRC}/src/framing/src/msourcecf.c + ${LIQUIDDSPSRC}/src/framing/src/ofdmflexframegen.c + ${LIQUIDDSPSRC}/src/framing/src/ofdmflexframesync.c + ${LIQUIDDSPSRC}/src/framing/src/presync_cccf.c + ${LIQUIDDSPSRC}/src/framing/src/symstreamcf.c + ${LIQUIDDSPSRC}/src/framing/src/symtrack_cccf.c + ${LIQUIDDSPSRC}/src/framing/src/qdetector_cccf.c + ${LIQUIDDSPSRC}/src/framing/src/qpacketmodem.c + ${LIQUIDDSPSRC}/src/framing/src/qpilotgen.c + ${LIQUIDDSPSRC}/src/framing/src/qpilotsync.c + ) + +# +# MODULE : math +# +set(math_SOURCES + ${LIQUIDDSPSRC}/src/math/src/poly.c + ${LIQUIDDSPSRC}/src/math/src/polyc.c + ${LIQUIDDSPSRC}/src/math/src/polyf.c + ${LIQUIDDSPSRC}/src/math/src/polycf.c + ${LIQUIDDSPSRC}/src/math/src/math.c + ${LIQUIDDSPSRC}/src/math/src/math.bessel.c + ${LIQUIDDSPSRC}/src/math/src/math.gamma.c + ${LIQUIDDSPSRC}/src/math/src/math.complex.c + ${LIQUIDDSPSRC}/src/math/src/math.trig.c + ${LIQUIDDSPSRC}/src/math/src/modular_arithmetic.c + ) + +# +# MODULE : matrix +# +set(matrix_SOURCES + ${LIQUIDDSPSRC}/src/matrix/src/matrix.c + ${LIQUIDDSPSRC}/src/matrix/src/matrixf.c + ${LIQUIDDSPSRC}/src/matrix/src/matrixc.c + ${LIQUIDDSPSRC}/src/matrix/src/matrixcf.c + ${LIQUIDDSPSRC}/src/matrix/src/smatrix.common.c + ${LIQUIDDSPSRC}/src/matrix/src/smatrixb.c + ${LIQUIDDSPSRC}/src/matrix/src/smatrixf.c + ${LIQUIDDSPSRC}/src/matrix/src/smatrixi.c + ) + +# +# MODULE : modem +# +set(modem_SOURCES + ${LIQUIDDSPSRC}/src/modem/src/ampmodem.c + ${LIQUIDDSPSRC}/src/modem/src/cpfskdem.c + ${LIQUIDDSPSRC}/src/modem/src/cpfskmod.c + ${LIQUIDDSPSRC}/src/modem/src/fskdem.c + ${LIQUIDDSPSRC}/src/modem/src/fskmod.c + ${LIQUIDDSPSRC}/src/modem/src/gmskdem.c + ${LIQUIDDSPSRC}/src/modem/src/gmskmod.c + ${LIQUIDDSPSRC}/src/modem/src/modemf.c + ${LIQUIDDSPSRC}/src/modem/src/modem_utilities.c + ${LIQUIDDSPSRC}/src/modem/src/modem_apsk_const.c + ${LIQUIDDSPSRC}/src/modem/src/modem_arb_const.c + ) + +# +# MODULE : multichannel +# +set(multichannel_SOURCES + ${LIQUIDDSPSRC}/src/multichannel/src/firpfbch_crcf.c + ${LIQUIDDSPSRC}/src/multichannel/src/firpfbch_cccf.c + ${LIQUIDDSPSRC}/src/multichannel/src/ofdmframe.common.c + ${LIQUIDDSPSRC}/src/multichannel/src/ofdmframegen.c + ${LIQUIDDSPSRC}/src/multichannel/src/ofdmframesync.c + ) + +# +# MODULE : nco - numerically-controlled oscillator +# +set(nco_SOURCES + ${LIQUIDDSPSRC}/src/nco/src/nco_crcf.c + ${LIQUIDDSPSRC}/src/nco/src/nco.utilities.c + ) + +# +# MODULE : optim - optimization +# +set(optim_SOURCES + ${LIQUIDDSPSRC}/src/optim/src/chromosome.c + ${LIQUIDDSPSRC}/src/optim/src/gasearch.c + ${LIQUIDDSPSRC}/src/optim/src/gradsearch.c + ${LIQUIDDSPSRC}/src/optim/src/optim.common.c + ${LIQUIDDSPSRC}/src/optim/src/qnsearch.c + ${LIQUIDDSPSRC}/src/optim/src/utilities.c + ) + +# +# MODULE : quantization +# +set(quantization_SOURCES + ${LIQUIDDSPSRC}/src/quantization/src/compand.c + ${LIQUIDDSPSRC}/src/quantization/src/quantizercf.c + ${LIQUIDDSPSRC}/src/quantization/src/quantizerf.c + ${LIQUIDDSPSRC}/src/quantization/src/quantizer.inline.c + ) + +# +# MODULE : random +# +set(random_SOURCES + ${LIQUIDDSPSRC}/src/random/src/rand.c + ${LIQUIDDSPSRC}/src/random/src/randn.c + ${LIQUIDDSPSRC}/src/random/src/randexp.c + ${LIQUIDDSPSRC}/src/random/src/randweib.c + ${LIQUIDDSPSRC}/src/random/src/randgamma.c + ${LIQUIDDSPSRC}/src/random/src/randnakm.c + ${LIQUIDDSPSRC}/src/random/src/randricek.c + ${LIQUIDDSPSRC}/src/random/src/scramble.c + ) + +# +# MODULE : sequence +# +set(sequence_SOURCES + ${LIQUIDDSPSRC}/src/sequence/src/bsequence.c + ${LIQUIDDSPSRC}/src/sequence/src/msequence.c + ) + +# +# MODULE : utility +# +set(utility_SOURCES + ${LIQUIDDSPSRC}/src/utility/src/bshift_array.c + ${LIQUIDDSPSRC}/src/utility/src/byte_utilities.c + ${LIQUIDDSPSRC}/src/utility/src/msb_index.c + ${LIQUIDDSPSRC}/src/utility/src/pack_bytes.c + ${LIQUIDDSPSRC}/src/utility/src/shift_array.c + ) + +# +# MODULE : vector +# +set(vector_SOURCES + ${LIQUIDDSPSRC}/src/vector/src/vectorf_add.port.c + ${LIQUIDDSPSRC}/src/vector/src/vectorf_norm.port.c + ${LIQUIDDSPSRC}/src/vector/src/vectorf_mul.port.c + ${LIQUIDDSPSRC}/src/vector/src/vectorf_trig.port.c + ${LIQUIDDSPSRC}/src/vector/src/vectorcf_add.port.c + ${LIQUIDDSPSRC}/src/vector/src/vectorcf_norm.port.c + ${LIQUIDDSPSRC}/src/vector/src/vectorcf_mul.port.c + ${LIQUIDDSPSRC}/src/vector/src/vectorcf_trig.port.c + ) + +# +# Library +# +set(liquid_SOURCES + ${LIQUIDDSPSRC}/src/libliquid.c + ${agc_SOURCES} + ${audio_SOURCES} + ${buffer_SOURCES} + ${channel_SOURCES} + ${dotprod_SOURCES} + ${equalization_SOURCES} + ${fec_SOURCES} + ${fft_SOURCES} + ${filter_SOURCES} + ${framing_SOURCES} + ${math_SOURCES} + ${matrix_SOURCES} + ${modem_SOURCES} + ${multichannel_SOURCES} + ${nco_SOURCES} + ${optim_SOURCES} + ${quantization_SOURCES} + ${random_SOURCES} + ${sequence_SOURCES} + ${utility_SOURCES} + ${vector_SOURCES} + ) + +add_library(liquid SHARED ${liquid_SOURCES}) +if (HAVE_LIBM) + target_link_libraries(liquid m) +endif () +if (HAVE_LIBFEC) + target_link_libraries(liquid fec) +endif () +if (NOT LIQUID_FFTOVERRIDE AND HAVE_LIBFFTW3F) + target_link_libraries(liquid fftw3f) +endif () + +set_property(TARGET liquid PROPERTY OUTPUT_NAME "liquid") +set_property(TARGET liquid PROPERTY SOVERSION "${LIQUID_VERSION}") +set_property(TARGET liquid PROPERTY COMPILE_FLAGS "${_EXTRA_C_FLAGS}") diff --git a/liquiddsp/cmake/Modules/CheckCPUID.cmake b/liquiddsp/cmake/Modules/CheckCPUID.cmake new file mode 100644 index 000000000..139c186b3 --- /dev/null +++ b/liquiddsp/cmake/Modules/CheckCPUID.cmake @@ -0,0 +1,49 @@ +# example usage: CHECK_CPUID("mmx" HAVE_MMX [TRUE|FALSE]) +macro(CHECK_CPUID CHARACTERISTIC VARIABLE) + if (${ARGC} GREATER 2) + set(_CPUID_FORCE ${ARGV2}) + else () + unset(_CPUID_FORCE) + endif () + + message("-- Checking for CPU characteristic ${CHARACTERISTIC}") + + if (DEFINED _CPUID_FORCE AND _CPUID_FORCE) + set(_CPUID_CHARACTERISTIC_FOUND ${_CPUID_FORCE}) + set(_FORCED "(forced)") + else () + if (CMAKE_CROSSCOMPILING) + # When cross compiling, we need to test each characteristic. + try_compile(CPUID_COMPILE_RESULT + ${CMAKE_CURRENT_BINARY_DIR} + SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/cmcpuid.c + COMPILE_DEFINITIONS "-DCROSS_COMPILING" "-DTEST_${CHARACTERISTIC}" + OUTPUT_VARIABLE CPUID_COMPILE_OUTPUT + ) + set(_CPUID_CHARACTERISTIC_FOUND ${CPUID_COMPILE_RESULT}) + else () + if (NOT _CPUID_CHARACTERISTICS) + try_run(CPUID_RUN_RESULT CPUID_COMPILE_RESULT + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/cmcpuid.c + RUN_OUTPUT_VARIABLE CPUID_CHARACTERISTICS + ) + set(_CPUID_CHARACTERISTICS "${CPUID_CHARACTERISTICS}" CACHE INTERNAL "CPU Characteristics") + endif () + if (${_CPUID_CHARACTERISTICS} MATCHES "@${CHARACTERISTIC}@") + set(_CPUID_CHARACTERISTIC_FOUND TRUE) + else () + set(_CPUID_CHARACTERISTIC_FOUND FALSE) + endif () + endif () + unset(_FORCED) + endif () + + if (_CPUID_CHARACTERISTIC_FOUND) + message("-- Checking for CPU characteristic ${CHARACTERISTIC} - found ${_FORCED}") + else () + message("-- Checking for CPU characteristic ${CHARACTERISTIC} - not found") + endif () + set(${VARIABLE} ${_CPUID_CHARACTERISTIC_FOUND} CACHE INTERNAL "Check for CPU characteristic ${CHARACTERISTIC}" FORCE) +endmacro() + diff --git a/liquiddsp/cmake/Modules/CheckRequiredFunction.cmake b/liquiddsp/cmake/Modules/CheckRequiredFunction.cmake new file mode 100644 index 000000000..33f846a55 --- /dev/null +++ b/liquiddsp/cmake/Modules/CheckRequiredFunction.cmake @@ -0,0 +1,16 @@ +include(CheckFunctionExists) +include(CheckLibraryExists) + +macro(CHECK_REQUIRED_FUNCTION FUNCTION LIBRARY VARIABLE) + # First try without any library. + CHECK_FUNCTION_EXISTS("${FUNCTION}" ${VARIABLE}) + if (NOT ${VARIABLE}) + unset(${VARIABLE} CACHE) + # Retry with the library specified + CHECK_LIBRARY_EXISTS("${LIBRARY}" "${FUNCTION}" "" ${VARIABLE}) + endif () + if (NOT ${VARIABLE}) + message(FATAL_ERROR "Required function '${FUNCTION}' not found") + endif () +endmacro () + diff --git a/liquiddsp/cmake/Modules/LiquidBuildSamples.cmake b/liquiddsp/cmake/Modules/LiquidBuildSamples.cmake new file mode 100644 index 000000000..b64cf2663 --- /dev/null +++ b/liquiddsp/cmake/Modules/LiquidBuildSamples.cmake @@ -0,0 +1,12 @@ +function(LIQUID_BUILD_SAMPLES) + cmake_parse_arguments(LBS "" "SUITE" "SAMPLES" ${ARGN}) + if (NOT DEFINED LBS_SUITE) + message(FATAL_ERROR "Need to specify SUITE ") + endif () + foreach(_sample IN ITEMS ${LBS_SAMPLES}) + add_executable("${LBS_SUITE}_${_sample}" "${_sample}.c") + target_link_libraries("${LBS_SUITE}_${_sample}" ${LIQUID_LIBRARY}) + set_property(TARGET "${LBS_SUITE}_${_sample}" PROPERTY OUTPUT_NAME "${_sample}") + endforeach() +endfunction() + diff --git a/liquiddsp/cmake/Modules/cmcpuid.c b/liquiddsp/cmake/Modules/cmcpuid.c new file mode 100644 index 000000000..a2b22c83c --- /dev/null +++ b/liquiddsp/cmake/Modules/cmcpuid.c @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2016-present Orlando Bassotto + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef CROSS_COMPILING +/* + * This is executed when targeting the host. + */ +#include +#include +#include +#if defined(_MSC_VER) +#include +#endif + +#define ISA_X86_MMX (1 << 0) +#define ISA_X86_SSE (1 << 1) +#define ISA_X86_SSE2 (1 << 2) +#define ISA_X86_SSE3 (1 << 3) +#define ISA_X86_SSSE3 (1 << 4) +#define ISA_X86_SSE41 (1 << 5) +#define ISA_X86_SSE42 (1 << 6) +#define ISA_X86_AVX1 (1 << 7) +#define ISA_X86_AVX2 (1 << 8) +#define ISA_PPC_VMX (1 << 9) +#define ISA_ARM_NEON (1 << 10) +#define ISA_ARM64_NEON (1 << 11) + +#if !(defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_AMD64)) +static jmp_buf return_jmp; + +static void sighandler(int signo) +{ + longjmp(return_jmp, 1); +} +#endif + +static void +siginit(void) +{ +#if !(defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_AMD64)) + signal(SIGSEGV, sighandler); +#ifdef SIGBUS + signal(SIGBUS, sighandler); +#endif + signal(SIGILL, sighandler); +#endif +} + +static unsigned +check_isa(void) +{ +#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_AMD64) +#if defined(_M_IX86) || defined(_M_AMD64) + int regs[4]; +#endif + unsigned eax, ebx, ecx, edx; + int supported; + unsigned isa = 0; + +#if defined(_M_IX86) || defined(_M_AMD64) + __cpuid(regs, 1); + ecx = regs[2]; + edx = regs[3]; +#else + eax = 0x00000001; + __asm__ __volatile__( + "cpuid" + :"=c"(ecx) // %ecx contains large feature flag set + :"0"(eax) // call with 0x1 + :"%eax","%ebx","%edx" + ); +#endif + + if (edx & (1 << 23)) { + /* MMX */ + isa |= ISA_X86_MMX; + } + + if (edx & (1 << 25)) { + /* SSE */ + isa |= ISA_X86_SSE; + } + + if (edx & (1 << 26)) { + /* SSE */ + isa |= ISA_X86_SSE2; + } + + if (ecx & (1 << 0)) { + /* SSE3 */ + isa |= ISA_X86_SSE3; + } + + if (ecx & (1 << 9)) { + /* SSSE3 */ + isa |= ISA_X86_SSSE3; + } + + if (ecx & (1 << 19)) { + /* SSE4.1 */ + isa |= ISA_X86_SSE41; + } + + if (ecx & (1 << 20)) { + /* SSE4.2 */ + isa |= ISA_X86_SSE42; + } + + if (ecx & (1 << 28)) { + /* AVX1 */ + isa |= ISA_X86_AVX1; + +#if defined(_M_IX86) || defined(_M_AMD64) + __cpuid(regs, 7); + ebx = regs[1]; +#else + eax = 0x00000007; + __asm__ __volatile__( + "cpuid" + : "=b"(ebx) + : "0"(eax) + : "%eax", "%ecx", "%edx" + ); +#endif + + if (ebx & (1 << 5)) { + /* AVX2 */ + isa |= ISA_X86_AVX2; + } + } + + return isa; +#elif defined(__powerpc__) || defined(__powerpc64__) || defined(__powerpc64le__) + if (setjmp(return_jmp) == 1) + return 0; + + __asm__ __volatile__(".long 0x10011000"); + + return ISA_PPC_VMX; +#elif defined(__arm__) || defined(_M_ARM) + /* Windows on ARM is always Thumb-2, and NEON is always available. */ +#if !defined(_M_ARM) + if (setjmp(return_jmp) == 1) + return 0; + +#if defined(__thumb__) + __asm__ __volatile__(".short 0xef12"); + __asm__ __volatile__(".short 0x0054"); +#else + __asm__ __volatile__(".word 0xf2120054"); +#endif +#endif + + return ISA_ARM_NEON; +#elif defined(__aarch64__) || defined(__arm64__) + return ISA_ARM64_NEON; +#else + return 0; +#endif +} + +int +main() +{ + unsigned isa; + + siginit(); + isa = check_isa(); + + if (isa & ISA_X86_MMX) { + printf("@mmx@"); + } + if (isa & ISA_X86_SSE) { + printf("@sse@"); + } + if (isa & ISA_X86_SSE2) { + printf("@sse2@"); + } + if (isa & ISA_X86_SSE3) { + printf("@sse3@"); + } + if (isa & ISA_X86_SSSE3) { + printf("@ssse3@"); + } + if (isa & ISA_X86_SSE41) { + printf("@sse41@"); + } + if (isa & ISA_X86_SSE42) { + printf("@sse42@"); + } + if (isa & ISA_X86_AVX1) { + printf("@avx@"); + } + if (isa & ISA_X86_AVX2) { + printf("@avx2@"); + } + if (isa & ISA_PPC_VMX) { + printf("@vmx@"); + } + if (isa & ISA_ARM_NEON) { + printf("@neon@"); + } + if (isa & ISA_ARM64_NEON) { + printf("@neon64@"); + } + printf("\n"); + return 0; +} +#else +/* + * This is just compiled when targeting an architecture/system different + * than the host, it is just compiled hence the checks are on the compiler + * features available and not on the real CPU characteristics, as such these + * tests may not do what you want, you may need to force the characteristics + * in that case. + * + * A define TEST_xyz must be defined in order to check the support for the + * specified characteristic. + */ + +#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_AMD64) +#define _X86 +#endif + +#if defined(__powerpc__) || defined(__powerpc64__) || defined(__powerpc64le__) +#define _PPC +#endif + +#if defined(__arm__) +#define _ARM +#endif + +#if defined(__aarch64__) || defined(__arm64__) +#define _ARM64 +#endif + +#if defined(TEST_mmx) && !(defined(_X86) && defined(__MMX__)) +#error "MMX not available" +#endif + +#if defined(TEST_sse) && !(defined(_X86) && defined(__SSE__)) +#error "SSE not available" +#endif + +#if defined(TEST_sse2) && !(defined(_X86) && defined(__SSE2__)) +#error "SSE2 not available" +#endif + +#if defined(TEST_sse3) && !(defined(_X86) && defined(__SSE3__)) +#error "SSE3 not available" +#endif + +#if defined(TEST_ssse3) && !(defined(_X86) && defined(__SSSE3__)) +#error "SSSE3 not available" +#endif + +#if defined(TEST_sse41) && !(defined(_X86) && defined(__SSE4_1__)) +#error "SSE4.1 not available" +#endif + +#if defined(TEST_sse42) && !(defined(_X86) && defined(__SSE4_2__)) +#error "SSE4.2 not available" +#endif + +#if defined(TEST_avx) && !(defined(_X86) && defined(__AVX__)) +#error "AVX1 not available" +#endif + +#if defined(TEST_avx2) && !(defined(_X86) && defined(__AVX2__)) +#error "AVX2 not available" +#endif + +#if defined(TEST_vmx) && !(defined(_PPC) && defined(__ALTIVEC__)) +#error "VMX not available" +#endif + +#if defined(TEST_neon) && !(defined(_ARM) && defined(__ARM_NEON__)) +#error "NEON not available" +#endif + +#if defined(TEST_neon64) && !defined(_ARM64) +#error "NEON64 not available" +#endif + +int main() +{ + return 0; +} +#endif + diff --git a/liquiddsp/cmake/Modules/cmcpuid2.c b/liquiddsp/cmake/Modules/cmcpuid2.c new file mode 100644 index 000000000..b6266bd61 --- /dev/null +++ b/liquiddsp/cmake/Modules/cmcpuid2.c @@ -0,0 +1,113 @@ +/** + * Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies + * + * Please see distribution for license. + */ + +#include +#include +#include +#include + + +/** + * The supported instruction set on this machine for use in other functions. + * + * These must match up with the numbers used in MultiLib.cmake. + */ +typedef enum instructions_available_e +{ + supports_STANDARD = 1, + supports_SSE41 = 2, + supports_SSE42 = 3, + supports_AVX1 = 4, + supports_AVX2 = 5 +} instructions_available; + + +instructions_available getSupportedInstructionSet() { + + // probes of cpuid with %eax=0000_0001h + enum instructions_available_eax0000_0001h_e + { + probe01_SSE_3 = 1<<0, + probe01_SSE_4_1 = 1<<19, + probe01_SSE_4_2 = 1<<20, + probe01_AVX1 = 1<<28 + }; + + // probes of cpuid with %eax=0000_0007h + enum instructions_available_eax0000_0007h_e + { + probe07_AVX2 = 1<<5 + }; + + // the eax register + int32_t EAX; + // contends of the returned register + int32_t supported; + + // Call cpuid with eax=0x00000001 and get ecx + EAX = 0x00000001; + __asm__("cpuid" + :"=c"(supported) // %ecx contains large feature flag set + :"0"(EAX) // call with 0x1 + :"%eax","%ebx","%edx"); // clobbered + + if(supported & probe01_AVX1) // we have at least AVX1 + { + EAX = 0x00000007; + __asm__("cpuid" + :"=b"(supported) // %ebx contains feature flag AVX2 + :"0"(EAX) // call with 0x7 + :"%eax","%ecx","%edx"); // clobbered + + if(supported & probe07_AVX2) // we have at least AVX2 + { + printf("AVX2 SUPPORTED\n"); + return supports_AVX2; + } + printf("AVX1 SUPPORTED\n"); + return supports_AVX1; + } + else if(supported & probe01_SSE_4_1) // we have at least SSE4.1 + { + printf("SSE4.2 SUPPORTED\n"); + return supports_SSE42; + } + else // we have nothing specifically useful! + { + printf("STANDARD SUPPORTED\n"); + return supports_STANDARD; + } +} + + +int main(void) +{ + instructions_available ia; + ia = getSupportedInstructionSet(); + + switch(ia) + { + case supports_AVX2: + printf("AVX2\n"); + break; + case supports_AVX1: + printf("AVX1\n"); + break; + case supports_SSE42: + printf("SSE42\n"); + break; + case supports_SSE41: + printf("SSE41\n"); + break; + case supports_STANDARD: + printf("STANDARD\n"); + break; + default: + printf("Failed to find supported instruction set, this is an error!\n"); + exit(-1); + } + return ia; +} \ No newline at end of file