From 2019ca31eff3b7190cb6b2f3cf53734f95be9486 Mon Sep 17 00:00:00 2001 From: yagoda Date: Fri, 13 Oct 2017 15:35:48 +0100 Subject: [PATCH 01/49] adding neon support for new kernel structure --- lib/include/srslte/phy/utils/simd.h | 319 +++++++++++++++++++++++++--- 1 file changed, 292 insertions(+), 27 deletions(-) diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index 08eed115f..6e4185788 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -121,7 +121,17 @@ #define SRSLTE_SIMD_C16_SIZE 8 #else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON +#define SRSLTE_SIMD_F_SIZE 4 +#define SRSLTE_SIMD_CF_SIZE 4 + +#define SRSLTE_SIMD_I_SIZE 4 + +#define SRSLTE_SIMD_S_SIZE 8 +#define SRSLTE_SIMD_C16_SIZE 8 + +#else /* LV_HAVE_NEON */ #define SRSLTE_SIMD_F_SIZE 0 #define SRSLTE_SIMD_CF_SIZE 0 @@ -147,6 +157,10 @@ typedef __m256 simd_f_t; #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE typedef __m128 simd_f_t; +#else /* HAVE_NEON */ +#ifdef HAVE_NEON +typedef float32x4 simd_f_t; +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -161,6 +175,10 @@ static inline simd_f_t srslte_simd_f_load(float *ptr) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_load_ps(ptr); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vld1q_f32(ptr); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -175,12 +193,16 @@ static inline simd_f_t srslte_simd_f_loadu(float *ptr) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_loadu_ps(ptr); +#else /* LV_HAVE_SSE */ + #ifdef HAVE_NEON + return vld1q_f32(ptr); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ } -static inline void srslte_simd_f_store(float *ptr, simd_f_t simdreg) { +static inline void srslte_simd_f_store(float *ptr, simd_f_t simdreg) {vst1q_f32 #ifdef LV_HAVE_AVX512 _mm512_store_ps(ptr, simdreg); #else /* LV_HAVE_AVX512 */ @@ -189,6 +211,10 @@ static inline void srslte_simd_f_store(float *ptr, simd_f_t simdreg) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE _mm_store_ps(ptr, simdreg); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + vst1q_f32(ptr, simdreg); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -203,6 +229,10 @@ static inline void srslte_simd_f_storeu(float *ptr, simd_f_t simdreg) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE _mm_storeu_ps(ptr, simdreg); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + vst1q_f32(ptr, simdreg); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -217,6 +247,10 @@ static inline simd_f_t srslte_simd_f_set1(float x) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_set1_ps(x); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vdupq_n_f32(x); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -231,6 +265,10 @@ static inline simd_f_t srslte_simd_f_mul(simd_f_t a, simd_f_t b) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_mul_ps(a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vmulq_f32(a,b); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -245,6 +283,10 @@ static inline simd_f_t srslte_simd_f_rcp(simd_f_t a) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_rcp_ps(a); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vrecpeq_f32(a); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -265,6 +307,9 @@ static inline simd_f_t srslte_simd_f_addsub(simd_f_t a, simd_f_t b) { #endif /* LV_HAVE_AVX512 */ } + + + static inline simd_f_t srslte_simd_f_sub(simd_f_t a, simd_f_t b) { #ifdef LV_HAVE_AVX512 return _mm512_sub_ps(a, b); @@ -274,6 +319,10 @@ static inline simd_f_t srslte_simd_f_sub(simd_f_t a, simd_f_t b) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_sub_ps(a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vsubq_f32(a, b); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -286,8 +335,12 @@ static inline simd_f_t srslte_simd_f_add(simd_f_t a, simd_f_t b) { #ifdef LV_HAVE_AVX2 return _mm256_add_ps(a, b); #else /* LV_HAVE_AVX2 */ -#ifdef LV_HAVE_SSE +#ifdef LV_HAVE_SSE return _mm_add_ps(a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vaddq_f32(a, b); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -300,8 +353,12 @@ static inline simd_f_t srslte_simd_f_zero (void) { #ifdef LV_HAVE_AVX2 return _mm256_setzero_ps(); #else /* LV_HAVE_AVX2 */ -#ifdef LV_HAVE_SSE +#ifdef LV_HAVE_SSE return _mm_setzero_ps(); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vdupq_n_f32(0); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -344,6 +401,10 @@ static inline simd_f_t srslte_simd_f_hadd(simd_f_t a, simd_f_t b) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_hadd_ps(a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vcombine_f32( vpadd_f32( vget_low_f32(a), vget_high_f32(a) ), vpadd_f32( vget_low_f32(b), vget_high_f32(b) ) ); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -358,6 +419,10 @@ static inline simd_f_t srslte_simd_f_sqrt(simd_f_t a) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_sqrt_ps(a); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vrecpeq_f32(vrsqrteq_f32(a)); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -368,10 +433,15 @@ static inline simd_f_t srslte_simd_f_sqrt(simd_f_t a) { #if SRSLTE_SIMD_CF_SIZE +#ifdef HAVE_NEON + typedef float32x4x2_t simd_cf_t; +#else typedef struct { simd_f_t re; simd_f_t im; + } simd_cf_t; +#endif /* Complex Single precission Floating point functions */ static inline simd_cf_t srslte_simd_cfi_load(cf_t *ptr) { @@ -399,6 +469,10 @@ static inline simd_cf_t srslte_simd_cfi_load(cf_t *ptr) { __m128 i2 = _mm_load_ps((float*)(ptr + 2)); ret.re = _mm_shuffle_ps(i1, i2, _MM_SHUFFLE(2,0,2,0)); ret.im = _mm_shuffle_ps(i1, i2, _MM_SHUFFLE(3,1,3,1)); +#else +#ifdef HAVE_NEON + ret = vld2q_f32((float*)(ptr)); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -431,6 +505,10 @@ static inline simd_cf_t srslte_simd_cfi_loadu(cf_t *ptr) { __m128 i2 = _mm_loadu_ps((float*)(ptr + 2)); ret.re = _mm_shuffle_ps(i1, i2, _MM_SHUFFLE(2,0,2,0)); ret.im = _mm_shuffle_ps(i1, i2, _MM_SHUFFLE(3,1,3,1)); +#else +#ifdef HAVE_NEON + ret = vld2q_f32((float*)(ptr)); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -450,6 +528,11 @@ static inline simd_cf_t srslte_simd_cf_load(float *re, float *im) { #ifdef LV_HAVE_SSE ret.re = _mm_load_ps(re); ret.im = _mm_load_ps(im); +#else /*HAVE_NEON*/ +#ifdef HAVE_NEON + ret.val[0] = vld1q_f32(ptr); + ret.val[1] = vld1q_f32(ptr); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -469,6 +552,11 @@ static inline simd_cf_t srslte_simd_cf_loadu(float *re, float *im) { #ifdef LV_HAVE_SSE ret.re = _mm_loadu_ps(re); ret.im = _mm_loadu_ps(im); +#else /*HAVE_NEON*/ +#ifdef HAVE_NEON + ret.val[0] = vld1q_f32(ptr); + ret.val[1] = vld1q_f32(ptr); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -497,6 +585,10 @@ static inline void srslte_simd_cfi_store(cf_t *ptr, simd_cf_t simdreg) { #ifdef LV_HAVE_SSE _mm_store_ps((float*)(ptr), _mm_unpacklo_ps(simdreg.re, simdreg.im)); _mm_store_ps((float*)(ptr + 2), _mm_unpackhi_ps(simdreg.re, simdreg.im)); +#else /*HAVE_NEON*/ +#ifdef HAVE_NEON + vst2q_f32((float*)(ptr), simdreg); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -524,6 +616,10 @@ static inline void srslte_simd_cfi_storeu(cf_t *ptr, simd_cf_t simdreg) { #ifdef LV_HAVE_SSE _mm_storeu_ps((float*)(ptr), _mm_unpacklo_ps(simdreg.re, simdreg.im)); _mm_storeu_ps((float*)(ptr + 2), _mm_unpackhi_ps(simdreg.re, simdreg.im)); +#else /*HAVE_NEON*/ +#ifdef HAVE_NEON + vst2q_f32((float*)(ptr), simdreg); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -541,6 +637,11 @@ static inline void srslte_simd_cf_store(float *re, float *im, simd_cf_t simdreg) #ifdef LV_HAVE_SSE _mm_store_ps((float *) re, simdreg.re); _mm_store_ps((float *) im, simdreg.im); +#else /*HAVE_NEON*/ +#ifdef HAVE_NEON + vst1q_f32((float *) re, simdreg.val[0]); + vst1q_f32((float *) im, simdreg.val[1]); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -558,6 +659,11 @@ static inline void srslte_simd_cf_storeu(float *re, float *im, simd_cf_t simdreg #ifdef LV_HAVE_SSE _mm_storeu_ps((float *) re, simdreg.re); _mm_storeu_ps((float *) im, simdreg.im); +#else /*HAVE_NEON*/ +#ifdef HAVE_NEON + vst1q_f32((float *) re, simdreg.val[0]); + vst1q_f32((float *) im, simdreg.val[1]); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -576,6 +682,11 @@ static inline simd_cf_t srslte_simd_cf_set1 (cf_t x) { #ifdef LV_HAVE_SSE ret.re = _mm_set1_ps(__real__ x); ret.im = _mm_set1_ps(__imag__ x); +#else /*HAVE_NEON*/ +#ifdef HAVE_NEON + re.val[0] = vdupq_n_f32(__real__ x); + im.val[1] = vdupq_n_f32(__imag__ x); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -601,6 +712,13 @@ static inline simd_cf_t srslte_simd_cf_prod (simd_cf_t a, simd_cf_t b) { _mm_mul_ps(a.im, b.im)); ret.im = _mm_add_ps(_mm_mul_ps(a.re, b.im), _mm_mul_ps(a.im, b.re)); +#else +#ifdef HAVE_NEON + ret.val[0] = vsubq_f32(vmulq_f32(a.val[0],b.val[0]), + vmulq_f32(a.val[1],b.val[1])); + ret.val[1] = vaddq_f32(vmulq_f32(a.val[0],b.val[1]), + vmulq_f32(a.val[1],b.val[0])); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -626,6 +744,13 @@ static inline simd_cf_t srslte_simd_cf_conjprod (simd_cf_t a, simd_cf_t b) { _mm_mul_ps(a.im, b.im)); ret.im = _mm_sub_ps(_mm_mul_ps(a.im, b.re), _mm_mul_ps(a.re, b.im)); + #else +#ifdef HAVE_NEON + ret.val[0] = vaddq_f32(vmulq_f32(a.val[0],b.val[0]), + vmulq_f32(a.val[1],b.val[1])); + ret.val[1] = vsubq_f32(vmulq_f32(a.val[1],b.val[0]), + vmulq_f32(a.val[0],b.val[1])); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -645,6 +770,11 @@ static inline simd_cf_t srslte_simd_cf_add (simd_cf_t a, simd_cf_t b) { #ifdef LV_HAVE_SSE ret.re = _mm_add_ps(a.re, b.re); ret.im = _mm_add_ps(a.im, b.im); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + ret.val[0] = vaddq_f32(a.val[0],a.val[0]); + ret.val[1] = vaddq_f32(a.val[1],a.val[1]); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -665,6 +795,11 @@ static inline simd_cf_t srslte_simd_cf_mul (simd_cf_t a, simd_f_t b) { #ifdef LV_HAVE_SSE ret.re = _mm_mul_ps(a.re, b); ret.im = _mm_mul_ps(a.im, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + ret.val[0] = vmulq_f32(a.val[0],b); + ret.val[1] = vmulq_f32(a.val[1],b); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -699,6 +834,16 @@ static inline simd_cf_t srslte_simd_cf_rcp (simd_cf_t a) { simd_f_t neg_a_im = _mm_xor_ps(_mm_set1_ps(-0.0f), a.im); ret.re = _mm_mul_ps(a.re, rcp); ret.im = _mm_mul_ps(neg_a_im, rcp); + #else /* LV_HAVE_SSE */ + #ifdef HAVE_NEON + simd_f_t a2re = vmulq_f32(a.val[0], a.val[0]); + simd_f_t a2im = vmulq_f32(a.val[1], a.val[1]); + simd_f_t mod2 = vaddq_f32(a2re, a2im); + simd_f_t rcp = vrecpeq_f32(mod2); + simd_f_t neg_a_im = vnegq_f32(vdupq_n_f32(-0.0f), a.val[1]); + ret.val[0] = vmulq_f32(a.val[0], rcp); + ret.val[1] = vmulq_f32(neg_a_im, rcp); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -718,7 +863,11 @@ static inline simd_cf_t srslte_simd_cf_zero (void) { #ifdef LV_HAVE_SSE ret.re = _mm_setzero_ps(); ret.im = _mm_setzero_ps(); -#endif /* LV_HAVE_SSE */ +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + ret.val[0] = vdupq_n_f32(0); + ret.val[1] = vdupq_n_f32(0); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ return ret; @@ -739,6 +888,11 @@ typedef __m256 simd_sel_t; #ifdef LV_HAVE_SSE typedef __m128i simd_i_t; typedef __m128 simd_sel_t; +#else /* LV_HAVE_AVX2 */ +#ifdef LV_HAVE_SSE +typedef int32x4_t simd_i_t; +typedef __m128 simd_sel_t; +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -752,6 +906,10 @@ static inline simd_i_t srslte_simd_i_load(int *x) { #else #ifdef LV_HAVE_SSE return _mm_load_si128((__m128i*)x); +#else + #ifdef HAVE_NEON + return vld1_s32((int32x4_t*)x); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -780,6 +938,10 @@ static inline simd_i_t srslte_simd_i_set1(int x) { #else #ifdef LV_HAVE_SSE return _mm_set1_epi32(x); +#else + #ifdef HAVE_NEON + return vdupq_n_s32(x); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -794,10 +956,14 @@ static inline simd_i_t srslte_simd_i_add(simd_i_t a, simd_i_t b) { #else #ifdef LV_HAVE_SSE return _mm_add_epi32(a, b); +#else +#ifdef HAVE_NEON + return vaddq_s32(a, b); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ -} +}vcgtq_f32 static inline simd_sel_t srslte_simd_f_max(simd_f_t a, simd_f_t b) { #ifdef LV_HAVE_AVX512 @@ -808,6 +974,10 @@ static inline simd_sel_t srslte_simd_f_max(simd_f_t a, simd_f_t b) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return (simd_sel_t) _mm_cmpgt_ps(a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return (simd_sel_t) vcgtq_f32(a, b); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -841,6 +1011,10 @@ typedef __m256i simd_s_t; #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE typedef __m128i simd_s_t; +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON +typedef int16x8_t simd_s_t; +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -854,6 +1028,10 @@ static inline simd_s_t srslte_simd_s_load(int16_t *ptr) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_load_si128((__m128i*) ptr); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vld1q_s16((int16x8_t*) ptr); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -867,7 +1045,11 @@ static inline simd_s_t srslte_simd_s_loadu(int16_t *ptr) { return _mm256_loadu_si256((__m256i*) ptr); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE - return _mm_loadu_si128((__m128i*) ptr); + return _mm_loadu_si128((__m128i*) ptr) +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vld1q_s16((int16x8_t*) ptr); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -882,6 +1064,10 @@ static inline void srslte_simd_s_store(int16_t *ptr, simd_s_t simdreg) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE _mm_store_si128((__m128i*) ptr, simdreg); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + vst1q_s16((int16x8_t*) ptr, simdreg); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -896,11 +1082,15 @@ static inline void srslte_simd_s_storeu(int16_t *ptr, simd_s_t simdreg) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE _mm_storeu_si128((__m128i*) ptr, simdreg); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + vst1q_s16((int16x8_t*) ptr, simdreg); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ } - +vdupq_n_s16 static inline simd_s_t srslte_simd_s_zero(void) { #ifdef LV_HAVE_AVX512 return _mm512_setzero_si512(); @@ -910,10 +1100,14 @@ static inline simd_s_t srslte_simd_s_zero(void) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_setzero_si128(); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vdupq_n_s16(0); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ -} +}vmulq_s16 static inline simd_s_t srslte_simd_s_mul(simd_s_t a, simd_s_t b) { #ifdef LV_HAVE_AVX512 @@ -924,6 +1118,10 @@ static inline simd_s_t srslte_simd_s_mul(simd_s_t a, simd_s_t b) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_mullo_epi16(a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vmulq_s16(a, b); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -938,6 +1136,10 @@ static inline simd_s_t srslte_simd_s_add(simd_s_t a, simd_s_t b) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_add_epi16(a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vaddq_s16(a, b); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -952,6 +1154,10 @@ static inline simd_s_t srslte_simd_s_sub(simd_s_t a, simd_s_t b) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_sub_epi16(a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vsubq_s16(a, b); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -962,8 +1168,9 @@ static inline simd_s_t srslte_simd_s_sub(simd_s_t a, simd_s_t b) { #if SRSLTE_SIMD_C16_SIZE -typedef struct { +typedef #ifdef LV_HAVE_AVX512 + struct { union { __m512i m512; int16_t i16[32]; @@ -974,24 +1181,32 @@ typedef struct { } im; #else /* LV_HAVE_AVX512 */ #ifdef LV_HAVE_AVX2 - union { - __m256i m256; - int16_t i16[16]; - } re; - union { - __m256i m256; - int16_t i16[16]; - } im; + struct { + union { + __m256i m256; + int16_t i16[16]; + } re; + union { + __m256i m256; + int16_t i16[16]; + } im; #else #ifdef LV_HAVE_SSE - union { - __m128i m128; - int16_t i16[8]; - } re; - union { - __m128i m128; - int16_t i16[8]; - } im; + struct { + union { + __m128i m128; + int16_t i16[8]; + } re; + union { + __m128i m128; + int16_t i16[8]; + } im; +#else +#ifdef HAVE_NEON + union { + int16x8x2_t m128; + int16_t i16[16]; +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -1017,6 +1232,10 @@ static inline simd_c16_t srslte_simd_c16i_load(c16_t *ptr) { __m128i in2 = _mm_load_si128((__m128i*)(ptr + 8)); ret.re.m128 = _mm_blend_epi16(in1,_mm_shufflelo_epi16(_mm_shufflehi_epi16(in2, 0b10100000), 0b10100000), 0b10101010); ret.im.m128 = _mm_blend_epi16(_mm_shufflelo_epi16(_mm_shufflehi_epi16(in1, 0b11110101), 0b11110101),in2, 0b10101010); +#else /* LV_HAVE_SSE*/ +#ifdef HAVE_NEON + ret.m128 = vld2q_s16((int16_t*)(ptr)); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -1032,6 +1251,11 @@ static inline simd_c16_t srslte_simd_c16_load(int16_t *re, int16_t *im) { #ifdef LV_HAVE_SSE ret.re.m128 = _mm_load_si128((__m128i*)(re)); ret.im.m128 = _mm_load_si128((__m128i*)(im)); +#else /* LV_HAVE_SSE*/ +#ifdef HAVE_NEON + ret.m128.val[0] = vld1q_s16((int16_t*)(re)); + ret.m128.val[1] = vld1q_s16((int16_t*)(im)); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ return ret; @@ -1046,6 +1270,11 @@ static inline simd_c16_t srslte_simd_c16_loadu(int16_t *re, int16_t *im) { #ifdef LV_HAVE_SSE ret.re.m128 = _mm_loadu_si128((__m128i*)(re)); ret.im.m128 = _mm_loadu_si128((__m128i*)(im)); +#else /* LV_HAVE_SSE*/ +#ifdef HAVE_NEON + ret.m128.val[0] = vld1q_s16((int16_t*)(re)); + ret.m128.val[1] = vld1q_s16((int16_t*)(im)); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ return ret; @@ -1063,6 +1292,10 @@ static inline void srslte_simd_c16i_store(c16_t *ptr, simd_c16_t simdreg) { __m128i im_sw = _mm_shufflelo_epi16(_mm_shufflehi_epi16(simdreg.im.m128, 0b10110001), 0b10110001); _mm_store_si128((__m128i *) (ptr), _mm_blend_epi16(simdreg.re.m128, im_sw, 0b10101010)); _mm_store_si128((__m128i *) (ptr + 8), _mm_blend_epi16(re_sw, simdreg.im.m128, 0b10101010)); +#else /*HAVE_NEON*/ +#ifdef HAVE_NEON + vst2q_f32((float*)(ptr) ,simdreg); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ } @@ -1079,6 +1312,10 @@ static inline void srslte_simd_c16i_storeu(c16_t *ptr, simd_c16_t simdreg) { __m128i im_sw = _mm_shufflelo_epi16(_mm_shufflehi_epi16(simdreg.im.m128, 0b10110001), 0b10110001); _mm_storeu_si128((__m128i *) (ptr), _mm_blend_epi16(simdreg.re.m128, im_sw, 0b10101010)); _mm_storeu_si128((__m128i *) (ptr + 8), _mm_blend_epi16(re_sw, simdreg.im.m128, 0b10101010)); +#else /*HAVE_NEON*/ +#ifdef HAVE_NEON + vst2q_f32((float*)(ptr) ,simdreg); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ } @@ -1091,6 +1328,11 @@ static inline void srslte_simd_c16_store(int16_t *re, int16_t *im, simd_c16_t si #ifdef LV_HAVE_SSE _mm_store_si128((__m128i *) re, simdreg.re.m128); _mm_store_si128((__m128i *) im, simdreg.im.m128); +#else +#ifdef HAVE_NEON + vst1q_f32((int16_t *) re, simdreg.m128.val[0]); + vst1q_f32((int16_t *) im, simdreg.m128.val[1]); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ } @@ -1103,10 +1345,17 @@ static inline void srslte_simd_c16_storeu(int16_t *re, int16_t *im, simd_c16_t s #ifdef LV_HAVE_SSE _mm_storeu_si128((__m128i *) re, simdreg.re.m128); _mm_storeu_si128((__m128i *) im, simdreg.im.m128); +#else +#ifdef HAVE_NEON + vst1q_f32((int16_t *) re, simdreg.m128.val[0]); + vst1q_f32((int16_t *) im, simdreg.m128.val[1]); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ } + +//TODO static inline simd_c16_t srslte_simd_c16_prod (simd_c16_t a, simd_c16_t b) { simd_c16_t ret; #ifdef LV_HAVE_AVX2 @@ -1134,11 +1383,16 @@ static inline simd_c16_t srslte_simd_c16_add (simd_c16_t a, simd_c16_t b) { #ifdef LV_HAVE_SSE ret.re.m128 = _mm_add_epi16(a.re.m128, b.re.m128); ret.im.m128 = _mm_add_epi16(a.im.m128, b.im.m128); +#else +#ifdef HAVE_NEON + ret.m128.val[0] = vaddq_s32(a.m127.val[0],a.m127.val[0]); + ret.m128.val[1] = vaddq_s32(a.m127.val[1],a.m127.val[1]); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ return ret; } - +vdupq_n_s16 static inline simd_c16_t srslte_simd_c16_zero (void) { simd_c16_t ret; #ifdef LV_HAVE_AVX2 @@ -1148,7 +1402,12 @@ static inline simd_c16_t srslte_simd_c16_zero (void) { #ifdef LV_HAVE_SSE ret.re.m128 = _mm_setzero_si128(); ret.im.m128 = _mm_setzero_si128(); -#endif /* LV_HAVE_SSE */ +#else +#ifdef HAVE_NEON + ret.m128.val[0] = vdupq_n_s16(0); + ret.m128.val[1] = vdupq_n_s16(0); +#endif /* HAVE_NEON */ +#endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ return ret; } @@ -1182,6 +1441,12 @@ static inline simd_s_t srslte_simd_convert_2f_s(simd_f_t a, simd_f_t b) { __m128i ai = _mm_cvttps_epi32(a); __m128i bi = _mm_cvttps_epi32(b); return _mm_packs_epi32(ai, bi); + #else +#ifdef HAVE_NEON + int32x4_t ai = vcvtq_s32_f32(a); + int32x4_t bi = vcvtq_s32_f32(b); + return (simd_s_t)vcombine_s16(vqmovn_s32(ai), vqmovn_s32(bi)); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ From 2a381c109c9b5a21a9d6699bffb86ed5b7f918d3 Mon Sep 17 00:00:00 2001 From: ilshatDesu <32833109+ilshatDesu@users.noreply.github.com> Date: Mon, 16 Oct 2017 10:59:37 +0300 Subject: [PATCH 02/49] Update enb_cfg_parser.cc Non critical error in SIB1. CellIdentity is constucted from eNBID and SectorID. --- srsenb/src/enb_cfg_parser.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 3beb85a65..00f01d498 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -749,7 +749,7 @@ int enb::parse_sibs(all_args_t *args, rrc_cfg_t *rrc_cfg, phy_cfg_t *phy_config_ } // Fill rest of data from enb config - sib1->cell_id = args->enb.s1ap.enb_id; + sib1->cell_id = (args->enb.s1ap.enb_id << 8) + args->enb.s1ap.cell_id; sib1->tracking_area_code = args->enb.s1ap.tac; sib1->freq_band_indicator = srslte_band_get_band(args->rf.dl_earfcn); sib1->N_plmn_ids = 1; From f4b9e7311a1daa4b306c9e8bebd3c956db3e6cad Mon Sep 17 00:00:00 2001 From: yagoda Date: Tue, 17 Oct 2017 15:51:27 +0000 Subject: [PATCH 03/49] adding neon support to new vector structure --- lib/include/srslte/phy/utils/simd.h | 123 +++++++++++++++++++--------- lib/src/phy/utils/vector_simd.c | 37 +++++++-- 2 files changed, 116 insertions(+), 44 deletions(-) diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index 6e4185788..e7820c307 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -33,6 +33,11 @@ #endif #include #endif /* LV_HAVE_SSE */ +#include + +#ifdef HAVE_NEON +#include +#endif /* * SSE Macros @@ -140,6 +145,7 @@ #define SRSLTE_SIMD_S_SIZE 0 #define SRSLTE_SIMD_C16_SIZE 0 +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -159,7 +165,7 @@ typedef __m256 simd_f_t; typedef __m128 simd_f_t; #else /* HAVE_NEON */ #ifdef HAVE_NEON -typedef float32x4 simd_f_t; +typedef float32x4_t simd_f_t; #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -188,7 +194,7 @@ static inline simd_f_t srslte_simd_f_loadu(float *ptr) { #ifdef LV_HAVE_AVX512 return _mm512_loadu_ps(ptr); #else /* LV_HAVE_AVX512 */ - #ifdef LV_HAVE_AVX2 + #ifdef LV_HAVE_AVX2 return _mm256_loadu_ps(ptr); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE @@ -202,7 +208,7 @@ static inline simd_f_t srslte_simd_f_loadu(float *ptr) { #endif /* LV_HAVE_AVX512 */ } -static inline void srslte_simd_f_store(float *ptr, simd_f_t simdreg) {vst1q_f32 +static inline void srslte_simd_f_store(float *ptr, simd_f_t simdreg) { #ifdef LV_HAVE_AVX512 _mm512_store_ps(ptr, simdreg); #else /* LV_HAVE_AVX512 */ @@ -281,11 +287,11 @@ static inline simd_f_t srslte_simd_f_rcp(simd_f_t a) { #ifdef LV_HAVE_AVX2 return _mm256_rcp_ps(a); #else /* LV_HAVE_AVX2 */ - #ifdef LV_HAVE_SSE +#ifdef LV_HAVE_SSE return _mm_rcp_ps(a); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON - return vrecpeq_f32(a); + return vmulq_f32(vrecpeq_f32(a), vrecpsq_f32(vrecpeq_f32(a), a)); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -302,6 +308,22 @@ static inline simd_f_t srslte_simd_f_addsub(simd_f_t a, simd_f_t b) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_addsub_ps(a, b); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON // CURRENTLY USES GENERIC IMPLEMENTATION FOR NEON + float* a_ptr = &a; + float* b_ptr = &b; + simd_f_t ret; + float* c_ptr = &ret; + for(int i = 0; i<4;i++){ + if(i%2==0){ + c_ptr[i] = a_ptr[i] - b_ptr[i]; + }else{ + c_ptr[i] = a_ptr[i] + b_ptr[i]; + } + } + + return ret; +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -373,6 +395,10 @@ static inline simd_f_t srslte_simd_f_swap(simd_f_t a) { #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE return _mm_shuffle_ps(a, a, 0b10110001); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON + return vcombine_f32(vrev64_f32(vget_low_f32(a)), vrev64_f32(vget_high_f32(a))); +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -421,7 +447,9 @@ static inline simd_f_t srslte_simd_f_sqrt(simd_f_t a) { return _mm_sqrt_ps(a); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON - return vrecpeq_f32(vrsqrteq_f32(a)); + float32x4_t sqrt_reciprocal = vrsqrteq_f32(a); + sqrt_reciprocal = vmulq_f32(vrsqrtsq_f32(vmulq_f32(a,sqrt_reciprocal), sqrt_reciprocal),sqrt_reciprocal); + return vmulq_f32(a,sqrt_reciprocal); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -530,8 +558,8 @@ static inline simd_cf_t srslte_simd_cf_load(float *re, float *im) { ret.im = _mm_load_ps(im); #else /*HAVE_NEON*/ #ifdef HAVE_NEON - ret.val[0] = vld1q_f32(ptr); - ret.val[1] = vld1q_f32(ptr); + ret.val[0] = vld1q_f32(re); + ret.val[1] = vld1q_f32(im); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -554,8 +582,8 @@ static inline simd_cf_t srslte_simd_cf_loadu(float *re, float *im) { ret.im = _mm_loadu_ps(im); #else /*HAVE_NEON*/ #ifdef HAVE_NEON - ret.val[0] = vld1q_f32(ptr); - ret.val[1] = vld1q_f32(ptr); + ret.val[0] = vld1q_f32(re); + ret.val[1] = vld1q_f32(im); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -684,8 +712,8 @@ static inline simd_cf_t srslte_simd_cf_set1 (cf_t x) { ret.im = _mm_set1_ps(__imag__ x); #else /*HAVE_NEON*/ #ifdef HAVE_NEON - re.val[0] = vdupq_n_f32(__real__ x); - im.val[1] = vdupq_n_f32(__imag__ x); + ret.val[0] = vdupq_n_f32(__real__ x); + ret.val[1] = vdupq_n_f32(__imag__ x); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -772,8 +800,8 @@ static inline simd_cf_t srslte_simd_cf_add (simd_cf_t a, simd_cf_t b) { ret.im = _mm_add_ps(a.im, b.im); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON - ret.val[0] = vaddq_f32(a.val[0],a.val[0]); - ret.val[1] = vaddq_f32(a.val[1],a.val[1]); + ret.val[0] = vaddq_f32(a.val[0],b.val[0]); + ret.val[1] = vaddq_f32(a.val[1],b.val[1]); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -839,8 +867,8 @@ static inline simd_cf_t srslte_simd_cf_rcp (simd_cf_t a) { simd_f_t a2re = vmulq_f32(a.val[0], a.val[0]); simd_f_t a2im = vmulq_f32(a.val[1], a.val[1]); simd_f_t mod2 = vaddq_f32(a2re, a2im); - simd_f_t rcp = vrecpeq_f32(mod2); - simd_f_t neg_a_im = vnegq_f32(vdupq_n_f32(-0.0f), a.val[1]); + simd_f_t rcp = vmulq_f32(vrecpeq_f32(mod2), vrecpsq_f32(vrecpeq_f32(mod2), mod2)); + simd_f_t neg_a_im = vnegq_f32(a.val[1]); ret.val[0] = vmulq_f32(a.val[0], rcp); ret.val[1] = vmulq_f32(neg_a_im, rcp); #endif /* HAVE_NEON */ @@ -868,6 +896,7 @@ static inline simd_cf_t srslte_simd_cf_zero (void) { ret.val[0] = vdupq_n_f32(0); ret.val[1] = vdupq_n_f32(0); #endif /* HAVE_NEON */ +#endif /* HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ return ret; @@ -889,9 +918,9 @@ typedef __m256 simd_sel_t; typedef __m128i simd_i_t; typedef __m128 simd_sel_t; #else /* LV_HAVE_AVX2 */ -#ifdef LV_HAVE_SSE +#ifdef HAVE_NEON typedef int32x4_t simd_i_t; -typedef __m128 simd_sel_t; +typedef int32x4_t simd_sel_t; #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -908,7 +937,7 @@ static inline simd_i_t srslte_simd_i_load(int *x) { return _mm_load_si128((__m128i*)x); #else #ifdef HAVE_NEON - return vld1_s32((int32x4_t*)x); + return vld1q_s32((int*)x); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -924,6 +953,10 @@ static inline void srslte_simd_i_store(int *x, simd_i_t reg) { #else #ifdef LV_HAVE_SSE _mm_store_si128((__m128i*)x, reg); +#else +#ifdef HAVE_NEON + vst1q_s32((int*)x, reg); +#endif /*HAVE_NEON*/ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -963,7 +996,7 @@ static inline simd_i_t srslte_simd_i_add(simd_i_t a, simd_i_t b) { #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ -}vcgtq_f32 +} static inline simd_sel_t srslte_simd_f_max(simd_f_t a, simd_f_t b) { #ifdef LV_HAVE_AVX512 @@ -992,6 +1025,25 @@ static inline simd_i_t srslte_simd_i_select(simd_i_t a, simd_i_t b, simd_sel_t s #else #ifdef LV_HAVE_SSE return (__m128i) _mm_blendv_ps((__m128)a, (__m128)b, selector); +#else /* LV_HAVE_SSE */ +#ifdef HAVE_NEON // CURRENTLY USES GENERIC IMPLEMENTATION FOR NEON + + int* a_ptr = &a; + int* b_ptr = &b; + simd_i_t ret; + int* sel = &selector; + + int* c_ptr = &ret; + for(int i = 0;i<4;i++) + { + if(sel[i] == -1){ + c_ptr[i] = b_ptr[i]; + }else{ + c_ptr[i] = a_ptr[i]; + } + } + return ret; +#endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ @@ -1030,7 +1082,7 @@ static inline simd_s_t srslte_simd_s_load(int16_t *ptr) { return _mm_load_si128((__m128i*) ptr); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON - return vld1q_s16((int16x8_t*) ptr); + return vld1q_s16(ptr); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -1048,7 +1100,7 @@ static inline simd_s_t srslte_simd_s_loadu(int16_t *ptr) { return _mm_loadu_si128((__m128i*) ptr) #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON - return vld1q_s16((int16x8_t*) ptr); + return vld1q_s16(ptr); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -1066,7 +1118,7 @@ static inline void srslte_simd_s_store(int16_t *ptr, simd_s_t simdreg) { _mm_store_si128((__m128i*) ptr, simdreg); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON - vst1q_s16((int16x8_t*) ptr, simdreg); + vst1q_s16( ptr, simdreg); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -1084,13 +1136,12 @@ static inline void srslte_simd_s_storeu(int16_t *ptr, simd_s_t simdreg) { _mm_storeu_si128((__m128i*) ptr, simdreg); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON - vst1q_s16((int16x8_t*) ptr, simdreg); + vst1q_s16(ptr, simdreg); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ } -vdupq_n_s16 static inline simd_s_t srslte_simd_s_zero(void) { #ifdef LV_HAVE_AVX512 return _mm512_setzero_si512(); @@ -1107,7 +1158,7 @@ static inline simd_s_t srslte_simd_s_zero(void) { #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ #endif /* LV_HAVE_AVX512 */ -}vmulq_s16 +} static inline simd_s_t srslte_simd_s_mul(simd_s_t a, simd_s_t b) { #ifdef LV_HAVE_AVX512 @@ -1294,7 +1345,7 @@ static inline void srslte_simd_c16i_store(c16_t *ptr, simd_c16_t simdreg) { _mm_store_si128((__m128i *) (ptr + 8), _mm_blend_epi16(re_sw, simdreg.im.m128, 0b10101010)); #else /*HAVE_NEON*/ #ifdef HAVE_NEON - vst2q_f32((float*)(ptr) ,simdreg); + vst2q_s16((int16_t*)(ptr) ,simdreg.m128); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -1314,7 +1365,7 @@ static inline void srslte_simd_c16i_storeu(c16_t *ptr, simd_c16_t simdreg) { _mm_storeu_si128((__m128i *) (ptr + 8), _mm_blend_epi16(re_sw, simdreg.im.m128, 0b10101010)); #else /*HAVE_NEON*/ #ifdef HAVE_NEON - vst2q_f32((float*)(ptr) ,simdreg); + vst2q_s16((int16_t*)(ptr) ,simdreg.m128); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -1330,8 +1381,8 @@ static inline void srslte_simd_c16_store(int16_t *re, int16_t *im, simd_c16_t si _mm_store_si128((__m128i *) im, simdreg.im.m128); #else #ifdef HAVE_NEON - vst1q_f32((int16_t *) re, simdreg.m128.val[0]); - vst1q_f32((int16_t *) im, simdreg.m128.val[1]); + vst1q_s16((int16_t *) re, simdreg.m128.val[0]); + vst1q_s16((int16_t *) im, simdreg.m128.val[1]); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ @@ -1347,15 +1398,13 @@ static inline void srslte_simd_c16_storeu(int16_t *re, int16_t *im, simd_c16_t s _mm_storeu_si128((__m128i *) im, simdreg.im.m128); #else #ifdef HAVE_NEON - vst1q_f32((int16_t *) re, simdreg.m128.val[0]); - vst1q_f32((int16_t *) im, simdreg.m128.val[1]); + vst1q_s16((int16_t *) re, simdreg.m128.val[0]); + vst1q_s16((int16_t *) im, simdreg.m128.val[1]); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ } - -//TODO static inline simd_c16_t srslte_simd_c16_prod (simd_c16_t a, simd_c16_t b) { simd_c16_t ret; #ifdef LV_HAVE_AVX2 @@ -1385,14 +1434,14 @@ static inline simd_c16_t srslte_simd_c16_add (simd_c16_t a, simd_c16_t b) { ret.im.m128 = _mm_add_epi16(a.im.m128, b.im.m128); #else #ifdef HAVE_NEON - ret.m128.val[0] = vaddq_s32(a.m127.val[0],a.m127.val[0]); - ret.m128.val[1] = vaddq_s32(a.m127.val[1],a.m127.val[1]); + ret.m128.val[0] = vaddq_s16(a.m128.val[0],a.m128.val[0]); + ret.m128.val[1] = vaddq_s16(a.m128.val[1],a.m128.val[1]); #endif /* HAVE_NEON */ #endif /* LV_HAVE_SSE */ #endif /* LV_HAVE_AVX2 */ return ret; } -vdupq_n_s16 + static inline simd_c16_t srslte_simd_c16_zero (void) { simd_c16_t ret; #ifdef LV_HAVE_AVX2 diff --git a/lib/src/phy/utils/vector_simd.c b/lib/src/phy/utils/vector_simd.c index 0294bd1af..ab281a653 100644 --- a/lib/src/phy/utils/vector_simd.c +++ b/lib/src/phy/utils/vector_simd.c @@ -751,10 +751,37 @@ void srslte_vec_div_fff_simd(float *x, float *y, float *z, int len) { } } + + +int srslte_vec_sc_prod_ccc_simd2(cf_t *x, cf_t h, cf_t *z, int len) +{ + int i = 0; + const unsigned int loops = len / 4; +#ifdef HAVE_NEON + simd_cf_t h_vec; + h_vec.val[0] = srslte_simd_f_set1(__real__ h); + h_vec.val[1] = srslte_simd_f_set1(__imag__ h); + for (; i < loops; i++) { + + simd_cf_t in = srslte_simd_cfi_load(&x[i*4]); + simd_cf_t temp = srslte_simd_cf_prod(in, h_vec); + srslte_simd_cfi_store(&z[i*4], temp); + } + +#endif + i = loops * 4; +return i; +} + void srslte_vec_sc_prod_ccc_simd(cf_t *x, cf_t h, cf_t *z, int len) { int i = 0; #if SRSLTE_SIMD_F_SIZE + + +#ifdef HAVE_NEON + i = srslte_vec_sc_prod_ccc_simd2(x, h, z, len); +#else const simd_f_t hre = srslte_simd_f_set1(__real__ h); const simd_f_t him = srslte_simd_f_set1(__imag__ h); @@ -766,8 +793,8 @@ void srslte_vec_sc_prod_ccc_simd(cf_t *x, cf_t h, cf_t *z, int len) { simd_f_t sw = srslte_simd_f_swap(temp); simd_f_t m2 = srslte_simd_f_mul(him, sw); simd_f_t r = srslte_simd_f_addsub(m1, m2); - srslte_simd_f_store((float *) &z[i], r); + } } else { for (; i < len - SRSLTE_SIMD_F_SIZE / 2 + 1; i += SRSLTE_SIMD_F_SIZE / 2) { @@ -782,10 +809,11 @@ void srslte_vec_sc_prod_ccc_simd(cf_t *x, cf_t h, cf_t *z, int len) { } } #endif - +#endif for (; i < len; i++) { z[i] = x[i] * h; } + } void srslte_vec_sc_prod_fff_simd(float *x, float h, float *z, int len) { @@ -831,7 +859,6 @@ void srslte_vec_abs_cf_simd(cf_t *x, float *z, int len) { simd_f_t z1 = srslte_simd_f_hadd(mul1, mul2); z1 = srslte_simd_f_sqrt(z1); - srslte_simd_f_store(&z[i], z1); } } else { @@ -966,9 +993,7 @@ uint32_t srslte_vec_max_fi_simd(float *x, int len) { if (SRSLTE_IS_ALIGNED(x)) { for (; i < len - SRSLTE_SIMD_I_SIZE + 1; i += SRSLTE_SIMD_I_SIZE) { simd_f_t a = srslte_simd_f_load(&x[i]); - simd_sel_t res = srslte_simd_f_max(a, simd_max_values); - simd_max_indexes = srslte_simd_i_select(simd_max_indexes, simd_indexes, res); simd_max_values = (simd_f_t) srslte_simd_i_select((simd_i_t) simd_max_values, (simd_i_t) a, res); simd_indexes = srslte_simd_i_add(simd_indexes, simd_inc); @@ -976,9 +1001,7 @@ uint32_t srslte_vec_max_fi_simd(float *x, int len) { } else { for (; i < len - SRSLTE_SIMD_I_SIZE + 1; i += SRSLTE_SIMD_I_SIZE) { simd_f_t a = srslte_simd_f_loadu(&x[i]); - simd_sel_t res = srslte_simd_f_max(a, simd_max_values); - simd_max_indexes = srslte_simd_i_select(simd_max_indexes, simd_indexes, res); simd_max_values = (simd_f_t) srslte_simd_i_select((simd_i_t) simd_max_values, (simd_i_t) a, res); simd_indexes = srslte_simd_i_add(simd_indexes, simd_inc); From 2b0b57176f08b00ffac338742e931fbc35ccde69 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 17 Oct 2017 12:10:31 -0400 Subject: [PATCH 04/49] Removed pid from demux --- srsue/hdr/mac/demux.h | 14 ++++++------ srsue/hdr/mac/dl_harq.h | 13 +++++------ srsue/src/mac/demux.cc | 48 +++++++++++++++++++---------------------- srsue/src/mac/mac.cc | 1 - 4 files changed, 37 insertions(+), 39 deletions(-) diff --git a/srsue/hdr/mac/demux.h b/srsue/hdr/mac/demux.h index 8b722e8c9..fb38990ec 100644 --- a/srsue/hdr/mac/demux.h +++ b/srsue/hdr/mac/demux.h @@ -41,14 +41,16 @@ namespace srsue { class demux : public srslte::pdu_queue::process_callback { public: - demux(uint8_t nof_harq_proc_); + demux(); void init(phy_interface_mac_common* phy_h_, rlc_interface_mac *rlc, srslte::log* log_h_, srslte::timers::timer* time_alignment_timer); bool process_pdus(); - uint8_t* request_buffer(uint32_t pid, uint32_t len); + uint8_t* request_buffer(uint32_t len); + uint8_t* request_buffer_bcch(uint32_t len); void deallocate(uint8_t* payload_buffer_ptr); - void push_pdu(uint32_t pid, uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp); + void push_pdu(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp); + void push_pdu_bcch(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp); void push_pdu_temp_crnti(uint8_t *buff, uint32_t nof_bytes); void set_uecrid_callback(bool (*callback)(void*, uint64_t), void *arg); @@ -59,7 +61,8 @@ public: private: const static int MAX_PDU_LEN = 150*1024/8; // ~ 150 Mbps const static int NOF_BUFFER_PDUS = 64; // Number of PDU buffers per HARQ pid - uint8_t bcch_buffer[1024]; // BCCH PID has a dedicated buffer + const static int MAX_BCCH_PDU_LEN = 1024; + uint8_t bcch_buffer[MAX_BCCH_PDU_LEN]; // BCCH PID has a dedicated buffer bool (*uecrid_callback) (void*, uint64_t); void *uecrid_callback_arg; @@ -76,8 +79,7 @@ private: srslte::log *log_h; srslte::timers::timer *time_alignment_timer; rlc_interface_mac *rlc; - uint8_t nof_harq_proc; - + // Buffer of PDUs srslte::pdu_queue pdus; }; diff --git a/srsue/hdr/mac/dl_harq.h b/srsue/hdr/mac/dl_harq.h index ee925596f..442a534d5 100644 --- a/srsue/hdr/mac/dl_harq.h +++ b/srsue/hdr/mac/dl_harq.h @@ -262,8 +262,11 @@ private: if (!ack) { // Instruct the PHY To combine the received data and attempt to decode it - payload_buffer_ptr = harq_entity->demux_unit->request_buffer(pid * SRSLTE_MAX_TB + tid, - cur_grant.n_bytes[tid]); + if (pid == HARQ_BCCH_PID) { + payload_buffer_ptr = harq_entity->demux_unit->request_buffer_bcch(cur_grant.n_bytes[tid]); + } else { + payload_buffer_ptr = harq_entity->demux_unit->request_buffer(cur_grant.n_bytes[tid]); + } action->payload_ptr[tid] = payload_buffer_ptr; if (!action->payload_ptr) { action->decode_enabled[tid] = false; @@ -305,8 +308,7 @@ private: harq_entity->pcap->write_dl_sirnti(payload_buffer_ptr, cur_grant.n_bytes[tid], ack, cur_grant.tti); } Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (BCCH)\n", cur_grant.n_bytes[tid]); - harq_entity->demux_unit->push_pdu(pid * SRSLTE_MAX_TB + tid, payload_buffer_ptr, cur_grant.n_bytes[tid], - cur_grant.tti); + harq_entity->demux_unit->push_pdu_bcch(payload_buffer_ptr, cur_grant.n_bytes[tid], cur_grant.tti); } else { if (harq_entity->pcap) { harq_entity->pcap->write_dl_crnti(payload_buffer_ptr, cur_grant.n_bytes[tid], cur_grant.rnti, ack, @@ -318,8 +320,7 @@ private: harq_entity->demux_unit->push_pdu_temp_crnti(payload_buffer_ptr, cur_grant.n_bytes[tid]); } else { Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit\n", cur_grant.n_bytes[tid]); - harq_entity->demux_unit->push_pdu(pid * SRSLTE_MAX_TB + tid, payload_buffer_ptr, cur_grant.n_bytes[tid], - cur_grant.tti); + harq_entity->demux_unit->push_pdu(payload_buffer_ptr, cur_grant.n_bytes[tid], cur_grant.tti); // Compute average number of retransmissions per packet harq_entity->average_retx = SRSLTE_VEC_CMA((float) n_retx, harq_entity->average_retx, diff --git a/srsue/src/mac/demux.cc b/srsue/src/mac/demux.cc index 75bafd1b4..14c524165 100644 --- a/srsue/src/mac/demux.cc +++ b/srsue/src/mac/demux.cc @@ -36,7 +36,7 @@ namespace srsue { -demux::demux(uint8_t nof_harq_proc_) : mac_msg(20), pending_mac_msg(20), nof_harq_proc(nof_harq_proc_) +demux::demux() : mac_msg(20), pending_mac_msg(20) { } @@ -64,18 +64,18 @@ void demux::deallocate(uint8_t* payload_buffer_ptr) pdus.deallocate(payload_buffer_ptr); } } - -uint8_t* demux::request_buffer(uint32_t pid, uint32_t len) -{ - uint8_t *buff = NULL; - if (pid < nof_harq_proc) { - return pdus.request(len); - } else if (pid == nof_harq_proc) { - buff = bcch_buffer; +uint8_t* demux::request_buffer_bcch(uint32_t len) +{ + if (len < MAX_BCCH_PDU_LEN) { + return bcch_buffer; } else { - Error("Requested buffer for invalid PID=%d\n", pid); + return NULL; } - return buff; +} + +uint8_t* demux::request_buffer(uint32_t len) +{ + return pdus.request(len); } /* Demultiplexing of MAC PDU associated with a Temporal C-RNTI. The PDU will @@ -117,21 +117,17 @@ void demux::push_pdu_temp_crnti(uint8_t *buff, uint32_t nof_bytes) * This function enqueues the packet and returns quicly because ACK * deadline is important here. */ -void demux::push_pdu(uint32_t pid, uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) -{ - if (pid < nof_harq_proc) { - return pdus.push(buff, nof_bytes, tstamp); - } else if (pid == nof_harq_proc) { - /* Demultiplexing of MAC PDU associated with SI-RNTI. The PDU passes through - * the MAC in transparent mode. - * Warning: In this case function sends the message to RLC now, since SI blocks do not - * require ACK feedback to be transmitted quickly. - */ - Debug("Pushed BCCH MAC PDU in transparent mode\n"); - rlc->write_pdu_bcch_dlsch(buff, nof_bytes); - } else { - Error("Pushed buffer for invalid PID=%d\n", pid); - } +void demux::push_pdu(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) { + return pdus.push(buff, nof_bytes, tstamp); +} + +/* Demultiplexing of MAC PDU associated with SI-RNTI. The PDU passes through +* the MAC in transparent mode. +* Warning: In this case function sends the message to RLC now, since SI blocks do not +* require ACK feedback to be transmitted quickly. +*/ +void demux::push_pdu_bcch(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) { + rlc->write_pdu_bcch_dlsch(buff, nof_bytes); } bool demux::process_pdus() diff --git a/srsue/src/mac/mac.cc b/srsue/src/mac/mac.cc index 04b7c4750..1a2c909ae 100644 --- a/srsue/src/mac/mac.cc +++ b/srsue/src/mac/mac.cc @@ -44,7 +44,6 @@ namespace srsue { mac::mac() : ttisync(10240), timers(64), mux_unit(MAC_NOF_HARQ_PROC), - demux_unit(SRSLTE_MAX_TB*MAC_NOF_HARQ_PROC), pdu_process_thread(&demux_unit) { started = false; From 0504e7a51b42288cd9e7f9b113b7d8bc4cc2f30d Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 18 Oct 2017 12:49:43 +0200 Subject: [PATCH 05/49] Fixed test for abs value. Solved compilation Neon warnings and SSE errors --- lib/include/srslte/phy/utils/simd.h | 16 +++++++-------- lib/src/phy/utils/test/vector_test.c | 30 ++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index e7820c307..0c378591e 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -310,10 +310,10 @@ static inline simd_f_t srslte_simd_f_addsub(simd_f_t a, simd_f_t b) { return _mm_addsub_ps(a, b); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON // CURRENTLY USES GENERIC IMPLEMENTATION FOR NEON - float* a_ptr = &a; - float* b_ptr = &b; + float* a_ptr = (float*) &a; + float* b_ptr = (float*) &b; simd_f_t ret; - float* c_ptr = &ret; + float* c_ptr = (float*) &ret; for(int i = 0; i<4;i++){ if(i%2==0){ c_ptr[i] = a_ptr[i] - b_ptr[i]; @@ -1028,12 +1028,12 @@ static inline simd_i_t srslte_simd_i_select(simd_i_t a, simd_i_t b, simd_sel_t s #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON // CURRENTLY USES GENERIC IMPLEMENTATION FOR NEON - int* a_ptr = &a; - int* b_ptr = &b; + int* a_ptr = (int*) &a; + int* b_ptr = (int*) &b; simd_i_t ret; - int* sel = &selector; + int* sel = (int*) &selector; - int* c_ptr = &ret; + int* c_ptr = (int*) &ret; for(int i = 0;i<4;i++) { if(sel[i] == -1){ @@ -1097,7 +1097,7 @@ static inline simd_s_t srslte_simd_s_loadu(int16_t *ptr) { return _mm256_loadu_si256((__m256i*) ptr); #else /* LV_HAVE_AVX2 */ #ifdef LV_HAVE_SSE - return _mm_loadu_si128((__m128i*) ptr) + return _mm_loadu_si128((__m128i*) ptr); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON return vld1q_s16(ptr); diff --git a/lib/src/phy/utils/test/vector_test.c b/lib/src/phy/utils/test/vector_test.c index 8d5b9f2d6..4ebed9862 100644 --- a/lib/src/phy/utils/test/vector_test.c +++ b/lib/src/phy/utils/test/vector_test.c @@ -63,12 +63,12 @@ bool verbose = false; strncpy(func_name, #X, 32);\ CODE;\ passed = (mse < MAX_MSE);\ - printf("%32s (%5d) ... %7.1f MSamp/s ... %3s Passed\n", func_name, block_size, \ - (double) block_size*NOF_REPETITIONS/ *timing, passed?"":"Not");\ + printf("%32s (%5d) ... %7.1f MSamp/s ... %3s Passed (%.6f)\n", func_name, block_size, \ + (double) block_size*NOF_REPETITIONS/ *timing, passed?"":"Not", mse);\ return passed;\ } -#define MALLOC(TYPE, NAME) TYPE *NAME = malloc(sizeof(TYPE)*block_size) +#define MALLOC(TYPE, NAME) TYPE *NAME = srslte_vec_malloc(sizeof(TYPE)*block_size) static double elapsed_us(struct timeval *ts_start, struct timeval *ts_end) { @@ -507,7 +507,7 @@ TEST(srslte_vec_abs_cf, for (int i = 0; i < block_size; i++) { gold = sqrtf(crealf(x[i]) * crealf(x[i]) + cimagf(x[i])*cimagf(x[i])); - mse += cabsf(gold - z[i]); + mse += cabsf(gold - z[i])/block_size; } free(x); @@ -771,12 +771,27 @@ int main(int argc, char **argv) { size_count++; } + char fname[68]; + FILE *f = NULL; + void * p = popen("(date +%g%m%d && hostname) | tr '\\r\\n' '__'", "r"); + if (p) { + fgets(fname, 64, p); + strncpy(fname + strnlen(fname, 64) - 1, ".tsv", 4); + f = fopen(fname, "w"); + if (f) printf("Saving benchmark results in '%s'\n", fname); + } + pclose(p); + + printf("\n"); printf("%32s |", "Subroutine/MSps"); + if (f) fprintf(f, "Subroutine/MSps Vs Vector size\t"); for (int i = 0; i < size_count; i++) { printf(" %7d", sizes[i]); + if (f) fprintf(f, "%d\t", sizes[i]); } printf(" |\n"); + if (f) fprintf(f, "\n"); for (int j = 0; j < 32; j++) { printf("-"); @@ -789,12 +804,19 @@ int main(int argc, char **argv) { for (int i = 0; i < func_count; i++) { printf("%32s | ", func_names[i]); + if (f) fprintf(f, "%s\t", func_names[i]); + for (int j = 0; j < size_count; j++) { printf(" %s%7.1f\x1b[0m", (passed[i][j])?"":"\x1B[31m", (double) NOF_REPETITIONS*(double)sizes[j]/timmings[i][j]); + if (f) fprintf(f, "%.1f\t", (double) NOF_REPETITIONS*(double)sizes[j]/timmings[i][j]); + all_passed &= passed[i][j]; } printf(" |\n"); + if (f) fprintf(f, "\n"); } + if (f) fclose(f); + return (all_passed)?SRSLTE_SUCCESS:SRSLTE_ERROR; } From 29b9b6001b114009ae72dee94e441c6a39f622b9 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 18 Oct 2017 15:00:07 +0200 Subject: [PATCH 06/49] fix metric hub when called with periodicity other than 1s --- lib/include/srslte/common/metrics_hub.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/include/srslte/common/metrics_hub.h b/lib/include/srslte/common/metrics_hub.h index 687722bcc..67f0cdbc6 100644 --- a/lib/include/srslte/common/metrics_hub.h +++ b/lib/include/srslte/common/metrics_hub.h @@ -34,8 +34,9 @@ public: metrics_hub() { m = NULL; } - bool init(metrics_interface *m_, float report_period_secs=1.0) { - m = m_; + bool init(metrics_interface *m_, float report_period_secs_=1.0) { + m = m_; + report_period_secs = report_period_secs_; start_periodic(report_period_secs*1e6); return true; } @@ -55,13 +56,13 @@ private: bzero(&metric, sizeof(metrics_t)); m->get_metrics(metric); for (uint32_t i=0;iset_metrics(metric); + listeners[i]->set_metrics(metric, report_period_secs); } } } metrics_interface *m; - std::vector*> listeners; - + std::vector*> listeners; + float report_period_secs; }; } // namespace srslte From ab11a80c6f0c331f415df4a86cc68d8ba4b72e08 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 18 Oct 2017 15:00:47 +0200 Subject: [PATCH 07/49] fix bug in tti interval calculation now returning 0 when called with the same value --- lib/src/phy/common/phy_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/phy/common/phy_common.c b/lib/src/phy/common/phy_common.c index b502fbd75..b4f5e122b 100644 --- a/lib/src/phy/common/phy_common.c +++ b/lib/src/phy/common/phy_common.c @@ -605,7 +605,7 @@ int srslte_band_get_fd_region(enum band_geographical_area region, srslte_earfcn_ /* Returns the interval tti1-tti2 mod 10240 */ uint32_t srslte_tti_interval(uint32_t tti1, uint32_t tti2) { - if (tti1 > tti2) { + if (tti1 >= tti2) { return tti1-tti2; } else { return 10240-tti2+tti1; From 5ee2a37c2bef57653d996c02b2fe590998287abe Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 18 Oct 2017 15:01:36 +0200 Subject: [PATCH 08/49] fix bug in dl_harq where if always returned true --- srsue/hdr/mac/dl_harq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/hdr/mac/dl_harq.h b/srsue/hdr/mac/dl_harq.h index ee925596f..75e80fd95 100644 --- a/srsue/hdr/mac/dl_harq.h +++ b/srsue/hdr/mac/dl_harq.h @@ -265,7 +265,7 @@ private: payload_buffer_ptr = harq_entity->demux_unit->request_buffer(pid * SRSLTE_MAX_TB + tid, cur_grant.n_bytes[tid]); action->payload_ptr[tid] = payload_buffer_ptr; - if (!action->payload_ptr) { + if (!action->payload_ptr[tid]) { action->decode_enabled[tid] = false; Error("Can't get a buffer for TBS=%d\n", cur_grant.n_bytes[tid]); return; From aa5a3bfdae9f636de8a15d091b489fafda1500e2 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 18 Oct 2017 15:41:36 +0200 Subject: [PATCH 09/49] fix bug reported by coverity --- lib/include/srslte/common/metrics_hub.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/include/srslte/common/metrics_hub.h b/lib/include/srslte/common/metrics_hub.h index 67f0cdbc6..66cc4acbd 100644 --- a/lib/include/srslte/common/metrics_hub.h +++ b/lib/include/srslte/common/metrics_hub.h @@ -31,9 +31,10 @@ template class metrics_hub : public periodic_thread { public: - metrics_hub() { - m = NULL; - } + metrics_hub() + :m(NULL) + ,report_period_secs(1) + {} bool init(metrics_interface *m_, float report_period_secs_=1.0) { m = m_; report_period_secs = report_period_secs_; From 12877fe2960a64fb371f6bd8060bd94475d9abdf Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 18 Oct 2017 16:33:19 -0400 Subject: [PATCH 10/49] Missing ip_netmask configuration file --- srsue/src/main.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 47d5f807e..3b0cad2d0 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -122,6 +122,10 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { /* Expert section */ + ("expert.ip_netmask", + bpo::value(&args->expert.ip_netmask)->default_value("255.255.255.0"), + "Netmask of the tun_srsue device") + ("expert.phy.worker_cpu_mask", bpo::value(&args->expert.phy.worker_cpu_mask)->default_value(-1), "cpu bit mask (eg 255 = 1111 1111)") From 739b8fc457f3588f0d9d580c43de978d31329390 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 18 Oct 2017 16:34:18 -0400 Subject: [PATCH 11/49] Restored TA commands --- srsue/src/phy/phy.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index df29726d5..9760ab374 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -200,8 +200,8 @@ void phy::set_timeadv_rar(uint32_t ta_cmd) { void phy::set_timeadv(uint32_t ta_cmd) { n_ta = srslte_N_ta_new(n_ta, ta_cmd); - //sf_recv.set_time_adv_sec(((float) n_ta)*SRSLTE_LTE_TS); - Warning("Not supported: Set TA: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, ((float) n_ta)*SRSLTE_LTE_TS*1e6); + sf_recv.set_time_adv_sec(((float) n_ta)*SRSLTE_LTE_TS); + //Warning("Not supported: Set TA: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, ((float) n_ta)*SRSLTE_LTE_TS*1e6); } void phy::configure_prach_params() @@ -308,7 +308,8 @@ void phy::reset() pdcch_dl_search_reset(); for(uint32_t i=0;i Date: Wed, 18 Oct 2017 16:49:36 -0400 Subject: [PATCH 12/49] Fix for async dl scheduling --- lib/include/srslte/common/common.h | 1 + srsue/hdr/mac/mac.h | 2 +- srsue/src/phy/phch_worker.cc | 11 +++++++---- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib/include/srslte/common/common.h b/lib/include/srslte/common/common.h index 6372af73e..fbc703486 100644 --- a/lib/include/srslte/common/common.h +++ b/lib/include/srslte/common/common.h @@ -52,6 +52,7 @@ #define TTIMOD_SZ (((2*HARQ_DELAY_MS) < 10)?10:20) #define TTIMOD(tti) (tti%TTIMOD_SZ) +#define MOD_N_PROC (2*HARQ_DELAY_MS-8) #define ASYNC_DL_SCHED (HARQ_DELAY_MS <= 4) // Cat 3 UE - Max number of DL-SCH transport block bits received within a TTI diff --git a/srsue/hdr/mac/mac.h b/srsue/hdr/mac/mac.h index d19f668bf..87bb764e1 100644 --- a/srsue/hdr/mac/mac.h +++ b/srsue/hdr/mac/mac.h @@ -135,7 +135,7 @@ private: demux demux_unit; /* DL/UL HARQ */ - dl_harq_entity dl_harq; + dl_harq_entity dl_harq; ul_harq_entity ul_harq; /* MAC Uplink-related Procedures */ diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index f89696015..a32bb7537 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -65,8 +65,7 @@ phch_worker::phch_worker() : tr_exec(10240) cell_initiated = false; pregen_enabled = false; trace_enabled = false; - - reset(); + reset(); } @@ -97,7 +96,7 @@ void phch_worker::reset() bzero(&period_cqi, sizeof(srslte_cqi_periodic_cfg_t)); I_sr = 0; rnti_is_set = false; - rar_cqi_request = false; + rar_cqi_request = false; cfi = 0; } @@ -482,7 +481,11 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant) /* Fill MAC grant structure */ grant->ndi[0] = dci_unpacked.ndi; grant->ndi[1] = dci_unpacked.ndi_1; - grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:(tti%(2*HARQ_DELAY_MS)); + if (tti < MOD_N_PROC) { + grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:tti+(2*HARQ_DELAY_MS); + } else { + grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:(tti%(2*HARQ_DELAY_MS)); + } grant->n_bytes[0] = grant->phy_grant.dl.mcs[0].tbs / (uint32_t) 8; grant->n_bytes[1] = grant->phy_grant.dl.mcs[1].tbs / (uint32_t) 8; grant->tti = tti; From 177f36fc8c1fa7c31667cd3bc8baa3d2c5548af9 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 18 Oct 2017 16:50:22 -0400 Subject: [PATCH 13/49] Improved cell reestablishment procedure timers (still not working the authentication) --- srsue/hdr/phy/phch_recv.h | 4 ++-- srsue/hdr/upper/rrc.h | 5 ++++- srsue/src/mac/mac.cc | 3 ++- srsue/src/phy/phch_common.cc | 1 + srsue/src/upper/rrc.cc | 28 ++++++++++++++++------------ 5 files changed, 25 insertions(+), 16 deletions(-) diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index c51622e53..01a296094 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -158,7 +158,7 @@ private: uint32_t current_earfcn; uint32_t sync_sfn_cnt; - const static uint32_t SYNC_SFN_TIMEOUT = 200; + const static uint32_t SYNC_SFN_TIMEOUT = 1000; float ul_dl_factor; int cur_earfcn_index; bool cell_search_in_progress; @@ -166,7 +166,7 @@ private: float measure_rsrp; srslte_ue_dl_t ue_dl_measure; - const static int RSRP_MEASURE_NOF_FRAMES = 5; + const static int RSRP_MEASURE_NOF_FRAMES = 10; int cell_sync_sfn(); int cell_meas_rsrp(); diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index 3643f76c3..3e2fb70dd 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -98,6 +98,8 @@ private: uint8_t transaction_id; bool drb_up; + bool reestablishment_in_progress; + // timeouts in ms uint32_t connecting_timeout; @@ -244,7 +246,8 @@ private: // Helpers void rrc_connection_release(); - void radio_link_failure(); + void con_restablish_cell_reselected(); + void radio_link_failure(); static void* start_sib_thread(void *rrc_); void sib_search(); void apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2); diff --git a/srsue/src/mac/mac.cc b/srsue/src/mac/mac.cc index 1a2c909ae..f8d10bb34 100644 --- a/srsue/src/mac/mac.cc +++ b/srsue/src/mac/mac.cc @@ -117,7 +117,8 @@ void mac::reset() Info("Resetting MAC\n"); - timers.stop_all(); + timers.get(timer_alignment)->stop(); + timers.get(contention_resolution_timer)->stop(); ul_harq.reset_ndi(); diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index 7d2948c1a..d956ddd15 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -336,6 +336,7 @@ void phch_common::reset_ul() pthread_mutex_trylock(&tx_mutex[i]); pthread_mutex_unlock(&tx_mutex[i]); } + radio_h->tx_end(); } } diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 94c2e449a..4ed20deeb 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -35,8 +35,6 @@ #include "srslte/common/security.h" #include "srslte/common/bcd_helpers.h" -#define TIMEOUT_RESYNC_REESTABLISH 100 - using namespace srslte; namespace srsue { @@ -92,6 +90,8 @@ void rrc::init(phy_interface_rrc *phy_, pthread_mutex_init(&mutex, NULL); + reestablishment_in_progress = false; + ue_category = SRSLTE_UE_CATEGORY; t301 = mac_timers->timer_get_unique_id(); t310 = mac_timers->timer_get_unique_id(); @@ -207,7 +207,11 @@ void rrc::run_thread() { break; case RRC_STATE_CELL_SELECTED: rrc_log->info("RRC Cell Selected: Sending connection request...\n"); - send_con_request(); + if (reestablishment_in_progress) { + con_restablish_cell_reselected(); + } else { + send_con_request(); + } state = RRC_STATE_CONNECTING; connecting_timeout = 0; break; @@ -226,6 +230,7 @@ void rrc::run_thread() { usleep(60000); rrc_log->info("Leaving RRC_CONNECTED state\n"); drb_up = false; + reestablishment_in_progress = false; pdcp->reset(); rlc->reset(); phy->reset(); @@ -663,6 +668,8 @@ void rrc::send_con_restablish_request() { ul_ccch_msg.msg.rrc_con_reest_req.cause = LIBLTE_RRC_CON_REEST_REQ_CAUSE_OTHER_FAILURE; liblte_rrc_pack_ul_ccch_msg(&ul_ccch_msg, (LIBLTE_BIT_MSG_STRUCT *) &bit_buf); + reestablishment_in_progress = true; + rrc_log->info("Initiating RRC Connection Reestablishment Procedure\n"); rrc_log->console("RRC Connection Reestablishment\n"); mac_timers->timer_get(t310)->stop(); @@ -673,19 +680,16 @@ void rrc::send_con_restablish_request() { set_phy_default(); mac->reset(); set_mac_default(); +} - // FIXME: Cell selection should be different?? - - // Wait for cell re-synchronization - uint32_t timeout_cnt = 0; - while (!phy->sync_status() && timeout_cnt < TIMEOUT_RESYNC_REESTABLISH) { - usleep(10000); - timeout_cnt++; - } +// Actions following cell reselection 5.3.7.3 +void rrc::con_restablish_cell_reselected() +{ + reestablishment_in_progress = false; + rrc_log->info("Cell Selection finished. Initiating transmission of RRC Connection Reestablishment Request\n"); mac_timers->timer_get(t301)->reset(); mac_timers->timer_get(t301)->run(); mac_timers->timer_get(t311)->stop(); - rrc_log->info("Cell Selection finished. Initiating transmission of RRC Connection Reestablishment Request\n"); // Byte align and pack the message bits for PDCP if ((bit_buf.N_bits % 8) != 0) { From b8d5b5b6a92807ebee34ebb698c2f190a79b3efb Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Wed, 18 Oct 2017 21:54:52 +0100 Subject: [PATCH 14/49] count_dl fix --- srsue/src/upper/nas.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/srsue/src/upper/nas.cc b/srsue/src/upper/nas.cc index f0fd8cf54..110c8c78e 100644 --- a/srsue/src/upper/nas.cc +++ b/srsue/src/upper/nas.cc @@ -281,7 +281,6 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { LIBLTE_MME_ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT_MSG_STRUCT act_def_eps_bearer_context_accept; nas_log->info("Received Attach Accept\n"); - count_dl++; liblte_mme_unpack_attach_accept_msg((LIBLTE_BYTE_MSG_STRUCT *) pdu, &attach_accept); @@ -359,6 +358,8 @@ void nas::parse_attach_accept(uint32_t lcid, byte_buffer_t *pdu) { state = EMM_STATE_REGISTERED; current_plmn = selecting_plmn; + count_dl++; + // Send EPS bearer context accept and attach complete count_ul++; act_def_eps_bearer_context_accept.eps_bearer_id = eps_bearer_id; @@ -437,6 +438,9 @@ void nas::parse_authentication_request(uint32_t lcid, byte_buffer_t *pdu) { nas_log->console("Warning: Network authentication failure\n"); pool->deallocate(pdu); } + + // Reset DL counter (as per 24.301 5.4.3.2) + count_dl = 0; } void nas::parse_authentication_reject(uint32_t lcid, byte_buffer_t *pdu) { @@ -539,6 +543,8 @@ void nas::parse_security_mode_command(uint32_t lcid, byte_buffer_t *pdu) { } } + count_dl++; + if (!success) { // Reuse pdu for response pdu->reset(); From f1ec1b2f3c07bdf3bb0c09bb86e7996204742637 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 18 Oct 2017 19:33:43 -0400 Subject: [PATCH 15/49] disable attempt to resync after N310 (too soon if N310 is low) --- srsue/src/upper/rrc.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 4ed20deeb..10373dcf2 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -489,12 +489,12 @@ void rrc::earfcn_end() { // Detection of physical layer problems (5.3.11.1) void rrc::out_of_sync() { - current_cell->in_sync = false; + current_cell->in_sync = false; if (!mac_timers->timer_get(t311)->is_running() && !mac_timers->timer_get(t310)->is_running()) { n310_cnt++; if (n310_cnt == N310) { // attempt resync - phy->sync_reset(); + //phy->sync_reset(); mac_timers->timer_get(t310)->reset(); mac_timers->timer_get(t310)->run(); From 3292f9c2694ce5b5a75501427b5a2fd09fc38189 Mon Sep 17 00:00:00 2001 From: yagoda Date: Thu, 19 Oct 2017 16:38:58 +0000 Subject: [PATCH 16/49] simd.h tidy up & small fix for eMBMS --- lib/include/srslte/phy/utils/simd.h | 2 -- lib/src/phy/ue/ue_dl.c | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index 0c378591e..09e9cff8e 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -1027,12 +1027,10 @@ static inline simd_i_t srslte_simd_i_select(simd_i_t a, simd_i_t b, simd_sel_t s return (__m128i) _mm_blendv_ps((__m128)a, (__m128)b, selector); #else /* LV_HAVE_SSE */ #ifdef HAVE_NEON // CURRENTLY USES GENERIC IMPLEMENTATION FOR NEON - int* a_ptr = (int*) &a; int* b_ptr = (int*) &b; simd_i_t ret; int* sel = (int*) &selector; - int* c_ptr = (int*) &ret; for(int i = 0;i<4;i++) { diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index c4e2d3f6c..c11a29b8b 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -603,7 +603,8 @@ int srslte_ue_dl_decode_mbsfn(srslte_ue_dl_t * q, grant.sf_type = SRSLTE_SF_MBSFN; grant.nof_tb = 1; grant.mcs[0].idx = 2; - + grant.tb_en[0] = true; + grant.tb_en[1] = false; grant.nof_prb = q->pmch.cell.nof_prb; srslte_dl_fill_ra_mcs(&grant.mcs[0], grant.nof_prb); srslte_softbuffer_rx_reset_tbs(q->softbuffers[0], (uint32_t) grant.mcs[0].tbs); From 494802ba9b0299a5ddb02000240ea47236836ece Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 19 Oct 2017 14:33:05 -0400 Subject: [PATCH 17/49] Fixed bug in RLC UM when TX large number of segments in a PDU --- lib/src/upper/rlc_um.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index b2697178c..045fb0b7e 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -309,7 +309,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) } // Pull SDUs from queue - while(pdu_space > head_len && tx_sdu_queue.size() > 0) + while(pdu_space > head_len + 1 && tx_sdu_queue.size() > 0) { log->debug("pdu_space=%d, head_len=%d\n", pdu_space, head_len); if(last_li > 0) From 399f1cdbd1352aad215f2baaf8386f335334e70b Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 19 Oct 2017 14:47:14 -0400 Subject: [PATCH 18/49] Force retx for mcs>29 and new tb if rv=0 && mcs<29 --- lib/include/srslte/common/common.h | 1 - srsue/hdr/mac/dl_harq.h | 9 +++++---- srsue/hdr/mac/mac.h | 2 +- srsue/src/phy/phch_worker.cc | 6 +----- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/lib/include/srslte/common/common.h b/lib/include/srslte/common/common.h index fbc703486..6372af73e 100644 --- a/lib/include/srslte/common/common.h +++ b/lib/include/srslte/common/common.h @@ -52,7 +52,6 @@ #define TTIMOD_SZ (((2*HARQ_DELAY_MS) < 10)?10:20) #define TTIMOD(tti) (tti%TTIMOD_SZ) -#define MOD_N_PROC (2*HARQ_DELAY_MS-8) #define ASYNC_DL_SCHED (HARQ_DELAY_MS <= 4) // Cat 3 UE - Max number of DL-SCH transport block bits received within a TTI diff --git a/srsue/hdr/mac/dl_harq.h b/srsue/hdr/mac/dl_harq.h index 278dbc6dc..9abcf0922 100644 --- a/srsue/hdr/mac/dl_harq.h +++ b/srsue/hdr/mac/dl_harq.h @@ -259,7 +259,7 @@ private: memcpy(&cur_grant, &grant, sizeof(Tgrant)); // If data has not yet been successfully decoded - if (!ack) { + if (!ack || (grant.rv[tid]==0 && grant.phy_grant.dl.mcs[tid].idx < 29)) { // Instruct the PHY To combine the received data and attempt to decode it if (pid == HARQ_BCCH_PID) { @@ -347,9 +347,10 @@ private: // Determine if it's a new transmission 5.3.2.2 bool calc_is_new_transmission(Tgrant grant) { - if ((grant.ndi[tid] != cur_grant.ndi[tid]) || // 1st condition (NDI has changed) - (pid == HARQ_BCCH_PID && grant.rv[tid] == 0) || // 2nd condition (Broadcast and 1st transmission) - is_first_tb) // 3rd condition (first TB) + if (grant.phy_grant.dl.mcs[tid].idx < 28 && // mcs 29,30,31 always retx regardless of rest + ((grant.ndi[tid] != cur_grant.ndi[tid]) || // 1st condition (NDI has changed) + (pid == HARQ_BCCH_PID && grant.rv[tid] == 0) || // 2nd condition (Broadcast and 1st transmission) + is_first_tb)) { is_first_tb = false; is_new_transmission = true; diff --git a/srsue/hdr/mac/mac.h b/srsue/hdr/mac/mac.h index 87bb764e1..d19f668bf 100644 --- a/srsue/hdr/mac/mac.h +++ b/srsue/hdr/mac/mac.h @@ -135,7 +135,7 @@ private: demux demux_unit; /* DL/UL HARQ */ - dl_harq_entity dl_harq; + dl_harq_entity dl_harq; ul_harq_entity ul_harq; /* MAC Uplink-related Procedures */ diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index a32bb7537..1d86461cd 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -481,11 +481,7 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant) /* Fill MAC grant structure */ grant->ndi[0] = dci_unpacked.ndi; grant->ndi[1] = dci_unpacked.ndi_1; - if (tti < MOD_N_PROC) { - grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:tti+(2*HARQ_DELAY_MS); - } else { - grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:(tti%(2*HARQ_DELAY_MS)); - } + grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:(tti%(2*HARQ_DELAY_MS)); grant->n_bytes[0] = grant->phy_grant.dl.mcs[0].tbs / (uint32_t) 8; grant->n_bytes[1] = grant->phy_grant.dl.mcs[1].tbs / (uint32_t) 8; grant->tti = tti; From 2f44e2bf3a4082211a4f57f3d99e778af103e8ec Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 19 Oct 2017 16:10:27 -0400 Subject: [PATCH 19/49] Refactored cases mcs>29 for ul/dl --- lib/include/srslte/phy/common/phy_common.h | 3 +- lib/include/srslte/phy/phch/ra.h | 3 +- lib/src/phy/modem/demod_hard.c | 1 + lib/src/phy/modem/modem_table.c | 1 + lib/src/phy/phch/dci.c | 4 +- lib/src/phy/phch/ra.c | 182 ++++++++------------- lib/src/phy/phch/test/pusch_test.c | 2 +- srsenb/src/phy/phch_worker.cc | 2 +- srsue/hdr/phy/phch_worker.h | 7 +- srsue/src/phy/phch_worker.cc | 47 ++++-- 10 files changed, 123 insertions(+), 129 deletions(-) diff --git a/lib/include/srslte/phy/common/phy_common.h b/lib/include/srslte/phy/common/phy_common.h index 148a12974..0b71ad82e 100644 --- a/lib/include/srslte/phy/common/phy_common.h +++ b/lib/include/srslte/phy/common/phy_common.h @@ -197,7 +197,8 @@ typedef enum SRSLTE_API { SRSLTE_MOD_BPSK = 0, SRSLTE_MOD_QPSK, SRSLTE_MOD_16QAM, - SRSLTE_MOD_64QAM + SRSLTE_MOD_64QAM, + SRSLTE_MOD_LAST } srslte_mod_t; typedef struct SRSLTE_API { diff --git a/lib/include/srslte/phy/phch/ra.h b/lib/include/srslte/phy/phch/ra.h index 3039455ed..680d80dd6 100644 --- a/lib/include/srslte/phy/phch/ra.h +++ b/lib/include/srslte/phy/phch/ra.h @@ -226,8 +226,7 @@ SRSLTE_API uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant, SRSLTE_API int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci, uint32_t nof_prb, uint32_t n_rb_ho, - srslte_ra_ul_grant_t *grant, - uint32_t harq_pid); + srslte_ra_ul_grant_t *grant); SRSLTE_API void srslte_ra_ul_grant_to_nbits(srslte_ra_ul_grant_t *grant, srslte_cp_t cp, diff --git a/lib/src/phy/modem/demod_hard.c b/lib/src/phy/modem/demod_hard.c index 76f54236d..899559ecc 100644 --- a/lib/src/phy/modem/demod_hard.c +++ b/lib/src/phy/modem/demod_hard.c @@ -44,6 +44,7 @@ int srslte_demod_hard_demodulate(srslte_demod_hard_t* q, cf_t* symbols, uint8_t int nbits=-1; switch(q->mod) { + case SRSLTE_MOD_LAST: case SRSLTE_MOD_BPSK: hard_bpsk_demod(symbols,bits,nsymbols); nbits=nsymbols; diff --git a/lib/src/phy/modem/modem_table.c b/lib/src/phy/modem/modem_table.c index c19e52e77..3c4ad2417 100644 --- a/lib/src/phy/modem/modem_table.c +++ b/lib/src/phy/modem/modem_table.c @@ -82,6 +82,7 @@ int srslte_modem_table_set(srslte_modem_table_t* q, cf_t* table, uint32_t nsymbo int srslte_modem_table_lte(srslte_modem_table_t* q, srslte_mod_t modulation) { srslte_modem_table_init(q); switch(modulation) { + case SRSLTE_MOD_LAST: case SRSLTE_MOD_BPSK: q->nbits_x_symbol = 1; q->nsymbols = 2; diff --git a/lib/src/phy/phch/dci.c b/lib/src/phy/phch/dci.c index 2daa7e10d..471429145 100644 --- a/lib/src/phy/phch/dci.c +++ b/lib/src/phy/phch/dci.c @@ -111,7 +111,7 @@ int srslte_dci_rar_to_ul_grant(srslte_dci_rar_grant_t *rar, uint32_t nof_prb, srslte_ra_type2_from_riv(riv, &ul_dci->type2_alloc.L_crb, &ul_dci->type2_alloc.RB_start, nof_prb, nof_prb); - if (srslte_ra_ul_dci_to_grant(ul_dci, nof_prb, n_rb_ho, grant, 0)) { + if (srslte_ra_ul_dci_to_grant(ul_dci, nof_prb, n_rb_ho, grant)) { return SRSLTE_ERROR; } @@ -177,7 +177,7 @@ int srslte_dci_msg_to_ul_grant(srslte_dci_msg_t *msg, uint32_t nof_prb, return ret; } - if (srslte_ra_ul_dci_to_grant(ul_dci, nof_prb, n_rb_ho, grant, harq_pid)) { + if (srslte_ra_ul_dci_to_grant(ul_dci, nof_prb, n_rb_ho, grant)) { return ret; } diff --git a/lib/src/phy/phch/ra.c b/lib/src/phy/phch/ra.c index be10c304c..8cae9fe65 100644 --- a/lib/src/phy/phch/ra.c +++ b/lib/src/phy/phch/ra.c @@ -185,108 +185,87 @@ int srslte_ra_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci, srslte_ra_ } } -srslte_mod_t last_mod[8]; -uint32_t last_ul_tbs_idx[8]; -uint32_t last_dl_tbs[8]; -uint32_t last_dl_tbs2[8]; - -static int ul_dci_to_grant_mcs(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant, uint32_t harq_pid) { - int tbs = -1; +static void ul_dci_to_grant_mcs(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant) { // 8.6.2 First paragraph if (dci->mcs_idx <= 28) { /* Table 8.6.1-1 on 36.213 */ if (dci->mcs_idx < 11) { grant->mcs.mod = SRSLTE_MOD_QPSK; - tbs = srslte_ra_tbs_from_idx(dci->mcs_idx, grant->L_prb); - last_ul_tbs_idx[harq_pid%8] = dci->mcs_idx; + grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx, grant->L_prb); } else if (dci->mcs_idx < 21) { grant->mcs.mod = SRSLTE_MOD_16QAM; - tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-1, grant->L_prb); - last_ul_tbs_idx[harq_pid%8] = dci->mcs_idx-1; + grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-1, grant->L_prb); } else if (dci->mcs_idx < 29) { grant->mcs.mod = SRSLTE_MOD_64QAM; - tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-2, grant->L_prb); - last_ul_tbs_idx[harq_pid%8] = dci->mcs_idx-2; + grant->mcs.tbs = srslte_ra_tbs_from_idx(dci->mcs_idx-2, grant->L_prb); } else { fprintf(stderr, "Invalid MCS index %d\n", dci->mcs_idx); } - last_mod[harq_pid%8] = grant->mcs.mod; } else if (dci->mcs_idx == 29 && dci->cqi_request && grant->L_prb <= 4) { // 8.6.1 and 8.6.2 36.213 second paragraph grant->mcs.mod = SRSLTE_MOD_QPSK; - tbs = srslte_ra_tbs_from_idx(last_ul_tbs_idx[harq_pid%8], grant->L_prb); - dci->rv_idx = 1; + grant->mcs.tbs = 0; + dci->rv_idx = 1; } else if (dci->mcs_idx >= 29) { - // Else use last TBS/Modulation and use mcs to obtain rv_idx - tbs = srslte_ra_tbs_from_idx(last_ul_tbs_idx[harq_pid%8], grant->L_prb); - grant->mcs.mod = last_mod[harq_pid%8]; + // Else use last TBS/Modulation and use mcs to obtain rv_idx + grant->mcs.tbs = -1; + grant->mcs.mod = SRSLTE_MOD_LAST; dci->rv_idx = dci->mcs_idx - 28; - DEBUG("TTI=%d, harq_pid=%d, mcs_idx=%d, tbs=%d, mod=%d, rv=%d\n", - harq_pid, harq_pid%8, dci->mcs_idx, tbs/8, grant->mcs.mod, dci->rv_idx); - } - if (tbs < 0) { - fprintf(stderr, "Error computing TBS\n"); - return SRSLTE_ERROR; - } else { - grant->mcs.tbs = (uint32_t) tbs; - return SRSLTE_SUCCESS; + DEBUG("mcs_idx=%d, tbs=%d, mod=%d, rv=%d\n", + dci->mcs_idx, grant->mcs.tbs/8, grant->mcs.mod, dci->rv_idx); } } -void srslte_ra_ul_grant_to_nbits(srslte_ra_ul_grant_t *grant, srslte_cp_t cp, uint32_t N_srs, srslte_ra_nbits_t *nbits) +void srslte_ra_ul_grant_to_nbits(srslte_ra_ul_grant_t *grant, srslte_cp_t cp, uint32_t N_srs, srslte_ra_nbits_t *nbits) { - nbits->nof_symb = 2*(SRSLTE_CP_NSYMB(cp)-1) - N_srs; + nbits->nof_symb = 2*(SRSLTE_CP_NSYMB(cp)-1) - N_srs; nbits->nof_re = nbits->nof_symb*grant->M_sc; nbits->nof_bits = nbits->nof_re * grant->Qm; } /** Compute PRB allocation for Uplink as defined in 8.1 and 8.4 of 36.213 */ -int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci, uint32_t nof_prb, uint32_t n_rb_ho, srslte_ra_ul_grant_t *grant, - uint32_t harq_pid) +int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci, uint32_t nof_prb, uint32_t n_rb_ho, srslte_ra_ul_grant_t *grant) { - - // Compute PRB allocation + + // Compute PRB allocation if (!srslte_ra_ul_dci_to_grant_prb_allocation(dci, grant, n_rb_ho, nof_prb)) { - - // Compute MCS - if (!ul_dci_to_grant_mcs(dci, grant, harq_pid)) { - - // Fill rest of grant structure - grant->mcs.idx = dci->mcs_idx; - grant->M_sc = grant->L_prb*SRSLTE_NRE; - grant->M_sc_init = grant->M_sc; // FIXME: What should M_sc_init be? - grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod); - } else { - fprintf(stderr, "Error computing MCS\n"); - return SRSLTE_ERROR; - } + + // Compute MCS + ul_dci_to_grant_mcs(dci, grant); + + // Fill rest of grant structure + grant->mcs.idx = dci->mcs_idx; + grant->M_sc = grant->L_prb*SRSLTE_NRE; + grant->M_sc_init = grant->M_sc; // FIXME: What should M_sc_init be? + grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod); + } else { printf("Error computing UL PRB allocation\n"); - return SRSLTE_ERROR; + return SRSLTE_ERROR; } return SRSLTE_SUCCESS; } -uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t cell, uint32_t nof_prb, uint32_t nof_ctrl_symbols) +uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t cell, uint32_t nof_prb, uint32_t nof_ctrl_symbols) { - uint32_t nof_refs = 0; + uint32_t nof_refs = 0; uint32_t nof_symb = 2*SRSLTE_CP_NSYMB(cell.cp)-nof_ctrl_symbols; switch(cell.nof_ports) { - case 1: - nof_refs = 2*3; - break; - case 2: - nof_refs = 4*3; - break; - case 4: - nof_refs = 4*4; - break; + case 1: + nof_refs = 2*3; + break; + case 2: + nof_refs = 4*3; + break; + case 4: + nof_refs = 4*4; + break; } return nof_prb * (nof_symb*SRSLTE_NRE-nof_refs); } /* Computes the number of RE for each PRB in the prb_dist structure */ -uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant, srslte_cell_t cell, +uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant, srslte_cell_t cell, uint32_t sf_idx, uint32_t nof_ctrl_symbols) { uint32_t j, s; @@ -300,7 +279,7 @@ uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant, srslte_cell_t ce } } } - return nof_re; + return nof_re; } @@ -315,7 +294,7 @@ int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_ uint32_t bitmask; uint32_t P = srslte_ra_type0_P(nof_prb); uint32_t n_rb_rbg_subset, n_rb_type1; - + bzero(grant, sizeof(srslte_ra_dl_grant_t)); switch (dci->alloc_type) { case SRSLTE_RA_ALLOC_TYPE0: @@ -352,14 +331,14 @@ int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_ * P * P + dci->type1_alloc.rbg_subset * P + (i + shift) % P] = true; grant->nof_prb++; } else { - return SRSLTE_ERROR; + return SRSLTE_ERROR; } } } memcpy(&grant->prb_idx[1], &grant->prb_idx[0], SRSLTE_MAX_PRB*sizeof(bool)); break; case SRSLTE_RA_ALLOC_TYPE2: - if (dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) { + if (dci->type2_alloc.mode == SRSLTE_RA_TYPE2_LOC) { for (i = 0; i < dci->type2_alloc.L_crb; i++) { grant->prb_idx[0][i + dci->type2_alloc.RB_start] = true; grant->nof_prb++; @@ -408,13 +387,13 @@ int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_ if (n_tilde_prb_odd < nof_prb) { grant->prb_idx[0][n_tilde_prb_odd] = true; } else { - return SRSLTE_ERROR; + return SRSLTE_ERROR; } } else { if (n_tilde_prb_odd + N_gap - N_tilde_vrb / 2 < nof_prb) { grant->prb_idx[0][n_tilde_prb_odd + N_gap - N_tilde_vrb / 2] = true; } else { - return SRSLTE_ERROR; + return SRSLTE_ERROR; } } grant->nof_prb++; @@ -422,13 +401,13 @@ int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_ if(n_tilde_prb_even < nof_prb) { grant->prb_idx[1][n_tilde_prb_even] = true; } else { - return SRSLTE_ERROR; + return SRSLTE_ERROR; } } else { if (n_tilde_prb_even + N_gap - N_tilde_vrb / 2 < nof_prb) { grant->prb_idx[1][n_tilde_prb_even + N_gap - N_tilde_vrb / 2] = true; } else { - return SRSLTE_ERROR; + return SRSLTE_ERROR; } } } @@ -442,8 +421,7 @@ int srslte_ra_dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_ } int srslte_dl_fill_ra_mcs(srslte_ra_mcs_t *mcs, uint32_t nprb) { - uint32_t i_tbs = 0; - int tbs = -1; + int i_tbs = 0; if (mcs->idx < 10) { mcs->mod = SRSLTE_MOD_QPSK; i_tbs = mcs->idx; @@ -455,30 +433,26 @@ int srslte_dl_fill_ra_mcs(srslte_ra_mcs_t *mcs, uint32_t nprb) { i_tbs = mcs->idx-2; } else if (mcs->idx == 29) { mcs->mod = SRSLTE_MOD_QPSK; - tbs = 0; - i_tbs = 0; + i_tbs = -1; } else if (mcs->idx == 30) { mcs->mod = SRSLTE_MOD_16QAM; - tbs = 0; - i_tbs = 0; + i_tbs = -1; } else if (mcs->idx == 31) { mcs->mod = SRSLTE_MOD_64QAM; - tbs = 0; - i_tbs = 0; + i_tbs = -1; } - - if (tbs == -1) { + + int tbs = -1; + if (i_tbs >= 0) { tbs = srslte_ra_tbs_from_idx(i_tbs, nprb); - if (tbs >= 0) { - mcs->tbs = tbs; - } - } - return tbs; + mcs->tbs = tbs; + } + return tbs; } int srslte_dl_fill_ra_mcs_pmch(srslte_ra_mcs_t *mcs, uint32_t nprb) { - uint32_t i_tbs = 0; - int tbs = -1; + uint32_t i_tbs = 0; + int tbs = -1; if (mcs->idx < 5) { mcs->mod = SRSLTE_MOD_QPSK; i_tbs = mcs->idx*2; @@ -492,7 +466,7 @@ int srslte_dl_fill_ra_mcs_pmch(srslte_ra_mcs_t *mcs, uint32_t nprb) { mcs->mod = SRSLTE_MOD_64QAM; i_tbs = mcs->idx + 5; }else if (mcs->idx < 28) { - //mcs->mod = SRSLTE_MOD_256QAM; + //mcs->mod = SRSLTE_MOD_256QAM; i_tbs = mcs->idx + 5; }else if (mcs->idx == 28) { mcs->mod = SRSLTE_MOD_QPSK; @@ -511,15 +485,15 @@ int srslte_dl_fill_ra_mcs_pmch(srslte_ra_mcs_t *mcs, uint32_t nprb) { tbs = 0; i_tbs = 0; } - - + + if (tbs == -1) { tbs = srslte_ra_tbs_from_idx(i_tbs, nprb); if (tbs >= 0) { - mcs->tbs = tbs; + mcs->tbs = tbs; } - } - return tbs; + } + return tbs; } /* Modulation order and transport block size determination 7.1.7 in 36.213 @@ -530,9 +504,9 @@ int srslte_dl_fill_ra_mcs_pmch(srslte_ra_mcs_t *mcs, uint32_t nprb) { * */ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *grant, bool crc_is_crnti) { uint32_t n_prb=0; - int tbs = -1; - uint32_t i_tbs = 0; - + int tbs = -1; + uint32_t i_tbs = 0; + if (!crc_is_crnti) { if (dci->dci_is_1a) { n_prb = dci->type2_alloc.n_prb1a == SRSLTE_RA_TYPE2_NPRB1A_2 ? 2 : 3; @@ -546,35 +520,23 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr } } else { fprintf(stderr, "Error decoding DCI: P/SI/RA-RNTI supports Format1A/1C only\n"); - return SRSLTE_ERROR; + return SRSLTE_ERROR; } grant->mcs[0].mod = SRSLTE_MOD_QPSK; grant->mcs[0].tbs = (uint32_t) tbs; } else { n_prb = grant->nof_prb; - grant->nof_tb = 0; + grant->nof_tb = 0; if (dci->tb_en[0]) { grant->mcs[0].idx = dci->mcs_idx; - tbs = srslte_dl_fill_ra_mcs(&grant->mcs[0], n_prb); - if (tbs) { - last_dl_tbs[dci->harq_process%8] = tbs; - } else { - // For mcs>=29, set last TBS received for this PID - grant->mcs[0].tbs = last_dl_tbs[dci->harq_process%8]; - } + grant->mcs[0].tbs = srslte_dl_fill_ra_mcs(&grant->mcs[0], n_prb); grant->nof_tb++; } else { grant->mcs[0].tbs = 0; } if (dci->tb_en[1]) { grant->mcs[1].idx = dci->mcs_idx_1; - tbs = srslte_dl_fill_ra_mcs(&grant->mcs[1], n_prb); - if (tbs) { - last_dl_tbs2[dci->harq_process%8] = tbs; - } else { - // For mcs>=29, set last TBS received for this PID - grant->mcs[1].tbs = last_dl_tbs2[dci->harq_process%8]; - } + grant->mcs[1].tbs = srslte_dl_fill_ra_mcs(&grant->mcs[1], n_prb); } else { grant->mcs[1].tbs = 0; } diff --git a/lib/src/phy/phch/test/pusch_test.c b/lib/src/phy/phch/test/pusch_test.c index 9d048e680..cf0be75c3 100644 --- a/lib/src/phy/phch/test/pusch_test.c +++ b/lib/src/phy/phch/test/pusch_test.c @@ -136,7 +136,7 @@ int main(int argc, char **argv) { dci.mcs_idx = mcs_idx; srslte_ra_ul_grant_t grant; - if (srslte_ra_ul_dci_to_grant(&dci, cell.nof_prb, 0, &grant, 0)) { + if (srslte_ra_ul_dci_to_grant(&dci, cell.nof_prb, 0, &grant)) { fprintf(stderr, "Error computing resource allocation\n"); return ret; } diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 52b617fd5..b80467f4d 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -408,7 +408,7 @@ int phch_worker::decode_pusch(srslte_enb_ul_pusch_t *grants, uint32_t nof_pusch) srslte_ra_ul_grant_t phy_grant; int res = -1; - if (!srslte_ra_ul_dci_to_grant(&grants[i].grant, enb_ul.cell.nof_prb, n_rb_ho, &phy_grant, tti_rx%8)) { + if (!srslte_ra_ul_dci_to_grant(&grants[i].grant, enb_ul.cell.nof_prb, n_rb_ho, &phy_grant)) { if (phy_grant.mcs.mod == SRSLTE_MOD_64QAM) { phy_grant.mcs.mod = SRSLTE_MOD_16QAM; } diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index 0811723e0..c26966c17 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -149,7 +149,12 @@ private: uint32_t I_sr; float cfo; bool rar_cqi_request; - + + // Save last TBS for mcs>28 cases + int last_dl_tbs[2*HARQ_DELAY_MS][SRSLTE_MAX_CODEWORDS]; + int last_ul_tbs[2*HARQ_DELAY_MS]; + srslte_mod_t last_ul_mod[2*HARQ_DELAY_MS]; + // Metrics dl_metrics_t dl_metrics; ul_metrics_t ul_metrics; diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 1d86461cd..9fa3ff669 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -478,10 +478,20 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant) return false; } + grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:(tti%(2*HARQ_DELAY_MS)); + + // Set last TBS for this TB (pid) in case of mcs>29 (7.1.7.2 of 36.213) + for (int i=0;iphy_grant.dl.mcs[i].tbs < 0) { + grant->phy_grant.dl.mcs[i].tbs = last_dl_tbs[grant->pid%(2*HARQ_DELAY_MS)][i]; + } + // save it + last_dl_tbs[grant->pid%(2*HARQ_DELAY_MS)][i] = grant->phy_grant.dl.mcs[i].tbs; + } + /* Fill MAC grant structure */ grant->ndi[0] = dci_unpacked.ndi; grant->ndi[1] = dci_unpacked.ndi_1; - grant->pid = ASYNC_DL_SCHED?dci_unpacked.harq_process:(tti%(2*HARQ_DELAY_MS)); grant->n_bytes[0] = grant->phy_grant.dl.mcs[0].tbs / (uint32_t) 8; grant->n_bytes[1] = grant->phy_grant.dl.mcs[1].tbs / (uint32_t) 8; grant->tti = tti; @@ -718,14 +728,29 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant) ue_dl.last_location_ul.ncce, (1<phy_grant.ul.mcs.tbs==0) { - srslte_vec_fprint_hex(stdout, dci_msg.data, dci_msg.nof_bits); + Info("Received PUSCH grant with empty data\n"); } } } - + + if (ret) { + + // Use last TBS for this TB in case of mcs>28 + if (grant->phy_grant.ul.mcs.tbs < 0) { + grant->phy_grant.ul.mcs.tbs = last_ul_tbs[tti%(2*HARQ_DELAY_MS)]; + } + last_ul_tbs[tti%(2*HARQ_DELAY_MS)] = grant->phy_grant.ul.mcs.tbs; + + if (grant->phy_grant.ul.mcs.mod == SRSLTE_MOD_LAST) { + grant->phy_grant.ul.mcs.mod = last_ul_mod[tti%(2*HARQ_DELAY_MS)]; + grant->phy_grant.ul.Qm = srslte_mod_bits_x_symbol(grant->phy_grant.ul.mcs.mod); + } + last_ul_mod[tti%(2*HARQ_DELAY_MS)] = grant->phy_grant.ul.mcs.mod; + } + /* Limit UL modulation if not supported by the UE or disabled by higher layers */ if (!phy->config->enable_64qam) { - if (grant->phy_grant.ul.mcs.mod == SRSLTE_MOD_64QAM) { + if (grant->phy_grant.ul.mcs.mod >= SRSLTE_MOD_64QAM) { grant->phy_grant.ul.mcs.mod = SRSLTE_MOD_16QAM; grant->phy_grant.ul.Qm = 4; } @@ -898,7 +923,7 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui if (srslte_ue_ul_cfg_grant(&ue_ul, grant, TTI_TX(tti), rv, current_tx_nb)) { Error("Configuring UL grant\n"); } - + if (srslte_ue_ul_pusch_encode_rnti_softbuffer(&ue_ul, payload, uci_data, softbuffer, @@ -925,12 +950,12 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui #endif Info("PUSCH: tti_tx=%d, alloc=(%d,%d), tbs=%d, mcs=%d, rv=%d, ack=%s, ri=%s, cfo=%.1f KHz%s\n", - (tti+4)%10240, - grant->n_prb[0], grant->n_prb[0]+grant->L_prb, - grant->mcs.tbs/8, grant->mcs.idx, rv, - uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no", - uci_data.uci_ri_len>0?(uci_data.uci_ri?"1":"0"):"no", - cfo*15, timestr); + (tti+HARQ_DELAY_MS)%10240, + grant->n_prb[0], grant->n_prb[0]+grant->L_prb, + grant->mcs.tbs/8, grant->mcs.idx, rv, + uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no", + uci_data.uci_ri_len>0?(uci_data.uci_ri?"1":"0"):"no", + cfo*15, timestr); // Store metrics ul_metrics.mcs = grant->mcs.idx; From 9dbbe9731a472d54e2a2a7f47186a04f5f02bb5a Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 19 Oct 2017 16:18:40 -0400 Subject: [PATCH 20/49] missing netmaks string after merge --- srsue/hdr/ue_base.h | 1 + 1 file changed, 1 insertion(+) diff --git a/srsue/hdr/ue_base.h b/srsue/hdr/ue_base.h index 411896f70..634219083 100644 --- a/srsue/hdr/ue_base.h +++ b/srsue/hdr/ue_base.h @@ -109,6 +109,7 @@ typedef struct { std::string ue_cateogry; bool metrics_csv_enable; std::string metrics_csv_filename; + std::string ip_netmask; }expert_args_t; typedef struct { From 05d6a1c82927859f183230243dbf1fd8f6c245ad Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 19 Oct 2017 16:26:00 -0400 Subject: [PATCH 21/49] added option to configure netmask (rules out previous commit) --- srsue/hdr/ue_base.h | 2 +- srsue/hdr/upper/gw.h | 5 +++++ srsue/src/ue.cc | 2 ++ srsue/src/upper/gw.cc | 13 ++++++++++++- srsue/ue.conf.example | 4 +++- 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/srsue/hdr/ue_base.h b/srsue/hdr/ue_base.h index 634219083..b547945a9 100644 --- a/srsue/hdr/ue_base.h +++ b/srsue/hdr/ue_base.h @@ -103,13 +103,13 @@ typedef struct { }gui_args_t; typedef struct { + std::string ip_netmask; phy_args_t phy; float metrics_period_secs; bool pregenerate_signals; std::string ue_cateogry; bool metrics_csv_enable; std::string metrics_csv_filename; - std::string ip_netmask; }expert_args_t; typedef struct { diff --git a/srsue/hdr/upper/gw.h b/srsue/hdr/upper/gw.h index 800b31624..b97ceb6c5 100644 --- a/srsue/hdr/upper/gw.h +++ b/srsue/hdr/upper/gw.h @@ -57,8 +57,13 @@ public: // NAS interface srslte::error_t setup_if_addr(uint32_t ip_addr, char *err_str); + void set_netmask(std::string netmask); + private: + bool default_netmask; + std::string netmask; + static const int GW_THREAD_PRIO = 7; pdcp_interface_gw *pdcp; diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 3560a78fe..a99281e6f 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -185,6 +185,8 @@ bool ue::init(all_args_t *args_) nas.init(&usim, &rrc, &gw, &nas_log, 1 /* RB_ID_SRB1 */); gw.init(&pdcp, &nas, &gw_log, 3 /* RB_ID_DRB1 */); + gw.set_netmask(args->expert.ip_netmask); + rrc.init(&phy, &mac, &rlc, &pdcp, &nas, &usim, &mac, &rrc_log); rrc.set_ue_category(atoi(args->expert.ue_cateogry.c_str())); diff --git a/srsue/src/upper/gw.cc b/srsue/src/upper/gw.cc index 07ac36989..1e3e81999 100644 --- a/srsue/src/upper/gw.cc +++ b/srsue/src/upper/gw.cc @@ -44,6 +44,7 @@ gw::gw() :if_up(false) { current_ip_addr = 0; + default_netmask = true; } void gw::init(pdcp_interface_gw *pdcp_, nas_interface_gw *nas_, srslte::log *gw_log_, uint32_t lcid_) @@ -104,6 +105,12 @@ void gw::get_metrics(gw_metrics_t &m) ul_tput_bytes = 0; } +void gw::set_netmask(std::string netmask) { + default_netmask = false; + this->netmask = netmask; +} + + /******************************************************************************* PDCP interface *******************************************************************************/ @@ -152,7 +159,11 @@ srslte::error_t gw::setup_if_addr(uint32_t ip_addr, char *err_str) return(srslte::ERROR_CANT_START); } ifr.ifr_netmask.sa_family = AF_INET; - ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.0"); + const char *mask = "255.255.255.0"; + if (!default_netmask) { + mask = netmask.c_str(); + } + ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr(mask); if(0 > ioctl(sock, SIOCSIFNETMASK, &ifr)) { err_str = strerror(errno); diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 5d14d3c3c..d0dc67952 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -98,7 +98,8 @@ enable = false ##################################################################### # Expert configuration options # -# ue_category: Sets UE category (range 1-5). Default: 4 +# ip_netmask: Netmask of the tun_srsue device. Default: 255.255.255.0 +# ue_category: Sets UE category (range 1-5). Default: 4 # # prach_gain: PRACH gain (dB). If defined, forces a gain for the tranmsission of PRACH only., # Default is to use tx_gain in [rf] section. @@ -138,6 +139,7 @@ enable = false # ##################################################################### [expert] +#ip_netmask = 255.255.255.0 #ue_category = 4 #prach_gain = 30 #cqi_max = 15 From 49a105baed23e14fcac95e23a005837477b6b41c Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Thu, 19 Oct 2017 22:21:18 +0100 Subject: [PATCH 22/49] Fix for tests, minor fix for RLC UM --- lib/src/upper/rlc_um.cc | 2 +- lib/test/upper/rlc_um_test.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index 045fb0b7e..d95e186e7 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -277,7 +277,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) int head_len = rlc_um_packed_length(&header); int pdu_space = nof_bytes; - if(pdu_space <= head_len) + if(pdu_space <= head_len + 1) { log->warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n", rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len); diff --git a/lib/test/upper/rlc_um_test.cc b/lib/test/upper/rlc_um_test.cc index 0894a2a8b..8abcfae3c 100644 --- a/lib/test/upper/rlc_um_test.cc +++ b/lib/test/upper/rlc_um_test.cc @@ -123,7 +123,7 @@ void basic_test() byte_buffer_t pdu_bufs[NBUFS]; for(int i=0;i Date: Thu, 19 Oct 2017 18:10:17 -0400 Subject: [PATCH 23/49] coverty uninitialized member --- srsue/src/mac/demux.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/src/mac/demux.cc b/srsue/src/mac/demux.cc index 14c524165..171e7bf45 100644 --- a/srsue/src/mac/demux.cc +++ b/srsue/src/mac/demux.cc @@ -36,7 +36,7 @@ namespace srsue { -demux::demux() : mac_msg(20), pending_mac_msg(20) +demux::demux() : mac_msg(20), pending_mac_msg(20), rlc(NULL) { } From c14393b24f874b4e12d3bbfb883133fedda4f6f1 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Thu, 19 Oct 2017 19:39:54 -0400 Subject: [PATCH 24/49] Disable RSSI sensor by default --- srsue/src/main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 3b0cad2d0..1b146a9f3 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -155,7 +155,7 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { "Pregenerate uplink signals after attach. Improves CPU performance.") ("expert.rssi_sensor_enabled", - bpo::value(&args->expert.phy.rssi_sensor_enabled)->default_value(true), + bpo::value(&args->expert.phy.rssi_sensor_enabled)->default_value(false), "Enable or disable RF frontend RSSI sensor. In some USRP devices can cause segmentation fault") ("expert.prach_gain", From a570e63c5b8977a8f864cde6d7103a2233ae8c83 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 20 Oct 2017 15:05:04 +0200 Subject: [PATCH 25/49] Corrected bug in RA --- lib/include/srslte/phy/phch/ra.h | 2 -- lib/src/phy/phch/ra.c | 14 ++++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/include/srslte/phy/phch/ra.h b/lib/include/srslte/phy/phch/ra.h index 680d80dd6..aef8f4751 100644 --- a/lib/include/srslte/phy/phch/ra.h +++ b/lib/include/srslte/phy/phch/ra.h @@ -103,9 +103,7 @@ typedef struct SRSLTE_API { bool prb_idx[2][SRSLTE_MAX_PRB]; uint32_t nof_prb; uint32_t Qm[SRSLTE_MAX_CODEWORDS]; - uint32_t Qm2[SRSLTE_MAX_CODEWORDS]; srslte_ra_mcs_t mcs[SRSLTE_MAX_CODEWORDS]; - srslte_ra_mcs_t mcs2[SRSLTE_MAX_CODEWORDS]; uint32_t nof_tb; srslte_sf_t sf_type; bool tb_en[SRSLTE_MAX_CODEWORDS]; diff --git a/lib/src/phy/phch/ra.c b/lib/src/phy/phch/ra.c index 8cae9fe65..913bd9548 100644 --- a/lib/src/phy/phch/ra.c +++ b/lib/src/phy/phch/ra.c @@ -549,7 +549,7 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr } grant->pinfo = dci->pinfo; - if (tbs < 0) { + if (grant->mcs[0].tbs < 0 || grant->mcs[1].tbs < 0) { return SRSLTE_ERROR; } else { return SRSLTE_SUCCESS; @@ -584,10 +584,12 @@ int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci, if (msg_rnti >= SRSLTE_CRNTI_START && msg_rnti <= SRSLTE_CRNTI_END) { crc_is_crnti = true; } - // Compute PRB allocation - if (!srslte_ra_dl_dci_to_grant_prb_allocation(dci, grant, nof_prb)) { - // Compute MCS - if (!dl_dci_to_grant_mcs(dci, grant, crc_is_crnti)) { + // Compute PRB allocation + int ret =srslte_ra_dl_dci_to_grant_prb_allocation(dci, grant, nof_prb); + if (!ret) { + // Compute MCS + ret = dl_dci_to_grant_mcs(dci, grant, crc_is_crnti); + if (ret == SRSLTE_SUCCESS) { // Apply Section 7.1.7.3. If RA-RNTI and Format1C rv_idx=0 if (msg_rnti >= SRSLTE_RARNTI_START && msg_rnti <= SRSLTE_RARNTI_END && dci->dci_is_1c) @@ -869,4 +871,4 @@ void srslte_ra_prb_fprint(FILE *f, srslte_ra_dl_grant_t *grant) { } } -} \ No newline at end of file +} From 3b4649b9f730786d010962b33b924693137d8925 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 20 Oct 2017 09:29:56 -0400 Subject: [PATCH 26/49] Fixed bug in calc_new_transmission --- srsue/hdr/mac/dl_harq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/hdr/mac/dl_harq.h b/srsue/hdr/mac/dl_harq.h index 9abcf0922..521018d73 100644 --- a/srsue/hdr/mac/dl_harq.h +++ b/srsue/hdr/mac/dl_harq.h @@ -347,7 +347,7 @@ private: // Determine if it's a new transmission 5.3.2.2 bool calc_is_new_transmission(Tgrant grant) { - if (grant.phy_grant.dl.mcs[tid].idx < 28 && // mcs 29,30,31 always retx regardless of rest + if (grant.phy_grant.dl.mcs[tid].idx <= 28 && // mcs 29,30,31 always retx regardless of rest ((grant.ndi[tid] != cur_grant.ndi[tid]) || // 1st condition (NDI has changed) (pid == HARQ_BCCH_PID && grant.rv[tid] == 0) || // 2nd condition (Broadcast and 1st transmission) is_first_tb)) From c8bba2f4d07ada34376ff19c19c10a9cf50f7a17 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 20 Oct 2017 16:09:27 +0200 Subject: [PATCH 27/49] DFT optimization. memcpy removal (#76) * Solved PHICH Segmentation fault for MIMO * Initial Guru FFT optimitzation * Guru (i)FFT implemented. All test passed! * Integrated new DFT into pdsch_enodeb and pdsch_ue. Solved more DFT bugs. * Solved Merge Errors and bugs * Solved UL Guru bug (DC missing). Updated Init and OFDM calls for enb and ue (cell measurement too). --- lib/examples/cell_measurement.c | 28 +- lib/examples/pdsch_enodeb.c | 26 +- lib/examples/pdsch_ue.c | 13 +- lib/include/srslte/phy/common/phy_common.h | 4 +- lib/include/srslte/phy/dft/dft.h | 24 ++ lib/include/srslte/phy/dft/ofdm.h | 40 +-- lib/include/srslte/phy/enb/enb_dl.h | 8 +- lib/include/srslte/phy/enb/enb_ul.h | 1 + lib/include/srslte/phy/ue/ue_dl.h | 3 +- lib/include/srslte/phy/ue/ue_mib.h | 2 +- lib/include/srslte/phy/ue/ue_ul.h | 1 + lib/src/phy/dft/dft_fftw.c | 62 +++- lib/src/phy/dft/ofdm.c | 271 +++++++++++++++--- lib/src/phy/dft/test/ofdm_test.c | 63 +++- lib/src/phy/enb/enb_dl.c | 57 ++-- lib/src/phy/enb/enb_ul.c | 31 +- lib/src/phy/phch/test/pbch_file_test.c | 4 +- lib/src/phy/phch/test/pcfich_file_test.c | 10 +- lib/src/phy/phch/test/pdcch_file_test.c | 6 +- lib/src/phy/phch/test/pdsch_pdcch_file_test.c | 4 +- lib/src/phy/phch/test/phich_file_test.c | 6 +- lib/src/phy/phch/test/pmch_file_test.c | 2 +- lib/src/phy/phch/test/pmch_test.c | 122 ++++---- lib/src/phy/sync/test/sync_test.c | 12 +- lib/src/phy/ue/ue_dl.c | 77 ++--- lib/src/phy/ue/ue_mib.c | 13 +- lib/src/phy/ue/ue_ul.c | 22 +- srsenb/hdr/phy/phch_worker.h | 2 +- srsenb/src/phy/phch_worker.cc | 19 +- srsue/src/phy/phch_recv.cc | 8 +- srsue/src/phy/phch_worker.cc | 4 +- 31 files changed, 647 insertions(+), 298 deletions(-) diff --git a/lib/examples/cell_measurement.c b/lib/examples/cell_measurement.c index 37796682f..bfb8194df 100644 --- a/lib/examples/cell_measurement.c +++ b/lib/examples/cell_measurement.c @@ -249,7 +249,7 @@ int main(int argc, char **argv) { fprintf(stderr, "Error initiating ue_sync\n"); return -1; } - if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) { + if (srslte_ue_dl_init(&ue_dl, sf_buffer, cell.nof_prb, 1)) { fprintf(stderr, "Error initiating UE downlink processing module\n"); return -1; } @@ -257,7 +257,7 @@ int main(int argc, char **argv) { fprintf(stderr, "Error initiating UE downlink processing module\n"); return -1; } - if (srslte_ue_mib_init(&ue_mib, cell.nof_prb)) { + if (srslte_ue_mib_init(&ue_mib, sf_buffer, cell.nof_prb)) { fprintf(stderr, "Error initaiting UE MIB decoder\n"); return -1; } @@ -271,8 +271,16 @@ int main(int argc, char **argv) { /* Initialize subframe counter */ sf_cnt = 0; - - if (srslte_ofdm_rx_init(&fft, cell.cp, cell.nof_prb)) { + + int sf_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp); + + cf_t *sf_symbols = srslte_vec_malloc(sf_re * sizeof(cf_t)); + + for (int i=0;iout = fftwf_malloc(size_out*len); } +int srslte_dft_replan_guru_c(srslte_dft_plan_t *plan, const int new_dft_points, cf_t *in_buffer, + cf_t *out_buffer, int istride, int ostride, int how_many, + int idist, int odist) { + int sign = (plan->forward) ? FFTW_FORWARD : FFTW_BACKWARD; + + const fftwf_iodim iodim = {new_dft_points, istride, ostride}; + const fftwf_iodim howmany_dims = {how_many, idist, odist}; + + /* Destroy current plan */ + fftwf_destroy_plan(plan->p); + + plan->p = fftwf_plan_guru_dft(1, &iodim, 1, &howmany_dims, in_buffer, out_buffer, sign, FFTW_TYPE); + if (!plan->p) { + return -1; + } + plan->size = new_dft_points; + plan->init_size = plan->size; + + return 0; +} + int srslte_dft_replan_c(srslte_dft_plan_t *plan, const int new_dft_points) { int sign = (plan->dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD; if (plan->p) { @@ -107,6 +128,32 @@ int srslte_dft_replan_c(srslte_dft_plan_t *plan, const int new_dft_points) { return 0; } +int srslte_dft_plan_guru_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir, cf_t *in_buffer, + cf_t *out_buffer, int istride, int ostride, int how_many, + int idist, int odist) { + int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD; + + const fftwf_iodim iodim = {dft_points, istride, ostride}; + const fftwf_iodim howmany_dims = {how_many, idist, odist}; + + plan->p = fftwf_plan_guru_dft(1, &iodim, 1, &howmany_dims, in_buffer, out_buffer, sign, FFTW_TYPE); + if (!plan->p) { + return -1; + } + plan->size = dft_points; + plan->init_size = plan->size; + plan->mode = SRSLTE_DFT_COMPLEX; + plan->dir = dir; + plan->forward = (dir==SRSLTE_DFT_FORWARD)?true:false; + plan->mirror = false; + plan->db = false; + plan->norm = false; + plan->dc = false; + plan->is_guru = true; + + return 0; +} + int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_dir_t dir) { allocate(plan,sizeof(fftwf_complex),sizeof(fftwf_complex), dft_points); int sign = (dir == SRSLTE_DFT_FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD; @@ -123,6 +170,7 @@ int srslte_dft_plan_c(srslte_dft_plan_t *plan, const int dft_points, srslte_dft_ plan->db = false; plan->norm = false; plan->dc = false; + plan->is_guru = false; return 0; } @@ -232,6 +280,14 @@ void srslte_dft_run_c(srslte_dft_plan_t *plan, cf_t *in, cf_t *out) { plan->forward, plan->mirror, plan->dc); } +void srslte_dft_run_guru_c(srslte_dft_plan_t *plan) { + if (plan->is_guru == true) { + fftwf_execute(plan->p); + } else { + fprintf(stderr, "srslte_dft_run_guru_c: the selected plan is not guru!\n"); + } +} + void srslte_dft_run_r(srslte_dft_plan_t *plan, float *in, float *out) { float norm; int i; @@ -255,8 +311,10 @@ void srslte_dft_run_r(srslte_dft_plan_t *plan, float *in, float *out) { void srslte_dft_plan_free(srslte_dft_plan_t *plan) { if (!plan) return; if (!plan->size) return; - if (plan->in) fftwf_free(plan->in); - if (plan->out) fftwf_free(plan->out); + if (!plan->is_guru) { + if (plan->in) fftwf_free(plan->in); + if (plan->out) fftwf_free(plan->out); + } if (plan->p) fftwf_destroy_plan(plan->p); bzero(plan, sizeof(srslte_dft_plan_t)); } diff --git a/lib/src/phy/dft/ofdm.c b/lib/src/phy/dft/ofdm.c index db5939274..8ea690bb5 100644 --- a/lib/src/phy/dft/ofdm.c +++ b/lib/src/phy/dft/ofdm.c @@ -37,23 +37,79 @@ #include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/vector.h" +/* Uncomment next line for avoiding Guru DFT call */ +//#define AVOID_GURU -int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_prb, srslte_dft_dir_t dir) { - return srslte_ofdm_init_mbsfn_(q, cp, symbol_sz, nof_prb, dir, SRSLTE_SF_NORM); +int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, int symbol_sz, int nof_prb, srslte_dft_dir_t dir) { + return srslte_ofdm_init_mbsfn_(q, cp, in_buffer, out_buffer, symbol_sz, nof_prb, dir, SRSLTE_SF_NORM); } +int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, int symbol_sz, int nof_prb, srslte_dft_dir_t dir, srslte_sf_t sf_type) { -int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_prb, srslte_dft_dir_t dir, srslte_sf_t sf_type) { + /* Set OFDM object attributes */ + q->symbol_sz = (uint32_t) symbol_sz; + q->nof_symbols = SRSLTE_CP_NSYMB(cp); + q->nof_symbols_mbsfn = SRSLTE_CP_NSYMB(SRSLTE_CP_EXT); + q->cp = cp; + q->freq_shift = false; + q->nof_re = (uint32_t) nof_prb * SRSLTE_NRE; + q->nof_guards = ((symbol_sz - q->nof_re) / 2); + q->slot_sz = (uint32_t) SRSLTE_SLOT_LEN(symbol_sz); + q->sf_sz = (uint32_t) SRSLTE_SF_LEN(symbol_sz); + q->in_buffer = in_buffer; + q->out_buffer= out_buffer; if (srslte_dft_plan_c(&q->fft_plan, symbol_sz, dir)) { fprintf(stderr, "Error: Creating DFT plan\n"); return -1; } + +#ifdef AVOID_GURU q->tmp = srslte_vec_malloc((uint32_t) symbol_sz * sizeof(cf_t)); if (!q->tmp) { perror("malloc"); return -1; } + bzero(q->tmp, sizeof(cf_t) * symbol_sz); +#else + int cp1 = SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN_NORM(0, symbol_sz):SRSLTE_CP_LEN_EXT(symbol_sz); + int cp2 = SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN_NORM(1, symbol_sz):SRSLTE_CP_LEN_EXT(symbol_sz); + + q->tmp = srslte_vec_malloc(sizeof(cf_t) * q->sf_sz); + if (!q->tmp) { + perror("malloc"); + return -1; + } + bzero(q->tmp, sizeof(cf_t) * q->sf_sz); + + if (dir == SRSLTE_DFT_BACKWARD) { + bzero(in_buffer, sizeof(cf_t) * SRSLTE_SF_LEN_RE(nof_prb, cp)); + }else { + bzero(in_buffer, sizeof(cf_t) * q->sf_sz); + } + + for (int slot = 0; slot < 2; slot++) { + //bzero(&q->fft_plan_sf[slot], sizeof(srslte_dft_plan_t)); + //bzero(q->tmp + SRSLTE_CP_NSYMB(cp)*symbol_sz*slot, sizeof(cf_t) * (cp1 + (SRSLTE_CP_NSYMB(cp) - 1)*cp2 + SRSLTE_CP_NSYMB(cp)*symbol_sz)); + if (dir == SRSLTE_DFT_FORWARD) { + if (srslte_dft_plan_guru_c(&q->fft_plan_sf[slot], symbol_sz, dir, + in_buffer + cp1 + q->slot_sz * slot, + q->tmp + q->nof_symbols * q->symbol_sz * slot, + 1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz + cp2, symbol_sz)) { + fprintf(stderr, "Error: Creating DFT plan (1)\n"); + return -1; + } + } else { + if (srslte_dft_plan_guru_c(&q->fft_plan_sf[slot], symbol_sz, dir, + q->tmp + q->nof_symbols * q->symbol_sz * slot, + out_buffer + cp1 + q->slot_sz * slot, + 1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz, symbol_sz + cp2)) { + fprintf(stderr, "Error: Creating DFT plan (1)\n"); + return -1; + } + } + } +#endif q->shift_buffer = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN(symbol_sz)); if (!q->shift_buffer) { @@ -64,15 +120,6 @@ int srslte_ofdm_init_mbsfn_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int srslte_dft_plan_set_mirror(&q->fft_plan, true); srslte_dft_plan_set_dc(&q->fft_plan, true); - q->symbol_sz = (uint32_t) symbol_sz; - q->nof_symbols = SRSLTE_CP_NSYMB(cp); - q->nof_symbols_mbsfn = SRSLTE_CP_NSYMB(SRSLTE_CP_EXT); - q->cp = cp; - q->freq_shift = false; - q->nof_re = nof_prb * SRSLTE_NRE; - q->nof_guards = ((symbol_sz - q->nof_re) / 2); - q->slot_sz = SRSLTE_SLOT_LEN(symbol_sz); - DEBUG("Init %s symbol_sz=%d, nof_symbols=%d, cp=%s, nof_re=%d, nof_guards=%d\n", dir==SRSLTE_DFT_FORWARD?"FFT":"iFFT", q->symbol_sz, q->nof_symbols, q->cp==SRSLTE_CP_NORM?"Normal":"Extended", q->nof_re, q->nof_guards); @@ -101,9 +148,60 @@ int srslte_ofdm_replan_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof q->symbol_sz = (uint32_t) symbol_sz; q->nof_symbols = SRSLTE_CP_NSYMB(cp); q->cp = cp; - q->nof_re = nof_prb * SRSLTE_NRE; + q->nof_re = (uint32_t) nof_prb * SRSLTE_NRE; q->nof_guards = ((symbol_sz - q->nof_re) / 2); - q->slot_sz = SRSLTE_SLOT_LEN(symbol_sz); + q->slot_sz = (uint32_t) SRSLTE_SLOT_LEN(symbol_sz); + q->sf_sz = (uint32_t) SRSLTE_SF_LEN(symbol_sz); + +#ifndef AVOID_GURU + cf_t *in_buffer = q->in_buffer; + cf_t *out_buffer = q->out_buffer; + + int cp1 = SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN_NORM(0, symbol_sz):SRSLTE_CP_LEN_EXT(symbol_sz); + int cp2 = SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN_NORM(1, symbol_sz):SRSLTE_CP_LEN_EXT(symbol_sz); + + srslte_dft_dir_t dir = q->fft_plan_sf[0].dir; + + if (q->tmp) { + free(q->tmp); + } + + q->tmp = srslte_vec_malloc(sizeof(cf_t) * q->sf_sz); + if (!q->tmp) { + perror("malloc"); + return -1; + } + bzero(q->tmp, sizeof(cf_t) * q->sf_sz); + + if (dir == SRSLTE_DFT_BACKWARD) { + bzero(in_buffer, sizeof(cf_t) * SRSLTE_SF_LEN_RE(nof_prb, cp)); + }else { + bzero(in_buffer, sizeof(cf_t) * q->sf_sz); + } + + for (int slot = 0; slot < 2; slot++) { + srslte_dft_plan_free(&q->fft_plan_sf[slot]); + + if (dir == SRSLTE_DFT_FORWARD) { + if (srslte_dft_plan_guru_c(&q->fft_plan_sf[slot], symbol_sz, dir, + in_buffer + cp1 + q->slot_sz * slot, + q->tmp + q->nof_symbols * q->symbol_sz * slot, + 1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz + cp2, symbol_sz)) { + fprintf(stderr, "Error: Creating DFT plan (1)\n"); + return -1; + } + } else { + if (srslte_dft_plan_guru_c(&q->fft_plan_sf[slot], symbol_sz, dir, + q->tmp + q->nof_symbols * q->symbol_sz * slot, + out_buffer + cp1 + q->slot_sz * slot, + 1, 1, SRSLTE_CP_NSYMB(cp), symbol_sz, symbol_sz + cp2)) { + fprintf(stderr, "Error: Creating DFT plan (1)\n"); + return -1; + } + } + } +#endif /* AVOID_GURU */ + if (q->freq_shift) { srslte_ofdm_set_freq_shift(q, q->freq_shift_f); @@ -118,6 +216,15 @@ int srslte_ofdm_replan_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof void srslte_ofdm_free_(srslte_ofdm_t *q) { srslte_dft_plan_free(&q->fft_plan); + +#ifndef AVOID_GURU + for (int slot = 0; slot < 2; slot++) { + if (q->fft_plan_sf[slot].init_size) { + srslte_dft_plan_free(&q->fft_plan_sf[slot]); + } + } +#endif + if (q->tmp) { free(q->tmp); } @@ -127,28 +234,28 @@ void srslte_ofdm_free_(srslte_ofdm_t *q) { bzero(q, sizeof(srslte_ofdm_t)); } -int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) { +int srslte_ofdm_rx_init(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, uint32_t max_prb) { int symbol_sz = srslte_symbol_sz(max_prb); if (symbol_sz < 0) { fprintf(stderr, "Error: Invalid nof_prb=%d\n", max_prb); return -1; } q->max_prb = max_prb; - return srslte_ofdm_init_(q, cp, symbol_sz, max_prb, SRSLTE_DFT_FORWARD); + return srslte_ofdm_init_(q, cp, in_buffer, out_buffer, symbol_sz, max_prb, SRSLTE_DFT_FORWARD); } -int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) +int srslte_ofdm_rx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, uint32_t nof_prb) { int symbol_sz = srslte_symbol_sz(nof_prb); if (symbol_sz < 0) { fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb); return -1; } - return srslte_ofdm_init_mbsfn_(q, cp, symbol_sz, nof_prb, SRSLTE_DFT_FORWARD, SRSLTE_SF_MBSFN); + return srslte_ofdm_init_mbsfn_(q, cp, in_buffer, out_buffer, symbol_sz, nof_prb, SRSLTE_DFT_FORWARD, SRSLTE_SF_MBSFN); } -int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) { +int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, uint32_t max_prb) { uint32_t i; int ret; @@ -158,7 +265,7 @@ int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) { return -1; } q->max_prb = max_prb; - ret = srslte_ofdm_init_(q, cp, symbol_sz, max_prb, SRSLTE_DFT_BACKWARD); + ret = srslte_ofdm_init_(q, cp, in_buffer, out_buffer, symbol_sz, max_prb, SRSLTE_DFT_BACKWARD); if (ret == SRSLTE_SUCCESS) { @@ -173,7 +280,7 @@ int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t max_prb) { return ret; } -int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) +int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, cf_t *in_buffer, cf_t *out_buffer, uint32_t nof_prb) { uint32_t i; int ret; @@ -184,7 +291,7 @@ int srslte_ofdm_tx_init_mbsfn(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb return -1; } - ret = srslte_ofdm_init_mbsfn_(q, cp, symbol_sz, nof_prb, SRSLTE_DFT_BACKWARD, SRSLTE_SF_MBSFN); + ret = srslte_ofdm_init_mbsfn_(q, cp, in_buffer, out_buffer, symbol_sz, nof_prb, SRSLTE_DFT_BACKWARD, SRSLTE_SF_MBSFN); if (ret == SRSLTE_SUCCESS) { srslte_dft_plan_set_norm(&q->fft_plan, false); @@ -207,7 +314,8 @@ int srslte_ofdm_rx_set_prb(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) { } return srslte_ofdm_replan_(q, cp, symbol_sz, nof_prb); } else { - fprintf(stderr, "OFDM: Error calling set_prb: nof_prb must be equal or lower initialized max_prb\n"); + fprintf(stderr, "OFDM (Rx): Error calling set_prb: nof_prb (%d) must be equal or lower initialized max_prb (%d)\n", + nof_prb, q->max_prb); return -1; } } @@ -234,7 +342,8 @@ int srslte_ofdm_tx_set_prb(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) { } return ret; } else { - fprintf(stderr, "OFDM: Error calling set_prb: nof_prb must be equal or lower initialized max_prb\n"); + fprintf(stderr, "OFDM (Tx): Error calling set_prb: nof_prb (%d) must be equal or lower initialized max_prb (%d)\n", + nof_prb, q->max_prb); return -1; } } @@ -274,8 +383,12 @@ void srslte_ofdm_tx_free(srslte_ofdm_t *q) { /* Transforms input samples into output OFDM symbols. * Performs FFT on a each symbol and removes CP. */ -void srslte_ofdm_rx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) { +void srslte_ofdm_rx_slot(srslte_ofdm_t *q, int slot_in_sf) { + cf_t *output = q->out_buffer + slot_in_sf * q->nof_re * q->nof_symbols; + +#ifdef AVOID_GURU uint32_t i; + cf_t *input = q->in_buffer + slot_in_sf * q->slot_sz; for (i=0;inof_symbols;i++) { input += SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz); srslte_dft_run_c(&q->fft_plan, input, q->tmp); @@ -283,6 +396,25 @@ void srslte_ofdm_rx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) { input += q->symbol_sz; output += q->nof_re; } +#else + float norm = 1.0f/sqrtf(q->fft_plan.size); + cf_t *tmp = q->tmp + slot_in_sf * q->symbol_sz * q->nof_symbols; + uint32_t dc = (q->fft_plan.dc) ? 1:0; + + srslte_dft_run_guru_c(&q->fft_plan_sf[slot_in_sf]); + + for (int i = 0; i < q->nof_symbols; i++) { + memcpy(output, tmp + q->symbol_sz - q->nof_re / 2, sizeof(cf_t) * q->nof_re / 2); + memcpy(output + q->nof_re / 2, &tmp[dc], sizeof(cf_t) * q->nof_re / 2); + + if (q->fft_plan.norm) { + srslte_vec_sc_prod_cfc(output, norm, output, q->nof_re); + } + + tmp += q->symbol_sz; + output += q->nof_re; + } +#endif } void srslte_ofdm_rx_slot_mbsfn(srslte_ofdm_t *q, cf_t *input, cf_t *output) @@ -314,29 +446,32 @@ void srslte_ofdm_rx_slot_zerocopy(srslte_ofdm_t *q, cf_t *input, cf_t *output) { } } -void srslte_ofdm_rx_sf(srslte_ofdm_t *q, cf_t *input, cf_t *output) { - uint32_t n; +void srslte_ofdm_rx_sf(srslte_ofdm_t *q) { + uint32_t n; if (q->freq_shift) { - srslte_vec_prod_ccc(input, q->shift_buffer, input, 2*q->slot_sz); + srslte_vec_prod_ccc(q->in_buffer, q->shift_buffer, q->in_buffer, 2*q->slot_sz); } if(!q->mbsfn_subframe){ for (n=0;n<2;n++) { - srslte_ofdm_rx_slot(q, &input[n*q->slot_sz], &output[n*q->nof_re*q->nof_symbols]); + srslte_ofdm_rx_slot(q, n); } } else{ - srslte_ofdm_rx_slot_mbsfn(q, &input[0*q->slot_sz], &output[0*q->nof_re*q->nof_symbols]); - srslte_ofdm_rx_slot(q, &input[1*q->slot_sz], &output[1*q->nof_re*q->nof_symbols]); + srslte_ofdm_rx_slot_mbsfn(q, &q->in_buffer[0*q->slot_sz], &q->out_buffer[0*q->nof_re*q->nof_symbols]); + srslte_ofdm_rx_slot(q, 1); } } /* Transforms input OFDM symbols into output samples. * Performs FFT on a each symbol and adds CP. */ -void srslte_ofdm_tx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) { - uint32_t i, cp_len; - for (i=0;inof_symbols;i++) { - cp_len = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz); +void srslte_ofdm_tx_slot(srslte_ofdm_t *q, int slot_in_sf) { + cf_t *input = q->in_buffer + slot_in_sf * q->nof_re * q->nof_symbols; + cf_t *output = q->out_buffer + slot_in_sf * q->slot_sz; + +#ifdef AVOID_GURU + for (int i=0;inof_symbols;i++) { + int cp_len = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz); memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t)); srslte_dft_run_c(&q->fft_plan, q->tmp, &output[cp_len]); input += q->nof_re; @@ -344,6 +479,60 @@ void srslte_ofdm_tx_slot(srslte_ofdm_t *q, cf_t *input, cf_t *output) { memcpy(output, &output[q->symbol_sz], cp_len * sizeof(cf_t)); output += q->symbol_sz + cp_len; } +#else + float norm = 1.0f/sqrtf(q->symbol_sz); + cf_t *tmp = q->tmp + slot_in_sf * q->symbol_sz * q->nof_symbols; + + bzero(tmp, q->slot_sz); + uint32_t dc = (q->fft_plan.dc) ? 1:0; + + for (int i = 0; i < q->nof_symbols; i++) { + memcpy(&tmp[dc], &input[q->nof_re / 2], q->nof_re / 2 * sizeof(cf_t)); + memcpy(&tmp[q->symbol_sz - q->nof_re / 2], &input[0], q->nof_re / 2 * sizeof(cf_t)); + + input += q->nof_re; + tmp += q->symbol_sz; + } + + srslte_dft_run_guru_c(&q->fft_plan_sf[slot_in_sf]); + + for (int i=0;inof_symbols;i++) { + int cp_len = SRSLTE_CP_ISNORM(q->cp) ? SRSLTE_CP_LEN_NORM(i, q->symbol_sz) : SRSLTE_CP_LEN_EXT(q->symbol_sz); + + if (q->fft_plan.norm) { + srslte_vec_sc_prod_cfc(&output[cp_len], norm, &output[cp_len], q->symbol_sz); + } + + /* add CP */ + memcpy(output, &output[q->symbol_sz], cp_len * sizeof(cf_t)); + output += q->symbol_sz + cp_len; + } +#endif + + /*input = q->in_buffer + slot_in_sf * q->nof_re * q->nof_symbols; + cf_t *output2 = srslte_vec_malloc(sizeof(cf_t) * q->slot_sz); + cf_t *o2 = output2; + bzero(q->tmp, sizeof(cf_t)*q->symbol_sz); + //bzero(output2, sizeof(cf_t)*q->slot_sz); + for (int i=0;inof_symbols;i++) { + int cp_len = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(i, q->symbol_sz):SRSLTE_CP_LEN_EXT(q->symbol_sz); + memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t)); + srslte_dft_run_c(&q->fft_plan, q->tmp, &o2[cp_len]); + input += q->nof_re; + memcpy(o2, &o2[q->symbol_sz], cp_len * sizeof(cf_t)); + o2 += q->symbol_sz + cp_len; + } + cf_t *output1 = q->out_buffer + slot_in_sf * q->slot_sz;//srslte_vec_malloc(sizeof(cf_t) * q->slot_sz); + + for (int i = 0; i < q->slot_sz; i++) { + float error = cabsf(output1[i] - output2[i])/cabsf(output2[i]); + cf_t k = output1[i]/output2[i]; + if (error > 0.1) printf("%d/%05d error=%f output=%+f%+fi gold=%+f%+fi k=%+f%+fi\n", slot_in_sf, i, error, + __real__ output1[i], __imag__ output1[i], + __real__ output2[i], __imag__ output2[i], + __real__ k, __imag__ k); + } + free(output2);/**/ } void srslte_ofdm_tx_slot_mbsfn(srslte_ofdm_t *q, cf_t *input, cf_t *output) @@ -369,20 +558,20 @@ void srslte_ofdm_set_normalize(srslte_ofdm_t *q, bool normalize_enable) { srslte_dft_plan_set_norm(&q->fft_plan, normalize_enable); } -void srslte_ofdm_tx_sf(srslte_ofdm_t *q, cf_t *input, cf_t *output) +void srslte_ofdm_tx_sf(srslte_ofdm_t *q) { - uint32_t n; + uint32_t n; if(!q->mbsfn_subframe){ for (n=0;n<2;n++) { - srslte_ofdm_tx_slot(q, &input[n*q->nof_re*q->nof_symbols], &output[n*q->slot_sz]); + srslte_ofdm_tx_slot(q, n); } } else{ - srslte_ofdm_tx_slot_mbsfn(q, &input[0*q->nof_re*q->nof_symbols], &output[0*q->slot_sz]); - srslte_ofdm_tx_slot(q, &input[1*q->nof_re*q->nof_symbols], &output[1*q->slot_sz]); + srslte_ofdm_tx_slot_mbsfn(q, &q->in_buffer[0*q->nof_re*q->nof_symbols], &q->out_buffer[0*q->slot_sz]); + srslte_ofdm_tx_slot(q, 1); } if (q->freq_shift) { - srslte_vec_prod_ccc(output, q->shift_buffer, output, 2*q->slot_sz); + srslte_vec_prod_ccc(q->out_buffer, q->shift_buffer, q->out_buffer, 2*q->slot_sz); } } diff --git a/lib/src/phy/dft/test/ofdm_test.c b/lib/src/phy/dft/test/ofdm_test.c index 11aac7f4e..e77fcd39e 100644 --- a/lib/src/phy/dft/test/ofdm_test.c +++ b/lib/src/phy/dft/test/ofdm_test.c @@ -35,16 +35,28 @@ int nof_prb = -1; srslte_cp_t cp = SRSLTE_CP_NORM; +int nof_repetitions = 128; + +static double elapsed_us(struct timeval *ts_start, struct timeval *ts_end) { + if (ts_end->tv_usec > ts_start->tv_usec) { + return ((double) ts_end->tv_sec - (double) ts_start->tv_sec) * 1000000 + + (double) ts_end->tv_usec - (double) ts_start->tv_usec; + } else { + return ((double) ts_end->tv_sec - (double) ts_start->tv_sec - 1) * 1000000 + + ((double) ts_end->tv_usec + 1000000) - (double) ts_start->tv_usec; + } +} void usage(char *prog) { printf("Usage: %s\n", prog); printf("\t-n nof_prb [Default All]\n"); printf("\t-e extended cyclic prefix [Default Normal]\n"); + printf("\t-r nof_repetitions [Default %d]\n", nof_repetitions); } void parse_args(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "ne")) != -1) { + while ((opt = getopt(argc, argv, "ner")) != -1) { switch (opt) { case 'n': nof_prb = atoi(argv[optind]); @@ -52,6 +64,9 @@ void parse_args(int argc, char **argv) { case 'e': cp = SRSLTE_CP_EXT; break; + case 'r': + nof_repetitions = atoi(argv[optind]); + break; default: usage(argv[0]); exit(-1); @@ -61,6 +76,7 @@ void parse_args(int argc, char **argv) { int main(int argc, char **argv) { + struct timeval start, end; srslte_ofdm_t fft, ifft; cf_t *input, *outfft, *outifft; float mse; @@ -81,48 +97,65 @@ int main(int argc, char **argv) { printf("Running test for %d PRB, %d RE... ", n_prb, n_re);fflush(stdout); - input = malloc(sizeof(cf_t) * n_re); + input = srslte_vec_malloc(sizeof(cf_t) * n_re * 2); if (!input) { perror("malloc"); exit(-1); } - outfft = malloc(sizeof(cf_t) * SRSLTE_SLOT_LEN(srslte_symbol_sz(n_prb))); + outfft = srslte_vec_malloc(sizeof(cf_t) * n_re * 2); if (!outfft) { perror("malloc"); exit(-1); } - outifft = malloc(sizeof(cf_t) * n_re); + outifft = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SLOT_LEN(srslte_symbol_sz(n_prb)) * 2); if (!outifft) { perror("malloc"); exit(-1); } + bzero(outifft, sizeof(cf_t) * SRSLTE_SLOT_LEN(srslte_symbol_sz(n_prb)) * 2); - if (srslte_ofdm_rx_init(&fft, cp, n_prb)) { + if (srslte_ofdm_rx_init(&fft, cp, outifft, outfft, n_prb)) { fprintf(stderr, "Error initializing FFT\n"); exit(-1); } - srslte_dft_plan_set_norm(&fft.fft_plan, true); + srslte_ofdm_set_normalize(&fft, true); - if (srslte_ofdm_tx_init(&ifft, cp, n_prb)) { + if (srslte_ofdm_tx_init(&ifft, cp, input, outifft, n_prb)) { fprintf(stderr, "Error initializing iFFT\n"); exit(-1); } - srslte_dft_plan_set_norm(&ifft.fft_plan, true); + srslte_ofdm_set_normalize(&ifft, true); for (i=0;i 1.0f) printf("%04d. %+.1f%+.1fi Vs. %+.1f%+.1f %+.1f%+.1f (mse=%f)\n", i, __real__ input[i], __imag__ input[i], __real__ outifft[i], __imag__ outifft[i], __real__ outfft[i], __imag__ outfft[i], mse); } - printf("MSE=%f\n", mse); + /*for (i=0;i= 0.07) { printf("MSE too large\n"); diff --git a/lib/src/phy/enb/enb_dl.c b/lib/src/phy/enb/enb_dl.c index 2ba179399..54a63bc2a 100644 --- a/lib/src/phy/enb/enb_dl.c +++ b/lib/src/phy/enb/enb_dl.c @@ -41,7 +41,7 @@ #define SRSLTE_ENB_RF_AMP 0.1 -int srslte_enb_dl_init(srslte_enb_dl_t *q, uint32_t max_prb) +int srslte_enb_dl_init(srslte_enb_dl_t *q, cf_t *out_buffer[SRSLTE_MAX_PORTS], uint32_t max_prb) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -53,13 +53,26 @@ int srslte_enb_dl_init(srslte_enb_dl_t *q, uint32_t max_prb) q->cfi = 3; q->tx_amp = SRSLTE_ENB_RF_AMP; - - if (srslte_ofdm_tx_init(&q->ifft, SRSLTE_CP_NORM, max_prb)) { - fprintf(stderr, "Error initiating FFT\n"); - goto clean_exit; + + for (int i=0;isf_symbols[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t)); + if (!q->sf_symbols[i]) { + perror("malloc"); + goto clean_exit; + } + q->slot1_symbols[i] = &q->sf_symbols[i][SRSLTE_SLOT_LEN_RE(max_prb, SRSLTE_CP_NORM)]; } - srslte_ofdm_set_normalize(&q->ifft, true); + for (int i = 0; i < SRSLTE_MAX_PORTS; i++) { + if (srslte_ofdm_tx_init(&q->ifft[i], SRSLTE_CP_NORM, q->sf_symbols[i], out_buffer[i], max_prb)) { + fprintf(stderr, "Error initiating FFT (%d)\n", i); + goto clean_exit; + } + } + + for (int i = 0; i < q->cell.nof_ports; i++) { + srslte_ofdm_set_normalize(&q->ifft[i], true); + } if (srslte_pbch_init(&q->pbch)) { fprintf(stderr, "Error creating PBCH object\n"); @@ -89,15 +102,6 @@ int srslte_enb_dl_init(srslte_enb_dl_t *q, uint32_t max_prb) goto clean_exit; } - for (int i=0;isf_symbols[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t)); - if (!q->sf_symbols[i]) { - perror("malloc"); - goto clean_exit; - } - q->slot1_symbols[i] = &q->sf_symbols[i][SRSLTE_SLOT_LEN_RE(max_prb, SRSLTE_CP_NORM)]; - } - ret = SRSLTE_SUCCESS; } else { @@ -114,7 +118,9 @@ clean_exit: void srslte_enb_dl_free(srslte_enb_dl_t *q) { if (q) { - srslte_ofdm_tx_free(&q->ifft); + for (int i = 0; i < SRSLTE_MAX_PORTS; i++) { + srslte_ofdm_tx_free(&q->ifft[i]); + } srslte_regs_free(&q->regs); srslte_pbch_free(&q->pbch); srslte_pcfich_free(&q->pcfich); @@ -152,9 +158,11 @@ int srslte_enb_dl_set_cell(srslte_enb_dl_t *q, srslte_cell_t cell) fprintf(stderr, "Error resizing REGs\n"); return SRSLTE_ERROR; } - if (srslte_ofdm_rx_set_prb(&q->ifft, q->cell.cp, q->cell.nof_prb)) { - fprintf(stderr, "Error initiating FFT\n"); - return SRSLTE_ERROR; + for (int i = 0; i < q->cell.nof_ports; i++) { + if (srslte_ofdm_tx_set_prb(&q->ifft[i], q->cell.cp, q->cell.nof_prb)) { + fprintf(stderr, "Error re-planning iFFT (%d)\n", i); + return SRSLTE_ERROR; + } } if (srslte_pbch_set_cell(&q->pbch, q->cell)) { fprintf(stderr, "Error creating PBCH object\n"); @@ -264,14 +272,15 @@ void srslte_enb_dl_put_base(srslte_enb_dl_t *q, uint32_t tti) } -void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q, cf_t *signal_buffer) +void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q) { - - srslte_ofdm_tx_sf(&q->ifft, q->sf_symbols[0], signal_buffer); - // TODO: PAPR control float norm_factor = (float) sqrt(q->cell.nof_prb)/15; - srslte_vec_sc_prod_cfc(signal_buffer, q->tx_amp*norm_factor, signal_buffer, SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); + + for (int i = 0; i < q->cell.nof_ports; i++) { + srslte_ofdm_tx_sf(&q->ifft[i]); + srslte_vec_sc_prod_cfc(q->ifft[i].out_buffer, q->tx_amp*norm_factor, q->ifft[i].out_buffer, (uint32_t) SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); + } } int srslte_enb_dl_add_rnti(srslte_enb_dl_t *q, uint16_t rnti) diff --git a/lib/src/phy/enb/enb_ul.c b/lib/src/phy/enb/enb_ul.c index db05d44ea..f94eb0277 100644 --- a/lib/src/phy/enb/enb_ul.c +++ b/lib/src/phy/enb/enb_ul.c @@ -40,6 +40,7 @@ #define MAX_CANDIDATES 16 int srslte_enb_ul_init(srslte_enb_ul_t *q, + cf_t *in_buffer, uint32_t max_prb) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -55,8 +56,20 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q, perror("malloc"); goto clean_exit; } - - if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) { + + q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t)); + if (!q->sf_symbols) { + perror("malloc"); + goto clean_exit; + } + + q->ce = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t)); + if (!q->ce) { + perror("malloc"); + goto clean_exit; + } + + if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, in_buffer, q->sf_symbols, max_prb)) { fprintf(stderr, "Error initiating FFT\n"); goto clean_exit; } @@ -80,18 +93,6 @@ int srslte_enb_ul_init(srslte_enb_ul_t *q, goto clean_exit; } - q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t)); - if (!q->sf_symbols) { - perror("malloc"); - goto clean_exit; - } - - q->ce = srslte_vec_malloc(SRSLTE_SF_LEN_RE(max_prb, SRSLTE_CP_NORM) * sizeof(cf_t)); - if (!q->ce) { - perror("malloc"); - goto clean_exit; - } - ret = SRSLTE_SUCCESS; } else { @@ -254,7 +255,7 @@ int srslte_enb_ul_cfg_ue(srslte_enb_ul_t *q, uint16_t rnti, void srslte_enb_ul_fft(srslte_enb_ul_t *q, cf_t *signal_buffer) { - srslte_ofdm_rx_sf(&q->fft, signal_buffer, q->sf_symbols); + srslte_ofdm_rx_sf(&q->fft); } int get_pucch(srslte_enb_ul_t *q, uint16_t rnti, diff --git a/lib/src/phy/phch/test/pbch_file_test.c b/lib/src/phy/phch/test/pbch_file_test.c index 734640d55..2ca12e4c9 100644 --- a/lib/src/phy/phch/test/pbch_file_test.c +++ b/lib/src/phy/phch/test/pbch_file_test.c @@ -140,7 +140,7 @@ int base_init() { return -1; } - if (srslte_ofdm_init_(&fft, cell.cp, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { + if (srslte_ofdm_init_(&fft, cell.cp, input_buffer, fft_buffer, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { fprintf(stderr, "Error initializing FFT\n"); return -1; } @@ -203,7 +203,7 @@ int main(int argc, char **argv) { if (nread > 0) { // process 1st subframe only - srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer); + srslte_ofdm_rx_sf(&fft); /* Get channel estimates for each port */ srslte_chest_dl_estimate(&chest, fft_buffer, ce, 0); diff --git a/lib/src/phy/phch/test/pcfich_file_test.c b/lib/src/phy/phch/test/pcfich_file_test.c index dfb8d72e3..e92d6c7ba 100644 --- a/lib/src/phy/phch/test/pcfich_file_test.c +++ b/lib/src/phy/phch/test/pcfich_file_test.c @@ -120,15 +120,15 @@ int base_init() { fmatlab = NULL; } - flen = SRSLTE_SF_LEN(srslte_symbol_sz(cell.nof_prb)); + flen = SRSLTE_SF_LEN(srslte_symbol_sz_power2(cell.nof_prb)); - input_buffer = malloc(flen * sizeof(cf_t)); + input_buffer = srslte_vec_malloc(flen * sizeof(cf_t)); if (!input_buffer) { perror("malloc"); exit(-1); } - fft_buffer = malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t)); + fft_buffer = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t)); if (!fft_buffer) { perror("malloc"); return -1; @@ -151,7 +151,7 @@ int base_init() { return -1; } - if (srslte_ofdm_init_(&fft, cell.cp, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { + if (srslte_ofdm_init_(&fft, cell.cp, input_buffer, fft_buffer, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { fprintf(stderr, "Error initializing FFT\n"); return -1; } @@ -215,7 +215,7 @@ int main(int argc, char **argv) { n = srslte_filesource_read(&fsrc, input_buffer, flen); - srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer); + srslte_ofdm_rx_sf(&fft); if (fmatlab) { fprintf(fmatlab, "infft="); diff --git a/lib/src/phy/phch/test/pdcch_file_test.c b/lib/src/phy/phch/test/pdcch_file_test.c index d4ceed4b6..5482d9f98 100644 --- a/lib/src/phy/phch/test/pdcch_file_test.c +++ b/lib/src/phy/phch/test/pdcch_file_test.c @@ -126,7 +126,7 @@ int base_init() { exit(-1); } - flen = 2 * (SRSLTE_SLOT_LEN(srslte_symbol_sz(cell.nof_prb))); + flen = 2 * (SRSLTE_SLOT_LEN(srslte_symbol_sz_power2(cell.nof_prb))); input_buffer = malloc(flen * sizeof(cf_t)); if (!input_buffer) { @@ -157,7 +157,7 @@ int base_init() { return -1; } - if (srslte_ofdm_init_(&fft, cell.cp, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { + if (srslte_ofdm_init_(&fft, cell.cp, input_buffer, fft_buffer, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { fprintf(stderr, "Error initializing FFT\n"); return -1; } @@ -231,7 +231,7 @@ int main(int argc, char **argv) { INFO("Reading %d samples sub-frame %d\n", flen, frame_cnt); - srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer); + srslte_ofdm_rx_sf(&fft); /* Get channel estimates for each port */ srslte_chest_dl_estimate(&chest, fft_buffer, ce, frame_cnt %10); diff --git a/lib/src/phy/phch/test/pdsch_pdcch_file_test.c b/lib/src/phy/phch/test/pdsch_pdcch_file_test.c index 90c0e1c17..0faf7eca1 100644 --- a/lib/src/phy/phch/test/pdsch_pdcch_file_test.c +++ b/lib/src/phy/phch/test/pdsch_pdcch_file_test.c @@ -129,7 +129,7 @@ int base_init() { exit(-1); } - flen = 2 * (SRSLTE_SLOT_LEN(srslte_symbol_sz(cell.nof_prb))); + flen = SRSLTE_SF_LEN(srslte_symbol_sz_power2(cell.nof_prb)); input_buffer[0] = malloc(flen * sizeof(cf_t)); if (!input_buffer[0]) { @@ -137,7 +137,7 @@ int base_init() { exit(-1); } - if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) { + if (srslte_ue_dl_init(&ue_dl, input_buffer, cell.nof_prb, 1)) { fprintf(stderr, "Error initializing UE DL\n"); return -1; } diff --git a/lib/src/phy/phch/test/phich_file_test.c b/lib/src/phy/phch/test/phich_file_test.c index d7078f933..65f7ce9c0 100644 --- a/lib/src/phy/phch/test/phich_file_test.c +++ b/lib/src/phy/phch/test/phich_file_test.c @@ -144,7 +144,7 @@ int base_init() { fmatlab = NULL; } - flen = SRSLTE_SF_LEN(srslte_symbol_sz(cell.nof_prb)); + flen = SRSLTE_SF_LEN(srslte_symbol_sz_power2(cell.nof_prb)); input_buffer = malloc(flen * sizeof(cf_t)); if (!input_buffer) { @@ -175,7 +175,7 @@ int base_init() { return -1; } - if (srslte_ofdm_init_(&fft, cell.cp, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { + if (srslte_ofdm_init_(&fft, cell.cp, input_buffer, fft_buffer, srslte_symbol_sz_power2(cell.nof_prb), cell.nof_prb, SRSLTE_DFT_FORWARD)) { fprintf(stderr, "Error initializing FFT\n"); return -1; } @@ -242,7 +242,7 @@ int main(int argc, char **argv) { n = srslte_filesource_read(&fsrc, input_buffer, flen); - srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer); + srslte_ofdm_rx_sf(&fft); if (fmatlab) { fprintf(fmatlab, "infft="); diff --git a/lib/src/phy/phch/test/pmch_file_test.c b/lib/src/phy/phch/test/pmch_file_test.c index ac66072fa..6586b2ee9 100644 --- a/lib/src/phy/phch/test/pmch_file_test.c +++ b/lib/src/phy/phch/test/pmch_file_test.c @@ -140,7 +140,7 @@ int base_init() { exit(-1); } - if (srslte_ue_dl_init(&ue_dl, cell.nof_prb, 1)) { + if (srslte_ue_dl_init(&ue_dl, input_buffer, cell.nof_prb, 1)) { fprintf(stderr, "Error initializing UE DL\n"); return -1; } diff --git a/lib/src/phy/phch/test/pmch_test.c b/lib/src/phy/phch/test/pmch_test.c index a187ca2bb..a9c29ef64 100644 --- a/lib/src/phy/phch/test/pmch_test.c +++ b/lib/src/phy/phch/test/pmch_test.c @@ -139,7 +139,7 @@ cf_t *tx_slot_symbols[SRSLTE_MAX_PORTS]; cf_t *rx_slot_symbols[SRSLTE_MAX_PORTS]; srslte_pmch_t pmch_tx, pmch_rx; srslte_pdsch_cfg_t pmch_cfg; -srslte_ofdm_t ifft_mbsfn, fft_mbsfn; +srslte_ofdm_t ifft_mbsfn[SRSLTE_MAX_PORTS], fft_mbsfn[SRSLTE_MAX_PORTS]; int main(int argc, char **argv) { uint32_t i, j, k; @@ -169,10 +169,10 @@ int main(int argc, char **argv) { grant.tb_en[1] = false; grant.nof_tb = 1; grant.mcs[0].idx = mcs_idx; - + grant.nof_prb = cell.nof_prb; grant.sf_type = SRSLTE_SF_MBSFN; - + srslte_dl_fill_ra_mcs(&grant.mcs[0], cell.nof_prb); grant.Qm[0] = srslte_mod_bits_x_symbol(grant.mcs[0].mod); for(int i = 0; i < 2; i++){ @@ -181,41 +181,6 @@ int main(int argc, char **argv) { } } - - -#ifdef DO_OFDM - - if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn, SRSLTE_CP_EXT, cell.nof_prb)) { - fprintf(stderr, "Error creating iFFT object\n"); - exit(-1); - } - if (srslte_ofdm_rx_init_mbsfn(&fft_mbsfn, SRSLTE_CP_EXT, cell.nof_prb)) { - fprintf(stderr, "Error creating iFFT object\n"); - exit(-1); - } - - srslte_ofdm_set_non_mbsfn_region(&ifft_mbsfn, non_mbsfn_region); - srslte_ofdm_set_non_mbsfn_region(&fft_mbsfn, non_mbsfn_region); - srslte_ofdm_set_normalize(&ifft_mbsfn, true); - srslte_ofdm_set_normalize(&fft_mbsfn, true); - - - for (i = 0; i < cell.nof_ports; i++) { - tx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); - } - - for (i = 0; i < nof_rx_antennas; i++) { - rx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); - } -#endif /* DO_OFDM */ - - /* Configure PDSCH */ - - if (srslte_pmch_cfg(&pmch_cfg, cell, &grant, cfi, subframe)) { - fprintf(stderr, "Error configuring PMCH\n"); - exit(-1); - } - /* init memory */ for (i=0;isample_offset = 0; q->nof_rx_antennas = nof_rx_antennas; - if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) { - fprintf(stderr, "Error initiating FFT\n"); - goto clean_exit; + for (int j = 0; j < SRSLTE_MAX_PORTS; j++) { + q->sf_symbols_m[j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t)); + if (!q->sf_symbols_m[j]) { + perror("malloc"); + goto clean_exit; + } + for (uint32_t i=0;ice_m[i][j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t)); + if (!q->ce_m[i][j]) { + perror("malloc"); + goto clean_exit; + } + bzero(q->ce_m[i][j], MAX_SFLEN_RE * sizeof(cf_t)); + } } - - if (srslte_ofdm_rx_init_mbsfn(&q->fft_mbsfn, SRSLTE_CP_EXT, max_prb)) { + + q->sf_symbols = q->sf_symbols_m[0]; + for (int i=0;ice[i] = q->ce_m[i][0]; + } + + for (int i = 0; i < nof_rx_antennas; i++) { + if (srslte_ofdm_rx_init(&q->fft[i], SRSLTE_CP_NORM, in_buffer[i], q->sf_symbols_m[i], max_prb)) { + fprintf(stderr, "Error initiating FFT\n"); + goto clean_exit; + } + } + + if (srslte_ofdm_rx_init_mbsfn(&q->fft_mbsfn, SRSLTE_CP_EXT, in_buffer[0], q->sf_symbols_m[0], max_prb)) { fprintf(stderr, "Error initiating FFT for MBSFN subframes \n"); goto clean_exit; } @@ -127,28 +151,7 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q, fprintf(stderr, "Error initiating SFO correct\n"); goto clean_exit; } - srslte_cfo_set_tol(&q->sfo_correct, 1e-5f/q->fft.symbol_sz); - - for (int j = 0; j < SRSLTE_MAX_PORTS; j++) { - q->sf_symbols_m[j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t)); - if (!q->sf_symbols_m[j]) { - perror("malloc"); - goto clean_exit; - } - for (uint32_t i=0;ice_m[i][j] = srslte_vec_malloc(MAX_SFLEN_RE * sizeof(cf_t)); - if (!q->ce_m[i][j]) { - perror("malloc"); - goto clean_exit; - } - bzero(q->ce_m[i][j], MAX_SFLEN_RE * sizeof(cf_t)); - } - } - - q->sf_symbols = q->sf_symbols_m[0]; - for (int i=0;ice[i] = q->ce_m[i][0]; - } + srslte_cfo_set_tol(&q->sfo_correct, 1e-5f/q->fft[0].symbol_sz); ret = SRSLTE_SUCCESS; } else { @@ -164,7 +167,9 @@ clean_exit: void srslte_ue_dl_free(srslte_ue_dl_t *q) { if (q) { - srslte_ofdm_rx_free(&q->fft); + for (int port = 0; port < SRSLTE_MAX_PORTS; port++) { + srslte_ofdm_rx_free(&q->fft[port]); + } srslte_ofdm_rx_free(&q->fft_mbsfn); srslte_chest_dl_free(&q->chest); srslte_regs_free(&q->regs); @@ -219,10 +224,12 @@ int srslte_ue_dl_set_cell(srslte_ue_dl_t *q, srslte_cell_t cell) fprintf(stderr, "Error resizing SFO correct\n"); return SRSLTE_ERROR; } - srslte_cfo_set_tol(&q->sfo_correct, 1e-5/q->fft.symbol_sz); - if (srslte_ofdm_rx_set_prb(&q->fft, q->cell.cp, q->cell.nof_prb)) { - fprintf(stderr, "Error resizing FFT\n"); - return SRSLTE_ERROR; + srslte_cfo_set_tol(&q->sfo_correct, 1e-5f/q->fft[0].symbol_sz); + for (int port = 0; port < q->nof_rx_antennas; port++) { + if (srslte_ofdm_rx_set_prb(&q->fft[port], q->cell.cp, q->cell.nof_prb)) { + fprintf(stderr, "Error resizing FFT\n"); + return SRSLTE_ERROR; + } } if (srslte_chest_dl_set_cell(&q->chest, q->cell)) { fprintf(stderr, "Error resizing channel estimator\n"); @@ -339,9 +346,9 @@ int srslte_ue_dl_decode_fft_estimate_mbsfn(srslte_ue_dl_t *q, cf_t *input[SRSLTE /* Run FFT for all subframe data */ for (int j=0;jnof_rx_antennas;j++) { if(sf_type == SRSLTE_SF_MBSFN ) { - srslte_ofdm_rx_sf(&q->fft_mbsfn, input[j], q->sf_symbols_m[j]); + srslte_ofdm_rx_sf(&q->fft_mbsfn); }else{ - srslte_ofdm_rx_sf(&q->fft, input[j], q->sf_symbols_m[j]); + srslte_ofdm_rx_sf(&q->fft[j]); } /* Correct SFO multiplying by complex exponential in the time domain */ @@ -351,7 +358,7 @@ int srslte_ue_dl_decode_fft_estimate_mbsfn(srslte_ue_dl_t *q, cf_t *input[SRSLTE srslte_cfo_correct(&q->sfo_correct, &q->sf_symbols_m[j][i*q->cell.nof_prb*SRSLTE_NRE], &q->sf_symbols_m[j][i*q->cell.nof_prb*SRSLTE_NRE], - q->sample_offset / q->fft.symbol_sz); + q->sample_offset / q->fft[j].symbol_sz); } } } diff --git a/lib/src/phy/ue/ue_mib.c b/lib/src/phy/ue/ue_mib.c index 46a470ab8..c003a2ba3 100644 --- a/lib/src/phy/ue/ue_mib.c +++ b/lib/src/phy/ue/ue_mib.c @@ -35,7 +35,8 @@ #include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/vector.h" -int srslte_ue_mib_init(srslte_ue_mib_t * q, +int srslte_ue_mib_init(srslte_ue_mib_t * q, + cf_t *in_buffer[SRSLTE_MAX_PORTS], uint32_t max_prb) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -65,7 +66,7 @@ int srslte_ue_mib_init(srslte_ue_mib_t * q, } } - if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) { + if (srslte_ofdm_rx_init(&q->fft, SRSLTE_CP_NORM, in_buffer[0], q->sf_symbols, max_prb)) { fprintf(stderr, "Error initializing FFT\n"); goto clean_exit; } @@ -143,14 +144,14 @@ void srslte_ue_mib_reset(srslte_ue_mib_t * q) srslte_pbch_decode_reset(&q->pbch); } -int srslte_ue_mib_decode(srslte_ue_mib_t * q, cf_t *input, +int srslte_ue_mib_decode(srslte_ue_mib_t * q, uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN], uint32_t *nof_tx_ports, int *sfn_offset) { int ret = SRSLTE_SUCCESS; cf_t *ce_slot1[SRSLTE_MAX_PORTS]; /* Run FFT for the slot symbols */ - srslte_ofdm_rx_sf(&q->fft, input, q->sf_symbols); + srslte_ofdm_rx_sf(&q->fft); /* Get channel estimates of sf idx #0 for each port */ ret = srslte_chest_dl_estimate(&q->chest, q->sf_symbols, q->ce, 0); @@ -198,7 +199,7 @@ int srslte_ue_mib_sync_init_multi(srslte_ue_mib_sync_t *q, } q->nof_rx_antennas = nof_rx_antennas; - if (srslte_ue_mib_init(&q->ue_mib, SRSLTE_UE_MIB_NOF_PRB)) { + if (srslte_ue_mib_init(&q->ue_mib, q->sf_buffer, SRSLTE_UE_MIB_NOF_PRB)) { fprintf(stderr, "Error initiating ue_mib\n"); return SRSLTE_ERROR; } @@ -274,7 +275,7 @@ int srslte_ue_mib_sync_decode(srslte_ue_mib_sync_t * q, return -1; } else if (srslte_ue_sync_get_sfidx(&q->ue_sync) == 0) { if (ret == 1) { - mib_ret = srslte_ue_mib_decode(&q->ue_mib, q->sf_buffer[0], bch_payload, nof_tx_ports, sfn_offset); + mib_ret = srslte_ue_mib_decode(&q->ue_mib, bch_payload, nof_tx_ports, sfn_offset); } else { DEBUG("Resetting PBCH decoder after %d frames\n", q->ue_mib.frame_cnt); srslte_ue_mib_reset(&q->ue_mib); diff --git a/lib/src/phy/ue/ue_ul.c b/lib/src/phy/ue/ue_ul.c index 37dfecd93..853937f7c 100644 --- a/lib/src/phy/ue/ue_ul.c +++ b/lib/src/phy/ue/ue_ul.c @@ -41,6 +41,7 @@ #define DEFAULT_CFO_TOL 50.0 // Hz int srslte_ue_ul_init(srslte_ue_ul_t *q, + cf_t *out_buffer, uint32_t max_prb) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -50,8 +51,14 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q, ret = SRSLTE_ERROR; bzero(q, sizeof(srslte_ue_ul_t)); - - if (srslte_ofdm_tx_init(&q->fft, SRSLTE_CP_NORM, max_prb)) { + + q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_PRB(max_prb) * sizeof(cf_t)); + if (!q->sf_symbols) { + perror("malloc"); + goto clean_exit; + } + + if (srslte_ofdm_tx_init(&q->fft, SRSLTE_CP_NORM, q->sf_symbols, out_buffer, max_prb)) { fprintf(stderr, "Error initiating FFT\n"); goto clean_exit; } @@ -83,11 +90,6 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q, fprintf(stderr, "Error initiating srslte_refsignal_ul\n"); goto clean_exit; } - q->sf_symbols = srslte_vec_malloc(SRSLTE_SF_LEN_PRB(max_prb) * sizeof(cf_t)); - if (!q->sf_symbols) { - perror("malloc"); - goto clean_exit; - } q->refsignal = srslte_vec_malloc(2 * SRSLTE_NRE * max_prb * sizeof(cf_t)); if (!q->refsignal) { perror("malloc"); @@ -347,7 +349,7 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data, q->last_pucch_format = format; - srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal); + srslte_ofdm_tx_sf(&q->fft); if (q->cfo_en) { srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb)); @@ -417,7 +419,7 @@ int srslte_ue_ul_srs_encode(srslte_ue_ul_t *q, uint32_t tti, cf_t *output_signal } } - srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal); + srslte_ofdm_tx_sf(&q->fft); if (q->cfo_en) { srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb)); @@ -486,7 +488,7 @@ int srslte_ue_ul_pusch_encode_rnti_softbuffer(srslte_ue_ul_t *q, } } - srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal); + srslte_ofdm_tx_sf(&q->fft); if (q->cfo_en) { srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb)); diff --git a/srsenb/hdr/phy/phch_worker.h b/srsenb/hdr/phy/phch_worker.h index 906e8b9d0..48878a879 100644 --- a/srsenb/hdr/phy/phch_worker.h +++ b/srsenb/hdr/phy/phch_worker.h @@ -88,7 +88,7 @@ private: bool running; cf_t *signal_buffer_rx; - cf_t *signal_buffer_tx; + cf_t *signal_buffer_tx[SRSLTE_MAX_PORTS]; uint32_t tti_rx, tti_tx, tti_sched_ul, sf_rx, sf_tx, sf_sched_ul, tx_mutex_cnt; srslte_enb_dl_t enb_dl; diff --git a/srsenb/src/phy/phch_worker.cc b/srsenb/src/phy/phch_worker.cc index 3a1fb8ca4..8a6173347 100644 --- a/srsenb/src/phy/phch_worker.cc +++ b/srsenb/src/phy/phch_worker.cc @@ -93,12 +93,13 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_) fprintf(stderr, "Error allocating memory\n"); return; } - signal_buffer_tx = (cf_t*) srslte_vec_malloc(2*SRSLTE_SF_LEN_PRB(phy->cell.nof_prb)*sizeof(cf_t)); - if (!signal_buffer_tx) { + bzero(&signal_buffer_tx, sizeof(cf_t *) * SRSLTE_MAX_PORTS); + signal_buffer_tx[0] = (cf_t*) srslte_vec_malloc(2*SRSLTE_SF_LEN_PRB(phy->cell.nof_prb)*sizeof(cf_t)); + if (!signal_buffer_tx[0]) { fprintf(stderr, "Error allocating memory\n"); return; } - if (srslte_enb_dl_init(&enb_dl, phy->cell.nof_prb)) { + if (srslte_enb_dl_init(&enb_dl, signal_buffer_tx, phy->cell.nof_prb)) { fprintf(stderr, "Error initiating ENB DL\n"); return; } @@ -106,7 +107,7 @@ void phch_worker::init(phch_common* phy_, srslte::log *log_h_) fprintf(stderr, "Error initiating ENB DL\n"); return; } - if (srslte_enb_ul_init(&enb_ul, phy->cell.nof_prb)) { + if (srslte_enb_ul_init(&enb_ul, signal_buffer_rx, phy->cell.nof_prb)) { fprintf(stderr, "Error initiating ENB UL\n"); return; } @@ -156,8 +157,10 @@ void phch_worker::stop() if (signal_buffer_rx) { free(signal_buffer_rx); } - if (signal_buffer_tx) { - free(signal_buffer_tx); + for (int i = 0; i < SRSLTE_MAX_PORTS; i++) { + if (signal_buffer_tx[i]) { + free(signal_buffer_tx[i]); + } } pthread_mutex_unlock(&mutex); pthread_mutex_destroy(&mutex); @@ -336,9 +339,9 @@ void phch_worker::work_imp() } // Generate signal and transmit - srslte_enb_dl_gen_signal(&enb_dl, signal_buffer_tx); + srslte_enb_dl_gen_signal(&enb_dl); Debug("Sending to radio\n"); - phy->worker_end(tx_mutex_cnt, signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time); + phy->worker_end(tx_mutex_cnt, signal_buffer_tx[0], SRSLTE_SF_LEN_PRB(phy->cell.nof_prb), tx_time); #ifdef DEBUG_WRITE_FILE fwrite(signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb)*sizeof(cf_t), 1, f); diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index c14141257..041418b5a 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -101,13 +101,13 @@ void phch_recv:: init(srslte::radio_multi *_radio_handler, mac_interface_phy *_ if (do_agc) { srslte_ue_sync_start_agc(&cs.ue_sync, callback_set_rx_gain, last_gain); } - - if (srslte_ue_dl_init(&ue_dl_measure, SRSLTE_MAX_PRB, nof_rx_antennas)) { + + if (srslte_ue_dl_init(&ue_dl_measure, sf_buffer, SRSLTE_MAX_PRB, nof_rx_antennas)) { Error("SYNC: Initiating ue_dl_measure\n"); return; } - if (srslte_ue_mib_init(&ue_mib, SRSLTE_MAX_PRB)) { + if (srslte_ue_mib_init(&ue_mib, sf_buffer, SRSLTE_MAX_PRB)) { Error("SYNC: Initiating UE MIB decoder\n"); return; } @@ -374,7 +374,7 @@ int phch_recv::cell_sync_sfn(void) { int sfn_offset = 0; Info("SYNC: Trying to decode MIB... SNR=%.1f dB\n", 10*log10(srslte_chest_dl_get_snr(&ue_mib.chest))); - int n = srslte_ue_mib_decode(&ue_mib, sf_buffer[0], bch_payload, NULL, &sfn_offset); + int n = srslte_ue_mib_decode(&ue_mib, bch_payload, NULL, &sfn_offset); if (n < 0) { Error("SYNC: Error decoding MIB while synchronising SFN"); return -1; diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index c0fec2ba2..ee1011aea 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -118,12 +118,12 @@ bool phch_worker::init(uint32_t max_prb, srslte::log *log_h) } } - if (srslte_ue_dl_init(&ue_dl, max_prb, phy->args->nof_rx_ant)) { + if (srslte_ue_dl_init(&ue_dl, signal_buffer, max_prb, phy->args->nof_rx_ant)) { Error("Initiating UE DL\n"); return false; } - if (srslte_ue_ul_init(&ue_ul, max_prb)) { + if (srslte_ue_ul_init(&ue_ul, signal_buffer[0], max_prb)) { Error("Initiating UE UL\n"); return false; } From b0157cb4f870b330c6b2daa737c9335a43aaa17e Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 20 Oct 2017 10:40:59 -0400 Subject: [PATCH 28/49] Removed error when can't save fft wisdom (prints in mkl) --- lib/src/phy/dft/dft_fftw.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/src/phy/dft/dft_fftw.c b/lib/src/phy/dft/dft_fftw.c index a06dd397f..9d6898117 100644 --- a/lib/src/phy/dft/dft_fftw.c +++ b/lib/src/phy/dft/dft_fftw.c @@ -56,9 +56,7 @@ void srslte_dft_load() { void srslte_dft_exit() { #ifdef FFTW_WISDOM_FILE - if (!fftwf_export_wisdom_to_filename(FFTW_WISDOM_FILE)) { - fprintf(stderr, "Error saving FFTW wisdom to file %s\n", FFTW_WISDOM_FILE); - } + fftwf_export_wisdom_to_filename(FFTW_WISDOM_FILE); #endif } From 7e3fbbc63918f049ad5eca2560d5ff4db19920bc Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Fri, 20 Oct 2017 16:18:26 +0100 Subject: [PATCH 29/49] Adding ASN support for RRC measurement report messages --- lib/include/srslte/asn1/liblte_rrc.h | 97 ++++++++++- lib/src/asn1/liblte_rrc.cc | 249 ++++++++++++++++++++++++++- lib/test/CMakeLists.txt | 1 + lib/test/asn1/CMakeLists.txt | 23 +++ lib/test/asn1/rrc_meas_test.cc | 91 ++++++++++ 5 files changed, 451 insertions(+), 10 deletions(-) create mode 100644 lib/test/asn1/CMakeLists.txt create mode 100644 lib/test/asn1/rrc_meas_test.cc diff --git a/lib/include/srslte/asn1/liblte_rrc.h b/lib/include/srslte/asn1/liblte_rrc.h index 5a8515dbb..c5c3b60e2 100644 --- a/lib/include/srslte/asn1/liblte_rrc.h +++ b/lib/include/srslte/asn1/liblte_rrc.h @@ -6435,11 +6435,102 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_mobility_from_eutra_command_msg(LIBLTE_BIT_M Document Reference: 36.331 v10.0.0 Section 6.2.2 *********************************************************************/ -// Defines -// Enums +typedef struct{ + LIBLTE_RRC_CELL_GLOBAL_ID_EUTRA_STRUCT cell_global_id; + uint16 tracking_area_code; + LIBLTE_RRC_PLMN_IDENTITY_STRUCT plmn_identity_list[5]; + uint32 n_plmn_identity_list; + bool have_plmn_identity_list; +}LIBLTE_RRC_CGI_INFO_STRUCT; +LIBLTE_ERROR_ENUM liblte_rrc_pack_cgi_info_ie(LIBLTE_RRC_CGI_INFO_STRUCT *cgi_info, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_cgi_info_ie(uint8 **ie_ptr, + LIBLTE_RRC_CGI_INFO_STRUCT *cgi_info); + +typedef struct{ + uint8 rsrp_result; + bool have_rsrp; + uint8 rsrq_result; + bool have_rsrq; +}LIBLTE_RRC_MEAS_RESULT_STRUCT; +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_result_ie(LIBLTE_RRC_MEAS_RESULT_STRUCT *meas_result, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_result_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_RESULT_STRUCT *meas_result); + +typedef struct{ + uint16 phys_cell_id; + LIBLTE_RRC_CGI_INFO_STRUCT cgi_info; + bool have_cgi_info; + LIBLTE_RRC_MEAS_RESULT_STRUCT meas_result; +}LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT; +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_result_eutra_ie(LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT *meas_result_eutra, + uint8 **ie_ptr); +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_result_eutra_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT *meas_result_eutra); + +typedef struct{ + //FIXME +}LIBLTE_RRC_MEAS_RESULT_UTRA_STRUCT; +typedef struct{ + //FIXME +}LIBLTE_RRC_MEAS_RESULT_GERAN_STRUCT; +typedef struct{ + //FIXME +}LIBLTE_RRC_MEAS_RESULT_CDMA2000_STRUCT; + + + +typedef struct{ + LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT result_eutra_list[8]; + uint8 n_result; +}LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA_STRUCT; + +typedef struct{ + LIBLTE_RRC_MEAS_RESULT_UTRA_STRUCT result_utra_list[8]; + uint8 n_result; +}LIBLTE_RRC_MEAS_RESULT_LIST_UTRA_STRUCT; + +typedef struct{ + LIBLTE_RRC_MEAS_RESULT_GERAN_STRUCT result_geran_list[8]; + uint8 n_result; +}LIBLTE_RRC_MEAS_RESULT_LIST_GERAN_STRUCT; + + +typedef struct{ + bool pre_registration_status_HRPD; + LIBLTE_RRC_MEAS_RESULT_CDMA2000_STRUCT cdma2000[8]; +}LIBLTE_RRC_MEAS_RESULTS_CDMA2000_STRUCT; + +typedef enum{ + LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA = 0, + LIBLTE_RRC_MEAS_RESULT_LIST_UTRA, + LIBLTE_RRC_MEAS_RESULT_LIST_GERAN, + LIBLTE_RRC_MEAS_RESULTS_CDMA2000, + LIBLTE_RRC_MEAS_RESULT_N_ITEMS, +}LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_ENUM; +static const char liblte_rrc_meas_reult_neigh_cells_text[LIBLTE_RRC_MEAS_RESULT_N_ITEMS][32] = { "measResultListEUTRA", "measResultListUTRA", "measResultListGERAN", "measResultsCDMA2000"}; + + +typedef union{ + LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA_STRUCT eutra; + LIBLTE_RRC_MEAS_RESULT_LIST_UTRA_STRUCT utra; + LIBLTE_RRC_MEAS_RESULT_LIST_GERAN_STRUCT geran; + LIBLTE_RRC_MEAS_RESULTS_CDMA2000_STRUCT cdma2000; +}LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_UNION; + +//TODO: pack/unpack for the result lists + + // Structs typedef struct{ - // FIXME + uint8 meas_id; + uint8 pcell_rsrp_result; + uint8 pcell_rsrq_result; + + LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_UNION meas_result_neigh_cells; + LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_ENUM meas_result_neigh_cells_choice; + bool have_meas_result_neigh_cells; }LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT; // Functions LIBLTE_ERROR_ENUM liblte_rrc_pack_measurement_report_msg(LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *meas_report, diff --git a/lib/src/asn1/liblte_rrc.cc b/lib/src/asn1/liblte_rrc.cc index e4621994e..c53399384 100644 --- a/lib/src/asn1/liblte_rrc.cc +++ b/lib/src/asn1/liblte_rrc.cc @@ -4764,6 +4764,9 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_plmn_identity_ie(LIBLTE_RRC_PLMN_IDENTITY_STRU if(plmn_id != NULL && ie_ptr != NULL) { + if(0xFFFF == plmn_id->mcc) { + mcc_opt = false; + } liblte_value_2_bits(mcc_opt, ie_ptr, 1); if(true == mcc_opt) @@ -12754,7 +12757,241 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_paging_msg(LIBLTE_BIT_MSG_STRUCT *msg, Document Reference: 36.331 v10.0.0 Section 6.2.2 *********************************************************************/ -// FIXME +LIBLTE_ERROR_ENUM liblte_rrc_pack_cgi_info_ie(LIBLTE_RRC_CGI_INFO_STRUCT *cgi_info, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(cgi_info != NULL && + ie_ptr != NULL) + { + liblte_value_2_bits(cgi_info->have_plmn_identity_list, ie_ptr, 1); + liblte_rrc_pack_cell_global_id_eutra_ie(&cgi_info->cell_global_id, ie_ptr); + liblte_rrc_pack_tracking_area_code_ie(cgi_info->tracking_area_code, ie_ptr); + if(cgi_info->have_plmn_identity_list) { + liblte_value_2_bits(cgi_info->n_plmn_identity_list-1, ie_ptr, 3); + for(uint32 i=0; in_plmn_identity_list; i++) { + liblte_rrc_pack_plmn_identity_ie(&cgi_info->plmn_identity_list[i], ie_ptr); + } + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_cgi_info_ie(uint8 **ie_ptr, + LIBLTE_RRC_CGI_INFO_STRUCT *cgi_info) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + cgi_info != NULL) + { + cgi_info->have_plmn_identity_list = (bool)liblte_bits_2_value(ie_ptr, 1); + liblte_rrc_unpack_cell_global_id_eutra_ie(ie_ptr, &cgi_info->cell_global_id); + liblte_rrc_unpack_tracking_area_code_ie(ie_ptr, &cgi_info->tracking_area_code); + if(cgi_info->have_plmn_identity_list) { + cgi_info->n_plmn_identity_list = liblte_bits_2_value(ie_ptr, 3) + 1; + for(uint32 i=0; in_plmn_identity_list; i++) { + liblte_rrc_unpack_plmn_identity_ie(ie_ptr, &cgi_info->plmn_identity_list[i]); + } + } + err = LIBLTE_SUCCESS; + } + + return(err); +} + +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_result_ie(LIBLTE_RRC_MEAS_RESULT_STRUCT *meas_result, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(meas_result != NULL && + ie_ptr != NULL) + { + //ext + liblte_value_2_bits(0, ie_ptr, 1); + + //options + liblte_value_2_bits(meas_result->have_rsrp, ie_ptr, 1); + liblte_value_2_bits(meas_result->have_rsrq, ie_ptr, 1); + + if(meas_result->have_rsrp) { + liblte_rrc_pack_rsrp_range_ie(meas_result->rsrp_result, ie_ptr); + } + if(meas_result->have_rsrq) { + liblte_rrc_pack_rsrq_range_ie(meas_result->rsrq_result, ie_ptr); + } + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_result_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_RESULT_STRUCT *meas_result) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + meas_result != NULL) + { + //ext + bool ext = liblte_bits_2_value(ie_ptr, 1); + + //options + meas_result->have_rsrp = liblte_bits_2_value(ie_ptr, 1); + meas_result->have_rsrq = liblte_bits_2_value(ie_ptr, 1); + + if(meas_result->have_rsrp) { + liblte_rrc_unpack_rsrp_range_ie(ie_ptr, &meas_result->rsrp_result); + } + if(meas_result->have_rsrq) { + liblte_rrc_unpack_rsrq_range_ie(ie_ptr, &meas_result->rsrq_result); + } + + //skip extensions + liblte_rrc_consume_noncrit_extension(ext, __func__, ie_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +LIBLTE_ERROR_ENUM liblte_rrc_pack_meas_result_eutra_ie(LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT *meas_result_eutra, + uint8 **ie_ptr) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(meas_result_eutra != NULL && + ie_ptr != NULL) + { + liblte_value_2_bits(meas_result_eutra->have_cgi_info, ie_ptr, 1); + liblte_rrc_pack_phys_cell_id_ie(meas_result_eutra->phys_cell_id, ie_ptr); + if(meas_result_eutra->have_cgi_info) { + liblte_rrc_pack_cgi_info_ie(&meas_result_eutra->cgi_info, ie_ptr); + } + liblte_rrc_pack_meas_result_ie(&meas_result_eutra->meas_result, ie_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_meas_result_eutra_ie(uint8 **ie_ptr, + LIBLTE_RRC_MEAS_RESULT_EUTRA_STRUCT *meas_result_eutra) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + + if(ie_ptr != NULL && + meas_result_eutra != NULL) + { + meas_result_eutra->have_cgi_info = liblte_bits_2_value(ie_ptr, 1); + liblte_rrc_unpack_phys_cell_id_ie(ie_ptr, &meas_result_eutra->phys_cell_id); + if(meas_result_eutra->have_cgi_info) { + liblte_rrc_unpack_cgi_info_ie(ie_ptr, &meas_result_eutra->cgi_info); + } + liblte_rrc_unpack_meas_result_ie(ie_ptr, &meas_result_eutra->meas_result); + + err = LIBLTE_SUCCESS; + } + + return(err); +} + +LIBLTE_ERROR_ENUM liblte_rrc_pack_measurement_report_msg(LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *meas_report, + LIBLTE_BIT_MSG_STRUCT *msg) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(meas_report != NULL && + msg != NULL) + { + //MeasurementReport + liblte_value_2_bits(0, &msg_ptr, 1); //critical extensions + liblte_value_2_bits(0, &msg_ptr, 3); //c1 + + //MeasurementReport-r8-IEs + liblte_value_2_bits(0, &msg_ptr, 1); //non-critical extensions + + //MeasResults + liblte_value_2_bits(0, &msg_ptr, 1); //ext + liblte_value_2_bits(meas_report->have_meas_result_neigh_cells, &msg_ptr, 1); + liblte_rrc_pack_meas_id_ie(meas_report->meas_id, &msg_ptr); + liblte_rrc_pack_rsrp_range_ie(meas_report->pcell_rsrp_result, &msg_ptr); + liblte_rrc_pack_rsrq_range_ie(meas_report->pcell_rsrq_result, &msg_ptr); + if(meas_report->have_meas_result_neigh_cells) { + liblte_value_2_bits(0, &msg_ptr, 1); //choice from before extension marker + liblte_value_2_bits(meas_report->meas_result_neigh_cells_choice, &msg_ptr, 2); + if(meas_report->meas_result_neigh_cells_choice != LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA) { + printf("NOT HANDLING %s\n", liblte_rrc_meas_reult_neigh_cells_text[meas_report->meas_result_neigh_cells_choice]); + } else { + //MeasResultListEUTRA + liblte_value_2_bits(meas_report->meas_result_neigh_cells.eutra.n_result-1, &msg_ptr, 3); + for(uint32 i=0; imeas_result_neigh_cells.eutra.n_result; i++) { + liblte_rrc_pack_meas_result_eutra_ie(&meas_report->meas_result_neigh_cells.eutra.result_eutra_list[i], &msg_ptr); + } + } + } + + // Fill in the number of bits used + msg->N_bits = msg_ptr - msg->msg; + + err = LIBLTE_SUCCESS; + } + + return(err); +} +LIBLTE_ERROR_ENUM liblte_rrc_unpack_measurement_report_msg(LIBLTE_BIT_MSG_STRUCT *msg, + LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *meas_report) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 *msg_ptr = msg->msg; + + if(msg != NULL && + meas_report != NULL) + { + //MeasurementReport + bool crit_ext = liblte_bits_2_value(&msg_ptr, 1); //critical extensions + liblte_bits_2_value(&msg_ptr, 3); //c1 + + //MeasurementReport-r8-IEs + bool non_crit_ext = liblte_bits_2_value(&msg_ptr, 1); //non-critical extensions + + //MeasResults + bool ext = liblte_bits_2_value(&msg_ptr, 1); + meas_report->have_meas_result_neigh_cells = liblte_bits_2_value(&msg_ptr, 1); + liblte_rrc_unpack_meas_id_ie(&msg_ptr, &meas_report->meas_id); + liblte_rrc_unpack_rsrp_range_ie(&msg_ptr, &meas_report->pcell_rsrp_result); + liblte_rrc_unpack_rsrq_range_ie(&msg_ptr, &meas_report->pcell_rsrq_result); + if(meas_report->have_meas_result_neigh_cells) { + liblte_bits_2_value(&msg_ptr, 1); //choice from before extension marker + meas_report->meas_result_neigh_cells_choice = (LIBLTE_RRC_MEAS_RESULT_NEIGH_CELLS_ENUM) liblte_bits_2_value(&msg_ptr, 2); + if(meas_report->meas_result_neigh_cells_choice != LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA) { + printf("NOT HANDLING %s\n", liblte_rrc_meas_reult_neigh_cells_text[meas_report->meas_result_neigh_cells_choice]); + } else { + //MeasResultListEUTRA + meas_report->meas_result_neigh_cells.eutra.n_result = liblte_bits_2_value(&msg_ptr, 3) + 1; + for(uint32 i=0; imeas_result_neigh_cells.eutra.n_result; i++) { + liblte_rrc_unpack_meas_result_eutra_ie(&msg_ptr, &meas_report->meas_result_neigh_cells.eutra.result_eutra_list[i]); + } + } + } + + //skip extensions + liblte_rrc_consume_noncrit_extension(crit_ext, __func__, &msg_ptr); + liblte_rrc_consume_noncrit_extension(non_crit_ext, __func__, &msg_ptr); + liblte_rrc_consume_noncrit_extension(ext, __func__, &msg_ptr); + + err = LIBLTE_SUCCESS; + } + + return(err); +} /********************************************************************* Message Name: MBSFN Area Configuration @@ -13550,9 +13787,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_pack_ul_dcch_msg(LIBLTE_RRC_UL_DCCH_MSG_STRUCT *ul_ err = liblte_rrc_pack_csfb_parameters_request_cdma2000_msg((LIBLTE_RRC_CSFB_PARAMETERS_REQUEST_CDMA2000_STRUCT *)&ul_dcch_msg->msg, &global_msg); }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT == ul_dcch_msg->msg_type){ - printf("NOT HANDLING MEASUREMENT REPORT\n"); -// err = liblte_rrc_pack_measurement_report_msg((LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *)&ul_dcch_msg->msg, -// &global_msg); + err = liblte_rrc_pack_measurement_report_msg((LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *)&ul_dcch_msg->msg, + &global_msg); }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE == ul_dcch_msg->msg_type){ err = liblte_rrc_pack_rrc_connection_reconfiguration_complete_msg((LIBLTE_RRC_CONNECTION_RECONFIGURATION_COMPLETE_STRUCT *)&ul_dcch_msg->msg, &global_msg); @@ -13630,9 +13866,8 @@ LIBLTE_ERROR_ENUM liblte_rrc_unpack_ul_dcch_msg(LIBLTE_BIT_MSG_STRUCT *m err = liblte_rrc_unpack_csfb_parameters_request_cdma2000_msg(&global_msg, (LIBLTE_RRC_CSFB_PARAMETERS_REQUEST_CDMA2000_STRUCT *)&ul_dcch_msg->msg); }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT == ul_dcch_msg->msg_type){ - printf("NOT HANDLING MEASUREMENT REPORT\n"); -// err = liblte_rrc_unpack_measurement_report_msg(&global_msg, -// (LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *)&ul_dcch_msg->msg); + err = liblte_rrc_unpack_measurement_report_msg(&global_msg, + (LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *)&ul_dcch_msg->msg); }else if(LIBLTE_RRC_UL_DCCH_MSG_TYPE_RRC_CON_RECONFIG_COMPLETE == ul_dcch_msg->msg_type){ err = liblte_rrc_unpack_rrc_connection_reconfiguration_complete_msg(&global_msg, (LIBLTE_RRC_CONNECTION_RECONFIGURATION_COMPLETE_STRUCT *)&ul_dcch_msg->msg); diff --git a/lib/test/CMakeLists.txt b/lib/test/CMakeLists.txt index a1af8153c..72e9e9100 100644 --- a/lib/test/CMakeLists.txt +++ b/lib/test/CMakeLists.txt @@ -18,5 +18,6 @@ # and at http://www.gnu.org/licenses/. # +add_subdirectory(asn1) add_subdirectory(common) add_subdirectory(upper) diff --git a/lib/test/asn1/CMakeLists.txt b/lib/test/asn1/CMakeLists.txt new file mode 100644 index 000000000..6c52d1972 --- /dev/null +++ b/lib/test/asn1/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright 2013-2017 Software Radio Systems Limited +# +# This file is part of srsLTE +# +# srsLTE is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# srsLTE is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# A copy of the GNU Affero General Public License can be found in +# the LICENSE file in the top-level directory of this distribution +# and at http://www.gnu.org/licenses/. +# + +add_executable(rrc_meas_test rrc_meas_test.cc) +target_link_libraries(rrc_meas_test srslte_common srslte_phy srslte_asn1) +add_test(rrc_meas_test rrc_meas_test) diff --git a/lib/test/asn1/rrc_meas_test.cc b/lib/test/asn1/rrc_meas_test.cc new file mode 100644 index 000000000..63a4d61b6 --- /dev/null +++ b/lib/test/asn1/rrc_meas_test.cc @@ -0,0 +1,91 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2015 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsUE library. + * + * srsUE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsUE is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include +#include +#include +#include "srslte/common/log_filter.h" +#include "srslte/asn1/liblte_rrc.h" + + +void basic_test() { + srslte::log_filter log1("RRC"); + log1.set_level(srslte::LOG_LEVEL_DEBUG); + log1.set_hex_limit(128); + + LIBLTE_BIT_MSG_STRUCT bit_buf; + LIBLTE_BIT_MSG_STRUCT bit_buf2; + LIBLTE_BYTE_MSG_STRUCT byte_buf; + LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg; + + uint32_t rrc_message_len = 18; + uint8_t rrc_message[] = {0x08, 0x10, 0x49, 0x3C, 0x0D, 0x97, 0x89, 0x83, + 0xC0, 0x84, 0x20, 0x82, 0x08, 0x21, 0x00, 0x01, + 0xBC, 0x48}; + + srslte_bit_unpack_vector(rrc_message, bit_buf.msg, rrc_message_len*8); + bit_buf.N_bits = rrc_message_len*8; + liblte_rrc_unpack_ul_dcch_msg((LIBLTE_BIT_MSG_STRUCT*)&bit_buf, &ul_dcch_msg); + + assert(ul_dcch_msg.msg_type == LIBLTE_RRC_UL_DCCH_MSG_TYPE_MEASUREMENT_REPORT); + LIBLTE_RRC_MEASUREMENT_REPORT_STRUCT *rep = &ul_dcch_msg.msg.measurement_report; + assert(rep->meas_id == 1); + assert(rep->pcell_rsrp_result == 73); + assert(rep->pcell_rsrq_result == 15); + assert(rep->have_meas_result_neigh_cells); + assert(rep->meas_result_neigh_cells_choice == LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA); + LIBLTE_RRC_MEAS_RESULT_LIST_EUTRA_STRUCT *eutra = &rep->meas_result_neigh_cells.eutra; + assert(eutra->n_result == 1); + assert(eutra->result_eutra_list[0].phys_cell_id == 357); + assert(eutra->result_eutra_list[0].have_cgi_info); + assert(eutra->result_eutra_list[0].cgi_info.have_plmn_identity_list); + assert(eutra->result_eutra_list[0].cgi_info.cell_global_id.plmn_id.mcc == 0xF898); + assert(eutra->result_eutra_list[0].cgi_info.cell_global_id.plmn_id.mnc == 0xFF78); + assert(eutra->result_eutra_list[0].cgi_info.cell_global_id.cell_id == 0x1084104); + assert(eutra->result_eutra_list[0].cgi_info.tracking_area_code == 0x1042); + assert(eutra->result_eutra_list[0].cgi_info.have_plmn_identity_list); + assert(eutra->result_eutra_list[0].cgi_info.n_plmn_identity_list == 1); + assert(eutra->result_eutra_list[0].cgi_info.plmn_identity_list[0].mcc == 0xFFFF); + assert(eutra->result_eutra_list[0].cgi_info.plmn_identity_list[0].mnc == 0xFF00); + assert(eutra->result_eutra_list[0].meas_result.have_rsrp); + assert(eutra->result_eutra_list[0].meas_result.rsrp_result == 60); + assert(eutra->result_eutra_list[0].meas_result.have_rsrp); + assert(eutra->result_eutra_list[0].meas_result.rsrq_result == 18); + + liblte_rrc_pack_ul_dcch_msg(&ul_dcch_msg, (LIBLTE_BIT_MSG_STRUCT*)&bit_buf2); + srslte_bit_pack_vector(bit_buf2.msg, byte_buf.msg, bit_buf2.N_bits); + byte_buf.N_bytes = (bit_buf2.N_bits+7)/8; + log1.info_hex(byte_buf.msg, byte_buf.N_bytes, "UL_DCCH Packed message\n"); + + for(uint32_t i=0; i Date: Fri, 20 Oct 2017 18:17:07 +0200 Subject: [PATCH 30/49] SSE optimization for srslte_bit_interleave_w_offset --- lib/src/phy/utils/bit.c | 126 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/lib/src/phy/utils/bit.c b/lib/src/phy/utils/bit.c index 9ef53c35a..b1ae383a6 100644 --- a/lib/src/phy/utils/bit.c +++ b/lib/src/phy/utils/bit.c @@ -31,6 +31,12 @@ #include #include +#ifdef LV_HAVE_SSE + +#include + +#endif /* LV_HAVE_SSE */ + #include "srslte/phy/utils/bit.h" void srslte_bit_interleave(uint8_t *input, uint8_t *output, uint16_t *interleaver, uint32_t nof_bits) { @@ -53,6 +59,125 @@ void srslte_bit_interleave_w_offset(uint8_t *input, uint8_t *output, uint16_t *i } w_offset_p=8-w_offset; } +#ifdef LV_HAVE_SSE + __m64 m64mask = _mm_setr_pi8((uint8_t) 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1); + __m128i m128mask = _mm_set1_epi64(m64mask); + + union { + uint8_t v[8]; + __m64 m64; + } a, b, c; + + union { + __m128i m128; + uint16_t u16[8]; + uint8_t u8[16]; + struct { + __m64 reg_a; + __m64 reg_b; + } m64; + struct { + uint16_t i0, i1, i2, i3, i4, i5, i6, i7; + } v; + } ipx, epx, ipx2, epx2, b128, a128, c128; + + uint32_t i = st; + for (; i < (nof_bits / 8 - 1); i += 2) { + ipx.m128 = _mm_loadu_si128((__m128i *) (interleaver + (i * 8) - w_offset_p)); + epx.m128 = _mm_shuffle_epi8(ipx.m128, _mm_set_epi8(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E)); + ipx2.m128 = _mm_loadu_si128((__m128i *) (interleaver + ((i + 1) * 8) - w_offset_p)); + epx2.m128 = _mm_shuffle_epi8(ipx2.m128, _mm_set_epi8(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E)); + + epx.m64.reg_b = epx2.m64.reg_a; + + b128.m128 = _mm_and_si128(epx.m128, _mm_set1_epi8(0x7)); + b128.m128 = _mm_shuffle_epi8(m128mask, b128.m128); + + ipx.m128 = _mm_srli_epi16(ipx.m128, 3); + ipx2.m128 = _mm_srli_epi16(ipx2.m128, 3); + + a128.m128 = _mm_set_epi8(input[ipx2.v.i0], + input[ipx2.v.i1], + input[ipx2.v.i2], + input[ipx2.v.i3], + input[ipx2.v.i4], + input[ipx2.v.i5], + input[ipx2.v.i6], + input[ipx2.v.i7], + input[ipx.v.i0], + input[ipx.v.i1], + input[ipx.v.i2], + input[ipx.v.i3], + input[ipx.v.i4], + input[ipx.v.i5], + input[ipx.v.i6], + input[ipx.v.i7]); + + c128.m128 = _mm_cmpeq_epi8(_mm_and_si128(a128.m128, b128.m128), b128.m128); + uint16_t o = (uint16_t) _mm_movemask_epi8(c128.m128); + *((uint16_t *) (output + i)) = o; + } + + for (; i < nof_bits / 8; i++) { + ipx.m128 = _mm_loadu_si128((__m128i *) (interleaver + i * 8 - w_offset_p)); + epx.m128 = _mm_shuffle_epi8(ipx.m128, _mm_set_epi8(0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, + 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E)); + b.m64 = _mm_and_si64(epx.m64.reg_a, _mm_set1_pi8(0x7)); + b.m64 = _mm_shuffle_pi8(m64mask, b.m64); + + ipx.m128 = _mm_srli_epi16(ipx.m128, 3); + + a.m64 = _mm_set_pi8(input[ipx.v.i0], + input[ipx.v.i1], + input[ipx.v.i2], + input[ipx.v.i3], + input[ipx.v.i4], + input[ipx.v.i5], + input[ipx.v.i6], + input[ipx.v.i7]); + + c.m64 = _mm_cmpeq_pi8(_mm_and_si64(a.m64, b.m64), b.m64); + output[i] = (uint8_t) _mm_movemask_pi8(c.m64); + } + +#if 0 + /* THIS PIECE OF CODE IS FOR CHECKING SIMD BEHAVIOUR. DO NOT ENABLE. */ + uint8_t *output2 = malloc(nof_bits/8); + for (i=st;i Date: Fri, 20 Oct 2017 12:34:34 -0400 Subject: [PATCH 31/49] Added option to ue.conf to configure CFO EMA (set default to 0.4) --- lib/include/srslte/interfaces/ue_interfaces.h | 3 ++- lib/include/srslte/phy/ue/ue_sync.h | 5 ++++- lib/src/phy/ue/ue_sync.c | 5 +++++ srsue/src/main.cc | 5 +++++ srsue/src/phy/phch_recv.cc | 1 + srsue/ue.conf.example | 9 ++++++++- 6 files changed, 25 insertions(+), 3 deletions(-) diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 8561ba55c..88dfd285c 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -445,7 +445,8 @@ typedef struct { float snr_ema_coeff; std::string snr_estim_alg; bool cfo_integer_enabled; - float cfo_correct_tol_hz; + float cfo_correct_tol_hz; + float cfo_ema; int time_correct_period; bool sfo_correct_disable; std::string sss_algorithm; diff --git a/lib/include/srslte/phy/ue/ue_sync.h b/lib/include/srslte/phy/ue/ue_sync.h index bd280acd0..e5877dd23 100644 --- a/lib/include/srslte/phy/ue/ue_sync.h +++ b/lib/include/srslte/phy/ue/ue_sync.h @@ -185,7 +185,10 @@ SRSLTE_API void srslte_ue_sync_set_cfo_tol(srslte_ue_sync_t *q, float tol); SRSLTE_API void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q, - float cfo); + float cfo); + +SRSLTE_API void srslte_ue_sync_set_cfo_ema(srslte_ue_sync_t *q, + float ema); SRSLTE_API void srslte_ue_sync_cfo_i_detec_en(srslte_ue_sync_t *q, bool enable); diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index f121c5bac..e9c02ca8b 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -359,6 +359,11 @@ uint32_t srslte_ue_sync_peak_idx(srslte_ue_sync_t *q) { return q->peak_idx; } +void srslte_ue_sync_set_cfo_ema(srslte_ue_sync_t *q, float ema) { + srslte_sync_set_cfo_ema_alpha(&q->sfind, ema); + srslte_sync_set_cfo_ema_alpha(&q->strack, ema); +} + srslte_ue_sync_state_t srslte_ue_sync_get_state(srslte_ue_sync_t *q) { return q->state; } diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 1b146a9f3..52d4b13c9 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -202,6 +202,11 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { bpo::value(&args->expert.phy.cfo_correct_tol_hz)->default_value(50.0), "Tolerance (in Hz) for digial CFO compensation.") + ("expert.cfo_ema", + bpo::value(&args->expert.phy.cfo_ema)->default_value(0.4), + "CFO Exponential Moving Average coefficient. Lower makes it more robust to noise " + "but vulnerable to periodic interruptions due to VCO corrections.") + ("expert.time_correct_period", bpo::value(&args->expert.phy.time_correct_period)->default_value(5), "Period for sampling time offset correction.") diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index cf8bd6786..8a69a7f76 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -209,6 +209,7 @@ void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q) { srslte_ue_sync_cfo_i_detec_en(q, true); } + srslte_ue_sync_set_cfo_ema(q, worker_com->args->cfo_ema); srslte_ue_sync_set_cfo_tol(q, worker_com->args->cfo_correct_tol_hz); int time_correct_period = worker_com->args->time_correct_period; diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index d0dc67952..5b3559ae9 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -98,7 +98,10 @@ enable = false ##################################################################### # Expert configuration options # +# ue_category: Sets UE category (range 1-5). Default: 4 # ip_netmask: Netmask of the tun_srsue device. Default: 255.255.255.0 +# rssi_sensor_enabled: Enable or disable RF frontend RSSI sensor. Required for RSRP metrics but +# can cause UHD instability for long-duration testing. Default true. # ue_category: Sets UE category (range 1-5). Default: 4 # # prach_gain: PRACH gain (dB). If defined, forces a gain for the tranmsission of PRACH only., @@ -116,7 +119,9 @@ enable = false # nof_phy_threads: Selects the number of PHY threads (maximum 4, minimum 1, default 2) # equalizer_mode: Selects equalizer mode. Valid modes are: "mmse", "zf" or any # non-negative real number to indicate a regularized zf coefficient. -# Default is MMSE. +# Default is MMSE. +# cfo_ema: CFO Exponential Moving Average coefficient. Lower makes it more robust to noise +# but vulnerable to periodic interruptions due to VCO corrections. # cfo_integer_enabled: Enables integer CFO estimation and correction. This needs improvement # and may lead to incorrect synchronization. Use with caution. # cfo_correct_tol_hz: Tolerance (in Hz) for digial CFO compensation. Lower tolerance means that @@ -140,6 +145,7 @@ enable = false ##################################################################### [expert] #ip_netmask = 255.255.255.0 +#rssi_sensor_enabled = false #ue_category = 4 #prach_gain = 30 #cqi_max = 15 @@ -150,6 +156,7 @@ enable = false #attach_enable_64qam = false #nof_phy_threads = 2 #equalizer_mode = mmse +#cfo_ema = 0.4 #cfo_integer_enabled = false #cfo_correct_tol_hz = 50 #time_correct_period = 5 From 3cbe526cbc7fbaad9cb1febfcba4fa2c47783671 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Fri, 20 Oct 2017 12:43:04 -0400 Subject: [PATCH 32/49] Revert "Disable RSSI sensor by default" This reverts commit c14393b24f874b4e12d3bbfb883133fedda4f6f1. --- srsue/src/main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 52d4b13c9..b933b66f3 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -155,7 +155,7 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { "Pregenerate uplink signals after attach. Improves CPU performance.") ("expert.rssi_sensor_enabled", - bpo::value(&args->expert.phy.rssi_sensor_enabled)->default_value(false), + bpo::value(&args->expert.phy.rssi_sensor_enabled)->default_value(true), "Enable or disable RF frontend RSSI sensor. In some USRP devices can cause segmentation fault") ("expert.prach_gain", From ac8cbcaaea91116eb5a5f531e69a1eb8dd007f97 Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Wed, 25 Oct 2017 11:18:49 +0100 Subject: [PATCH 33/49] 1-byte PDU fix for RLC AM --- lib/src/upper/rlc_am.cc | 4 ++-- lib/test/upper/rlc_am_test.cc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index b62a7e88e..96b231a09 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -613,7 +613,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) uint32_t pdu_space = nof_bytes; uint8_t *pdu_ptr = pdu->msg; - if(pdu_space <= head_len) + if(pdu_space <= head_len + 1) { log->warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n", rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len); @@ -652,7 +652,7 @@ int rlc_am::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) } // Pull SDUs from queue - while(pdu_space > head_len && tx_sdu_queue.size() > 0) + while(pdu_space > head_len + 1 && tx_sdu_queue.size() > 0) { if(last_li > 0) header.li[header.N_li++] = last_li; diff --git a/lib/test/upper/rlc_am_test.cc b/lib/test/upper/rlc_am_test.cc index 7a37d0d5d..9ada2ba42 100644 --- a/lib/test/upper/rlc_am_test.cc +++ b/lib/test/upper/rlc_am_test.cc @@ -123,7 +123,7 @@ void basic_test() byte_buffer_t pdu_bufs[NBUFS]; for(int i=0;i Date: Thu, 26 Oct 2017 09:02:30 +0200 Subject: [PATCH 34/49] fix bug in RLC AM where poll bit was never set if poll_byte and poll_pdu are zero - In case both poll_pdu and poll_byte are zero a status PDU is requested from the other AM entity every N data PDUs --- lib/include/srslte/upper/rlc_am.h | 2 ++ lib/src/upper/rlc_am.cc | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/lib/include/srslte/upper/rlc_am.h b/lib/include/srslte/upper/rlc_am.h index afbd18544..cee0d5959 100644 --- a/lib/include/srslte/upper/rlc_am.h +++ b/lib/include/srslte/upper/rlc_am.h @@ -163,6 +163,8 @@ private: static const int reordering_timeout_id = 1; + static const int poll_periodicity = 8; // After how many data PDUs a status PDU shall be requested + // Timer checks bool status_prohibited(); bool poll_retx(); diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index 96b231a09..05f35ad76 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -381,6 +381,18 @@ bool rlc_am::poll_required() return true; if(poll_retx()) return true; + + if(tx_sdu_queue.size() == 0 && retx_queue.size() == 0) + return true; + + /* According to 5.2.2.1 in 36.322 v13.3.0 a poll should be requested if + * the entire AM window is unacknowledged, i.e. no new PDU can be transmitted. + * However, it seems more appropiate to request more often if polling + * is disabled otherwise, e.g. every N PDUs. + */ + if (cfg.poll_pdu == 0 && cfg.poll_byte == 0 && vt_s % poll_periodicity == 0) + return true; + return false; } From 50b196a04e019d8516fdca1efe79fb30e60ba803 Mon Sep 17 00:00:00 2001 From: Merlin Chlosta Date: Fri, 27 Oct 2017 16:18:55 +0200 Subject: [PATCH 35/49] Write SFN to MAC-LTE PCAP file --- lib/include/srslte/common/pcap.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/include/srslte/common/pcap.h b/lib/include/srslte/common/pcap.h index d9937c060..db1dc17d0 100644 --- a/lib/include/srslte/common/pcap.h +++ b/lib/include/srslte/common/pcap.h @@ -80,8 +80,9 @@ typedef struct pcaprec_hdr_s { #define MAC_LTE_UEID_TAG 0x03 /* 2 bytes, network order */ -#define MAC_LTE_SUBFRAME_TAG 0x04 +#define MAC_LTE_FRAME_SUBFRAME_TAG 0x04 /* 2 bytes, network order */ +/* SFN is stored in 12 MSB and SF in 4 LSB */ #define MAC_LTE_PREDFINED_DATA_TAG 0x05 /* 1 byte */ @@ -150,7 +151,7 @@ inline int MAC_LTE_PCAP_WritePDU(FILE *fd, MAC_Context_Info_t *context, pcaprec_hdr_t packet_header; char context_header[256]; int offset = 0; - unsigned short tmp16; + uint16_t tmp16; /* Can't write if file wasn't successfully opened */ if (fd == NULL) { @@ -176,9 +177,11 @@ inline int MAC_LTE_PCAP_WritePDU(FILE *fd, MAC_Context_Info_t *context, memcpy(context_header+offset, &tmp16, 2); offset += 2; - /* Subframe number */ - context_header[offset++] = MAC_LTE_SUBFRAME_TAG; - tmp16 = htons(context->subFrameNumber); + /* Subframe Number and System Frame Number */ + /* SFN is stored in 12 MSB and SF in 4 LSB */ + context_header[offset++] = MAC_LTE_FRAME_SUBFRAME_TAG; + tmp16 = (context->sysFrameNumber << 4) | context->subFrameNumber; + tmp16 = htons(tmp16); memcpy(context_header+offset, &tmp16, 2); offset += 2; @@ -215,4 +218,4 @@ inline void MAC_LTE_PCAP_Close(FILE *fd) fclose(fd); } -#endif /* UEPCAP_H */ \ No newline at end of file +#endif /* UEPCAP_H */ From abbd2e0f85e932246ec382f4afa6f454031e06be Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 28 Oct 2017 14:33:01 -0700 Subject: [PATCH 36/49] return error on precoding error --- lib/src/phy/mimo/precoding.c | 2 +- lib/src/phy/phch/pdsch.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/src/phy/mimo/precoding.c b/lib/src/phy/mimo/precoding.c index a21219a91..5d96bed27 100644 --- a/lib/src/phy/mimo/precoding.c +++ b/lib/src/phy/mimo/precoding.c @@ -1454,7 +1454,7 @@ int srslte_predecoding_type_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_ return srslte_predecoding_single_multi(y, h[0], x[0], nof_rxant, nof_symbols, noise_estimate); } else { fprintf(stderr, - "Number of ports and layers must be 1 for transmission on single antenna ports\n"); + "Number of ports and layers must be 1 for transmission on single antenna ports (%d, %d)\n", nof_ports, nof_layers); return -1; } break; diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index b438a2957..ddfcf3f86 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -677,8 +677,10 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, } // Pre-decoder - srslte_predecoding_type_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers, - cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, noise_estimate); + if (srslte_predecoding_type_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers, + cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, noise_estimate)<0) { + return -1; + } // Layer demapping only if necessary if (cfg->nof_layers != nof_tb) { From 9c04bf2848beb52b5b64ef2a6bba35570e89a5b5 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 28 Oct 2017 16:13:17 -0700 Subject: [PATCH 37/49] Removed metrics period from listener --- lib/include/srslte/common/metrics_hub.h | 6 +++--- srsue/hdr/metrics_csv.h | 4 +++- srsue/hdr/metrics_stdout.h | 4 +++- srsue/src/main.cc | 2 ++ srsue/src/metrics_csv.cc | 9 +++++++-- srsue/src/metrics_stdout.cc | 6 +++++- 6 files changed, 23 insertions(+), 8 deletions(-) diff --git a/lib/include/srslte/common/metrics_hub.h b/lib/include/srslte/common/metrics_hub.h index 66cc4acbd..a9b77d5f6 100644 --- a/lib/include/srslte/common/metrics_hub.h +++ b/lib/include/srslte/common/metrics_hub.h @@ -24,8 +24,8 @@ template class metrics_listener { public: - virtual void set_metrics(metrics_t &m, float report_period_secs=1.0) = 0; -}; + virtual void set_metrics(metrics_t &m) = 0; +}; template class metrics_hub : public periodic_thread @@ -57,7 +57,7 @@ private: bzero(&metric, sizeof(metrics_t)); m->get_metrics(metric); for (uint32_t i=0;iset_metrics(metric, report_period_secs); + listeners[i]->set_metrics(metric); } } } diff --git a/srsue/hdr/metrics_csv.h b/srsue/hdr/metrics_csv.h index a897265d2..f0b3e48c4 100644 --- a/srsue/hdr/metrics_csv.h +++ b/srsue/hdr/metrics_csv.h @@ -48,12 +48,14 @@ class metrics_csv : public srslte::metrics_listener public: metrics_csv(std::string filename); - void set_metrics(ue_metrics_t &m, float report_period_secs); + void set_periodicity(float metrics_report_period_sec); + void set_metrics(ue_metrics_t &m); void set_ue_handle(ue_metrics_interface *ue_); private: std::string float_to_string(float f, int digits, bool add_semicolon = true); + float metrics_report_period; std::ofstream file; ue_metrics_interface* ue; uint32_t n_reports; diff --git a/srsue/hdr/metrics_stdout.h b/srsue/hdr/metrics_stdout.h index 8ae33b24e..87a67cb2e 100644 --- a/srsue/hdr/metrics_stdout.h +++ b/srsue/hdr/metrics_stdout.h @@ -46,8 +46,9 @@ class metrics_stdout : public srslte::metrics_listener public: metrics_stdout(); + void set_periodicity(float metrics_report_period_sec); void toggle_print(bool b); - void set_metrics(ue_metrics_t &m, float report_period_secs); + void set_metrics(ue_metrics_t &m); void set_ue_handle(ue_metrics_interface *ue_); private: @@ -55,6 +56,7 @@ private: std::string float_to_eng_string(float f, int digits); std::string int_to_eng_string(int f, int digits); + float metrics_report_period; bool do_print; uint8_t n_reports; ue_metrics_interface* ue; diff --git a/srsue/src/main.cc b/srsue/src/main.cc index b933b66f3..01f77f2fa 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -386,11 +386,13 @@ int main(int argc, char *argv[]) metricshub.init(ue, args.expert.metrics_period_secs); metricshub.add_listener(&metrics_screen); metrics_screen.set_ue_handle(ue); + metrics_screen.set_periodicity(args.expert.metrics_period_secs); metrics_csv metrics_file(args.expert.metrics_csv_filename); if (args.expert.metrics_csv_enable) { metricshub.add_listener(&metrics_file); metrics_file.set_ue_handle(ue); + metrics_file.set_periodicity(args.expert.metrics_period_secs); } pthread_t input; diff --git a/srsue/src/metrics_csv.cc b/srsue/src/metrics_csv.cc index f9bdce213..7c84659b5 100644 --- a/srsue/src/metrics_csv.cc +++ b/srsue/src/metrics_csv.cc @@ -43,6 +43,7 @@ namespace srsue{ metrics_csv::metrics_csv(std::string filename) :n_reports(0) + ,metrics_report_period(1.0) ,ue(NULL) { file.open(filename.c_str()); @@ -53,7 +54,11 @@ void metrics_csv::set_ue_handle(ue_metrics_interface *ue_) ue = ue_; } -void metrics_csv::set_metrics(ue_metrics_t &metrics, float metrics_report_period) +void metrics_csv::set_periodicity(float metrics_report_period_sec) { + this->metrics_report_period = metrics_report_period_sec; +} + +void metrics_csv::set_metrics(ue_metrics_t &metrics) { if (file.is_open() && ue != NULL) { if(n_reports == 0) { @@ -75,7 +80,7 @@ void metrics_csv::set_metrics(ue_metrics_t &metrics, float metrics_report_period file << float_to_string(metrics.phy.ul.mcs, 2); file << float_to_string((float) metrics.mac.ul_buffer, 2); file << float_to_string((float) metrics.mac.tx_brate/metrics_report_period, 2); - if (metrics.mac.tx_pkts > 0) { + if (metrics.mac.tx_pkts > 0) { file << float_to_string((float) 100*metrics.mac.tx_errors/metrics.mac.tx_pkts, 1); } else { file << float_to_string(0, 2); diff --git a/srsue/src/metrics_stdout.cc b/srsue/src/metrics_stdout.cc index 048532c8f..9f413b65f 100644 --- a/srsue/src/metrics_stdout.cc +++ b/srsue/src/metrics_stdout.cc @@ -50,6 +50,7 @@ char const * const prefixes[2][9] = metrics_stdout::metrics_stdout() :do_print(false) ,n_reports(10) + ,metrics_report_period(1.0) ,ue(NULL) { } @@ -64,8 +65,11 @@ void metrics_stdout::toggle_print(bool b) do_print = b; } +void metrics_stdout::set_periodicity(float metrics_report_period_sec) { + this->metrics_report_period = metrics_report_period_sec; +} -void metrics_stdout::set_metrics(ue_metrics_t &metrics, float metrics_report_period) +void metrics_stdout::set_metrics(ue_metrics_t &metrics) { if(!do_print || ue == NULL) return; From c7f74099549f8da2b4a8ab388b8c2756be650d34 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 28 Oct 2017 21:07:19 -0700 Subject: [PATCH 38/49] Edit warning log --- srsenb/src/mac/scheduler.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/srsenb/src/mac/scheduler.cc b/srsenb/src/mac/scheduler.cc index a7e3d12d6..81ed0882e 100644 --- a/srsenb/src/mac/scheduler.cc +++ b/srsenb/src/mac/scheduler.cc @@ -597,12 +597,13 @@ int sched::dl_sched_data(dl_sched_data_t data[MAX_DATA_LIST]) uint16_t rnti = (uint16_t) iter->first; dl_harq_proc *h = dl_metric->get_user_allocation(user); - + + uint32_t aggr_level = user->get_aggr_level(srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1, cfg.cell.nof_prb, cfg.cell.nof_ports)); if (h) { // Try to schedule DCI first if (generate_dci(&data[nof_data_elems].dci_location, - user->get_locations(current_cfi, sf_idx), - user->get_aggr_level(srslte_dci_format_sizeof(SRSLTE_DCI_FORMAT1, cfg.cell.nof_prb, cfg.cell.nof_ports)), user)) + user->get_locations(current_cfi, sf_idx), + aggr_level, user)) { bool is_newtx = h->is_empty(); int tbs = user->generate_format1(h, &data[nof_data_elems], current_tti, current_cfi); @@ -620,7 +621,8 @@ int sched::dl_sched_data(dl_sched_data_t data[MAX_DATA_LIST]) } } else { h->reset(); - Warning("SCHED: Could not schedule DL DCI for rnti=0x%x, pid=%d\n", rnti, h->get_id()); + Warning("SCHED: Could not schedule DL DCI for rnti=0x%x, pid=%d, L=%d, nof_candidates=%d\n", + rnti, h->get_id(), aggr_level, user->get_locations(current_cfi, sf_idx)->nof_loc[aggr_level] ); } } } From 1d095b006adc7db940f9b7d7ebc6672f352db64a Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 28 Oct 2017 23:30:29 -0700 Subject: [PATCH 39/49] Removed unused nof_tb variable --- lib/examples/pdsch_enodeb.c | 3 ++- lib/include/srslte/phy/phch/ra.h | 1 - lib/src/phy/phch/ra.c | 2 -- lib/src/phy/phch/test/pmch_test.c | 1 - lib/src/phy/ue/ue_dl.c | 1 - 5 files changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/examples/pdsch_enodeb.c b/lib/examples/pdsch_enodeb.c index f7f17bc2b..1d807973c 100644 --- a/lib/examples/pdsch_enodeb.c +++ b/lib/examples/pdsch_enodeb.c @@ -942,7 +942,8 @@ int main(int argc, char **argv) { } /* Configure pmch_cfg parameters */ srslte_ra_dl_grant_t grant; - grant.nof_tb = 1; + grant.tb_en[0] = true; + grant.tb_en[1] = false; grant.mcs[0].idx = 2; grant.mcs[0].mod = SRSLTE_MOD_QPSK; grant.nof_prb = cell.nof_prb; diff --git a/lib/include/srslte/phy/phch/ra.h b/lib/include/srslte/phy/phch/ra.h index aef8f4751..e9c402236 100644 --- a/lib/include/srslte/phy/phch/ra.h +++ b/lib/include/srslte/phy/phch/ra.h @@ -104,7 +104,6 @@ typedef struct SRSLTE_API { uint32_t nof_prb; uint32_t Qm[SRSLTE_MAX_CODEWORDS]; srslte_ra_mcs_t mcs[SRSLTE_MAX_CODEWORDS]; - uint32_t nof_tb; srslte_sf_t sf_type; bool tb_en[SRSLTE_MAX_CODEWORDS]; uint32_t pinfo; diff --git a/lib/src/phy/phch/ra.c b/lib/src/phy/phch/ra.c index 913bd9548..8fe0ef934 100644 --- a/lib/src/phy/phch/ra.c +++ b/lib/src/phy/phch/ra.c @@ -526,11 +526,9 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr grant->mcs[0].tbs = (uint32_t) tbs; } else { n_prb = grant->nof_prb; - grant->nof_tb = 0; if (dci->tb_en[0]) { grant->mcs[0].idx = dci->mcs_idx; grant->mcs[0].tbs = srslte_dl_fill_ra_mcs(&grant->mcs[0], n_prb); - grant->nof_tb++; } else { grant->mcs[0].tbs = 0; } diff --git a/lib/src/phy/phch/test/pmch_test.c b/lib/src/phy/phch/test/pmch_test.c index a9c29ef64..bf415e692 100644 --- a/lib/src/phy/phch/test/pmch_test.c +++ b/lib/src/phy/phch/test/pmch_test.c @@ -167,7 +167,6 @@ int main(int argc, char **argv) { /* If transport block 0 is enabled */ grant.tb_en[0] = true; grant.tb_en[1] = false; - grant.nof_tb = 1; grant.mcs[0].idx = mcs_idx; grant.nof_prb = cell.nof_prb; diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index 930fe2623..1c3b79440 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -608,7 +608,6 @@ int srslte_ue_dl_decode_mbsfn(srslte_ue_dl_t * q, //float noise_estimate = 0; grant.sf_type = SRSLTE_SF_MBSFN; - grant.nof_tb = 1; grant.mcs[0].idx = 2; grant.tb_en[0] = true; grant.tb_en[1] = false; From be0b832927241544e84b3d1643d558354019ed20 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sun, 29 Oct 2017 10:29:53 -0700 Subject: [PATCH 40/49] Implement CW swap and TB to CW mapping for TM4 --- lib/src/phy/phch/dci.c | 28 +++++++++++++++++++++++++++- srsue/src/phy/phch_worker.cc | 7 +------ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/lib/src/phy/phch/dci.c b/lib/src/phy/phch/dci.c index 471429145..3ce4cd6ae 100644 --- a/lib/src/phy/phch/dci.c +++ b/lib/src/phy/phch/dci.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "srslte/phy/phch/dci.h" #include "srslte/phy/common/phy_common.h" @@ -1159,7 +1160,32 @@ int dci_format2AB_unpack(srslte_dci_msg_t *msg, srslte_ra_dl_dci_t *data, uint32 } else if (msg->format == SRSLTE_DCI_FORMAT2A) { data->pinfo = srslte_bit_pack(&y, precoding_bits_f2a(nof_ports)); } - + + // Table 5.3.3.1.5-1 + if (SRSLTE_RA_DL_GRANT_NOF_TB(data) == 2) { + if (data->tb_cw_swap) { + uint32_t tmp = data->rv_idx; + data->rv_idx = data->rv_idx_1; + data->rv_idx_1 = tmp; + + tmp = data->mcs_idx; + data->mcs_idx = data->mcs_idx_1; + data->mcs_idx_1 = tmp; + + bool tmp_ndi = data->ndi; + data->ndi = data->ndi_1; + data->ndi_1 = tmp_ndi; + } + } + + // Table 5.3.3.1.5-2 + if (!data->tb_en[0]) { + data->rv_idx = data->rv_idx_1; + data->mcs_idx = data->mcs_idx_1; + data->ndi = data->ndi_1; + + data->tb_en[1] = false; + } return SRSLTE_SUCCESS; } diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 33795a69f..cf0eab94c 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -504,11 +504,6 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant) grant->tb_en[1] = dci_unpacked.tb_en[1]; grant->tb_cw_swap = dci_unpacked.tb_cw_swap; // FIXME: tb_cw_swap not supported - if (grant->tb_cw_swap) { - Info("tb_cw_swap = true\n"); - printf("tb_cw_swap = true\n"); - } - last_dl_pdcch_ncce = srslte_ue_dl_get_ncce(&ue_dl); char hexstr[16]; @@ -633,7 +628,7 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL for (int i=0;itb_en[i]) { - snprintf(tbstr[i], 128, ", TB%d: tbs=%d, mcs=%d, rv=%d, crc=%s, it=%d", + snprintf(tbstr[i], 128, ", CW%d: tbs=%d, mcs=%d, rv=%d, crc=%s, it=%d", i, grant->mcs[i].tbs/8, grant->mcs[i].idx, rv[i], acks[i] ? "OK" : "KO", srslte_pdsch_last_noi_cw(&ue_dl.pdsch, i)); } From de937faa205fbcc04140c5143d51a5374b06bc69 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sun, 29 Oct 2017 11:02:18 -0700 Subject: [PATCH 41/49] Set invalid inputs error to dlsch_decode --- lib/src/phy/phch/pdsch.c | 3 +++ lib/src/phy/phch/sch.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index ddfcf3f86..99f4fbfa5 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -610,6 +610,9 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *c } else if (ret == SRSLTE_ERROR) { *ack = false; ret = SRSLTE_SUCCESS; + } else if (ret == SRSLTE_ERROR_INVALID_INPUTS) { + *ack = false; + ret = SRSLTE_ERROR; } } else { ERROR("Detected NULL pointer in TB%d &softbuffer=%p &data=%p &ack=%p", codeword_idx, softbuffer, (void*)data, ack); diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index e76fa6aef..b9860ffa4 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -458,12 +458,12 @@ static int decode_tb(srslte_sch_t *q, if (cb_segm->F) { fprintf(stderr, "Error filler bits are not supported. Use standard TBS\n"); - return SRSLTE_ERROR; + return SRSLTE_ERROR_INVALID_INPUTS; } if (cb_segm->C > softbuffer->max_cb) { fprintf(stderr, "Error number of CB (%d) exceeds soft buffer size (%d CBs)\n", cb_segm->C, softbuffer->max_cb); - return SRSLTE_ERROR; + return SRSLTE_ERROR_INVALID_INPUTS; } bool crc_ok = true; From 45d78d33fb785ae7f7b01447ad13b0f9bc535980 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 30 Oct 2017 16:44:52 -0700 Subject: [PATCH 42/49] Consider negative elapsed time values in activity monitor due to multiple PHY threads. Fixes issue #111 --- srsenb/src/upper/rrc.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 35abda80a..e176e8ac5 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -768,9 +768,9 @@ bool rrc::ue::is_timeout() } if (deadline_str) { - uint64_t deadline = deadline_s*1e6 + deadline_us; - uint64_t elapsed = t[0].tv_sec*1e6 + t[0].tv_usec; - if (elapsed > deadline) { + int64_t deadline = deadline_s*1e6 + deadline_us; + int64_t elapsed = t[0].tv_sec*1e6 + t[0].tv_usec; + if (elapsed > deadline && elapsed > 0) { parent->rrc_log->warning("User rnti=0x%x expired %s deadline: %d:%d>%d:%d us\n", rnti, deadline_str, t[0].tv_sec, t[0].tv_usec, From 81b34afff9221d04b1c57581f9ac75f4313e1da7 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 30 Oct 2017 21:49:02 -0700 Subject: [PATCH 43/49] Normalize srsENB OFDM tx signal (srsENB not working PDSCH before this commit until ofdm changes commit) --- lib/src/phy/enb/enb_dl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/phy/enb/enb_dl.c b/lib/src/phy/enb/enb_dl.c index 54a63bc2a..2dee5b7f7 100644 --- a/lib/src/phy/enb/enb_dl.c +++ b/lib/src/phy/enb/enb_dl.c @@ -31,6 +31,7 @@ #include #include #include +#include #define CURRENT_FFTSIZE srslte_symbol_sz(q->cell.nof_prb) @@ -275,7 +276,7 @@ void srslte_enb_dl_put_base(srslte_enb_dl_t *q, uint32_t tti) void srslte_enb_dl_gen_signal(srslte_enb_dl_t *q) { // TODO: PAPR control - float norm_factor = (float) sqrt(q->cell.nof_prb)/15; + float norm_factor = (float) sqrt(q->cell.nof_prb)/15/sqrt(q->ifft[0].symbol_sz); for (int i = 0; i < q->cell.nof_ports; i++) { srslte_ofdm_tx_sf(&q->ifft[i]); From 98969b2011fc7fdbc6aa995645b0f5585fb7f27e Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 31 Oct 2017 12:19:35 +0100 Subject: [PATCH 44/49] Implemented 3GPP 36.212 Tables 5.3.3.1.5-1 and 5.3.3.1.5-2 --- lib/include/srslte/phy/phch/pdsch_cfg.h | 1 + lib/include/srslte/phy/phch/ra.h | 1 + lib/src/phy/phch/pdsch.c | 66 ++++++++++++++----------- lib/src/phy/phch/ra.c | 5 +- lib/src/phy/phch/sch.c | 12 ++--- lib/src/phy/phch/test/CMakeLists.txt | 16 ++++++ lib/src/phy/phch/test/pdsch_test.c | 17 ++++++- 7 files changed, 80 insertions(+), 38 deletions(-) diff --git a/lib/include/srslte/phy/phch/pdsch_cfg.h b/lib/include/srslte/phy/phch/pdsch_cfg.h index eb4927fbb..63b3fefcc 100644 --- a/lib/include/srslte/phy/phch/pdsch_cfg.h +++ b/lib/include/srslte/phy/phch/pdsch_cfg.h @@ -48,6 +48,7 @@ typedef struct SRSLTE_API { uint32_t nof_layers; uint32_t codebook_idx; srslte_mimo_type_t mimo_type; + bool tb_cw_swap; } srslte_pdsch_cfg_t; #endif diff --git a/lib/include/srslte/phy/phch/ra.h b/lib/include/srslte/phy/phch/ra.h index e9c402236..f4274e416 100644 --- a/lib/include/srslte/phy/phch/ra.h +++ b/lib/include/srslte/phy/phch/ra.h @@ -107,6 +107,7 @@ typedef struct SRSLTE_API { srslte_sf_t sf_type; bool tb_en[SRSLTE_MAX_CODEWORDS]; uint32_t pinfo; + bool tb_cw_swap; } srslte_ra_dl_grant_t; #define SRSLTE_RA_DL_GRANT_NOF_TB(G) ((((G)->tb_en[0])?1:0)+(((G)->tb_en[1])?1:0)) diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index 99f4fbfa5..7c744f552 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -477,6 +477,7 @@ int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra cfg->sf_idx = sf_idx; memcpy(cfg->rv, rvidx, sizeof(uint32_t) * SRSLTE_MAX_CODEWORDS); cfg->mimo_type = mimo_type; + cfg->tb_cw_swap = grant->tb_cw_swap; /* Check and configure PDSCH transmission modes */ switch(mimo_type) { @@ -543,19 +544,19 @@ static srslte_sequence_t *get_user_sequence(srslte_pdsch_t *q, uint16_t rnti, static int srslte_pdsch_codeword_encode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, uint16_t rnti, uint8_t *data, - uint32_t codeword_idx) { - srslte_ra_nbits_t *nbits = &cfg->nbits[codeword_idx]; - srslte_ra_mcs_t *mcs = &cfg->grant.mcs[codeword_idx]; - uint32_t rv = cfg->rv[codeword_idx]; + uint32_t codeword_idx, uint32_t tb_idx) { + srslte_ra_nbits_t *nbits = &cfg->nbits[tb_idx]; + srslte_ra_mcs_t *mcs = &cfg->grant.mcs[tb_idx]; + uint32_t rv = cfg->rv[tb_idx]; if (nbits->nof_bits) { - INFO("Encoding PDSCH SF: %d (TB %d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", - cfg->sf_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs, + INFO("Encoding PDSCH SF: %d (TB%d -> CW%d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", + cfg->sf_idx, tb_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs, nbits->nof_re, nbits->nof_bits, rv); /* Channel coding */ - if (srslte_dlsch_encode2(&q->dl_sch, cfg, softbuffer, data, q->e[codeword_idx], codeword_idx)) { - ERROR("Error encoding TB %d", codeword_idx); + if (srslte_dlsch_encode2(&q->dl_sch, cfg, softbuffer, data, q->e[codeword_idx], tb_idx)) { + ERROR("Error encoding (TB%d -> CW%d)", tb_idx, codeword_idx); return SRSLTE_ERROR; } @@ -577,15 +578,15 @@ static int srslte_pdsch_codeword_encode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *c static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint8_t *data, - uint32_t codeword_idx, bool *ack) { - srslte_ra_nbits_t *nbits = &cfg->nbits[codeword_idx]; - srslte_ra_mcs_t *mcs = &cfg->grant.mcs[codeword_idx]; - uint32_t rv = cfg->rv[codeword_idx]; + uint32_t codeword_idx, uint32_t tb_idx, bool *ack) { + srslte_ra_nbits_t *nbits = &cfg->nbits[tb_idx]; + srslte_ra_mcs_t *mcs = &cfg->grant.mcs[tb_idx]; + uint32_t rv = cfg->rv[tb_idx]; int ret = SRSLTE_ERROR_INVALID_INPUTS; if (softbuffer && data && ack) { - INFO("Decoding PDSCH SF: %d (TB %d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", - cfg->sf_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs, + INFO("Decoding PDSCH SF: %d (CW%d -> TB%d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", + cfg->sf_idx, codeword_idx, tb_idx, srslte_mod_string(mcs->mod), mcs->tbs, nbits->nof_re, nbits->nof_bits, rv); /* demodulate symbols @@ -601,7 +602,7 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *c srslte_scrambling_s_offset(seq, q->e[codeword_idx], 0, nbits->nof_bits); /* Return */ - ret = srslte_dlsch_decode2(&q->dl_sch, cfg, softbuffer, q->e[codeword_idx], data, codeword_idx); + ret = srslte_dlsch_decode2(&q->dl_sch, cfg, softbuffer, q->e[codeword_idx], data, tb_idx); q->last_nof_iterations[codeword_idx] = srslte_sch_last_noi(&q->dl_sch); @@ -690,16 +691,22 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, srslte_layerdemap_type(x, q->d, cfg->nof_layers, nof_tb, nof_symbols[0], nof_symbols, cfg->mimo_type); } - // Codeword decoding - for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb ++) { - /* Decode only if transport block is enabled and the default ACK is not true */ - if (cfg->grant.tb_en[tb] && !acks[tb]) { - int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb], rnti, data[tb], tb, &acks[tb]); - /* Check if there has been any execution error */ - if (ret) { - return ret; + /* Codeword decoding: Implementation of 3GPP 36.212 Table 5.3.3.1.5-1 and Table 5.3.3.1.5-2 */ + uint32_t cw_idx = (nof_tb == SRSLTE_MAX_TB && cfg->tb_cw_swap) ? 1 : 0; + for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) { + /* Decode only if transport block is enabled and the default ACK is not true */ + if (cfg->grant.tb_en[tb_idx]) { + if (!acks[tb_idx]) { + int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb_idx], rnti, data[tb_idx], cw_idx, tb_idx, &acks[tb_idx]); + + /* Check if there has been any execution error */ + if (ret) { + return ret; + } } + + cw_idx = (cw_idx + 1) % SRSLTE_MAX_CODEWORDS; } } @@ -772,20 +779,23 @@ int srslte_pdsch_encode(srslte_pdsch_t *q, } /* If both transport block size is zero return error */ - if (cfg->grant.mcs[0].tbs == 0) { + if (!nof_tb) { return SRSLTE_ERROR_INVALID_INPUTS; } - if (cfg->nbits[0].nof_re > q->max_re) { + if (cfg->nbits[0].nof_re > q->max_re || cfg->nbits[1].nof_re > q->max_re) { fprintf(stderr, "Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n", cfg->nbits[0].nof_re, q->max_re, q->cell.nof_prb); return SRSLTE_ERROR_INVALID_INPUTS; } - for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb ++) { - if (cfg->grant.tb_en[tb]) { - ret |= srslte_pdsch_codeword_encode(q, cfg, softbuffers[tb], rnti, data[tb], tb); + /* Implementation of 3GPP 36.212 Table 5.3.3.1.5-1 and Table 5.3.3.1.5-2 */ + uint32_t cw_idx = (nof_tb == SRSLTE_MAX_TB && cfg->tb_cw_swap) ? 1 : 0; + for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) { + if (cfg->grant.tb_en[tb_idx]) { + ret |= srslte_pdsch_codeword_encode(q, cfg, softbuffers[tb_idx], rnti, data[tb_idx], cw_idx, tb_idx); + cw_idx = (cw_idx + 1) % SRSLTE_MAX_CODEWORDS; } } diff --git a/lib/src/phy/phch/ra.c b/lib/src/phy/phch/ra.c index 8fe0ef934..735794e35 100644 --- a/lib/src/phy/phch/ra.c +++ b/lib/src/phy/phch/ra.c @@ -546,6 +546,7 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr } } grant->pinfo = dci->pinfo; + grant->tb_cw_swap = dci->tb_cw_swap; if (grant->mcs[0].tbs < 0 || grant->mcs[1].tbs < 0) { return SRSLTE_ERROR; @@ -559,10 +560,10 @@ void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant, uint32_t cfi, srsl { // Compute number of RE for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { + nbits[i].nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb < 10 ? (cfi + 1) : cfi); + nbits[i].lstart = cell.nof_prb < 10 ? (cfi + 1) : cfi; if (grant->tb_en[i]) { /* Compute number of RE for first transport block */ - nbits[i].nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb < 10 ? (cfi + 1) : cfi); - nbits[i].lstart = cell.nof_prb < 10 ? (cfi + 1) : cfi; if (SRSLTE_SF_NORM == grant->sf_type) { nbits[i].nof_symb = 2 * SRSLTE_CP_NSYMB(cell.cp) - nbits[0].lstart; } else if (SRSLTE_SF_MBSFN == grant->sf_type) { diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index b9860ffa4..930364725 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -517,15 +517,15 @@ int srslte_dlsch_decode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuf int srslte_dlsch_decode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, - int16_t *e_bits, uint8_t *data, int codeword_idx) { + int16_t *e_bits, uint8_t *data, int tb_idx) { uint32_t Nl = 1; if (cfg->nof_layers != SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant)) { Nl = 2; } - return decode_tb(q, softbuffer, &cfg->cb_segm[codeword_idx], - cfg->grant.Qm[codeword_idx] * Nl, cfg->rv[codeword_idx], cfg->nbits[codeword_idx].nof_bits, + return decode_tb(q, softbuffer, &cfg->cb_segm[tb_idx], + cfg->grant.Qm[tb_idx] * Nl, cfg->rv[tb_idx], cfg->nbits[tb_idx].nof_bits, e_bits, data); } @@ -546,15 +546,15 @@ int srslte_dlsch_encode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuf } int srslte_dlsch_encode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, - uint8_t *data, uint8_t *e_bits, int codeword_idx) { + uint8_t *data, uint8_t *e_bits, int tb_idx) { uint32_t Nl = 1; if (cfg->nof_layers != SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant)) { Nl = 2; } - return encode_tb(q, softbuffer, &cfg->cb_segm[codeword_idx], cfg->grant.Qm[codeword_idx]*Nl, cfg->rv[codeword_idx], - cfg->nbits[codeword_idx].nof_bits, data, e_bits); + return encode_tb(q, softbuffer, &cfg->cb_segm[tb_idx], cfg->grant.Qm[tb_idx]*Nl, cfg->rv[tb_idx], + cfg->nbits[tb_idx].nof_bits, data, e_bits); } /* Compute the interleaving function on-the-fly, because it depends on number of RI bits diff --git a/lib/src/phy/phch/test/CMakeLists.txt b/lib/src/phy/phch/test/CMakeLists.txt index 6e6b8c024..f1a2bccee 100644 --- a/lib/src/phy/phch/test/CMakeLists.txt +++ b/lib/src/phy/phch/test/CMakeLists.txt @@ -119,6 +119,14 @@ add_test(pdsch_test_multiplex1cw_p0_50 pdsch_test -x multiplex -a 2 -p 0 -n 50) add_test(pdsch_test_multiplex1cw_p0_75 pdsch_test -x multiplex -a 2 -p 0 -n 75) add_test(pdsch_test_multiplex1cw_p0_100 pdsch_test -x multiplex -a 2 -p 0 -n 100) +# PDSCH test for Spatial Multiplex transmision mode with PMI = 0 (1 codeword, swapped) +add_test(pdsch_test_multiplex1cw_p0_6_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 6 -F 1) +add_test(pdsch_test_multiplex1cw_p0_15_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 15) +add_test(pdsch_test_multiplex1cw_p0_25_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 25) +add_test(pdsch_test_multiplex1cw_p0_50_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 50) +add_test(pdsch_test_multiplex1cw_p0_75_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 75) +add_test(pdsch_test_multiplex1cw_p0_100_swap pdsch_test -x multiplex -a 2 -p 0 -m 0 -r 1 -M 28 -t 0 -n 100) + # PDSCH test for Spatial Multiplex transmision mode with PMI = 1 (1 codeword) add_test(pdsch_test_multiplex1cw_p1_6 pdsch_test -x multiplex -a 2 -p 1 -n 6) add_test(pdsch_test_multiplex1cw_p1_12 pdsch_test -x multiplex -a 2 -p 1 -n 12) @@ -151,6 +159,14 @@ add_test(pdsch_test_multiplex2cw_p0_50 pdsch_test -x multiplex -a 2 -t 0 -p 0 - add_test(pdsch_test_multiplex2cw_p0_75 pdsch_test -x multiplex -a 2 -t 0 -p 0 -n 75) add_test(pdsch_test_multiplex2cw_p0_100 pdsch_test -x multiplex -a 2 -t 0 -p 0 -n 100) +# PDSCH test for Spatial Multiplex transmision mode with PMI = 0 (2 codeword, swapped) +add_test(pdsch_test_multiplex2cw_p0_6_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -M 28 -n 6 -w -F 1) +add_test(pdsch_test_multiplex2cw_p0_12_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -m 28 -n 12 -w) +add_test(pdsch_test_multiplex2cw_p0_25_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -M 28 -n 25 -w) +add_test(pdsch_test_multiplex2cw_p0_50_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -m 28 -n 50 -w) +add_test(pdsch_test_multiplex2cw_p0_75_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -M 28 -n 75 -w) +add_test(pdsch_test_multiplex2cw_p0_100_swap pdsch_test -x multiplex -a 2 -t 0 -p 0 -m 28 -n 100 -w) + # PDSCH test for Spatial Multiplex transmision mode with PMI = 1 (2 codeword) add_test(pdsch_test_multiplex2cw_p1_6 pdsch_test -x multiplex -a 2 -t 0 -p 1 -n 6) add_test(pdsch_test_multiplex2cw_p1_12 pdsch_test -x multiplex -a 2 -t 0 -p 1 -n 12) diff --git a/lib/src/phy/phch/test/pdsch_test.c b/lib/src/phy/phch/test/pdsch_test.c index 0c98079b9..b97e8b299 100644 --- a/lib/src/phy/phch/test/pdsch_test.c +++ b/lib/src/phy/phch/test/pdsch_test.c @@ -59,6 +59,7 @@ uint32_t subframe = 1; int rv_idx[SRSLTE_MAX_CODEWORDS] = {0, 1}; uint16_t rnti = 1234; uint32_t nof_rx_antennas = 1; +bool tb_cw_swap = false; uint32_t pmi = 0; char *input_file = NULL; @@ -77,12 +78,13 @@ void usage(char *prog) { printf("\t-n cell.nof_prb [Default %d]\n", cell.nof_prb); printf("\t-a nof_rx_antennas [Default %d]\n", nof_rx_antennas); printf("\t-p pmi (multiplex only) [Default %d]\n", pmi); + printf("\t-w Swap Transport Blocks\n"); printf("\t-v [set srslte_verbose to debug, default none]\n"); } void parse_args(int argc, char **argv) { int opt; - while ((opt = getopt(argc, argv, "fmMcsrtRFpnavx")) != -1) { + while ((opt = getopt(argc, argv, "fmMcsrtRFpnawvx")) != -1) { switch(opt) { case 'f': input_file = argv[optind]; @@ -123,6 +125,9 @@ void parse_args(int argc, char **argv) { case 'a': nof_rx_antennas = (uint32_t) atoi(argv[optind]); break; + case 'w': + tb_cw_swap = true; + break; case 'v': srslte_verbose++; break; @@ -207,6 +212,11 @@ int main(int argc, char **argv) { dci.tb_en[1] = true; } + /* Enable swap */ + if (SRSLTE_RA_DL_GRANT_NOF_TB(&dci) == SRSLTE_MAX_TB && tb_cw_swap) { + dci.tb_cw_swap = tb_cw_swap; + } + /* Generate grant from DCI */ if (srslte_ra_dl_dci_to_grant(&dci, cell.nof_prb, rnti, &grant)) { fprintf(stderr, "Error computing resource allocation\n"); @@ -255,7 +265,7 @@ int main(int argc, char **argv) { } - for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { + for (i = 0; i < SRSLTE_MAX_TB; i++) { if (grant.tb_en[i]) { data_tx[i] = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs[i].tbs); if (!data_tx[i]) { @@ -271,6 +281,9 @@ int main(int argc, char **argv) { } bzero(data_rx[i], sizeof(uint8_t) * grant.mcs[i].tbs); + } else { + data_tx[i] = NULL; + data_rx[i] = NULL; } } From 3a054a22b922dbfc28a0fc33c50e099ad0eda221 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 31 Oct 2017 07:26:49 -0700 Subject: [PATCH 45/49] Remove OFDM normalization from enb_dl_init and do it before transmission --- lib/src/phy/enb/enb_dl.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/src/phy/enb/enb_dl.c b/lib/src/phy/enb/enb_dl.c index 2dee5b7f7..98224d740 100644 --- a/lib/src/phy/enb/enb_dl.c +++ b/lib/src/phy/enb/enb_dl.c @@ -71,10 +71,6 @@ int srslte_enb_dl_init(srslte_enb_dl_t *q, cf_t *out_buffer[SRSLTE_MAX_PORTS], u } } - for (int i = 0; i < q->cell.nof_ports; i++) { - srslte_ofdm_set_normalize(&q->ifft[i], true); - } - if (srslte_pbch_init(&q->pbch)) { fprintf(stderr, "Error creating PBCH object\n"); goto clean_exit; From 0d95159a2a45a0cdf3de81cea12c414ff384558a Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 31 Oct 2017 08:01:02 -0700 Subject: [PATCH 46/49] Fix issue #114 --- lib/src/common/pdu.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/common/pdu.cc b/lib/src/common/pdu.cc index 57bc07043..b8d17d984 100644 --- a/lib/src/common/pdu.cc +++ b/lib/src/common/pdu.cc @@ -823,7 +823,7 @@ void rar_subh::write_subheader(uint8_t** ptr, bool is_last) // Section 6.2.3 void rar_subh::write_payload(uint8_t** ptr) { - *(*ptr + 0) = (uint8_t) (ta&0x7f0)>>4; + *(*ptr + 0) = (uint8_t) ((ta&0x7f0)>>4); *(*ptr + 1) = (uint8_t) ((ta&0xf) <<4) | (grant[0]<<3) | (grant[1]<<2) | (grant[2]<<1) | grant[3]; uint8_t *x = &grant[4]; *(*ptr + 2) = (uint8_t) srslte_bit_pack(&x, 8); From bb2bc952470b2d69eb3592839aa3ee4f8a43ca92 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 31 Oct 2017 22:46:57 -0700 Subject: [PATCH 47/49] Fix diversity tx not working for 4 ports --- lib/src/phy/phch/pdsch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index 7c744f552..b984adee3 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -493,7 +493,7 @@ int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra ERROR("Wrong number of transport blocks (%d) for transmit diversity.", nof_tb); return SRSLTE_ERROR; } - cfg->nof_layers = 2; + cfg->nof_layers = cell.nof_ports; break; case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX: if (nof_tb == 1) { From d615dc9ec9194dc565a6417baec7e53d8c79b8dd Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 1 Nov 2017 16:30:14 -0700 Subject: [PATCH 48/49] Added missing deallocation in RLC UM in case of too small pdu --- lib/src/upper/rlc_um.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index d95e186e7..4756e2f7c 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -279,6 +279,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) if(pdu_space <= head_len + 1) { + pool->deallocate(pdu); log->warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n", rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len); return 0; @@ -348,7 +349,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) rlc_um_write_data_pdu_header(&header, pdu); memcpy(payload, pdu->msg, pdu->N_bytes); uint32_t ret = pdu->N_bytes; - log->debug("%sreturning length %d\n", rrc->get_rb_name(lcid).c_str(), pdu->N_bytes); + log->debug("%s returning length %d\n", rrc->get_rb_name(lcid).c_str(), pdu->N_bytes); pool->deallocate(pdu); debug_state(); From 935afe6ef35886956aeb722c4d64f5bde708bd6d Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Thu, 2 Nov 2017 17:44:56 +0000 Subject: [PATCH 49/49] Minor soapy fix --- lib/src/phy/rf/rf_soapy_imp.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lib/src/phy/rf/rf_soapy_imp.c b/lib/src/phy/rf/rf_soapy_imp.c index fef533ffc..18c5b01cd 100644 --- a/lib/src/phy/rf/rf_soapy_imp.c +++ b/lib/src/phy/rf/rf_soapy_imp.c @@ -286,11 +286,6 @@ double rf_soapy_set_rx_srate(void *h, double rate) return SRSLTE_ERROR; } - if (SoapySDRDevice_setBandwidth(handler->device, SOAPY_SDR_RX, 0, rate) != 0) { - printf("setBandwidth Rx failed: %s\n", SoapySDRDevice_lastError()); - return SRSLTE_ERROR; - } - return SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_RX,0); } @@ -302,11 +297,6 @@ double rf_soapy_set_tx_srate(void *h, double rate) return SRSLTE_ERROR; } - if (SoapySDRDevice_setBandwidth(handler->device, SOAPY_SDR_TX, 0, rate) != 0) { - printf("setBandwidth Tx failed: %s\n", SoapySDRDevice_lastError()); - return SRSLTE_ERROR; - } - return SoapySDRDevice_getSampleRate(handler->device, SOAPY_SDR_TX,0); }