From 2b9bd1173e0a2c6b6308543e19fd6d2fa8574301 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 8 Mar 2021 11:48:02 +0100 Subject: [PATCH] More NR-PUSCH UCI bit multiplexing --- lib/include/srslte/phy/phch/pusch_nr.h | 1 + lib/src/phy/phch/pusch_nr.c | 182 +++++++++++++++---------- lib/src/phy/phch/uci_nr.c | 21 ++- 3 files changed, 130 insertions(+), 74 deletions(-) diff --git a/lib/include/srslte/phy/phch/pusch_nr.h b/lib/include/srslte/phy/phch/pusch_nr.h index 6f37ee646..2db7268e4 100644 --- a/lib/include/srslte/phy/phch/pusch_nr.h +++ b/lib/include/srslte/phy/phch/pusch_nr.h @@ -59,6 +59,7 @@ typedef struct SRSLTE_API { uint32_t* pos_ack; ///< Reserved resource elements for HARQ-ACK multiplexing position uint32_t* pos_csi1; ///< Reserved resource elements for CSI part 1 multiplexing position uint32_t* pos_csi2; ///< Reserved resource elements for CSI part 1 multiplexing position + bool uci_mux; ///< Set to true if PUSCH needs to multiplex UCI uint32_t G_ack; ///< Number of encoded HARQ-ACK bits uint32_t G_csi1; ///< Number of encoded CSI part 1 bits uint32_t G_csi2; ///< Number of encoded CSI part 2 bits diff --git a/lib/src/phy/phch/pusch_nr.c b/lib/src/phy/phch/pusch_nr.c index 89c2c0a30..89b5159cd 100644 --- a/lib/src/phy/phch/pusch_nr.c +++ b/lib/src/phy/phch/pusch_nr.c @@ -471,6 +471,11 @@ pusch_nr_cinit(const srslte_carrier_nr_t* carrier, const srslte_sch_cfg_nr_t* cf static inline int pusch_nr_fill_uci_cfg(srslte_pusch_nr_t* q, const srslte_sch_cfg_nr_t* cfg) { + if (cfg->grant.nof_prb == 0) { + ERROR("Invalid number of PRB (%d)", cfg->grant.nof_prb); + return SRSLTE_ERROR; + } + // Initially, copy all fields q->uci_cfg = cfg->uci; @@ -582,6 +587,15 @@ static inline int pusch_nr_fill_uci_cfg(srslte_pusch_nr_t* q, const srslte_sch_c // Implements TS 38.212 6.2.7 Data and control multiplexing (for NR-PUSCH) static int pusch_nr_gen_mux_uci(srslte_pusch_nr_t* q, const srslte_uci_cfg_nr_t* cfg) { + // Decide whether UCI shall be multiplexed + q->uci_mux = (q->G_ack > 0 || q->G_csi1 > 0 || q->G_csi2 > 0); + + // Check if UCI multiplexing is NOT required + if (!q->uci_mux) { + q->G_ulsch = 0; + return SRSLTE_SUCCESS; + } + // Bit positions uint32_t* pos_ulsch = q->pos_ulsch; // coded bits for UL-SCH uint32_t* pos_ack = q->pos_ack; // coded bits for HARQ-ACK @@ -602,11 +616,15 @@ static int pusch_nr_gen_mux_uci(srslte_pusch_nr_t* q, const srslte_uci_cfg_nr_t* uint32_t Nl = cfg->pusch.nof_layers; uint32_t Qm = srslte_mod_bits_x_symbol(cfg->pusch.modulation); - // If 2 or less HARQ-ACK bits, use reserve + // if the number of HARQ-ACK information bits to be transmitted on PUSCH is 0, 1 or 2 bits uint32_t G_ack_rvd = 0; if (cfg->o_ack <= 2) { - G_ack_rvd = G_ack; - G_ack = 0; + // the number of reserved resource elements for potential HARQ-ACK transmission is calculated according to Clause + // 6.3.2.4.2.1, by setting O_ACK = 2 ; + G_ack_rvd = srslte_uci_nr_pusch_ack_nof_bits(&q->uci_cfg.pusch, 2); + + // Disable non reserved HARQ-ACK bits + G_ack = 0; } // Counters @@ -704,7 +722,7 @@ static int pusch_nr_gen_mux_uci(srslte_pusch_nr_t* q, const srslte_uci_cfg_nr_t* } csi1_m_re_count--; csi1_i++; - } else if (csi2_m_re_count != 0 && csi2_i % csi2_d == 0 && m_csi2_count < G_csi2) { + } else if (!reserved && csi2_m_re_count != 0 && csi2_i % csi2_d == 0 && m_csi2_count < G_csi2) { for (uint32_t j = 0; j < Nl * Qm; j++) { pos_csi2[m_csi2_count++] = m_all_count + j; } @@ -716,14 +734,20 @@ static int pusch_nr_gen_mux_uci(srslte_pusch_nr_t* q, const srslte_uci_cfg_nr_t* pos_ulsch[m_ulsch_count++] = m_all_count + j; } ulsch_m_re_count--; - csi1_i++; - csi2_i++; + if (!reserved) { + csi1_i++; + csi2_i++; + } } - // Set reserved bits + // Set reserved bits only if there are ACK bits if (reserved) { - for (uint32_t j = 0; j < Nl * Qm; j++) { - pos_ack[m_ack_count++] = m_all_count + j; + if (cfg->o_ack > 0) { + for (uint32_t j = 0; j < Nl * Qm; j++) { + pos_ack[m_ack_count++] = m_all_count + j; + } + } else { + m_ack_count += Nl * Qm; } ack_m_re_count--; } @@ -751,12 +775,13 @@ static int pusch_nr_gen_mux_uci(srslte_pusch_nr_t* q, const srslte_uci_cfg_nr_t* q->G_ulsch = m_ulsch_count; // Assert Number of bits - if (G_ack_rvd != 0 && G_ack_rvd != m_ack_count) { + if (G_ack_rvd != 0 && G_ack_rvd != m_ack_count && cfg->o_ack > 0) { ERROR("Not matched %d!=%d", G_ack_rvd, m_ack_count); } if (G_ack != 0 && G_ack != m_ack_count) { ERROR("Not matched %d!=%d", G_ack, m_ack_count); } + q->G_csi1 = m_csi1_count; if (G_csi1 != 0 && G_csi1 != m_csi1_count) { ERROR("Not matched %d!=%d", G_csi1, m_csi1_count); } @@ -770,7 +795,7 @@ static int pusch_nr_gen_mux_uci(srslte_pusch_nr_t* q, const srslte_uci_cfg_nr_t* DEBUG("UL-SCH bit positions:"); srslte_vec_fprint_i(stdout, (int*)pos_ulsch, m_ulsch_count); } - if (m_ack_count != 0) { + if (m_ack_count != 0 && cfg->o_ack > 0) { DEBUG("HARQ-ACK bit positions [%d]:", m_ack_count); srslte_vec_fprint_i(stdout, (int*)pos_ack, m_ack_count); } @@ -843,34 +868,41 @@ static inline int pusch_nr_encode_codeword(srslte_pusch_nr_t* q, return SRSLTE_ERROR; } - // Multiplex UL-SCH - for (uint32_t i = 0; i < q->G_ulsch; i++) { - q->b[tb->cw_idx][q->pos_ulsch[i]] = q->g_ulsch[i]; - } + // Multiplex UL-SCH with UCI only if it is necessary + uint8_t* b = q->g_ulsch; + if (q->uci_mux) { + // Change b location + b = q->b[tb->cw_idx]; - // Multiplex CSI part 1 - for (uint32_t i = 0; i < q->G_csi1; i++) { - q->b[tb->cw_idx][q->pos_csi1[i]] = q->g_csi1[i]; - } + // Multiplex UL-SCH + for (uint32_t i = 0; i < q->G_ulsch; i++) { + b[q->pos_ulsch[i]] = q->g_ulsch[i]; + } - // Multiplex CSI part 2 - for (uint32_t i = 0; i < q->G_csi2; i++) { - q->b[tb->cw_idx][q->pos_csi2[i]] = q->g_csi2[i]; - } + // Multiplex CSI part 1 + for (uint32_t i = 0; i < q->G_csi1; i++) { + b[q->pos_csi1[i]] = q->g_csi1[i]; + } - // Multiplex HARQ-ACK - for (uint32_t i = 0; i < q->G_ack; i++) { - q->b[tb->cw_idx][q->pos_ack[i]] = q->g_ack[i]; + // Multiplex CSI part 2 + for (uint32_t i = 0; i < q->G_csi2; i++) { + b[q->pos_csi2[i]] = q->g_csi2[i]; + } + + // Multiplex HARQ-ACK + for (uint32_t i = 0; i < q->G_ack; i++) { + b[q->pos_ack[i]] = q->g_ack[i]; + } } if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) { DEBUG("b="); - srslte_vec_fprint_b(stdout, q->b[tb->cw_idx], tb->nof_bits); + srslte_vec_fprint_b(stdout, b, tb->nof_bits); } // 7.3.1.1 Scrambling uint32_t cinit = pusch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx); - srslte_sequence_apply_bit(q->b[tb->cw_idx], q->b[tb->cw_idx], tb->nof_bits, cinit); + srslte_sequence_apply_bit(b, q->b[tb->cw_idx], tb->nof_bits, cinit); // Special Scrambling condition if (q->uci_cfg.o_ack <= 2) { @@ -1044,60 +1076,70 @@ static inline int pusch_nr_decode_codeword(srslte_pusch_nr_t* q, srslte_vec_fprint_bs(stdout, llr, tb->nof_bits); } - // Demultiplex UL-SCH, change sign - int8_t* g_ulsch = (int8_t*)q->g_ulsch; - for (uint32_t i = 0; i < q->G_ulsch; i++) { - g_ulsch[i] = -llr[q->pos_ulsch[i]]; - } - for (uint32_t i = q->G_ulsch; i < tb->nof_bits; i++) { - g_ulsch[i] = 0; - } + // Demultiplex UCI only if necessary + if (q->uci_mux) { + // Demultiplex UL-SCH, change sign + int8_t* g_ulsch = (int8_t*)q->g_ulsch; + for (uint32_t i = 0; i < q->G_ulsch; i++) { + g_ulsch[i] = -llr[q->pos_ulsch[i]]; + } + for (uint32_t i = q->G_ulsch; i < tb->nof_bits; i++) { + g_ulsch[i] = 0; + } - // Demultiplex HARQ-ACK - int8_t* g_ack = (int8_t*)q->g_ack; - for (uint32_t i = 0; i < q->G_ack; i++) { - g_ack[i] = llr[q->pos_ack[i]]; - } + // Demultiplex HARQ-ACK + int8_t* g_ack = (int8_t*)q->g_ack; + for (uint32_t i = 0; i < q->G_ack; i++) { + g_ack[i] = llr[q->pos_ack[i]]; + } - // Demultiplex CSI part 1 - int8_t* g_csi1 = (int8_t*)q->g_csi1; - for (uint32_t i = 0; i < q->G_csi1; i++) { - g_csi1[i] = llr[q->pos_csi1[i]]; - } + // Demultiplex CSI part 1 + int8_t* g_csi1 = (int8_t*)q->g_csi1; + for (uint32_t i = 0; i < q->G_csi1; i++) { + g_csi1[i] = llr[q->pos_csi1[i]]; + } - // Demultiplex CSI part 2 - int8_t* g_csi2 = (int8_t*)q->g_csi2; - for (uint32_t i = 0; i < q->G_csi2; i++) { - g_csi2[i] = llr[q->pos_csi2[i]]; + // Demultiplex CSI part 2 + int8_t* g_csi2 = (int8_t*)q->g_csi2; + for (uint32_t i = 0; i < q->G_csi2; i++) { + g_csi2[i] = llr[q->pos_csi2[i]]; + } + + // Decode HARQ-ACK + if (q->G_ack) { + if (srslte_uci_nr_decode_pusch_ack(&q->uci, &q->uci_cfg, g_ack, &res->uci)) { + ERROR("Error in UCI decoding"); + return SRSLTE_ERROR; + } + } + + // Decode CSI part 1 + if (q->G_csi1) { + if (srslte_uci_nr_decode_pusch_csi1(&q->uci, &q->uci_cfg, g_csi1, &res->uci)) { + ERROR("Error in UCI decoding"); + return SRSLTE_ERROR; + } + } + + // Decode CSI part 2 + // ... Not implemented + + // Change LLR pointer + llr = g_ulsch; + } else { + for (uint32_t i = 0; i < tb->nof_bits; i++) { + llr[i] *= -1; + } } // Decode Ul-SCH if (q->G_ulsch != 0) { - if (srslte_ulsch_nr_decode(&q->sch, &cfg->sch_cfg, tb, g_ulsch, res->payload, &res->crc) < SRSLTE_SUCCESS) { + if (srslte_ulsch_nr_decode(&q->sch, &cfg->sch_cfg, tb, llr, res->payload, &res->crc) < SRSLTE_SUCCESS) { ERROR("Error in SCH decoding"); return SRSLTE_ERROR; } } - // Decode HARQ-ACK - if (q->G_ack) { - if (srslte_uci_nr_decode_pusch_ack(&q->uci, &q->uci_cfg, g_ack, &res->uci)) { - ERROR("Error in UCI decoding"); - return SRSLTE_ERROR; - } - } - - // Decode CSI part 1 - if (q->G_csi1) { - if (srslte_uci_nr_decode_pusch_csi1(&q->uci, &q->uci_cfg, g_csi1, &res->uci)) { - ERROR("Error in UCI decoding"); - return SRSLTE_ERROR; - } - } - - // Decode CSI part 2 - // ... Not implemented - return SRSLTE_SUCCESS; } diff --git a/lib/src/phy/phch/uci_nr.c b/lib/src/phy/phch/uci_nr.c index f1c025a14..bed5e35e6 100644 --- a/lib/src/phy/phch/uci_nr.c +++ b/lib/src/phy/phch/uci_nr.c @@ -451,7 +451,7 @@ static int uci_nr_encode_2bit(srslte_uci_nr_t* q, const srslte_uci_cfg_nr_t* cfg } if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO && !handler_registered) { - UCI_NR_INFO_TX("Two bit encoded NR-UCI; o="); + UCI_NR_INFO_TX("Two bit encoded NR-UCI; E=%d; o=", E); srslte_vec_fprint_b(stdout, o, E); } @@ -982,6 +982,11 @@ int srslte_uci_nr_pusch_ack_nof_bits(const srslte_uci_nr_pusch_cfg_t* cfg, uint3 return SRSLTE_ERROR_INVALID_INPUTS; } + if (cfg->nof_layers == 0) { + ERROR("Invalid number of layers (%d)", cfg->nof_layers); + return SRSLTE_ERROR; + } + int Q_ack_prime = uci_nr_pusch_Q_prime_ack(cfg, O_ack); if (Q_ack_prime < SRSLTE_SUCCESS) { ERROR("Error calculating number of RE"); @@ -1006,10 +1011,13 @@ int srslte_uci_nr_encode_pusch_ack(srslte_uci_nr_t* q, // 6.3.2.1 UCI bit sequence generation // 6.3.2.1.1 HARQ-ACK bool has_csi_part2 = srslte_csi_has_part2(cfg->csi, cfg->nof_csi); - if (cfg->pusch.K_sum == 0 && cfg->nof_csi > 1 && !has_csi_part2 && cfg->o_ack < 2) { - A = 2; - q->bit_sequence[0] = (cfg->o_ack == 0) ? 0 : value->ack[0]; + if (cfg->pusch.K_sum == 0 && cfg->nof_csi > 1 && !has_csi_part2 && A < 2) { + q->bit_sequence[0] = (A == 0) ? 0 : value->ack[0]; q->bit_sequence[1] = 0; + A = 2; + } else if (A == 0) { + UCI_NR_INFO_TX("No HARQ-ACK to mux"); + return SRSLTE_SUCCESS; } else { srslte_vec_u8_copy(q->bit_sequence, value->ack, cfg->o_ack); } @@ -1142,6 +1150,11 @@ int srslte_uci_nr_encode_pusch_csi1(srslte_uci_nr_t* q, return SRSLTE_ERROR; } + if (A == 0) { + UCI_NR_INFO_TX("No CSI part 1 to mux"); + return SRSLTE_SUCCESS; + } + // Compute total of encoded bits according to 6.3.2.4 Rate matching int E_uci = srslte_uci_nr_pusch_csi1_nof_bits(cfg); if (E_uci < SRSLTE_SUCCESS) {