diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf index 58ba62696a..e314a1f299 100644 --- a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf +++ b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf @@ -149,7 +149,7 @@ gNBs = bwp_list = ( { scs = 1; bwpStart = 0; bwpSize = 106;}, { scs = 1; bwpStart = 0; bwpSize = 36;}, - { scs = 1; bwpStart = 36; bwpSize = 70;} + { scs = 1; bwpStart = 40; bwpSize = 50;} ); # ------- SCTP definitions diff --git a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml index 836143431a..d0a65801a3 100644 --- a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml @@ -183,7 +183,7 @@ -t 10 -R idefix sabox-nepes - 85 + 65 diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 6b4648f572..dd6b8135ab 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -73,6 +73,7 @@ typedef struct { typedef struct { /// frequency_domain_resource; uint8_t frequency_domain_resource[6]; + uint32_t rb_offset; uint8_t StartSymbolIndex; uint16_t StartSymbolBitmap; uint8_t duration; diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index 28d22b31bb..12bff45dee 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -61,9 +61,13 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, int reg_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE]; nr_fill_reg_list(reg_list, pdcch_pdu_rel15); // compute rb_offset and n_prb based on frequency allocation - int rb_offset; - int n_rb; - get_coreset_rballoc(pdcch_pdu_rel15->FreqDomainResource,&n_rb,&rb_offset); + int n_rb, cset_start; + get_coreset_rballoc(pdcch_pdu_rel15->FreqDomainResource, &n_rb, &cset_start); + int additional_offset = 0; + // first common RB of the first group of 6 PRBs has common RB index equal to 6 * ⌈BWP_start / 6⌉ + if (pdcch_pdu_rel15->CoreSetType == 1) + additional_offset = (pdcch_pdu_rel15->BWPStart + 5) / 6 * 6 - pdcch_pdu_rel15->BWPStart; + int rb_offset = cset_start + additional_offset; uint16_t cset_start_sc = frame_parms->first_carrier_offset + (pdcch_pdu_rel15->BWPStart + rb_offset) * NR_NB_SC_PER_RB; int idx1 = pdcch_pdu_rel15->StartSymbolIndex+pdcch_pdu_rel15->DurationSymbols; int idx2 = (((n_rb + rb_offset + pdcch_pdu_rel15->BWPStart) * 3) + 15) & ~15; @@ -194,7 +198,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB, // dmrs index depends on reference point for k according to 38.211 7.4.1.3.2 int dmrs_idx; if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) - dmrs_idx = (reg_list[d][reg_count] + pdcch_pdu_rel15->BWPStart) * 3; + dmrs_idx = (reg_list[d][reg_count] + pdcch_pdu_rel15->BWPStart + rb_offset) * 3; else dmrs_idx = (reg_list[d][reg_count] + rb_offset) * 3; diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index f4ab076921..822389ebdc 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -204,6 +204,7 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, c16_t dl_ch_estimates_ext[][arraySz], NR_DL_FRAME_PARMS *frame_parms, uint8_t *coreset_freq_dom, + uint32_t rb_offset, uint32_t coreset_nbr_rb, uint32_t n_BWP_start) { @@ -250,7 +251,7 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz, continue; } for (int rb = 0; rb < 6; rb++) { - int c_rb = rb_group * 6 + rb; + int c_rb = rb_group * 6 + rb + rb_offset; c16_t *rxF = NULL; if ((frame_parms->N_RB_DL & 1) == 0) { if ((c_rb + n_BWP_start) < frame_parms->N_RB_DL / 2) @@ -338,10 +339,9 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue, fapi_nr_coreset_t *coreset = &phy_pdcch_config->pdcch_config[ss_idx].coreset; int32_t pdcch_est_size = ceil_mod(fp->ofdm_symbol_size + LTE_CE_FILTER_LENGTH, 16); __attribute__((aligned(16))) c16_t pdcch_dl_ch_estimates[fp->nb_antennas_rx][pdcch_est_size]; - int n_rb; - int rb_offset; - get_coreset_rballoc(coreset->frequency_domain_resource, &n_rb, &rb_offset); - + int n_rb, cset_start; + get_coreset_rballoc(coreset->frequency_domain_resource, &n_rb, &cset_start); + int rb_offset = cset_start + coreset->rb_offset; unsigned short scrambling_id = coreset->pdcch_dmrs_scrambling_id; int dmrs_ref = 0; if (coreset->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG) @@ -376,6 +376,7 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue, pdcch_dl_ch_estimates_ext, fp, coreset->frequency_domain_resource, + coreset->rb_offset, n_rb, phy_pdcch_config->pdcch_config[ss_idx].BWPStart); @@ -509,10 +510,8 @@ void nr_pdcch_dci_indication(const UE_nr_rxtx_proc_t *proc, uint8_t unused_start_symb[NR_SYMBOLS_PER_SLOT] = {0}; const int num_monitoring_occ = get_pdcch_mon_occasions_slot(rel15, unused_start_symb); const int llr_stride = llr_size / rel15->coreset.duration; - - int n_rb; - int rb_offset; - get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &rb_offset); + int n_rb, cset_start; + get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &cset_start); for (int m = 0; m < num_monitoring_occ; m++) { /// PDCCH/DCI e-sequence (input to rate matching). @@ -643,9 +642,9 @@ static void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue, .ss_type = rel15->ss_type_options[k], .coreset_type = rel15->coreset.CoreSetType, }; - int n_rb, rb_offset; - get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &rb_offset); - dci->cset_start = rel15->BWPStart + rb_offset; + int n_rb, cset_start; + get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &cset_start); + dci->cset_start = rel15->BWPStart + cset_start + rel15->coreset.rb_offset; dci->payloadSize = dci_length; memcpy(dci->payloadBits, dci_estimation, (dci_length + 7) / 8); dci_ind->number_of_dcis++; 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 1f84b11a48..af6bf37aff 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -122,9 +122,18 @@ static void config_dci_pdu(NR_UE_MAC_INST_t *mac, if(coreset_id > 0) { coreset = ue_get_coreset(pdcch_config, coreset_id); rel15->coreset.CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG; + if (coreset->ext1 && coreset->ext1->rb_Offset_r16) + rel15->coreset.rb_offset = *coreset->ext1->rb_Offset_r16; + else { + // first common RB of the first group of 6 PRBs has common RB index equal to + // 6 * ⌈BWP_start / 6⌉ if rb-Offset is not provided + int start_common = (current_DL_BWP->BWPStart + 5) / 6 * 6; + rel15->coreset.rb_offset = start_common - current_DL_BWP->BWPStart; + } } else { coreset = mac->coreset0; rel15->coreset.CoreSetType = NFAPI_NR_CSET_CONFIG_MIB_SIB1; + rel15->coreset.rb_offset = 0; } rel15->coreset.duration = coreset->duration; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 00c41953a1..43d36f0515 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -404,7 +404,8 @@ bwp_info_t get_pdsch_bwp_start_size(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) if (sched_ctrl->coreset->controlResourceSetId == 0) { bwp_info.bwpStart = nr_mac->cset0_bwp_start; } else { - bwp_info.bwpStart = dl_bwp->BWPStart + sched_ctrl->sched_pdcch.rb_start; + int additional_offset = (dl_bwp->BWPStart + 5) / 6 * 6 - dl_bwp->BWPStart; + bwp_info.bwpStart = dl_bwp->BWPStart + sched_ctrl->sched_pdcch.rb_start + additional_offset; } if (nr_mac->cset0_bwp_size > 0) { bwp_info.bwpSize = min(dl_bwp->BWPSize, nr_mac->cset0_bwp_size); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index f9a099d79b..97feb06b81 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -454,6 +454,7 @@ static NR_SearchSpace_t *get_searchspace(NR_ServingCellConfigCommon_t *scc, /// @param rb_start Output parameter for the starting resource block index of the CORESET static void get_coreset_rb_params(const NR_ControlResourceSet_t *coreset, uint16_t *n_rb, uint16_t *rb_start) { + AssertFatal(!coreset->ext1 || !coreset->ext1->rb_Offset_r16, "rb-Offset in coreset configuration not handled\n"); *n_rb = 0; *rb_start = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 72bc611e2c..538d244dd8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -273,21 +273,23 @@ NR_SearchSpace_t *rrc_searchspace_config(bool is_common, return ss; } -static NR_ControlResourceSet_t *get_coreset_config(int bwp_id, int curr_bwp, uint64_t ssb_bitmap) +static NR_ControlResourceSet_t *get_coreset_config(int bwp_id, 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 eff_bwp_size = bwp_size - additional_offset; coreset->frequencyDomainResources.buf = calloc(1,6); - coreset->frequencyDomainResources.buf[0] = (curr_bwp < 48) ? 0xf0 : 0xff; - coreset->frequencyDomainResources.buf[1] = (curr_bwp < 96) ? 0x00 : 0xff; - coreset->frequencyDomainResources.buf[2] = (curr_bwp < 144) ? 0x00 : 0xff; - coreset->frequencyDomainResources.buf[3] = (curr_bwp < 192) ? 0x00 : 0xff; - coreset->frequencyDomainResources.buf[4] = (curr_bwp < 240) ? 0x00 : 0xff; + 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; coreset->frequencyDomainResources.size = 6; coreset->frequencyDomainResources.bits_unused = 3; - coreset->duration = (curr_bwp < 48) ? 2 : 1; + coreset->duration = (eff_bwp_size < 48) ? 2 : 1; coreset->cce_REG_MappingType.present = NR_ControlResourceSet__cce_REG_MappingType_PR_nonInterleaved; coreset->precoderGranularity = NR_ControlResourceSet__precoderGranularity_sameAsREG_bundle; @@ -1746,10 +1748,10 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t bwp->bwp_Common->pdcch_ConfigCommon->choice.setup = calloc(1,sizeof(*bwp->bwp_Common->pdcch_ConfigCommon->choice.setup)); bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->controlResourceSetZero = NULL; - int curr_bwp = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,MAX_BWP_SIZE); - + 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, curr_bwp, ssb_bitmap); + NR_ControlResourceSet_t *coreset = get_coreset_config(bwp->bwp_Id, bwp_start, bwp_size, ssb_bitmap); bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonControlResourceSet = coreset; bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceZero=NULL; @@ -1790,7 +1792,7 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t nr_rrc_config_dl_tda(bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList, get_frame_type((int)*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing), scc->tdd_UL_DL_ConfigurationCommon, - curr_bwp); + bwp_size); if (!bwp->bwp_Dedicated) { bwp->bwp_Dedicated=calloc(1,sizeof(*bwp->bwp_Dedicated)); @@ -1803,7 +1805,7 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t // coreset2 is identical to coreset above, but reallocated to prevent double // frees - NR_ControlResourceSet_t *coreset2 = get_coreset_config(bwp->bwp_Id, curr_bwp, ssb_bitmap); + NR_ControlResourceSet_t *coreset2 = get_coreset_config(bwp->bwp_Id, 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); @@ -3332,8 +3334,9 @@ static NR_BWP_DownlinkDedicated_t *configure_initial_dl_bwp(const NR_ServingCell pdcch_Config->searchSpacesToAddModList = calloc(1, sizeof(*pdcch_Config->searchSpacesToAddModList)); pdcch_Config->controlResourceSetToAddModList = calloc(1, sizeof(*pdcch_Config->controlResourceSetToAddModList)); NR_BWP_t *genericParameters = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters; - int curr_bwp = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); - NR_ControlResourceSet_t *coreset = get_coreset_config(0, curr_bwp, bitmap); + 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); asn1cSeqAdd(&pdcch_Config->controlResourceSetToAddModList->list, coreset); int css_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS];