diff --git a/lib/include/srslte/phy/phch/pdsch.h b/lib/include/srslte/phy/phch/pdsch.h index b4620be69..9a9b16788 100644 --- a/lib/include/srslte/phy/phch/pdsch.h +++ b/lib/include/srslte/phy/phch/pdsch.h @@ -35,13 +35,6 @@ #ifndef PDSCH_ #define PDSCH_ -#ifndef SRSLTE_SINGLE_THREAD - -#include -#include - -#endif /* SRSLTE_SINGLE_THREAD */ - #include "srslte/config.h" #include "srslte/phy/common/phy_common.h" #include "srslte/phy/mimo/precoding.h" @@ -59,34 +52,6 @@ typedef struct { bool sequence_generated; } srslte_pdsch_user_t; -#ifndef SRSLTE_SINGLE_THREAD - -typedef struct { - /* Thread identifier: they must set before thread creation */ - uint32_t codeword_idx; - void *pdsch_ptr; - - /* Configuration Encoder/Decoder: they must be set before posting start semaphore */ - srslte_pdsch_cfg_t *cfg; - uint16_t rnti; - - /* Encoder/Decoder data pointers: they must be set before posting start semaphore */ - uint8_t *data; - void *softbuffer; - - /* Execution status */ - int ret_status; - - /* Semaphores */ - sem_t start; - sem_t finish; - - /* Thread kill flag */ - bool quit; -} srslte_pdsch_thread_args_t; - -#endif /* SRSLTE_SINGLE_THREAD */ - /* PDSCH object */ typedef struct SRSLTE_API { srslte_cell_t cell; @@ -111,13 +76,6 @@ typedef struct SRSLTE_API { srslte_sch_t dl_sch[SRSLTE_MAX_CODEWORDS]; -#ifndef SRSLTE_SINGLE_THREAD - - pthread_t threads[SRSLTE_MAX_CODEWORDS]; - srslte_pdsch_thread_args_t thread_args[SRSLTE_MAX_CODEWORDS]; - -#endif /* SRSLTE_SINGLE_THREAD */ - } srslte_pdsch_t; SRSLTE_API int srslte_pdsch_init(srslte_pdsch_t *q, @@ -190,14 +148,13 @@ SRSLTE_API int srslte_pdsch_decode_multi(srslte_pdsch_t *q, uint16_t rnti, uint8_t *data[SRSLTE_MAX_CODEWORDS]); -SRSLTE_API int srslte_pdsch_ri_pmi_select(srslte_pdsch_t *q, - srslte_pdsch_cfg_t *cfg, - cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], - float noise_estimate, - uint32_t nof_ce, - uint32_t *ri, - uint32_t *pmi, - float *current_sinr); +SRSLTE_API int srslte_pdsch_pmi_select(srslte_pdsch_t *q, + srslte_pdsch_cfg_t *cfg, + cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], + float noise_estimate, + uint32_t nof_ce, + uint32_t pmi[SRSLTE_MAX_LAYERS], + float sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS]); SRSLTE_API void srslte_pdsch_set_max_noi(srslte_pdsch_t *q, int max_iter); diff --git a/lib/include/srslte/phy/ue/ue_dl.h b/lib/include/srslte/phy/ue/ue_dl.h index 88442b93d..0fc8f9422 100644 --- a/lib/include/srslte/phy/ue/ue_dl.h +++ b/lib/include/srslte/phy/ue/ue_dl.h @@ -94,7 +94,12 @@ typedef struct SRSLTE_API { cf_t *sf_symbols_m[SRSLTE_MAX_PORTS]; cf_t *ce[SRSLTE_MAX_PORTS]; // compatibility cf_t *ce_m[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; - + + /* RI, PMI and SINR for MIMO statistics */ + float sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS]; + uint32_t pmi[SRSLTE_MAX_LAYERS]; + uint32_t ri; + srslte_dci_format_t dci_format; uint64_t pkt_errors; uint64_t pkts_total; diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index 3ff2a910b..31642751f 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -33,13 +33,6 @@ #include #include -#ifndef SRSLTE_SINGLE_THREAD - -#include -#include - -#endif /* SRSLTE_SINGLE_THREAD */ - #include "prb_dl.h" #include "srslte/phy/phch/pdsch.h" #include "srslte/phy/phch/sch.h" @@ -64,13 +57,6 @@ extern int indices[100000]; extern int indices_ptr; #endif -#ifndef SRSLTE_SINGLE_THREAD - -static void *srslte_pdsch_encode_thread (void *arg); -static void *srslte_pdsch_decode_thread (void *arg); - -#endif /* SRSLTE_SINGLE_THREAD */ - float srslte_pdsch_coderate(uint32_t tbs, uint32_t nof_re) { return (float) (tbs + 24)/(nof_re); @@ -263,20 +249,6 @@ int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_ goto clean; } -#ifndef SRSLTE_SINGLE_THREAD - if (sem_init(&q->thread_args[i].start, 0, 0)) { - ERROR("Creating semaphore"); - goto clean; - } - if (sem_init(&q->thread_args[i].finish, 0, 0)) { - ERROR("Creating semaphore"); - goto clean; - } - q->thread_args[i].codeword_idx = (uint32_t) i; - q->thread_args[i].pdsch_ptr = q; - pthread_create(&q->threads[i], NULL, (is_receiver) ? srslte_pdsch_decode_thread : srslte_pdsch_encode_thread, - (void *) &q->thread_args[i]); -#endif /* SRSLTE_SINGLE_THREAD */ } /* Layer mapped symbols memory allocation */ @@ -339,15 +311,6 @@ void srslte_pdsch_free(srslte_pdsch_t *q) { for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { -#ifndef SRSLTE_SINGLE_THREAD - /* Stop threads */ - q->thread_args[i].quit = true; - sem_post(&q->thread_args[i].start); - pthread_join(q->threads[i], NULL); - pthread_detach(q->threads[i]); - -#endif /* SRSLTE_SINGLE_THREAD */ - if (q->e[i]) { free(q->e[i]); } @@ -359,7 +322,6 @@ void srslte_pdsch_free(srslte_pdsch_t *q) { /* Free sch objects */ srslte_sch_free(&q->dl_sch[i]); - } for (i = 0; i < q->cell.nof_ports; i++) { @@ -506,7 +468,7 @@ int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) { return SRSLTE_SUCCESS; } -static inline int srslte_pdsch_codeword_encode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_t *cfg, +static int srslte_pdsch_codeword_encode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, uint16_t rnti, uint8_t *data, uint32_t codeword_idx) { srslte_sch_t *dl_sch = &pdsch->dl_sch[codeword_idx]; @@ -550,33 +512,7 @@ static inline int srslte_pdsch_codeword_encode(srslte_pdsch_t *pdsch, srslte_pds return SRSLTE_SUCCESS; } - -#ifndef SRSLTE_SINGLE_THREAD - -static void *srslte_pdsch_encode_thread(void *arg) { - srslte_pdsch_thread_args_t *q = (srslte_pdsch_thread_args_t *) arg; - uint32_t codeword_idx = q->codeword_idx; - - INFO("[PDSCH Encoder CW %d] waiting for data\n", codeword_idx); - - sem_wait(&q->start); - while (!q->quit) { - q->ret_status = srslte_pdsch_codeword_encode(q->pdsch_ptr, q->cfg, q->softbuffer, q->rnti, q->data, codeword_idx); - - /* Post finish semaphore */ - sem_post(&q->finish); - - /* Wait for next loop */ - sem_wait(&q->start); - } - - pthread_exit(NULL); - return q; -} - -#endif /* SRSLTE_SINGLE_THREAD */ - -static inline int srslte_pdsch_codeword_decode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_t *cfg, +static int srslte_pdsch_codeword_decode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint8_t *data, uint32_t codeword_idx) { srslte_sch_t *dl_sch = &pdsch->dl_sch[codeword_idx]; @@ -588,6 +524,10 @@ static inline int srslte_pdsch_codeword_decode(srslte_pdsch_t *pdsch, srslte_pds cfg->sf_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs, nbits->nof_re, nbits->nof_bits, (codeword_idx == 0) ? cfg->rv : cfg->rv2); + /* demodulate symbols + * The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation, + * thus we don't need tot set it in the LLRs normalization + */ srslte_demod_soft_demodulate_s(mcs->mod, pdsch->d[codeword_idx], pdsch->e[codeword_idx], cfg->nbits.nof_re); if (pdsch->users[rnti] && pdsch->users[rnti]->sequence_generated) { @@ -609,32 +549,6 @@ static inline int srslte_pdsch_codeword_decode(srslte_pdsch_t *pdsch, srslte_pds return SRSLTE_SUCCESS; } -#ifndef SRSLTE_SINGLE_THREAD - -static void *srslte_pdsch_decode_thread(void *arg) { - srslte_pdsch_thread_args_t *q = (srslte_pdsch_thread_args_t *) arg; - uint32_t codeword_idx = q->codeword_idx; - - INFO("[PDSCH Encoder CW %d] waiting for data\n", codeword_idx); - - sem_wait(&q->start); - while (!q->quit) { - q->ret_status = srslte_pdsch_codeword_decode(q->pdsch_ptr, q->cfg, q->softbuffer, q->rnti, q->data, codeword_idx); - - /* Post finish semaphore */ - sem_post(&q->finish); - - /* Wait for next loop */ - sem_wait(&q->start); - } - - pthread_exit(NULL); - return q; -} - -#endif /* SRSLTE_SINGLE_THREAD */ - - void srslte_pdsch_free_rnti(srslte_pdsch_t* q, uint16_t rnti) { if (q->users[rnti]) { @@ -760,32 +674,9 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q, srslte_vec_save_file("pdsch_symbols.dat", q->d, cfg->nbits.nof_re*sizeof(cf_t)); } -#ifndef SRSLTE_SINGLE_THREAD - - for (i = 0; i < cfg->grant.nof_tb; i++) { - srslte_pdsch_thread_args_t *thread_args = &q->thread_args[i]; - thread_args->cfg = cfg; - thread_args->softbuffer = &softbuffers[i]; - thread_args->data = data[i]; - thread_args->rnti = rnti; - sem_post(&thread_args->start); - } - - for (i = 0; i < cfg->grant.nof_tb; i++) { - srslte_pdsch_thread_args_t *thread_args = &q->thread_args[i]; - sem_wait(&thread_args->finish); - ret |= thread_args->ret_status; - } - -#else - /* demodulate symbols - * The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation, - * thus we don't need tot set it in the LLRs normalization - */ for (uint32_t tb = 0; tb < cfg->grant.nof_tb; tb ++) { ret |= srslte_pdsch_codeword_decode(q, cfg, &softbuffers[tb], rnti, data[tb], tb); } -#endif /* SRSLTE_SINGLE_THREAD */ if (SRSLTE_VERBOSE_ISDEBUG()) { DEBUG("SAVED FILE llr.dat: LLR estimates after demodulation and descrambling\n",0); @@ -799,71 +690,21 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q, } } -int srslte_pdsch_ri_pmi_select(srslte_pdsch_t *q, - srslte_pdsch_cfg_t *cfg, - cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], float noise_estimate, uint32_t nof_ce, - uint32_t *ri, uint32_t *pmi, - float *current_sinr) { - uint32_t best_pmi_1l; - uint32_t best_pmi_2l; - float sinr_1l[SRSLTE_MAX_CODEBOOKS]; - float sinr_2l[SRSLTE_MAX_CODEBOOKS]; - float best_sinr_1l = 0.0; - float best_sinr_2l = 0.0; - int n1, n2; +int srslte_pdsch_pmi_select(srslte_pdsch_t *q, + srslte_pdsch_cfg_t *cfg, + cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], float noise_estimate, uint32_t nof_ce, + uint32_t pmi[SRSLTE_MAX_LAYERS], float sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS]) { if (q->cell.nof_ports == 2 && q->nof_rx_antennas == 2) { - n1 = srslte_precoding_pmi_select(ce, nof_ce, noise_estimate, 1, &best_pmi_1l, sinr_1l); - if (n1 < 0) { - ERROR("PMI Select for 1 layer"); - return SRSLTE_ERROR; - } - - n2 = srslte_precoding_pmi_select(ce, nof_ce, noise_estimate, 2, &best_pmi_2l, sinr_2l); - if (n2 < 0) { - ERROR("PMI Select for 2 layer"); - return SRSLTE_ERROR; - } - - for (int i = 0; i < n1; i++) { - if (sinr_1l[i] > best_sinr_1l) { - best_sinr_1l = sinr_1l[i]; - } - } - - for (int i = 0; i < n2; i++) { - if (sinr_2l[i] > best_sinr_2l) { - best_sinr_2l = sinr_2l[i]; - } - } - - /* Set RI */ - if (ri != NULL) { - *ri = (best_sinr_1l > best_sinr_2l) ? 1 : 2; - } - - /* Set PMI */ - if (pmi != NULL) { - *pmi = (best_sinr_1l > best_sinr_2l) ? best_pmi_1l : best_pmi_2l; - } - - /* Set current SINR */ - if (current_sinr != NULL && cfg->mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) { - if (cfg->nof_layers == 1) { - *current_sinr = sinr_1l[cfg->codebook_idx]; - } else if (cfg->nof_layers == 2) { - *current_sinr = sinr_2l[cfg->codebook_idx - 1]; - } else { - ERROR("Not implemented number of layers"); - return SRSLTE_ERROR; + for (int nof_layers = 1; nof_layers <= cfg->nof_layers; nof_layers++ ) { + if (sinr[nof_layers - 1] && pmi) { + if (srslte_precoding_pmi_select(ce, nof_ce, noise_estimate, nof_layers, &pmi[nof_layers - 1], + sinr[nof_layers - 1]) < 0) { + ERROR("PMI Select for %d layers", nof_layers); + return SRSLTE_ERROR; + } } } - - /* Print Trace */ - if (ri != NULL && pmi != NULL && current_sinr != NULL) { - INFO("PDSCH Select RI=%d; PMI=%d; Current SINR=%.1fdB (nof_layers=%d, codebook_idx=%d)\n", *ri, *pmi, - 10*log10(*current_sinr), cfg->nof_layers, cfg->codebook_idx); - } } else { ERROR("Not implemented configuration"); return SRSLTE_ERROR_INVALID_INPUTS; @@ -981,28 +822,9 @@ int srslte_pdsch_encode_multi(srslte_pdsch_t *q, return SRSLTE_ERROR_INVALID_INPUTS; } -#ifndef SRSLTE_SINGLE_THREAD - - for (int tb = 0; tb < cfg->grant.nof_tb; tb++) { - srslte_pdsch_thread_args_t *thread_args = &q->thread_args[tb]; - thread_args->cfg = cfg; - thread_args->softbuffer = &softbuffers[tb]; - thread_args->data = data[tb]; - thread_args->rnti = rnti; - sem_post(&thread_args->start); - } - - for (int tb = 0; tb < cfg->grant.nof_tb; tb++) { - srslte_pdsch_thread_args_t *thread_args = &q->thread_args[tb]; - sem_wait(&thread_args->finish); - ret |= thread_args->ret_status; - } - -#else for (uint32_t tb = 0; tb < cfg->grant.nof_tb; tb ++) { ret |= srslte_pdsch_codeword_encode(q, cfg, &softbuffers[tb], rnti, data[tb], tb); } -#endif /* SRSLTE_SINGLE_THREAD */ if (q->cell.nof_ports > 1) { int nof_symbols; diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index 85e851a3e..3f51a3036 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -454,9 +454,58 @@ int srslte_ue_dl_decode_rnti_multi(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_POR int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint32_t *ri, uint32_t *pmi, float *current_sinr) { float noise_estimate = srslte_chest_dl_get_noise_estimate(&q->chest); - return srslte_pdsch_ri_pmi_select(&q->pdsch, &q->pdsch_cfg, q->ce_m, noise_estimate, - SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp), - ri, pmi, current_sinr); + float best_sinr = -INFINITY; + uint32_t best_pmi = 0, best_ri = 0; + + if (q->cell.nof_ports == 2 && q->nof_rx_antennas == 2) { + if (srslte_pdsch_pmi_select(&q->pdsch, &q->pdsch_cfg, q->ce_m, noise_estimate, + SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp), q->pmi, q->sinr)) { + ERROR("SINR calculation error"); + return SRSLTE_ERROR; + } + + /* Select the best Rank indicator (RI) and Precoding Matrix Indicator (PMI) */ + for (uint32_t nof_layers = 1; nof_layers <= q->pdsch_cfg.nof_layers; nof_layers++ ) { + if (q->sinr[nof_layers][q->pmi[nof_layers]] > best_sinr) { + best_sinr = q->sinr[nof_layers][q->pmi[nof_layers]]; + best_pmi = q->pmi[nof_layers]; + best_ri = nof_layers; + } + } + + /* Set RI */ + if (ri != NULL) { + *ri = best_ri; + } + + /* Set PMI */ + if (pmi != NULL) { + *pmi = best_pmi; + } + + /* Set current SINR */ + if (current_sinr != NULL && q->pdsch_cfg.mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) { + if (q->pdsch_cfg.nof_layers == 1) { + *current_sinr = q->sinr[0][q->pdsch_cfg.codebook_idx]; + } else if (q->pdsch_cfg.nof_layers == 2) { + *current_sinr = q->sinr[1][q->pdsch_cfg.codebook_idx - 1]; + } else { + ERROR("Not implemented number of layers"); + return SRSLTE_ERROR; + } + } + + /* Print Trace */ + if (ri != NULL && pmi != NULL && current_sinr != NULL) { + INFO("PDSCH Select RI=%d; PMI=%d; Current SINR=%.1fdB (nof_layers=%d, codebook_idx=%d)\n", *ri, *pmi, + 10*log10(*current_sinr), q->pdsch_cfg.nof_layers, q->pdsch_cfg.codebook_idx); + } + } else { + ERROR("Not implemented configuration"); + return SRSLTE_ERROR_INVALID_INPUTS; + } + + return SRSLTE_SUCCESS; } uint32_t srslte_ue_dl_get_ncce(srslte_ue_dl_t *q) {