[hamradio-commits] [gnss-sdr] 116/149: add neon implementation

Carles Fernandez carles_fernandez-guest at moszumanska.debian.org
Sat Feb 6 19:43:10 UTC 2016


This is an automated email from the git hooks/post-receive script.

carles_fernandez-guest pushed a commit to branch next
in repository gnss-sdr.

commit 2d2170604146c4cd010478d8808249a6ab22d07c
Author: Carles Fernandez <carles.fernandez at gmail.com>
Date:   Sun Jan 24 13:02:02 2016 +0100

    add neon implementation
---
 .../volk_gnsssdr_16ic_resamplerxnpuppet_16ic.h     | 27 ++++++
 .../volk_gnsssdr_16ic_xn_resampler_16ic_xn.h       | 96 ++++++++++++++++++++++
 2 files changed, 123 insertions(+)

diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_resamplerxnpuppet_16ic.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_resamplerxnpuppet_16ic.h
index 396ebc3..c3f3e0d 100644
--- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_resamplerxnpuppet_16ic.h
+++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_resamplerxnpuppet_16ic.h
@@ -119,7 +119,34 @@ static inline void volk_gnsssdr_16ic_resamplerxnpuppet_16ic_u_sse2(lv_16sc_t* re
     volk_gnsssdr_free(result_aux);
 }
 
+#endif
+
+#ifdef LV_HAVE_NEON
+
+static inline void volk_gnsssdr_16ic_resamplerxnpuppet_16ic_neon(lv_16sc_t* result, const lv_16sc_t* local_code, unsigned int num_points)
+{
+    float code_phase_step_chips = 0.1;
+    int code_length_chips = 1023;
+    int num_out_vectors = 3;
+    float * rem_code_phase_chips = (float*)volk_gnsssdr_malloc(sizeof(float) * num_out_vectors, volk_gnsssdr_get_alignment());
+    lv_16sc_t** result_aux =  (lv_16sc_t**)volk_gnsssdr_malloc(sizeof(lv_16sc_t*) * num_out_vectors, volk_gnsssdr_get_alignment());
+    for(unsigned int n = 0; n < num_out_vectors; n++)
+    {
+        rem_code_phase_chips[n] = -0.234;
+        result_aux[n] = (lv_16sc_t*)volk_gnsssdr_malloc(sizeof(lv_16sc_t) * num_points, volk_gnsssdr_get_alignment());
+    }
+    volk_gnsssdr_16ic_xn_resampler_16ic_xn_neon(result_aux, local_code, rem_code_phase_chips, code_phase_step_chips, code_length_chips, num_out_vectors, num_points);
+
+    memcpy(result, result_aux[0], sizeof(lv_16sc_t) * num_points);
+    volk_gnsssdr_free(rem_code_phase_chips);
+    for(unsigned int n = 0; n < num_out_vectors; n++)
+    {
+        volk_gnsssdr_free(result_aux[n]);
+    }
+    volk_gnsssdr_free(result_aux);
+}
 
 #endif
 
+
 #endif // INCLUDED_volk_gnsssdr_16ic_resamplerpuppet_16ic_H
