diff --git a/lib/include/srslte/phy/phch/pdsch_nr.h b/lib/include/srslte/phy/phch/pdsch_nr.h index 641687f39..8218b252b 100644 --- a/lib/include/srslte/phy/phch/pdsch_nr.h +++ b/lib/include/srslte/phy/phch/pdsch_nr.h @@ -37,6 +37,14 @@ #include "srslte/phy/phch/sch_nr.h" #include "srslte/phy/scrambling/scrambling.h" +/** + * @brief PDSCH encoder and decoder initialization arguments + */ +typedef struct SRSLTE_API { + srslte_sch_nr_args_t sch; + bool measure_evm; +} srslte_pdsch_args_t; + /** * @brief PDSCH NR object */ @@ -50,6 +58,7 @@ typedef struct SRSLTE_API { cf_t* d[SRSLTE_MAX_CODEWORDS]; ///< PDSCH modulated bits cf_t* x[SRSLTE_MAX_LAYERS_NR]; ///< PDSCH modulated bits srslte_modem_table_t modem_tables[SRSLTE_MOD_NITEMS]; ///< Modulator tables + srslte_evm_buffer_t* evm_buffer; } srslte_pdsch_nr_t; /** @@ -61,9 +70,9 @@ typedef struct { float evm; } srslte_pdsch_res_nr_t; -SRSLTE_API int srslte_pdsch_nr_init_tx(srslte_pdsch_nr_t* q); +SRSLTE_API int srslte_pdsch_nr_init_tx(srslte_pdsch_nr_t* q, const srslte_pdsch_args_t* args); -SRSLTE_API int srslte_pdsch_nr_init_rx(srslte_pdsch_nr_t* q); +SRSLTE_API int srslte_pdsch_nr_init_rx(srslte_pdsch_nr_t* q, const srslte_pdsch_args_t* args); SRSLTE_API void srslte_pdsch_nr_free(srslte_pdsch_nr_t* q); diff --git a/lib/include/srslte/phy/phch/sch_nr.h b/lib/include/srslte/phy/phch/sch_nr.h index 8264cb2f0..5972dc733 100644 --- a/lib/include/srslte/phy/phch/sch_nr.h +++ b/lib/include/srslte/phy/phch/sch_nr.h @@ -65,11 +65,14 @@ typedef struct SRSLTE_API { srslte_ldpc_rm_t rx_rm; } srslte_sch_nr_t; +/** + * @brief SCH encoder and decoder initialization arguments + */ typedef struct SRSLTE_API { bool disable_simd; - bool use_flooded; - float scaling_factor; -} srslte_sch_nr_decoder_cfg_t; + bool decoder_use_flooded; + float decoder_scaling_factor; +} srslte_sch_nr_args_t; /** * @brief Common SCH configuration @@ -121,9 +124,9 @@ SRSLTE_API int srslte_dlsch_nr_fill_cfg(srslte_sch_nr_t* q, const srslte_sch_tb_t* tb, srslte_sch_nr_common_cfg_t* cfg); -SRSLTE_API int srslte_sch_nr_init_tx(srslte_sch_nr_t* q); +SRSLTE_API int srslte_sch_nr_init_tx(srslte_sch_nr_t* q, const srslte_sch_nr_args_t* cfg); -SRSLTE_API int srslte_sch_nr_init_rx(srslte_sch_nr_t* q, const srslte_sch_nr_decoder_cfg_t* cfg); +SRSLTE_API int srslte_sch_nr_init_rx(srslte_sch_nr_t* q, const srslte_sch_nr_args_t* cfg); SRSLTE_API int srslte_sch_nr_set_carrier(srslte_sch_nr_t* q, const srslte_carrier_nr_t* carrier); diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index a0ef75fc4..33e1f1be9 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -495,7 +495,7 @@ int srslte_pdsch_set_cell(srslte_pdsch_t* q, srslte_cell_t cell) // Resize EVM buffer, only for UE if (q->is_ue) { for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { - srslte_evm_buffer_resize(q->evm_buffer[i], cell.nof_prb); + srslte_evm_buffer_resize(q->evm_buffer[i], srslte_ra_tbs_from_idx(SRSLTE_RA_NOF_TBS_IDX - 1, cell.nof_prb)); } } diff --git a/lib/src/phy/phch/pdsch_nr.c b/lib/src/phy/phch/pdsch_nr.c index 93de3077d..5ce77313e 100644 --- a/lib/src/phy/phch/pdsch_nr.c +++ b/lib/src/phy/phch/pdsch_nr.c @@ -22,30 +22,33 @@ #include "srslte/phy/common/phy_common_nr.h" #include "srslte/phy/phch/ra_nr.h" -int pdsch_nr_init_common(srslte_pdsch_nr_t* q) +int pdsch_nr_init_common(srslte_pdsch_nr_t* q, const srslte_pdsch_args_t* args) { for (srslte_mod_t mod = SRSLTE_MOD_BPSK; mod < SRSLTE_MOD_NITEMS; mod++) { if (srslte_modem_table_lte(&q->modem_tables[mod], mod) < SRSLTE_SUCCESS) { ERROR("Error initialising modem table for %s\n", srslte_mod_string(mod)); return SRSLTE_ERROR; } + if (args->measure_evm) { + srslte_modem_table_bytes(&q->modem_tables[mod]); + } } return SRSLTE_SUCCESS; } -int srslte_pdsch_nr_init_tx(srslte_pdsch_nr_t* q) +int srslte_pdsch_nr_init_tx(srslte_pdsch_nr_t* q, const srslte_pdsch_args_t* args) { if (q == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; } - if (pdsch_nr_init_common(q) < SRSLTE_SUCCESS) { + if (pdsch_nr_init_common(q, args) < SRSLTE_SUCCESS) { return SRSLTE_ERROR; } - if (srslte_sch_nr_init_tx(&q->sch)) { + if (srslte_sch_nr_init_tx(&q->sch, &args->sch)) { ERROR("Initialising SCH\n"); return SRSLTE_ERROR; } @@ -53,24 +56,30 @@ int srslte_pdsch_nr_init_tx(srslte_pdsch_nr_t* q) return SRSLTE_SUCCESS; } -int srslte_pdsch_nr_init_rx(srslte_pdsch_nr_t* q) +int srslte_pdsch_nr_init_rx(srslte_pdsch_nr_t* q, const srslte_pdsch_args_t* args) { - if (q == NULL) { + if (q == NULL || args == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; } - if (pdsch_nr_init_common(q) < SRSLTE_SUCCESS) { + if (pdsch_nr_init_common(q, args) < SRSLTE_SUCCESS) { return SRSLTE_ERROR; } - srslte_sch_nr_decoder_cfg_t decoder_cfg = {}; - decoder_cfg.disable_simd = true; - if (srslte_sch_nr_init_rx(&q->sch, &decoder_cfg)) { + if (srslte_sch_nr_init_rx(&q->sch, &args->sch)) { ERROR("Initialising SCH\n"); return SRSLTE_ERROR; } + if (args->measure_evm) { + q->evm_buffer = srslte_evm_buffer_alloc(8); + if (q->evm_buffer == NULL) { + ERROR("Initialising EVM\n"); + return SRSLTE_ERROR; + } + } + return SRSLTE_SUCCESS; } @@ -132,6 +141,10 @@ int srslte_pdsch_nr_set_carrier(srslte_pdsch_nr_t* q, return SRSLTE_ERROR; } + if (q->evm_buffer != NULL) { + srslte_evm_buffer_resize(q->evm_buffer, SRSLTE_SLOT_LEN_RE_NR(q->max_prb) * SRSLTE_MAX_QM); + } + return SRSLTE_SUCCESS; } @@ -162,6 +175,10 @@ void srslte_pdsch_nr_free(srslte_pdsch_nr_t* q) for (srslte_mod_t mod = SRSLTE_MOD_BPSK; mod < SRSLTE_MOD_NITEMS; mod++) { srslte_modem_table_free(&q->modem_tables[mod]); } + + if (q->evm_buffer != NULL) { + srslte_evm_free(q->evm_buffer); + } } /** @@ -498,6 +515,12 @@ static inline int pdsch_nr_decode_codeword(srslte_pdsch_nr_t* q, if (srslte_demod_soft_demodulate_b(tb->mod, q->d[tb->cw_idx], llr, tb->nof_re)) { return SRSLTE_ERROR; } + + // EVM + if (q->evm_buffer != NULL) { + res->evm = srslte_evm_run_b(q->evm_buffer, &q->modem_tables[tb->mod], q->d[tb->cw_idx], llr, tb->nof_bits); + } + // Change LLR sign for (uint32_t i = 0; i < tb->nof_bits; i++) { llr[i] = -llr[i]; diff --git a/lib/src/phy/phch/pusch.c b/lib/src/phy/phch/pusch.c index 743cc97b8..5b8674a3d 100644 --- a/lib/src/phy/phch/pusch.c +++ b/lib/src/phy/phch/pusch.c @@ -249,7 +249,7 @@ int srslte_pusch_set_cell(srslte_pusch_t* q, srslte_cell_t cell) // Resize EVM buffer, only for eNb if (!q->is_ue && q->evm_buffer) { - srslte_evm_buffer_resize(q->evm_buffer, cell.nof_prb); + srslte_evm_buffer_resize(q->evm_buffer, srslte_ra_tbs_from_idx(SRSLTE_RA_NOF_TBS_IDX - 1, cell.nof_prb)); } q->cell = cell; diff --git a/lib/src/phy/phch/sch_nr.c b/lib/src/phy/phch/sch_nr.c index b3cbf69de..5f70eb0e1 100644 --- a/lib/src/phy/phch/sch_nr.c +++ b/lib/src/phy/phch/sch_nr.c @@ -190,7 +190,7 @@ static inline int sch_nr_init_common(srslte_sch_nr_t* q) return SRSLTE_SUCCESS; } -int srslte_sch_nr_init_tx(srslte_sch_nr_t* q) +int srslte_sch_nr_init_tx(srslte_sch_nr_t* q, const srslte_sch_nr_args_t* args) { int ret = sch_nr_init_common(q); if (ret < SRSLTE_SUCCESS) { @@ -198,6 +198,11 @@ int srslte_sch_nr_init_tx(srslte_sch_nr_t* q) } srslte_ldpc_encoder_type_t encoder_type = SRSLTE_LDPC_ENCODER_C; +#ifdef LV_HAVE_AVX2 + if (!args->disable_simd) { + encoder_type = SRSLTE_LDPC_ENCODER_AVX2; + } +#endif // LV_HAVE_AVX2 // Iterate over all possible lifting sizes for (uint16_t ls = 0; ls <= MAX_LIFTSIZE; ls++) { @@ -240,7 +245,7 @@ int srslte_sch_nr_init_tx(srslte_sch_nr_t* q) return SRSLTE_SUCCESS; } -int srslte_sch_nr_init_rx(srslte_sch_nr_t* q, const srslte_sch_nr_decoder_cfg_t* decoder_cfg) +int srslte_sch_nr_init_rx(srslte_sch_nr_t* q, const srslte_sch_nr_args_t* args) { int ret = sch_nr_init_common(q); if (ret < SRSLTE_SUCCESS) { @@ -248,9 +253,9 @@ int srslte_sch_nr_init_rx(srslte_sch_nr_t* q, const srslte_sch_nr_decoder_cfg_t* } srslte_ldpc_decoder_type_t decoder_type = SRSLTE_LDPC_DECODER_C; - if (decoder_cfg->use_flooded) { + if (args->decoder_use_flooded) { #ifdef LV_HAVE_AVX2 - if (decoder_cfg->disable_simd) { + if (args->disable_simd) { decoder_type = SRSLTE_LDPC_DECODER_C_FLOOD; } else { decoder_type = SRSLTE_LDPC_DECODER_C_AVX2_FLOOD; @@ -260,13 +265,13 @@ int srslte_sch_nr_init_rx(srslte_sch_nr_t* q, const srslte_sch_nr_decoder_cfg_t* #endif // LV_HAVE_AVX2 } else { #ifdef LV_HAVE_AVX2 - if (!decoder_cfg->disable_simd) { + if (!args->disable_simd) { decoder_type = SRSLTE_LDPC_DECODER_C_AVX2; } #endif // LV_HAVE_AVX2 } - float scaling_factor = isnormal(decoder_cfg->scaling_factor) ? decoder_cfg->scaling_factor : 0.75f; + float scaling_factor = isnormal(args->decoder_scaling_factor) ? args->decoder_scaling_factor : 0.75f; // Iterate over all possible lifting sizes for (uint16_t ls = 0; ls <= MAX_LIFTSIZE; ls++) { diff --git a/lib/src/phy/phch/test/dlsch_nr_test.c b/lib/src/phy/phch/test/dlsch_nr_test.c index e752150ce..b41b04324 100644 --- a/lib/src/phy/phch/test/dlsch_nr_test.c +++ b/lib/src/phy/phch/test/dlsch_nr_test.c @@ -108,8 +108,8 @@ int main(int argc, char** argv) goto clean_exit; } - srslte_sch_nr_decoder_cfg_t decoder_cfg = {}; - decoder_cfg.disable_simd = false; + srslte_sch_nr_args_t decoder_cfg = {}; + decoder_cfg.disable_simd = false; if (srslte_sch_nr_init_rx(&sch_nr_rx, &decoder_cfg) < SRSLTE_SUCCESS) { ERROR("Error initiating SCH NR for Rx\n"); goto clean_exit; diff --git a/lib/src/phy/phch/test/pdsch_nr_test.c b/lib/src/phy/phch/test/pdsch_nr_test.c index eb82e7d7e..1ad301459 100644 --- a/lib/src/phy/phch/test/pdsch_nr_test.c +++ b/lib/src/phy/phch/test/pdsch_nr_test.c @@ -99,12 +99,16 @@ int main(int argc, char** argv) goto clean_exit; } - if (srslte_pdsch_nr_init_tx(&pdsch_tx) < SRSLTE_SUCCESS) { + srslte_pdsch_args_t pdsch_args = {}; + pdsch_args.sch.disable_simd = true; + pdsch_args.measure_evm = true; + + if (srslte_pdsch_nr_init_tx(&pdsch_tx, &pdsch_args) < SRSLTE_SUCCESS) { ERROR("Error initiating PDSCH for Tx\n"); goto clean_exit; } - if (srslte_pdsch_nr_init_rx(&pdsch_rx) < SRSLTE_SUCCESS) { + if (srslte_pdsch_nr_init_rx(&pdsch_rx, &pdsch_args) < SRSLTE_SUCCESS) { ERROR("Error initiating SCH NR for Rx\n"); goto clean_exit; } @@ -225,6 +229,11 @@ int main(int argc, char** argv) goto clean_exit; } + if (pdsch_res->evm > 0.001f) { + ERROR("Error PDSCH EVM is too high %f\n", pdsch_res->evm); + goto clean_exit; + } + float mse = 0.0f; uint32_t nof_re = srslte_ra_dl_nr_slot_nof_re(&pdsch_cfg, &pdsch_grant); for (uint32_t i = 0; i < pdsch_grant.nof_layers; i++) { @@ -260,7 +269,7 @@ int main(int argc, char** argv) goto clean_exit; } - printf("n_prb=%d; mcs=%d; TBS=%d; PASSED!\n", n_prb, mcs, pdsch_grant.tb[0].tbs); + printf("n_prb=%d; mcs=%d; TBS=%d; EVM=%f; PASSED!\n", n_prb, mcs, pdsch_grant.tb[0].tbs, pdsch_res[0].evm); } }