From b8a9a7fc70233c6d54c3acaab7e344db40d8aade Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 12 Apr 2021 11:23:27 +0200 Subject: [PATCH] Review soft demodulator zero check --- lib/include/srsran/phy/modem/demod_soft.h | 10 +++ lib/src/phy/modem/demod_soft.c | 31 ++++++- lib/src/phy/modem/test/soft_demod_test.c | 99 ++++++++++++----------- lib/src/phy/phch/pdsch_nr.c | 2 +- 4 files changed, 90 insertions(+), 52 deletions(-) diff --git a/lib/include/srsran/phy/modem/demod_soft.h b/lib/include/srsran/phy/modem/demod_soft.h index ea3337942..64d680b28 100644 --- a/lib/include/srsran/phy/modem/demod_soft.h +++ b/lib/include/srsran/phy/modem/demod_soft.h @@ -33,4 +33,14 @@ SRSRAN_API int srsran_demod_soft_demodulate_s(srsran_mod_t modulation, const cf_ SRSRAN_API int srsran_demod_soft_demodulate_b(srsran_mod_t modulation, const cf_t* symbols, int8_t* llr, int nsymbols); +/** + * @brief Soft-demodulates complex symbols into 8-bit LLR. It forces zero symbols produce zero LLRs. + * @param modulation Modulation + * @param symbols Complex symbols + * @param llr 8-bit LLRs + * @param nsymbols Number of symbols + * @return SRSLTE_SUCCESS if the provided pointers are valid, SRSLTE_ERROR code otherwise + */ +SRSRAN_API int srsran_demod_soft_demodulate2_b(srsran_mod_t modulation, const cf_t* symbols, int8_t* llr, int nsymbols); + #endif // SRSRAN_DEMOD_SOFT_H diff --git a/lib/src/phy/modem/demod_soft.c b/lib/src/phy/modem/demod_soft.c index a81bf1eaf..b7ef05d42 100644 --- a/lib/src/phy/modem/demod_soft.c +++ b/lib/src/phy/modem/demod_soft.c @@ -883,6 +883,9 @@ int srsran_demod_soft_demodulate(srsran_mod_t modulation, const cf_t* symbols, f int srsran_demod_soft_demodulate_s(srsran_mod_t modulation, const cf_t* symbols, short* llr, int nsymbols) { + if (symbols == NULL || llr == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } switch (modulation) { case SRSRAN_MOD_BPSK: demod_bpsk_lte_s(symbols, llr, nsymbols); @@ -908,6 +911,9 @@ int srsran_demod_soft_demodulate_s(srsran_mod_t modulation, const cf_t* symbols, int srsran_demod_soft_demodulate_b(srsran_mod_t modulation, const cf_t* symbols, int8_t* llr, int nsymbols) { + if (symbols == NULL || llr == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } switch (modulation) { case SRSRAN_MOD_BPSK: demod_bpsk_lte_b(symbols, llr, nsymbols); @@ -926,17 +932,34 @@ int srsran_demod_soft_demodulate_b(srsran_mod_t modulation, const cf_t* symbols, break; default: ERROR("Invalid modulation %d", modulation); - return -1; + return SRSRAN_ERROR; + } + return SRSRAN_SUCCESS; +} + +int srsran_demod_soft_demodulate2_b(srsran_mod_t modulation, const cf_t* symbols, int8_t* llr, int nsymbols) +{ + if (symbols == NULL || llr == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + if (srsran_demod_soft_demodulate_b(modulation, symbols, llr, nsymbols) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; } + // If the number of bits is 2 or less, this is unnecessary + if (modulation < SRSRAN_MOD_16QAM) { + return SRSRAN_SUCCESS; + } + + // Iterate all symbols seeking for zero LLR uint32_t nof_bits_x_symbol = srsran_mod_bits_x_symbol(modulation); for (uint32_t i = 0; i < nsymbols; i++) { - if (!isnormal(__real__ symbols[i]) || !isnormal(__imag__ symbols[i])) { + if (symbols[i] == 0.0f) { for (uint32_t j = 0; j < nof_bits_x_symbol; j++) { llr[i * nof_bits_x_symbol + j] = 0; } } } - return 0; -} + return SRSRAN_SUCCESS; +} \ No newline at end of file diff --git a/lib/src/phy/modem/test/soft_demod_test.c b/lib/src/phy/modem/test/soft_demod_test.c index ee3ee49f3..3465098bb 100644 --- a/lib/src/phy/modem/test/soft_demod_test.c +++ b/lib/src/phy/modem/test/soft_demod_test.c @@ -10,11 +10,8 @@ * */ -#include -#include #include #include -#include #include #include #include @@ -25,7 +22,7 @@ static uint32_t nof_frames = 10; static uint32_t num_bits = 1000; static srsran_mod_t modulation = SRSRAN_MOD_NITEMS; -void usage(char* prog) +static void usage(char* prog) { printf("Usage: %s [nfv] -m modulation (1: BPSK, 2: QPSK, 4: QAM16, 6: QAM64)\n", prog); printf("\t-n num_bits [Default %d]\n", num_bits); @@ -33,7 +30,7 @@ void usage(char* prog) printf("\t-v srsran_verbose [Default None]\n"); } -void parse_args(int argc, char** argv) +static void parse_args(int argc, char** argv) { int opt; while ((opt = getopt(argc, argv, "nmvf")) != -1) { @@ -82,33 +79,16 @@ void parse_args(int argc, char** argv) } } -float mse_threshold() -{ - switch (modulation) { - case SRSRAN_MOD_BPSK: - return 1.0e-6; - case SRSRAN_MOD_QPSK: - return 1.0e-6; - case SRSRAN_MOD_16QAM: - return 0.11; - case SRSRAN_MOD_64QAM: - return 0.19; - case SRSRAN_MOD_256QAM: - return 0.3; - default: - return -1.0f; - } -} - int main(int argc, char** argv) { - int i; srsran_modem_table_t mod; - uint8_t * input, *output; - cf_t* symbols; - float* llr; - short* llr_s; - int8_t* llr_b; + uint8_t* input = NULL; + cf_t* symbols = NULL; + float* llr = NULL; + short* llr_s = NULL; + int8_t* llr_b = NULL; + int8_t* llr_b2 = NULL; + srsran_random_t random_gen = srsran_random_init(0); parse_args(argc, argv); @@ -127,11 +107,6 @@ int main(int argc, char** argv) perror("malloc"); exit(-1); } - output = srsran_vec_u8_malloc(num_bits); - if (!output) { - perror("malloc"); - exit(-1); - } symbols = srsran_vec_cf_malloc(num_bits / mod.nbits_x_symbol); if (!symbols) { perror("malloc"); @@ -156,17 +131,21 @@ int main(int argc, char** argv) exit(-1); } - /* generate random data */ - srand(0); + llr_b2 = srsran_vec_i8_malloc(num_bits); + if (!llr_b2) { + perror("malloc"); + exit(-1); + } int ret = -1; struct timeval t[3]; - float mean_texec = 0.0; - float mean_texec_s = 0.0; - float mean_texec_b = 0.0; + float mean_texec = 0.0f; + float mean_texec_s = 0.0f; + float mean_texec_b = 0.0f; + float mean_texec_b2 = 0.0f; for (int n = 0; n < nof_frames; n++) { - for (i = 0; i < num_bits; i++) { - input[i] = rand() % 2; + for (int i = 0; i < num_bits; i++) { + input[i] = srsran_random_uniform_int_dist(random_gen, 0, 1); } /* modulate */ @@ -200,6 +179,15 @@ int main(int argc, char** argv) mean_texec_b = SRSRAN_VEC_CMA((float)t[0].tv_usec, mean_texec_b, n - 1); } + gettimeofday(&t[1], NULL); + srsran_demod_soft_demodulate2_b(modulation, symbols, llr_b2, num_bits / mod.nbits_x_symbol); + gettimeofday(&t[2], NULL); + get_time_interval(t); + + if (n > 0) { + mean_texec_b2 = SRSRAN_VEC_CMA((float)t[0].tv_usec, mean_texec_b2, n - 1); + } + if (SRSRAN_VERBOSE_ISDEBUG()) { printf("bits="); srsran_vec_fprint_b(stdout, input, num_bits); @@ -215,12 +203,27 @@ int main(int argc, char** argv) printf("llr_b="); srsran_vec_fprint_bs(stdout, llr_b, num_bits); + + printf("llr_b2="); + srsran_vec_fprint_bs(stdout, llr_b2, num_bits); } // Check demodulation errors - for (int i = 0; i < num_bits; i++) { - if (input[i] != (llr[i] > 0 ? 1 : 0)) { - printf("Error in bit %d\n", i); + for (int j = 0; j < num_bits; j++) { + if (input[j] != (llr[j] > 0 ? 1 : 0)) { + ERROR("Error in bit %d\n", j); + goto clean_exit; + } + if (input[j] != (llr_s[j] > 0 ? 1 : 0)) { + ERROR("Error in bit %d\n", j); + goto clean_exit; + } + if (input[j] != (llr_b[j] > 0 ? 1 : 0)) { + ERROR("Error in bit %d\n", j); + goto clean_exit; + } + if (input[j] != (llr_b2[j] > 0 ? 1 : 0)) { + ERROR("Error in bit %d\n", j); goto clean_exit; } } @@ -228,21 +231,23 @@ int main(int argc, char** argv) ret = 0; clean_exit: + srsran_random_free(random_gen); free(llr_b); free(llr_s); free(llr); free(symbols); - free(output); free(input); srsran_modem_table_free(&mod); - printf("Mean Throughput: %.2f/%.2f/%.2f. Mbps ExTime: %.2f/%.2f/%.2f us\n", + printf("Mean Throughput: %.2f/%.2f/%.2f/%.2f. Mbps ExTime: %.2f/%.2f/%.2f/%.2f us\n", num_bits / mean_texec, num_bits / mean_texec_s, num_bits / mean_texec_b, + num_bits / mean_texec_b2, mean_texec, mean_texec_s, - mean_texec_b); + mean_texec_b, + mean_texec_b2); exit(ret); } diff --git a/lib/src/phy/phch/pdsch_nr.c b/lib/src/phy/phch/pdsch_nr.c index ea7972a80..f87f32bcb 100644 --- a/lib/src/phy/phch/pdsch_nr.c +++ b/lib/src/phy/phch/pdsch_nr.c @@ -456,7 +456,7 @@ static inline int pdsch_nr_decode_codeword(srsran_pdsch_nr_t* q, // Demodulation int8_t* llr = (int8_t*)q->b[tb->cw_idx]; - if (srsran_demod_soft_demodulate_b(tb->mod, q->d[tb->cw_idx], llr, tb->nof_re)) { + if (srsran_demod_soft_demodulate2_b(tb->mod, q->d[tb->cw_idx], llr, tb->nof_re)) { return SRSRAN_ERROR; }