diff --git a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_xn_resampler_16ic_xn.h b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_xn_resampler_16ic_xn.h
index e1795d8..a53c67a 100644
--- a/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_xn_resampler_16ic_xn.h
+++ b/src/algorithms/libs/volk_gnsssdr_module/volk_gnsssdr/kernels/volk_gnsssdr/volk_gnsssdr_16ic_xn_resampler_16ic_xn.h
@@ -262,4 +262,100 @@ static inline void volk_gnsssdr_16ic_xn_resampler_16ic_xn_u_sse2(lv_16sc_t** res
 
 #endif /* LV_HAVE_SSE2 */
 
+#ifdef LV_HAVE_NEON
+#include <arm_neon.h>
+
+static inline void volk_gnsssdr_16ic_xn_resampler_16ic_xn_neon(lv_16sc_t** result, const lv_16sc_t* local_code, float* rem_code_phase_chips ,float code_phase_step_chips, unsigned int code_length_chips, int num_out_vectors, unsigned int num_output_samples)
+{
+    unsigned int number;
+    const unsigned int quarterPoints = num_output_samples / 4;
+    float32x4_t half = vdupq_n_f32(0.5f);
+
+    lv_16sc_t** _result = result;
+    __attribute__((aligned(16))) int local_code_chip_index[4];
+    float tmp_rem_code_phase_chips;
+    float32x4_t _rem_code_phase, _code_phase_step_chips;
+    int32x4_t _code_length_chips, _code_length_chips_minus1;
+    float32x4_t _code_phase_out, _code_phase_out_with_offset;
+    float32x4_t sign, PlusHalf, Round;
+
+    _code_phase_step_chips = vld1q_dup_f32(&code_phase_step_chips); //load float to all four float values in float32x4_t register
+    __attribute__((aligned(16))) int four_times_code_length_chips_minus1[4];
+    four_times_code_length_chips_minus1[0] = code_length_chips - 1;
+    four_times_code_length_chips_minus1[1] = code_length_chips - 1;
+    four_times_code_length_chips_minus1[2] = code_length_chips - 1;
+    four_times_code_length_chips_minus1[3] = code_length_chips - 1;
+
+    __attribute__((aligned(16))) int four_times_code_length_chips[4];
+    four_times_code_length_chips[0] = code_length_chips;
+    four_times_code_length_chips[1] = code_length_chips;
+    four_times_code_length_chips[2] = code_length_chips;
+    four_times_code_length_chips[3] = code_length_chips;
+
+    _code_length_chips = vld1q_s32((int32_t*)&four_times_code_length_chips); //load float to all four float values in float32x4_t register
+    _code_length_chips_minus1 = vld1q_s32((int32_t*)&four_times_code_length_chips_minus1); //load float to all four float values in float32x4_t register
+
+    int32x4_t  _code_phase_out_int, _code_phase_out_int_neg, _code_phase_out_int_over;
+    uint32x4_t negative_indexes, overflow_indexes;
+    int32x4_t zero = vmovq_n_s32(0);
+
+    __attribute__((aligned(16))) float init_idx_float[4] = { 0.0f, 1.0f, 2.0f, 3.0f };
+    float32x4_t _4output_index = vld1q_f32(init_idx_float);
+    __attribute__((aligned(16))) float init_4constant_float[4] = { 4.0f, 4.0f, 4.0f, 4.0f };
+    float32x4_t _4constant_float = vld1q_f32(init_4constant_float);
+
+    int current_vector = 0;
+    int sample_idx = 0;
+    for(number = 0; number < quarterPoints; number++)
+        {
+            //common to all outputs
+            _code_phase_out = vmulq_f32(_code_phase_step_chips, _4output_index); //compute the code phase point with the phase step
+
+            //output vector dependant (different code phase offset)
+            for(current_vector = 0; current_vector < num_out_vectors; current_vector++)
+                {
+                    tmp_rem_code_phase_chips = rem_code_phase_chips[current_vector] - 0.5f; // adjust offset to perform correct rounding (chip transition at 0)
+                    _rem_code_phase = vld1q_dup_f32(&tmp_rem_code_phase_chips); //load float to all four float values in float32x4_t register
+
+                    _code_phase_out_with_offset = vaddq_f32(_code_phase_out, _rem_code_phase); //add the phase offset
+                    //_code_phase_out_int = _mm_cvtps_epi32(_code_phase_out_with_offset); //convert to integer
+                    sign = vcvtq_f32_u32((vshrq_n_u32(vreinterpretq_u32_f32(_code_phase_out_with_offset), 31)));
+                    PlusHalf = vaddq_f32(_code_phase_out_with_offset, half);
+                    Round = vsubq_f32(PlusHalf, sign);
+                    _code_phase_out_int = vcvtq_s32_f32(Round);
+
+                    negative_indexes = vcltq_s32(_code_phase_out_int, zero); //test for negative values
+                    _code_phase_out_int_neg = vaddq_s32(_code_phase_out_int, _code_length_chips); //the negative values branch
+                    _code_phase_out_int_neg = veorq_s32(_code_phase_out_int, vandq_s32( (int32x4_t)negative_indexes, veorq_s32( _code_phase_out_int_neg, _code_phase_out_int )));
+
+                    overflow_indexes = vcgtq_s32(_code_phase_out_int_neg, _code_length_chips_minus1); //test for overflow values
+                    _code_phase_out_int_over = vsubq_s32(_code_phase_out_int_neg, _code_length_chips); //the negative values branch
+                    _code_phase_out_int_over = veorq_s32(_code_phase_out_int_neg, vandq_s32( (int32x4_t)overflow_indexes, veorq_s32( _code_phase_out_int_over, _code_phase_out_int_neg )));
+
+                    vst1q_s32((int32_t*)local_code_chip_index, _code_phase_out_int_over); // Store the results back
+
+                    //todo: optimize the local code lookup table with intrinsics, if possible
+                    _result[current_vector][sample_idx] = local_code[local_code_chip_index[0]];
+                    _result[current_vector][sample_idx + 1] = local_code[local_code_chip_index[1]];
+                    _result[current_vector][sample_idx + 2] = local_code[local_code_chip_index[2]];
+                    _result[current_vector][sample_idx + 3] = local_code[local_code_chip_index[3]];
+                }
+            _4output_index = vaddq_f32(_4output_index, _4constant_float);
+            sample_idx += 4;
+        }
+
+    for(number = quarterPoints * 4; number < num_output_samples; number++)
+        {
+            for(current_vector = 0; current_vector < num_out_vectors; current_vector++)
+                {
+                    local_code_chip_index[0] = (int)(code_phase_step_chips * (float)(number) + rem_code_phase_chips[current_vector]);
+                    if (local_code_chip_index[0] < 0.0) local_code_chip_index[0] += code_length_chips - 1;
+                    if (local_code_chip_index[0] > (code_length_chips - 1)) local_code_chip_index[0] -= code_length_chips;
+                    _result[current_vector][number] = local_code[local_code_chip_index[0]];
+                }
+        }
+}
+
+#endif /* LV_HAVE_NEON */
+
 #endif /*INCLUDED_volk_gnsssdr_16ic_xn_resampler_16ic_xn_H*/

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-hamradio/gnss-sdr.git



More information about the pkg-hamradio-commits mailing list