From 94325d13d230293a4ef1160c265f8cefc1d678ed Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 17 Aug 2017 10:23:03 +0200 Subject: [PATCH] Scalable PDSCH with MAX_CODEWORDS PDSCH plus decoding threads for bitrate increase --- lib/examples/cell_measurement.c | 2 +- lib/examples/pdsch_ue.c | 2 +- lib/include/srslte/phy/phch/pdsch.h | 68 ++- lib/include/srslte/phy/phch/ra.h | 7 + lib/include/srslte/phy/phch/sch.h | 7 + lib/include/srslte/phy/ue/ue_dl.h | 7 +- lib/include/srslte/phy/utils/debug.h | 7 +- lib/src/phy/phch/pdsch.c | 530 +++++++++++------- lib/src/phy/phch/sch.c | 35 +- lib/src/phy/phch/test/dlsch_encode_test_mex.c | 8 +- lib/src/phy/phch/test/pdsch_test.c | 27 +- lib/src/phy/phch/test/pdsch_test_mex.c | 6 +- lib/src/phy/ue/ue_dl.c | 8 +- srsue/src/phy/phch_worker.cc | 2 +- 14 files changed, 485 insertions(+), 231 deletions(-) diff --git a/lib/examples/cell_measurement.c b/lib/examples/cell_measurement.c index 9c7856daa..90b963db8 100644 --- a/lib/examples/cell_measurement.c +++ b/lib/examples/cell_measurement.c @@ -320,7 +320,7 @@ int main(int argc, char **argv) { } else if (n == 0) { printf("CFO: %+6.4f kHz, SFO: %+6.4f kHz, NOI: %.2f, PDCCH-Det: %.3f\r", srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync)/1000, - srslte_sch_average_noi(&ue_dl.pdsch.dl_sch), + srslte_pdsch_average_noi(&ue_dl.pdsch), (float) ue_dl.nof_detected/nof_trials); nof_trials++; } else { diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index 1c6059d9f..24bdba55b 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -846,7 +846,7 @@ void *plot_thread_run(void *arg) { plot_scatter_setNewData(&pscatequal_pdcch, ue_dl.pdcch.d, 36*ue_dl.pdcch.nof_cce); } - plot_scatter_setNewData(&pscatequal, ue_dl.pdsch.d, nof_symbols); + plot_scatter_setNewData(&pscatequal, ue_dl.pdsch.d[0], nof_symbols); if (plot_sf_idx == 1) { if (prog_args.net_port_signal > 0) { diff --git a/lib/include/srslte/phy/phch/pdsch.h b/lib/include/srslte/phy/phch/pdsch.h index fc250a7d5..b4620be69 100644 --- a/lib/include/srslte/phy/phch/pdsch.h +++ b/lib/include/srslte/phy/phch/pdsch.h @@ -35,6 +35,13 @@ #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" @@ -48,11 +55,38 @@ #include "srslte/phy/phch/pdsch_cfg.h" typedef struct { - srslte_sequence_t seq[SRSLTE_NSUBFRAMES_X_FRAME]; - srslte_sequence_t seq2[SRSLTE_NSUBFRAMES_X_FRAME]; + srslte_sequence_t seq[SRSLTE_MAX_CODEWORDS][SRSLTE_NSUBFRAMES_X_FRAME]; 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; @@ -66,10 +100,8 @@ typedef struct SRSLTE_API { cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; /* Channel estimation (Rx only) */ cf_t *symbols[SRSLTE_MAX_PORTS]; /* PDSCH Encoded/Decoded Symbols */ cf_t *x[SRSLTE_MAX_LAYERS]; /* Layer mapped */ - cf_t *d; /* Modulated/Demodulated codeword 1 */ - cf_t *d2; /* Modulated/Demodulated codeword 2 */ - void *e; - void *e2; + cf_t *d[SRSLTE_MAX_CODEWORDS]; /* Modulated/Demodulated codewords */ + void *e[SRSLTE_MAX_CODEWORDS]; /* tx & rx objects */ srslte_modem_table_t mod[4]; @@ -77,8 +109,15 @@ typedef struct SRSLTE_API { // This is to generate the scrambling seq for multiple CRNTIs srslte_pdsch_user_t **users; - srslte_sch_t dl_sch; - + 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, @@ -151,7 +190,18 @@ SRSLTE_API int srslte_pdsch_decode_multi(srslte_pdsch_t *q, uint16_t rnti, uint8_t *data[SRSLTE_MAX_CODEWORDS]); -SRSLTE_API float srslte_pdsch_average_noi(srslte_pdsch_t *q); +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 void srslte_pdsch_set_max_noi(srslte_pdsch_t *q, int max_iter); + +SRSLTE_API float srslte_pdsch_average_noi(srslte_pdsch_t *q); SRSLTE_API uint32_t srslte_pdsch_last_noi(srslte_pdsch_t *q); diff --git a/lib/include/srslte/phy/phch/ra.h b/lib/include/srslte/phy/phch/ra.h index 5fab0f10b..8a025ad97 100644 --- a/lib/include/srslte/phy/phch/ra.h +++ b/lib/include/srslte/phy/phch/ra.h @@ -223,6 +223,13 @@ SRSLTE_API void srslte_ra_dl_grant_to_nbits_multi(srslte_ra_dl_grant_t *grant, srslte_ra_nbits_t *nbits, srslte_ra_nbits_t *nbits2); +SRSLTE_API void srslte_ra_dl_grant_to_nbits_multi(srslte_ra_dl_grant_t *grant, + uint32_t cfi, + srslte_cell_t cell, + uint32_t sf_idx, + srslte_ra_nbits_t *nbits, + srslte_ra_nbits_t *nbits2); + SRSLTE_API uint32_t srslte_ra_dl_approx_nof_re(srslte_cell_t cell, uint32_t nof_prb, uint32_t nof_ctrl_symbols); diff --git a/lib/include/srslte/phy/phch/sch.h b/lib/include/srslte/phy/phch/sch.h index 128cfea6f..4fa1b3b0f 100644 --- a/lib/include/srslte/phy/phch/sch.h +++ b/lib/include/srslte/phy/phch/sch.h @@ -96,6 +96,13 @@ SRSLTE_API int srslte_dlsch_encode(srslte_sch_t *q, uint8_t *data, uint8_t *e_bits); +SRSLTE_API 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); + SRSLTE_API int srslte_dlsch_encode_multi(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t softbuffers[SRSLTE_MAX_CODEWORDS], diff --git a/lib/include/srslte/phy/ue/ue_dl.h b/lib/include/srslte/phy/ue/ue_dl.h index 0c77ba911..88442b93d 100644 --- a/lib/include/srslte/phy/ue/ue_dl.h +++ b/lib/include/srslte/phy/ue/ue_dl.h @@ -191,12 +191,17 @@ SRSLTE_API int srslte_ue_dl_decode_rnti(srslte_ue_dl_t * q, uint32_t tti, uint16_t rnti); -SRSLTE_API int srslte_ue_dl_decode_rnti_multi(srslte_ue_dl_t * q, +SRSLTE_API int srslte_ue_dl_decode_rnti_multi(srslte_ue_dl_t * q, cf_t *input[SRSLTE_MAX_PORTS], uint8_t *data[SRSLTE_MAX_CODEWORDS], uint32_t tti, uint16_t rnti); +SRSLTE_API int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, + uint32_t *ri, + uint32_t *pmi, + float *current_sinr); + SRSLTE_API bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t n_prb_lowest, diff --git a/lib/include/srslte/phy/utils/debug.h b/lib/include/srslte/phy/utils/debug.h index e1021bc2a..e4b4756f8 100644 --- a/lib/include/srslte/phy/utils/debug.h +++ b/lib/include/srslte/phy/utils/debug.h @@ -63,6 +63,11 @@ SRSLTE_API extern int srslte_verbose; #define INFO(_fmt, ...) if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO) \ fprintf(stdout, "[INFO]: " _fmt, __VA_ARGS__) -#define ERROR(_fmt) fprintf(stderr, "%s.%d: " _fmt "\n", __FILE__, __LINE__) +#if CMAKE_BUILD_TYPE==Debug +/* In debug mode, it prints out the */ +#define ERROR(_fmt, ...) fprintf(stderr, "%s.%d: " _fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) +#else +#define ERROR(_fmt, ...) fprintf(stderr, "[ERROR in %s]:" _fmt "\n", __FUNCTION__, ##__VA_ARGS__) +#endif /* CMAKE_BUILD_TYPE==Debug */ #endif // DEBUG_H diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index 8cdfd0884..3ff2a910b 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -32,9 +32,13 @@ #include #include #include -#include -#include -#include + +#ifndef SRSLTE_SINGLE_THREAD + +#include +#include + +#endif /* SRSLTE_SINGLE_THREAD */ #include "prb_dl.h" #include "srslte/phy/phch/pdsch.h" @@ -60,6 +64,13 @@ 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); @@ -234,28 +245,38 @@ int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_ } srslte_modem_table_bytes(&q->mod[i]); } - - srslte_sch_init(&q->dl_sch); - - // Allocate int16_t for reception (LLRs) - q->e = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM)); - if (!q->e) { - goto clean; - } - - q->e2 = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM)); - if (!q->e) { - goto clean; - } - q->d = srslte_vec_malloc(sizeof(cf_t) * q->max_re); - if (!q->d) { - goto clean; - } + for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { + if (srslte_sch_init(&q->dl_sch[i])) { + ERROR("Initiating DL SCH"); + goto clean; + } - q->d2 = srslte_vec_malloc(sizeof(cf_t) * q->max_re); - if (!q->d) { - goto clean; + // Allocate int16_t for reception (LLRs) + q->e[i] = srslte_vec_malloc(sizeof(int16_t) * q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM)); + if (!q->e[i]) { + goto clean; + } + + q->d[i] = srslte_vec_malloc(sizeof(cf_t) * q->max_re); + if (!q->d[i]) { + 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 */ @@ -290,10 +311,11 @@ int srslte_pdsch_init_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t nof_ perror("malloc"); goto clean; } - - ret = SRSLTE_SUCCESS; - } - clean: + } + + ret = SRSLTE_SUCCESS; + + clean: if (ret == SRSLTE_ERROR) { srslte_pdsch_free(q); } @@ -315,18 +337,31 @@ int srslte_pdsch_init_rx_multi(srslte_pdsch_t *q, srslte_cell_t cell, uint32_t n void srslte_pdsch_free(srslte_pdsch_t *q) { int i; - if (q->e) { - free(q->e); - } - if (q->e2) { - free(q->e2); - } - if (q->d) { - free(q->d); - } - if (q->d2) { - free(q->d2); + 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]); + } + + if (q->d[i]) { + free(q->d[i]); + } + + /* Free sch objects */ + srslte_sch_free(&q->dl_sch[i]); + + } + for (i = 0; i < q->cell.nof_ports; i++) { if (q->x[i]) { free(q->x[i]); @@ -354,8 +389,6 @@ void srslte_pdsch_free(srslte_pdsch_t *q) { srslte_modem_table_free(&q->mod[i]); } - srslte_sch_free(&q->dl_sch); - bzero(q, sizeof(srslte_pdsch_t)); } @@ -454,18 +487,17 @@ int srslte_pdsch_cfg_multi(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_r * to execute, so shall be called once the final C-RNTI has been allocated for the session. */ int srslte_pdsch_set_rnti(srslte_pdsch_t *q, uint16_t rnti) { - uint32_t i; + uint32_t i, j; if (!q->users[rnti]) { q->users[rnti] = calloc(1, sizeof(srslte_pdsch_user_t)); if (q->users[rnti]) { for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - if (srslte_sequence_pdsch(&q->users[rnti]->seq[i], rnti, 0, 2 * i, q->cell.id, - q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { - return SRSLTE_ERROR; - } - if (srslte_sequence_pdsch(&q->users[rnti]->seq2[i], rnti, 1, 2 * i, q->cell.id, - q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { - return SRSLTE_ERROR; + for (j = 0; j < SRSLTE_MAX_CODEWORDS; j++) { + if (srslte_sequence_pdsch(&q->users[rnti]->seq[j][i], rnti, j, 2 * i, q->cell.id, + q->max_re * srslte_mod_bits_x_symbol(SRSLTE_MOD_64QAM))) { + ERROR("Generating scrambling sequence"); + return SRSLTE_ERROR; + } } } q->users[rnti]->sequence_generated = true; @@ -474,70 +506,194 @@ 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, + 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]; + srslte_ra_nbits_t *nbits = (codeword_idx == 0) ? &cfg->nbits : &cfg->nbits2; + srslte_ra_mcs_t *mcs = (codeword_idx == 0) ? &cfg->grant.mcs : &cfg->grant.mcs2; + + 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, + nbits->nof_re, nbits->nof_bits, (codeword_idx == 0) ? cfg->rv : cfg->rv2); + + /* Channel coding */ + if (srslte_dlsch_encode2(dl_sch, cfg, softbuffer, data, pdsch->e[codeword_idx], codeword_idx)) { + ERROR("Error encoding TB %d", codeword_idx); + return SRSLTE_ERROR; + } + + /* Bit scrambling */ + if (!pdsch->users[rnti]) { + srslte_sequence_t seq; + + if (srslte_sequence_pdsch(&seq, rnti, codeword_idx, 2 * cfg->sf_idx, pdsch->cell.id, nbits->nof_bits)) { + ERROR("Initialising scrambling sequence"); + return SRSLTE_ERROR; + } + srslte_scrambling_bytes(&seq, (uint8_t *) pdsch->e[codeword_idx], nbits->nof_bits); + srslte_sequence_free(&seq); + + } else { + srslte_scrambling_bytes(&pdsch->users[rnti]->seq[codeword_idx][cfg->sf_idx], + (uint8_t *) pdsch->e[codeword_idx], + nbits->nof_bits); + } + + /* Bit mapping */ + srslte_mod_modulate_bytes(&pdsch->mod[mcs->mod], + (uint8_t *) pdsch->e[codeword_idx], + pdsch->d[codeword_idx], nbits->nof_bits); + } + + 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, + 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]; + srslte_ra_nbits_t *nbits = (codeword_idx == 0) ? &cfg->nbits : &cfg->nbits2; + srslte_ra_mcs_t *mcs = (codeword_idx == 0) ? &cfg->grant.mcs : &cfg->grant.mcs2; + + if (nbits->nof_bits) { + 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, + nbits->nof_re, nbits->nof_bits, (codeword_idx == 0) ? cfg->rv : cfg->rv2); + + 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) { + srslte_scrambling_s_offset(&pdsch->users[rnti]->seq[codeword_idx][cfg->sf_idx], pdsch->e[codeword_idx], + 0, nbits->nof_bits); + } else { + srslte_sequence_t seq; + if (srslte_sequence_pdsch(&seq, rnti, codeword_idx, 2 * cfg->sf_idx, pdsch->cell.id, nbits->nof_bits)) { + ERROR("Initialising scrambling sequence"); + return SRSLTE_ERROR; + } + srslte_scrambling_s_offset(&seq, pdsch->e[codeword_idx], codeword_idx, nbits->nof_bits); + srslte_sequence_free(&seq); + } + + return srslte_dlsch_decode2(dl_sch, cfg, softbuffer, pdsch->e[codeword_idx], data, codeword_idx); + } + + 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]) { for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { - srslte_sequence_free(&q->users[rnti]->seq[i]); - srslte_sequence_free(&q->users[rnti]->seq2[i]); + for (int j = 0; j < SRSLTE_MAX_CODEWORDS; j++) { + srslte_sequence_free(&q->users[rnti]->seq[j][i]); + } } free(q->users[rnti]); - q->users[rnti] = NULL; + q->users[rnti] = NULL; } } -int srslte_pdsch_decode(srslte_pdsch_t *q, +int srslte_pdsch_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, - cf_t *sf_symbols, cf_t *ce[SRSLTE_MAX_PORTS], float noise_estimate, - uint16_t rnti, uint8_t *data) + cf_t *sf_symbols, cf_t *ce[SRSLTE_MAX_PORTS], float noise_estimate, + uint16_t rnti, uint8_t *data) { - cf_t *_sf_symbols[SRSLTE_MAX_PORTS]; + cf_t *_sf_symbols[SRSLTE_MAX_PORTS]; cf_t *_ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; - - _sf_symbols[0] = sf_symbols; + + _sf_symbols[0] = sf_symbols; for (int i=0;icell.nof_ports;i++) { - _ce[i][0] = ce[i]; + _ce[i][0] = ce[i]; } return srslte_pdsch_decode_multi(q, cfg, softbuffer, _sf_symbols, _ce, noise_estimate, rnti, &data); } /** Decodes the PDSCH from the received symbols */ -int srslte_pdsch_decode_multi(srslte_pdsch_t *q, +int srslte_pdsch_decode_multi(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t softbuffers[SRSLTE_MAX_CODEWORDS], - cf_t *sf_symbols[SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], float noise_estimate, + cf_t *sf_symbols[SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], float noise_estimate, uint16_t rnti, uint8_t *data[SRSLTE_MAX_CODEWORDS]) { /* Set pointers for layermapping & precoding */ - uint32_t i, n; + uint32_t i; cf_t *x[SRSLTE_MAX_LAYERS]; int ret = 0; if (q != NULL && sf_symbols != NULL && - data != NULL && + data != NULL && cfg != NULL) { - + INFO("Decoding PDSCH SF: %d, RNTI: 0x%x, Mod %s, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: [%d %d], C_prb=%d\n", - cfg->sf_idx, rnti, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, cfg->nbits.nof_re, + cfg->sf_idx, rnti, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, cfg->nbits.nof_re, cfg->nbits.nof_bits, cfg->rv, cfg->rv2, cfg->grant.nof_prb); - /* number of layers equals number of ports */ - for (i = 0; i < q->cell.nof_ports; i++) { - x[i] = q->x[i]; - } - memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports)); - for (int j=0;jnof_rx_antennas;j++) { /* extract symbols */ - n = srslte_pdsch_get(q, sf_symbols[j], q->symbols[j], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx); + int n = srslte_pdsch_get(q, sf_symbols[j], q->symbols[j], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx); if (n != cfg->nbits.nof_re) { fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits.nof_re, n); return SRSLTE_ERROR; } - + /* extract channel estimates */ for (i = 0; i < q->cell.nof_ports; i++) { n = srslte_pdsch_get(q, ce[i][j], q->ce[i][j], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx); @@ -545,25 +701,42 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q, fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits.nof_re, n); return SRSLTE_ERROR; } - } + } } INFO("PDSCH Layer demapper and predecode: mimo_type=%d, nof_layers=%d, nof_tb=%d\n", cfg->mimo_type, cfg->nof_layers, cfg->grant.nof_tb); 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, cfg->nbits.nof_re, noise_estimate); + srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d[0], q->nof_rx_antennas, cfg->nbits.nof_re, noise_estimate); } else { int nof_symbols [SRSLTE_MAX_CODEWORDS]; nof_symbols[0] = cfg->nbits.nof_re * cfg->grant.nof_tb / cfg->nof_layers; nof_symbols[1] = cfg->nbits2.nof_re * cfg->grant.nof_tb / cfg->nof_layers; - 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.nof_re, cfg->mimo_type, 0.0); - srslte_layerdemap_type(x, (cf_t *[SRSLTE_MAX_CODEWORDS]) {q->d, q->d2}, cfg->nof_layers, cfg->grant.nof_tb, - nof_symbols[0], nof_symbols, cfg->mimo_type); + if (cfg->nof_layers == cfg->grant.nof_tb) { + for (i = 0; i < cfg->nof_layers; i++) { + x[i] = q->d[i]; + } + + 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.nof_re, cfg->mimo_type, noise_estimate); + + } else { + /* number of layers equals number of ports */ + for (i = 0; i < cfg->nof_layers; i++) { + x[i] = q->x[i]; + } + memset(&x[cfg->nof_layers], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - cfg->nof_layers)); + + 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.nof_re, cfg->mimo_type, noise_estimate); + + srslte_layerdemap_type(x, q->d, cfg->nof_layers, cfg->grant.nof_tb, + nof_symbols[0], nof_symbols, cfg->mimo_type); + } } - + if (SRSLTE_VERBOSE_ISDEBUG()) { char filename[FILENAME_MAX]; for (int j = 0; j < q->nof_rx_antennas; j++) { @@ -586,47 +759,33 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q, DEBUG("SAVED FILE pdsch_symbols.dat: symbols after equalization\n",0); srslte_vec_save_file("pdsch_symbols.dat", q->d, cfg->nbits.nof_re*sizeof(cf_t)); } - - /* 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 - */ - if (cfg->nbits.nof_bits) { - INFO("Decoding CW 0 (%d bits)\n", cfg->nbits.nof_bits); - srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->e, cfg->nbits.nof_re); - if (q->users[rnti] && q->users[rnti]->sequence_generated) { - srslte_scrambling_s_offset(&q->users[rnti]->seq[cfg->sf_idx], q->e, 0, cfg->nbits.nof_bits); - } else { - srslte_sequence_t seq; - if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { - return SRSLTE_ERROR; - } - srslte_scrambling_s_offset(&seq, q->e, 0, cfg->nbits.nof_bits); - srslte_sequence_free(&seq); - } +#ifndef SRSLTE_SINGLE_THREAD - ret |= srslte_dlsch_decode2(&q->dl_sch, cfg, &softbuffers[0], q->e, data[0], 0); + 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); } - if (cfg->nbits2.nof_bits) { - INFO("Decoding CW 1 (%d bits)\n", cfg->nbits2.nof_bits); - srslte_demod_soft_demodulate_s(cfg->grant.mcs2.mod, q->d2, q->e2, cfg->nbits2.nof_re); - - if (q->users[rnti] && q->users[rnti]->sequence_generated) { - srslte_scrambling_s_offset(&q->users[rnti]->seq2[cfg->sf_idx], q->e2, 0, cfg->nbits2.nof_bits); - } else { - srslte_sequence_t seq; - if (srslte_sequence_pdsch(&seq, rnti, 1, 2 * cfg->sf_idx, q->cell.id, cfg->nbits2.nof_bits)) { - return SRSLTE_ERROR; - } - srslte_scrambling_s_offset(&seq, q->e2, 0, cfg->nbits2.nof_bits); - srslte_sequence_free(&seq); - } - - ret |= srslte_dlsch_decode2(&q->dl_sch, cfg, &softbuffers[1], q->e2, data[1], 1); + 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); @@ -634,7 +793,7 @@ int srslte_pdsch_decode_multi(srslte_pdsch_t *q, } return ret; - + } else { return SRSLTE_ERROR_INVALID_INPUTS; } @@ -688,13 +847,13 @@ int srslte_pdsch_ri_pmi_select(srslte_pdsch_t *q, *pmi = (best_sinr_1l > best_sinr_2l) ? best_pmi_1l : best_pmi_2l; } - /* Set current condition number */ - if (current_sinr != NULL) { + /* 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 { + } else { ERROR("Not implemented number of layers"); return SRSLTE_ERROR; } @@ -713,16 +872,16 @@ int srslte_pdsch_ri_pmi_select(srslte_pdsch_t *q, return SRSLTE_SUCCESS; } -int srslte_pdsch_encode(srslte_pdsch_t *q, +int srslte_pdsch_encode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, - uint8_t *data, uint16_t rnti, cf_t *sf_symbols[SRSLTE_MAX_PORTS]) + uint8_t *data, uint16_t rnti, cf_t *sf_symbols[SRSLTE_MAX_PORTS]) { - + int i; /* Set pointers for layermapping & precoding */ cf_t *x[SRSLTE_MAX_LAYERS]; - int ret = SRSLTE_ERROR_INVALID_INPUTS; - + int ret = SRSLTE_ERROR_INVALID_INPUTS; + if (q != NULL && cfg != NULL) { @@ -732,11 +891,11 @@ int srslte_pdsch_encode(srslte_pdsch_t *q, return SRSLTE_ERROR_INVALID_INPUTS; } } - + if (cfg->grant.mcs.tbs == 0) { - return SRSLTE_ERROR_INVALID_INPUTS; + return SRSLTE_ERROR_INVALID_INPUTS; } - + if (cfg->nbits.nof_re > q->max_re) { fprintf(stderr, "Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n", @@ -745,7 +904,7 @@ int srslte_pdsch_encode(srslte_pdsch_t *q, } INFO("Encoding PDSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", - cfg->sf_idx, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, + cfg->sf_idx, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, cfg->nbits.nof_re, cfg->nbits.nof_bits, cfg->rv); /* number of layers equals number of ports */ @@ -754,28 +913,28 @@ int srslte_pdsch_encode(srslte_pdsch_t *q, } memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports)); - if (srslte_dlsch_encode(&q->dl_sch, cfg, softbuffer, data, q->e)) { + if (srslte_dlsch_encode(&q->dl_sch[0], cfg, softbuffer, data, q->e[0])) { fprintf(stderr, "Error encoding TB\n"); return SRSLTE_ERROR; } /* scramble */ if (q->users[rnti] && q->users[rnti]->sequence_generated) { - srslte_scrambling_bytes(&q->users[rnti]->seq[cfg->sf_idx], (uint8_t*) q->e, cfg->nbits.nof_bits); + srslte_scrambling_bytes(&q->users[rnti]->seq[0][cfg->sf_idx], (uint8_t*) q->e[0], cfg->nbits.nof_bits); } else { srslte_sequence_t seq; if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { return SRSLTE_ERROR; } - srslte_scrambling_bytes(&seq, (uint8_t*) q->e, cfg->nbits.nof_bits); + srslte_scrambling_bytes(&seq, (uint8_t*) q->e[0], cfg->nbits.nof_bits); srslte_sequence_free(&seq); } - - srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->e, q->d, cfg->nbits.nof_bits); - + + srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->e[0], q->d[0], cfg->nbits.nof_bits); + /* TODO: only diversity supported */ if (q->cell.nof_ports > 1) { - srslte_layermap_diversity(q->d, x, q->cell.nof_ports, cfg->nbits.nof_re); + srslte_layermap_diversity(q->d[0], x, q->cell.nof_ports, cfg->nbits.nof_re); srslte_precoding_diversity(x, q->symbols, q->cell.nof_ports, cfg->nbits.nof_re / q->cell.nof_ports); } else { @@ -786,10 +945,10 @@ int srslte_pdsch_encode(srslte_pdsch_t *q, for (i = 0; i < q->cell.nof_ports; i++) { srslte_pdsch_put(q, q->symbols[i], sf_symbols[i], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx); } - + ret = SRSLTE_SUCCESS; - } - return ret; + } + return ret; } int srslte_pdsch_encode_multi(srslte_pdsch_t *q, @@ -822,73 +981,57 @@ int srslte_pdsch_encode_multi(srslte_pdsch_t *q, return SRSLTE_ERROR_INVALID_INPUTS; } - INFO("Encoding PDSCH SF: %d (TB 1), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", - cfg->sf_idx, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, - cfg->nbits.nof_re, cfg->nbits.nof_bits, cfg->rv); - if (cfg->grant.nof_tb > 1) { - INFO("Encoding PDSCH SF: %d (TB 2), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", - cfg->sf_idx, srslte_mod_string(cfg->grant.mcs2.mod), cfg->grant.mcs2.tbs, - cfg->nbits.nof_re, cfg->nbits.nof_bits, cfg->rv2); - } +#ifndef SRSLTE_SINGLE_THREAD - /* number of layers equals number of ports */ - for (i = 0; i < q->cell.nof_ports; i++) { - x[i] = q->x[i]; + 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); } - memset(&x[q->cell.nof_ports], 0, sizeof(cf_t *) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports)); - if (srslte_dlsch_encode_multi(&q->dl_sch, cfg, softbuffers, data, (uint8_t *[SRSLTE_MAX_CODEWORDS]) {q->e, q->e2})) { - fprintf(stderr, "Error encoding TB\n"); - return SRSLTE_ERROR; + 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; } - /* scramble */ - if (!q->users[rnti]) { - srslte_sequence_t seq; +#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 (cfg->nbits.nof_bits) { - if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { - return SRSLTE_ERROR; + if (q->cell.nof_ports > 1) { + int nof_symbols; + /* If number of layers is equal to transport blocks (codewords) skip layer mapping */ + if (cfg->nof_layers == cfg->grant.nof_tb) { + for (i = 0; i < cfg->nof_layers; i++) { + x[i] = q->d[i]; } - srslte_scrambling_bytes(&seq, (uint8_t *) q->e, cfg->nbits.nof_bits); - srslte_sequence_free(&seq); - } - - if (cfg->nbits2.nof_bits) { - if (srslte_sequence_pdsch(&seq, rnti, 1, 2 * cfg->sf_idx, q->cell.id, cfg->nbits2.nof_bits)) { - return SRSLTE_ERROR; + nof_symbols = cfg->nbits.nof_re; + } else { + /* Initialise layer map pointers */ + for (i = 0; i < cfg->nof_layers; i++) { + x[i] = q->x[i]; } - srslte_scrambling_bytes(&seq, (uint8_t *) q->e2, cfg->nbits2.nof_bits); - srslte_sequence_free(&seq); - } - } else { - if (cfg->nbits.nof_bits) { - srslte_scrambling_bytes(&q->users[rnti]->seq[cfg->sf_idx], (uint8_t *) q->e, cfg->nbits.nof_bits); - } + memset(&x[cfg->nof_layers], 0, sizeof(cf_t *) * (SRSLTE_MAX_LAYERS - cfg->nof_layers)); - if (cfg->nbits2.nof_bits) { - srslte_scrambling_bytes(&q->users[rnti]->seq2[cfg->sf_idx], (uint8_t *) q->e2, cfg->nbits2.nof_bits); + nof_symbols = srslte_layermap_type(q->d, x, cfg->grant.nof_tb, cfg->nof_layers, + (int[SRSLTE_MAX_CODEWORDS]) {cfg->nbits.nof_re, cfg->nbits2.nof_re}, cfg->mimo_type); } - } - - if (cfg->nbits.nof_bits) { - srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t *) q->e, q->d, cfg->nbits.nof_bits); - } - if (cfg->nbits2.nof_bits) { - srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs2.mod], (uint8_t *) q->e2, q->d2, cfg->nbits2.nof_bits); - } - - if (q->cell.nof_ports > 1) { - int nof_symbols = srslte_layermap_type((cf_t *[SRSLTE_MAX_CODEWORDS]) {q->d, q->d2}, x, cfg->grant.nof_tb, cfg->nof_layers, - (int[SRSLTE_MAX_CODEWORDS]) {cfg->nbits.nof_re, cfg->nbits2.nof_re}, cfg->mimo_type); + /* Precode */ srslte_precoding_type(x, q->symbols, cfg->nof_layers, q->cell.nof_ports, cfg->codebook_idx, nof_symbols, cfg->mimo_type); } else { - memcpy(q->symbols[0], q->d, cfg->nbits.nof_re * sizeof(cf_t)); + memcpy(q->symbols[0], q->d[0], cfg->nbits.nof_re * sizeof(cf_t)); } /* mapping to resource elements */ + for (i = 0; i < q->cell.nof_ports; i++) { srslte_pdsch_put(q, q->symbols[i], sf_symbols[i], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx); } @@ -898,13 +1041,18 @@ int srslte_pdsch_encode_multi(srslte_pdsch_t *q, return ret; } -float srslte_pdsch_average_noi(srslte_pdsch_t *q) -{ - return q->dl_sch.average_nof_iterations; +void srslte_pdsch_set_max_noi(srslte_pdsch_t *q, int max_iter) { + for (int cw = 0; cw < SRSLTE_MAX_CODEWORDS; cw++) { + srslte_sch_set_max_noi(&q->dl_sch[cw], max_iter); + } +} + +float srslte_pdsch_average_noi(srslte_pdsch_t *q) { + return q->dl_sch[0].average_nof_iterations; } uint32_t srslte_pdsch_last_noi(srslte_pdsch_t *q) { - return q->dl_sch.nof_iterations; + return q->dl_sch[0].nof_iterations; } diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index 1caacacc9..4b78f6228 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -528,24 +528,25 @@ int srslte_dlsch_decode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbu int16_t *e_bits, uint8_t *data, int codeword_idx) { uint32_t Nl = 1; + int ret = SRSLTE_ERROR; if (cfg->nof_layers != cfg->grant.nof_tb) { Nl = 2; } if (codeword_idx == 0) { - return decode_tb(q, softbuffer, &cfg->cb_segm, + ret = decode_tb(q, softbuffer, &cfg->cb_segm, cfg->grant.Qm*Nl, cfg->rv, cfg->nbits.nof_bits, e_bits, data); - } - - if (codeword_idx == 1) { - return decode_tb(q, softbuffer, &cfg->cb_segm2, + } else if (codeword_idx == 1) { + ret = decode_tb(q, softbuffer, &cfg->cb_segm2, cfg->grant.Qm2*Nl, cfg->rv2, cfg->nbits2.nof_bits, e_bits, data); + } else { + ERROR("Not implemented"); } - return SRSLTE_ERROR; + return ret; } /** @@ -567,6 +568,28 @@ int srslte_dlsch_encode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuf data, e_bits); } +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) { + int ret = SRSLTE_ERROR; + uint32_t Nl = 1; + + if (cfg->nof_layers != cfg->grant.nof_tb) { + Nl = 2; + } + + if(codeword_idx == 0) { + /* Codeword 1 shall be encoded */ + ret = encode_tb(q, softbuffer, &cfg->cb_segm, cfg->grant.Qm*Nl, cfg->rv, cfg->nbits.nof_bits, data, e_bits); + } else if(codeword_idx == 1) { + /* Codeword 2 shall be encoded */ + ret = encode_tb(q, softbuffer, &cfg->cb_segm2, cfg->grant.Qm2*Nl, cfg->rv2, cfg->nbits2.nof_bits, data, e_bits); + } else { + ERROR("Not implemented"); + } + + return ret; +} + int srslte_dlsch_encode_multi(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t softbuffers[SRSLTE_MAX_CODEWORDS], uint8_t *data[SRSLTE_MAX_CODEWORDS], uint8_t *e_bits[SRSLTE_MAX_CODEWORDS]) { diff --git a/lib/src/phy/phch/test/dlsch_encode_test_mex.c b/lib/src/phy/phch/test/dlsch_encode_test_mex.c index f391ab111..c6181d9c5 100644 --- a/lib/src/phy/phch/test/dlsch_encode_test_mex.c +++ b/lib/src/phy/phch/test/dlsch_encode_test_mex.c @@ -46,7 +46,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) int i; srslte_sch_t dlsch; srslte_pdsch_cfg_t cfg; - srslte_softbuffer_tx_t *softbuffers[SRSLTE_MAX_CODEWORDS]; + srslte_softbuffer_tx_t softbuffers[SRSLTE_MAX_CODEWORDS]; uint32_t nof_codewords = 1; memset(&dlsch, 0, sizeof(srslte_sch_t)); @@ -107,8 +107,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) /* Initialise buffers */ for (i = 0; i < nof_codewords; i++) { - softbuffers[i] = srslte_vec_malloc(sizeof(srslte_softbuffer_tx_t)); - if (srslte_softbuffer_tx_init(softbuffers[i], cell.nof_prb)) { + if (srslte_softbuffer_tx_init(&softbuffers[i], cell.nof_prb)) { mexErrMsgTxt("Error initiating DL-SCH soft buffer\n"); return; } @@ -151,8 +150,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) free(e_bits); free(e_bits_unpacked); for (i = 0; i < nof_codewords; i++) { - srslte_softbuffer_tx_free(softbuffers[i]); - free(softbuffers[i]); + srslte_softbuffer_tx_free(&softbuffers[i]); } return; } diff --git a/lib/src/phy/phch/test/pdsch_test.c b/lib/src/phy/phch/test/pdsch_test.c index 8c79cc836..180e689d6 100644 --- a/lib/src/phy/phch/test/pdsch_test.c +++ b/lib/src/phy/phch/test/pdsch_test.c @@ -155,7 +155,8 @@ int main(int argc, char **argv) { int ret = -1; struct timeval t[3]; srslte_softbuffer_tx_t softbuffers_tx[SRSLTE_MAX_CODEWORDS]; - + int M=10; + parse_args(argc,argv); /* Initialise to zeros */ @@ -265,6 +266,7 @@ int main(int argc, char **argv) { perror("srslte_vec_malloc"); goto quit; } + bzero(data[0], sizeof(uint8_t) * grant.mcs.tbs); } if (grant.mcs2.tbs) { @@ -273,6 +275,7 @@ int main(int argc, char **argv) { perror("srslte_vec_malloc"); goto quit; } + bzero(data[1], sizeof(uint8_t) * grant.mcs2.tbs); } if (srslte_pdsch_init_rx_multi(&pdsch_rx, cell, nof_rx_antennas)) { @@ -388,10 +391,18 @@ int main(int argc, char **argv) { } pdsch_cfg.rv = rv_idx; pdsch_cfg.rv2 = rv_idx2; - if (srslte_pdsch_encode_multi(&pdsch_tx, &pdsch_cfg, softbuffers_tx, data, rnti, tx_slot_symbols)) { - fprintf(stderr, "Error encoding PDSCH\n"); - goto quit; + gettimeofday(&t[1], NULL); + for (k = 0; k < M; k++) { + if (srslte_pdsch_encode_multi(&pdsch_tx, &pdsch_cfg, softbuffers_tx, data, rnti, tx_slot_symbols)) { + ERROR("Error encoding PDSCH"); + goto quit; + } } + gettimeofday(&t[2], NULL); + get_time_interval(t); + printf("ENCODED in %.2f (PHY bitrate=%.2f Mbps. Processing bitrate=%.2f Mbps)\n", + (float) t[0].tv_usec/M, (float) (grant.mcs.tbs + grant.mcs2.tbs)/1000.0f, + (float) (grant.mcs.tbs + grant.mcs2.tbs)*M/t[0].tv_usec); #ifdef DO_OFDM for (i = 0; i < cell.nof_ports; i++) { @@ -422,9 +433,9 @@ int main(int argc, char **argv) { } - int M=10; - int r=0; - srslte_sch_set_max_noi(&pdsch_rx.dl_sch, 10); + int r=0; + srslte_pdsch_set_max_noi(&pdsch_rx, 10); + gettimeofday(&t[1], NULL); for (k = 0; k < M; k++) { #ifdef DO_OFDM @@ -443,7 +454,7 @@ int main(int argc, char **argv) { } gettimeofday(&t[2], NULL); get_time_interval(t); - INFO("DECODED %s in %.2f (PHY bitrate=%.2f Mbps. Processing bitrate=%.2f Mbps)\n", r?"Error":"OK", + printf("DECODED %s in %.2f (PHY bitrate=%.2f Mbps. Processing bitrate=%.2f Mbps)\n", r?"Error":"OK", (float) t[0].tv_usec/M, (float) (grant.mcs.tbs + grant.mcs2.tbs)/1000.0f, (float) (grant.mcs.tbs + grant.mcs2.tbs)*M/t[0].tv_usec); if (r) { diff --git a/lib/src/phy/phch/test/pdsch_test_mex.c b/lib/src/phy/phch/test/pdsch_test_mex.c index 5093c326d..eb198bcbe 100644 --- a/lib/src/phy/phch/test/pdsch_test_mex.c +++ b/lib/src/phy/phch/test/pdsch_test_mex.c @@ -213,7 +213,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) return; } - srslte_sch_set_max_noi(&pdsch.dl_sch, max_iterations); + srslte_pdsch_set_max_noi(&pdsch, max_iterations); bool input_fft_allocated = false; int r=-1; @@ -291,10 +291,10 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) mexutils_write_cf(pdsch.symbols[0], &plhs[2], cfg.nbits.nof_re, 1); } if (nlhs >= 4) { - mexutils_write_cf(pdsch.d, &plhs[3], cfg.nbits.nof_re, 1); + mexutils_write_cf(pdsch.d[0], &plhs[3], cfg.nbits.nof_re, 1); } if (nlhs >= 5) { - mexutils_write_s(pdsch.e, &plhs[4], cfg.nbits.nof_bits, 1); + mexutils_write_s(pdsch.e[0], &plhs[4], cfg.nbits.nof_bits, 1); } if (nlhs >= 6) { uint32_t len = nof_antennas*cell.nof_ports*SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp); diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index c068f5899..85e851a3e 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -293,19 +293,19 @@ int srslte_ue_dl_cfg_grant_multi(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint32_t pmi = 0; /* Translates Precoding Information (pinfo) to Precoding matrix Index (pmi) as 3GPP 36.212 Table 5.3.3.1.5-4 */ - if (q->pdsch_cfg.mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) { - if (q->pdsch_cfg.grant.nof_tb == 1) { + if (mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) { + if (grant->nof_tb == 1) { if (pinfo > 0 && pinfo < 5) { pmi = pinfo - 1; } else { - ERROR("Not Implemented"); + ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", q->pdsch_cfg.grant.nof_tb, pinfo); return SRSLTE_ERROR; } } else { if (pinfo < 2) { pmi = pinfo; } else { - ERROR("Not Implemented"); + ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", q->pdsch_cfg.grant.nof_tb, pinfo); return SRSLTE_ERROR; } } diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index ef3640a40..fce931837 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -432,7 +432,7 @@ bool phch_worker::decode_pdsch_multi(srslte_ra_dl_grant_t *grant, uint8_t *paylo /* Set decoder iterations */ if (phy->args->pdsch_max_its > 0) { - srslte_sch_set_max_noi(&ue_dl.pdsch.dl_sch, phy->args->pdsch_max_its); + srslte_pdsch_set_max_noi(&ue_dl.pdsch, phy->args->pdsch_max_its); }