diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 8df27ad16e..2607d8f587 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -66,6 +66,11 @@ typedef struct { uint64_t s_map; } nr_prach_info_t; +typedef struct { + uint16_t bwpStart; + uint16_t bwpSize; +} bwp_info_t; + uint32_t get_Y(const NR_SearchSpace_t *ss, int slot, rnti_t rnti); uint8_t get_BG(uint32_t A, uint16_t R); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index e1e9bfd982..63700d2a72 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -935,7 +935,8 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, ra->Msg3_tda_id, ra->msg3_TPC, 1, // Not toggling NDI in msg3 retransmissions - ul_bwp); + 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; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 226fe80dbb..4086588660 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -381,35 +381,39 @@ void abort_nr_dl_harq(NR_UE_info_t* UE, int8_t harq_pid) UE->mac_stats.dl.errors++; } -typedef struct { - int bwpStart; - int bwpSize; -} dl_bwp_info_t; - -static dl_bwp_info_t get_bwp_start_size(gNB_MAC_INST *mac, NR_UE_info_t *UE) +static bwp_info_t get_pdsch_bwp_start_size(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) { NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - // UE is scheduled in a set of contiguously allocated resource blocks within the active bandwidth part of size N_BWP PRBs - // except for the case when DCI format 1_0 is decoded in any common search space - // in which case the size of CORESET 0 shall be used if CORESET 0 is configured for the cell - // and the size of initial DL bandwidth part shall be used if CORESET 0 is not configured for the cell. - // TS 38.214 Section 5.1.2.2.2 - dl_bwp_info_t bwp_info; - bwp_info.bwpSize = dl_bwp->BWPSize; - bwp_info.bwpStart = dl_bwp->BWPStart; - if (sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common && - dl_bwp->dci_format == NR_DL_DCI_FORMAT_1_0) { - if (mac->cset0_bwp_size != 0) { - bwp_info.bwpStart = mac->cset0_bwp_start; - bwp_info.bwpSize = mac->cset0_bwp_size; + bwp_info_t bwp_info; + + // 3GPP TS 38.214 Section 5.1.2.2 Resource allocation in frequency domain + // For a PDSCH scheduled with a DCI format 1_0 in any type of PDCCH common search space, regardless of which bandwidth part is the + // active bandwidth part, RB numbering starts from the lowest RB of the CORESET in which the DCI was received; otherwise RB + // numbering starts from the lowest RB in the determined downlink bandwidth part. + // + // 3GPP TS 38.214 Section 5.1.2.2.2 Downlink resource allocation type 1 + // In downlink resource allocation of type 1, the resource block assignment information indicates to a scheduled UE a set of + // contiguously allocated non-interleaved or interleaved virtual resource blocks within the active bandwidth part of size PRBs + // except for the case when DCI format 1_0 is decoded in any common search space in which case the size of CORESET 0 shall be + // used if CORESET 0 is configured for the cell and the size of initial DL bandwidth part shall be used if CORESET 0 is not + // configured for the cell. + if (dl_bwp->dci_format == NR_DL_DCI_FORMAT_1_0 && sched_ctrl->search_space->searchSpaceType + && sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common + && dl_bwp->pdsch_Config->resourceAllocation == NR_PDSCH_Config__resourceAllocation_resourceAllocationType1) { + 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; } - else { - // TODO this is not entirely correct - // start would be the start of CORESET not of the initial BWP - bwp_info.bwpStart = UE->sc_info.initial_dl_BWPStart; - bwp_info.bwpSize = UE->sc_info.initial_dl_BWPSize; + if (nr_mac->cset0_bwp_size > 0) { + bwp_info.bwpSize = min(dl_bwp->BWPSize - bwp_info.bwpStart, nr_mac->cset0_bwp_size); + } else { + bwp_info.bwpSize = min(dl_bwp->BWPSize - bwp_info.bwpStart, UE->sc_info.initial_dl_BWPSize); } + } else { + bwp_info.bwpSize = dl_bwp->BWPSize; + bwp_info.bwpStart = dl_bwp->BWPStart; } return bwp_info; } @@ -463,7 +467,7 @@ static bool allocate_dl_retransmission(module_id_t module_id, uint16_t *rballoc_mask = nr_mac->common_channels[CC_id].vrb_map[beam_idx]; - dl_bwp_info_t bwp_info = get_bwp_start_size(nr_mac, UE); + bwp_info_t bwp_info = get_pdsch_bwp_start_size(nr_mac, UE); int rbStart = bwp_info.bwpStart; int rbStop = bwp_info.bwpStart + bwp_info.bwpSize - 1; int rbSize = 0; @@ -758,7 +762,7 @@ static void pf_dl(module_id_t module_id, const uint16_t slbitmap = SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols); uint16_t *rballoc_mask = mac->common_channels[CC_id].vrb_map[beam.idx]; - dl_bwp_info_t bwp_info = get_bwp_start_size(mac, iterator->UE); + bwp_info_t bwp_info = get_pdsch_bwp_start_size(mac, iterator->UE); int rbStart = 0; // WRT BWP start int rbStop = bwp_info.bwpSize - 1; int bwp_start = bwp_info.bwpStart; @@ -1060,7 +1064,7 @@ void nr_schedule_ue_spec(module_id_t module_id, const int pduindex = gNB_mac->pdu_index[CC_id]++; pdsch_pdu->pduIndex = pduindex; - dl_bwp_info_t bwp_info = get_bwp_start_size(gNB_mac, UE); + bwp_info_t bwp_info = get_pdsch_bwp_start_size(gNB_mac, UE); pdsch_pdu->BWPSize = bwp_info.bwpSize; pdsch_pdu->BWPStart = bwp_info.bwpStart; @@ -1176,9 +1180,20 @@ void nr_schedule_ue_spec(module_id_t module_id, AssertFatal(pdsch_Config == NULL || pdsch_Config->resourceAllocation == NR_PDSCH_Config__resourceAllocation_resourceAllocationType1, "Only frequency resource allocation type 1 is currently supported\n"); - dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu->rbSize, - pdsch_pdu->rbStart, - pdsch_pdu->BWPSize); + // 3GPP TS 38.214 Section 5.1.2.2.2 Downlink resource allocation type 1 + uint16_t riv_bwp_size = pdsch_pdu->BWPSize; + if (current_BWP->dci_format == NR_DL_DCI_FORMAT_1_0 + && sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common + && pdsch_Config->resourceAllocation == NR_PDSCH_Config__resourceAllocation_resourceAllocationType1) { + if (gNB_mac->cset0_bwp_size > 0) { + riv_bwp_size = gNB_mac->cset0_bwp_size; + } else { + riv_bwp_size = UE->sc_info.initial_dl_BWPSize; + } + } + dci_payload.frequency_domain_assignment.val = + PRBalloc_to_locationandbandwidth0(pdsch_pdu->rbSize, pdsch_pdu->rbStart, riv_bwp_size); + dci_payload.format_indicator = 1; dci_payload.time_domain_assignment.val = sched_pdsch->time_domain_allocation; dci_payload.mcs = sched_pdsch->mcs; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 5c4ee88a06..5ceff85296 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -497,13 +497,21 @@ NR_sched_pdcch_t set_pdcch_structure(gNB_MAC_INST *gNB_mac, pdcch.ShiftIndex = 0; } - int N_rb = 0; // nb of rbs of coreset per symbol - for (int i=0;i<6;i++) { - for (int t=0;t<8;t++) { - N_rb+=((coreset->frequencyDomainResources.buf[i]>>t)&1); + uint16_t N_rb = 0; // nb of rbs of coreset per symbol + uint16_t rb_start = 0; + for (int i = 0; i < 6; i++) { + for (int t = 0; t < 8; t++) { + if (coreset->frequencyDomainResources.buf[i] >> (7 - t) & 1) { + if (N_rb == 0) { + rb_start = 48 * i + t * 6; + } + N_rb++; + } } } - pdcch.n_rb = N_rb*=6; // each bit of frequencyDomainResources represents 6 PRBs + + pdcch.rb_start = rb_start; + pdcch.n_rb = N_rb *= 6; // each bit of frequencyDomainResources represents 6 PRBs return pdcch; } @@ -782,13 +790,20 @@ void config_uldci(const NR_UE_ServingCell_Info_t *sc_info, int time_domain_assignment, uint8_t tpc, uint8_t ndi, - NR_UE_UL_BWP_t *ul_bwp) + NR_UE_UL_BWP_t *ul_bwp, + NR_SearchSpace__searchSpaceType_PR ss_type) { int bwp_id = ul_bwp->bwp_id; nr_dci_format_t dci_format = ul_bwp->dci_format; + // 3GPP TS 38.214 Section 6.1.2.2.2 Uplink resource allocation type 1 + uint16_t riv_bwp_size = ul_bwp->BWPSize; + if (dci_format == NR_UL_DCI_FORMAT_0_0 && ss_type == NR_SearchSpace__searchSpaceType_PR_common && ul_bwp->pusch_Config + && ul_bwp->pusch_Config->resourceAllocation == NR_PUSCH_Config__resourceAllocation_resourceAllocationType1) { + riv_bwp_size = sc_info->initial_ul_BWPSize; + } dci_pdu_rel15->frequency_domain_assignment.val = - PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, pusch_pdu->rb_start, ul_bwp->BWPSize); + PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, pusch_pdu->rb_start, riv_bwp_size); dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment; dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping; dci_pdu_rel15->mcs = pusch_pdu->mcs_index; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index c554dc7cea..35c817b975 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -65,6 +65,28 @@ int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot) return 0; // if FDD or not mixed slot in TDD, for now use default TDA (TODO handle CSI-RS slots) } +static bwp_info_t get_pusch_bwp_start_size(NR_UE_info_t *UE) +{ + NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + bwp_info_t bwp_info; + bwp_info.bwpStart = ul_bwp->BWPStart; + + // 3GPP TS 38.214 Section 6.1.2.2.2 Uplink resource allocation type 1 + // In uplink resource allocation of type 1, the resource block assignment information indicates to a scheduled UE a set of + // contiguously allocated non-interleaved virtual resource blocks within the active bandwidth part of size PRBs except for the + // case when DCI format 0_0 is decoded in any common search space in which case the size of the initial UL bandwidth part shall + // be used. + if (ul_bwp->dci_format == NR_UL_DCI_FORMAT_0_0 && sched_ctrl->search_space->searchSpaceType + && sched_ctrl->search_space->searchSpaceType->present == NR_SearchSpace__searchSpaceType_PR_common + && ul_bwp->pusch_Config->resourceAllocation == NR_PUSCH_Config__resourceAllocation_resourceAllocationType1) { + bwp_info.bwpSize = min(ul_bwp->BWPSize, UE->sc_info.initial_ul_BWPSize); + } else { + bwp_info.bwpSize = ul_bwp->BWPSize; + } + return bwp_info; +} + static int compute_ph_factor(int mu, int tbs_bits, int rb, int n_layers, int n_symbols, int n_dmrs, long *deltaMCS, bool include_bw) { // 38.213 7.1.1 @@ -1673,8 +1695,9 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; int rbStart = 0; // wrt BWP start - const uint32_t bwpSize = ul_bwp->BWPSize; - const uint32_t bwpStart = ul_bwp->BWPStart; + bwp_info_t bwp_info = get_pusch_bwp_start_size(UE); + const uint32_t bwpSize = bwp_info.bwpSize; + const uint32_t bwpStart = bwp_info.bwpStart; const uint8_t nrOfLayers = retInfo->nrOfLayers; LOG_D(NR_MAC,"retInfo->time_domain_allocation = %d, tda = %d\n", retInfo->time_domain_allocation, tda); LOG_D(NR_MAC,"tbs %d\n",retInfo->tb_size); @@ -1963,8 +1986,9 @@ static void pf_ul(module_id_t module_id, min_rb, rbStart, sched_pusch->dmrs_info.num_dmrs_cdm_grps_no_data); - const uint32_t bwpSize = current_BWP->BWPSize; - const uint32_t bwpStart = current_BWP->BWPStart; + bwp_info_t bwp_info = get_pusch_bwp_start_size(UE); + const uint32_t bwpStart = bwp_info.bwpStart; + const uint32_t bwpSize = bwp_info.bwpSize; const uint16_t slbitmap = SL_to_bitmap(sched_pusch->tda_info.startSymbolIndex, sched_pusch->tda_info.nrOfSymbols); while (rbStart < bwpSize && (rballoc_mask[rbStart + bwpStart] & slbitmap)) rbStart++; @@ -2112,8 +2136,9 @@ static void pf_ul(module_id_t module_id, int rbStart = 0; const uint16_t slbitmap = SL_to_bitmap(sched_pusch->tda_info.startSymbolIndex, sched_pusch->tda_info.nrOfSymbols); - const uint32_t bwpSize = current_BWP->BWPSize; - const uint32_t bwpStart = current_BWP->BWPStart; + bwp_info_t bwp_info = get_pusch_bwp_start_size(iterator->UE); + const uint32_t bwpStart = bwp_info.bwpStart; + const uint32_t bwpSize = bwp_info.bwpSize; while (rbStart < bwpSize && (rballoc_mask[rbStart + bwpStart] & slbitmap)) rbStart++; sched_pusch->rbStart = rbStart; @@ -2662,7 +2687,8 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_ sched_pusch->time_domain_allocation, UE->UE_sched_ctrl.tpc0, cur_harq->ndi, - current_BWP); + current_BWP, + ss->searchSpaceType->present); // Reset TPC to 0 dB to not request new gain multiple times before computing new value for SNR UE->UE_sched_ctrl.tpc0 = 1; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index c78c061820..f0b59c73de 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -166,7 +166,8 @@ void config_uldci(const NR_UE_ServingCell_Info_t *sc_info, int time_domain_assignment, uint8_t tpc, uint8_t ndi, - NR_UE_UL_BWP_t *ul_bwp); + NR_UE_UL_BWP_t *ul_bwp, + NR_SearchSpace__searchSpaceType_PR ss_type); void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, slot_t slotP); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 1e7ac572ef..0b977de276 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -198,7 +198,8 @@ typedef struct NR_sched_pdcch { uint8_t InterleaverSize; uint16_t ShiftIndex; uint8_t DurationSymbols; - int n_rb; + uint16_t n_rb; + uint16_t rb_start; } NR_sched_pdcch_t; /*! \brief gNB template for the Random access information */