From 6fc9c96c58b7856c3a23ec87a3ceccd0a0e3129f Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 28 Feb 2018 12:02:17 +0100 Subject: [PATCH 1/5] Added CSI softbits weightening for Single antenna transmission --- lib/include/srslte/phy/mimo/precoding.h | 3 + lib/include/srslte/phy/phch/pdsch.h | 6 ++ lib/include/srslte/phy/utils/simd.h | 12 +++- .../phy/ch_estimation/test/chest_test_dl.c | 4 +- lib/src/phy/mimo/precoding.c | 58 +++++++++++++++++-- lib/src/phy/mimo/test/precoder_test.c | 2 +- lib/src/phy/phch/pbch.c | 2 +- lib/src/phy/phch/pcfich.c | 2 +- lib/src/phy/phch/pdcch.c | 2 +- lib/src/phy/phch/pdsch.c | 52 ++++++++++++++++- lib/src/phy/phch/phich.c | 2 +- lib/src/phy/phch/pmch.c | 2 +- lib/src/phy/phch/pucch.c | 2 +- lib/src/phy/phch/pusch.c | 2 +- 14 files changed, 135 insertions(+), 16 deletions(-) diff --git a/lib/include/srslte/phy/mimo/precoding.h b/lib/include/srslte/phy/mimo/precoding.h index f8463d1cb..27395085c 100644 --- a/lib/include/srslte/phy/mimo/precoding.h +++ b/lib/include/srslte/phy/mimo/precoding.h @@ -79,6 +79,7 @@ SRSLTE_API int srslte_precoding_type(cf_t *x[SRSLTE_MAX_LAYERS], SRSLTE_API int srslte_predecoding_single(cf_t *y, cf_t *h, cf_t *x, + float *csi, int nof_symbols, float scaling, float noise_estimate); @@ -86,6 +87,7 @@ SRSLTE_API int srslte_predecoding_single(cf_t *y, SRSLTE_API int srslte_predecoding_single_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, + float *csi, int nof_rxant, int nof_symbols, float scaling, @@ -111,6 +113,7 @@ SRSLTE_API void srslte_predecoding_set_mimo_decoder (srslte_mimo_decoder_t _mimo SRSLTE_API int srslte_predecoding_type(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], cf_t *x[SRSLTE_MAX_LAYERS], + float *csi, int nof_rxant, int nof_ports, int nof_layers, diff --git a/lib/include/srslte/phy/phch/pdsch.h b/lib/include/srslte/phy/phch/pdsch.h index dab900d77..1889078e6 100644 --- a/lib/include/srslte/phy/phch/pdsch.h +++ b/lib/include/srslte/phy/phch/pdsch.h @@ -76,6 +76,9 @@ typedef struct SRSLTE_API { cf_t *d[SRSLTE_MAX_CODEWORDS]; /* Modulated/Demodulated codewords */ void *e[SRSLTE_MAX_CODEWORDS]; + bool csi_enabled; + float *csi[SRSLTE_MAX_CODEWORDS]; /* Channel Strengh Indicator */ + /* tx & rx objects */ srslte_modem_table_t mod[4]; @@ -107,6 +110,9 @@ SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q, SRSLTE_API void srslte_pdsch_set_power_allocation(srslte_pdsch_t *q, float rho_a); +SRSLTE_API int srslte_pdsch_enable_csi(srslte_pdsch_t *q, + bool enable); + SRSLTE_API void srslte_pdsch_free_rnti(srslte_pdsch_t *q, uint16_t rnti); diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index e22a9ef09..3b5a00a8a 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -530,7 +530,7 @@ static inline simd_cf_t srslte_simd_cfi_loadu(const cf_t *ptr) { 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F), in2); #else /* LV_HAVE_AVX512 */ - #ifdef LV_HAVE_AVX2 +#ifdef LV_HAVE_AVX2 __m256 in1 = _mm256_permute_ps(_mm256_loadu_ps((float*)(ptr)), 0b11011000); __m256 in2 = _mm256_permute_ps(_mm256_loadu_ps((float*)(ptr + 4)), 0b11011000); ret.re = _mm256_unpacklo_ps(in1, in2); @@ -705,6 +705,16 @@ static inline void srslte_simd_cf_storeu(float *re, float *im, simd_cf_t simdreg #endif /* LV_HAVE_AVX512 */ } +static inline simd_f_t srslte_simd_cf_re(simd_cf_t in) { + simd_f_t out = in.re; +#ifdef LV_HAVE_AVX2 + /* Permute for AVX registers (mis SSE registers) */ + const __m256i idx = _mm256_setr_epi32(0, 2, 4, 6, 1, 3, 5, 7); + out = _mm256_permutevar8x32_ps(out, idx); +#endif /* LV_HAVE_AVX2 */ + return out; +} + static inline simd_cf_t srslte_simd_cf_set1 (cf_t x) { simd_cf_t ret; #ifdef LV_HAVE_AVX512 diff --git a/lib/src/phy/ch_estimation/test/chest_test_dl.c b/lib/src/phy/ch_estimation/test/chest_test_dl.c index 62f7e1c86..222263c7e 100644 --- a/lib/src/phy/ch_estimation/test/chest_test_dl.c +++ b/lib/src/phy/ch_estimation/test/chest_test_dl.c @@ -173,7 +173,7 @@ int main(int argc, char **argv) { gettimeofday(&t[1], NULL); for (int j=0;j<100;j++) { - srslte_predecoding_single(input, ce, output, num_re, 1.0f, 0); + srslte_predecoding_single(input, ce, output, NULL, num_re, 1.0f, 0); } gettimeofday(&t[2], NULL); get_time_interval(t); @@ -188,7 +188,7 @@ int main(int argc, char **argv) { gettimeofday(&t[1], NULL); for (int j=0;j<100;j++) { - srslte_predecoding_single(input, ce, output, num_re, 1.0f, srslte_chest_dl_get_noise_estimate(&est)); + srslte_predecoding_single(input, ce, output, NULL, num_re, 1.0f, srslte_chest_dl_get_noise_estimate(&est)); } gettimeofday(&t[2], NULL); get_time_interval(t); diff --git a/lib/src/phy/mimo/precoding.c b/lib/src/phy/mimo/precoding.c index 6d50e3ed2..f8faeda75 100644 --- a/lib/src/phy/mimo/precoding.c +++ b/lib/src/phy/mimo/precoding.c @@ -34,6 +34,7 @@ #include "srslte/phy/utils/vector.h" #include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/mat.h" +#include "srslte/phy/utils/simd.h" #ifdef LV_HAVE_SSE #include @@ -252,8 +253,49 @@ int srslte_predecoding_single_gen(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_ return nof_symbols; } +int srslte_predecoding_single_csi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, float *csi, int nof_rxant, int nof_symbols, float scaling, float noise_estimate) { + int i = 0; + +#if SRSLTE_SIMD_CF_SIZE + const simd_f_t _noise = srslte_simd_f_set1(noise_estimate); + const simd_f_t _scaling = srslte_simd_f_set1(1.0f / scaling); + + for (; i < nof_symbols - SRSLTE_SIMD_CF_SIZE + 1; i += SRSLTE_SIMD_CF_SIZE) { + simd_cf_t _r = srslte_simd_cf_zero(); + simd_f_t _hh = srslte_simd_f_zero(); + + for (int p = 0; p < nof_rxant; p++) { + simd_cf_t _y = srslte_simd_cfi_load(&y[p][i]); + simd_cf_t _h = srslte_simd_cfi_load(&h[p][i]); + + _r = srslte_simd_cf_add(_r, srslte_simd_cf_conjprod(_y, _h)); + _hh = srslte_simd_f_add(_hh, srslte_simd_cf_re(srslte_simd_cf_conjprod(_h, _h))); + } + + simd_f_t _csi = srslte_simd_f_add(_hh, _noise); + simd_cf_t _x = srslte_simd_cf_mul(srslte_simd_cf_mul(_r, _scaling), srslte_simd_f_rcp(_csi)); + + srslte_simd_f_store(&csi[i], _csi); + srslte_simd_cfi_store(&x[i], _x); + } +#endif + + for (; i < nof_symbols; i++) { + cf_t r = 0; + float hh = 0; + float _scaling = 1.0f / scaling; + for (int p = 0; p < nof_rxant; p++) { + r += y[p][i] * conj(h[p][i]); + hh += (__real__ h[p][i] * __real__ h[p][i]) + (__imag__ h[p][i] * __imag__ h[p][i]); + } + csi[i] = hh + noise_estimate; + x[i] = r * _scaling / csi[i]; + } + return nof_symbols; +} + /* ZF/MMSE SISO equalizer x=y(h'h+no)^(-1)h' (ZF if n0=0.0)*/ -int srslte_predecoding_single(cf_t *y_, cf_t *h_, cf_t *x, int nof_symbols, float scaling, float noise_estimate) { +int srslte_predecoding_single(cf_t *y_, cf_t *h_, cf_t *x, float *csi, int nof_symbols, float scaling, float noise_estimate) { cf_t *y[SRSLTE_MAX_PORTS]; cf_t *h[SRSLTE_MAX_PORTS]; @@ -261,6 +303,10 @@ int srslte_predecoding_single(cf_t *y_, cf_t *h_, cf_t *x, int nof_symbols, floa h[0] = h_; int nof_rxant = 1; + if (csi) { + return srslte_predecoding_single_csi(y, h, x, csi, nof_rxant, nof_symbols, scaling, noise_estimate); + } + #ifdef LV_HAVE_AVX if (nof_symbols > 32 && nof_rxant <= 2) { return srslte_predecoding_single_avx(y, h, x, nof_rxant, nof_symbols, scaling, noise_estimate); @@ -281,8 +327,12 @@ int srslte_predecoding_single(cf_t *y_, cf_t *h_, cf_t *x, int nof_symbols, floa } /* ZF/MMSE SISO equalizer x=y(h'h+no)^(-1)h' (ZF if n0=0.0)*/ -int srslte_predecoding_single_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, +int srslte_predecoding_single_multi(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS], cf_t *x, float *csi, int nof_rxant, int nof_symbols, float scaling, float noise_estimate) { + if (csi) { + return srslte_predecoding_single_csi(y, h, x, csi, nof_rxant, nof_symbols, scaling, noise_estimate); + } + #ifdef LV_HAVE_AVX if (nof_symbols > 32) { return srslte_predecoding_single_avx(y, h, x, nof_rxant, nof_symbols, scaling, noise_estimate); @@ -1418,7 +1468,7 @@ void srslte_predecoding_set_mimo_decoder (srslte_mimo_decoder_t _mimo_decoder) { /* 36.211 v10.3.0 Section 6.3.4 */ int srslte_predecoding_type(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - cf_t *x[SRSLTE_MAX_LAYERS], int nof_rxant, int nof_ports, int nof_layers, + cf_t *x[SRSLTE_MAX_LAYERS], float *csi, int nof_rxant, int nof_ports, int nof_layers, int codebook_idx, int nof_symbols, srslte_mimo_type_t type, float scaling, float noise_estimate) { @@ -1451,7 +1501,7 @@ int srslte_predecoding_type(cf_t *y[SRSLTE_MAX_PORTS], cf_t *h[SRSLTE_MAX_PORTS] return -1; case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA: if (nof_ports == 1 && nof_layers == 1) { - return srslte_predecoding_single_multi(y, h[0], x[0], nof_rxant, nof_symbols, scaling, noise_estimate); + return srslte_predecoding_single_multi(y, h[0], x[0], csi, nof_rxant, nof_symbols, scaling, noise_estimate); } else { fprintf(stderr, "Number of ports and layers must be 1 for transmission on single antenna ports (%d, %d)\n", nof_ports, nof_layers); diff --git a/lib/src/phy/mimo/test/precoder_test.c b/lib/src/phy/mimo/test/precoder_test.c index 1054545c3..a6925f318 100644 --- a/lib/src/phy/mimo/test/precoder_test.c +++ b/lib/src/phy/mimo/test/precoder_test.c @@ -291,7 +291,7 @@ int main(int argc, char **argv) { /* predecoding / equalization */ struct timeval t[3]; gettimeofday(&t[1], NULL); - srslte_predecoding_type(r, h, xr, nof_rx_ports, nof_tx_ports, nof_layers, + srslte_predecoding_type(r, h, xr, NULL, nof_rx_ports, nof_tx_ports, nof_layers, codebook_idx, nof_re, type, scaling, powf(10, -snr_db / 10)); gettimeofday(&t[2], NULL); get_time_interval(t); diff --git a/lib/src/phy/phch/pbch.c b/lib/src/phy/phch/pbch.c index c72b12c60..e7c0c33af 100644 --- a/lib/src/phy/phch/pbch.c +++ b/lib/src/phy/phch/pbch.c @@ -497,7 +497,7 @@ int srslte_pbch_decode(srslte_pbch_t *q, cf_t *slot1_symbols, cf_t *ce_slot1[SRS /* in control channels, only diversity is supported */ if (nant == 1) { /* no need for layer demapping */ - srslte_predecoding_single(q->symbols[0], q->ce[0], q->d, q->nof_symbols, 1.0f, noise_estimate); + srslte_predecoding_single(q->symbols[0], q->ce[0], q->d, NULL, q->nof_symbols, 1.0f, noise_estimate); } else { srslte_predecoding_diversity(q->symbols[0], q->ce, x, nant, q->nof_symbols, 1.0f); diff --git a/lib/src/phy/phch/pcfich.c b/lib/src/phy/phch/pcfich.c index 7269000a8..6b00e768a 100644 --- a/lib/src/phy/phch/pcfich.c +++ b/lib/src/phy/phch/pcfich.c @@ -219,7 +219,7 @@ int srslte_pcfich_decode_multi(srslte_pcfich_t *q, cf_t *sf_symbols[SRSLTE_MAX_P /* in control channels, only diversity is supported */ if (q->cell.nof_ports == 1) { /* no need for layer demapping */ - srslte_predecoding_single_multi(q_symbols, q_ce[0], q->d, q->nof_rx_antennas, q->nof_symbols, 1.0f, noise_estimate); + srslte_predecoding_single_multi(q_symbols, q_ce[0], q->d, NULL, q->nof_rx_antennas, q->nof_symbols, 1.0f, noise_estimate); } else { srslte_predecoding_diversity_multi(q_symbols, q_ce, x, q->nof_rx_antennas, q->cell.nof_ports, q->nof_symbols, 1.0f); srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports, q->nof_symbols / q->cell.nof_ports); diff --git a/lib/src/phy/phch/pdcch.c b/lib/src/phy/phch/pdcch.c index 206ef1be6..83f681f8f 100644 --- a/lib/src/phy/phch/pdcch.c +++ b/lib/src/phy/phch/pdcch.c @@ -490,7 +490,7 @@ int srslte_pdcch_extract_llr_multi(srslte_pdcch_t *q, cf_t *sf_symbols[SRSLTE_MA /* in control channels, only diversity is supported */ if (q->cell.nof_ports == 1) { /* no need for layer demapping */ - srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, q->nof_rx_antennas, nof_symbols, 1.0f, noise_estimate/2); + srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, NULL, q->nof_rx_antennas, nof_symbols, 1.0f, noise_estimate/2); } else { srslte_predecoding_diversity_multi(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, nof_symbols, 1.0f); srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports, nof_symbols / q->cell.nof_ports); diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index 1cf4af4e2..4cfa5c75c 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -294,6 +294,10 @@ void srslte_pdsch_free(srslte_pdsch_t *q) { if (q->d[i]) { free(q->d[i]); } + + if (q->csi[i]) { + free(q->csi[i]); + } } /* Free sch objects */ @@ -394,6 +398,22 @@ void srslte_pdsch_set_power_allocation(srslte_pdsch_t *q, float rho_a) { } } +int srslte_pdsch_enable_csi(srslte_pdsch_t *q, bool enable) { + if (enable) { + for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { + if (!q->csi[i]) { + q->csi[i] = srslte_vec_malloc(sizeof(float) * q->max_re); + if (!q->csi[i]) { + return SRSLTE_ERROR; + } + } + } + } + q->csi_enabled = enable; + + return SRSLTE_SUCCESS; +} + void srslte_pdsch_free_rnti(srslte_pdsch_t* q, uint16_t rnti) { uint32_t rnti_idx = q->is_ue?0:rnti; @@ -617,6 +637,36 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *c /* Bit scrambling */ srslte_scrambling_s_offset(seq, q->e[codeword_idx], 0, nbits->nof_bits); + uint32_t qm = nbits->nof_bits/nbits->nof_re; + switch(cfg->grant.mcs[tb_idx].mod) { + + case SRSLTE_MOD_BPSK: + qm = 1; + break; + case SRSLTE_MOD_QPSK: + qm = 2; + break; + case SRSLTE_MOD_16QAM: + qm = 4; + break; + case SRSLTE_MOD_64QAM: + qm = 6; + break; + default: + ERROR("No modulation"); + } + + int16_t *e = q->e[codeword_idx]; + + if (q->csi_enabled) { + for (int i = 0; i < nbits->nof_bits / qm; i++) { + float csi = q->csi[codeword_idx][i]; + for (int k = 0; k < qm; k++) { + e[qm * i + k] = (int16_t) ((float) e[qm * i + k] * csi); + } + } + } + /* Return */ ret = srslte_dlsch_decode2(&q->dl_sch, cfg, softbuffer, q->e[codeword_idx], data, tb_idx); @@ -702,7 +752,7 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, } // Pre-decoder - if (srslte_predecoding_type(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers, + if (srslte_predecoding_type(q->symbols, q->ce, x, q->csi[0], q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers, cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, pdsch_scaling, noise_estimate)<0) { DEBUG("Error predecoding\n"); return SRSLTE_ERROR; diff --git a/lib/src/phy/phch/phich.c b/lib/src/phy/phch/phich.c index 6990d69e2..15aa4db88 100644 --- a/lib/src/phy/phch/phich.c +++ b/lib/src/phy/phch/phich.c @@ -239,7 +239,7 @@ int srslte_phich_decode(srslte_phich_t *q, cf_t *sf_symbols[SRSLTE_MAX_PORTS], /* in control channels, only diversity is supported */ if (q->cell.nof_ports == 1) { /* no need for layer demapping */ - srslte_predecoding_single_multi(q_sf_symbols, q_ce[0], q->d0, q->nof_rx_antennas, SRSLTE_PHICH_MAX_NSYMB, 1.0f, noise_estimate); + srslte_predecoding_single_multi(q_sf_symbols, q_ce[0], q->d0, NULL, q->nof_rx_antennas, SRSLTE_PHICH_MAX_NSYMB, 1.0f, noise_estimate); } else { srslte_predecoding_diversity_multi(q_sf_symbols, q_ce, x, q->nof_rx_antennas, q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB, 1.0f); srslte_layerdemap_diversity(x, q->d0, q->cell.nof_ports, SRSLTE_PHICH_MAX_NSYMB / q->cell.nof_ports); diff --git a/lib/src/phy/phch/pmch.c b/lib/src/phy/phch/pmch.c index c1c322f34..c7ec0b204 100644 --- a/lib/src/phy/phch/pmch.c +++ b/lib/src/phy/phch/pmch.c @@ -378,7 +378,7 @@ int srslte_pmch_decode_multi(srslte_pmch_t *q, } // No tx diversity in MBSFN - srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, q->nof_rx_antennas, cfg->nbits[0].nof_re, 1.0f, noise_estimate); + srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, NULL, q->nof_rx_antennas, cfg->nbits[0].nof_re, 1.0f, noise_estimate); if (SRSLTE_VERBOSE_ISDEBUG()) { DEBUG("SAVED FILE subframe.dat: received subframe symbols\n"); diff --git a/lib/src/phy/phch/pucch.c b/lib/src/phy/phch/pucch.c index b1317de3e..dd3977757 100644 --- a/lib/src/phy/phch/pucch.c +++ b/lib/src/phy/phch/pucch.c @@ -787,7 +787,7 @@ int srslte_pucch_decode(srslte_pucch_t* q, srslte_pucch_format_t format, } // Equalization - srslte_predecoding_single(q->z_tmp, q->ce, q->z, nof_re, 1.0f, noise_estimate); + srslte_predecoding_single(q->z_tmp, q->ce, q->z, NULL, nof_re, 1.0f, noise_estimate); // Perform ML-decoding float corr=0, corr_max=-1e9; diff --git a/lib/src/phy/phch/pusch.c b/lib/src/phy/phch/pusch.c index feb4e8b4f..aa049f7c0 100644 --- a/lib/src/phy/phch/pusch.c +++ b/lib/src/phy/phch/pusch.c @@ -596,7 +596,7 @@ int srslte_pusch_decode(srslte_pusch_t *q, } // Equalization - srslte_predecoding_single(q->d, q->ce, q->z, cfg->nbits.nof_re, 1.0f, noise_estimate); + srslte_predecoding_single(q->d, q->ce, q->z, NULL, cfg->nbits.nof_re, 1.0f, noise_estimate); // DFT predecoding srslte_dft_precoding(&q->dft_precoding, q->z, q->d, cfg->grant.L_prb, cfg->nbits.nof_symb); From 8cabfa82cf80a40d5c0de822f5ab59abc69e0e6c Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 28 Feb 2018 12:30:34 +0100 Subject: [PATCH 2/5] Added CSI report enable option in SRS UE --- lib/include/srslte/interfaces/ue_interfaces.h | 1 + srsue/src/main.cc | 3 +++ srsue/src/phy/phch_worker.cc | 1 + srsue/ue.conf.example | 4 ++++ 4 files changed, 9 insertions(+) diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index f18a6737b..735e1d02d 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -493,6 +493,7 @@ typedef struct { bool rssi_sensor_enabled; bool sic_pss_enabled; float rx_gain_offset; + bool pdsch_csi_enabled; } phy_args_t; diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 1cac2092d..cce7568b1 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -269,6 +269,9 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { bpo::value(&args->expert.phy.estimator_fil_w)->default_value(0.1), "Chooses the coefficients for the 3-tap channel estimator centered filter.") + ("expert.pdsch_csi_enabled", + bpo::value(&args->expert.phy.pdsch_csi_enabled)->default_value(false), + "Stores the Channel State Information and uses it for weightening the softbits. It is only compatible with TM1.") ("rf_calibration.tx_corr_dc_gain", bpo::value(&args->rf_cal.tx_corr_dc_gain)->default_value(0.0), "TX DC offset gain correction") diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 6a533759b..ce4fb5d7f 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -137,6 +137,7 @@ bool phch_worker::init(uint32_t max_prb, srslte::log *log_h, srslte::log *log_ph srslte_chest_dl_cfo_estimate_enable(&ue_dl.chest, phy->args->cfo_ref_mask!=0, phy->args->cfo_ref_mask); srslte_ue_ul_set_normalization(&ue_ul, true); srslte_ue_ul_set_cfo_enable(&ue_ul, true); + srslte_pdsch_enable_csi(&ue_dl.pdsch, phy->args->pdsch_csi_enabled); mem_initiated = true; diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index b8cc43c2e..a288470d3 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -173,6 +173,9 @@ enable = false # cfo_loop_pss_timeout: After the PSS estimation is below cfo_loop_pss_tol for cfo_loop_pss_timeout times consecutively, # RS adjustments are allowed. # +# pdsch_csi_enabled: Stores the Channel State Information and uses it for weightening the softbits. It is only +# compatible with TM1. It is False by default. +# ##################################################################### [expert] #ip_netmask = 255.255.255.0 @@ -196,6 +199,7 @@ enable = false #pregenerate_signals = false #metrics_csv_enable = false #metrics_csv_filename = /tmp/ue_metrics.csv +#pdsch_csi_enabled = true # Caution! Only TM1 supported! # CFO related values #cfo_integer_enabled = false From 2a69211f32a032918766d28a9fbdd624c11f1d2e Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 1 Mar 2018 13:59:01 +0100 Subject: [PATCH 3/5] SCH does not terminate all codeblocks if one fail. Also, SCH does not decode blocks with CRC=OK --- lib/include/srslte/phy/fec/softbuffer.h | 3 ++ lib/src/phy/fec/softbuffer.c | 46 ++++++++++++++++++++++--- lib/src/phy/phch/sch.c | 31 +++++++++++++---- 3 files changed, 69 insertions(+), 11 deletions(-) diff --git a/lib/include/srslte/phy/fec/softbuffer.h b/lib/include/srslte/phy/fec/softbuffer.h index a47cc7b96..3949134d8 100644 --- a/lib/include/srslte/phy/fec/softbuffer.h +++ b/lib/include/srslte/phy/fec/softbuffer.h @@ -42,6 +42,9 @@ typedef struct SRSLTE_API { uint32_t max_cb; int16_t **buffer_f; + uint8_t **data; + bool *cb_crc; + bool tb_crc; } srslte_softbuffer_rx_t; typedef struct SRSLTE_API { diff --git a/lib/src/phy/fec/softbuffer.c b/lib/src/phy/fec/softbuffer.c index 8efa937cb..9ed526825 100644 --- a/lib/src/phy/fec/softbuffer.c +++ b/lib/src/phy/fec/softbuffer.c @@ -47,32 +47,56 @@ int srslte_softbuffer_rx_init(srslte_softbuffer_rx_t *q, uint32_t nof_prb) { int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q != NULL) { - ret = SRSLTE_ERROR; - bzero(q, sizeof(srslte_softbuffer_rx_t)); ret = srslte_ra_tbs_from_idx(26, nof_prb); if (ret != SRSLTE_ERROR) { q->max_cb = (uint32_t) ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1; + ret = SRSLTE_ERROR; q->buffer_f = srslte_vec_malloc(sizeof(int16_t*) * q->max_cb); if (!q->buffer_f) { perror("malloc"); - return SRSLTE_ERROR; + goto clean_exit; } + q->data = srslte_vec_malloc(sizeof(uint8_t*) * q->max_cb); + if (!q->data) { + perror("malloc"); + goto clean_exit; + } + + q->cb_crc = srslte_vec_malloc(sizeof(bool) * q->max_cb); + if (!q->cb_crc) { + perror("malloc"); + goto clean_exit; + } + bzero(q->cb_crc, sizeof(bool) * q->max_cb); + // FIXME: Use HARQ buffer limitation based on UE category for (uint32_t i=0;imax_cb;i++) { q->buffer_f[i] = srslte_vec_malloc(sizeof(int16_t) * SOFTBUFFER_SIZE); if (!q->buffer_f[i]) { perror("malloc"); - return SRSLTE_ERROR; + goto clean_exit; + } + + q->data[i] = srslte_vec_malloc(sizeof(uint8_t) * 6144/8); + if (!q->data[i]) { + perror("malloc"); + goto clean_exit; } } //srslte_softbuffer_rx_reset(q); ret = SRSLTE_SUCCESS; } } + + clean_exit: + if (ret != SRSLTE_SUCCESS) { + srslte_softbuffer_rx_free(q); + } + return ret; } @@ -86,6 +110,17 @@ void srslte_softbuffer_rx_free(srslte_softbuffer_rx_t *q) { } free(q->buffer_f); } + if (q->data) { + for (uint32_t i=0;imax_cb;i++) { + if (q->data[i]) { + free(q->data[i]); + } + } + free(q->data); + } + if (q->cb_crc) { + free(q->cb_crc); + } bzero(q, sizeof(srslte_softbuffer_rx_t)); } } @@ -110,6 +145,9 @@ void srslte_softbuffer_rx_reset_cb(srslte_softbuffer_rx_t *q, uint32_t nof_cb) { } } } + if (q->cb_crc) { + bzero(q->cb_crc, sizeof(bool) * q->max_cb); + } } diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index e6b7d49b9..b679e00f9 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -336,14 +336,17 @@ bool decode_tb_cb(srslte_sch_t *q, decoder_input[i] = NULL; } + uint32_t remaining_cb = 0; for (int i=0;icb_crc[i]; + if (softbuffer->cb_crc[i] == false) { + remaining_cb ++; + } } srslte_tdec_reset(&q->decoder, cb_len); - uint32_t remaining_cb = nof_cb; - q->nof_iterations = 0; while(remaining_cb>0) { @@ -401,7 +404,8 @@ bool decode_tb_cb(srslte_sch_t *q, // CRC is OK if (!srslte_crc_checksum_byte(crc_ptr, q->cb_in, len_crc)) { - memcpy(&data[(cb_idx[i]*rlen)/8], q->cb_in, rlen/8 * sizeof(uint8_t)); + memcpy(softbuffer->data[cb_idx[i]], q->cb_in, rlen/8 * sizeof(uint8_t)); + softbuffer->cb_crc[cb_idx[i]] = true; q->nof_iterations += srslte_tdec_get_nof_iterations_cb(&q->decoder, i); @@ -418,15 +422,28 @@ bool decode_tb_cb(srslte_sch_t *q, cb_idx[i], remaining_cb, i, first_cb, nof_cb); q->nof_iterations += q->max_iterations; - q->nof_iterations /= (nof_cb-remaining_cb+1); - return false; + srslte_tdec_reset_cb(&q->decoder, i); + remaining_cb--; + decoder_input[i] = NULL; + cb_idx[i] = 0; } } } } + softbuffer->tb_crc = true; + for (int i = 0; i < nof_cb && softbuffer->tb_crc; i++) { + /* If one CB failed return false */ + softbuffer->tb_crc = softbuffer->cb_crc[i]; + } + if (softbuffer->tb_crc) { + for (int i = 0; i < nof_cb; i++) { + memcpy(&data[i * rlen / 8], softbuffer->data[i], rlen/8 * sizeof(uint8_t)); + } + } + q->nof_iterations /= nof_cb; - return true; + return softbuffer->tb_crc; } /** From ec901373d4487b591c2a735677f8f251c05f2bfb Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 1 Mar 2018 13:58:04 +0100 Subject: [PATCH 4/5] Correction ofo simd.h for AVX512 --- lib/include/srslte/phy/utils/simd.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/include/srslte/phy/utils/simd.h b/lib/include/srslte/phy/utils/simd.h index 3b5a00a8a..3223c18a7 100644 --- a/lib/include/srslte/phy/utils/simd.h +++ b/lib/include/srslte/phy/utils/simd.h @@ -707,11 +707,13 @@ static inline void srslte_simd_cf_storeu(float *re, float *im, simd_cf_t simdreg static inline simd_f_t srslte_simd_cf_re(simd_cf_t in) { simd_f_t out = in.re; +#ifndef LV_HAVE_AVX512 #ifdef LV_HAVE_AVX2 /* Permute for AVX registers (mis SSE registers) */ const __m256i idx = _mm256_setr_epi32(0, 2, 4, 6, 1, 3, 5, 7); out = _mm256_permutevar8x32_ps(out, idx); #endif /* LV_HAVE_AVX2 */ +#endif /* LV_HAVE_AVX512 */ return out; } From 962164277ad90b4c2f70dfab3b0571d6c8311926 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 6 Mar 2018 17:09:59 +0100 Subject: [PATCH 5/5] Normalize CSI to maximum. --- lib/src/phy/phch/pdsch.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index 4cfa5c75c..c59956a71 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -659,8 +659,13 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *c int16_t *e = q->e[codeword_idx]; if (q->csi_enabled) { + const uint32_t csi_max_idx = srslte_vec_max_fi(q->csi[codeword_idx], nbits->nof_bits / qm); + float csi_max = 1.0f; + if (csi_max_idx < nbits->nof_bits / qm) { + csi_max = q->csi[codeword_idx][csi_max_idx]; + } for (int i = 0; i < nbits->nof_bits / qm; i++) { - float csi = q->csi[codeword_idx][i]; + const float csi = q->csi[codeword_idx][i] / csi_max; for (int k = 0; k < qm; k++) { e[qm * i + k] = (int16_t) ((float) e[qm * i + k] * csi); }