diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index b8663aa435..327a86ea47 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -462,92 +462,117 @@ static inline void do_txdataF(c16_t **txdataF, int start_sc, int txdataF_offset_per_symbol) { - NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - int rb = 0; - uint16_t subCarrier = start_sc; - const nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming; - while (rb < rel15->rbSize) { - // get pmi info - const int pmi = (pb->prg_size > 0) ? (pb->prgs_list[(int)rb / pb->prg_size].pm_idx) : 0; - const int pmi2 = (rb < (rel15->rbSize - 1) && pb->prg_size > 0) ? (pb->prgs_list[(int)(rb + 1) / pb->prg_size].pm_idx) : -1; - const int pmi3 = (rb < (rel15->rbSize - 2) && pb->prg_size > 0) ? (pb->prgs_list[(int)(rb + 2) / pb->prg_size].pm_idx) : -1; - const int pmi4 = (rb < (rel15->rbSize - 3) && pb->prg_size > 0) ? (pb->prgs_list[(int)(rb + 3) / pb->prg_size].pm_idx) : -1; + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + int rb = 0; + uint16_t subCarrier = start_sc; + const nfapi_nr_tx_precoding_and_beamforming_t *pb = &rel15->precodingAndBeamforming; - // If pmi of next RB and pmi of current RB are the same, we do 2 RB in a row - // if pmi differs, or current rb is the end (rel15->rbSize - 1), than we do 1 RB in a row - int rb_step0 = pmi == pmi2 ? 2 : 1; - const int rb_step = rb_step0==2 && pmi3==pmi && pmi4==pmi ? 4 : rb_step0; - const int re_cnt = NR_NB_SC_PER_RB * rb_step; - if (pmi == 0) { // unitary Precoding - if (subCarrier + re_cnt <= symbol_sz) { // RB does not cross DC - if (ant < rel15->nrOfLayers) - memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], - &txdataF_precoding[ant][subCarrier], - re_cnt * sizeof(**txdataF)); - else - memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, re_cnt * sizeof(**txdataF)); - } else { // RB does cross DC - const int neg_length = symbol_sz - subCarrier; - const int pos_length = re_cnt - neg_length; - if (ant < rel15->nrOfLayers) { - memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], - &txdataF_precoding[ant][subCarrier], - neg_length * sizeof(**txdataF)); - memcpy(&txdataF[ant][txdataF_offset_per_symbol], &txdataF_precoding[ant], pos_length * sizeof(**txdataF)); + // Compute which layer this antenna carries under identity precoding. + // Standard identity maps layer N → antenna N, but when antennas are muted + // we must remap layers to active antennas. Otherwise layer data sent to a + // muted antenna is lost (RU blanks it) while active antennas sit idle. + // E.g. mask=0x0D (ant 1 muted, 3 layers): ant0→L0, ant2→L1, ant3→L2. + int identity_layer = -1; + { + const nr_antenna_state_t *ast = &gNB->antenna_state; + int active_count = nr_get_active_tx_antenna_count(ast); + if (active_count > 0 && active_count < frame_parms->nb_antennas_tx) { + if (nr_is_tx_antenna_active(ast, ant)) { + identity_layer = 0; + for (int a = 0; a < ant; a++) + if (nr_is_tx_antenna_active(ast, a)) + identity_layer++; + if (identity_layer >= rel15->nrOfLayers) + identity_layer = -1; + } } else { - memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, neg_length * sizeof(**txdataF)); - memset(&txdataF[ant][txdataF_offset_per_symbol], 0, pos_length * sizeof(**txdataF)); + // No muting: standard identity (layer N = antenna N) + identity_layer = (ant < rel15->nrOfLayers) ? ant : -1; } - } - subCarrier += re_cnt; - if (subCarrier >= symbol_sz) { - subCarrier -= symbol_sz; - } - } else { // non-unitary Precoding - AssertFatal(frame_parms->nb_antennas_tx > 1, "No precoding can be done with a single antenna port\n"); - // get the precoding matrix weights: - nfapi_nr_pm_pdu_t *pmi_pdu = &gNB->gNB_config.pmi_list.pmi_pdu[pmi - 1]; // pmi 0 is identity matrix - AssertFatal(pmi == pmi_pdu->pm_idx, "PMI %d doesn't match to the one in precoding matrix %d\n", pmi, pmi_pdu->pm_idx); - AssertFatal(ant < pmi_pdu->num_ant_ports, - "Antenna port index %d exceeds precoding matrix AP size %d\n", - ant, - pmi_pdu->num_ant_ports); - AssertFatal(rel15->nrOfLayers == pmi_pdu->numLayers, - "Number of layers %d doesn't match to the one in precoding matrix %d\n", - rel15->nrOfLayers, - pmi_pdu->numLayers); - if ((subCarrier + re_cnt) < symbol_sz) { // within ofdm_symbol_size, use SIMDe - nr_layer_precoder_simd(rel15->nrOfLayers, - symbol_sz, - txdataF_precoding, - ant, - pmi_pdu, - subCarrier, - re_cnt, - &txdataF[ant][txdataF_offset_per_symbol]); - subCarrier += re_cnt; - } else { // crossing ofdm_symbol_size, use simple arithmetic operations - for (int i = 0; i < re_cnt; i++) { - txdataF[ant][txdataF_offset_per_symbol + subCarrier] = - nr_layer_precoder_cm(rel15->nrOfLayers, symbol_sz, txdataF_precoding, ant, pmi_pdu, subCarrier); -#ifdef DEBUG_DLSCH_MAPPING - printf("antenna %d\t l %d \t subCarrier %d \t txdataF: %d %d\n", - ant, - l_symbol, - subCarrier, - txdataF[ant][l_symbol * symbol_sz + subCarrier + txdataF_offset].r, - txdataF[ant][l_symbol * symbol_sz + subCarrier + txdataF_offset].i); -#endif - if (++subCarrier >= symbol_sz) { - subCarrier -= symbol_sz; - } - } - } // else{ // crossing ofdm_symbol_size, use simple arithmetic operations - } // else { // non-unitary Precoding + } - rb += rb_step; - } // RB loop: while(rb < rel15->rbSize) + while (rb < rel15->rbSize) { + // get pmi info + const int pmi = (pb->prg_size > 0) ? (pb->prgs_list[(int)rb / pb->prg_size].pm_idx) : 0; + const int pmi2 = (rb < (rel15->rbSize - 1) && pb->prg_size > 0) ? (pb->prgs_list[(int)(rb + 1) / pb->prg_size].pm_idx) : -1; + const int pmi3 = (rb < (rel15->rbSize - 2) && pb->prg_size > 0) ? (pb->prgs_list[(int)(rb + 2) / pb->prg_size].pm_idx) : -1; + const int pmi4 = (rb < (rel15->rbSize - 3) && pb->prg_size > 0) ? (pb->prgs_list[(int)(rb + 3) / pb->prg_size].pm_idx) : -1; + + // If pmi of next RB and pmi of current RB are the same, we do 2 RB in a row + // if pmi differs, or current rb is the end (rel15->rbSize - 1), than we do 1 RB in a row + int rb_step0 = pmi == pmi2 ? 2 : 1; + const int rb_step = rb_step0==2 && pmi3==pmi && pmi4==pmi ? 4 : rb_step0; + const int re_cnt = NR_NB_SC_PER_RB * rb_step; + if (pmi == 0) { // unitary Precoding + if (subCarrier + re_cnt <= symbol_sz) { // RB does not cross DC + if (identity_layer >= 0) + memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], + &txdataF_precoding[identity_layer][subCarrier], + re_cnt * sizeof(**txdataF)); + else + memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, re_cnt * sizeof(**txdataF)); + } else { // RB does cross DC + const int neg_length = symbol_sz - subCarrier; + const int pos_length = re_cnt - neg_length; + if (identity_layer >= 0) { + memcpy(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], + &txdataF_precoding[identity_layer][subCarrier], + neg_length * sizeof(**txdataF)); + memcpy(&txdataF[ant][txdataF_offset_per_symbol], &txdataF_precoding[identity_layer], pos_length * sizeof(**txdataF)); + } else { + memset(&txdataF[ant][txdataF_offset_per_symbol + subCarrier], 0, neg_length * sizeof(**txdataF)); + memset(&txdataF[ant][txdataF_offset_per_symbol], 0, pos_length * sizeof(**txdataF)); + } + } + subCarrier += re_cnt; + if (subCarrier >= symbol_sz) { + subCarrier -= symbol_sz; + } + } else { // non-unitary Precoding + AssertFatal(frame_parms->nb_antennas_tx > 1, "No precoding can be done with a single antenna port\n"); + // get the precoding matrix weights: + nfapi_nr_pm_pdu_t *pmi_pdu = &gNB->gNB_config.pmi_list.pmi_pdu[pmi - 1]; // pmi 0 is identity matrix + AssertFatal(pmi == pmi_pdu->pm_idx, "PMI %d doesn't match to the one in precoding matrix %d\n", pmi, pmi_pdu->pm_idx); + AssertFatal(ant < pmi_pdu->num_ant_ports, + "Antenna port index %d exceeds precoding matrix AP size %d\n", + ant, + pmi_pdu->num_ant_ports); + AssertFatal(rel15->nrOfLayers == pmi_pdu->numLayers, + "Number of layers %d doesn't match to the one in precoding matrix %d\n", + rel15->nrOfLayers, + pmi_pdu->numLayers); + if ((subCarrier + re_cnt) < symbol_sz) { // within ofdm_symbol_size, use SIMDe + nr_layer_precoder_simd(rel15->nrOfLayers, + symbol_sz, + txdataF_precoding, + ant, + pmi_pdu, + subCarrier, + re_cnt, + &txdataF[ant][txdataF_offset_per_symbol]); + subCarrier += re_cnt; + } else { // crossing ofdm_symbol_size, use simple arithmetic operations + for (int i = 0; i < re_cnt; i++) { + txdataF[ant][txdataF_offset_per_symbol + subCarrier] = + nr_layer_precoder_cm(rel15->nrOfLayers, symbol_sz, txdataF_precoding, ant, pmi_pdu, subCarrier); +#ifdef DEBUG_DLSCH_MAPPING + printf("antenna %d\t l %d \t subCarrier %d \t txdataF: %d %d\n", + ant, + l_symbol, + subCarrier, + txdataF[ant][l_symbol * symbol_sz + subCarrier + txdataF_offset].r, + txdataF[ant][l_symbol * symbol_sz + subCarrier + txdataF_offset].i); +#endif + if (++subCarrier >= symbol_sz) { + subCarrier -= symbol_sz; + } + } + } // else{ // crossing ofdm_symbol_size, use simple arithmetic operations + } // else { // non-unitary Precoding + rb += rb_step; + } // RB loop: while(rb < rel15->rbSize) } + static int do_one_dlsch(unsigned char *input_ptr, PHY_VARS_gNB *gNB, NR_gNB_DLSCH_t *dlsch, int slot) { const int16_t amp = gNB->TX_AMP; diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c index e1de1eab44..93768d9b6c 100644 --- a/openair1/SCHED_NR/nr_ru_procedures.c +++ b/openair1/SCHED_NR/nr_ru_procedures.c @@ -264,25 +264,25 @@ void nr_feptx(void *arg) // If there is no digital beamforming we just need to copy the data to RU if (ru->config.dbt_config.num_dig_beams == 0 || ru->gNB_list[0]->common_vars.analog_bf) { - // Check antenna muting state for energy saving - const nr_antenna_state_t *ant_state = &ru->gNB_list[0]->antenna_state; - bool is_active = nr_is_tx_antenna_active(ant_state, aa); - if (!is_active) { - // Antenna is muted - zero out the buffer (transmission blanking) - memset((void*)&ru->common.txdataF_BF[tx_idx][txdataF_BF_offset], 0, numSamples * sizeof(int32_t)); - if (startSymbol == 0) { - LOG_I(PHY, "[ANTENNA_MUTE] TX ant %d muted (mask=0x%02X, num_tx=%d), blanking slot %d\n", - aa, nr_get_tx_antenna_bitmask(ant_state), ant_state->num_tx_antennas, slot); + // Check antenna muting state for energy saving + const nr_antenna_state_t *ant_state = &ru->gNB_list[0]->antenna_state; + bool is_active = nr_is_tx_antenna_active(ant_state, aa); + if (!is_active) { + // Antenna is muted - zero out the buffer (transmission blanking) + memset((void*)&ru->common.txdataF_BF[tx_idx][txdataF_BF_offset], 0, numSamples * sizeof(int32_t)); + /* if (startSymbol == 0) { */ + /* LOG_I(PHY, "[ANTENNA_MUTE] TX ant %d muted (mask=0x%02X, num_tx=%d), blanking slot %d\n", */ + /* aa, nr_get_tx_antenna_bitmask(ant_state), ant_state->num_tx_antennas, slot); */ + /* } */ + } else { + // Antenna is active - copy data normally + memcpy((void*)&ru->common.txdataF_BF[tx_idx][txdataF_BF_offset], + (void*)&ru->gNB_list[0]->common_vars.txdataF[bb][aa][txdataF_offset], + numSamples * sizeof(int32_t)); } - } else { - // Antenna is active - copy data normally - memcpy((void*)&ru->common.txdataF_BF[tx_idx][txdataF_BF_offset], - (void*)&ru->gNB_list[0]->common_vars.txdataF[bb][aa][txdataF_offset], - numSamples * sizeof(int32_t)); - } } else { - AssertFatal(false, "This needs to be fixed by using appropriate beams from config\n"); + AssertFatal(false, "This needs to be fixed by using appropriate beams from config\n"); } /* const c16_t *dst = (const c16_t *)&ru->common.txdataF_BF[tx_idx][txdataF_BF_offset]; */ diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c index 3583661475..70ed79c726 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_pdcp.c @@ -108,7 +108,10 @@ bool read_pdcp_sm(void* data) } num_ues++; - AssertFatal(num_ues < MAX_MOBILES_PER_GNB, "cannot have more UEs than global UE number maximum\n"); + if (num_ues >= MAX_MOBILES_PER_GNB) { + LOG_W(PDCP, "num_ues %zu >= MAX_MOBILES_PER_GNB %d, skipping remaining UEs\n", num_ues, MAX_MOBILES_PER_GNB); + break; + } } #elif defined (NGRAN_GNB_CUUP) diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c index 8933b802a0..9f6db07d6e 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -178,7 +178,7 @@ static void capture_sst_sd(test_cond_value_t* test_cond_value, uint8_t *sst, uin *sd = malloc(sizeof(uint32_t)); **sd = buf[1] << 16 | buf[2] << 8 | buf[3]; } - printf("[E2 AGENT][E2SM-KPM] Condition NSSAI (%d, %x).\n", *sst, (*sd) ? **sd : 0xffffff); + /* printf("[E2 AGENT][E2SM-KPM] Condition NSSAI (%d, %x).\n", *sst, (*sd) ? **sd : 0xffffff); */ break; } default: @@ -226,7 +226,10 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_cu(const test_info_lst_t test_info) break; } } - AssertFatal(arr_ue_id.sz < MAX_MOBILES_PER_GNB, "cannot have more UEs than global UE number maximum\n"); + if (arr_ue_id.sz >= MAX_MOBILES_PER_GNB) { + LOG_W(NR_MAC, "arr_ue_id.sz %zu >= MAX_MOBILES_PER_GNB %d, skipping remaining UEs\n", arr_ue_id.sz, MAX_MOBILES_PER_GNB); + break; + } } free(sd); // if NULL, nothing happens @@ -319,7 +322,10 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_du_or_monolithic(const test_info_lst break; } } - AssertFatal(arr_ue_id.sz < MAX_MOBILES_PER_GNB, "cannot have more UEs than global UE number maximum\n"); + if (arr_ue_id.sz >= MAX_MOBILES_PER_GNB) { + LOG_W(NR_MAC, "arr_ue_id.sz %zu >= MAX_MOBILES_PER_GNB %d, skipping remaining UEs\n", arr_ue_id.sz, MAX_MOBILES_PER_GNB); + break; + } } node_stats[1].mac_stats.dl.total_prb_aggregate = mac->mac_stats.dl.total_prb_aggregate; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 814e7aa3af..ec48740a3d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3898,8 +3898,10 @@ bool nr_mac_ue_is_active(const NR_UE_info_t *ue) return true; } -#define UL_FAILURE_REQ_GRACE 10000 -#define UL_FAILURE_TIMEOUT 30000 +/* #define UL_FAILURE_REQ_GRACE 10000 */ +/* #define UL_FAILURE_TIMEOUT 30000 */ +#define UL_FAILURE_REQ_GRACE 2000 +#define UL_FAILURE_TIMEOUT 2500 void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing) { if (sched_ctrl->ul_failure) {