From b64c4e57088863bad60a645834ff5befd3854ac1 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 19 Nov 2025 17:51:09 +0100 Subject: [PATCH 01/15] fixes to make multiplexing pattern 2 and 3 work for Type0-PDCCH CSS Correct how the slot for SIB1 is computed in case of MUX pattern 2 and 3. Renamed n_0 to slot for clarity. n_c was never used outside of the function, so remove it where it is not used. --- openair2/LAYER2/NR_MAC_COMMON/nr_mac.h | 3 +- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 35 +++++++++---------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 22 +++++++++--- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h index 6e73a0f855..f73c1f2db3 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -472,8 +472,7 @@ typedef struct Type0_PDCCH_CSS_config_s { uint32_t type0_pdcch_ss_mux_pattern; uint16_t frame; int sfn_c; - uint32_t n_c; - uint32_t n_0; + uint32_t slot; uint32_t first_symbol_index; uint32_t search_space_duration; uint32_t search_space_frame_period; // in slots diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 563b3f2ca2..917c00ec6b 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -3726,8 +3726,8 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD // type0-pdcch search space float big_o = 0.0f; float big_m = 0.0f; - type0_PDCCH_CSS_config->sfn_c = -1; // only valid for mux=1 - type0_PDCCH_CSS_config->n_c = UINT_MAX; + type0_PDCCH_CSS_config->sfn_c = 0; // only valid for mux=1 + type0_PDCCH_CSS_config->slot = UINT_MAX; type0_PDCCH_CSS_config->first_symbol_index = UINT_MAX; type0_PDCCH_CSS_config->search_space_duration = 0; // element of search space // 38.213 table 10.1-1 @@ -3738,9 +3738,9 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD big_o = table_38213_13_11_c1[index_4lsb]; big_m = table_38213_13_11_c3[index_4lsb]; - uint32_t temp = (uint32_t)(big_o*(1<ssb_index*big_m); - type0_PDCCH_CSS_config->n_c = temp / num_slot_per_frame; - type0_PDCCH_CSS_config->sfn_c = type0_PDCCH_CSS_config->n_c % 2; + uint32_t temp = (uint32_t)(big_o * (1 << scs_pdcch)) + (uint32_t)(type0_PDCCH_CSS_config->ssb_index * big_m); + type0_PDCCH_CSS_config->slot = temp % num_slot_per_frame; + type0_PDCCH_CSS_config->sfn_c = (temp / num_slot_per_frame) % 2; if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 7) && (type0_PDCCH_CSS_config->ssb_index&1)){ type0_PDCCH_CSS_config->first_symbol_index = type0_PDCCH_CSS_config->num_symbols; @@ -3757,9 +3757,9 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD big_o = table_38213_13_12_c1[index_4lsb]; big_m = table_38213_13_12_c3[index_4lsb]; - uint32_t temp = (uint32_t)(big_o*(1<ssb_index*big_m); - type0_PDCCH_CSS_config->n_c = temp / num_slot_per_frame; - type0_PDCCH_CSS_config->sfn_c = type0_PDCCH_CSS_config->n_c % 2; + uint32_t temp = (uint32_t)(big_o * (1 << scs_pdcch)) + (uint32_t)(type0_PDCCH_CSS_config->ssb_index * big_m); + type0_PDCCH_CSS_config->slot = temp % num_slot_per_frame; + type0_PDCCH_CSS_config->sfn_c = (temp / num_slot_per_frame) % 2; if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 10) && (type0_PDCCH_CSS_config->ssb_index&1)){ type0_PDCCH_CSS_config->first_symbol_index = 7; @@ -3782,7 +3782,7 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD AssertFatal(index_4lsb == 0, "38.213 Table 13-13 4 LSB out of range\n"); // PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot // sfn_c = SFN_C_EQ_SFN_SSB; - type0_PDCCH_CSS_config->n_c = ssb_slot; + type0_PDCCH_CSS_config->slot = ssb_slot; switch(type0_PDCCH_CSS_config->ssb_index & 0x3){ // ssb_index(i) mod 4 case 0: type0_PDCCH_CSS_config->first_symbol_index = 0; @@ -3804,7 +3804,7 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD AssertFatal(index_4lsb == 0, "38.213 Table 13-14 4 LSB out of range\n"); // PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot // sfn_c = SFN_C_EQ_SFN_SSB; - type0_PDCCH_CSS_config->n_c = ssb_slot; + type0_PDCCH_CSS_config->slot = ssb_slot; switch(type0_PDCCH_CSS_config->ssb_index & 0x7){ // ssb_index(i) mod 8 case 0: type0_PDCCH_CSS_config->first_symbol_index = 0; @@ -3820,11 +3820,11 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD break; case 4: type0_PDCCH_CSS_config->first_symbol_index = 12; - type0_PDCCH_CSS_config->n_c = ssb_slot - 1; + type0_PDCCH_CSS_config->slot = ssb_slot - 1; break; case 5: type0_PDCCH_CSS_config->first_symbol_index = 13; - type0_PDCCH_CSS_config->n_c = ssb_slot - 1; + type0_PDCCH_CSS_config->slot = ssb_slot - 1; break; case 6: type0_PDCCH_CSS_config->first_symbol_index = 0; @@ -3848,7 +3848,7 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD AssertFatal(index_4lsb == 0, "38.213 Table 13-15 4 LSB out of range\n"); // PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot // sfn_c = SFN_C_EQ_SFN_SSB; - type0_PDCCH_CSS_config->n_c = ssb_slot; + type0_PDCCH_CSS_config->slot = ssb_slot; switch(type0_PDCCH_CSS_config->ssb_index & 0x3){ // ssb_index(i) mod 4 case 0: type0_PDCCH_CSS_config->first_symbol_index = 4; @@ -3870,11 +3870,8 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD // SSB periodicity in slots type0_PDCCH_CSS_config->search_space_frame_period = ssb_period * slots_per_frame; } + AssertFatal(type0_PDCCH_CSS_config->slot != UINT_MAX, "type0_PDCCH_CSS_config slot not configured"); - AssertFatal(type0_PDCCH_CSS_config->sfn_c >= 0, ""); - AssertFatal(type0_PDCCH_CSS_config->n_c != UINT_MAX, ""); - - type0_PDCCH_CSS_config->n_0 = ((uint32_t)(big_o*(1<ssb_index*big_m))%num_slot_per_frame; type0_PDCCH_CSS_config->cset_start_rb = ssb_offset_point_a - type0_PDCCH_CSS_config->rb_offset; AssertFatal(type0_PDCCH_CSS_config->cset_start_rb >= 0, "Invalid CSET0 start PRB %d SSB offset point A %d RB offset %d\n", type0_PDCCH_CSS_config->cset_start_rb, ssb_offset_point_a, type0_PDCCH_CSS_config->rb_offset); @@ -3950,8 +3947,8 @@ void fill_searchSpaceZero(NR_SearchSpace_t *ss0, int slots_per_frame, NR_Type0_P const uint32_t periodicity = type0_PDCCH_CSS_config->search_space_frame_period; const uint32_t offset = type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 1 ? - type0_PDCCH_CSS_config->n_0 + (slots_per_frame * type0_PDCCH_CSS_config->sfn_c) : - type0_PDCCH_CSS_config->n_c; + type0_PDCCH_CSS_config->slot + (slots_per_frame * type0_PDCCH_CSS_config->sfn_c) : + type0_PDCCH_CSS_config->slot; ss0->searchSpaceId = 0; *ss0->controlResourceSetId = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 6dd4886911..9f661984d0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -85,7 +85,7 @@ static void schedule_ssb(frame_t frame, dl_config_pdu->ssb_pdu.ssb_pdu_rel15.precoding_and_beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = beam_index; dl_req->nPDUs++; - LOG_D(MAC,"Scheduling ssb %d at frame %d and slot %d\n", i_ssb, frame, slot); + LOG_D(NR_MAC,"Scheduling ssb %d at frame %d and slot %d\n", i_ssb, frame, slot); } static void fill_ssb_vrb_map(NR_COMMON_channels_t *cc, @@ -521,6 +521,19 @@ static bool check_sib1_tda(gNB_MAC_INST *gNB_mac, } } +static bool check_frame_sib1(NR_ServingCellConfigCommon_t *scc, NR_Type0_PDCCH_CSS_config_t *type0, int frame) +{ + if (type0->type0_pdcch_ss_mux_pattern == 1) + return frame % 2 == type0->sfn_c; + else { + long ssb_period = *scc->ssb_periodicityServingCell; + int ssb_frame_periodicity = 1; // every how many frames SSB are generated + if (ssb_period > 1) // 0 is every half frame + ssb_frame_periodicity = 1 << (ssb_period -1); + return frame % ssb_frame_periodicity == 0; + } +} + void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, slot_t slotP, @@ -553,13 +566,14 @@ void schedule_nr_sib1(module_id_t module_idP, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[i]; - if((frameP % 2 == type0_PDCCH_CSS_config->sfn_c) && - (slotP == type0_PDCCH_CSS_config->n_0) && + if(check_frame_sib1(scc, type0_PDCCH_CSS_config, frameP) && + (slotP == type0_PDCCH_CSS_config->slot) && (type0_PDCCH_CSS_config->num_rbs > 0) && (type0_PDCCH_CSS_config->active == true)) { AssertFatal(is_dl_slot(slotP, &gNB_mac->frame_structure), - "Trying to schedule SIB1 in slot %d which is not DL. Check searchSpaceZero configuration.\n", + "Trying to schedule SIB1 for SSB %d in slot %d which is not DL. Check searchSpaceZero configuration.\n", + type0_PDCCH_CSS_config->ssb_index, slotP); const int n_slots_frame = gNB_mac->frame_structure.numb_slots_frame; int beam_index = get_beam_from_ssbidx(gNB_mac, i); From 7173bb6cac7726fdeb18ba1ceeb719ae50a5f28d Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 19 Nov 2025 18:14:12 +0100 Subject: [PATCH 02/15] formatting --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 174 +++++++++--------- 1 file changed, 92 insertions(+), 82 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 917c00ec6b..f25d6283aa 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -3560,26 +3560,23 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD uint32_t ssb_period, uint32_t ssb_offset_point_a) { - NR_SubcarrierSpacing_t scs_pdcch; - - channel_bandwidth_t min_channel_bw; - // according to Table 5.3.5-1 in 38.104 // band 79 is the only one which minimum is 40 // for all the other channels it is either 10 or 5 // and there is no difference between the two for this implementation so it is set it to 10 + channel_bandwidth_t min_channel_bw; if (nr_band == 79) min_channel_bw = bw_40MHz; else min_channel_bw = bw_10MHz; + NR_SubcarrierSpacing_t scs_pdcch; if (frequency_range == FR2) { if(mib->subCarrierSpacingCommon == NR_MIB__subCarrierSpacingCommon_scs15or60) scs_pdcch = NR_SubcarrierSpacing_kHz60; else scs_pdcch = NR_SubcarrierSpacing_kHz120; - } - else { + } else { frequency_range = FR1; if(mib->subCarrierSpacingCommon == NR_MIB__subCarrierSpacingCommon_scs15or60) scs_pdcch = NR_SubcarrierSpacing_kHz15; @@ -3590,8 +3587,7 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD type0_PDCCH_CSS_config->ssb_index = ssb_index; type0_PDCCH_CSS_config->frame = frameP; - uint8_t ssb_slot = ssb_start_symbol/14; - + uint8_t ssb_slot = ssb_start_symbol / 14; uint32_t is_condition_A = (ssb_subcarrier_offset == 0); // 38.213 ch.13 uint32_t index_4msb = (mib->pdcch_ConfigSIB1.controlResourceSetZero); uint32_t index_4lsb = (mib->pdcch_ConfigSIB1.searchSpaceZero); @@ -3599,59 +3595,59 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD type0_PDCCH_CSS_config->num_rbs = -1; type0_PDCCH_CSS_config->num_symbols = -1; type0_PDCCH_CSS_config->rb_offset = -1; - LOG_D(NR_MAC,"NR_SubcarrierSpacing_kHz30 %d, scs_ssb %d, scs_pdcch %d, min_chan_bw %d\n",(int)NR_SubcarrierSpacing_kHz30,(int)scs_ssb,(int)scs_pdcch,min_channel_bw); + LOG_D(NR_MAC, + "NR_SubcarrierSpacing_kHz30 %d, scs_ssb %d, scs_pdcch %d, min_chan_bw %d\n", + (int)NR_SubcarrierSpacing_kHz30, + (int)scs_ssb, + (int)scs_pdcch, + min_channel_bw); // type0-pdcch coreset - switch( ((int)scs_ssb << 3) | (int)scs_pdcch ){ + switch(((int)scs_ssb << 3) | (int)scs_pdcch) { case (NR_SubcarrierSpacing_kHz15 << 3) | NR_SubcarrierSpacing_kHz15: AssertFatal(index_4msb < 15, "38.213 Table 13-1 4 MSB out of range\n"); type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1; - type0_PDCCH_CSS_config->num_rbs = table_38213_13_1_c2[index_4msb]; + type0_PDCCH_CSS_config->num_rbs = table_38213_13_1_c2[index_4msb]; type0_PDCCH_CSS_config->num_symbols = table_38213_13_1_c3[index_4msb]; - type0_PDCCH_CSS_config->rb_offset = table_38213_13_1_c4[index_4msb]; + type0_PDCCH_CSS_config->rb_offset = table_38213_13_1_c4[index_4msb]; break; - case (NR_SubcarrierSpacing_kHz15 << 3) | NR_SubcarrierSpacing_kHz30: AssertFatal(index_4msb < 14, "38.213 Table 13-2 4 MSB out of range\n"); type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1; - type0_PDCCH_CSS_config->num_rbs = table_38213_13_2_c2[index_4msb]; + type0_PDCCH_CSS_config->num_rbs = table_38213_13_2_c2[index_4msb]; type0_PDCCH_CSS_config->num_symbols = table_38213_13_2_c3[index_4msb]; - type0_PDCCH_CSS_config->rb_offset = table_38213_13_2_c4[index_4msb]; + type0_PDCCH_CSS_config->rb_offset = table_38213_13_2_c4[index_4msb]; break; - case (NR_SubcarrierSpacing_kHz30 << 3) | NR_SubcarrierSpacing_kHz15: - if((min_channel_bw & bw_5MHz) | (min_channel_bw & bw_10MHz)){ + if((min_channel_bw & bw_5MHz) | (min_channel_bw & bw_10MHz)) { AssertFatal(index_4msb < 9, "38.213 Table 13-3 4 MSB out of range\n"); type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1; - type0_PDCCH_CSS_config->num_rbs = table_38213_13_3_c2[index_4msb]; + type0_PDCCH_CSS_config->num_rbs = table_38213_13_3_c2[index_4msb]; type0_PDCCH_CSS_config->num_symbols = table_38213_13_3_c3[index_4msb]; - type0_PDCCH_CSS_config->rb_offset = table_38213_13_3_c4[index_4msb]; - }else if(min_channel_bw & bw_40MHz){ + type0_PDCCH_CSS_config->rb_offset = table_38213_13_3_c4[index_4msb]; + } else if(min_channel_bw & bw_40MHz) { AssertFatal(index_4msb < 9, "38.213 Table 13-5 4 MSB out of range\n"); type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1; - type0_PDCCH_CSS_config->num_rbs = table_38213_13_5_c2[index_4msb]; + type0_PDCCH_CSS_config->num_rbs = table_38213_13_5_c2[index_4msb]; type0_PDCCH_CSS_config->num_symbols = table_38213_13_5_c3[index_4msb]; - type0_PDCCH_CSS_config->rb_offset = table_38213_13_5_c4[index_4msb]; - }else{ ; } - + type0_PDCCH_CSS_config->rb_offset = table_38213_13_5_c4[index_4msb]; + } else{ ; } break; - case (NR_SubcarrierSpacing_kHz30 << 3) | NR_SubcarrierSpacing_kHz30: - if((min_channel_bw & bw_5MHz) | (min_channel_bw & bw_10MHz)){ + if((min_channel_bw & bw_5MHz) | (min_channel_bw & bw_10MHz)) { type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1; - type0_PDCCH_CSS_config->num_rbs = table_38213_13_4_c2[index_4msb]; + type0_PDCCH_CSS_config->num_rbs = table_38213_13_4_c2[index_4msb]; type0_PDCCH_CSS_config->num_symbols = table_38213_13_4_c3[index_4msb]; - type0_PDCCH_CSS_config->rb_offset = table_38213_13_4_c4[index_4msb]; + type0_PDCCH_CSS_config->rb_offset = table_38213_13_4_c4[index_4msb]; - }else if(min_channel_bw & bw_40MHz){ + } else if(min_channel_bw & bw_40MHz) { AssertFatal(index_4msb < 10, "38.213 Table 13-6 4 MSB out of range\n"); type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1; - type0_PDCCH_CSS_config->num_rbs = table_38213_13_6_c2[index_4msb]; + type0_PDCCH_CSS_config->num_rbs = table_38213_13_6_c2[index_4msb]; type0_PDCCH_CSS_config->num_symbols = table_38213_13_6_c3[index_4msb]; - type0_PDCCH_CSS_config->rb_offset = table_38213_13_6_c4[index_4msb]; - }else{ ; } + type0_PDCCH_CSS_config->rb_offset = table_38213_13_6_c4[index_4msb]; + } else{ ; } break; - case (NR_SubcarrierSpacing_kHz120 << 3) | NR_SubcarrierSpacing_kHz60: AssertFatal(index_4msb < 12, "38.213 Table 13-7 4 MSB out of range\n"); if (index_4msb < 8) { @@ -3660,15 +3656,14 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 2; } - type0_PDCCH_CSS_config->num_rbs = table_38213_13_7_c2[index_4msb]; + type0_PDCCH_CSS_config->num_rbs = table_38213_13_7_c2[index_4msb]; type0_PDCCH_CSS_config->num_symbols = table_38213_13_7_c3[index_4msb]; - if(!is_condition_A && (index_4msb == 8 || index_4msb == 10)){ - type0_PDCCH_CSS_config->rb_offset = table_38213_13_7_c4[index_4msb] - 1; - }else{ - type0_PDCCH_CSS_config->rb_offset = table_38213_13_7_c4[index_4msb]; + if(!is_condition_A && (index_4msb == 8 || index_4msb == 10)) { + type0_PDCCH_CSS_config->rb_offset = table_38213_13_7_c4[index_4msb] - 1; + } else { + type0_PDCCH_CSS_config->rb_offset = table_38213_13_7_c4[index_4msb]; } break; - case (NR_SubcarrierSpacing_kHz120 << 3) | NR_SubcarrierSpacing_kHz120: AssertFatal(index_4msb < 8, "38.213 Table 13-8 4 MSB out of range\n"); if (index_4msb < 4) { @@ -3677,23 +3672,21 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 3; } - type0_PDCCH_CSS_config->num_rbs = table_38213_13_8_c2[index_4msb]; + type0_PDCCH_CSS_config->num_rbs = table_38213_13_8_c2[index_4msb]; type0_PDCCH_CSS_config->num_symbols = table_38213_13_8_c3[index_4msb]; - if(!is_condition_A && (index_4msb == 4 || index_4msb == 6)){ - type0_PDCCH_CSS_config->rb_offset = table_38213_13_8_c4[index_4msb] - 1; - }else{ - type0_PDCCH_CSS_config->rb_offset = table_38213_13_8_c4[index_4msb]; + if(!is_condition_A && (index_4msb == 4 || index_4msb == 6)) { + type0_PDCCH_CSS_config->rb_offset = table_38213_13_8_c4[index_4msb] - 1; + } else { + type0_PDCCH_CSS_config->rb_offset = table_38213_13_8_c4[index_4msb]; } break; - case (NR_SubcarrierSpacing_kHz240 << 3) | NR_SubcarrierSpacing_kHz60: AssertFatal(index_4msb < 4, "38.213 Table 13-9 4 MSB out of range\n"); type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 1; - type0_PDCCH_CSS_config->num_rbs = table_38213_13_9_c2[index_4msb]; + type0_PDCCH_CSS_config->num_rbs = table_38213_13_9_c2[index_4msb]; type0_PDCCH_CSS_config->num_symbols = table_38213_13_9_c3[index_4msb]; - type0_PDCCH_CSS_config->rb_offset = table_38213_13_9_c4[index_4msb]; + type0_PDCCH_CSS_config->rb_offset = table_38213_13_9_c4[index_4msb]; break; - case (NR_SubcarrierSpacing_kHz240 << 3) | NR_SubcarrierSpacing_kHz120: AssertFatal(index_4msb < 8, "38.213 Table 13-10 4 MSB out of range\n"); if (index_4msb < 4) { @@ -3701,25 +3694,37 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD } else if (index_4msb < 8) { type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern = 2; } - type0_PDCCH_CSS_config->num_rbs = table_38213_13_10_c2[index_4msb]; + type0_PDCCH_CSS_config->num_rbs = table_38213_13_10_c2[index_4msb]; type0_PDCCH_CSS_config->num_symbols = table_38213_13_10_c3[index_4msb]; - if(!is_condition_A && (index_4msb == 4 || index_4msb == 6)){ - type0_PDCCH_CSS_config->rb_offset = table_38213_13_10_c4[index_4msb]-1; - }else{ - type0_PDCCH_CSS_config->rb_offset = table_38213_13_10_c4[index_4msb]; + if(!is_condition_A && (index_4msb == 4 || index_4msb == 6)) { + type0_PDCCH_CSS_config->rb_offset = table_38213_13_10_c4[index_4msb]-1; + } else { + type0_PDCCH_CSS_config->rb_offset = table_38213_13_10_c4[index_4msb]; } - break; - default: - LOG_E(NR_MAC,"NR_SubcarrierSpacing_kHz30 %d, scs_ssb %d, scs_pdcch %d, min_chan_bw %d\n",NR_SubcarrierSpacing_kHz30,(int)scs_ssb,(int)scs_pdcch,min_channel_bw); + LOG_E(NR_MAC, + "NR_SubcarrierSpacing_kHz30 %d, scs_ssb %d, scs_pdcch %d, min_chan_bw %d\n", + NR_SubcarrierSpacing_kHz30, + (int)scs_ssb, + (int)scs_pdcch, + min_channel_bw); break; } - LOG_D(NR_MAC,"Coreset0: index_4msb=%d, num_rbs=%d, num_symb=%d, rb_offset=%d\n", - index_4msb,type0_PDCCH_CSS_config->num_rbs,type0_PDCCH_CSS_config->num_symbols,type0_PDCCH_CSS_config->rb_offset ); + LOG_D(NR_MAC, + "Coreset0: index_4msb=%d, num_rbs=%d, num_symb=%d, rb_offset=%d\n", + index_4msb, + type0_PDCCH_CSS_config->num_rbs, + type0_PDCCH_CSS_config->num_symbols, + type0_PDCCH_CSS_config->rb_offset); - AssertFatal(type0_PDCCH_CSS_config->num_rbs != -1, "Type0 PDCCH coreset num_rbs undefined, index_4msb=%d, min_channel_bw %d, scs_ssb %d, scs_pdcch %d\n",index_4msb,min_channel_bw,(int)scs_ssb,(int)scs_pdcch); + AssertFatal(type0_PDCCH_CSS_config->num_rbs != -1, + "Type0 PDCCH coreset num_rbs undefined, index_4msb=%d, min_channel_bw %d, scs_ssb %d, scs_pdcch %d\n", + index_4msb, + min_channel_bw, + (int)scs_ssb, + (int)scs_pdcch); AssertFatal(type0_PDCCH_CSS_config->num_symbols != -1, "Type0 PDCCH coreset num_symbols undefined"); AssertFatal(type0_PDCCH_CSS_config->rb_offset != -1, "Type0 PDCCH coreset rb_offset undefined"); @@ -3734,7 +3739,7 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD /// MUX PATTERN 1 int slots_per_frame = get_slots_per_frame_from_scs(scs_ssb); - if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 1 && frequency_range == FR1){ + if (type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 1 && frequency_range == FR1) { big_o = table_38213_13_11_c1[index_4lsb]; big_m = table_38213_13_11_c3[index_4lsb]; @@ -3742,9 +3747,9 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD type0_PDCCH_CSS_config->slot = temp % num_slot_per_frame; type0_PDCCH_CSS_config->sfn_c = (temp / num_slot_per_frame) % 2; - if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 7) && (type0_PDCCH_CSS_config->ssb_index&1)){ + if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 7) && (type0_PDCCH_CSS_config->ssb_index & 1)) { type0_PDCCH_CSS_config->first_symbol_index = type0_PDCCH_CSS_config->num_symbols; - }else{ + } else { type0_PDCCH_CSS_config->first_symbol_index = table_38213_13_11_c4[index_4lsb]; } // 38.213 chapter 13: over two consecutive slots @@ -3753,7 +3758,7 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD type0_PDCCH_CSS_config->search_space_frame_period = slots_per_frame << 1; } - if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 1 && frequency_range == FR2){ + if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 1 && frequency_range == FR2) { big_o = table_38213_13_12_c1[index_4lsb]; big_m = table_38213_13_12_c3[index_4lsb]; @@ -3761,11 +3766,11 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD type0_PDCCH_CSS_config->slot = temp % num_slot_per_frame; type0_PDCCH_CSS_config->sfn_c = (temp / num_slot_per_frame) % 2; - if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 10) && (type0_PDCCH_CSS_config->ssb_index&1)){ + if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 10) && (type0_PDCCH_CSS_config->ssb_index & 1)) { type0_PDCCH_CSS_config->first_symbol_index = 7; - }else if((index_4lsb == 6 || index_4lsb == 7 || index_4lsb == 8 || index_4lsb == 11) && (type0_PDCCH_CSS_config->ssb_index&1)){ + } else if ((index_4lsb == 6 || index_4lsb == 7 || index_4lsb == 8 || index_4lsb == 11) && (type0_PDCCH_CSS_config->ssb_index & 1)) { type0_PDCCH_CSS_config->first_symbol_index = type0_PDCCH_CSS_config->num_symbols; - }else{ + } else { type0_PDCCH_CSS_config->first_symbol_index = 0; } // 38.213 chapter 13: over two consecutive slots @@ -3775,15 +3780,15 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD } /// MUX PATTERN 2 - if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 2){ + if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 2) { - if((scs_ssb == NR_SubcarrierSpacing_kHz120) && (scs_pdcch == NR_SubcarrierSpacing_kHz60)){ + if((scs_ssb == NR_SubcarrierSpacing_kHz120) && (scs_pdcch == NR_SubcarrierSpacing_kHz60)) { // 38.213 Table 13-13 AssertFatal(index_4lsb == 0, "38.213 Table 13-13 4 LSB out of range\n"); // PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot // sfn_c = SFN_C_EQ_SFN_SSB; type0_PDCCH_CSS_config->slot = ssb_slot; - switch(type0_PDCCH_CSS_config->ssb_index & 0x3){ // ssb_index(i) mod 4 + switch(type0_PDCCH_CSS_config->ssb_index & 0x3) { // ssb_index(i) mod 4 case 0: type0_PDCCH_CSS_config->first_symbol_index = 0; break; @@ -3796,16 +3801,16 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD case 3: type0_PDCCH_CSS_config->first_symbol_index = 7; break; - default: break; + default: + break; } - - }else if((scs_ssb == NR_SubcarrierSpacing_kHz240) && (scs_pdcch == NR_SubcarrierSpacing_kHz120)){ + } else if((scs_ssb == NR_SubcarrierSpacing_kHz240) && (scs_pdcch == NR_SubcarrierSpacing_kHz120)) { // 38.213 Table 13-14 AssertFatal(index_4lsb == 0, "38.213 Table 13-14 4 LSB out of range\n"); // PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot // sfn_c = SFN_C_EQ_SFN_SSB; type0_PDCCH_CSS_config->slot = ssb_slot; - switch(type0_PDCCH_CSS_config->ssb_index & 0x7){ // ssb_index(i) mod 8 + switch(type0_PDCCH_CSS_config->ssb_index & 0x7) { // ssb_index(i) mod 8 case 0: type0_PDCCH_CSS_config->first_symbol_index = 0; break; @@ -3832,9 +3837,10 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD case 7: type0_PDCCH_CSS_config->first_symbol_index = 1; break; - default: break; + default: + break; } - }else{ ; } + } else { ; } // 38.213 chapter 13: over one slot type0_PDCCH_CSS_config->search_space_duration = 1; // SSB periodicity in slots @@ -3842,14 +3848,14 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD } /// MUX PATTERN 3 - if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 3){ - if((scs_ssb == NR_SubcarrierSpacing_kHz120) && (scs_pdcch == NR_SubcarrierSpacing_kHz120)){ + if(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern == 3) { + if((scs_ssb == NR_SubcarrierSpacing_kHz120) && (scs_pdcch == NR_SubcarrierSpacing_kHz120)) { // 38.213 Table 13-15 AssertFatal(index_4lsb == 0, "38.213 Table 13-15 4 LSB out of range\n"); // PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot // sfn_c = SFN_C_EQ_SFN_SSB; type0_PDCCH_CSS_config->slot = ssb_slot; - switch(type0_PDCCH_CSS_config->ssb_index & 0x3){ // ssb_index(i) mod 4 + switch(type0_PDCCH_CSS_config->ssb_index & 0x3) { // ssb_index(i) mod 4 case 0: type0_PDCCH_CSS_config->first_symbol_index = 4; break; @@ -3862,9 +3868,10 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD case 3: type0_PDCCH_CSS_config->first_symbol_index = 6; break; - default: break; + default: + break; } - }else{ ; } + } else { ; } // 38.213 chapter 13: over one slot type0_PDCCH_CSS_config->search_space_duration = 1; // SSB periodicity in slots @@ -3873,8 +3880,11 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD AssertFatal(type0_PDCCH_CSS_config->slot != UINT_MAX, "type0_PDCCH_CSS_config slot not configured"); type0_PDCCH_CSS_config->cset_start_rb = ssb_offset_point_a - type0_PDCCH_CSS_config->rb_offset; - AssertFatal(type0_PDCCH_CSS_config->cset_start_rb >= 0, "Invalid CSET0 start PRB %d SSB offset point A %d RB offset %d\n", - type0_PDCCH_CSS_config->cset_start_rb, ssb_offset_point_a, type0_PDCCH_CSS_config->rb_offset); + AssertFatal(type0_PDCCH_CSS_config->cset_start_rb >= 0, + "Invalid CSET0 start PRB %d SSB offset point A %d RB offset %d\n", + type0_PDCCH_CSS_config->cset_start_rb, + ssb_offset_point_a, + type0_PDCCH_CSS_config->rb_offset); } void fill_coresetZero(NR_ControlResourceSet_t *coreset0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config) From 28f30375816914b089990fbd4cc097c5728359cf Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 19 Nov 2025 19:17:45 +0100 Subject: [PATCH 03/15] fix for PDCCH channel estimation start subcarrier --- openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 46e2918749..dbf9559c4b 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -828,7 +828,7 @@ void nr_pdcch_channel_estimation(const PHY_VARS_NR_UE *ue, first_carrier_offset, BWPStart, coreset_start_rb, nb_rb_coreset); #endif - unsigned short coreset_start_subcarrier = first_carrier_offset+(BWPStart + coreset_start_rb)*12; + unsigned short coreset_start_subcarrier = (first_carrier_offset + (BWPStart + coreset_start_rb) * 12) % symb_sz; #if CH_INTERP int16_t *fl = filt16a_l1; From 75820422a43db97e839ba92df999ed4867863075 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 20 Nov 2025 10:46:44 +0100 Subject: [PATCH 04/15] check if CSET0 exceeds upper BW limit --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 6 ++++++ openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 1 + openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c | 1 + openair2/LAYER2/NR_MAC_gNB/config.c | 2 ++ openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 3 ++- 5 files changed, 12 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index f25d6283aa..b932d80e6f 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -3556,6 +3556,7 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD NR_SubcarrierSpacing_t scs_ssb, frequency_range_t frequency_range, int nr_band, + int grid_size, uint32_t ssb_index, uint32_t ssb_period, uint32_t ssb_offset_point_a) @@ -3885,6 +3886,11 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD type0_PDCCH_CSS_config->cset_start_rb, ssb_offset_point_a, type0_PDCCH_CSS_config->rb_offset); + AssertFatal(type0_PDCCH_CSS_config->cset_start_rb + type0_PDCCH_CSS_config->num_rbs <= grid_size, + "Invalid combination of start PRB %d and size %d of CSET0. Exceeds full BW %d\n", + type0_PDCCH_CSS_config->cset_start_rb, + type0_PDCCH_CSS_config->num_rbs, + grid_size); } void fill_coresetZero(NR_ControlResourceSet_t *coreset0, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 8f795452b8..728ea74238 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -244,6 +244,7 @@ void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PD NR_SubcarrierSpacing_t scs_ssb, frequency_range_t frequency_range, int nr_band, + int grid_size, uint32_t ssb_index, uint32_t ssb_period, uint32_t ssb_offset_point_a); 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 477e39a60a..dc82e5d308 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -449,6 +449,7 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl scs, mac->frequency_range, mac->nr_band, + 273, // at this point UE in principle doesn't know the grid size (we assume the largest) mac->mib_ssb, 1, // If the UE is not configured with a periodicity, the UE assumes a periodicity of a half frame ssb_offset_point_a); diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index ed4d902345..80401de63a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -789,6 +789,7 @@ static void config_sched_ctrlCommon(gNB_MAC_INST *nr_mac) NR_SubcarrierSpacing_t scs = *scc->ssbSubcarrierSpacing; const long band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; + const int bw = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; uint16_t ssb_start_symbol = get_ssb_start_symbol(band, scs, 0); int8_t ssb_period = *scc->ssb_periodicityServingCell; @@ -810,6 +811,7 @@ static void config_sched_ctrlCommon(gNB_MAC_INST *nr_mac) scs, frequency_range, band, + bw, 0, ssb_frame_periodicity, prb_offset); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 9f661984d0..12d09426a9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -134,7 +134,7 @@ static void schedule_one_ssb(gNB_MAC_INST *gNB, const NR_MIB_t *mib = cc->mib->message.choice.mib; uint32_t mib_pdu = (*(uint32_t *)cc->MIB_pdu) & ((1 << 24) - 1); uint8_t ssbSubcarrierOffset = gNB->ssb_SubcarrierOffset; - + const int bw = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; uint16_t ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb); NR_beam_alloc_t beam = beam_allocation_procedure(&gNB->beam_info, frameP, slotP, get_beam_from_ssbidx(gNB, i_ssb), slots_per_frame); @@ -159,6 +159,7 @@ static void schedule_one_ssb(gNB_MAC_INST *gNB, scs, FR, band, + bw, i_ssb, ssb_frame_periodicity, prb_offset); From 143a2f87a7da5bce7f1106c0bd69a88a0757322d Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 21 Nov 2025 18:18:36 +0100 Subject: [PATCH 05/15] fix in ld condition in DMRS function --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index b932d80e6f..5f38693218 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -3217,7 +3217,7 @@ int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config, // For TypeB, ld is the duration of the scheduled PDSCH resources int ld = (mappingtype == typeA) ? (NrOfSymbols + startSymbol) : NrOfSymbols; - AssertFatal(ld > 2 && ld < 15,"Illegal NrOfSymbols according to Table 5.1.2.1-1 Spec 38.214 %d\n",ld); + AssertFatal(ld > 1 && ld < 15,"Illegal NrOfSymbols according to Table 5.1.2.1-1 Spec 38.214 %d\n",ld); AssertFatal((NrOfSymbols + startSymbol) < 15,"Illegal S+L according to Table 5.1.2.1-1 Spec 38.214 S:%d L:%d\n",startSymbol, NrOfSymbols); if (mappingtype == typeA) { From e0af1a2e75e33ee89ed3ee27327d8043a4b32119 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 26 Nov 2025 10:50:57 +0100 Subject: [PATCH 06/15] convert RFsim FR2 32 PRB test into 66 PRB to test MUX pattern 3 --- ...conf => gnb.sa.band257.u3.66prb.rfsim.conf} | 18 +++++++++--------- ...rb.xml => container_5g_rfsim_fr2_66prb.xml} | 8 ++++---- .../docker-compose.yaml | 4 ++-- doc/analog_beamforming.md | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) rename ci-scripts/conf_files/{gnb.sa.band261.u3.32prb.rfsim.conf => gnb.sa.band257.u3.66prb.rfsim.conf} (98%) rename ci-scripts/xml_files/{container_5g_rfsim_fr2_32prb.xml => container_5g_rfsim_fr2_66prb.xml} (92%) rename ci-scripts/yaml_files/{5g_rfsimulator_fr2_32prb => 5g_rfsimulator_fr2_66prb}/docker-compose.yaml (97%) diff --git a/ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band257.u3.66prb.rfsim.conf similarity index 98% rename from ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf rename to ci-scripts/conf_files/gnb.sa.band257.u3.66prb.rfsim.conf index c37acc89f5..fac77fc70e 100644 --- a/ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb.sa.band257.u3.66prb.rfsim.conf @@ -29,40 +29,40 @@ gNBs = # downlinkConfigCommon #frequencyInfoDL # this is pointA + 16 PRBs@120kHz SCS (same as initial BWP) - absoluteFrequencySSB = 2071387; - dl_frequencyBand = 261; + absoluteFrequencySSB = 2078299; + dl_frequencyBand = 257; # this is 27.900 GHz - dl_absoluteFrequencyPointA = 2071001; + dl_absoluteFrequencyPointA = 2077915; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 dl_subcarrierSpacing = 3; - dl_carrierBandwidth = 32; + dl_carrierBandwidth = 66; #initialDownlinkBWP #genericParameters # this is RBstart=0,L=32 (275*(L-1))+RBstart - initialDLBWPlocationAndBandwidth = 8525; + initialDLBWPlocationAndBandwidth = 13475; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 3; #pdcch-ConfigCommon - initialDLBWPcontrolResourceSetZero = 1; + initialDLBWPcontrolResourceSetZero = 4; initialDLBWPsearchSpaceZero = 0; #uplinkConfigCommon #frequencyInfoUL - ul_frequencyBand = 261; + ul_frequencyBand = 257; #scs-SpecificCarrierList ul_offstToCarrier = 0; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 ul_subcarrierSpacing = 3; - ul_carrierBandwidth = 32; + ul_carrierBandwidth = 66; pMax = 20; #initialUplinkBWP #genericParameters - initialULBWPlocationAndBandwidth = 8525; + initialULBWPlocationAndBandwidth = 13475; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialULBWPsubcarrierSpacing = 3; diff --git a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml b/ci-scripts/xml_files/container_5g_rfsim_fr2_66prb.xml similarity index 92% rename from ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml rename to ci-scripts/xml_files/container_5g_rfsim_fr2_66prb.xml index 5eab626ece..b64837c839 100644 --- a/ci-scripts/xml_files/container_5g_rfsim_fr2_32prb.xml +++ b/ci-scripts/xml_files/container_5g_rfsim_fr2_66prb.xml @@ -21,7 +21,7 @@ --> - rfsim-fr2-32prb-5gnr-tdd + rfsim-fr2-66prb-5gnr-tdd Monolithic FR2 gNB wrench @@ -42,7 +42,7 @@ Deploy_Object Deploy OAI gNB localhost - ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb + ci-scripts/yaml_files/5g_rfsimulator_fr2_66prb mysql oai-amf oai-smf oai-upf oai-ext-dn @@ -50,7 +50,7 @@ Deploy_Object Deploy OAI NR-UE localhost - ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb + ci-scripts/yaml_files/5g_rfsimulator_fr2_66prb oai-gnb oai-nr-ue @@ -88,7 +88,7 @@ true Undeploy all OAI 5G stack localhost - ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb + ci-scripts/yaml_files/5g_rfsimulator_fr2_66prb 10,0,0,0 10,0,0,0 diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fr2_66prb/docker-compose.yaml similarity index 97% rename from ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml rename to ci-scripts/yaml_files/5g_rfsimulator_fr2_66prb/docker-compose.yaml index 7ae33004f5..dfc7064c0d 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fr2_32prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fr2_66prb/docker-compose.yaml @@ -102,7 +102,7 @@ services: public_net: ipv4_address: 192.168.71.140 volumes: - - ../../conf_files/gnb.sa.band261.u3.32prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf + - ../../conf_files/gnb.sa.band257.u3.66prb.rfsim.conf:/opt/oai-gnb/etc/gnb.conf healthcheck: test: /bin/bash -c "pgrep nr-softmodem" start_period: 10s @@ -122,7 +122,7 @@ services: environment: USE_ADDITIONAL_OPTIONS: --rfsim --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time - -r 32 --numerology 3 --band 261 -C 27533160000 --ssb 73 + -C 27972480000 -r 66 --numerology 3 --ssb 72 --band 257 ASAN_OPTIONS: detect_leaks=0 devices: - /dev/net/tun:/dev/net/tun diff --git a/doc/analog_beamforming.md b/doc/analog_beamforming.md index 6a11a9f94a..02bc4a46f9 100644 --- a/doc/analog_beamforming.md +++ b/doc/analog_beamforming.md @@ -14,7 +14,7 @@ Analog beamforming implementation also allows to enable distributed antenna syst # Configuration file fields for analog beamforming -A set of parameters in configuration files controls the implementation of analog beamforming and instructs the scheduler on how to behave in such scenarios. Since most notably this technique in 5G is employed in FR2, the configuration file example currently available is a RFsim one for band 261. [Config file example](../ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf) +A set of parameters in configuration files controls the implementation of analog beamforming and instructs the scheduler on how to behave in such scenarios. Since most notably this technique in 5G is employed in FR2, the configuration file example currently available is a RFsim one for band 261. [Config file example](../ci-scripts/conf_files/gnb.sa.band257.u3.66prb.rfsim.conf) In the `MACRLC` section of configuration files, there are three new parameters: `set_analog_beamforming`, `beam_duration` and `beams_per_period`. The explanation of these parameters is here provided: - `set_analog_beamforming` can be set a value equal to 1 or 2 to activate or 0 to desactivate analog beamforming (default value is 0) From 39e32c59988e69078d6c2689754edca40affb17e Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 28 Nov 2025 12:41:37 +0100 Subject: [PATCH 07/15] simplify SIB1 scheduling by removing unnecessary storage of information in sched_ctrlCommon --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 124 +++++++++--------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 12d09426a9..d4f1d48601 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -320,62 +320,37 @@ static bool update_rb_mcs_tbs(NR_sched_pdsch_t *pdsch, uint32_t num_total_bytes, return true; } -static NR_sched_pdsch_t schedule_control_sib1(gNB_MAC_INST *gNB_mac, - int CC_id, - NR_sched_pdcch_t *pdcch, - NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, - int time_domain_allocation, - NR_pdsch_dmrs_t *dmrs_parms, - NR_tda_info_t *tda_info, - uint8_t candidate_idx, - int beam, - uint16_t num_total_bytes) +static NR_sched_pdsch_t allocate_sib1(gNB_MAC_INST *gNB_mac, + int CC_id, + NR_sched_pdcch_t *pdcch, + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, + int aggregation_level, + int cce_index, + int time_domain_allocation, + NR_tda_info_t *tda_info, + int beam, + uint16_t num_total_bytes) { - AssertFatal(gNB_mac->sched_ctrlCommon, "sched_ctrlCommon is NULL\n"); NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id]; - uint16_t *vrb_map = cc->vrb_map[beam]; + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + NR_pdsch_dmrs_t dmrs_parms = get_dl_dmrs_params(scc, NULL, tda_info, 1); NR_sched_pdsch_t pdsch = { .bwp_info = get_pdsch_bwp_start_size(gNB_mac, NULL), .time_domain_allocation = time_domain_allocation, - .dmrs_parms = *dmrs_parms, + .dmrs_parms = dmrs_parms, .tda_info = *tda_info, .nrOfLayers = 1, .pm_index = 0, .mcs = 0, // starting from mcs 0 }; - gNB_mac->sched_ctrlCommon->num_total_bytes = num_total_bytes; - uint8_t nr_of_candidates = 0; - - for (int i = 0; i < 3; i++) { - find_aggregation_candidates(&gNB_mac->sched_ctrlCommon->aggregation_level, &nr_of_candidates, gNB_mac->sched_ctrlCommon->search_space,4< 0) - break; // choosing the lower value of aggregation level available - } - AssertFatal(nr_of_candidates > 0, "nr_of_candidates is 0\n"); - gNB_mac->sched_ctrlCommon->cce_index = find_pdcch_candidate(gNB_mac, - CC_id, - gNB_mac->sched_ctrlCommon->aggregation_level, - nr_of_candidates, - beam, - pdcch, - gNB_mac->sched_ctrlCommon->coreset, - 0); - - AssertFatal(gNB_mac->sched_ctrlCommon->cce_index >= 0, "Could not find CCE for coreset0\n"); - - bool success = update_rb_mcs_tbs(&pdsch, gNB_mac->sched_ctrlCommon->num_total_bytes, vrb_map); + uint16_t *vrb_map = cc->vrb_map[beam]; + bool success = update_rb_mcs_tbs(&pdsch, num_total_bytes, vrb_map); if (success) { // Mark the corresponding RBs as used - fill_pdcch_vrb_map(gNB_mac, - CC_id, - pdcch, - gNB_mac->sched_ctrlCommon->cce_index, - gNB_mac->sched_ctrlCommon->aggregation_level, - beam); - for (int rb = 0; rb < pdsch.rbSize; rb++) { + fill_pdcch_vrb_map(gNB_mac, CC_id, pdcch, cce_index, aggregation_level, beam); + for (int rb = 0; rb < pdsch.rbSize; rb++) vrb_map[rb + type0_PDCCH_CSS_config->cset_start_rb] |= SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols); - } } else { pdsch.tb_size = 0; // to signal we couldn't allocate TBS pdsch.time_domain_allocation = -1; @@ -478,10 +453,11 @@ static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac, static bool check_sib1_tda(gNB_MAC_INST *gNB_mac, NR_sched_pdcch_t *sched_pdcch, NR_beam_alloc_t *beam, + int aggregation_level, + int cce_index, int tda, int ssb_index, - int CC_id, - int candidate_idx) + int CC_id) { NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; @@ -502,18 +478,17 @@ static bool check_sib1_tda(gNB_MAC_INST *gNB_mac, if (tda_info.startSymbolIndex < type0_PDCCH_CSS_config->first_symbol_index + type0_PDCCH_CSS_config->num_symbols) return false; - NR_pdsch_dmrs_t dmrs_parms = get_dl_dmrs_params(scc, NULL, &tda_info, 1); - // Configure sched_ctrlCommon for SIB1 - gNB_mac->sib1_pdsch[ssb_index] = schedule_control_sib1(gNB_mac, - CC_id, - sched_pdcch, - type0_PDCCH_CSS_config, - tda, - &dmrs_parms, - &tda_info, - candidate_idx, - beam->idx, - cc->sib1_bcch_length); + gNB_mac->sib1_pdsch[ssb_index] = allocate_sib1(gNB_mac, + CC_id, + sched_pdcch, + type0_PDCCH_CSS_config, + aggregation_level, + cce_index, + tda, + &tda_info, + beam->idx, + cc->sib1_bcch_length); + if (gNB_mac->sib1_pdsch[ssb_index].tb_size > 0) { LOG_D(NR_MAC, "Found TDA for SIB1: %d\n", tda); return true; @@ -544,7 +519,6 @@ void schedule_nr_sib1(module_id_t module_idP, /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ // TODO: Get these values from RRC const int CC_id = 0; - uint8_t candidate_idx = 0; gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; @@ -588,10 +562,30 @@ void schedule_nr_sib1(module_id_t module_idP, NULL, type0_PDCCH_CSS_config); + + uint8_t nr_of_candidates, aggregation_level; + for (int c = 0; c < 3; c++) { + find_aggregation_candidates(&aggregation_level, + &nr_of_candidates, + gNB_mac->sched_ctrlCommon->search_space, + 4 << c); + if (nr_of_candidates > 0) + break; // choosing the lower value of aggregation level available + } + AssertFatal(nr_of_candidates > 0, "nr_of_candidates is 0\n"); + int cce_index = find_pdcch_candidate(gNB_mac, + CC_id, + aggregation_level, + nr_of_candidates, + beam.idx, + &sched_pdcch, + gNB_mac->sched_ctrlCommon->coreset, + 0); + bool res = false; if (gNB_mac->sib1_pdsch[i].time_domain_allocation < 0) { for (int t = 0; t < 16; t++) { - if (check_sib1_tda(gNB_mac, &sched_pdcch, &beam, t, i, CC_id, candidate_idx)) { + if (check_sib1_tda(gNB_mac, &sched_pdcch, &beam, aggregation_level, cce_index, t, i, CC_id)) { res = true; break; } @@ -599,7 +593,14 @@ void schedule_nr_sib1(module_id_t module_idP, } AssertFatal(gNB_mac->sib1_pdsch[i].time_domain_allocation >= 0, "Couldn't select any TDA for SIB1\n"); if (!res) - res = check_sib1_tda(gNB_mac, &sched_pdcch, &beam, gNB_mac->sib1_pdsch[i].time_domain_allocation, i, CC_id, candidate_idx); + res = check_sib1_tda(gNB_mac, + &sched_pdcch, + &beam, + aggregation_level, + cce_index, + gNB_mac->sib1_pdsch[i].time_domain_allocation, + i, + CC_id); int tb_size = gNB_mac->sib1_pdsch[i].tb_size; AssertFatal(res && tb_size > 0, "Couldn't allocate TB for SIB1 for an already allocated TDA\n"); nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; @@ -609,8 +610,8 @@ void schedule_nr_sib1(module_id_t module_idP, &sched_pdcch, gNB_mac->sched_ctrlCommon->search_space, gNB_mac->sched_ctrlCommon->coreset, - gNB_mac->sched_ctrlCommon->aggregation_level, - gNB_mac->sched_ctrlCommon->cce_index, + aggregation_level, + cce_index, dl_req, pdu_index, type0_PDCCH_CSS_config, @@ -682,7 +683,6 @@ static void other_sib_sched_control(module_id_t module_idP, NR_COMMON_channels_t *cc = &gNB_mac->common_channels[0]; NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[cc->ssb_index[beam_index]]; - AssertFatal(gNB_mac->sched_ctrlCommon, "sched_ctrlCommon is NULL\n"); NR_PDSCH_ConfigCommon_t *pdsch_ConfigCommon = scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup; int time_domain_allocation = 1; NR_tda_info_t tda_info = set_tda_info_from_list(pdsch_ConfigCommon->pdsch_TimeDomainAllocationList, time_domain_allocation); From def635ad7dbf2a6b0fdf9e1ffeab8e82207975cb Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 28 Nov 2025 13:03:33 +0100 Subject: [PATCH 08/15] type int for aggregation level and candidates --- openair1/SIMULATION/NR_PHY/dlsim.c | 10 +++------- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 9 +++------ openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 5 +---- openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c | 7 ++----- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 6 +++--- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 7 +++---- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 6 ++---- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 2 +- 9 files changed, 19 insertions(+), 35 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 40ad816d2c..454a23770e 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -198,16 +198,12 @@ void nr_dlsim_preprocessor(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pp_pdsch) NR_UE_DL_BWP_t *current_BWP = &UE_info->current_DL_BWP; NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon; - uint8_t nr_of_candidates = 0; + int nr_of_candidates = 0; if (g_mcsIndex < 4) { - find_aggregation_candidates(&sched_ctrl->aggregation_level, - &nr_of_candidates, - sched_ctrl->search_space,8); + find_aggregation_candidates(&sched_ctrl->aggregation_level, &nr_of_candidates, sched_ctrl->search_space, 8); } if (nr_of_candidates == 0) { - find_aggregation_candidates(&sched_ctrl->aggregation_level, - &nr_of_candidates, - sched_ctrl->search_space,4); + find_aggregation_candidates(&sched_ctrl->aggregation_level, &nr_of_candidates, sched_ctrl->search_space, 4); } uint32_t Y = get_Y(sched_ctrl->search_space, pp_pdsch->slot, UE_info->rnti); int CCEIndex = find_pdcch_candidate(nr_mac, diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 5f38693218..f111f571ba 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1463,14 +1463,11 @@ int get_format0(uint8_t index, uint8_t unpaired, frequency_range_t frequency_ran return format; } -void find_aggregation_candidates(uint8_t *aggregation_level, - uint8_t *nr_of_candidates, - const NR_SearchSpace_t *ss, - int L) +void find_aggregation_candidates(int *aggregation_level, int *nr_of_candidates, const NR_SearchSpace_t *ss, int L) { - AssertFatal(L>=1 && L<=16,"L %d not ok\n", L); + AssertFatal(L >= 1 && L <= 16,"L %d not ok\n", L); *nr_of_candidates = 0; - switch(L) { + switch (L) { case 1: if (ss->nrofCandidates->aggregationLevel1 != NR_SearchSpace__nrofCandidates__aggregationLevel1_n0) { *aggregation_level = 1; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 728ea74238..51bd9aa948 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -171,10 +171,7 @@ uint16_t get_rb_bwp_dci(nr_dci_format_t format, uint16_t initial_ul_bwp_size, uint16_t initial_dl_bwp_size); -void find_aggregation_candidates(uint8_t *aggregation_level, - uint8_t *nr_of_candidates, - const NR_SearchSpace_t *ss, - int maxL); +void find_aggregation_candidates(int *aggregation_level, int *nr_of_candidates, const NR_SearchSpace_t *ss, int L); bool get_nr_prach_sched_from_info(nr_prach_info_t info, int config_index, 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 dc82e5d308..0e8651a84d 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -44,11 +44,8 @@ static void fill_dci_search_candidates(const NR_SearchSpace_t *ss, fapi_nr_dl_co int i = 0; for (int maxL = 16; maxL > 0; maxL >>= 1) { - uint8_t aggregation, max_number_of_candidates; - find_aggregation_candidates(&aggregation, - &max_number_of_candidates, - ss, - maxL); + int aggregation, max_number_of_candidates; + find_aggregation_candidates(&aggregation, &max_number_of_candidates, ss, maxL); if (max_number_of_candidates == 0) continue; LOG_T(NR_MAC_DCI, "L %d, max number of candidates %d, aggregation %d\n", maxL, max_number_of_candidates, aggregation); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 5f80703c21..a5d35e68be 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -918,7 +918,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, nr_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu_rel15; } - uint8_t aggregation_level; + int aggregation_level; int CCEIndex = get_cce_index(nr_mac, CC_id, slot, 0, &aggregation_level, @@ -1517,7 +1517,7 @@ static void nr_generate_Msg2(module_id_t module_idP, return; } - uint8_t aggregation_level; + int aggregation_level; int CCEIndex = get_cce_index(nr_mac, CC_id, slotP, 0, &aggregation_level, beam.idx, ss, coreset, &sched_ctrl->sched_pdcch, 0); if (CCEIndex < 0) { @@ -1716,7 +1716,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, return; // get CCEindex, needed also for PUCCH and then later for PDCCH - uint8_t aggregation_level; + int aggregation_level; int CCEIndex = get_cce_index(nr_mac, CC_id, slotP, 0, &aggregation_level, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index d4f1d48601..01f349877a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -562,8 +562,7 @@ void schedule_nr_sib1(module_id_t module_idP, NULL, type0_PDCCH_CSS_config); - - uint8_t nr_of_candidates, aggregation_level; + int nr_of_candidates, aggregation_level; for (int c = 0; c < 3; c++) { find_aggregation_candidates(&aggregation_level, &nr_of_candidates, @@ -690,8 +689,8 @@ static void other_sib_sched_control(module_id_t module_idP, NR_pdsch_dmrs_t dmrs_parms = get_dl_dmrs_params(scc, NULL, &tda_info, 1); - uint8_t aggregation_level = 0; - uint8_t nr_of_candidates = 0; + int aggregation_level = 0; + int nr_of_candidates = 0; for (int i = 0; i < 5; i++) { find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss, 16 >> i); if (nr_of_candidates > 0) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 4a7213ab34..86fe6f06eb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -592,7 +592,7 @@ int get_cce_index(const gNB_MAC_INST *nrmac, const int CC_id, const int slot, const rnti_t rnti, - uint8_t *aggregation_level, + int *aggregation_level, int beam_idx, const NR_SearchSpace_t *ss, const NR_ControlResourceSet_t *coreset, @@ -600,11 +600,9 @@ int get_cce_index(const gNB_MAC_INST *nrmac, float pdcch_cl_adjust) { const uint32_t Y = get_Y(ss, slot, rnti); - uint8_t nr_of_candidates; - int agg_level_search_order[NUM_PDCCH_AGG_LEVELS]; determine_aggregation_level_search_order(agg_level_search_order, pdcch_cl_adjust); - + int nr_of_candidates; for (int i = 0; i < NUM_PDCCH_AGG_LEVELS; i++) { find_aggregation_candidates(aggregation_level, &nr_of_candidates, ss, 1 << agg_level_search_order[i]); if (nr_of_candidates > 0) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index a8d4c76b31..279f8d01b9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -420,7 +420,7 @@ int get_cce_index(const gNB_MAC_INST *nrmac, const int CC_id, const int slot, const rnti_t rnti, - uint8_t *aggregation_level, + int *aggregation_level, int beam_idx, const NR_SearchSpace_t *ss, const NR_ControlResourceSet_t *coreset, diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 5914c74a45..2971d76607 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -620,7 +620,7 @@ typedef struct { /// CCE index and Aggr. Level are shared for PUSCH/PDSCH allocation decisions /// corresponding to the sched_pusch/sched_pdsch structures below int cce_index; - uint8_t aggregation_level; + int aggregation_level; uint32_t dl_cce_fail, ul_cce_fail; /// Array of PUCCH scheduling information From e22c6c84387a08a855702e52c10ac31d0862a5a7 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 28 Nov 2025 15:52:03 +0100 Subject: [PATCH 09/15] change sched_ctrlCommon to be SIB1 specific and to allow to store search spaces for each SSB at pre-configuration --- common/utils/telnetsrv/telnetsrv_o1.c | 4 +- openair2/LAYER2/NR_MAC_gNB/config.c | 50 ++--- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 175 +++++++++--------- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 2 +- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 3 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 9 +- 6 files changed, 120 insertions(+), 123 deletions(-) diff --git a/common/utils/telnetsrv/telnetsrv_o1.c b/common/utils/telnetsrv/telnetsrv_o1.c index 9ff56e3521..04cd008655 100644 --- a/common/utils/telnetsrv/telnetsrv_o1.c +++ b/common/utils/telnetsrv/telnetsrv_o1.c @@ -345,8 +345,8 @@ static int set_bwconfig(char *buf, int debug, telnet_printfunc_t prnt) ERROR_MSG_RET("unhandled option %s\n", buf); } - free(RC.nrmac[0]->sched_ctrlCommon); - RC.nrmac[0]->sched_ctrlCommon = NULL; + free(RC.nrmac[0]->sched_ctrlSIB1); + RC.nrmac[0]->sched_ctrlSIB1 = NULL; free_MIB_NR(mac->common_channels[0].mib); mac->common_channels[0].mib = get_new_MIB_NR(scc); diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 80401de63a..25348a85f2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -777,21 +777,17 @@ static void initialize_beam_information(NR_beam_info_t *beam_info, int mu, int s } } -static void config_sched_ctrlCommon(gNB_MAC_INST *nr_mac) +static void config_sched_ctrlSIB1(gNB_MAC_INST *nr_mac) { const NR_MIB_t *mib = nr_mac->common_channels[0].mib->message.choice.mib; NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon; - NR_UE_sched_ctrl_t *sched_ctrlCommon = calloc_or_fail(1, sizeof(*sched_ctrlCommon)); - nr_mac->sched_ctrlCommon = sched_ctrlCommon; - sched_ctrlCommon->search_space = calloc_or_fail(1, sizeof(*sched_ctrlCommon->search_space)); - sched_ctrlCommon->coreset = calloc_or_fail(1, sizeof(*sched_ctrlCommon->coreset)); + NR_sched_ctrl_sib1_t *sched_ctrlCommon = calloc_or_fail(1, sizeof(*sched_ctrlCommon)); + nr_mac->sched_ctrlSIB1 = sched_ctrlCommon; NR_SubcarrierSpacing_t scs = *scc->ssbSubcarrierSpacing; const long band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; const int bw = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - uint16_t ssb_start_symbol = get_ssb_start_symbol(band, scs, 0); - int8_t ssb_period = *scc->ssb_periodicityServingCell; uint8_t ssb_frame_periodicity = 1; if (ssb_period > 1) @@ -802,23 +798,27 @@ static void config_sched_ctrlCommon(gNB_MAC_INST *nr_mac) const int prb_offset = frequency_range == FR1 ? nr_mac->ssb_OffsetPointA >> scs : nr_mac->ssb_OffsetPointA >> (scs - 2); NR_Type0_PDCCH_CSS_config_t type0_PDCCH_CSS_config = {0}; - get_type0_PDCCH_CSS_config_parameters(&type0_PDCCH_CSS_config, - 0, - mib, - numb_slots_frame, - nr_mac->ssb_SubcarrierOffset, - ssb_start_symbol, - scs, - frequency_range, - band, - bw, - 0, - ssb_frame_periodicity, - prb_offset); - - fill_searchSpaceZero(sched_ctrlCommon->search_space, numb_slots_frame, &type0_PDCCH_CSS_config); - - fill_coresetZero(sched_ctrlCommon->coreset, &type0_PDCCH_CSS_config); + for (int i = 0; i < get_max_ssbs(scc); i++) { + if (is_ssb_configured(scc, i)) { + uint16_t ssb_start_symbol = get_ssb_start_symbol(band, scs, i); + get_type0_PDCCH_CSS_config_parameters(&type0_PDCCH_CSS_config, + 0, + mib, + numb_slots_frame, + nr_mac->ssb_SubcarrierOffset, + ssb_start_symbol, + scs, + frequency_range, + band, + bw, + i, + ssb_frame_periodicity, + prb_offset); + fill_searchSpaceZero(&sched_ctrlCommon->search_space[i], numb_slots_frame, &type0_PDCCH_CSS_config); + } + } + // CSET0 doesn't depend on SSB index + fill_coresetZero(&sched_ctrlCommon->coreset, &type0_PDCCH_CSS_config); nr_mac->cset0_bwp_start = type0_PDCCH_CSS_config.cset_start_rb; nr_mac->cset0_bwp_size = type0_PDCCH_CSS_config.num_rbs; } @@ -890,7 +890,7 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c find_SSB_and_RO_available(nrmac); if (IS_SA_MODE(get_softmodem_params())) - config_sched_ctrlCommon(nrmac); + config_sched_ctrlSIB1(nrmac); seq_arr_init(&nrmac->ul_tda, sizeof(NR_tda_info_t)); init_ul_tda_info(scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList, &nrmac->ul_tda); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index 01f349877a..b3e3236161 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -114,57 +114,46 @@ static int encode_mib(NR_BCCH_BCH_Message_t *mib, frame_t frame, uint8_t *buffer return encode_size; } -static void schedule_one_ssb(gNB_MAC_INST *gNB, - nfapi_nr_dl_tti_request_body_t *dl_req, - const long band, - const NR_SubcarrierSpacing_t scs, - const int i_ssb, - const int rel_slot, - const frame_t frameP, - const slot_t slotP, - const int CC_id, - const uint8_t ssb_frame_periodicity, - const frequency_range_t FR) +int get_max_ssbs(const NR_ServingCellConfigCommon_t *scc) { - // if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters - const int slots_per_frame = gNB->frame_structure.numb_slots_frame; - const uint16_t offset_pointa = gNB->ssb_OffsetPointA; - NR_COMMON_channels_t *cc = &gNB->common_channels[CC_id]; - NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - const NR_MIB_t *mib = cc->mib->message.choice.mib; - uint32_t mib_pdu = (*(uint32_t *)cc->MIB_pdu) & ((1 << 24) - 1); - uint8_t ssbSubcarrierOffset = gNB->ssb_SubcarrierOffset; - const int bw = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - uint16_t ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb); - NR_beam_alloc_t beam = - beam_allocation_procedure(&gNB->beam_info, frameP, slotP, get_beam_from_ssbidx(gNB, i_ssb), slots_per_frame); - AssertFatal(beam.idx >= 0, "Cannot allocate SSB %d in any available beam\n", i_ssb); - const uint16_t beam_index = - convert_to_fapi_beam(get_allocated_beam(&gNB->beam_info, frameP, slotP, slots_per_frame, beam.idx), gNB->beam_info.beam_mode); - const int prb_offset = (FR == FR2) ? offset_pointa >> (scs - 2) : offset_pointa >> scs; - schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, beam_index, ssbSubcarrierOffset, offset_pointa, mib_pdu); - fill_ssb_vrb_map(cc, - prb_offset, - (FR == FR2) ? ssbSubcarrierOffset >> (scs - 2) : ssbSubcarrierOffset, - ssb_start_symbol, - CC_id, - beam.idx); - if (IS_SA_MODE(get_softmodem_params())) { - get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb], - frameP, - mib, - slots_per_frame, - ssbSubcarrierOffset, - ssb_start_symbol, - scs, - FR, - band, - bw, - i_ssb, - ssb_frame_periodicity, - prb_offset); - gNB->type0_PDCCH_CSS_config[i_ssb].active = true; + int L_max = 0; + switch (scc->ssb_PositionsInBurst->present) { + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap: + L_max = 4; + break; + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap: + L_max = 8; + break; + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap: + L_max = 64; + break; + default: + AssertFatal(false, "Invalid SSB configuration\n"); } + return L_max; +} + +bool is_ssb_configured(const NR_ServingCellConfigCommon_t *scc, int ssb_index) +{ + const BIT_STRING_t *shortBitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap; + const BIT_STRING_t *mediumBitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap; + const BIT_STRING_t *longBitmap = &scc->ssb_PositionsInBurst->choice.longBitmap; + + int pos = 0; + switch (scc->ssb_PositionsInBurst->present) { + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap: + pos = shortBitmap->buf[0] >> (7 - ssb_index); + break; + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap: + pos = mediumBitmap->buf[0] >> (7 - ssb_index); + break; + case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap: + pos = longBitmap->buf[ssb_index / 8] >> (7 - (ssb_index % 8)); + break; + default: + AssertFatal(false, "Invalid SSB configuration\n"); + } + return pos & 0x01; } void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi_nr_dl_tti_request_t *DL_req) @@ -175,6 +164,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { NR_COMMON_channels_t *cc = &gNB->common_channels[CC_id]; + const NR_MIB_t *mib = cc->mib->message.choice.mib; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; const int slots_per_frame = gNB->frame_structure.numb_slots_frame; dl_req = &DL_req->dl_tti_request_body; @@ -195,6 +185,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi mib_sdu_length); } + uint32_t mib_pdu = (*(uint32_t *)cc->MIB_pdu) & ((1 << 24) - 1); int8_t ssb_period = *scc->ssb_periodicityServingCell; uint8_t ssb_frame_periodicity = 1; // every how many frames SSB are generated @@ -212,45 +203,45 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi NR_SubcarrierSpacing_t scs = *scc->ssbSubcarrierSpacing; const long band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; - - const BIT_STRING_t *shortBitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap; - const BIT_STRING_t *mediumBitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap; - const BIT_STRING_t *longBitmap = &scc->ssb_PositionsInBurst->choice.longBitmap; - - switch (scc->ssb_PositionsInBurst->present) { - case 1: - // short bitmap (<3GHz) max 4 SSBs - for (int i_ssb = 0; i_ssb < 4; i_ssb++) { - if ((shortBitmap->buf[0] >> (7 - i_ssb)) & 0x01) { - uint16_t ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb); - if ((ssb_start_symbol / 14) == rel_slot) - schedule_one_ssb(gNB, dl_req, band, scs, i_ssb, rel_slot, frameP, slotP, CC_id, ssb_frame_periodicity, FR1); + const int bw = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; + const uint16_t offset_pointa = gNB->ssb_OffsetPointA; + uint8_t ssbSubcarrierOffset = gNB->ssb_SubcarrierOffset; + const int L_max = get_max_ssbs(scc); + const frequency_range_t frequency_range = scc->ssb_PositionsInBurst->present == 3 ? FR2 : FR1; + const int prb_offset = frequency_range == FR1 ? offset_pointa >> scs : offset_pointa >> (scs - 2); + for (int i_ssb = 0; i_ssb < L_max; i_ssb++) { + if (is_ssb_configured(scc, i_ssb)) { + uint16_t ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb); + // if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters + if ((ssb_start_symbol / 14) == rel_slot) { + NR_beam_alloc_t beam = beam_allocation_procedure(&gNB->beam_info, + frameP, + slotP, + get_beam_from_ssbidx(gNB, i_ssb), + slots_per_frame); + AssertFatal(beam.idx >= 0, "Cannot allocate SSB %d in any available beam\n", i_ssb); + const uint16_t alloc_beam_idx = get_allocated_beam(&gNB->beam_info, frameP, slotP, slots_per_frame, beam.idx); + const uint16_t fapi_beam = convert_to_fapi_beam(alloc_beam_idx, gNB->beam_info.beam_mode); + schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, fapi_beam, ssbSubcarrierOffset, offset_pointa, mib_pdu); + fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id, beam.idx); + if (IS_SA_MODE(get_softmodem_params())) { + get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb], + frameP, + mib, + slots_per_frame, + ssbSubcarrierOffset, + ssb_start_symbol, + scs, + frequency_range, + band, + bw, + i_ssb, + ssb_frame_periodicity, + prb_offset); + gNB->type0_PDCCH_CSS_config[i_ssb].active = true; } } - break; - case 2: - // medium bitmap (<6GHz) max 8 SSBs - for (int i_ssb = 0; i_ssb < 8; i_ssb++) { - if ((mediumBitmap->buf[0] >> (7 - i_ssb)) & 0x01) { - uint16_t ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb); - if ((ssb_start_symbol / 14) == rel_slot) - schedule_one_ssb(gNB, dl_req, band, scs, i_ssb, rel_slot, frameP, slotP, CC_id, ssb_frame_periodicity, FR1); - } - } - break; - case 3: - // long bitmap FR2 max 64 SSBs - for (int i_ssb = 0; i_ssb < 64; i_ssb++) { - if ((longBitmap->buf[i_ssb / 8] >> (7 - (i_ssb % 8))) & 0x01) { - uint16_t ssb_start_symbol = get_ssb_start_symbol(band, scs, i_ssb); - if ((ssb_start_symbol / 14) == rel_slot) - schedule_one_ssb(gNB, dl_req, band, scs, i_ssb, rel_slot, frameP, slotP, CC_id, ssb_frame_periodicity, FR2); - } - } - break; - default: - AssertFatal(0,"SSB bitmap size value %d undefined (allowed values 1,2,3)\n", - scc->ssb_PositionsInBurst->present); + } } } } @@ -556,8 +547,8 @@ void schedule_nr_sib1(module_id_t module_idP, AssertFatal(beam.idx >= 0, "Cannot allocate SIB1 corresponding to SSB %d in any available beam\n", i); LOG_D(NR_MAC,"(%d.%d) SIB1 transmission: ssb_index %d\n", frameP, slotP, type0_PDCCH_CSS_config->ssb_index); NR_sched_pdcch_t sched_pdcch = set_pdcch_structure(NULL, - gNB_mac->sched_ctrlCommon->search_space, - gNB_mac->sched_ctrlCommon->coreset, + &gNB_mac->sched_ctrlSIB1->search_space[i], + &gNB_mac->sched_ctrlSIB1->coreset, scc, NULL, type0_PDCCH_CSS_config); @@ -566,7 +557,7 @@ void schedule_nr_sib1(module_id_t module_idP, for (int c = 0; c < 3; c++) { find_aggregation_candidates(&aggregation_level, &nr_of_candidates, - gNB_mac->sched_ctrlCommon->search_space, + &gNB_mac->sched_ctrlSIB1->search_space[i], 4 << c); if (nr_of_candidates > 0) break; // choosing the lower value of aggregation level available @@ -578,7 +569,7 @@ void schedule_nr_sib1(module_id_t module_idP, nr_of_candidates, beam.idx, &sched_pdcch, - gNB_mac->sched_ctrlCommon->coreset, + &gNB_mac->sched_ctrlSIB1->coreset, 0); bool res = false; @@ -607,8 +598,8 @@ void schedule_nr_sib1(module_id_t module_idP, nr_fill_nfapi_dl_SIB_pdu(gNB_mac, &gNB_mac->sib1_pdsch[i], &sched_pdcch, - gNB_mac->sched_ctrlCommon->search_space, - gNB_mac->sched_ctrlCommon->coreset, + &gNB_mac->sched_ctrlSIB1->search_space[i], + &gNB_mac->sched_ctrlSIB1->coreset, aggregation_level, cce_index, dl_req, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 86fe6f06eb..55b76e8eb7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -397,7 +397,7 @@ NR_ControlResourceSet_t *get_coreset(gNB_MAC_INST *nrmac, NR_ControlResourceSetId_t coreset_id) { if (coreset_id == 0) { - return nrmac->sched_ctrlCommon->coreset; // this is coreset 0 + return &nrmac->sched_ctrlSIB1->coreset; // this is coreset 0 } if (bwp_dedicated) { const int n = bwp_dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list.count; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 279f8d01b9..239c63b18f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -39,7 +39,8 @@ void set_cset_offset(uint16_t); void get_K1_K2(int N1, int N2, int *K1, int *K2, int layers); int get_NTN_Koffset(const NR_ServingCellConfigCommon_t *scc); - +bool is_ssb_configured(const NR_ServingCellConfigCommon_t *scc, int ssb_index); +int get_max_ssbs(const NR_ServingCellConfigCommon_t *scc); int get_first_ul_slot(const frame_structure_t *fs, bool mixed); int get_ul_slots_per_period(const frame_structure_t *fs); int get_ul_slots_per_frame(const frame_structure_t *fs); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 2971d76607..46b32482cc 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -883,6 +883,11 @@ typedef struct dlul_mac_stats { mac_stats_t ul; } dlul_mac_stats_t; +typedef struct { + NR_SearchSpace_t search_space[MAX_NUM_OF_SSB]; + NR_ControlResourceSet_t coreset; +} NR_sched_ctrl_sib1_t; + /// helper type to encapsulate a frame/slot combination in a single type. /// Currently only used in the UL preprocessor. Note: if you use this type /// further, please refactor it into a common type first. @@ -979,11 +984,11 @@ typedef struct gNB_MAC_INST_s { nr_mac_config_t radio_config; nr_rlc_configuration_t rlc_config; - NR_UE_sched_ctrl_t *sched_ctrlCommon; + NR_sched_ctrl_sib1_t *sched_ctrlSIB1; NR_sched_pdcch_t *sched_pdcch_otherSI; uint16_t cset0_bwp_start; uint16_t cset0_bwp_size; - NR_Type0_PDCCH_CSS_config_t type0_PDCCH_CSS_config[64]; + NR_Type0_PDCCH_CSS_config_t type0_PDCCH_CSS_config[MAX_NUM_OF_SSB]; bool first_MIB; NR_bler_options_t dl_bler; From 64091c9a5125bc38c1d3bc1b83261cc1cd28ec50 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 28 Nov 2025 16:21:06 +0100 Subject: [PATCH 10/15] remove workaround to take into account first symbol index, necessary when only SS for SSB 0 was pre-computed --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 55b76e8eb7..c1f1b17e5e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -513,7 +513,7 @@ NR_sched_pdcch_t set_pdcch_structure(gNB_MAC_INST *gNB_mac, for (int i = 0; i < sps; i++) { if ((monitoringSymbolsWithinSlot >> (sps - 1 - i)) & 1) { - pdcch.StartSymbolIndex = ss->searchSpaceId == 0 ? i + type0_PDCCH_CSS_config->first_symbol_index : i; + pdcch.StartSymbolIndex = i; break; } } From 5e6d9dbbc6d36f62b0a64073fb24b9d773be4884 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 2 Dec 2025 09:40:20 +0100 Subject: [PATCH 11/15] fix for SSB larger than 7 at UE --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 5 +---- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 11 ++++++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 3ba221386f..b94a8758c8 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -195,10 +195,7 @@ void nr_ue_decode_mib(NR_UE_MAC_INST_t *mac, int cc_id) frame = frame << 4; mac->mib_frame = frame | frame_number_4lsb; - if (mac->frequency_range == FR2) { - for (int i = 0; i < 3; i++) - mac->mib_ssb += (((extra_bits >> (7 - i)) & 0x01) << (3 + i)); - } else{ + if (mac->frequency_range == FR1) { if(ssb_subcarrier_offset_msb) ssb_subcarrier_offset = ssb_subcarrier_offset | 0x10; } diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 09f3218f1e..42030133af 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -108,18 +108,23 @@ static int handle_bcch_bch(NR_UE_MAC_INST_t *mac, void *phy_data, uint8_t *pduP, unsigned int additional_bits, - uint32_t ssb_index, + uint32_t ssb_index_mod8, uint32_t ssb_length, uint16_t ssb_start_subcarrier, long ssb_arfcn, uint16_t cell_id) { - mac->mib_ssb = ssb_index; + mac->mib_ssb = ssb_index_mod8; mac->physCellId = cell_id; mac->mib_additional_bits = additional_bits; mac->ssb_start_subcarrier = ssb_start_subcarrier; - if(ssb_length == 64) + if(ssb_length == 64) { mac->frequency_range = FR2; + uint8_t ab = additional_bits & 0xff; + uint8_t out; + reverse_bits_u8(&ab, 1, &out); + mac->mib_ssb += (out & 0x7) << 3; + } else mac->frequency_range = FR1; // fixed 3 bytes MIB PDU From 15bd09dd240e57950910d4f5d733e7b5e97a1966 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 8 Dec 2025 14:54:48 +0100 Subject: [PATCH 12/15] use commonControlResourceSet instead of CSET0 as coreset for common SearchSpaces in case of MUX pattern 3 --- .../gnb.sa.band257.u3.66prb.rfsim.conf | 11 +++- .../docker-compose.yaml | 2 +- openair2/GNB_APP/gnb_config.c | 2 +- openair2/LAYER2/NR_MAC_gNB/config.c | 9 +++ openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c | 59 ++++++++++++++----- openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h | 2 +- 6 files changed, 65 insertions(+), 20 deletions(-) diff --git a/ci-scripts/conf_files/gnb.sa.band257.u3.66prb.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band257.u3.66prb.rfsim.conf index fac77fc70e..d7c0e1a307 100644 --- a/ci-scripts/conf_files/gnb.sa.band257.u3.66prb.rfsim.conf +++ b/ci-scripts/conf_files/gnb.sa.band257.u3.66prb.rfsim.conf @@ -32,7 +32,7 @@ gNBs = absoluteFrequencySSB = 2078299; dl_frequencyBand = 257; # this is 27.900 GHz - dl_absoluteFrequencyPointA = 2077915; + dl_absoluteFrequencyPointA = 2077963; #scs-SpecificCarrierList dl_offstToCarrier = 0; # subcarrierSpacing @@ -42,7 +42,7 @@ gNBs = #initialDownlinkBWP #genericParameters # this is RBstart=0,L=32 (275*(L-1))+RBstart - initialDLBWPlocationAndBandwidth = 13475; + initialDLBWPlocationAndBandwidth = 6349; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialDLBWPsubcarrierSpacing = 3; @@ -62,7 +62,7 @@ gNBs = pMax = 20; #initialUplinkBWP #genericParameters - initialULBWPlocationAndBandwidth = 13475; + initialULBWPlocationAndBandwidth = 6349; # subcarrierSpacing # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 initialULBWPsubcarrierSpacing = 3; @@ -143,6 +143,11 @@ gNBs = ); + first_active_bwp = 1; + bwp_list = ( + { scs = 3; bwpStart = 0; bwpSize = 66;} + ); + # ------- SCTP definitions SCTP : { diff --git a/ci-scripts/yaml_files/5g_rfsimulator_fr2_66prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_fr2_66prb/docker-compose.yaml index dfc7064c0d..972dd56010 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_fr2_66prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_fr2_66prb/docker-compose.yaml @@ -122,7 +122,7 @@ services: environment: USE_ADDITIONAL_OPTIONS: --rfsim --rfsimulator.serveraddr 192.168.71.140 --log_config.global_log_options level,nocolor,time - -C 27972480000 -r 66 --numerology 3 --ssb 72 --band 257 + -C 27975360000 -r 66 --numerology 3 --ssb 48 --band 257 ASAN_OPTIONS: detect_leaks=0 devices: - /dev/net/tun:/dev/net/tun diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 36ee2e4f0c..6fe8bad943 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -587,7 +587,7 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap) nr_rrc_config_dl_tda(dlcc->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList, frame_type, scc->tdd_UL_DL_ConfigurationCommon, - dlcc->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); + NRRIV2BW(dlcc->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE)); if (frame_type == FDD) { ASN_STRUCT_FREE(asn_DEF_NR_TDD_UL_DL_ConfigCommon, scc->tdd_UL_DL_ConfigurationCommon); diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 25348a85f2..de524d60d8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -821,6 +821,15 @@ static void config_sched_ctrlSIB1(gNB_MAC_INST *nr_mac) fill_coresetZero(&sched_ctrlCommon->coreset, &type0_PDCCH_CSS_config); nr_mac->cset0_bwp_start = type0_PDCCH_CSS_config.cset_start_rb; nr_mac->cset0_bwp_size = type0_PDCCH_CSS_config.num_rbs; + if (type0_PDCCH_CSS_config.type0_pdcch_ss_mux_pattern > 1) { + int bwp_start = NRRIV2PRBOFFSET(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, + MAX_BWP_SIZE); + int bwp_size = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); + // we need to configure a commonControlResourceSet != 0 + // because CSET0 would start from a symbol != 0 and that's unwanted for anything but SIB1 + // The network configures the commonControlResourceSet in SIB1 so that it is contained in the bandwidth of CSET0 + configure_coreset_for_mux23(scc, nr_mac->cset0_bwp_start - bwp_start, nr_mac->cset0_bwp_size, bwp_start, bwp_size); + } } /** diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 50f5fd684c..15d9546172 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -273,20 +273,41 @@ NR_SearchSpace_t *rrc_searchspace_config(bool is_common, return ss; } -static NR_ControlResourceSet_t *get_coreset_config(int bwp_id, int bwp_start, int bwp_size, uint64_t ssb_bitmap) +static NR_ControlResourceSet_t *get_coreset_config(int bwp_id, + int cset_offset, + int cset_limit, + int bwp_start, + int bwp_size, + uint64_t ssb_bitmap) { NR_ControlResourceSet_t *coreset = calloc(1, sizeof(*coreset)); AssertFatal(coreset != NULL, "out of memory\n"); // frequency domain resources depending on BWP size int additional_offset = (bwp_start + 5) / 6 * 6 - bwp_start; + int cset_shift = 0; + if (cset_offset > additional_offset) { + cset_shift = cset_offset / 6 + (cset_offset % 6 > 0); + additional_offset += cset_shift * 6; + } int eff_bwp_size = bwp_size - additional_offset; + if (cset_limit && eff_bwp_size > cset_limit) + eff_bwp_size = cset_limit; + AssertFatal(eff_bwp_size >= 24, "CORESET effective BWP size %d is less than 24 PRB, can't allocate\n", eff_bwp_size); coreset->frequencyDomainResources.buf = calloc(1,6); - coreset->frequencyDomainResources.buf[0] = (eff_bwp_size < 48) ? 0xf0 : 0xff; - coreset->frequencyDomainResources.buf[1] = (eff_bwp_size < 96) ? 0x00 : 0xff; - coreset->frequencyDomainResources.buf[2] = (eff_bwp_size < 144) ? 0x00 : 0xff; - coreset->frequencyDomainResources.buf[3] = (eff_bwp_size < 192) ? 0x00 : 0xff; - coreset->frequencyDomainResources.buf[4] = (eff_bwp_size < 240) ? 0x00 : 0xff; - coreset->frequencyDomainResources.buf[5] = 0x00; + uint64_t buf = 0; + if (eff_bwp_size < 48) + buf = 0xf; + else { + for (int i = 0; i < eff_bwp_size / 48; i++) { + buf <<= 8; + buf += 0xff; + } + } + buf <<= cset_shift; + for (int b = 0; b < 6; b++) { + uint8_t temp_buf = (buf >> (8 * b)) & 0xff; + reverse_bits_u8(&temp_buf, 1, &coreset->frequencyDomainResources.buf[b]); + } coreset->frequencyDomainResources.size = 6; coreset->frequencyDomainResources.bits_unused = 3; coreset->duration = (eff_bwp_size < 48) ? 2 : 1; @@ -1001,8 +1022,8 @@ void prepare_sim_uecap(NR_UE_NR_Capability_t *cap, void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsch_TimeDomainAllocationList, frame_type_t frame_type, NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, - int curr_bwp) { - + int curr_bwp) +{ // coreset duration setting to be improved in the framework of RRC harmonization, potentially using a common function int len_coreset = 1; if (curr_bwp < 48) @@ -1751,7 +1772,7 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t int bwp_size = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); int bwp_start = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); uint64_t ssb_bitmap = get_ssb_bitmap(scc); - NR_ControlResourceSet_t *coreset = get_coreset_config(bwp->bwp_Id, bwp_start, bwp_size, ssb_bitmap); + NR_ControlResourceSet_t *coreset = get_coreset_config(bwp->bwp_Id, 0, 0, bwp_start, bwp_size, ssb_bitmap); bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonControlResourceSet = coreset; bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceZero=NULL; @@ -1803,9 +1824,8 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList = calloc(1,sizeof(*bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList)); bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList = calloc(1,sizeof(*bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList)); - // coreset2 is identical to coreset above, but reallocated to prevent double - // frees - NR_ControlResourceSet_t *coreset2 = get_coreset_config(bwp->bwp_Id, bwp_start, bwp_size, ssb_bitmap); + // coreset2 is identical to coreset above, but reallocated to prevent double frees + NR_ControlResourceSet_t *coreset2 = get_coreset_config(bwp->bwp_Id, 0, 0, bwp_start, bwp_size, ssb_bitmap); asn1cSeqAdd(&bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list, coreset2); int rrc_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS]; int num_cces = get_coreset_num_cces(coreset2->frequencyDomainResources.buf, coreset2->duration); @@ -2710,6 +2730,17 @@ static BIT_STRING_t bit_string_clone(const BIT_STRING_t *orig) return bs; } + +void configure_coreset_for_mux23(const NR_ServingCellConfigCommon_t *scc, int offset, int limit, int bwp_start, int bwp_size) +{ + NR_ControlResourceSet_t *coreset = get_coreset_config(5, offset, limit, bwp_start, bwp_size, get_ssb_bitmap(scc)); + NR_PDCCH_ConfigCommon_t *pdcch_common = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup; + pdcch_common->commonControlResourceSet = coreset; + for (int i = 0; i < pdcch_common->commonSearchSpaceList->list.count; i++) { + *pdcch_common->commonSearchSpaceList->list.array[i]->controlResourceSetId = coreset->controlResourceSetId; + } +} + NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, const plmn_id_t *plmn, uint64_t cellID, @@ -3336,7 +3367,7 @@ static NR_BWP_DownlinkDedicated_t *configure_initial_dl_bwp(const NR_ServingCell NR_BWP_t *genericParameters = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters; int bwp_size = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); int bwp_start = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); - NR_ControlResourceSet_t *coreset = get_coreset_config(0, bwp_start, bwp_size, bitmap); + NR_ControlResourceSet_t *coreset = get_coreset_config(0, 0, 0, bwp_start, bwp_size, bitmap); asn1cSeqAdd(&pdcch_Config->controlResourceSetToAddModList->list, coreset); int css_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS]; diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h index 6752db8bc8..cbfd603020 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h @@ -68,7 +68,7 @@ NR_BCCH_BCH_Message_t *get_new_MIB_NR(const NR_ServingCellConfigCommon_t *scc); void free_MIB_NR(NR_BCCH_BCH_Message_t *mib); int encode_MIB_NR(NR_BCCH_BCH_Message_t *mib, int frame, uint8_t *buf, int buf_size); int encode_MIB_NR_setup(NR_MIB_t *mib, int frame, uint8_t *buf, int buf_size); - +void configure_coreset_for_mux23(const NR_ServingCellConfigCommon_t *scc, int offset, int limit, int bwp_start, int bwp_size); struct NR_MeasurementTimingConfiguration; struct NR_MeasurementTimingConfiguration *get_new_MeasurementTimingConfiguration(const NR_ServingCellConfigCommon_t *scc); int encode_MeasurementTimingConfiguration(const struct NR_MeasurementTimingConfiguration *mtc, uint8_t *buf, int buf_len); From 9031b26cf8096a11a3b3c0404a0524f2e8bbadf3 Mon Sep 17 00:00:00 2001 From: francescomani Date: Sun, 14 Dec 2025 16:19:14 +0100 Subject: [PATCH 13/15] add safety check to avoid scheduling MSG4 ACK if there is less than 2 symbols in mixed slot (PUCCH for MSG4 ACK is 2 symbols) --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index bc29981928..db5a817897 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -1150,8 +1150,8 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac, const int minfbtime = mac->radio_config.minRXTXTIME + NTN_gNB_Koffset; const NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; - const int n_slots_frame = mac->frame_structure.numb_slots_frame; const frame_structure_t *fs = &mac->frame_structure; + const int n_slots_frame = fs->numb_slots_frame; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_PUCCH_Config_t *pucch_Config = ul_bwp->pucch_Config; @@ -1173,9 +1173,12 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac, const int pucch_slot = (slot + pdsch_to_harq_feedback[f] + NTN_gNB_Koffset) % n_slots_frame; // check if the slot is UL if (fs->frame_type == TDD) { - int mod_slot = pucch_slot % fs->numb_slots_period; + int mod_slot = get_slot_idx_in_period(pucch_slot, fs); if (!is_ul_slot(mod_slot, fs)) continue; + const tdd_period_config_t *pc = &fs->period_cfg; + if (r_pucch >= 0 && is_mixed_slot(mod_slot, fs) && pc->tdd_slot_bitmap[mod_slot].num_ul_symbols < 2) + continue; } const int pucch_frame = (frame + ((slot + pdsch_to_harq_feedback[f] + NTN_gNB_Koffset) / n_slots_frame)) % MAX_FRAME_NUMBER; // we store PUCCH resources according to slot, TDD configuration and size of the vector containing PUCCH structures From c903d9f640ffde323534c357deb746d67d71de9a Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 22 Dec 2025 17:44:03 +0100 Subject: [PATCH 14/15] refactoring nr_generate_Msg3_retransmission replacing if(X) logic with if(!X) logic --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 356 +++++++++--------- 1 file changed, 178 insertions(+), 178 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index a5d35e68be..d23e95f5ae 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -813,186 +813,186 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, const int sched_frame = (frame + (slot + K2) / slots_frame) % MAX_FRAME_NUMBER; const int sched_slot = (slot + K2) % slots_frame; - if (is_dl_slot(slot, &nr_mac->frame_structure) && is_ul_slot(sched_slot, &nr_mac->frame_structure)) { - NR_beam_alloc_t beam_ul = beam_allocation_procedure(&nr_mac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_frame); - if (beam_ul.idx < 0) - return; - NR_beam_alloc_t beam_dci = beam_allocation_procedure(&nr_mac->beam_info, frame, slot, UE->UE_beam_index, slots_frame); - if (beam_dci.idx < 0) { - reset_beam_status(&nr_mac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_frame, beam_ul.new_beam); - return; - } - int buffer_index = ul_buffer_index(sched_frame, sched_slot, slots_frame, nr_mac->vrb_map_UL_size); - uint16_t *vrb_map_UL = &nr_mac->common_channels[CC_id].vrb_map_UL[beam_ul.idx][buffer_index * MAX_BWP_SIZE]; + if (!is_dl_slot(slot, &nr_mac->frame_structure) || !is_ul_slot(sched_slot, &nr_mac->frame_structure)) + return; - NR_pusch_dmrs_t dmrs_info = get_ul_dmrs_params(scc, ul_bwp, &tda_info, 1); - int num_dmrs_symb = count_bits64_with_mask(dmrs_info.ul_dmrs_symb_pos, tda_info.startSymbolIndex, tda_info.nrOfSymbols); - int TBS = 0, mcsindex = 0, R = 0, Qm = 0; - while(TBS < 7) { // TBS for msg3 is 7 bytes (except for RRCResumeRequest1 currently not implemented) - mcsindex++; - AssertFatal(mcsindex <= 28, "Exceeding MCS limit for Msg3\n"); - R = nr_get_code_rate_ul(mcsindex, ul_bwp->mcs_table); - Qm = nr_get_Qm_ul(mcsindex, ul_bwp->mcs_table); - TBS = nr_compute_tbs(Qm, - R, - ra->msg3_nb_rb, - tda_info.nrOfSymbols, - num_dmrs_symb * 12, // nb dmrs set for no data in dmrs symbol - 0, //nb_rb_oh - 0, // to verify tb scaling - 1) >> 3; - } - - NR_sched_pusch_t sched_pusch = { - .bwp_info = get_pusch_bwp_start_size(UE), - .tb_size = TBS, - .rbSize = ra->msg3_nb_rb, - .R = R, - .Qm = Qm, - .mcs = mcsindex, - .nrOfLayers = 1, - .tda_info = tda_info, - .dmrs_info = dmrs_info, - }; - - int rbStart = 0; - for (int i = 0; (i < ra->msg3_nb_rb) && (rbStart <= (sched_pusch.bwp_info.bwpSize - ra->msg3_nb_rb)); i++) { - if (vrb_map_UL[rbStart + sched_pusch.bwp_info.bwpStart + i] & SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols)) { - rbStart += i; - i = 0; - } - } - if (rbStart > (sched_pusch.bwp_info.bwpSize - ra->msg3_nb_rb)) { - // cannot find free vrb_map for msg3 retransmission in this slot - reset_beam_status(&nr_mac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_frame, beam_ul.new_beam); - reset_beam_status(&nr_mac->beam_info, frame, slot, UE->UE_beam_index, slots_frame, beam_dci.new_beam); - return; - } - - sched_pusch.rbStart = rbStart; - LOG_I(NR_MAC, - "%4d%2d: RA RNTI %04x CC_id %d Scheduling retransmission of Msg3 in (%d,%d)\n", - frame, - slot, - UE->rnti, - CC_id, - sched_frame, - sched_slot); - - buffer_index = ul_buffer_index(sched_frame, sched_slot, slots_frame, nr_mac->UL_tti_req_ahead_size); - nfapi_nr_ul_tti_request_t *future_ul_tti_req = &nr_mac->UL_tti_req_ahead[CC_id][buffer_index]; - AssertFatal(future_ul_tti_req->SFN == sched_frame - && future_ul_tti_req->Slot == sched_slot, - "future UL_tti_req's frame.slot %d.%d does not match PUSCH %d.%d\n", - future_ul_tti_req->SFN, - future_ul_tti_req->Slot, - sched_frame, - sched_slot); - AssertFatal(future_ul_tti_req->n_pdus < - sizeof(future_ul_tti_req->pdus_list) / sizeof(future_ul_tti_req->pdus_list[0]), - "Invalid future_ul_tti_req->n_pdus %d\n", future_ul_tti_req->n_pdus); - future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; - future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); - nfapi_nr_pusch_pdu_t *pusch_pdu = prepare_pusch_pdu(future_ul_tti_req, - UE, - scc, - &sched_pusch, - get_transformPrecoding(ul_bwp, NR_UL_DCI_FORMAT_0_0, 0), - 0, - ra->msg3_round, - ul_bwp->pusch_Config && ul_bwp->pusch_Config->frequencyHopping, - UE->rnti, - nr_mac->beam_info.beam_mode); - future_ul_tti_req->n_pdus += 1; - - // generation of DCI 0_0 to schedule msg3 retransmission - nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = nr_mac->pdcch_pdu_idx[CC_id][coresetid]; - if (!pdcch_pdu_rel15) { - nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu = &ul_dci_req->ul_dci_pdu_list[ul_dci_req->numPdus]; - memset(ul_dci_request_pdu, 0, sizeof(nfapi_nr_ul_dci_request_pdus_t)); - ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; - ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); - pdcch_pdu_rel15 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; - ul_dci_req->numPdus += 1; - nr_configure_pdcch(pdcch_pdu_rel15, coreset, &UE->UE_sched_ctrl.sched_pdcch); - nr_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu_rel15; - } - - int aggregation_level; - int CCEIndex = get_cce_index(nr_mac, - CC_id, slot, 0, - &aggregation_level, - beam_dci.idx, - ss, - coreset, - &UE->UE_sched_ctrl.sched_pdcch, - 0); - if (CCEIndex < 0) { - LOG_E(NR_MAC, "UE %04x cannot find free CCE!\n", UE->rnti); - reset_beam_status(&nr_mac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_frame, beam_ul.new_beam); - reset_beam_status(&nr_mac->beam_info, frame, slot, UE->UE_beam_index, slots_frame, beam_dci.new_beam); - return; - } - - // Fill PDCCH DL DCI PDU - const uint16_t fapi_beam = convert_to_fapi_beam(UE->UE_beam_index, nr_mac->beam_info.beam_mode); - nfapi_nr_dl_dci_pdu_t *dci_pdu = - prepare_dci_pdu(pdcch_pdu_rel15, scc, ss, coreset, aggregation_level, CCEIndex, fapi_beam, UE->rnti); - pdcch_pdu_rel15->numDlDci++; - - dci_pdu_rel15_t uldci_payload = {0}; - config_uldci(sc_info, - pusch_pdu, - &uldci_payload, - NULL, - NULL, - ra->Msg3_tda_id, - ra->msg3_TPC, - 1, // Not toggling NDI in msg3 retransmissions - ul_bwp, - ss->searchSpaceType->present); - - // Reset TPC to 0 dB to not request new gain multiple times before computing new value for SNR - ra->msg3_TPC = 1; - - fill_dci_pdu_rel15(sc_info, - &UE->current_DL_BWP, - ul_bwp, - dci_pdu, - &uldci_payload, - NR_UL_DCI_FORMAT_0_0, - TYPE_TC_RNTI_, - ss, - coreset, - 0, // parameter not needed for DCI 0_0 - nr_mac->cset0_bwp_size); - - // Mark the corresponding RBs as used - - fill_pdcch_vrb_map(nr_mac, - CC_id, - &UE->UE_sched_ctrl.sched_pdcch, - CCEIndex, - aggregation_level, - beam_dci.idx); - - for (int rb = 0; rb < ra->msg3_nb_rb; rb++) { - vrb_map_UL[rbStart + sched_pusch.bwp_info.bwpStart + rb] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); - } - - // Restart RA contention resolution timer in Msg3 retransmission slot (current slot + K2) - // 3GPP TS 38.321 Section 5.1.5 Contention Resolution - start_ra_contention_resolution_timer( - ra, - scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer, - K2, - ul_bwp->scs); - - // reset state to wait msg3 - ra->ra_state = nrRA_WAIT_Msg3; - ra->Msg3_frame = sched_frame; - ra->Msg3_slot = sched_slot; + NR_beam_alloc_t beam_ul = beam_allocation_procedure(&nr_mac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_frame); + if (beam_ul.idx < 0) + return; + NR_beam_alloc_t beam_dci = beam_allocation_procedure(&nr_mac->beam_info, frame, slot, UE->UE_beam_index, slots_frame); + if (beam_dci.idx < 0) { + reset_beam_status(&nr_mac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_frame, beam_ul.new_beam); + return; } + int buffer_index = ul_buffer_index(sched_frame, sched_slot, slots_frame, nr_mac->vrb_map_UL_size); + uint16_t *vrb_map_UL = &nr_mac->common_channels[CC_id].vrb_map_UL[beam_ul.idx][buffer_index * MAX_BWP_SIZE]; + + NR_pusch_dmrs_t dmrs_info = get_ul_dmrs_params(scc, ul_bwp, &tda_info, 1); + int num_dmrs_symb = count_bits64_with_mask(dmrs_info.ul_dmrs_symb_pos, tda_info.startSymbolIndex, tda_info.nrOfSymbols); + int TBS = 0, mcsindex = 0, R = 0, Qm = 0; + while(TBS < 7) { // TBS for msg3 is 7 bytes (except for RRCResumeRequest1 currently not implemented) + mcsindex++; + AssertFatal(mcsindex <= 28, "Exceeding MCS limit for Msg3\n"); + R = nr_get_code_rate_ul(mcsindex, ul_bwp->mcs_table); + Qm = nr_get_Qm_ul(mcsindex, ul_bwp->mcs_table); + TBS = nr_compute_tbs(Qm, + R, + ra->msg3_nb_rb, + tda_info.nrOfSymbols, + num_dmrs_symb * 12, // nb dmrs set for no data in dmrs symbol + 0, //nb_rb_oh + 0, // to verify tb scaling + 1) >> 3; + } + + NR_sched_pusch_t sched_pusch = { + .bwp_info = get_pusch_bwp_start_size(UE), + .tb_size = TBS, + .rbSize = ra->msg3_nb_rb, + .R = R, + .Qm = Qm, + .mcs = mcsindex, + .nrOfLayers = 1, + .tda_info = tda_info, + .dmrs_info = dmrs_info, + }; + + int rbStart = 0; + for (int i = 0; (i < ra->msg3_nb_rb) && (rbStart <= (sched_pusch.bwp_info.bwpSize - ra->msg3_nb_rb)); i++) { + if (vrb_map_UL[rbStart + sched_pusch.bwp_info.bwpStart + i] & SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols)) { + rbStart += i; + i = 0; + } + } + if (rbStart > (sched_pusch.bwp_info.bwpSize - ra->msg3_nb_rb)) { + // cannot find free vrb_map for msg3 retransmission in this slot + reset_beam_status(&nr_mac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_frame, beam_ul.new_beam); + reset_beam_status(&nr_mac->beam_info, frame, slot, UE->UE_beam_index, slots_frame, beam_dci.new_beam); + return; + } + + sched_pusch.rbStart = rbStart; + LOG_I(NR_MAC, + "%4d%2d: RA RNTI %04x CC_id %d Scheduling retransmission of Msg3 in (%d,%d)\n", + frame, + slot, + UE->rnti, + CC_id, + sched_frame, + sched_slot); + + buffer_index = ul_buffer_index(sched_frame, sched_slot, slots_frame, nr_mac->UL_tti_req_ahead_size); + nfapi_nr_ul_tti_request_t *future_ul_tti_req = &nr_mac->UL_tti_req_ahead[CC_id][buffer_index]; + AssertFatal(future_ul_tti_req->SFN == sched_frame + && future_ul_tti_req->Slot == sched_slot, + "future UL_tti_req's frame.slot %d.%d does not match PUSCH %d.%d\n", + future_ul_tti_req->SFN, + future_ul_tti_req->Slot, + sched_frame, + sched_slot); + AssertFatal(future_ul_tti_req->n_pdus < + sizeof(future_ul_tti_req->pdus_list) / sizeof(future_ul_tti_req->pdus_list[0]), + "Invalid future_ul_tti_req->n_pdus %d\n", future_ul_tti_req->n_pdus); + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE; + future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t); + nfapi_nr_pusch_pdu_t *pusch_pdu = prepare_pusch_pdu(future_ul_tti_req, + UE, + scc, + &sched_pusch, + get_transformPrecoding(ul_bwp, NR_UL_DCI_FORMAT_0_0, 0), + 0, + ra->msg3_round, + ul_bwp->pusch_Config && ul_bwp->pusch_Config->frequencyHopping, + UE->rnti, + nr_mac->beam_info.beam_mode); + future_ul_tti_req->n_pdus += 1; + + // generation of DCI 0_0 to schedule msg3 retransmission + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = nr_mac->pdcch_pdu_idx[CC_id][coresetid]; + if (!pdcch_pdu_rel15) { + nfapi_nr_ul_dci_request_pdus_t *ul_dci_request_pdu = &ul_dci_req->ul_dci_pdu_list[ul_dci_req->numPdus]; + memset(ul_dci_request_pdu, 0, sizeof(nfapi_nr_ul_dci_request_pdus_t)); + ul_dci_request_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE; + ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); + pdcch_pdu_rel15 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; + ul_dci_req->numPdus += 1; + nr_configure_pdcch(pdcch_pdu_rel15, coreset, &UE->UE_sched_ctrl.sched_pdcch); + nr_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu_rel15; + } + + int aggregation_level; + int CCEIndex = get_cce_index(nr_mac, + CC_id, slot, 0, + &aggregation_level, + beam_dci.idx, + ss, + coreset, + &UE->UE_sched_ctrl.sched_pdcch, + 0); + if (CCEIndex < 0) { + LOG_E(NR_MAC, "UE %04x cannot find free CCE!\n", UE->rnti); + reset_beam_status(&nr_mac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_frame, beam_ul.new_beam); + reset_beam_status(&nr_mac->beam_info, frame, slot, UE->UE_beam_index, slots_frame, beam_dci.new_beam); + return; + } + + // Fill PDCCH DL DCI PDU + const uint16_t fapi_beam = convert_to_fapi_beam(UE->UE_beam_index, nr_mac->beam_info.beam_mode); + nfapi_nr_dl_dci_pdu_t *dci_pdu = + prepare_dci_pdu(pdcch_pdu_rel15, scc, ss, coreset, aggregation_level, CCEIndex, fapi_beam, UE->rnti); + pdcch_pdu_rel15->numDlDci++; + + dci_pdu_rel15_t uldci_payload = {0}; + config_uldci(sc_info, + pusch_pdu, + &uldci_payload, + NULL, + NULL, + ra->Msg3_tda_id, + ra->msg3_TPC, + 1, // Not toggling NDI in msg3 retransmissions + ul_bwp, + ss->searchSpaceType->present); + + // Reset TPC to 0 dB to not request new gain multiple times before computing new value for SNR + ra->msg3_TPC = 1; + + fill_dci_pdu_rel15(sc_info, + &UE->current_DL_BWP, + ul_bwp, + dci_pdu, + &uldci_payload, + NR_UL_DCI_FORMAT_0_0, + TYPE_TC_RNTI_, + ss, + coreset, + 0, // parameter not needed for DCI 0_0 + nr_mac->cset0_bwp_size); + + // Mark the corresponding RBs as used + fill_pdcch_vrb_map(nr_mac, + CC_id, + &UE->UE_sched_ctrl.sched_pdcch, + CCEIndex, + aggregation_level, + beam_dci.idx); + + for (int rb = 0; rb < ra->msg3_nb_rb; rb++) { + vrb_map_UL[rbStart + sched_pusch.bwp_info.bwpStart + rb] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); + } + + // Restart RA contention resolution timer in Msg3 retransmission slot (current slot + K2) + // 3GPP TS 38.321 Section 5.1.5 Contention Resolution + start_ra_contention_resolution_timer( + ra, + scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer, + K2, + ul_bwp->scs); + + // reset state to wait msg3 + ra->ra_state = nrRA_WAIT_Msg3; + ra->Msg3_frame = sched_frame; + ra->Msg3_slot = sched_slot; } static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc, From bcfa68347fd9aeedd71884713d08af05d17665b4 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 22 Dec 2025 17:48:12 +0100 Subject: [PATCH 15/15] fix bug in selecting MSG3 re-transmission slot --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 1 + openair2/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c | 9 +++++++++ openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 6 +++++- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 8 +------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 1 - 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 51bd9aa948..12b444539f 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -114,6 +114,7 @@ int16_t fill_dmrs_mask(const NR_PDSCH_Config_t *pdsch_Config, mappingType_t mappingtype, int length); int get_slots_per_frame_from_scs(int scs); +uint16_t get_ul_bitmap(const frame_structure_t *fs, int slot); bool is_ul_slot(const slot_t slot, const frame_structure_t *fs); bool is_dl_slot(const slot_t slot, const frame_structure_t *fs); bool is_mixed_slot(const slot_t slot, const frame_structure_t *fs); diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c index 922a0153d9..1636cbe436 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common_tdd.c @@ -24,6 +24,15 @@ #include "common/utils/nr/nr_common.h" #include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h" +uint16_t get_ul_bitmap(const frame_structure_t *fs, int slot) +{ + const int slot_period = slot % fs->numb_slots_period; + const tdd_bitmap_t *bm = &fs->period_cfg.tdd_slot_bitmap[slot_period]; + /* For some reason, we only store the number of symbols if it's mixed */ + const int num_ul_symbols = bm->slot_type == TDD_NR_MIXED_SLOT ? bm->num_ul_symbols : 14; + return SL_to_bitmap(14 - num_ul_symbols, num_ul_symbols); +} + int get_slots_per_frame_from_scs(int scs) { const int nr_slots_per_frame[5] = {10, 20, 40, 80, 160}; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index d23e95f5ae..b3b3b38b60 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -812,8 +812,12 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, uint16_t K2 = tda_info.k2 + get_NTN_Koffset(scc); const int sched_frame = (frame + (slot + K2) / slots_frame) % MAX_FRAME_NUMBER; const int sched_slot = (slot + K2) % slots_frame; + uint16_t slot_bitmap = get_ul_bitmap(&nr_mac->frame_structure, sched_slot); + uint16_t msg3_mask = SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); - if (!is_dl_slot(slot, &nr_mac->frame_structure) || !is_ul_slot(sched_slot, &nr_mac->frame_structure)) + if (!is_dl_slot(slot, &nr_mac->frame_structure) + || !is_ul_slot(sched_slot, &nr_mac->frame_structure) + || !((msg3_mask & slot_bitmap) == msg3_mask)) return; NR_beam_alloc_t beam_ul = beam_allocation_procedure(&nr_mac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_frame); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 92b9221054..3282c4a483 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -46,13 +46,7 @@ int get_num_ul_tda(gNB_MAC_INST *nrmac, int slot, int k2, const NR_tda_info_t ** /* we assume that this function is mutex-protected from outside */ NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); - const frame_structure_t *fs = &nrmac->frame_structure; - const int slot_period = slot % fs->numb_slots_period; - const tdd_bitmap_t *bm = &fs->period_cfg.tdd_slot_bitmap[slot_period]; - /* For some reason, we only store the number of symbols if it's mixed */ - const int num_ul_symbols = bm->slot_type == TDD_NR_MIXED_SLOT ? bm->num_ul_symbols : 14; - const uint16_t ul_bitmap = SL_to_bitmap(14 - num_ul_symbols, num_ul_symbols); - + const uint16_t ul_bitmap = get_ul_bitmap(&nrmac->frame_structure, slot); *first_idx = NULL; FOR_EACH_SEQ_ARR(NR_tda_info_t *, tda, &nrmac->ul_tda) { DevAssert(tda->valid_tda); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 239c63b18f..efcabbc98a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -48,7 +48,6 @@ int get_dl_slots_per_period(const frame_structure_t *fs); int get_full_ul_slots_per_period(const frame_structure_t *fs); int get_full_dl_slots_per_period(const frame_structure_t *fs); int get_ul_slot_offset(const frame_structure_t *fs, int idx, bool count_mixed); - void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_allocator_t *uia); void mac_top_init_gNB(ngran_node_t node_type,