From 5c885627b5a3bbb26773910e801656a506a45c83 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Fri, 9 Oct 2015 14:47:48 +0200 Subject: [PATCH 1/6] Fix building on ArchLinux --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ea860622b..927ba72c8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1085,9 +1085,9 @@ endif(ENABLE_GPROF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MY_CXX_FLAGS}") if(OS_IS_LINUX) - if(${LINUX_DISTRIBUTION} MATCHES "Fedora" OR ${LINUX_DISTRIBUTION} MATCHES "openSUSE") + if(${LINUX_DISTRIBUTION} MATCHES "Fedora" OR ${LINUX_DISTRIBUTION} MATCHES "openSUSE" OR ${LINUX_DISTRIBUTION} MATCHES "ArchLinux") link_libraries(pthread) - endif(${LINUX_DISTRIBUTION} MATCHES "Fedora" OR ${LINUX_DISTRIBUTION} MATCHES "openSUSE") + endif(${LINUX_DISTRIBUTION} MATCHES "Fedora" OR ${LINUX_DISTRIBUTION} MATCHES "openSUSE" OR ${LINUX_DISTRIBUTION} MATCHES "ArchLinux") endif(OS_IS_LINUX) From df6bd17bd844cddf46ce3f7e2a86fcde4a5eb24b Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Sun, 25 Oct 2015 11:26:21 +0100 Subject: [PATCH 2/6] Adding the CGRAN manifest --- MANIFEST.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 MANIFEST.md diff --git a/MANIFEST.md b/MANIFEST.md new file mode 100644 index 000000000..7d8dbe48a --- /dev/null +++ b/MANIFEST.md @@ -0,0 +1,25 @@ +title: gnss.sdr +brief: An open source global navigation satellite systems software defined receiver +tags: + - sdr + - gnss + - gps + - Galileo +author: + - Carles Fernandez-Prades + - Javier Arribas + - et altri (see AUTHORS file for a list of contributors) +copyright_owner: + - The Authors +dependencies: gnuradio (>= 3.7.3), armadillo, gflags, glog, gnutls +license: GPLv3+ +repo: https://github.com/gnss-sdr/gnss-sdr +website: http://gnss-sdr.org +icon: http://a.fsdn.com/con/app/proj/gnss-sdr/screenshots/logo400x400.jpg +--- +Global Navigation Satellite Systems receiver defined by software. It performs all the signal +processing from raw signal samples up to the computation of the Position-Velocity-Time solution, +including code and phase observables. It is able to work with raw data files or, if there is +computational power enough, in real time with suitable radiofrequency front-ends. This software +is mainly developed at [CTTC](http://www.cttc.es "Centre Tecnologic de Telecomunicacions de Catalunya") +with contributions from around the world. More info at [gnss-sdr.org](http://gnss-sdr.org "GNSS-SDR's Homepage"). \ No newline at end of file From 8838e9063e7479c1c6339e0d012724d269e8d000 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Tue, 3 Nov 2015 08:26:27 +0100 Subject: [PATCH 3/6] Fix bug in CGRAN manifest --- MANIFEST.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MANIFEST.md b/MANIFEST.md index 7d8dbe48a..eb7ee5617 100644 --- a/MANIFEST.md +++ b/MANIFEST.md @@ -1,4 +1,4 @@ -title: gnss.sdr +title: gnss-sdr brief: An open source global navigation satellite systems software defined receiver tags: - sdr From 5e3466ff0bd9439d4dda136ab5bf316e9307327e Mon Sep 17 00:00:00 2001 From: sundw Date: Sun, 15 Nov 2015 23:04:42 +0800 Subject: [PATCH 4/6] update version of armadillo in CMakeLists.txt --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 927ba72c8..31cfe90aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -733,8 +733,8 @@ if(NOT ARMADILLO_FOUND) message(STATUS " Armadillo will be downloaded and built automatically ") message(STATUS " when doing 'make'. ") - set(armadillo_RELEASE 5.200.2) - set(armadillo_MD5 "ef57ba4c473a3b67c672441a7face09e") + set(armadillo_RELEASE 6.200.4) + set(armadillo_MD5 "20c9de6ad06b4339a7fd3f67d78922e4") ExternalProject_Add( armadillo-${armadillo_RELEASE} From a26255270e5bf08be0d4362df279fb386a7135d1 Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Fri, 29 Jan 2016 18:43:44 +0100 Subject: [PATCH 5/6] Optimized SSE3 16ic rotator volk_gnsssdr module --- .../volk_gnsssdr_16ic_rotatorpuppet_16ic.h | 16 +- .../volk_gnsssdr_16ic_s32fc_x2_rotator_16ic.h | 292 +++++++++--------- 2 files changed, 146 insertions(+), 162 deletions(-) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_rotatorpuppet_16ic.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_rotatorpuppet_16ic.h index e77b7df1e..87632b2dc 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_rotatorpuppet_16ic.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_rotatorpuppet_16ic.h @@ -24,9 +24,9 @@ static inline void volk_gnsssdr_16ic_rotatorpuppet_16ic_generic(lv_16sc_t* outVe #endif /* LV_HAVE_GENERIC */ -#ifdef LV_HAVE_SSE2 +#ifdef LV_HAVE_SSE3 -static inline void volk_gnsssdr_16ic_rotatorpuppet_16ic_a_sse2(lv_16sc_t* outVector, const lv_16sc_t* inVector, unsigned int num_points) +static inline void volk_gnsssdr_16ic_rotatorpuppet_16ic_a_sse3(lv_16sc_t* outVector, const lv_16sc_t* inVector, unsigned int num_points) { // phases must be normalized. Phase rotator expects a complex exponential input! float rem_carrier_phase_in_rad = 0.345; @@ -35,14 +35,14 @@ static inline void volk_gnsssdr_16ic_rotatorpuppet_16ic_a_sse2(lv_16sc_t* outVec phase[0] = lv_cmake(cos(rem_carrier_phase_in_rad), -sin(rem_carrier_phase_in_rad)); lv_32fc_t phase_inc[1]; phase_inc[0] = lv_cmake(cos(phase_step_rad), -sin(phase_step_rad)); - volk_gnsssdr_16ic_s32fc_x2_rotator_16ic_a_sse2(outVector, inVector, phase_inc[0], phase, num_points); + volk_gnsssdr_16ic_s32fc_x2_rotator_16ic_a_sse3(outVector, inVector, phase_inc[0], phase, num_points); } -#endif /* LV_HAVE_SSE2 */ +#endif /* LV_HAVE_SSE3 */ -#ifdef LV_HAVE_SSE2 +#ifdef LV_HAVE_SSE3 -static inline void volk_gnsssdr_16ic_rotatorpuppet_16ic_u_sse2(lv_16sc_t* outVector, const lv_16sc_t* inVector, unsigned int num_points) +static inline void volk_gnsssdr_16ic_rotatorpuppet_16ic_u_sse3(lv_16sc_t* outVector, const lv_16sc_t* inVector, unsigned int num_points) { // phases must be normalized. Phase rotator expects a complex exponential input! float rem_carrier_phase_in_rad = 0.345; @@ -51,10 +51,10 @@ static inline void volk_gnsssdr_16ic_rotatorpuppet_16ic_u_sse2(lv_16sc_t* outVec phase[0] = lv_cmake(cos(rem_carrier_phase_in_rad), -sin(rem_carrier_phase_in_rad)); lv_32fc_t phase_inc[1]; phase_inc[0] = lv_cmake(cos(phase_step_rad), -sin(phase_step_rad)); - volk_gnsssdr_16ic_s32fc_x2_rotator_16ic_u_sse2(outVector, inVector, phase_inc[0], phase, num_points); + volk_gnsssdr_16ic_s32fc_x2_rotator_16ic_u_sse3(outVector, inVector, phase_inc[0], phase, num_points); } -#endif /* LV_HAVE_SSE2 */ +#endif /* LV_HAVE_SSE3 */ #ifdef LV_HAVE_NEON diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_s32fc_x2_rotator_16ic.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_s32fc_x2_rotator_16ic.h index d926e0f10..aa4fd20b0 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_s32fc_x2_rotator_16ic.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_s32fc_x2_rotator_16ic.h @@ -38,6 +38,7 @@ #include #include +#include #define ROTATOR_RELOAD 512 @@ -72,198 +73,181 @@ static inline void volk_gnsssdr_16ic_s32fc_x2_rotator_16ic_generic(lv_16sc_t* ou #endif /* LV_HAVE_GENERIC */ -#ifdef LV_HAVE_SSE2 -#include +#ifdef LV_HAVE_SSE3 +#include -static inline void volk_gnsssdr_16ic_s32fc_x2_rotator_16ic_a_sse2(lv_16sc_t* outVector, const lv_16sc_t* inVector, const lv_32fc_t phase_inc, lv_32fc_t* phase, unsigned int num_points) +static inline void volk_gnsssdr_16ic_s32fc_x2_rotator_16ic_a_sse3(lv_16sc_t* outVector, const lv_16sc_t* inVector, const lv_32fc_t phase_inc, lv_32fc_t* phase, unsigned int num_points) { const unsigned int sse_iters = num_points / 4; - __m128i a,b,c, c_sr, mask_imag, mask_real, real, imag, imag1,imag2, b_sl, a_sl, result; + __m128 a,b, two_phase_acc_reg,two_phase_inc_reg; + __m128i c1,c2,result; + __attribute__((aligned(16))) lv_32fc_t two_phase_inc[2]; + two_phase_inc[0]=phase_inc*phase_inc; + two_phase_inc[1]=phase_inc*phase_inc; + two_phase_inc_reg=_mm_load_ps((float*) two_phase_inc); + __attribute__((aligned(16))) lv_32fc_t two_phase_acc[2]; + two_phase_acc[0]=(*phase); + two_phase_acc[1]=(*phase)*phase_inc; + two_phase_acc_reg=_mm_load_ps((float*) two_phase_acc); - mask_imag = _mm_set_epi8(255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0); - mask_real = _mm_set_epi8(0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255); + const lv_16sc_t* _in = inVector; - const lv_16sc_t* _in_a = inVector; - __attribute__((aligned(32))) lv_32fc_t four_phase_rotations_32fc[4]; - // debug - //__attribute__((aligned(16))) lv_16sc_t four_phase_rotations_16sc[4]; - - // specify how many bits are used in the rotation (2^(N-1)) (it WILL increase the output signal range!) - __attribute__((aligned(32))) float rotator_amplitude_float[4] = { 4.0f, 4.0f, 4.0f, 4.0f }; - __m128 _rotator_amplitude_reg = _mm_load_ps(rotator_amplitude_float); - - //const lv_16sc_t* _in_b = in_b; lv_16sc_t* _out = outVector; - __m128 fc_reg1, fc_reg2; - __m128i sc_reg1, sc_reg2; // is __m128i defined in xmmintrin.h? + __m128 yl, yh, tmp1, tmp2, tmp3; - for(unsigned int number = 0; number < sse_iters; number++) - { - //std::complex memory structure: real part -> reinterpret_cast(a)[2*i] - //imaginery part -> reinterpret_cast(a)[2*i + 1] - // a[127:0]=[a3.i,a3.r,a2.i,a2.r,a1.i,a1.r,a0.i,a0.r] - a = _mm_load_si128((__m128i*)_in_a); //load (2 byte imag, 2 byte real) x 4 into 128 bits reg - //b = _mm_loadu_si128((__m128i*)_in_b); + for(unsigned int number = 0; number < sse_iters; number++) + { + a = _mm_set_ps((float)(lv_cimag(_in[1])), (float)(lv_creal(_in[1])), (float)(lv_cimag(_in[0])), (float)(lv_creal(_in[0]))); // //load (2 byte imag, 2 byte real) x 2 into 128 bits reg + //complex 32fc multiplication b=a*two_phase_acc_reg + yl = _mm_moveldup_ps(two_phase_acc_reg); // Load yl with cr,cr,dr,dr + yh = _mm_movehdup_ps(two_phase_acc_reg); // Load yh with ci,ci,di,di + tmp1 = _mm_mul_ps(a, yl); // tmp1 = ar*cr,ai*cr,br*dr,bi*dr + a = _mm_shuffle_ps(a, a, 0xB1); // Re-arrange x to be ai,ar,bi,br + tmp2 = _mm_mul_ps(a, yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di + b=_mm_addsub_ps(tmp1, tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di + c1 = _mm_cvtps_epi32(b); // convert from 32fc to 32ic - // compute next four 16ic complex exponential values for phase rotation + //complex 32fc multiplication two_phase_acc_reg=two_phase_acc_reg*two_phase_inc_reg + yl = _mm_moveldup_ps(two_phase_acc_reg); // Load yl with cr,cr,dr,dr + yh = _mm_movehdup_ps(two_phase_acc_reg); // Load yh with ci,ci,di,di + tmp1 = _mm_mul_ps(two_phase_inc_reg, yl); // tmp1 = ar*cr,ai*cr,br*dr,bi*dr + tmp3 = _mm_shuffle_ps(two_phase_inc_reg, two_phase_inc_reg, 0xB1); // Re-arrange x to be ai,ar,bi,br + tmp2 = _mm_mul_ps(tmp3, yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di + two_phase_acc_reg=_mm_addsub_ps(tmp1, tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di - // compute next four float complex rotations - four_phase_rotations_32fc[0]=*phase; - (*phase) *= phase_inc; - four_phase_rotations_32fc[1]=*phase; - (*phase) *= phase_inc; - four_phase_rotations_32fc[2]=*phase; - (*phase) *= phase_inc; - four_phase_rotations_32fc[3]=*phase; - (*phase) *= phase_inc; - //convert the rotations to integers - fc_reg1 = _mm_load_ps((float*)&four_phase_rotations_32fc[0]); + //next two samples + _in += 2; + a = _mm_set_ps((float)(lv_cimag(_in[1])), (float)(lv_creal(_in[1])), (float)(lv_cimag(_in[0])), (float)(lv_creal(_in[0]))); // //load (2 byte imag, 2 byte real) x 2 into 128 bits reg + //complex 32fc multiplication b=a*two_phase_acc_reg + yl = _mm_moveldup_ps(two_phase_acc_reg); // Load yl with cr,cr,dr,dr + yh = _mm_movehdup_ps(two_phase_acc_reg); // Load yh with ci,ci,di,di + tmp1 = _mm_mul_ps(a, yl); // tmp1 = ar*cr,ai*cr,br*dr,bi*dr + a = _mm_shuffle_ps(a, a, 0xB1); // Re-arrange x to be ai,ar,bi,br + tmp2 = _mm_mul_ps(a, yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di + b=_mm_addsub_ps(tmp1, tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di + c2 = _mm_cvtps_epi32(b); // convert from 32fc to 32ic - // disable next line for 1 bit rotation (equivalent to a square wave NCO) - fc_reg1 = _mm_mul_ps (fc_reg1, _rotator_amplitude_reg); + //complex 32fc multiplication two_phase_acc_reg=two_phase_acc_reg*two_phase_inc_reg + yl = _mm_moveldup_ps(two_phase_acc_reg); // Load yl with cr,cr,dr,dr + yh = _mm_movehdup_ps(two_phase_acc_reg); // Load yh with ci,ci,di,di + tmp1 = _mm_mul_ps(two_phase_inc_reg, yl); // tmp1 = ar*cr,ai*cr,br*dr,bi*dr + tmp3 = _mm_shuffle_ps(two_phase_inc_reg, two_phase_inc_reg, 0xB1); // Re-arrange x to be ai,ar,bi,br + tmp2 = _mm_mul_ps(tmp3, yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di + two_phase_acc_reg=_mm_addsub_ps(tmp1, tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di - fc_reg2 = _mm_load_ps((float*)&four_phase_rotations_32fc[2]); - sc_reg1 = _mm_cvtps_epi32(fc_reg1); - sc_reg2 = _mm_cvtps_epi32(fc_reg2); - b = _mm_packs_epi32(sc_reg1, sc_reg2); + // store four output samples + result = _mm_packs_epi32(c1, c2);// convert from 32ic to 16ic + _mm_store_si128((__m128i*)_out, result); - // debug - //_mm_store_si128((__m128i*)four_phase_rotations_16sc, b); - //printf("phase fc: %f,%f phase sc: %i,%i \n",lv_creal(four_phase_rotations_32fc[0]),lv_cimag(four_phase_rotations_32fc[0]),lv_creal(four_phase_rotations_16sc[0]),lv_cimag(four_phase_rotations_16sc[0])); - - // multiply the input vector times the rotations - c = _mm_mullo_epi16 (a, b); // a3.i*b3.i, a3.r*b3.r, .... - - c_sr = _mm_srli_si128 (c, 2); // Shift a right by imm8 bytes while shifting in zeros, and store the results in dst. - real = _mm_subs_epi16 (c, c_sr); - real = _mm_and_si128 (real, mask_real); // a3.r*b3.r-a3.i*b3.i , 0, a3.r*b3.r- a3.i*b3.i - - b_sl = _mm_slli_si128(b, 2); // b3.r, b2.i .... - a_sl = _mm_slli_si128(a, 2); // a3.r, a2.i .... - - imag1 = _mm_mullo_epi16(a, b_sl); // a3.i*b3.r, .... - imag2 = _mm_mullo_epi16(b, a_sl); // b3.i*a3.r, .... - - imag = _mm_adds_epi16(imag1, imag2); - imag = _mm_and_si128 (imag, mask_imag); // a3.i*b3.r+b3.i*a3.r, 0, ... - - result = _mm_or_si128 (real, imag); - - // normalize the rotations - // TODO - - // store results - _mm_store_si128((__m128i*)_out, result); - - _in_a += 4; - _out += 4; - } + //next two samples + _in += 2; + _out += 4; + } + _mm_storeu_ps((float*)two_phase_acc, two_phase_acc_reg); + (*phase) = lv_cmake(two_phase_acc[0], two_phase_acc[0]); + lv_16sc_t tmp16; + lv_32fc_t tmp32; for (unsigned int i = sse_iters * 4; i < num_points; ++i) { - *_out++ = *_in_a++ * (*phase); - (*phase) *= phase_inc; + tmp16 = *_in++; + tmp32 = lv_cmake((float)lv_creal(tmp16), (float)lv_cimag(tmp16)) * (*phase); + *_out++ = lv_cmake((int16_t)rintf(lv_creal(tmp32)), (int16_t)rintf(lv_cimag(tmp32))); + (*phase) *= phase_inc; + } } -#endif /* LV_HAVE_SSE2 */ +#endif /* LV_HAVE_SSE3 */ -#ifdef LV_HAVE_SSE2 -#include +#ifdef LV_HAVE_SSE3 +#include -static inline void volk_gnsssdr_16ic_s32fc_x2_rotator_16ic_u_sse2(lv_16sc_t* outVector, const lv_16sc_t* inVector, const lv_32fc_t phase_inc, lv_32fc_t* phase, unsigned int num_points) +static inline void volk_gnsssdr_16ic_s32fc_x2_rotator_16ic_u_sse3(lv_16sc_t* outVector, const lv_16sc_t* inVector, const lv_32fc_t phase_inc, lv_32fc_t* phase, unsigned int num_points) { const unsigned int sse_iters = num_points / 4; - __m128i a,b,c, c_sr, mask_imag, mask_real, real, imag, imag1,imag2, b_sl, a_sl, result; + __m128 a,b, two_phase_acc_reg,two_phase_inc_reg; + __m128i c1,c2,result; + __attribute__((aligned(16))) lv_32fc_t two_phase_inc[2]; + two_phase_inc[0]=phase_inc*phase_inc; + two_phase_inc[1]=phase_inc*phase_inc; + two_phase_inc_reg=_mm_load_ps((float*) two_phase_inc); + __attribute__((aligned(16))) lv_32fc_t two_phase_acc[2]; + two_phase_acc[0]=(*phase); + two_phase_acc[1]=(*phase)*phase_inc; + two_phase_acc_reg=_mm_load_ps((float*) two_phase_acc); - mask_imag = _mm_set_epi8(255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0); - mask_real = _mm_set_epi8(0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255, 0, 0, 255, 255); + const lv_16sc_t* _in = inVector; - const lv_16sc_t* _in_a = inVector; - __attribute__((aligned(32))) lv_32fc_t four_phase_rotations_32fc[4]; - // debug - //__attribute__((aligned(16))) lv_16sc_t four_phase_rotations_16sc[4]; - - // specify how many bits are used in the rotation (2^(N-1)) (it WILL increase the output signal range!) - __attribute__((aligned(32))) float rotator_amplitude_float[4] = { 4.0f, 4.0f, 4.0f, 4.0f }; - __m128 _rotator_amplitude_reg = _mm_load_ps(rotator_amplitude_float); - - //const lv_16sc_t* _in_b = in_b; lv_16sc_t* _out = outVector; - __m128 fc_reg1, fc_reg2; - __m128i sc_reg1, sc_reg2; // is __m128i defined in xmmintrin.h? + __m128 yl, yh, tmp1, tmp2, tmp3; - for(unsigned int number = 0; number < sse_iters; number++) - { - //std::complex memory structure: real part -> reinterpret_cast(a)[2*i] - //imaginery part -> reinterpret_cast(a)[2*i + 1] - // a[127:0]=[a3.i,a3.r,a2.i,a2.r,a1.i,a1.r,a0.i,a0.r] - a = _mm_loadu_si128((__m128i*)_in_a); //load (2 byte imag, 2 byte real) x 4 into 128 bits reg - //b = _mm_loadu_si128((__m128i*)_in_b); + for(unsigned int number = 0; number < sse_iters; number++) + { + a = _mm_set_ps((float)(lv_cimag(_in[1])), (float)(lv_creal(_in[1])), (float)(lv_cimag(_in[0])), (float)(lv_creal(_in[0]))); // //load (2 byte imag, 2 byte real) x 2 into 128 bits reg + //complex 32fc multiplication b=a*two_phase_acc_reg + yl = _mm_moveldup_ps(two_phase_acc_reg); // Load yl with cr,cr,dr,dr + yh = _mm_movehdup_ps(two_phase_acc_reg); // Load yh with ci,ci,di,di + tmp1 = _mm_mul_ps(a, yl); // tmp1 = ar*cr,ai*cr,br*dr,bi*dr + a = _mm_shuffle_ps(a, a, 0xB1); // Re-arrange x to be ai,ar,bi,br + tmp2 = _mm_mul_ps(a, yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di + b=_mm_addsub_ps(tmp1, tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di + c1 = _mm_cvtps_epi32(b); // convert from 32fc to 32ic - // compute next four 16ic complex exponential values for phase rotation + //complex 32fc multiplication two_phase_acc_reg=two_phase_acc_reg*two_phase_inc_reg + yl = _mm_moveldup_ps(two_phase_acc_reg); // Load yl with cr,cr,dr,dr + yh = _mm_movehdup_ps(two_phase_acc_reg); // Load yh with ci,ci,di,di + tmp1 = _mm_mul_ps(two_phase_inc_reg, yl); // tmp1 = ar*cr,ai*cr,br*dr,bi*dr + tmp3 = _mm_shuffle_ps(two_phase_inc_reg, two_phase_inc_reg, 0xB1); // Re-arrange x to be ai,ar,bi,br + tmp2 = _mm_mul_ps(tmp3, yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di + two_phase_acc_reg=_mm_addsub_ps(tmp1, tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di - // compute next four float complex rotations - four_phase_rotations_32fc[0]=*phase; - (*phase) *= phase_inc; - four_phase_rotations_32fc[1]=*phase; - (*phase) *= phase_inc; - four_phase_rotations_32fc[2]=*phase; - (*phase) *= phase_inc; - four_phase_rotations_32fc[3]=*phase; - (*phase) *= phase_inc; - //convert the rotations to integers - fc_reg1 = _mm_load_ps((float*)&four_phase_rotations_32fc[0]); + //next two samples + _in += 2; + a = _mm_set_ps((float)(lv_cimag(_in[1])), (float)(lv_creal(_in[1])), (float)(lv_cimag(_in[0])), (float)(lv_creal(_in[0]))); // //load (2 byte imag, 2 byte real) x 2 into 128 bits reg + //complex 32fc multiplication b=a*two_phase_acc_reg + yl = _mm_moveldup_ps(two_phase_acc_reg); // Load yl with cr,cr,dr,dr + yh = _mm_movehdup_ps(two_phase_acc_reg); // Load yh with ci,ci,di,di + tmp1 = _mm_mul_ps(a, yl); // tmp1 = ar*cr,ai*cr,br*dr,bi*dr + a = _mm_shuffle_ps(a, a, 0xB1); // Re-arrange x to be ai,ar,bi,br + tmp2 = _mm_mul_ps(a, yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di + b=_mm_addsub_ps(tmp1, tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di + c2 = _mm_cvtps_epi32(b); // convert from 32fc to 32ic - // disable next line for 1 bit rotation (equivalent to a square wave NCO) - fc_reg1 = _mm_mul_ps (fc_reg1, _rotator_amplitude_reg); + //complex 32fc multiplication two_phase_acc_reg=two_phase_acc_reg*two_phase_inc_reg + yl = _mm_moveldup_ps(two_phase_acc_reg); // Load yl with cr,cr,dr,dr + yh = _mm_movehdup_ps(two_phase_acc_reg); // Load yh with ci,ci,di,di + tmp1 = _mm_mul_ps(two_phase_inc_reg, yl); // tmp1 = ar*cr,ai*cr,br*dr,bi*dr + tmp3 = _mm_shuffle_ps(two_phase_inc_reg, two_phase_inc_reg, 0xB1); // Re-arrange x to be ai,ar,bi,br + tmp2 = _mm_mul_ps(tmp3, yh); // tmp2 = ai*ci,ar*ci,bi*di,br*di + two_phase_acc_reg=_mm_addsub_ps(tmp1, tmp2); // ar*cr-ai*ci, ai*cr+ar*ci, br*dr-bi*di, bi*dr+br*di - fc_reg2 = _mm_load_ps((float*)&four_phase_rotations_32fc[2]); - sc_reg1 = _mm_cvtps_epi32(fc_reg1); - sc_reg2 = _mm_cvtps_epi32(fc_reg2); - b = _mm_packs_epi32(sc_reg1, sc_reg2); + // store four output samples + result = _mm_packs_epi32(c1, c2);// convert from 32ic to 16ic + _mm_storeu_si128((__m128i*)_out, result); - // debug - //_mm_store_si128((__m128i*)four_phase_rotations_16sc, b); - //printf("phase fc: %f,%f phase sc: %i,%i \n",lv_creal(four_phase_rotations_32fc[0]),lv_cimag(four_phase_rotations_32fc[0]),lv_creal(four_phase_rotations_16sc[0]),lv_cimag(four_phase_rotations_16sc[0])); - - // multiply the input vector times the rotations - c = _mm_mullo_epi16 (a, b); // a3.i*b3.i, a3.r*b3.r, .... - - c_sr = _mm_srli_si128 (c, 2); // Shift a right by imm8 bytes while shifting in zeros, and store the results in dst. - real = _mm_subs_epi16 (c, c_sr); - real = _mm_and_si128 (real, mask_real); // a3.r*b3.r-a3.i*b3.i , 0, a3.r*b3.r- a3.i*b3.i - - b_sl = _mm_slli_si128(b, 2); // b3.r, b2.i .... - a_sl = _mm_slli_si128(a, 2); // a3.r, a2.i .... - - imag1 = _mm_mullo_epi16(a, b_sl); // a3.i*b3.r, .... - imag2 = _mm_mullo_epi16(b, a_sl); // b3.i*a3.r, .... - - imag = _mm_adds_epi16(imag1, imag2); - imag = _mm_and_si128 (imag, mask_imag); // a3.i*b3.r+b3.i*a3.r, 0, ... - - result = _mm_or_si128 (real, imag); - - // normalize the rotations - // TODO - - // store results - _mm_storeu_si128((__m128i*)_out, result); - - _in_a += 4; - _out += 4; - } + //next two samples + _in += 2; + _out += 4; + } + _mm_storeu_ps((float*)two_phase_acc, two_phase_acc_reg); + (*phase) = lv_cmake(two_phase_acc[0], two_phase_acc[0]); + lv_16sc_t tmp16; + lv_32fc_t tmp32; for (unsigned int i = sse_iters * 4; i < num_points; ++i) { - *_out++ = *_in_a++ * (*phase); - (*phase) *= phase_inc; + tmp16 = *_in++; + tmp32 = lv_cmake((float)lv_creal(tmp16), (float)lv_cimag(tmp16)) * (*phase); + *_out++ = lv_cmake((int16_t)rintf(lv_creal(tmp32)), (int16_t)rintf(lv_cimag(tmp32))); + (*phase) *= phase_inc; + } } -#endif /* LV_HAVE_SSE2 */ + +#endif /* LV_HAVE_SSE3 */ #ifdef LV_HAVE_NEON #include From 8c0781585290772cabc0d70060d97a83a24cc6ec Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Fri, 29 Jan 2016 19:30:31 +0100 Subject: [PATCH 6/6] fix missing time step in neon implementation --- .../volk_gnsssdr/volk_gnsssdr_16ic_s32fc_x2_rotator_16ic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_s32fc_x2_rotator_16ic.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_s32fc_x2_rotator_16ic.h index d926e0f10..e3421baf4 100644 --- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_s32fc_x2_rotator_16ic.h +++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_s32fc_x2_rotator_16ic.h @@ -357,7 +357,7 @@ static inline void volk_gnsssdr_16ic_s32fc_x2_rotator_16ic_neon(lv_16sc_t* outVe vst1q_f32((float32_t*)__phase_real, _phase_real); vst1q_f32((float32_t*)__phase_imag, _phase_imag); - (*phase) = lv_cmake(__phase_real[3], __phase_imag[3]); + (*phase) = lv_cmake((float32_t)__phase_real[3], (float32_t)__phase_imag[3]) * phase_inc; } for(i = 0; i < neon_iters % 4; ++i) {