From fffe9531c360434cbd6cccb269146b5f7bd17dfd Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 22 Jul 2025 13:51:05 +0200 Subject: [PATCH 1/9] add assert in a case of wrong gNB configuration file --- common/utils/nr/nr_common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 7875fe546a..7954db7d54 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -1160,6 +1160,7 @@ uint32_t get_ssb_offset_to_pointA(uint32_t absoluteFrequencySSB, const int ssb_offset_point_a = ((scaled_abs_diff / 12) - 10) * scaling; // Offset to point A needs to be divisible by scaling AssertFatal(ssb_offset_point_a % scaling == 0, "PRB offset %d not valid for scs %d\n", ssb_offset_point_a, ssbSubcarrierSpacing); + AssertFatal(ssb_offset_point_a >= 0, "ssb offset is negative %d for scs %d\n", ssb_offset_point_a, ssbSubcarrierSpacing); return ssb_offset_point_a; } From 3ca12f78e5a9f1abff7e57b4ae2b900d470b9085 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 23 Jul 2025 07:48:17 +0200 Subject: [PATCH 2/9] simplify function nr_pdcch_extract_rbs_single() --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 107 ++++++++------------------ 1 file changed, 33 insertions(+), 74 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index a027b042ca..7dcbbbe969 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -269,9 +269,9 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, LOG_DDD("dl_ch0 = &dl_ch_estimates[aarx = (%d)][0]\n", aarx); const int offset = symbol * coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS; - c16_t *dl_ch0_ext = &dl_ch_estimates_ext[aarx][offset]; + c16_t *dl_ch0_ext = dl_ch_estimates_ext[aarx] + offset; LOG_DDD("dl_ch0_ext = &dl_ch_estimates_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 9) = (%d)]\n", aarx, offset); - c16_t *rxF_ext = &rxdataF_ext[aarx][offset]; + c16_t *rxF_ext = rxdataF_ext[aarx] + offset; LOG_DDD("rxF_ext = &rxdataF_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 9) = (%d)]\n", aarx, offset); /* @@ -301,81 +301,40 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, c_rb += 6; c_rb_by6 = c_rb / 6; } - - // first we set initial conditions for pointer to rxdataF depending on the situation of the first RB within the CORESET - // (c_rb = n_BWP_start) - if ((frame_parms->N_RB_DL & 1) == 1 && (c_rb + n_BWP_start) == (frame_parms->N_RB_DL >> 1)) { - // treatment of RB containing the DC - // if odd number RBs in system bandwidth and first RB to be treated is higher than middle system bandwidth (around DC) - // we have to treat the RB in two parts: first part from i=0 to 5, the data is at the end of rxdataF (pointing at the - // end of the table) - c16_t *rxF = rxFbase + frame_parms->first_carrier_offset + 12 * (c_rb + n_BWP_start); - - int i = 0, j = 0; - for (; i < 6; i++) { // treating first part of the RB note that i=5 would correspond to DC. We treat it in NR - if ((i != 1) && (i != 5)) { - dl_ch0_ext[j] = dl_ch0[i]; - rxF_ext[j] = rxF[i]; - LOG_DSYMB(""); - j++; - } else { - LOG_DSYMB("\t\t <==> DM-RS PDCCH, this is a pilot symbol\n"); - } - } - - // then we point at the begining of the symbol part of rxdataF do process second part of RB - for (; i < 12; i++) { - if ((i != 9)) { - dl_ch0_ext[j] = dl_ch0[i]; - rxF_ext[j] = rxFbase[i - 6]; - LOG_DSYMB(""); - j++; - } else { - LOG_DSYMB("\t\t <==> DM-RS PDCCH, this is a pilot symbol\n"); - } - } - - } else { // treatment of any RB that does not contain the DC - c16_t *rxF=NULL; - if ((frame_parms->N_RB_DL & 1) == 0) { - if ((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) - // if RB to be treated is lower than middle system bandwidth then rxdataF pointed - // at (offset + c_br + symbol * ofdm_symbol_size): even case - rxF = rxFbase + (frame_parms->first_carrier_offset + 12 * c_rb) + n_BWP_start * 12; - else - // number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC) - // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF - // we point at the 1st part of the rxdataF in symbol - rxF = rxFbase + 12 * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)); - } else { - if ((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) - // if RB to be treated is lower than middle system bandwidth then rxdataF pointed - // at (offset + c_br + symbol * ofdm_symbol_size): odd case - rxF = rxFbase + frame_parms->first_carrier_offset + 12 * (c_rb + n_BWP_start); - else if ((c_rb + n_BWP_start) > (frame_parms->N_RB_DL >> 1)) - // number of RBs is odd and c_rb is higher than half system bandwidth + 1 - // if these conditions are true the pointer has to be situated at the 1st part of - // the rxdataF just after the first IQ symbols of the RB containing DC - // we point at the 1st part of the rxdataF in symbol - rxF = rxFbase + 12 * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)) - 6; - } - AssertFatal(rxF, "bug"); - int j = 0; - - for (int i = 0; i < 12; i++) { - if ((i != 1) && (i != 5) && (i != 9)) { - rxF_ext[j] = rxF[i]; - dl_ch0_ext[j] = dl_ch0[i]; - LOG_DSYMB(""); - j++; - } else { - LOG_DSYMB("\t\t <==> DM-RS PDCCH, this is a pilot symbol\n"); - } - } + c16_t *rxF = NULL; + if ((frame_parms->N_RB_DL & 1) == 0) { + if ((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) + // if RB to be treated is lower than middle system bandwidth then rxdataF pointed + // at (offset + c_br + symbol * ofdm_symbol_size): even case + rxF = rxFbase + (frame_parms->first_carrier_offset + 12 * c_rb) + n_BWP_start * 12; + else + // number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC) + // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF + // we point at the 1st part of the rxdataF in symbol + rxF = rxFbase + 12 * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)); + } else { + if ((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) + // if RB to be treated is lower than middle system bandwidth then rxdataF pointed + // at (offset + c_br + symbol * ofdm_symbol_size): odd case + rxF = rxFbase + frame_parms->first_carrier_offset + 12 * (c_rb + n_BWP_start); + else if ((c_rb + n_BWP_start) > (frame_parms->N_RB_DL >> 1)) + // number of RBs is odd and c_rb is higher than half system bandwidth + 1 + // if these conditions are true the pointer has to be situated at the 1st part of + // the rxdataF just after the first IQ symbols of the RB containing DC + // we point at the 1st part of the rxdataF in symbol + rxF = rxFbase + 12 * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)) - 6; + else + rxF = rxFbase + frame_parms->first_carrier_offset + 12 * (c_rb + n_BWP_start); + } + const int valid_re[NBR_RE_PER_RB_WITHOUT_DMRS] = {0, 2, 3, 4, 6, 7, 8, 10, 11}; + for (int i = 0; i < sizeofArray(valid_re); i++) { + rxF_ext[i] = rxF[valid_re[i]]; + dl_ch0_ext[i] = dl_ch0[valid_re[i]]; + LOG_DSYMB(""); } dl_ch0_ext += NBR_RE_PER_RB_WITHOUT_DMRS; rxF_ext += NBR_RE_PER_RB_WITHOUT_DMRS; - dl_ch0 += 12; + dl_ch0 += NBR_RE_PER_RB_WITH_DMRS; } } } From 2c22f49a456075323d8cfb3d68dccdef191c5773 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 23 Jul 2025 07:49:37 +0200 Subject: [PATCH 3/9] simplify nr_pdcch_channel_compensation() --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 38 +++++++++++---------------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 7dcbbbe969..c5ea4e35a0 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -352,29 +352,23 @@ void nr_pdcch_channel_compensation(int32_t rx_size, uint32_t coreset_nbr_rb) { for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - simde__m128i *dl_ch128 = (simde__m128i *)&dl_ch_estimates_ext[aarx][symbol * coreset_nbr_rb * 12]; - simde__m128i *rxdataF128 = (simde__m128i *)&rxdataF_ext[aarx][symbol * coreset_nbr_rb * 12]; - simde__m128i *rxdataF_comp128 = (simde__m128i *)&rxdataF_comp[aarx][symbol * coreset_nbr_rb * 12]; - //printf("ch compensation dl_ch ext addr %p \n", &dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*20*12]); - //printf("rxdataf ext addr %p symbol %d\n", &rxdataF_ext[aarx][symbol*20*12], symbol); - //printf("rxdataf_comp addr %p\n",&rxdataF_comp[(aatx<<1)+aarx][symbol*20*12]); - + const int sz = coreset_nbr_rb * 12; + c16_t *dl_ch = dl_ch_estimates_ext[aarx] + symbol * sz; + c16_t *rxdataF = rxdataF_ext[aarx] + symbol * sz; + c16_t *rxdataF_c = rxdataF_comp[aarx] + symbol * sz; // multiply by conjugated channel - mult_cpx_conj_vector((c16_t *)dl_ch128, (c16_t *)rxdataF128, (c16_t *)rxdataF_comp128, 12 * coreset_nbr_rb, output_shift); - - for (int rb = 0; rb < 12 * coreset_nbr_rb; rb++) { - LOG_DDD("rxdataF128[%d]=(%d,%d) X dlch[%d]=(%d,%d) rxdataF_comp128[%d]=(%d,%d)\n", - rb, - ((c16_t *)rxdataF128)[rb].r, - ((c16_t *)rxdataF128)[rb].i, - rb, - ((c16_t *)dl_ch128)[rb].r, - ((c16_t *)dl_ch128)[rb].i, - rb, - ((c16_t *)rxdataF_comp128)[rb].r, - ((c16_t *)rxdataF_comp128)[rb].i); - - } + mult_cpx_conj_vector(dl_ch, rxdataF, rxdataF_c, sz, output_shift); + for (int rb = 0; rb < sz; rb++) + LOG_DDD("rxdataF[%d]=(%d,%d) X dlch[%d]=(%d,%d) rxdataF_comp[%d]=(%d,%d)\n", + rb, + rxdataF[rb].r, + rxdataF[rb].i, + rb, + dl_ch[rb].r, + dl_ch[rb].i, + rb, + rxdataF_c[rb].r, + rxdataF_c[rb].i); } } From b30da5c0b22476f8567931ddcc0ecbc8e85654f3 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 23 Jul 2025 07:52:08 +0200 Subject: [PATCH 4/9] reduce size and make local rxdataF_comp in nr_rx_pdcch() --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 87 +++++++++++---------------- 1 file changed, 35 insertions(+), 52 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index c5ea4e35a0..29f8fdb6b3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -44,9 +44,7 @@ #include "assertions.h" #include "T.h" -//#define DEBUG_DCI_DECODING 1 - -//#define NR_PDCCH_DCI_DEBUG // activates NR_PDCCH_DCI_DEBUG logs +// #define NR_PDCCH_DCI_DEBUG // activates NR_PDCCH_DCI_DEBUG logs #ifdef NR_PDCCH_DCI_DEBUG #define LOG_DDD(a, ...) printf("<-NR_PDCCH_DCI_DEBUG (%s)-> " a, __func__, ##__VA_ARGS__ ) #define LOG_DSYMB(b) \ @@ -188,20 +186,23 @@ static void nr_pdcch_demapping_deinterleaving(c16_t *llr, static void nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, int32_t rx_size, - c16_t rxdataF_comp[][rx_size], + uint32_t coreset_nbr_rb, + c16_t rxdataF_comp[coreset_nbr_rb * 12], c16_t *pdcch_llr, - uint8_t symbol, - uint32_t coreset_nbr_rb) + uint8_t symbol) { - c16_t *rxF = &rxdataF_comp[0][(symbol * coreset_nbr_rb * 12)]; - c16_t *pdcch_llrp = &pdcch_llr[symbol * coreset_nbr_rb * 9]; + c16_t *rxF = rxdataF_comp; + c16_t *llr = pdcch_llr + symbol * coreset_nbr_rb * 9; - if (!pdcch_llrp) { + if (!llr) { LOG_E(NR_PHY_DCI, "pdcch_qpsk_llr: llr is null, symbol %d\n", symbol); return; } - LOG_DDD("llr logs: pdcch qpsk llr for symbol %d (pos %d), llr offset %ld\n",symbol,(symbol*frame_parms->N_RB_DL*12),pdcch_llrp-pdcch_llr); + LOG_DDD("llr logs: pdcch qpsk llr for symbol %d (pos %d), llr offset %ld\n", + symbol, + symbol * frame_parms->N_RB_DL * 12, + llr - pdcch_llr); for (int i = 0; i < coreset_nbr_rb * 9; i++) { // We clip the signal @@ -210,10 +211,9 @@ static void nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, res.r = max(-32, res.r); res.i = min(rxF->i, 31); res.i = max(-32, res.i); - *pdcch_llrp = res; - LOG_DDD("llr logs: rb=%d i=%d *rxF:%d => *pdcch_llrp:%d\n",i/18,i,*rxF,*pdcch_llrp); + *llr++ = res; + LOG_DDD("llr logs: rb=%d i=%d rxF:%d,%d => pdcch_llr:%d,%d\n", i / 18, i, rxF->r, rxF->i, llr->r, llr->i); rxF++; - pdcch_llrp++; } } @@ -330,7 +330,6 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, for (int i = 0; i < sizeofArray(valid_re); i++) { rxF_ext[i] = rxF[valid_re[i]]; dl_ch0_ext[i] = dl_ch0[valid_re[i]]; - LOG_DSYMB(""); } dl_ch0_ext += NBR_RE_PER_RB_WITHOUT_DMRS; rxF_ext += NBR_RE_PER_RB_WITHOUT_DMRS; @@ -339,23 +338,21 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, } } -#define print_shorts(s,x) printf("%s %d,%d,%d,%d,%d,%d,%d,%d\n",s,(x)[0],(x)[1],(x)[2],(x)[3],(x)[4],(x)[5],(x)[6],(x)[7]) - -void nr_pdcch_channel_compensation(int32_t rx_size, - c16_t rxdataF_ext[][rx_size], - c16_t dl_ch_estimates_ext[][rx_size], - c16_t rxdataF_comp[][rx_size], - int32_t **rho, - NR_DL_FRAME_PARMS *frame_parms, - uint8_t symbol, - uint8_t output_shift, - uint32_t coreset_nbr_rb) +static void nr_pdcch_channel_compensation(int32_t rx_size, + uint32_t coreset_nbr_rb, + c16_t rxdataF_ext[][rx_size], + c16_t dl_ch_estimates_ext[][rx_size], + c16_t rxdataF_comp[][coreset_nbr_rb * 12], + int32_t **rho, + NR_DL_FRAME_PARMS *frame_parms, + uint8_t symbol, + uint8_t output_shift) { for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { const int sz = coreset_nbr_rb * 12; c16_t *dl_ch = dl_ch_estimates_ext[aarx] + symbol * sz; c16_t *rxdataF = rxdataF_ext[aarx] + symbol * sz; - c16_t *rxdataF_c = rxdataF_comp[aarx] + symbol * sz; + c16_t *rxdataF_c = rxdataF_comp[aarx]; // multiply by conjugated channel mult_cpx_conj_vector(dl_ch, rxdataF, rxdataF_c, sz, output_shift); for (int rb = 0; rb < sz; rb++) @@ -375,10 +372,11 @@ void nr_pdcch_channel_compensation(int32_t rx_size, static void nr_pdcch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, int32_t rx_size, c16_t rxdataF_comp[][rx_size], int symbol) { if (frame_parms->nb_antennas_rx>1) { + LOG_D(NR_PHY_DCI, "we enter nr_pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n", frame_parms->nb_antennas_rx); const int sz = frame_parms->N_RB_DL * 12; - - simde__m128i *rxdataF_comp128_0 = (simde__m128i *)&rxdataF_comp[0][symbol * sz]; - simde__m128i *rxdataF_comp128_1 = (simde__m128i *)&rxdataF_comp[1][symbol * sz]; + + simde__m128i *rxdataF_comp128_0 = (simde__m128i *)rxdataF_comp[0]; + simde__m128i *rxdataF_comp128_1 = (simde__m128i *)rxdataF_comp[1]; // MRC on each re of rb for (int i = 0; i < sz >> 2; i++) { @@ -406,15 +404,10 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, // Pointers to extracted PDCCH symbols in frequency-domain. int32_t rx_size = ((4 * frame_parms->N_RB_DL * 12 + 31) >> 5) << 5; __attribute__((aligned(32))) c16_t rxdataF_ext[frame_parms->nb_antennas_rx][rx_size]; - __attribute__((aligned(32))) c16_t rxdataF_comp[frame_parms->nb_antennas_rx][rx_size]; __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[frame_parms->nb_antennas_rx][rx_size]; - - memset(rxdataF_comp, 0, sizeof(rxdataF_comp)); - // Pointer to llrs, 4-bit resolution. int32_t llr_size = 4 * n_rb * 9; c16_t llr[llr_size]; - memset(llr, 0, sizeof(llr)); LOG_D(NR_PHY_DCI, @@ -466,36 +459,26 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, LOG_D(NR_PHY_DCI, "we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n", log2_maxh); LOG_D(NR_PHY_DCI, "in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n"); // compute LLRs for ofdm symbol 0 only - nr_pdcch_channel_compensation(rx_size, rxdataF_ext, + __attribute__((aligned(32))) c16_t rxdataF_comp[frame_parms->nb_antennas_rx][n_rb * 12]; + nr_pdcch_channel_compensation(rx_size, + n_rb, + rxdataF_ext, pdcch_dl_ch_estimates_ext, rxdataF_comp, NULL, frame_parms, s, - log2_maxh, - n_rb); // log2_maxh+I0_shift + log2_maxh); // log2_maxh+I0_shift - UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), frame_parms->nb_antennas_rx, rx_size, 0); + UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), frame_parms->nb_antennas_rx, n_rb * 12, 0); - if (frame_parms->nb_antennas_rx > 1) { - LOG_D(NR_PHY_DCI, "we enter nr_pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n", frame_parms->nb_antennas_rx); - nr_pdcch_detection_mrc(frame_parms, rx_size, rxdataF_comp,s); - } + nr_pdcch_detection_mrc(frame_parms, n_rb * 12, rxdataF_comp, s); LOG_D(NR_PHY_DCI, "we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n", s); LOG_D(NR_PHY_DCI, "in nr_pdcch_llr(rxdataF_comp -> llr)\n"); - nr_pdcch_llr(frame_parms, - rx_size, - rxdataF_comp, - llr, - s, - n_rb); + nr_pdcch_llr(frame_parms, rx_size, n_rb, rxdataF_comp[0], llr, s); UEscopeCopy(ue, pdcchLlr, llr, sizeof(c16_t), 1, llr_size, 0); - -#ifdef DEBUG_DCI_DECODING - printf("demapping: slot %u, mi %d\n",slot,get_mi(frame_parms,slot)); -#endif } nr_pdcch_demapping_deinterleaving(llr, From e8f6d14c47f501793e2a70581c6314afada8e743 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 23 Jul 2025 07:56:33 +0200 Subject: [PATCH 5/9] simplify and make more local variables in nr_rx_pdcch() and fix small bugs (size 9 RE instaed of 12 RE) --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 116 ++++++++++---------------- 1 file changed, 42 insertions(+), 74 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 29f8fdb6b3..112739e09b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -218,35 +218,29 @@ static void nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, } //compute average channel_level on each (TX,RX) antenna pair -void nr_pdcch_channel_level(int32_t rx_size, - c16_t dl_ch_estimates_ext[][rx_size], - NR_DL_FRAME_PARMS *frame_parms, - int32_t *avg, - int symbol, - int nb_rb) +static int32_t nr_pdcch_channel_level(int nb_rb, c16_t dl_ch_estimates_ext[][nb_rb * 9], int nb_antennas_rx, int symbol) { - for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - - simde__m128i *dl_ch128 = (simde__m128i *)&dl_ch_estimates_ext[aarx][symbol * nb_rb * 12]; - + int32_t avgs = 0; + for (int aarx = 0; aarx < nb_antennas_rx; aarx++) { + simde__m128i *dl_ch128 = (simde__m128i *)&dl_ch_estimates_ext[aarx]; //compute average level - avg[aarx] = simde_mm_average(dl_ch128, nb_rb * 12, 0, nb_rb * 12); - //LOG_DDD("Channel level : %d\n", avg[aarx]); + int32_t tmp = simde_mm_average(dl_ch128, nb_rb * 9, 0, nb_rb * 9); + avgs = cmax(avgs, tmp); } + return avgs; } // This function will extract the mapped DM-RS PDCCH REs as per 38.211 Section 7.4.1.3.2 (Mapping to physical resources) static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, + uint32_t coreset_nbr_rb, c16_t rxdataF[][rxdataF_sz], int32_t est_size, c16_t dl_ch_estimates[][est_size], - int32_t rx_size, - c16_t rxdataF_ext[][rx_size], - c16_t dl_ch_estimates_ext[][rx_size], + c16_t rxdataF_ext[][coreset_nbr_rb * 9], + c16_t dl_ch_estimates_ext[][coreset_nbr_rb * 9], int symbol, NR_DL_FRAME_PARMS *frame_parms, uint8_t *coreset_freq_dom, - uint32_t coreset_nbr_rb, uint32_t n_BWP_start) { /* @@ -268,11 +262,8 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, c16_t *rxFbase = rxdataF[aarx] + frame_parms->ofdm_symbol_size * symbol; LOG_DDD("dl_ch0 = &dl_ch_estimates[aarx = (%d)][0]\n", aarx); - const int offset = symbol * coreset_nbr_rb * NBR_RE_PER_RB_WITH_DMRS; - c16_t *dl_ch0_ext = dl_ch_estimates_ext[aarx] + offset; - LOG_DDD("dl_ch0_ext = &dl_ch_estimates_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 9) = (%d)]\n", aarx, offset); - c16_t *rxF_ext = rxdataF_ext[aarx] + offset; - LOG_DDD("rxF_ext = &rxdataF_ext[aarx = (%d)][symbol * (frame_parms->N_RB_DL * 9) = (%d)]\n", aarx, offset); + c16_t *dl_ch0_ext = dl_ch_estimates_ext[aarx]; + c16_t *rxF_ext = rxdataF_ext[aarx]; /* * The following for loop handles treatment of PDCCH contained in table rxdataF (in frequency domain) @@ -338,20 +329,17 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, } } -static void nr_pdcch_channel_compensation(int32_t rx_size, - uint32_t coreset_nbr_rb, - c16_t rxdataF_ext[][rx_size], - c16_t dl_ch_estimates_ext[][rx_size], +static void nr_pdcch_channel_compensation(uint32_t coreset_nbr_rb, + c16_t rxdataF_ext[][coreset_nbr_rb * 9], + c16_t dl_ch_estimates_ext[][coreset_nbr_rb * 9], c16_t rxdataF_comp[][coreset_nbr_rb * 12], - int32_t **rho, - NR_DL_FRAME_PARMS *frame_parms, - uint8_t symbol, + int antRx, uint8_t output_shift) { - for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { - const int sz = coreset_nbr_rb * 12; - c16_t *dl_ch = dl_ch_estimates_ext[aarx] + symbol * sz; - c16_t *rxdataF = rxdataF_ext[aarx] + symbol * sz; + for (int aarx = 0; aarx < antRx; aarx++) { + const int sz = coreset_nbr_rb * 9; + c16_t *dl_ch = dl_ch_estimates_ext[aarx]; + c16_t *rxdataF = rxdataF_ext[aarx]; c16_t *rxdataF_c = rxdataF_comp[aarx]; // multiply by conjugated channel mult_cpx_conj_vector(dl_ch, rxdataF, rxdataF_c, sz, output_shift); @@ -369,19 +357,18 @@ static void nr_pdcch_channel_compensation(int32_t rx_size, } } -static void nr_pdcch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms, int32_t rx_size, c16_t rxdataF_comp[][rx_size], int symbol) +static void nr_pdcch_detection_mrc(int n_rb, c16_t rxdataF_comp[][n_rb * 9]) { - if (frame_parms->nb_antennas_rx>1) { - LOG_D(NR_PHY_DCI, "we enter nr_pdcch_detection_mrc(frame_parms->nb_antennas_rx=%d)\n", frame_parms->nb_antennas_rx); - const int sz = frame_parms->N_RB_DL * 12; + LOG_D(NR_PHY_DCI, "we enter nr_pdcch_detection_mrc (hard coded 2 antennas)\n"); + const int sz = n_rb * 9; - simde__m128i *rxdataF_comp128_0 = (simde__m128i *)rxdataF_comp[0]; - simde__m128i *rxdataF_comp128_1 = (simde__m128i *)rxdataF_comp[1]; + simde__m128i *rxdataF_comp128_0 = (simde__m128i *)rxdataF_comp[0]; + simde__m128i *rxdataF_comp128_1 = (simde__m128i *)rxdataF_comp[1]; - // MRC on each re of rb - for (int i = 0; i < sz >> 2; i++) { - rxdataF_comp128_0[i] = simde_mm_adds_epi16(simde_mm_srai_epi16(rxdataF_comp128_0[i], 1), simde_mm_srai_epi16(rxdataF_comp128_1[i], 1)); - } + // MRC on each re of rb + for (int i = 0; i < sz >> 2; i++) { + rxdataF_comp128_0[i] = + simde_mm_adds_epi16(simde_mm_srai_epi16(rxdataF_comp128_0[i], 1), simde_mm_srai_epi16(rxdataF_comp128_1[i], 1)); } } @@ -395,16 +382,12 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, { NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - uint8_t log2_maxh, aarx; - int32_t avgs; - int32_t avgP[4]; int n_rb,rb_offset; get_coreset_rballoc(rel15->coreset.frequency_domain_resource,&n_rb,&rb_offset); + const int antRx = frame_parms->nb_antennas_rx; // Pointers to extracted PDCCH symbols in frequency-domain. int32_t rx_size = ((4 * frame_parms->N_RB_DL * 12 + 31) >> 5) << 5; - __attribute__((aligned(32))) c16_t rxdataF_ext[frame_parms->nb_antennas_rx][rx_size]; - __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[frame_parms->nb_antennas_rx][rx_size]; // Pointer to llrs, 4-bit resolution. int32_t llr_size = 4 * n_rb * 9; c16_t llr[llr_size]; @@ -418,61 +401,46 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, for (int s=rel15->coreset.StartSymbolIndex; s<(rel15->coreset.StartSymbolIndex+rel15->coreset.duration); s++) { LOG_D(NR_PHY_DCI, "in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n"); + __attribute__((aligned(32))) c16_t rxdataF_ext[antRx][n_rb * 9]; + __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[antRx][n_rb * 9]; nr_pdcch_extract_rbs_single(ue->frame_parms.samples_per_slot_wCP, + n_rb, rxdataF, pdcch_est_size, pdcch_dl_ch_estimates, - rx_size, rxdataF_ext, pdcch_dl_ch_estimates_ext, s, frame_parms, rel15->coreset.frequency_domain_resource, - n_rb, rel15->BWPStart); - LOG_D(NR_PHY_DCI, - "we enter nr_pdcch_channel_level(avgP=%d) => compute channel level based on ofdm symbol 0, " - "pdcch_vars[eNB_id]->dl_ch_estimates_ext\n", - *avgP); LOG_D(NR_PHY_DCI, "in nr_pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n"); // compute channel level based on ofdm symbol 0 - nr_pdcch_channel_level(rx_size, - pdcch_dl_ch_estimates_ext, - frame_parms, - avgP, - s, - n_rb); - avgs = 0; - - for (aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) - avgs = cmax(avgs, avgP[aarx]); - - log2_maxh = (log2_approx(avgs) / 2) + 5; //+frame_parms->nb_antennas_rx; + int32_t avgs = nr_pdcch_channel_level(n_rb, pdcch_dl_ch_estimates_ext, antRx, s); + uint8_t log2_maxh = (log2_approx(avgs) / 2) + 5; //+antRx; #ifdef UE_DEBUG_TRACE LOG_D(NR_PHY_DCI, "slot %d: pdcch log2_maxh = %d (%d,%d)\n", proc->nr_slot_rx, log2_maxh, avgP[0], avgs); #endif #if T_TRACER - T(T_UE_PHY_PDCCH_ENERGY, T_INT(0), T_INT(0), T_INT(proc->frame_rx % 1024), T_INT(proc->nr_slot_rx), T_INT(avgP[0]), T_INT(avgP[1]), T_INT(avgP[2]), T_INT(avgP[3])); + T(T_UE_PHY_PDCCH_ENERGY, T_INT(0), T_INT(0), T_INT(proc->frame_rx % 1024), T_INT(proc->nr_slot_rx), T_INT(avgs)); #endif LOG_D(NR_PHY_DCI, "we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n", log2_maxh); LOG_D(NR_PHY_DCI, "in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n"); // compute LLRs for ofdm symbol 0 only - __attribute__((aligned(32))) c16_t rxdataF_comp[frame_parms->nb_antennas_rx][n_rb * 12]; - nr_pdcch_channel_compensation(rx_size, - n_rb, + __attribute__((aligned(32))) c16_t rxdataF_comp[antRx][n_rb * 12]; + nr_pdcch_channel_compensation(n_rb, rxdataF_ext, pdcch_dl_ch_estimates_ext, rxdataF_comp, - NULL, - frame_parms, - s, + antRx, log2_maxh); // log2_maxh+I0_shift - UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), frame_parms->nb_antennas_rx, n_rb * 12, 0); + UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), antRx, n_rb * 12, 0); - nr_pdcch_detection_mrc(frame_parms, n_rb * 12, rxdataF_comp, s); + if (antRx > 1) + nr_pdcch_detection_mrc(n_rb * 12, rxdataF_comp); LOG_D(NR_PHY_DCI, "we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n", s); LOG_D(NR_PHY_DCI, "in nr_pdcch_llr(rxdataF_comp -> llr)\n"); From 19d783f6d983b83e0072f79d43056fc11c4679f4 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 23 Jul 2025 08:03:48 +0200 Subject: [PATCH 6/9] generalize constant nb re per rn in dci_nr.c --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 80 +++++++++++++-------------- 1 file changed, 39 insertions(+), 41 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 112739e09b..5f41880251 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -61,14 +61,14 @@ #define LOG_DDD(a...) #define LOG_DSYMB(a...) #endif + #define NR_NBR_CORESET_ACT_BWP 3 // The number of CoreSets per BWP is limited to 3 (including initial CORESET: ControlResourceId 0) #define NR_NBR_SEARCHSPACE_ACT_BWP \ 10 // The number of SearSpaces per BWP is limited to 10 (including initial SEARCHSPACE: SearchSpaceId 0) -#ifdef LOG_I -#undef LOG_I -#define LOG_I(A, B...) printf(B) -#endif +#define RE_PER_RB 12 +// after removing the 3 DMRS RE, the RB contains 9 RE with PDCCH +#define RE_PER_RB_OUT_DMRS 9 static void nr_pdcch_demapping_deinterleaving(c16_t *llr, c16_t *e_rx, @@ -168,7 +168,7 @@ static void nr_pdcch_demapping_deinterleaving(c16_t *llr, } int rb_count = 0; - const int data_sc = 9; // 9 sub-carriers with data per PRB + const int data_sc = RE_PER_RB_OUT_DMRS; // 9 sub-carriers with data per PRB for (int c_id = 0; c_id < number_of_candidates; c_id++) { for (int symbol_idx = start_symbol; symbol_idx < start_symbol + coreset_time_dur; symbol_idx++) { for (int cce_count = 0; cce_count < L[c_id]; cce_count++) { @@ -187,12 +187,12 @@ static void nr_pdcch_demapping_deinterleaving(c16_t *llr, static void nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, int32_t rx_size, uint32_t coreset_nbr_rb, - c16_t rxdataF_comp[coreset_nbr_rb * 12], + c16_t rxdataF_comp[coreset_nbr_rb * RE_PER_RB], c16_t *pdcch_llr, uint8_t symbol) { c16_t *rxF = rxdataF_comp; - c16_t *llr = pdcch_llr + symbol * coreset_nbr_rb * 9; + c16_t *llr = pdcch_llr + symbol * coreset_nbr_rb * RE_PER_RB_OUT_DMRS; if (!llr) { LOG_E(NR_PHY_DCI, "pdcch_qpsk_llr: llr is null, symbol %d\n", symbol); @@ -201,10 +201,10 @@ static void nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, LOG_DDD("llr logs: pdcch qpsk llr for symbol %d (pos %d), llr offset %ld\n", symbol, - symbol * frame_parms->N_RB_DL * 12, + symbol * frame_parms->N_RB_DL * RE_PER_RB, llr - pdcch_llr); - for (int i = 0; i < coreset_nbr_rb * 9; i++) { + for (int i = 0; i < coreset_nbr_rb * RE_PER_RB_OUT_DMRS; i++) { // We clip the signal c16_t res; res.r = min(rxF->r, 31); @@ -218,13 +218,16 @@ static void nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, } //compute average channel_level on each (TX,RX) antenna pair -static int32_t nr_pdcch_channel_level(int nb_rb, c16_t dl_ch_estimates_ext[][nb_rb * 9], int nb_antennas_rx, int symbol) +static int32_t nr_pdcch_channel_level(int nb_rb, + c16_t dl_ch_estimates_ext[][nb_rb * RE_PER_RB_OUT_DMRS], + int nb_antennas_rx, + int symbol) { int32_t avgs = 0; for (int aarx = 0; aarx < nb_antennas_rx; aarx++) { simde__m128i *dl_ch128 = (simde__m128i *)&dl_ch_estimates_ext[aarx]; //compute average level - int32_t tmp = simde_mm_average(dl_ch128, nb_rb * 9, 0, nb_rb * 9); + int32_t tmp = simde_mm_average(dl_ch128, nb_rb * RE_PER_RB_OUT_DMRS, 0, nb_rb * RE_PER_RB_OUT_DMRS); avgs = cmax(avgs, tmp); } return avgs; @@ -236,8 +239,8 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, c16_t rxdataF[][rxdataF_sz], int32_t est_size, c16_t dl_ch_estimates[][est_size], - c16_t rxdataF_ext[][coreset_nbr_rb * 9], - c16_t dl_ch_estimates_ext[][coreset_nbr_rb * 9], + c16_t rxdataF_ext[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS], + c16_t dl_ch_estimates_ext[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS], int symbol, NR_DL_FRAME_PARMS *frame_parms, uint8_t *coreset_freq_dom, @@ -254,9 +257,6 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, * */ -#define NBR_RE_PER_RB_WITH_DMRS 12 - // after removing the 3 DMRS RE, the RB contains 9 RE with PDCCH -#define NBR_RE_PER_RB_WITHOUT_DMRS 9 for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { const c16_t *dl_ch0 = dl_ch_estimates[aarx] + frame_parms->ofdm_symbol_size * symbol; c16_t *rxFbase = rxdataF[aarx] + frame_parms->ofdm_symbol_size * symbol; @@ -297,47 +297,45 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, if ((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) // if RB to be treated is lower than middle system bandwidth then rxdataF pointed // at (offset + c_br + symbol * ofdm_symbol_size): even case - rxF = rxFbase + (frame_parms->first_carrier_offset + 12 * c_rb) + n_BWP_start * 12; + rxF = rxFbase + (frame_parms->first_carrier_offset + RE_PER_RB * c_rb) + n_BWP_start * RE_PER_RB; else // number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC) // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF // we point at the 1st part of the rxdataF in symbol - rxF = rxFbase + 12 * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)); + rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)); } else { if ((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) // if RB to be treated is lower than middle system bandwidth then rxdataF pointed // at (offset + c_br + symbol * ofdm_symbol_size): odd case - rxF = rxFbase + frame_parms->first_carrier_offset + 12 * (c_rb + n_BWP_start); + rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start); else if ((c_rb + n_BWP_start) > (frame_parms->N_RB_DL >> 1)) // number of RBs is odd and c_rb is higher than half system bandwidth + 1 // if these conditions are true the pointer has to be situated at the 1st part of // the rxdataF just after the first IQ symbols of the RB containing DC // we point at the 1st part of the rxdataF in symbol - rxF = rxFbase + 12 * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)) - 6; + rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)) - 6; else - rxF = rxFbase + frame_parms->first_carrier_offset + 12 * (c_rb + n_BWP_start); + rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start); } - const int valid_re[NBR_RE_PER_RB_WITHOUT_DMRS] = {0, 2, 3, 4, 6, 7, 8, 10, 11}; + const int valid_re[RE_PER_RB_OUT_DMRS] = {0, 2, 3, 4, 6, 7, 8, 10, 11}; for (int i = 0; i < sizeofArray(valid_re); i++) { - rxF_ext[i] = rxF[valid_re[i]]; - dl_ch0_ext[i] = dl_ch0[valid_re[i]]; + *rxF_ext++ = rxF[valid_re[i]]; + *dl_ch0_ext++ = dl_ch0[valid_re[i]]; } - dl_ch0_ext += NBR_RE_PER_RB_WITHOUT_DMRS; - rxF_ext += NBR_RE_PER_RB_WITHOUT_DMRS; - dl_ch0 += NBR_RE_PER_RB_WITH_DMRS; + dl_ch0 += RE_PER_RB; } } } static void nr_pdcch_channel_compensation(uint32_t coreset_nbr_rb, - c16_t rxdataF_ext[][coreset_nbr_rb * 9], - c16_t dl_ch_estimates_ext[][coreset_nbr_rb * 9], - c16_t rxdataF_comp[][coreset_nbr_rb * 12], + c16_t rxdataF_ext[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS], + c16_t dl_ch_estimates_ext[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS], + c16_t rxdataF_comp[][coreset_nbr_rb * RE_PER_RB], int antRx, uint8_t output_shift) { for (int aarx = 0; aarx < antRx; aarx++) { - const int sz = coreset_nbr_rb * 9; + const int sz = coreset_nbr_rb * RE_PER_RB_OUT_DMRS; c16_t *dl_ch = dl_ch_estimates_ext[aarx]; c16_t *rxdataF = rxdataF_ext[aarx]; c16_t *rxdataF_c = rxdataF_comp[aarx]; @@ -357,10 +355,10 @@ static void nr_pdcch_channel_compensation(uint32_t coreset_nbr_rb, } } -static void nr_pdcch_detection_mrc(int n_rb, c16_t rxdataF_comp[][n_rb * 9]) +static void nr_pdcch_detection_mrc(int n_rb, c16_t rxdataF_comp[][n_rb * RE_PER_RB_OUT_DMRS]) { LOG_D(NR_PHY_DCI, "we enter nr_pdcch_detection_mrc (hard coded 2 antennas)\n"); - const int sz = n_rb * 9; + const int sz = n_rb * RE_PER_RB_OUT_DMRS; simde__m128i *rxdataF_comp128_0 = (simde__m128i *)rxdataF_comp[0]; simde__m128i *rxdataF_comp128_1 = (simde__m128i *)rxdataF_comp[1]; @@ -387,9 +385,9 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, const int antRx = frame_parms->nb_antennas_rx; // Pointers to extracted PDCCH symbols in frequency-domain. - int32_t rx_size = ((4 * frame_parms->N_RB_DL * 12 + 31) >> 5) << 5; + int32_t rx_size = ((4 * frame_parms->N_RB_DL * RE_PER_RB + 31) >> 5) << 5; // Pointer to llrs, 4-bit resolution. - int32_t llr_size = 4 * n_rb * 9; + int32_t llr_size = 4 * n_rb * RE_PER_RB_OUT_DMRS; c16_t llr[llr_size]; memset(llr, 0, sizeof(llr)); @@ -401,8 +399,8 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, for (int s=rel15->coreset.StartSymbolIndex; s<(rel15->coreset.StartSymbolIndex+rel15->coreset.duration); s++) { LOG_D(NR_PHY_DCI, "in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n"); - __attribute__((aligned(32))) c16_t rxdataF_ext[antRx][n_rb * 9]; - __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[antRx][n_rb * 9]; + __attribute__((aligned(32))) c16_t rxdataF_ext[antRx][n_rb * RE_PER_RB_OUT_DMRS]; + __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[antRx][n_rb * RE_PER_RB_OUT_DMRS]; nr_pdcch_extract_rbs_single(ue->frame_parms.samples_per_slot_wCP, n_rb, rxdataF, @@ -429,7 +427,7 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, LOG_D(NR_PHY_DCI, "we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n", log2_maxh); LOG_D(NR_PHY_DCI, "in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n"); // compute LLRs for ofdm symbol 0 only - __attribute__((aligned(32))) c16_t rxdataF_comp[antRx][n_rb * 12]; + __attribute__((aligned(32))) c16_t rxdataF_comp[antRx][n_rb * RE_PER_RB]; nr_pdcch_channel_compensation(n_rb, rxdataF_ext, pdcch_dl_ch_estimates_ext, @@ -437,10 +435,10 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, antRx, log2_maxh); // log2_maxh+I0_shift - UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), antRx, n_rb * 12, 0); + UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), antRx, n_rb * RE_PER_RB, 0); if (antRx > 1) - nr_pdcch_detection_mrc(n_rb * 12, rxdataF_comp); + nr_pdcch_detection_mrc(n_rb * RE_PER_RB, rxdataF_comp); LOG_D(NR_PHY_DCI, "we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n", s); LOG_D(NR_PHY_DCI, "in nr_pdcch_llr(rxdataF_comp -> llr)\n"); @@ -572,6 +570,6 @@ void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, rel15->dci_format_options[k]); } } - e_rx_cand_idx += 9 * L * 6; // e_rx index for next candidate (L CCEs, 6 REGs per CCE and 9 REs per REG ) + e_rx_cand_idx += RE_PER_RB_OUT_DMRS * L * 6; // e_rx index for next candidate (L CCEs, 6 REGs per CCE and 9 REs per REG ) } } From b41c9e2e851e17683dfdd8b1879c017088049b87 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Tue, 22 Jul 2025 19:35:51 +0200 Subject: [PATCH 7/9] move static some functions that are used only in one file --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 2 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 49 +--------- .../NR_MAC_UE/nr_ue_dci_configuration.c | 10 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 98 +++++++++++++------ openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 10 +- 5 files changed, 80 insertions(+), 89 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 297be42261..dc01be2f98 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -548,7 +548,7 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t } } -void release_common_ss_cset(NR_BWP_PDCCH_t *pdcch) +static void release_common_ss_cset(NR_BWP_PDCCH_t *pdcch) { pdcch->otherSI_SS_id = -1; pdcch->ra_SS_id = -1; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index aacbbdcab2..29c1d7c51b 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -59,8 +59,6 @@ void nr_ue_mac_default_configs(NR_UE_MAC_INST_t *mac); void nr_ue_decode_mib(NR_UE_MAC_INST_t *mac, int cc_id); -void release_common_ss_cset(NR_BWP_PDCCH_t *pdcch); - /**\brief decode SIB1 and other SIs pdus in NR_UE, from if_module dl_ind \param mac pointer to MAC instance \param cc_id component carrier id @@ -117,12 +115,6 @@ void nr_ue_dl_scheduler(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info csi_payload_t nr_ue_aperiodic_csi_reporting(NR_UE_MAC_INST_t *mac, dci_field_t csi_request, int tda, long *K2); -/*! \fn int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id); - \brief This function schedules a positive or negative SR for schedulingRequestID sr_id - depending on the presence of any active SR and the prohibit timer. - If the max number of retransmissions is reached, it triggers a new RA */ -int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id); - nr_dci_format_t nr_ue_process_dci_indication_pdu(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, fapi_nr_dci_indication_pdu_t *dci); int8_t nr_ue_process_csirs_measurements(NR_UE_MAC_INST_t *mac, @@ -138,30 +130,11 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, int nr_get_csi_measurements(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sched_t *pucch); -csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, - struct NR_CSI_ReportConfig *csi_reportconfig, - NR_CSI_ResourceConfigId_t csi_ResourceConfigId, - NR_CSI_MeasConfig_t *csi_MeasConfig); - -csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, - struct NR_CSI_ReportConfig *csi_reportconfig, - NR_CSI_ResourceConfigId_t csi_ResourceConfigId, - NR_CSI_MeasConfig_t *csi_MeasConfig, - CSI_mapping_t mapping_type); - -csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, - struct NR_CSI_ReportConfig *csi_reportconfig, - NR_CSI_ResourceConfigId_t csi_ResourceConfigId, - const NR_CSI_MeasConfig_t *csi_MeasConfig); - csi_payload_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac, int csi_report_id, CSI_mapping_t mapping_type, NR_CSI_MeasConfig_t *csi_MeasConfig); -uint8_t get_rsrp_index(int rsrp); -uint8_t get_rsrp_diff_index(int best_rsrp,int current_rsrp); - /* \brief Get payload (MAC PDU) from UE PHY @param dl_info pointer to dl indication @param ul_time_alignment pointer to timing advance parameters @@ -170,8 +143,6 @@ uint8_t get_rsrp_diff_index(int best_rsrp,int current_rsrp); */ void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id); -void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac,nr_downlink_indication_t *dl_info, int pdu_id); - typedef struct { union { NR_BSR_SHORT s; @@ -187,28 +158,12 @@ int nr_write_ce_ulsch_pdu(uint8_t *mac_ce, const type_bsr_t *bsr, uint8_t *mac_ce_end); -void config_dci_pdu(NR_UE_MAC_INST_t *mac, - fapi_nr_dl_config_request_t *dl_config, - const int rnti_type, - const int slot, - const NR_SearchSpace_t *ss); - void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl_config, const frame_t frame, const int slot); void set_precoding_information_parameters(nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu, int n_antenna_port, long transformPrecoder, int precoding_information, NR_PUSCH_Config_t *pusch_Config); -void set_harq_status(NR_UE_MAC_INST_t *mac, - uint8_t pucch_id, - uint8_t harq_id, - int8_t delta_pucch, - uint16_t data_toul_fb, - uint8_t dai, - int n_CCE, - int N_CCE, - frame_t frame, - int slot); bool get_downlink_ack(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sched_t *pucch); initial_pucch_resource_t get_initial_pucch_resource(const int idx); @@ -285,9 +240,7 @@ and fills the PRACH PDU per each FD occasion. @param slotP Slot index @returns void */ -void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP); -void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot); -void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot); + void configure_csi_resource_mapping(fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_config_pdu, NR_CSI_RS_ResourceMapping_t *resourceMapping, uint32_t bwp_size, diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index 7a2e9c6ed9..388b28f846 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -104,11 +104,11 @@ NR_ControlResourceSet_t *ue_get_coreset(const NR_BWP_PDCCH_t *config, const int return coreset; } -void config_dci_pdu(NR_UE_MAC_INST_t *mac, - fapi_nr_dl_config_request_t *dl_config, - const int rnti_type, - const int slot, - const NR_SearchSpace_t *ss) +static void config_dci_pdu(NR_UE_MAC_INST_t *mac, + fapi_nr_dl_config_request_t *dl_config, + const int rnti_type, + const int slot, + const NR_SearchSpace_t *ss) { const NR_UE_DL_BWP_t *current_DL_BWP = mac->current_DL_BWP; const NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 8a892557b2..e623900f29 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -113,6 +113,43 @@ random-access procedure */ static void nr_ue_process_rar(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id); +/*! \fn int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id); + \brief This function schedules a positive or negative SR for schedulingRequestID sr_id + depending on the presence of any active SR and the prohibit timer. + If the max number of retransmissions is reached, it triggers a new RA */ +static int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id); + +static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + NR_CSI_MeasConfig_t *csi_MeasConfig); + +static csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + NR_CSI_MeasConfig_t *csi_MeasConfig, + CSI_mapping_t mapping_type); +static csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + const NR_CSI_MeasConfig_t *csi_MeasConfig); +static uint8_t get_rsrp_index(int rsrp); + +static uint8_t get_rsrp_diff_index(int best_rsrp, int current_rsrp); + +static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id); + +static void set_harq_status(NR_UE_MAC_INST_t *mac, + uint8_t pucch_id, + uint8_t harq_id, + int8_t delta_pucch, + uint16_t data_toul_fb, + uint8_t dai, + int n_CCE, + int N_CCE, + frame_t frame, + int slot); + int get_pucch0_mcs(const int O_ACK, const int O_SR, const int ack_payload, const int sr_payload) { int mcs = 0; @@ -1442,16 +1479,16 @@ int8_t nr_ue_process_csirs_measurements(NR_UE_MAC_INST_t *mac, return 0; } -void set_harq_status(NR_UE_MAC_INST_t *mac, - uint8_t pucch_id, - uint8_t harq_id, - int8_t delta_pucch, - uint16_t data_toul_fb, - uint8_t dai, - int n_CCE, - int N_CCE, - frame_t frame, - int slot) +static void set_harq_status(NR_UE_MAC_INST_t *mac, + uint8_t pucch_id, + uint8_t harq_id, + int8_t delta_pucch, + uint16_t data_toul_fb, + uint8_t dai, + int n_CCE, + int N_CCE, + frame_t frame, + int slot) { NR_UE_DL_HARQ_STATUS_t *current_harq = &mac->dl_harq_info[harq_id]; current_harq->active = true; @@ -2527,7 +2564,7 @@ bool trigger_periodic_scheduling_request(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *p return sr_count > 0; } -int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id) +static int8_t nr_ue_get_SR(NR_UE_MAC_INST_t *mac, frame_t frame, slot_t slot, NR_SchedulingRequestId_t sr_id) { // no UL-SCH resources available for this tti && UE has a valid PUCCH resources for SR configuration for this tti NR_UE_SCHEDULING_INFO *si = &mac->scheduling_info; @@ -2811,11 +2848,10 @@ csi_payload_t nr_get_csi_payload(NR_UE_MAC_INST_t *mac, return csi; } - -csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, - struct NR_CSI_ReportConfig *csi_reportconfig, - NR_CSI_ResourceConfigId_t csi_ResourceConfigId, - NR_CSI_MeasConfig_t *csi_MeasConfig) +static csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + NR_CSI_MeasConfig_t *csi_MeasConfig) { int nb_ssb = 0; // nb of ssb in the resource int nb_meas = 0; // nb of ssb to report measurements on @@ -2892,11 +2928,11 @@ csi_payload_t get_ssb_rsrp_payload(NR_UE_MAC_INST_t *mac, return csi; } -csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, - struct NR_CSI_ReportConfig *csi_reportconfig, - NR_CSI_ResourceConfigId_t csi_ResourceConfigId, - NR_CSI_MeasConfig_t *csi_MeasConfig, - CSI_mapping_t mapping_type) +static csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + NR_CSI_MeasConfig_t *csi_MeasConfig, + CSI_mapping_t mapping_type) { int p1_bits = 0; int p2_bits = 0; @@ -2980,10 +3016,10 @@ csi_payload_t get_csirs_RI_PMI_CQI_payload(NR_UE_MAC_INST_t *mac, return csi; } -csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, - struct NR_CSI_ReportConfig *csi_reportconfig, - NR_CSI_ResourceConfigId_t csi_ResourceConfigId, - const NR_CSI_MeasConfig_t *csi_MeasConfig) +static csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, + struct NR_CSI_ReportConfig *csi_reportconfig, + NR_CSI_ResourceConfigId_t csi_ResourceConfigId, + const NR_CSI_MeasConfig_t *csi_MeasConfig) { int n_bits = 0; uint64_t temp_payload = 0; @@ -3047,8 +3083,8 @@ csi_payload_t get_csirs_RSRP_payload(NR_UE_MAC_INST_t *mac, // returns index from RSRP // according to Table 10.1.6.1-1 in 38.133 -uint8_t get_rsrp_index(int rsrp) { - +static uint8_t get_rsrp_index(int rsrp) +{ int index = rsrp + 157; if (rsrp>-44) index = 113; @@ -3058,17 +3094,15 @@ uint8_t get_rsrp_index(int rsrp) { return index; } - // returns index from differential RSRP // according to Table 10.1.6.1-2 in 38.133 -uint8_t get_rsrp_diff_index(int best_rsrp,int current_rsrp) { - +static uint8_t get_rsrp_diff_index(int best_rsrp, int current_rsrp) +{ int diff = best_rsrp-current_rsrp; if (diff>30) return 15; else return (diff>>1); - } void nr_ue_send_sdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id) @@ -3697,7 +3731,7 @@ static int nr_ue_validate_successrar(uint8_t *pduP, // F: lenght of L is 0:8 or 1:16 bits wide // R: Reserved bit, set to zero. //////////////////////////////// -void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id) +static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info, int pdu_id) { frame_t frameP = dl_info->frame; int slot = dl_info->slot; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 6c257bcacf..3e90445aa3 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -78,6 +78,10 @@ static uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac, int P_MAX, bool *BSRsent); +static void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP); +static void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot); +static void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot); + static void clear_ul_config_request(NR_UE_MAC_INST_t *mac) { int slots = mac->frame_structure.numb_slots_frame; @@ -1709,7 +1713,7 @@ static bool schedule_uci_on_pusch(NR_UE_MAC_INST_t *mac, return mux_done; } -void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP) +static void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP) { PUCCH_sched_t pucch[3] = {0}; // TODO the size might change in the future in case of multiple SR or multiple CSI in a slot @@ -1784,7 +1788,7 @@ void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP) } } -void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot) +static void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot) { if (!mac->sc_info.csi_MeasConfig) return; @@ -2025,7 +2029,7 @@ void configure_csi_resource_mapping(fapi_nr_dl_config_csirs_pdu_rel15_t *csirs_c } } -void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot) +static void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot) { if (!mac->sc_info.csi_MeasConfig) return; From 343b983aa99d8526bbdc7a1e42822f5eeccd36c9 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Wed, 23 Jul 2025 08:23:26 +0200 Subject: [PATCH 8/9] fix SIMD tail length in nr_pdcch_detection_mrc() and replace >> operator by / --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 30 +++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 5f41880251..9449ee3084 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -185,7 +185,6 @@ static void nr_pdcch_demapping_deinterleaving(c16_t *llr, } static void nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, - int32_t rx_size, uint32_t coreset_nbr_rb, c16_t rxdataF_comp[coreset_nbr_rb * RE_PER_RB], c16_t *pdcch_llr, @@ -288,13 +287,13 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, int c_rb_by6 = c_rb / 6; // skip zeros in frequency domain bitmap - while ((coreset_freq_dom[c_rb_by6 >> 3] & (1 << (7 - (c_rb_by6 & 7)))) == 0) { + while ((coreset_freq_dom[c_rb_by6 / 8] & (1 << (7 - (c_rb_by6 & 7)))) == 0) { c_rb += 6; c_rb_by6 = c_rb / 6; } c16_t *rxF = NULL; if ((frame_parms->N_RB_DL & 1) == 0) { - if ((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) + if ((c_rb + n_BWP_start) < frame_parms->N_RB_DL / 2) // if RB to be treated is lower than middle system bandwidth then rxdataF pointed // at (offset + c_br + symbol * ofdm_symbol_size): even case rxF = rxFbase + (frame_parms->first_carrier_offset + RE_PER_RB * c_rb) + n_BWP_start * RE_PER_RB; @@ -302,18 +301,18 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, // number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC) // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF // we point at the 1st part of the rxdataF in symbol - rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)); + rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - frame_parms->N_RB_DL / 2); } else { - if ((c_rb + n_BWP_start) < (frame_parms->N_RB_DL >> 1)) + if ((c_rb + n_BWP_start) < frame_parms->N_RB_DL / 2) // if RB to be treated is lower than middle system bandwidth then rxdataF pointed // at (offset + c_br + symbol * ofdm_symbol_size): odd case rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start); - else if ((c_rb + n_BWP_start) > (frame_parms->N_RB_DL >> 1)) + else if ((c_rb + n_BWP_start) > frame_parms->N_RB_DL / 2) // number of RBs is odd and c_rb is higher than half system bandwidth + 1 // if these conditions are true the pointer has to be situated at the 1st part of // the rxdataF just after the first IQ symbols of the RB containing DC // we point at the 1st part of the rxdataF in symbol - rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - (frame_parms->N_RB_DL >> 1)) - 6; + rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - frame_parms->N_RB_DL / 2) - 6; else rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start); } @@ -360,14 +359,17 @@ static void nr_pdcch_detection_mrc(int n_rb, c16_t rxdataF_comp[][n_rb * RE_PER_ LOG_D(NR_PHY_DCI, "we enter nr_pdcch_detection_mrc (hard coded 2 antennas)\n"); const int sz = n_rb * RE_PER_RB_OUT_DMRS; - simde__m128i *rxdataF_comp128_0 = (simde__m128i *)rxdataF_comp[0]; - simde__m128i *rxdataF_comp128_1 = (simde__m128i *)rxdataF_comp[1]; + c16_t *rx0 = rxdataF_comp[0]; + c16_t *rx1 = rxdataF_comp[1]; // MRC on each re of rb - for (int i = 0; i < sz >> 2; i++) { - rxdataF_comp128_0[i] = - simde_mm_adds_epi16(simde_mm_srai_epi16(rxdataF_comp128_0[i], 1), simde_mm_srai_epi16(rxdataF_comp128_1[i], 1)); + int i = 0; + for (; i < (sz & ~3); i += 4) { + *(simde__m128i *)(rx0 + i) = + simde_mm_adds_epi16(simde_mm_srai_epi16(*(simde__m128i *)(rx0 + i), 1), simde_mm_srai_epi16(*(simde__m128i *)(rx1 + i), 1)); } + for (; i < sz; i++) + rx0[i] = (c16_t){(rx0[i].r + rx1[i].r) / 2, (rx0[i].i + rx1[i].i) / 2}; } void nr_rx_pdcch(PHY_VARS_NR_UE *ue, @@ -384,8 +386,6 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, get_coreset_rballoc(rel15->coreset.frequency_domain_resource,&n_rb,&rb_offset); const int antRx = frame_parms->nb_antennas_rx; - // Pointers to extracted PDCCH symbols in frequency-domain. - int32_t rx_size = ((4 * frame_parms->N_RB_DL * RE_PER_RB + 31) >> 5) << 5; // Pointer to llrs, 4-bit resolution. int32_t llr_size = 4 * n_rb * RE_PER_RB_OUT_DMRS; c16_t llr[llr_size]; @@ -442,7 +442,7 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, LOG_D(NR_PHY_DCI, "we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n", s); LOG_D(NR_PHY_DCI, "in nr_pdcch_llr(rxdataF_comp -> llr)\n"); - nr_pdcch_llr(frame_parms, rx_size, n_rb, rxdataF_comp[0], llr, s); + nr_pdcch_llr(frame_parms, n_rb, rxdataF_comp[0], llr, s); UEscopeCopy(ue, pdcchLlr, llr, sizeof(c16_t), 1, llr_size, 0); } From f835705dd143286abbbb2178cba3d87ed88da083 Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Fri, 25 Jul 2025 14:59:05 +0200 Subject: [PATCH 9/9] fix array sizes and aligment issues in 5G UE dci decoder --- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 112 ++++++++------------------ 1 file changed, 35 insertions(+), 77 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 9449ee3084..bf2d91bdc8 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -184,26 +184,9 @@ static void nr_pdcch_demapping_deinterleaving(c16_t *llr, } } -static void nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, - uint32_t coreset_nbr_rb, - c16_t rxdataF_comp[coreset_nbr_rb * RE_PER_RB], - c16_t *pdcch_llr, - uint8_t symbol) +static void nr_pdcch_llr(uint32_t sz, c16_t *rxF, c16_t *llr) { - c16_t *rxF = rxdataF_comp; - c16_t *llr = pdcch_llr + symbol * coreset_nbr_rb * RE_PER_RB_OUT_DMRS; - - if (!llr) { - LOG_E(NR_PHY_DCI, "pdcch_qpsk_llr: llr is null, symbol %d\n", symbol); - return; - } - - LOG_DDD("llr logs: pdcch qpsk llr for symbol %d (pos %d), llr offset %ld\n", - symbol, - symbol * frame_parms->N_RB_DL * RE_PER_RB, - llr - pdcch_llr); - - for (int i = 0; i < coreset_nbr_rb * RE_PER_RB_OUT_DMRS; i++) { + for (int i = 0; i < sz; i++) { // We clip the signal c16_t res; res.r = min(rxF->r, 31); @@ -217,16 +200,14 @@ static void nr_pdcch_llr(NR_DL_FRAME_PARMS *frame_parms, } //compute average channel_level on each (TX,RX) antenna pair -static int32_t nr_pdcch_channel_level(int nb_rb, - c16_t dl_ch_estimates_ext[][nb_rb * RE_PER_RB_OUT_DMRS], - int nb_antennas_rx, - int symbol) +static int32_t nr_pdcch_channel_level(int nb_re, int arraySz, c16_t dl_ch_estimates_ext[][arraySz], int nb_antennas_rx) { int32_t avgs = 0; for (int aarx = 0; aarx < nb_antennas_rx; aarx++) { simde__m128i *dl_ch128 = (simde__m128i *)&dl_ch_estimates_ext[aarx]; - //compute average level - int32_t tmp = simde_mm_average(dl_ch128, nb_rb * RE_PER_RB_OUT_DMRS, 0, nb_rb * RE_PER_RB_OUT_DMRS); + // compute average level + // if nb_re is not %4, some samples are missed inside simde_mm_average, so let's discard it + int32_t tmp = simde_mm_average(dl_ch128, nb_re & ~3, 0, nb_re & ~3); avgs = cmax(avgs, tmp); } return avgs; @@ -238,8 +219,9 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, c16_t rxdataF[][rxdataF_sz], int32_t est_size, c16_t dl_ch_estimates[][est_size], - c16_t rxdataF_ext[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS], - c16_t dl_ch_estimates_ext[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS], + int arraySz, + c16_t rxdataF_ext[][arraySz], + c16_t dl_ch_estimates_ext[][arraySz], int symbol, NR_DL_FRAME_PARMS *frame_parms, uint8_t *coreset_freq_dom, @@ -296,25 +278,23 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, if ((c_rb + n_BWP_start) < frame_parms->N_RB_DL / 2) // if RB to be treated is lower than middle system bandwidth then rxdataF pointed // at (offset + c_br + symbol * ofdm_symbol_size): even case - rxF = rxFbase + (frame_parms->first_carrier_offset + RE_PER_RB * c_rb) + n_BWP_start * RE_PER_RB; + rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start); else // number of RBs is even and c_rb is higher than half system bandwidth (we don't skip DC) // if these conditions are true the pointer has to be situated at the 1st part of the rxdataF // we point at the 1st part of the rxdataF in symbol rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - frame_parms->N_RB_DL / 2); } else { - if ((c_rb + n_BWP_start) < frame_parms->N_RB_DL / 2) + if ((c_rb + n_BWP_start) <= frame_parms->N_RB_DL / 2) // if RB to be treated is lower than middle system bandwidth then rxdataF pointed // at (offset + c_br + symbol * ofdm_symbol_size): odd case rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start); - else if ((c_rb + n_BWP_start) > frame_parms->N_RB_DL / 2) - // number of RBs is odd and c_rb is higher than half system bandwidth + 1 + else + // number of RBs is odd and c_rb is higher than half system bandwidth + 1 // if these conditions are true the pointer has to be situated at the 1st part of // the rxdataF just after the first IQ symbols of the RB containing DC // we point at the 1st part of the rxdataF in symbol rxF = rxFbase + RE_PER_RB * (c_rb + n_BWP_start - frame_parms->N_RB_DL / 2) - 6; - else - rxF = rxFbase + frame_parms->first_carrier_offset + RE_PER_RB * (c_rb + n_BWP_start); } const int valid_re[RE_PER_RB_OUT_DMRS] = {0, 2, 3, 4, 6, 7, 8, 10, 11}; for (int i = 0; i < sizeofArray(valid_re); i++) { @@ -326,50 +306,31 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, } } -static void nr_pdcch_channel_compensation(uint32_t coreset_nbr_rb, - c16_t rxdataF_ext[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS], - c16_t dl_ch_estimates_ext[][coreset_nbr_rb * RE_PER_RB_OUT_DMRS], - c16_t rxdataF_comp[][coreset_nbr_rb * RE_PER_RB], +static void nr_pdcch_channel_compensation(int arraySz, + c16_t rxdataF_ext[][arraySz], + c16_t dl_ch_estimates_ext[][arraySz], + c16_t rxdataF_comp[][arraySz], int antRx, uint8_t output_shift) { for (int aarx = 0; aarx < antRx; aarx++) { - const int sz = coreset_nbr_rb * RE_PER_RB_OUT_DMRS; - c16_t *dl_ch = dl_ch_estimates_ext[aarx]; - c16_t *rxdataF = rxdataF_ext[aarx]; - c16_t *rxdataF_c = rxdataF_comp[aarx]; - // multiply by conjugated channel - mult_cpx_conj_vector(dl_ch, rxdataF, rxdataF_c, sz, output_shift); - for (int rb = 0; rb < sz; rb++) - LOG_DDD("rxdataF[%d]=(%d,%d) X dlch[%d]=(%d,%d) rxdataF_comp[%d]=(%d,%d)\n", - rb, - rxdataF[rb].r, - rxdataF[rb].i, - rb, - dl_ch[rb].r, - dl_ch[rb].i, - rb, - rxdataF_c[rb].r, - rxdataF_c[rb].i); + // multiply by conjugated channel, this function require size in _m128i, else it doesn't process all samples + mult_cpx_conj_vector(dl_ch_estimates_ext[aarx], rxdataF_ext[aarx], rxdataF_comp[aarx], arraySz, output_shift); } } -static void nr_pdcch_detection_mrc(int n_rb, c16_t rxdataF_comp[][n_rb * RE_PER_RB_OUT_DMRS]) +static void nr_pdcch_detection_mrc(int sz, c16_t rxdataF_comp[][sz]) { LOG_D(NR_PHY_DCI, "we enter nr_pdcch_detection_mrc (hard coded 2 antennas)\n"); - const int sz = n_rb * RE_PER_RB_OUT_DMRS; - c16_t *rx0 = rxdataF_comp[0]; c16_t *rx1 = rxdataF_comp[1]; // MRC on each re of rb - int i = 0; - for (; i < (sz & ~3); i += 4) { + // input always aligned and accepting tail padding to process all actual samples + for (int i = 0; i < sz; i += 4) { *(simde__m128i *)(rx0 + i) = simde_mm_adds_epi16(simde_mm_srai_epi16(*(simde__m128i *)(rx0 + i), 1), simde_mm_srai_epi16(*(simde__m128i *)(rx1 + i), 1)); } - for (; i < sz; i++) - rx0[i] = (c16_t){(rx0[i].r + rx1[i].r) / 2, (rx0[i].i + rx1[i].i) / 2}; } void nr_rx_pdcch(PHY_VARS_NR_UE *ue, @@ -387,25 +348,25 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, const int antRx = frame_parms->nb_antennas_rx; // Pointer to llrs, 4-bit resolution. - int32_t llr_size = 4 * n_rb * RE_PER_RB_OUT_DMRS; + int32_t llr_size = (rel15->coreset.duration-rel15->coreset.StartSymbolIndex) * n_rb * RE_PER_RB_OUT_DMRS; c16_t llr[llr_size]; - memset(llr, 0, sizeof(llr)); LOG_D(NR_PHY_DCI, "pdcch coreset: freq %x, n_rb %d, rb_offset %d\n", rel15->coreset.frequency_domain_resource[0], n_rb, rb_offset); - for (int s=rel15->coreset.StartSymbolIndex; s<(rel15->coreset.StartSymbolIndex+rel15->coreset.duration); s++) { + for (int s = rel15->coreset.StartSymbolIndex; s < rel15->coreset.StartSymbolIndex + rel15->coreset.duration; s++) { LOG_D(NR_PHY_DCI, "in nr_pdcch_extract_rbs_single(rxdataF -> rxdataF_ext || dl_ch_estimates -> dl_ch_estimates_ext)\n"); - - __attribute__((aligned(32))) c16_t rxdataF_ext[antRx][n_rb * RE_PER_RB_OUT_DMRS]; - __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[antRx][n_rb * RE_PER_RB_OUT_DMRS]; + const int arraySz = ceil_mod(n_rb * RE_PER_RB_OUT_DMRS, 32); + __attribute__((aligned(32))) c16_t rxdataF_ext[antRx][arraySz]; + __attribute__((aligned(32))) c16_t pdcch_dl_ch_estimates_ext[antRx][arraySz]; nr_pdcch_extract_rbs_single(ue->frame_parms.samples_per_slot_wCP, n_rb, rxdataF, pdcch_est_size, pdcch_dl_ch_estimates, + arraySz, rxdataF_ext, pdcch_dl_ch_estimates_ext, s, @@ -415,7 +376,7 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, LOG_D(NR_PHY_DCI, "in nr_pdcch_channel_level(dl_ch_estimates_ext -> dl_ch_estimates_ext)\n"); // compute channel level based on ofdm symbol 0 - int32_t avgs = nr_pdcch_channel_level(n_rb, pdcch_dl_ch_estimates_ext, antRx, s); + int32_t avgs = nr_pdcch_channel_level(n_rb, arraySz, pdcch_dl_ch_estimates_ext, antRx); uint8_t log2_maxh = (log2_approx(avgs) / 2) + 5; //+antRx; #ifdef UE_DEBUG_TRACE @@ -427,25 +388,22 @@ void nr_rx_pdcch(PHY_VARS_NR_UE *ue, LOG_D(NR_PHY_DCI, "we enter nr_pdcch_channel_compensation(log2_maxh=%d)\n", log2_maxh); LOG_D(NR_PHY_DCI, "in nr_pdcch_channel_compensation(rxdataF_ext x dl_ch_estimates_ext -> rxdataF_comp)\n"); // compute LLRs for ofdm symbol 0 only - __attribute__((aligned(32))) c16_t rxdataF_comp[antRx][n_rb * RE_PER_RB]; - nr_pdcch_channel_compensation(n_rb, + __attribute__((aligned(32))) c16_t rxdataF_comp[antRx][arraySz]; + nr_pdcch_channel_compensation(arraySz, rxdataF_ext, pdcch_dl_ch_estimates_ext, rxdataF_comp, antRx, log2_maxh); // log2_maxh+I0_shift - UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), antRx, n_rb * RE_PER_RB, 0); + UEscopeCopy(ue, pdcchRxdataF_comp, rxdataF_comp, sizeof(struct complex16), antRx, n_rb * RE_PER_RB_OUT_DMRS, 0); if (antRx > 1) - nr_pdcch_detection_mrc(n_rb * RE_PER_RB, rxdataF_comp); + nr_pdcch_detection_mrc(arraySz, rxdataF_comp); - LOG_D(NR_PHY_DCI, "we enter nr_pdcch_llr(for symbol %d), pdcch_vars[eNB_id]->rxdataF_comp ---> pdcch_vars[eNB_id]->llr \n", s); - LOG_D(NR_PHY_DCI, "in nr_pdcch_llr(rxdataF_comp -> llr)\n"); - nr_pdcch_llr(frame_parms, n_rb, rxdataF_comp[0], llr, s); - - UEscopeCopy(ue, pdcchLlr, llr, sizeof(c16_t), 1, llr_size, 0); + nr_pdcch_llr(n_rb * RE_PER_RB_OUT_DMRS, rxdataF_comp[0], llr + s * n_rb * RE_PER_RB_OUT_DMRS); } + UEscopeCopy(ue, pdcchLlr, llr, sizeof(c16_t), 1, llr_size, 0); nr_pdcch_demapping_deinterleaving(llr, pdcch_e_rx,