diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index f754c88040..b92b83425e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1644,6 +1644,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, sub_frame_t slot, uint16_t *rballoc_mask, int *n_rb_sched, + int dci_beam_idx, NR_UE_info_t* UE, int harq_pid, const NR_ServingCellConfigCommon_t *scc, @@ -1733,7 +1734,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, slot, UE->rnti, &sched_ctrl->aggregation_level, - 0, // TODO use beam index + dci_beam_idx, sched_ctrl->search_space, sched_ctrl->coreset, &sched_ctrl->sched_pdcch, @@ -1744,12 +1745,7 @@ static bool allocate_ul_retransmission(gNB_MAC_INST *nrmac, } sched_ctrl->cce_index = CCEIndex; - fill_pdcch_vrb_map(nrmac, - CC_id, - &sched_ctrl->sched_pdcch, - CCEIndex, - sched_ctrl->aggregation_level, - 0); // TODO use beam index when implemented + fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam_idx); retInfo->frame = (frame + (slot + tda_info.k2) / nr_slots_per_frame[ul_bwp->scs]) % MAX_FRAME_NUMBER; retInfo->slot = (slot + tda_info.k2) % nr_slots_per_frame[ul_bwp->scs]; @@ -1793,7 +1789,8 @@ static void pf_ul(module_id_t module_id, int sched_slot, NR_UE_info_t *UE_list[], int max_num_ue, - int n_rb_sched) + int num_beams, + int n_rb_sched[num_beams]) { const int CC_id = 0; gNB_MAC_INST *nrmac = RC.nrmac[module_id]; @@ -1802,7 +1799,9 @@ static void pf_ul(module_id_t module_id, const int min_rb = nrmac->min_grant_prb; // UEs that could be scheduled UEsched_t UE_sched[MAX_MOBILES_PER_GNB + 1] = {0}; - int remainUEs = max_num_ue; + int remainUEs[num_beams]; + for (int i = 0; i < num_beams; i++) + remainUEs[i] = max_num_ue; int curUE = 0; /* Loop UE_list to calculate throughput and coeff */ @@ -1823,42 +1822,66 @@ static void pf_ul(module_id_t module_id, const uint32_t b = stats->current_bytes; UE->ul_thr_ue = (1 - a) * UE->ul_thr_ue + a * b; - if(remainUEs == 0) + int total_rem_ues = 0; + for (int i = 0; i < num_beams; i++) + total_rem_ues += remainUEs[i]; + if (total_rem_ues == 0) continue; + int n_dl = nr_slots_per_frame[UE->current_DL_BWP.scs]; + NR_beam_alloc_t dci_beam = beam_allocation_procedure(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl); + if (dci_beam.idx < 0) { + LOG_D(NR_MAC, "[UE %04x][%4d.%2d] Beam could not be allocated\n", UE->rnti, frame, slot); + continue; + } + + int n = nr_slots_per_frame[current_BWP->scs]; + NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, UE->UE_beam_index, n); + if (beam.idx < 0) { + LOG_D(NR_MAC, "[UE %04x][%4d.%2d] Beam could not be allocated\n", UE->rnti, frame, slot); + reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl, dci_beam.new_beam); + continue; + } const int index = ul_buffer_index(sched_frame, sched_slot, current_BWP->scs, nrmac->vrb_map_UL_size); - // TODO improve handling of beam in vrb_map (for now just using 0) - uint16_t *rballoc_mask = &nrmac->common_channels[CC_id].vrb_map_UL[0][index * MAX_BWP_SIZE]; + uint16_t *rballoc_mask = &nrmac->common_channels[CC_id].vrb_map_UL[beam.idx][index * MAX_BWP_SIZE]; /* Check if retransmission is necessary */ sched_pusch->ul_harq_pid = sched_ctrl->retrans_ul_harq.head; - LOG_D(NR_MAC,"pf_ul: UE %04x harq_pid %d\n",UE->rnti,sched_pusch->ul_harq_pid); + LOG_D(NR_MAC,"pf_ul: UE %04x harq_pid %d\n", UE->rnti, sched_pusch->ul_harq_pid); if (sched_pusch->ul_harq_pid >= 0) { /* Allocate retransmission*/ const int tda = get_ul_tda(nrmac, scc, sched_frame, sched_slot); - bool r = allocate_ul_retransmission(nrmac, frame, slot, rballoc_mask, &n_rb_sched, UE, sched_pusch->ul_harq_pid, scc, tda); + bool r = allocate_ul_retransmission(nrmac, + frame, + slot, + rballoc_mask, + &n_rb_sched[beam.idx], + dci_beam.idx, + UE, + sched_pusch->ul_harq_pid, + scc, + tda); if (!r) { - LOG_D(NR_MAC, "[UE %04x][%4d.%2d] UL retransmission could not be allocated\n", - UE->rnti, - frame, - slot); + LOG_D(NR_MAC, "[UE %04x][%4d.%2d] UL retransmission could not be allocated\n", UE->rnti, frame, slot); + reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, UE->UE_beam_index, n, beam.new_beam); + reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl, dci_beam.new_beam); continue; } - else LOG_D(NR_MAC,"%4d.%2d UL Retransmission UE RNTI %04x to be allocated, max_num_ue %d\n",frame,slot,UE->rnti,max_num_ue); + else + LOG_D(NR_MAC,"%4d.%2d UL Retransmission UE RNTI %04x to be allocated, max_num_ue %d\n", frame, slot, UE->rnti,max_num_ue); /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */ - remainUEs--; + remainUEs[beam.idx]--; continue; - } + } /* skip this UE if there are no free HARQ processes. This can happen e.g. * if the UE disconnected in L2sim, in which case the gNB is not notified * (this can be considered a design flaw) */ if (sched_ctrl->available_ul_harq.head < 0) { - LOG_D(NR_MAC, "[UE %04x][%4d.%2d] has no free UL HARQ process, skipping\n", - UE->rnti, - frame, - slot); + reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, UE->UE_beam_index, n, beam.new_beam); + reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl, dci_beam.new_beam); + LOG_D(NR_MAC, "[UE %04x][%4d.%2d] has no free UL HARQ process, skipping\n", UE->rnti, frame, slot); continue; } @@ -1866,8 +1889,10 @@ static void pf_ul(module_id_t module_id, /* preprocessor computed sched_frame/sched_slot */ const bool do_sched = nr_UE_is_to_be_scheduled(scc, 0, UE, sched_frame, sched_slot, nrmac->ulsch_max_frame_inactivity); - LOG_D(NR_MAC,"pf_ul: do_sched UE %04x => %s\n",UE->rnti,do_sched ? "yes" : "no"); + LOG_D(NR_MAC,"pf_ul: do_sched UE %04x => %s\n", UE->rnti, do_sched ? "yes" : "no"); if ((B == 0 && !do_sched) || nr_timer_is_active(&sched_ctrl->transm_interrupt)) { + reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, UE->UE_beam_index, n, beam.new_beam); + reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl, dci_beam.new_beam); continue; } @@ -1879,7 +1904,7 @@ static void pf_ul(module_id_t module_id, sched_ctrl->ul_bler_stats.mcs = sched_pusch->mcs; } else { sched_pusch->mcs = get_mcs_from_bler(bo, stats, &sched_ctrl->ul_bler_stats, max_mcs, frame); - LOG_D(NR_MAC,"%d.%d starting mcs %d bleri %f\n",frame,slot,sched_pusch->mcs,sched_ctrl->ul_bler_stats.bler); + LOG_D(NR_MAC,"%d.%d starting mcs %d bleri %f\n", frame, slot, sched_pusch->mcs, sched_ctrl->ul_bler_stats.bler); } /* Schedule UE on SR or UL inactivity and no data (otherwise, will be scheduled * based on data to transmit) */ @@ -1889,16 +1914,15 @@ static void pf_ul(module_id_t module_id, int CCEIndex = get_cce_index(nrmac, CC_id, slot, UE->rnti, &sched_ctrl->aggregation_level, - 0, // TODO use beam index + dci_beam.idx, sched_ctrl->search_space, sched_ctrl->coreset, &sched_ctrl->sched_pdcch, false); - if (CCEIndex<0) { - LOG_D(NR_MAC, "[UE %04x][%4d.%2d] no free CCE for UL DCI (BSR 0)\n", - UE->rnti, - frame, - slot); + if (CCEIndex < 0) { + LOG_D(NR_MAC, "[UE %04x][%4d.%2d] no free CCE for UL DCI (BSR 0)\n", UE->rnti, frame, slot); + reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, UE->UE_beam_index, n, beam.new_beam); + reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl, dci_beam.new_beam); continue; } @@ -1910,10 +1934,7 @@ static void pf_ul(module_id_t module_id, TYPE_C_RNTI_, sched_pusch->time_domain_allocation); AssertFatal(sched_pusch->tda_info.valid_tda, "Invalid TDA from get_ul_tda_info\n"); - sched_pusch->dmrs_info = get_ul_dmrs_params(scc, - current_BWP, - &sched_pusch->tda_info, - sched_pusch->nrOfLayers); + sched_pusch->dmrs_info = get_ul_dmrs_params(scc, current_BWP, &sched_pusch->tda_info, sched_pusch->nrOfLayers); int rbStart = 0; // wrt BWP start LOG_D(NR_MAC, @@ -1935,11 +1956,13 @@ static void pf_ul(module_id_t module_id, rbStart, min_rb, bwpSize); + reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, UE->UE_beam_index, n, beam.new_beam); + reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl, dci_beam.new_beam); continue; } sched_ctrl->cce_index = CCEIndex; - fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, 0); // TODO use beam index + fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam.idx); NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; sched_pusch->mcs = min(nrmac->min_grant_mcs, sched_pusch->mcs); @@ -1977,11 +2000,11 @@ static void pf_ul(module_id_t module_id, sched_pusch->phr_txpower_calc); /* Mark the corresponding RBs as used */ - n_rb_sched -= sched_pusch->rbSize; + n_rb_sched[beam.idx] -= sched_pusch->rbSize; for (int rb = bwpStart; rb < sched_ctrl->sched_pusch.rbSize; rb++) rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] |= slbitmap; - remainUEs--; + remainUEs[beam.idx]--; continue; } @@ -2006,31 +2029,59 @@ static void pf_ul(module_id_t module_id, UEsched_t *iterator=UE_sched; /* Loop UE_sched to find max coeff and allocate transmission */ - while (remainUEs > 0 && n_rb_sched >= min_rb && iterator->UE != NULL) { - + while (iterator->UE != NULL) { + NR_UE_UL_BWP_t *current_BWP = &iterator->UE->current_UL_BWP; + NR_UE_DL_BWP_t *dl_BWP = &iterator->UE->current_DL_BWP; NR_UE_sched_ctrl_t *sched_ctrl = &iterator->UE->UE_sched_ctrl; + NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; + + int n = nr_slots_per_frame[current_BWP->scs]; + NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, + sched_pusch->frame, + sched_pusch->slot, + iterator->UE->UE_beam_index, + n); + if (beam.idx < 0) { + LOG_D(NR_MAC, "[UE %04x][%4d.%2d] Beam could not be allocated\n", iterator->UE->rnti, frame, slot); + iterator++; + continue; + } + + if (remainUEs[beam.idx] == 0 || n_rb_sched[beam.idx] < min_rb) { + reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, iterator->UE->UE_beam_index, n, beam.new_beam); + iterator++; + continue; + } + + int n_dl = nr_slots_per_frame[dl_BWP->scs]; + NR_beam_alloc_t dci_beam = beam_allocation_procedure(&nrmac->beam_info, frame, slot, iterator->UE->UE_beam_index, n_dl); + if (dci_beam.idx < 0) { + LOG_D(NR_MAC, "[UE %04x][%4d.%2d] Beam could not be allocated\n", iterator->UE->rnti, frame, slot); + reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, iterator->UE->UE_beam_index, n, beam.new_beam); + iterator++; + continue; + } + int CCEIndex = get_cce_index(nrmac, CC_id, slot, iterator->UE->rnti, &sched_ctrl->aggregation_level, - 0, // TODO use beam index + dci_beam.idx, sched_ctrl->search_space, sched_ctrl->coreset, &sched_ctrl->sched_pdcch, false); - if (CCEIndex<0) { - LOG_D(NR_MAC, "[UE %04x][%4d.%2d] no free CCE for UL DCI\n", - iterator->UE->rnti, - frame, - slot); + if (CCEIndex < 0) { + reset_beam_status(&nrmac->beam_info, frame, slot, iterator->UE->UE_beam_index, n_dl, dci_beam.new_beam); + reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, iterator->UE->UE_beam_index, n, beam.new_beam); + LOG_D(NR_MAC, "[UE %04x][%4d.%2d] no free CCE for UL DCI\n", iterator->UE->rnti, frame, slot); iterator++; continue; } - else LOG_D(NR_MAC, "%4d.%2d free CCE for UL DCI UE %04x\n",frame,slot, iterator->UE->rnti); + else + LOG_D(NR_MAC, "%4d.%2d free CCE for UL DCI UE %04x\n", frame, slot, iterator->UE->rnti); - NR_UE_UL_BWP_t *current_BWP = &iterator->UE->current_UL_BWP; - NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; sched_pusch->nrOfLayers = sched_ctrl->srs_feedback.ul_ri + 1; sched_pusch->time_domain_allocation = get_ul_tda(nrmac, scc, sched_frame, sched_slot); @@ -2040,14 +2091,10 @@ static void pf_ul(module_id_t module_id, TYPE_C_RNTI_, sched_pusch->time_domain_allocation); AssertFatal(sched_pusch->tda_info.valid_tda, "Invalid TDA from get_ul_tda_info\n"); - sched_pusch->dmrs_info = get_ul_dmrs_params(scc, - current_BWP, - &sched_pusch->tda_info, - sched_pusch->nrOfLayers); + sched_pusch->dmrs_info = get_ul_dmrs_params(scc, current_BWP, &sched_pusch->tda_info, sched_pusch->nrOfLayers); const int index = ul_buffer_index(sched_frame, sched_slot, current_BWP->scs, nrmac->vrb_map_UL_size); - // TODO improve handling of beam in vrb_map (for now just using 0) - uint16_t *rballoc_mask = &nrmac->common_channels[CC_id].vrb_map_UL[0][index * MAX_BWP_SIZE]; + uint16_t *rballoc_mask = &nrmac->common_channels[CC_id].vrb_map_UL[beam.idx][index * MAX_BWP_SIZE]; int rbStart = 0; const uint16_t slbitmap = SL_to_bitmap(sched_pusch->tda_info.startSymbolIndex, sched_pusch->tda_info.nrOfSymbols); @@ -2061,6 +2108,8 @@ static void pf_ul(module_id_t module_id, max_rbSize++; if (rbStart + min_rb >= bwpSize || max_rbSize < min_rb) { + reset_beam_status(&nrmac->beam_info, frame, slot, iterator->UE->UE_beam_index, n_dl, dci_beam.new_beam); + reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, iterator->UE->UE_beam_index, n, beam.new_beam); LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not allocate UL data: no resources (rbStart %d, min_rb %d, bwpSize %d)\n", iterator->UE->rnti, frame, @@ -2135,14 +2184,14 @@ static void pf_ul(module_id_t module_id, /* Mark the corresponding RBs as used */ sched_ctrl->cce_index = CCEIndex; - fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, 0); // TODO use beam index + fill_pdcch_vrb_map(nrmac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, sched_ctrl->aggregation_level, dci_beam.idx); - n_rb_sched -= sched_pusch->rbSize; + n_rb_sched[beam.idx] -= sched_pusch->rbSize; for (int rb = bwpStart; rb < sched_ctrl->sched_pusch.rbSize; rb++) rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] |= slbitmap; /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */ - remainUEs--; + remainUEs[beam.idx]--; iterator++; } } @@ -2167,8 +2216,12 @@ static bool nr_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_fram if (!is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot)) return false; + int num_beams = nr_mac->beam_info.beam_allocation ? nr_mac->beam_info.beams_per_period : 1; int bw = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; - + int len[num_beams]; + for (int i = 0; i < num_beams; i++) + len[i] = bw; + int average_agg_level = 4; // TODO find a better estimation int max_sched_ues = bw / (average_agg_level * NR_NB_REG_PER_CCE); @@ -2176,7 +2229,7 @@ static bool nr_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_fram max_sched_ues = min(max_sched_ues, MAX_DCI_CORESET); /* proportional fair scheduling algorithm */ - pf_ul(module_id, frame, slot, sched_frame, sched_slot, nr_mac->UE_info.list, max_sched_ues, bw); + pf_ul(module_id, frame, slot, sched_frame, sched_slot, nr_mac->UE_info.list, max_sched_ues, num_beams, len); return true; }